@titan-design/react-ui 0.5.0 → 0.7.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 (307) hide show
  1. package/dist/bodymap.js +241 -189
  2. package/dist/bodymap.js.map +1 -1
  3. package/dist/bodymap.mjs +241 -189
  4. package/dist/bodymap.mjs.map +1 -1
  5. package/dist/index.d.mts +1017 -130
  6. package/dist/index.d.ts +1017 -130
  7. package/dist/index.js +3058 -1090
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +2992 -1091
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/{pages-MO0JCySL.d.mts → pages-8u_4WbL-.d.mts} +280 -57
  12. package/dist/{pages-D7Jlssvp.d.ts → pages-DaWiBOGa.d.ts} +280 -57
  13. package/dist/pages.d.mts +1 -1
  14. package/dist/pages.d.ts +1 -1
  15. package/dist/pages.js +1797 -1292
  16. package/dist/pages.js.map +1 -1
  17. package/dist/pages.mjs +1797 -1292
  18. package/dist/pages.mjs.map +1 -1
  19. package/dist/theme/index.d.mts +464 -268
  20. package/dist/theme/index.d.ts +464 -268
  21. package/dist/theme/index.js +303 -191
  22. package/dist/theme/index.js.map +1 -1
  23. package/dist/theme/index.mjs +295 -192
  24. package/dist/theme/index.mjs.map +1 -1
  25. package/dist/theme/tokens-css.js +160 -143
  26. package/dist/theme/tokens-css.js.map +1 -1
  27. package/dist/theme/tokens-css.mjs +160 -143
  28. package/dist/theme/tokens-css.mjs.map +1 -1
  29. package/package.json +3 -1
  30. package/src/arch/Architecture.stories.tsx +870 -0
  31. package/src/arch/annotations.json +48 -0
  32. package/src/arch/arch-graph.json +4301 -0
  33. package/src/components/custom/DateTime/DateTime.stories.tsx +83 -7
  34. package/src/components/custom/DateTime/DateTime.test.tsx +29 -3
  35. package/src/components/custom/DateTime/DateTime.tsx +55 -15
  36. package/src/components/custom/EmptyState/EmptyState.stories.tsx +1 -1
  37. package/src/components/custom/Gauge/Gauge.stories.tsx +1 -1
  38. package/src/components/custom/Gauge/Gauge.test.tsx +2 -2
  39. package/src/components/custom/Gauge/Gauge.tsx +6 -3
  40. package/src/components/custom/Metric/Metric.stories.tsx +1 -1
  41. package/src/components/custom/Scatter/Scatter.stories.tsx +1 -1
  42. package/src/components/custom/Scatter/Scatter.tsx +3 -5
  43. package/src/components/custom/Sidebar/Sidebar.stories.tsx +1 -1
  44. package/src/components/custom/Table/Table.stories.tsx +1 -1
  45. package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +62 -0
  46. package/src/components/custom/TimerReadout/TimerReadout.test.tsx +72 -0
  47. package/src/components/custom/TimerReadout/TimerReadout.tsx +75 -0
  48. package/src/components/custom/TimerReadout/index.ts +1 -0
  49. package/src/components/custom/Treemap/Treemap.stories.tsx +1 -1
  50. package/src/components/custom/Treemap/Treemap.tsx +3 -5
  51. package/src/components/custom/Typography/Typography.stories.tsx +46 -28
  52. package/src/components/custom/Typography/Typography.test.tsx +13 -3
  53. package/src/components/custom/Typography/Typography.tsx +5 -0
  54. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +21 -13
  55. package/src/components/custom/Workout/ActiveWorkoutPage.test.tsx +16 -13
  56. package/src/components/custom/Workout/ActiveWorkoutPage.tsx +11 -16
  57. package/src/components/custom/Workout/BaseBadge.stories.tsx +1 -1
  58. package/src/components/custom/Workout/BodyMap.stories.tsx +1 -1
  59. package/src/components/custom/Workout/BodyMap.tsx +6 -3
  60. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +1 -1
  61. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +6 -3
  62. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +1 -1
  63. package/src/components/custom/Workout/CapacityBandChart.test.tsx +2 -2
  64. package/src/components/custom/Workout/CapacityBandChart.tsx +9 -6
  65. package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
  66. package/src/components/custom/Workout/DeviationBar.test.tsx +1 -1
  67. package/src/components/custom/Workout/DeviationBar.tsx +7 -4
  68. package/src/components/custom/Workout/ExerciseCard.stories.tsx +51 -66
  69. package/src/components/custom/Workout/ExerciseCard.test.tsx +146 -143
  70. package/src/components/custom/Workout/ExerciseCard.tsx +176 -198
  71. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +99 -0
  72. package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +72 -0
  73. package/src/components/custom/Workout/ExerciseCardHeading.tsx +43 -0
  74. package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +151 -0
  75. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +5 -3
  76. package/src/components/custom/Workout/ExerciseDetailPage.test.tsx +4 -4
  77. package/src/components/custom/Workout/ExerciseDetailPage.tsx +6 -6
  78. package/src/components/custom/Workout/ExerciseHeading.stories.tsx +81 -0
  79. package/src/components/custom/Workout/ExerciseHeading.test.tsx +77 -0
  80. package/src/components/custom/Workout/ExerciseHeading.tsx +85 -0
  81. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +110 -0
  82. package/src/components/custom/Workout/ExerciseIndicator.test.tsx +93 -0
  83. package/src/components/custom/Workout/ExerciseIndicator.tsx +120 -0
  84. package/src/components/custom/Workout/FatigueMeter.stories.tsx +51 -0
  85. package/src/components/custom/Workout/FatigueMeter.test.tsx +73 -0
  86. package/src/components/custom/Workout/FatigueMeter.tsx +82 -0
  87. package/src/components/custom/Workout/InputBar.stories.tsx +1 -1
  88. package/src/components/custom/Workout/InputBar.tsx +2 -1
  89. package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
  90. package/src/components/custom/Workout/IntensityBar.test.tsx +8 -8
  91. package/src/components/custom/Workout/IntensityBar.tsx +10 -6
  92. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +153 -0
  93. package/src/components/custom/Workout/LiveAuraFrame.test.tsx +74 -0
  94. package/src/components/custom/Workout/LiveAuraFrame.tsx +105 -0
  95. package/src/components/custom/Workout/MesoCard.stories.tsx +1 -1
  96. package/src/components/custom/Workout/MesoCard.tsx +8 -3
  97. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
  98. package/src/components/custom/Workout/MesoProgressBar.test.tsx +1 -1
  99. package/src/components/custom/Workout/MesoProgressBar.tsx +3 -2
  100. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +1 -1
  101. package/src/components/custom/Workout/MesoStatusCard.tsx +20 -13
  102. package/src/components/custom/Workout/MetricTiles.stories.tsx +60 -0
  103. package/src/components/custom/Workout/MetricTiles.test.tsx +58 -0
  104. package/src/components/custom/Workout/MetricTiles.tsx +48 -0
  105. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +1 -1
  106. package/src/components/custom/Workout/MuscleGroupChip.tsx +7 -4
  107. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
  108. package/src/components/custom/Workout/PrBadge.stories.tsx +1 -1
  109. package/src/components/custom/Workout/PrBadge.tsx +5 -2
  110. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +1 -1
  111. package/src/components/custom/Workout/PrHistoryModal.tsx +4 -3
  112. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +4 -16
  113. package/src/components/custom/Workout/ProgramPlanningPage.tsx +10 -7
  114. package/src/components/custom/Workout/README.md +146 -4
  115. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +1 -1
  116. package/src/components/custom/Workout/ReadinessCheck.tsx +7 -4
  117. package/src/components/custom/Workout/RestTimer.stories.tsx +1 -1
  118. package/src/components/custom/Workout/RestTimer.tsx +17 -11
  119. package/src/components/custom/Workout/RowInventory.stories.tsx +405 -0
  120. package/src/components/custom/Workout/S3FullRail.stories.tsx +34 -0
  121. package/src/components/custom/Workout/S3SessionPace.stories.tsx +95 -0
  122. package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +61 -0
  123. package/src/components/custom/Workout/S3SetTypes.stories.tsx +176 -0
  124. package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +240 -0
  125. package/src/components/custom/Workout/ScheduleTiles.stories.tsx +40 -0
  126. package/src/components/custom/Workout/ScheduleTiles.test.tsx +34 -0
  127. package/src/components/custom/Workout/ScheduleTiles.tsx +70 -0
  128. package/src/components/custom/Workout/SegmentedBar.stories.tsx +99 -0
  129. package/src/components/custom/Workout/SegmentedBar.test.tsx +77 -0
  130. package/src/components/custom/Workout/SegmentedBar.tsx +172 -0
  131. package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +50 -0
  132. package/src/components/custom/Workout/SegmentedProgressBar.test.tsx +80 -0
  133. package/src/components/custom/Workout/SegmentedProgressBar.tsx +67 -0
  134. package/src/components/custom/Workout/SessionHeader.stories.tsx +121 -0
  135. package/src/components/custom/Workout/SessionHeader.test.tsx +122 -0
  136. package/src/components/custom/Workout/SessionHeader.tsx +152 -0
  137. package/src/components/custom/Workout/SessionRail.stories.tsx +153 -0
  138. package/src/components/custom/Workout/SessionRail.test.tsx +86 -0
  139. package/src/components/custom/Workout/SessionRail.tsx +126 -0
  140. package/src/components/custom/Workout/SetBar.stories.tsx +124 -0
  141. package/src/components/custom/Workout/SetBar.test.tsx +123 -0
  142. package/src/components/custom/Workout/SetBar.tsx +171 -0
  143. package/src/components/custom/Workout/SetRow.stories.tsx +50 -100
  144. package/src/components/custom/Workout/SetRow.test.tsx +94 -166
  145. package/src/components/custom/Workout/SetRow.tsx +170 -232
  146. package/src/components/custom/Workout/SetStrip.stories.tsx +154 -0
  147. package/src/components/custom/Workout/SetStrip.test.tsx +109 -0
  148. package/src/components/custom/Workout/SetStrip.tsx +71 -0
  149. package/src/components/custom/Workout/SetTableHeader.stories.tsx +66 -0
  150. package/src/components/custom/Workout/SetTableHeader.test.tsx +47 -0
  151. package/src/components/custom/Workout/SetTableHeader.tsx +88 -0
  152. package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +47 -0
  153. package/src/components/custom/Workout/SetsRepsLoad.test.tsx +44 -0
  154. package/src/components/custom/Workout/SetsRepsLoad.tsx +52 -0
  155. package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
  156. package/src/components/custom/Workout/Sparkline.tsx +2 -1
  157. package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
  158. package/src/components/custom/Workout/StatusDot.test.tsx +2 -2
  159. package/src/components/custom/Workout/StatusDot.tsx +12 -9
  160. package/src/components/custom/Workout/StatusPill.stories.tsx +59 -0
  161. package/src/components/custom/Workout/StatusPill.test.tsx +63 -0
  162. package/src/components/custom/Workout/StatusPill.tsx +88 -0
  163. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +1 -1
  164. package/src/components/custom/Workout/StrengthTrendChart.tsx +9 -6
  165. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +1 -1
  166. package/src/components/custom/Workout/SupersetWrapper.tsx +2 -1
  167. package/src/components/custom/Workout/TempoBar.stories.tsx +1 -1
  168. package/src/components/custom/Workout/TempoDisplay.stories.tsx +12 -1
  169. package/src/components/custom/Workout/TempoDisplay.tsx +29 -36
  170. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +1 -1
  171. package/src/components/custom/Workout/VelocityStrip.modalities.stories.tsx +254 -0
  172. package/src/components/custom/Workout/VelocityStrip.responsive.stories.tsx +145 -0
  173. package/src/components/custom/Workout/VelocityStrip.stories.tsx +129 -66
  174. package/src/components/custom/Workout/VelocityStrip.test.tsx +379 -144
  175. package/src/components/custom/Workout/VelocityStrip.tsx +508 -120
  176. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +73 -0
  177. package/src/components/custom/Workout/VolumeLandmarkBar.test.tsx +119 -0
  178. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +154 -0
  179. package/src/components/custom/Workout/WeekRow.stories.tsx +1 -1
  180. package/src/components/custom/Workout/WeekRow.tsx +3 -2
  181. package/src/components/custom/Workout/WeightBadge.stories.tsx +1 -1
  182. package/src/components/custom/Workout/WeightBadge.tsx +6 -2
  183. package/src/components/custom/Workout/WorkoutCard.stories.tsx +2 -6
  184. package/src/components/custom/Workout/WorkoutCard.test.tsx +13 -46
  185. package/src/components/custom/Workout/WorkoutCard.tsx +5 -2
  186. package/src/components/custom/Workout/WorkoutPill.stories.tsx +1 -1
  187. package/src/components/custom/Workout/WorkoutPill.tsx +12 -8
  188. package/src/components/custom/Workout/ZoneTrack.stories.tsx +140 -0
  189. package/src/components/custom/Workout/ZoneTrack.test.tsx +200 -0
  190. package/src/components/custom/Workout/ZoneTrack.tsx +315 -0
  191. package/src/components/custom/Workout/icons.tsx +6 -67
  192. package/src/components/custom/Workout/index.ts +55 -2
  193. package/src/components/custom/Workout/metricText.stories.tsx +69 -0
  194. package/src/components/custom/Workout/metricText.tsx +34 -0
  195. package/src/components/custom/Workout/paceTone.test.ts +29 -0
  196. package/src/components/custom/Workout/paceTone.ts +27 -0
  197. package/src/components/custom/Workout/setHeadingKit.tsx +177 -0
  198. package/src/components/custom/index.ts +1 -0
  199. package/src/components/custom/stepper/Stepper.stories.tsx +1 -1
  200. package/src/components/icons/SvgIcon.tsx +50 -0
  201. package/src/components/icons/icons.stories.tsx +122 -0
  202. package/src/components/icons/icons.test.tsx +73 -0
  203. package/src/components/icons/icons.tsx +153 -0
  204. package/src/components/icons/index.ts +4 -0
  205. package/src/components/index.ts +6 -0
  206. package/src/components/shell/BrandLockup.stories.tsx +27 -0
  207. package/src/components/shell/BrandLockup.test.tsx +23 -0
  208. package/src/components/shell/BrandLockup.tsx +47 -0
  209. package/src/components/shell/DashboardShell.stories.tsx +65 -0
  210. package/src/components/shell/DashboardShell.test.tsx +42 -0
  211. package/src/components/shell/DashboardShell.tsx +74 -0
  212. package/src/components/shell/DeviceIndicator.stories.tsx +28 -0
  213. package/src/components/shell/DeviceIndicator.test.tsx +26 -0
  214. package/src/components/shell/DeviceIndicator.tsx +52 -0
  215. package/src/components/shell/DeviceMenu.stories.tsx +47 -0
  216. package/src/components/shell/DeviceMenu.test.tsx +40 -0
  217. package/src/components/shell/DeviceMenu.tsx +65 -0
  218. package/src/components/shell/DeviceRow.stories.tsx +38 -0
  219. package/src/components/shell/DeviceRow.test.tsx +37 -0
  220. package/src/components/shell/DeviceRow.tsx +58 -0
  221. package/src/components/shell/NavItem.stories.tsx +52 -0
  222. package/src/components/shell/NavItem.test.tsx +35 -0
  223. package/src/components/shell/NavItem.tsx +75 -0
  224. package/src/components/shell/README.md +116 -0
  225. package/src/components/shell/SessionRailSpecimen.stories.tsx +753 -0
  226. package/src/components/shell/SessionStatePill.stories.tsx +27 -0
  227. package/src/components/shell/SessionStatePill.test.tsx +25 -0
  228. package/src/components/shell/SessionStatePill.tsx +46 -0
  229. package/src/components/shell/SideNav.stories.tsx +81 -0
  230. package/src/components/shell/SideNav.test.tsx +51 -0
  231. package/src/components/shell/SideNav.tsx +74 -0
  232. package/src/components/shell/TopBar.stories.tsx +49 -0
  233. package/src/components/shell/TopBar.test.tsx +36 -0
  234. package/src/components/shell/TopBar.tsx +89 -0
  235. package/src/components/shell/index.ts +13 -0
  236. package/src/components/ui/alert/Alert.stories.tsx +1 -1
  237. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +1 -1
  238. package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
  239. package/src/components/ui/badge/Badge.stories.tsx +1 -1
  240. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  241. package/src/components/ui/button/Button.stories.tsx +1 -1
  242. package/src/components/ui/card/Card.stories.tsx +1 -1
  243. package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
  244. package/src/components/ui/chip/Chip.stories.tsx +1 -1
  245. package/src/components/ui/collapse/Collapse.stories.tsx +1 -1
  246. package/src/components/ui/data-row/DataRow.stories.tsx +1 -1
  247. package/src/components/ui/divider/Divider.stories.tsx +1 -1
  248. package/src/components/ui/drawer/Drawer.stories.tsx +1 -1
  249. package/src/components/ui/form-field/FormField.stories.tsx +1 -1
  250. package/src/components/ui/help-tip/HelpTip.stories.tsx +1 -1
  251. package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
  252. package/src/components/ui/index.ts +1 -0
  253. package/src/components/ui/indicator/Indicator.stories.tsx +38 -2
  254. package/src/components/ui/indicator/Indicator.test.tsx +20 -1
  255. package/src/components/ui/indicator/Indicator.tsx +50 -6
  256. package/src/components/ui/indicator/index.ts +1 -1
  257. package/src/components/ui/input/Input.stories.tsx +1 -1
  258. package/src/components/ui/link/Link.stories.tsx +1 -1
  259. package/src/components/ui/list-item/ListItem.stories.tsx +1 -1
  260. package/src/components/ui/menu/Menu.stories.tsx +1 -1
  261. package/src/components/ui/modal/Modal.stories.tsx +1 -1
  262. package/src/components/ui/pill/Pill.stories.tsx +1 -1
  263. package/src/components/ui/popover/Popover.stories.tsx +1 -1
  264. package/src/components/ui/progress/Progress.stories.tsx +1 -1
  265. package/src/components/ui/radio/Radio.stories.tsx +1 -1
  266. package/src/components/ui/section/Section.stories.tsx +1 -1
  267. package/src/components/ui/select/Select.stories.tsx +1 -1
  268. package/src/components/ui/skeleton/Skeleton.stories.tsx +1 -1
  269. package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
  270. package/src/components/ui/spinner/Spinner.tsx +3 -2
  271. package/src/components/ui/stack/Stack.stories.tsx +1 -1
  272. package/src/components/ui/surface/Surface.stories.tsx +1 -1
  273. package/src/components/ui/switch/Switch.stories.tsx +1 -1
  274. package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
  275. package/src/components/ui/tile/Tile.stories.tsx +79 -0
  276. package/src/components/ui/tile/Tile.test.tsx +48 -0
  277. package/src/components/ui/tile/Tile.tsx +64 -0
  278. package/src/components/ui/tile/index.ts +2 -0
  279. package/src/components/ui/toast/Toast.stories.tsx +1 -1
  280. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +1 -1
  281. package/src/components/ui/toolbar-button/ToolbarButton.tsx +2 -1
  282. package/src/components/ui/tooltip/Tooltip.stories.tsx +1 -1
  283. package/src/examples/react-hook-form/ReactHookForm.stories.tsx +1 -1
  284. package/src/hooks/index.ts +2 -0
  285. package/src/hooks/useTimer.test.ts +150 -0
  286. package/src/hooks/useTimer.ts +77 -0
  287. package/src/index.ts +3 -0
  288. package/src/pages.ts +1 -1
  289. package/src/stories/PresetShowcase.stories.tsx +1 -1
  290. package/src/stories/ThemePresets.stories.tsx +1 -1
  291. package/src/theme/ColorSystem.stories.tsx +323 -0
  292. package/src/theme/Colors.stories.tsx +74 -9
  293. package/src/theme/barrel.ts +1 -0
  294. package/src/theme/config.ts +20 -3
  295. package/src/theme/elevation.stories.tsx +1 -1
  296. package/src/theme/extracted-colors-dataviz.ts +21 -0
  297. package/src/theme/extracted-colors-ui.ts +20 -0
  298. package/src/theme/global.css +69 -53
  299. package/src/theme/gradients.test.ts +25 -0
  300. package/src/theme/gradients.ts +36 -0
  301. package/src/theme/shadows.stories.tsx +1 -1
  302. package/src/theme/tokens/primitives.test.ts +232 -0
  303. package/src/theme/tokens/primitives.ts +238 -87
  304. package/src/theme/tokens/semantic.ts +101 -81
  305. package/src/theme/workout-tokens.ts +26 -21
  306. package/src/utils/avatar-color.ts +3 -3
  307. package/tailwind.config.js +15 -3
package/dist/pages.mjs CHANGED
@@ -6,22 +6,160 @@ import { twMerge } from 'tailwind-merge';
6
6
 
7
7
  // src/components/custom/Workout/ActiveWorkoutPage.tsx
8
8
 
9
+ // src/theme/tokens/primitives.ts
10
+ var primitiveColors = {
11
+ // Blue scale
12
+ blue: {
13
+ 400: "#60A5FA",
14
+ 600: "#5048E5",
15
+ 700: "#3832A0"},
16
+ // Red scale
17
+ red: {
18
+ 500: "#EF4444",
19
+ 600: "#D14343"},
20
+ // Vivid red scale
21
+ redVivid: {
22
+ 400: "#FF6070",
23
+ 500: "#FF4757",
24
+ 700: "#C42539"},
25
+ // Neutral/Gray scale
26
+ neutral: {
27
+ 50: "#FAFAFA",
28
+ 100: "#F3F4F6",
29
+ 300: "#D1D5DB",
30
+ 400: "#9CA3AF",
31
+ 500: "#6B7280",
32
+ 600: "#4B5563",
33
+ 900: "#111827"},
34
+ // Charcoal scale (dark backgrounds)
35
+ charcoal: {
36
+ 200: "#3C3C3C",
37
+ 300: "#2C2C2C",
38
+ 400: "#1F1F1F",
39
+ 500: "#1C1C1C",
40
+ 600: "#191919",
41
+ 700: "#161616",
42
+ 900: "#101010"
43
+ },
44
+ // Pure colors
45
+ white: "#FFFFFF"};
46
+ var primitiveRamps = {
47
+ red: {
48
+ 50: "#FFF4F4",
49
+ 500: "#E05254",
50
+ 600: "#D14343",
51
+ // pin
52
+ 700: "#A4221C",
53
+ 800: "#7E1002"},
54
+ orange: {
55
+ 200: "#FFC7A2",
56
+ 300: "#FFA063",
57
+ 400: "#FF7900",
58
+ // pin
59
+ 500: "#DA5F00",
60
+ 600: "#B94A00"},
61
+ amber: {
62
+ 50: "#FFF7DD",
63
+ 200: "#FFD352",
64
+ 300: "#F9B415",
65
+ // pin
66
+ 400: "#E08C00",
67
+ 500: "#C27400"},
68
+ green: {
69
+ 50: "#E3FFEE",
70
+ 200: "#58F69E",
71
+ 300: "#2ED573",
72
+ // pin
73
+ 400: "#21C05D",
74
+ 500: "#22A444",
75
+ 600: "#298732"},
76
+ cyan: {
77
+ // pin
78
+ 400: "#01B5D1",
79
+ 500: "#2697B7",
80
+ 600: "#307B9B",
81
+ 700: "#2A617F",
82
+ 800: "#22465F",
83
+ 900: "#0B3149"},
84
+ blue: {
85
+ 50: "#EFF8FF",
86
+ 300: "#78C2FF",
87
+ 500: "#2196F3",
88
+ // pin
89
+ 600: "#1072CB"},
90
+ magenta: {
91
+ 600: "#BA2996"}
92
+ };
93
+ var sequentialEffort = [
94
+ primitiveRamps.green[300],
95
+ primitiveRamps.amber[200],
96
+ primitiveRamps.amber[300],
97
+ primitiveRamps.orange[400],
98
+ primitiveRamps.red[600],
99
+ primitiveRamps.red[700]
100
+ ];
101
+ var discreteRainbow = [
102
+ "#E8ECFB",
103
+ "#D9CCE3",
104
+ "#D1BBD7",
105
+ "#CAACCB",
106
+ "#BA8DB4",
107
+ "#AE76A3",
108
+ "#AA6F9E",
109
+ "#994F88",
110
+ "#882E72",
111
+ "#1965B0",
112
+ "#437DBF",
113
+ "#5289C7",
114
+ "#6195CF",
115
+ "#7BAFDE",
116
+ "#4EB265",
117
+ "#90C987",
118
+ "#CAE0AB",
119
+ "#F7F056",
120
+ "#F7CB45",
121
+ "#F6C141",
122
+ "#F4A736",
123
+ "#F1932D",
124
+ "#EE8026",
125
+ "#E8601C",
126
+ "#E65518",
127
+ "#DC050C",
128
+ "#A5170E",
129
+ "#72190E",
130
+ "#42150A"
131
+ ];
132
+
9
133
  // src/theme/workout-tokens.ts
10
134
  var WORKOUT_TOKENS = {
11
135
  // Canonical 4-band performance scale — the single source for BOTH the
12
136
  // VelocityStrip zone bars and the SetRow RPE color (TD-03.43). The direction
13
137
  // is intentionally inverted between the two consumers: for velocity, green =
14
- // fastest/best; for RPE, green = easiest. Each component maps its own
15
- // thresholds onto these four colors. Kept as vivid data-viz values (distinct
16
- // from the muted status tokens) and theme-independent, so like the heatmap
17
- // scale below they are consumed inline as a JS import rather than CSS vars.
18
- // A JS import also resolves on native RN, unlike var(--…) strings.
138
+ // fastest/best; for RPE, green = easiest. This is the [0,2,3,4] subsample of
139
+ // the canonical `sequentialEffort` primitive: an EVEN hue walk across the ramp
140
+ // (green gold orange → red). The earlier [0,1,2,4] spent two of its four
141
+ // bands on adjacent yellows (amber-200 + amber-300) and skipped orange, reading
142
+ // yellow-heavy with an abrupt jump to red; sampling amber-300 + orange-400
143
+ // instead gives four cleanly separable bands that hold at 3px strip scale.
144
+ // Consumed inline (RN).
19
145
  scale: {
20
- green: "#2ed573",
21
- yellow: "#ffd43b",
22
- orange: "#ffa502",
23
- red: "#ff4757"
146
+ green: sequentialEffort[0],
147
+ // green-300
148
+ yellow: sequentialEffort[2],
149
+ // amber-300 (gold)
150
+ orange: sequentialEffort[3],
151
+ // orange-400 (true orange)
152
+ red: sequentialEffort[4]
153
+ // red-600
24
154
  },
155
+ // Surface and border colors were removed here: those flip with the theme, so
156
+ // components use the CSS custom properties (var(--color-surface-*/border-*))
157
+ // directly. Only theme-independent data-viz values remain below.
158
+ // Intensity bar specific — over-target tiers deepen along the red ramp.
159
+ intensity: {
160
+ // matches status-error
161
+ over2: primitiveRamps.red[700],
162
+ over3: primitiveRamps.red[800]},
25
163
  // Placeholder strip
26
164
  placeholder: {
27
165
  fill: "#3A3A3A"
@@ -31,12 +169,6 @@ var WORKOUT_TOKENS = {
31
169
  function roundRpe(rpe) {
32
170
  return Math.round(rpe * 2) / 2;
33
171
  }
34
- function rpeColor(rpe) {
35
- if (rpe >= 9.5) return WORKOUT_TOKENS.scale.red;
36
- if (rpe >= 8.5) return WORKOUT_TOKENS.scale.orange;
37
- if (rpe >= 7) return WORKOUT_TOKENS.scale.yellow;
38
- return WORKOUT_TOKENS.scale.green;
39
- }
40
172
  function roundWeight(weight) {
41
173
  return Math.round(weight);
42
174
  }
@@ -64,14 +196,258 @@ function wrapJsx(fn) {
64
196
  var jsx = wrapJsx(jsx$1);
65
197
  var jsxs = wrapJsx(jsxs$1);
66
198
 
199
+ // src/components/custom/Workout/SegmentedBar.tsx
200
+ var PULSE_HALF_MS = 950;
201
+ var PULSE_MIN_OPACITY = 0.45;
202
+ var SEGMENTED_BAR_GAP = 5;
203
+ function usePulse(active) {
204
+ const [value] = useState(() => new Animated.Value(0));
205
+ useEffect(() => {
206
+ if (!active) return;
207
+ const loop = Animated.loop(
208
+ Animated.sequence([
209
+ Animated.timing(value, {
210
+ toValue: 1,
211
+ duration: PULSE_HALF_MS,
212
+ easing: Easing.inOut(Easing.ease),
213
+ useNativeDriver: false
214
+ }),
215
+ Animated.timing(value, {
216
+ toValue: 0,
217
+ duration: PULSE_HALF_MS,
218
+ easing: Easing.inOut(Easing.ease),
219
+ useNativeDriver: false
220
+ })
221
+ ])
222
+ );
223
+ loop.start();
224
+ return () => loop.stop();
225
+ }, [active, value]);
226
+ return value;
227
+ }
228
+ function SegmentedBar({
229
+ segments,
230
+ height = 8,
231
+ gap = SEGMENTED_BAR_GAP,
232
+ radius = 2,
233
+ marker = null,
234
+ segmentTestID,
235
+ style,
236
+ ...props
237
+ }) {
238
+ const pulse = usePulse(segments.some((s) => s.pulse));
239
+ return /* @__PURE__ */ jsxs(View, { style: [{ flexDirection: "row", height, gap, position: "relative" }, style], ...props, children: [
240
+ segments.map((seg, i) => {
241
+ const fillStyle = {
242
+ width: `${(seg.fill ?? 1) * 100}%`,
243
+ height: "100%",
244
+ backgroundColor: seg.color,
245
+ opacity: seg.opacity
246
+ };
247
+ const testID = segmentTestID?.(seg, i) ?? "segmented-bar-segment";
248
+ return /* @__PURE__ */ jsx(
249
+ View,
250
+ {
251
+ style: {
252
+ flex: seg.weight ?? 1,
253
+ minWidth: 0,
254
+ height: "100%",
255
+ marginLeft: seg.leadingGap,
256
+ borderRadius: radius,
257
+ overflow: "hidden"
258
+ },
259
+ children: seg.pulse ? /* @__PURE__ */ jsx(
260
+ Animated.View,
261
+ {
262
+ style: {
263
+ ...fillStyle,
264
+ ...seg.pulseColor ? {
265
+ backgroundColor: pulse.interpolate({
266
+ inputRange: [0, 1],
267
+ outputRange: seg.pulseColor
268
+ })
269
+ } : {
270
+ opacity: pulse.interpolate({
271
+ inputRange: [0, 1],
272
+ outputRange: [PULSE_MIN_OPACITY, 1]
273
+ })
274
+ }
275
+ },
276
+ accessibilityElementsHidden: true,
277
+ testID
278
+ }
279
+ ) : /* @__PURE__ */ jsx(View, { style: fillStyle, accessibilityElementsHidden: true, testID })
280
+ },
281
+ i
282
+ );
283
+ }),
284
+ marker ? /* @__PURE__ */ jsx(
285
+ View,
286
+ {
287
+ style: {
288
+ position: "absolute",
289
+ left: `${marker.position * 100}%`,
290
+ top: 0,
291
+ bottom: 0,
292
+ width: 2,
293
+ backgroundColor: marker.color
294
+ },
295
+ accessibilityElementsHidden: true,
296
+ testID: "segmented-bar-marker"
297
+ }
298
+ ) : null
299
+ ] });
300
+ }
301
+
302
+ // src/components/custom/Workout/SetBar.tsx
303
+ var SET_STRIP_ZONES = {
304
+ slow: primitiveRamps.red[600],
305
+ moderate: primitiveRamps.orange[400],
306
+ fast: primitiveRamps.amber[300],
307
+ fastest: primitiveRamps.green[300]
308
+ };
309
+ var TODO_COLOR = primitiveColors.charcoal[300];
310
+ var SET_STRIP_VARIABLE_COLOR = primitiveRamps.cyan[900];
311
+ var NOTCH_GAP = 2;
312
+ var CLUSTER_GAP = 3;
313
+ var MYO_UPCOMING_CLUSTERS = 3;
314
+ var MYO_UPCOMING_CLUSTER_LEN = 5;
315
+ var MYO_UPCOMING_FADE = 0.6;
316
+ var PULSE_RANGE = {
317
+ [SET_STRIP_ZONES.slow]: [primitiveRamps.red[500], primitiveRamps.red[700]],
318
+ [SET_STRIP_ZONES.moderate]: [primitiveRamps.orange[300], primitiveRamps.orange[500]],
319
+ [SET_STRIP_ZONES.fast]: [primitiveRamps.amber[200], primitiveRamps.amber[400]],
320
+ [SET_STRIP_ZONES.fastest]: [primitiveRamps.green[200], primitiveRamps.green[400]]
321
+ };
322
+ function velocityZoneColor(v) {
323
+ if (v < 0.5) return SET_STRIP_ZONES.slow;
324
+ if (v < 0.75) return SET_STRIP_ZONES.moderate;
325
+ if (v < 1) return SET_STRIP_ZONES.fast;
326
+ return SET_STRIP_ZONES.fastest;
327
+ }
328
+ function chunkedSegments(chunks, gap) {
329
+ return chunks.flatMap(
330
+ (vels, ci) => vels.map((v, ri) => ({
331
+ color: velocityZoneColor(v),
332
+ ...ci > 0 && ri === 0 ? { leadingGap: gap } : {}
333
+ }))
334
+ );
335
+ }
336
+ function rangeSegments(floor, max, doneVels) {
337
+ return Array.from({ length: max }, (_, i) => {
338
+ if (i < doneVels.length) return { color: velocityZoneColor(doneVels[i]) };
339
+ return { color: i < floor ? TODO_COLOR : SET_STRIP_VARIABLE_COLOR };
340
+ });
341
+ }
342
+ function myoUpcomingSegments(activationLen, clusterCount) {
343
+ const activation = Array.from({ length: activationLen }, () => ({ color: TODO_COLOR }));
344
+ const trail = Array.from(
345
+ { length: clusterCount },
346
+ (_, ci) => Array.from({ length: MYO_UPCOMING_CLUSTER_LEN }, (_2, ri) => ({
347
+ color: SET_STRIP_VARIABLE_COLOR,
348
+ opacity: MYO_UPCOMING_FADE ** ci,
349
+ ...ri === 0 ? { leadingGap: CLUSTER_GAP } : {}
350
+ }))
351
+ ).flat();
352
+ return [...activation, ...trail];
353
+ }
354
+ function setSegments(set) {
355
+ if (set.status === "todo") {
356
+ return [{ color: TODO_COLOR }];
357
+ }
358
+ if (set.status === "done") {
359
+ return set.velocities.map((v) => ({ color: velocityZoneColor(v) }));
360
+ }
361
+ if (set.status === "range") {
362
+ return rangeSegments(set.floor, set.max, set.doneVels);
363
+ }
364
+ if (set.status === "drop") {
365
+ return chunkedSegments(set.subloads, NOTCH_GAP);
366
+ }
367
+ if (set.status === "myo") {
368
+ return chunkedSegments([set.activation, ...set.clusters], CLUSTER_GAP);
369
+ }
370
+ if (set.status === "myo-upcoming") {
371
+ return myoUpcomingSegments(set.activationLen, set.clusterCount ?? MYO_UPCOMING_CLUSTERS);
372
+ }
373
+ const performed = set.velocities.map((v) => {
374
+ const color = velocityZoneColor(v);
375
+ return { color, pulse: true, pulseColor: PULSE_RANGE[color] };
376
+ });
377
+ const remaining = Math.max(0, set.planned - set.velocities.length);
378
+ return [...performed, ...Array.from({ length: remaining }, () => ({ color: TODO_COLOR }))];
379
+ }
380
+ function setBarSegmentTestID(seg) {
381
+ if (seg.pulse) return "set-strip-pulse";
382
+ if (seg.color === SET_STRIP_VARIABLE_COLOR) return "set-strip-variable";
383
+ return seg.color === TODO_COLOR ? "set-strip-empty" : "set-strip-fill";
384
+ }
385
+ function SetBar({ set, height = 8 }) {
386
+ return /* @__PURE__ */ jsx(
387
+ SegmentedBar,
388
+ {
389
+ segments: setSegments(set),
390
+ height,
391
+ gap: 0,
392
+ radius: 0,
393
+ segmentTestID: setBarSegmentTestID,
394
+ style: { flex: 1, minWidth: 0, borderRadius: 2, overflow: "hidden" },
395
+ testID: "set-strip-set"
396
+ }
397
+ );
398
+ }
399
+
400
+ // src/components/custom/Workout/SetStrip.tsx
401
+ var SET_STRIP_GAP = 5;
402
+ function setCategory(set) {
403
+ switch (set.status) {
404
+ case "done":
405
+ case "drop":
406
+ case "myo":
407
+ return "done";
408
+ case "active":
409
+ return "active";
410
+ case "range":
411
+ return set.doneVels.length > 0 ? "active" : "upcoming";
412
+ case "todo":
413
+ case "myo-upcoming":
414
+ return "upcoming";
415
+ }
416
+ }
417
+ function describeSets(sets) {
418
+ const done = sets.filter((s) => setCategory(s) === "done").length;
419
+ const active = sets.filter((s) => setCategory(s) === "active").length;
420
+ const upcoming = sets.filter((s) => setCategory(s) === "upcoming").length;
421
+ return `Set progress: ${done} done, ${active} in progress, ${upcoming} upcoming`;
422
+ }
423
+ function SetStrip({ sets, height = 8, className, ...props }) {
424
+ return /* @__PURE__ */ jsx(
425
+ View,
426
+ {
427
+ className,
428
+ style: { flexDirection: "row", width: "100%", height, gap: SET_STRIP_GAP },
429
+ accessibilityRole: "image",
430
+ accessibilityLabel: describeSets(sets),
431
+ testID: "set-strip",
432
+ ...props,
433
+ children: sets.map((set, i) => /* @__PURE__ */ jsx(SetBar, { set, height }, i))
434
+ }
435
+ );
436
+ }
437
+
67
438
  // src/components/custom/Workout/VelocityStrip.tsx
68
439
  var VEL_COLORS = WORKOUT_TOKENS.scale;
69
- var zoneIdToScaleToken = {
70
- speed: "green",
71
- power: "yellow",
72
- strengthSpeed: "orange",
73
- maximalStrength: "red",
74
- grinding: "red"
440
+ var bandIdToEffortColor = {
441
+ speed: sequentialEffort[0],
442
+ // green-300
443
+ power: sequentialEffort[2],
444
+ // amber-300 (gold)
445
+ strengthSpeed: sequentialEffort[3],
446
+ // orange-400
447
+ maximalStrength: sequentialEffort[4],
448
+ // red-600
449
+ grinding: sequentialEffort[5]
450
+ // red-700 — the distinct 5th band
75
451
  };
76
452
  function getVelocityZoneColor(velocity) {
77
453
  if (velocity >= 1) return "vel-green";
@@ -110,14 +486,132 @@ function classifyBand(velocity, bands) {
110
486
  return bands[bands.length - 1];
111
487
  }
112
488
  function bandColor(band) {
113
- const token = zoneIdToScaleToken[band.id];
114
- return token ? VEL_COLORS[token] : VEL_COLORS.green;
489
+ return bandIdToEffortColor[band.id] ?? VEL_COLORS.green;
115
490
  }
116
491
  function getLossStyle(loss) {
117
492
  if (loss > 25) return { color: VEL_COLORS.red };
118
493
  if (loss > 20) return { color: VEL_COLORS.orange };
119
494
  return null;
120
495
  }
496
+ var REP_GAP = 2;
497
+ var WIDE_GAP = 8;
498
+ var TODO_COLOR2 = primitiveColors.charcoal[300];
499
+ var CONTINUE_OUTLINE = primitiveRamps.cyan[800];
500
+ function deriveDoneVelocities(set) {
501
+ switch (set.type) {
502
+ case "drop":
503
+ return set.subloads.flat();
504
+ case "myo":
505
+ return [...set.activation, ...set.clusters.flat()];
506
+ default:
507
+ return set.velocities;
508
+ }
509
+ }
510
+ function chunkedRepSlots(chunks) {
511
+ const slots = [];
512
+ chunks.forEach((chunk) => {
513
+ chunk.forEach((velocity, ri) => {
514
+ const first = slots.length === 0;
515
+ slots.push({ kind: "rep", velocity, leadingGap: first ? 0 : ri === 0 ? WIDE_GAP : REP_GAP });
516
+ });
517
+ });
518
+ return slots;
519
+ }
520
+ function buildSlots(set) {
521
+ switch (set.type) {
522
+ case "straight": {
523
+ const total = Math.max(set.velocities.length, set.planned ?? set.velocities.length);
524
+ return Array.from({ length: total }, (_, i) => {
525
+ const done = i < set.velocities.length;
526
+ return {
527
+ kind: done ? "rep" : "todo",
528
+ velocity: done ? set.velocities[i] : void 0,
529
+ leadingGap: i === 0 ? 0 : REP_GAP
530
+ };
531
+ });
532
+ }
533
+ case "range": {
534
+ const total = Math.max(set.max, set.velocities.length);
535
+ return Array.from({ length: total }, (_, i) => {
536
+ const kind = i < set.velocities.length ? "rep" : i < set.floor ? "todo" : "variable";
537
+ return {
538
+ kind,
539
+ velocity: kind === "rep" ? set.velocities[i] : void 0,
540
+ leadingGap: i === 0 ? 0 : REP_GAP
541
+ };
542
+ });
543
+ }
544
+ case "amrap": {
545
+ const reps = set.velocities.map((velocity, i) => ({
546
+ kind: "rep",
547
+ velocity,
548
+ leadingGap: i === 0 ? 0 : REP_GAP
549
+ }));
550
+ reps.push({ kind: "continue", leadingGap: reps.length === 0 ? 0 : REP_GAP });
551
+ return reps;
552
+ }
553
+ case "drop":
554
+ return chunkedRepSlots(set.subloads);
555
+ case "myo": {
556
+ const slots = chunkedRepSlots([set.activation, ...set.clusters]);
557
+ if (set.open) slots.push({ kind: "continue", leadingGap: slots.length === 0 ? 0 : REP_GAP });
558
+ return slots;
559
+ }
560
+ case "cluster": {
561
+ const total = Math.max(set.velocities.length, set.planned ?? set.velocities.length);
562
+ return Array.from({ length: total }, (_, i) => {
563
+ const done = i < set.velocities.length;
564
+ const boundary = i > 0 && i % set.groupSize === 0;
565
+ return {
566
+ kind: done ? "rep" : "todo",
567
+ velocity: done ? set.velocities[i] : void 0,
568
+ leadingGap: i === 0 ? 0 : boundary ? WIDE_GAP : REP_GAP
569
+ };
570
+ });
571
+ }
572
+ }
573
+ }
574
+ function setAccessibilityLabel(set, repCount) {
575
+ switch (set.type) {
576
+ case "straight":
577
+ return `Velocity strip, straight set, ${repCount} reps`;
578
+ case "range":
579
+ return `Velocity strip, rep-range set, floor ${set.floor} to ${set.max}, ${repCount} reps done`;
580
+ case "amrap":
581
+ return `Velocity strip, AMRAP set, ${repCount} reps and counting`;
582
+ case "drop":
583
+ return `Velocity strip, drop set, ${set.subloads.length} loads, ${repCount} reps`;
584
+ case "myo":
585
+ return `Velocity strip, myo-reps set, ${set.clusters.length} clusters${set.open ? ", open" : ""}, ${repCount} reps`;
586
+ case "cluster":
587
+ return `Velocity strip, cluster set, groups of ${set.groupSize}, ${repCount} reps`;
588
+ }
589
+ }
590
+ function slotAccessibilityLabel(slot, index) {
591
+ switch (slot.kind) {
592
+ case "rep":
593
+ return `Rep ${index + 1}: ${formatVelocity(slot.velocity ?? 0)} meters per second`;
594
+ case "todo":
595
+ return `Rep ${index + 1}: planned`;
596
+ case "variable":
597
+ return `Rep ${index + 1}: variable`;
598
+ case "continue":
599
+ return "Keep going";
600
+ }
601
+ }
602
+ var EXPANDED_TODO_STUB_PCT = 16;
603
+ var EXPANDED_ENCODED_PCT = 45;
604
+ var EXPANDED_HEIGHT = 60;
605
+ var FIXED_MAX_VELOCITY = 1.15;
606
+ var BARE_STUB_HEIGHT = 3;
607
+ function scaleDenominator(scale, maxVelocity) {
608
+ return scale === "fixed" ? FIXED_MAX_VELOCITY : maxVelocity * 1.15;
609
+ }
610
+ function bareSlotHeight(slot, height, denom) {
611
+ if (slot.kind !== "rep" || denom <= 0) return BARE_STUB_HEIGHT;
612
+ const ratio = Math.min(1, (slot.velocity ?? 0) / denom);
613
+ return Math.max(BARE_STUB_HEIGHT, ratio * height);
614
+ }
121
615
  function getReducedMotionPreference() {
122
616
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
123
617
  return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
@@ -139,31 +633,48 @@ var ANIMATION_EASING = Easing.bezier(0.22, 1, 0.36, 1);
139
633
  var POP_EASING = Easing.bezier(0.34, 1.56, 0.64, 1);
140
634
  function VelocityStrip({
141
635
  velocities,
636
+ set,
142
637
  zones,
143
638
  liveRepIndex,
144
- expanded = false,
639
+ expanded = true,
145
640
  onToggle,
146
641
  onRepPress,
147
- variant = "full",
642
+ variant = "expanded",
643
+ height = EXPANDED_HEIGHT,
644
+ scale = "peak",
645
+ showNumbers = true,
148
646
  showInfo = true,
149
647
  className,
150
648
  ...props
151
649
  }) {
152
- const maxVelocity = Math.max(...velocities, 0);
153
- const meanVelocity = calculateMeanVelocity(velocities);
154
- const loss = calculateVelocityLoss(velocities);
650
+ const doneVelocities = set ? deriveDoneVelocities(set) : velocities ?? [];
651
+ const slots = set ? buildSlots(set) : doneVelocities.map((v, i) => ({
652
+ kind: "rep",
653
+ velocity: v,
654
+ leadingGap: i === 0 ? 0 : REP_GAP
655
+ }));
656
+ const maxVelocity = Math.max(...doneVelocities, 0);
657
+ const meanVelocity = calculateMeanVelocity(doneVelocities);
658
+ const loss = calculateVelocityLoss(doneVelocities);
659
+ const framed = showNumbers || showInfo;
660
+ const scaleDenom = scaleDenominator(scale, maxVelocity);
155
661
  const hasZones = zones != null && zones.length > 0;
156
662
  const barColorFor = (v) => hasZones ? bandColor(classifyBand(v, zones)) : zoneHexMap[getVelocityZoneColor(v)];
663
+ const slotColor = (slot) => {
664
+ if (slot.kind === "rep") return barColorFor(slot.velocity ?? 0);
665
+ if (slot.kind === "todo") return TODO_COLOR2;
666
+ return SET_STRIP_VARIABLE_COLOR;
667
+ };
157
668
  const meanZone = hasZones ? classifyBand(meanVelocity, zones)?.label ?? "" : getVelocityZoneName(meanVelocity);
158
669
  const prefersReducedMotion = usePrefersReducedMotion();
159
- const [heightAnim] = useState(() => new Animated.Value(expanded ? 60 : 3));
670
+ const [heightAnim] = useState(() => new Animated.Value(expanded ? height : 3));
160
671
  const [labelOpacity] = useState(() => new Animated.Value(expanded ? 1 : 0));
161
672
  const [infoOpacity] = useState(() => new Animated.Value(expanded ? 1 : 0));
162
673
  const [liveScale] = useState(() => new Animated.Value(1));
163
- const liveVelocity = liveRepIndex != null ? velocities[liveRepIndex] : void 0;
674
+ const liveVelocity = liveRepIndex != null ? doneVelocities[liveRepIndex] : void 0;
164
675
  const isNewPeak = liveVelocity != null && maxVelocity > 0 && liveVelocity === maxVelocity;
165
676
  useEffect(() => {
166
- if (variant === "mini" || liveRepIndex == null || liveVelocity == null) return;
677
+ if (variant !== "expanded" || !framed || liveRepIndex == null || liveVelocity == null) return;
167
678
  if (prefersReducedMotion) {
168
679
  liveScale.setValue(1);
169
680
  return;
@@ -193,12 +704,12 @@ function VelocityStrip({
193
704
  useNativeDriver: true
194
705
  }).start();
195
706
  }
196
- }, [variant, liveRepIndex, liveVelocity, isNewPeak, prefersReducedMotion, liveScale]);
707
+ }, [variant, framed, liveRepIndex, liveVelocity, isNewPeak, prefersReducedMotion, liveScale]);
197
708
  useEffect(() => {
198
- if (variant === "mini") return;
709
+ if (variant !== "expanded" || !framed) return;
199
710
  Animated.parallel([
200
711
  Animated.timing(heightAnim, {
201
- toValue: expanded ? 60 : 3,
712
+ toValue: expanded ? height : 3,
202
713
  duration: ANIMATION_DURATION,
203
714
  easing: ANIMATION_EASING,
204
715
  useNativeDriver: false
@@ -216,39 +727,118 @@ function VelocityStrip({
216
727
  useNativeDriver: false
217
728
  })
218
729
  ]).start();
219
- }, [expanded, variant, heightAnim, labelOpacity, infoOpacity]);
730
+ }, [expanded, variant, framed, height, heightAnim, labelOpacity, infoOpacity]);
731
+ if (set == null && velocities == null) return null;
732
+ const repCount = doneVelocities.length;
733
+ const miniLabel = set ? setAccessibilityLabel(set, repCount) : `Velocity strip, ${repCount} reps`;
220
734
  if (variant === "mini") {
221
735
  const { style: externalStyle, ...restProps } = props;
222
736
  return /* @__PURE__ */ jsx(
223
737
  View,
224
738
  {
225
739
  className,
226
- style: [{ flexDirection: "row", height: 3, gap: 2, borderRadius: 2, overflow: "hidden" }, externalStyle],
740
+ style: [
741
+ { flexDirection: "row", height: 3, gap: REP_GAP, borderRadius: 2, overflow: "hidden" },
742
+ externalStyle
743
+ ],
227
744
  accessibilityRole: "image",
228
- accessibilityLabel: `Velocity strip, ${velocities.length} reps`,
745
+ accessibilityLabel: miniLabel,
229
746
  testID: "velocity-strip-mini",
230
747
  ...restProps,
231
- children: velocities.map((v, i) => /* @__PURE__ */ jsx(
748
+ children: slots.map((slot, i) => /* @__PURE__ */ jsx(
232
749
  View,
233
750
  {
234
751
  style: {
235
752
  flex: 1,
236
- backgroundColor: barColorFor(v),
753
+ backgroundColor: slotColor(slot),
237
754
  borderRadius: 1,
238
755
  minWidth: 4,
239
- height: "100%"
756
+ height: "100%",
757
+ // The container's uniform 2px gap covers rep spacing; a wide slot adds
758
+ // only the EXTRA (WIDE_GAP − REP_GAP) so the notch totals WIDE_GAP.
759
+ marginLeft: Math.max(0, slot.leadingGap - REP_GAP),
760
+ ...slot.kind === "continue" ? { borderWidth: 1, borderColor: CONTINUE_OUTLINE } : {}
761
+ },
762
+ accessibilityElementsHidden: true,
763
+ testID: slot.kind === "rep" ? `velocity-bar-${i}` : `velocity-slot-${slot.kind}`
764
+ },
765
+ i
766
+ ))
767
+ }
768
+ );
769
+ }
770
+ if (!framed) {
771
+ const { style: externalStyle, ...restProps } = props;
772
+ return /* @__PURE__ */ jsx(
773
+ View,
774
+ {
775
+ className,
776
+ style: [
777
+ { flexDirection: "row", height, gap: REP_GAP, alignItems: "flex-end" },
778
+ externalStyle
779
+ ],
780
+ accessibilityRole: "image",
781
+ accessibilityLabel: miniLabel,
782
+ testID: "velocity-strip-compact",
783
+ ...restProps,
784
+ children: slots.map((slot, i) => /* @__PURE__ */ jsx(
785
+ View,
786
+ {
787
+ style: {
788
+ flex: 1,
789
+ minWidth: 4,
790
+ height: bareSlotHeight(slot, height, scaleDenom),
791
+ // Top-rounded to match the framed chart's bars (the "rounded tops from
792
+ // the numbers one"); square bottoms since bars sit on the baseline.
793
+ borderTopLeftRadius: 2,
794
+ borderTopRightRadius: 2,
795
+ backgroundColor: slotColor(slot),
796
+ marginLeft: Math.max(0, slot.leadingGap - REP_GAP),
797
+ ...slot.kind === "continue" ? { borderWidth: 1, borderColor: CONTINUE_OUTLINE } : {}
240
798
  },
241
799
  accessibilityElementsHidden: true,
242
- testID: `velocity-bar-${i}`
800
+ testID: slot.kind === "rep" ? `velocity-bar-${i}` : `velocity-slot-${slot.kind}`
243
801
  },
244
802
  i
245
803
  ))
246
804
  }
247
805
  );
248
806
  }
249
- const stripLabel = `Velocity chart for set, ${velocities.length} reps, tap to ${expanded ? "collapse" : "expand"}`;
807
+ const stripLabel = set ? `${setAccessibilityLabel(set, repCount)}, tap to ${expanded ? "collapse" : "expand"}` : `Velocity chart for set, ${repCount} reps, tap to ${expanded ? "collapse" : "expand"}`;
250
808
  const hasInteractiveContainer = onToggle != null;
251
809
  const hasInteractiveReps = onRepPress != null && expanded;
810
+ const setBars = set != null && slots.map((slot, i) => {
811
+ const isStraightRep = set.type === "straight" && slot.kind === "rep";
812
+ const heightPct = isStraightRep ? scaleDenom > 0 ? Math.round((slot.velocity ?? 0) / scaleDenom * 100) : 0 : set.type === "straight" ? EXPANDED_TODO_STUB_PCT : EXPANDED_ENCODED_PCT;
813
+ return /* @__PURE__ */ jsx(
814
+ View,
815
+ {
816
+ style: {
817
+ flex: 1,
818
+ height: "100%",
819
+ justifyContent: "flex-end",
820
+ marginLeft: slot.leadingGap
821
+ },
822
+ children: /* @__PURE__ */ jsx(
823
+ View,
824
+ {
825
+ style: {
826
+ height: `${heightPct}%`,
827
+ minHeight: 2,
828
+ borderTopLeftRadius: 2,
829
+ borderTopRightRadius: 2,
830
+ backgroundColor: slotColor(slot),
831
+ ...slot.kind === "continue" ? { borderWidth: 1, borderColor: CONTINUE_OUTLINE } : {}
832
+ },
833
+ testID: slot.kind === "rep" ? `velocity-bar-${i}` : `velocity-slot-${slot.kind}`,
834
+ accessibilityRole: "image",
835
+ accessibilityLabel: slotAccessibilityLabel(slot, i)
836
+ }
837
+ )
838
+ },
839
+ i
840
+ );
841
+ });
252
842
  const stripContent = /* @__PURE__ */ jsxs(
253
843
  Animated.View,
254
844
  {
@@ -261,7 +851,9 @@ function VelocityStrip({
261
851
  borderRadius: expanded ? 6 : 2,
262
852
  paddingTop: expanded ? 16 : 0,
263
853
  paddingBottom: expanded ? 24 : 0,
264
- paddingHorizontal: expanded ? 6 : 0,
854
+ // No horizontal inset the framed chart's bars span full width, matching
855
+ // the bare spotlight and mini. Numbers/info sit in the vertical padding.
856
+ paddingHorizontal: 0,
265
857
  paddingVertical: expanded ? void 0 : 8,
266
858
  overflow: expanded ? "visible" : "hidden"
267
859
  }
@@ -271,46 +863,65 @@ function VelocityStrip({
271
863
  testID: "velocity-strip",
272
864
  ...props,
273
865
  children: [
274
- /* @__PURE__ */ jsx(
275
- View,
276
- {
277
- style: { flexDirection: "row", flex: 1, gap: 2, alignItems: "flex-end" },
278
- children: velocities.map((v, i) => {
279
- const barBackground = barColorFor(v);
280
- const barHeightPct = maxVelocity > 0 ? Math.round(v / (maxVelocity * 1.15) * 100) : 0;
281
- const isLive = liveRepIndex === i;
282
- const liveLabelSuffix = isLive ? isNewPeak ? ", latest rep, new set peak" : ", latest rep" : "";
283
- const barStyle = expanded ? { height: `${barHeightPct}%`, minHeight: 2, borderTopLeftRadius: 2, borderTopRightRadius: 2, backgroundColor: barBackground } : {
284
- minHeight: "100%",
285
- borderTopLeftRadius: 2,
286
- borderTopRightRadius: 2,
287
- borderBottomLeftRadius: 0,
288
- borderBottomRightRadius: 0,
289
- backgroundColor: barBackground
290
- };
291
- const barInner = isLive ? /* @__PURE__ */ jsx(
292
- Animated.View,
293
- {
294
- style: [barStyle, { transform: [{ scale: liveScale }] }],
295
- testID: `velocity-bar-${i}`,
296
- accessibilityRole: "image",
297
- accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second${liveLabelSuffix}`
298
- }
299
- ) : /* @__PURE__ */ jsx(
300
- View,
301
- {
302
- style: barStyle,
303
- testID: `velocity-bar-${i}`,
304
- accessibilityRole: "image",
305
- accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second`
306
- }
307
- );
308
- const bar = /* @__PURE__ */ jsxs(
309
- View,
310
- {
311
- style: { flex: 1, height: "100%", justifyContent: "flex-end", position: "relative" },
312
- children: [
313
- expanded && /* @__PURE__ */ jsx(Animated.View, { style: { opacity: labelOpacity, alignItems: "center", position: "absolute", top: -13, left: 0, right: 0 }, accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx(
866
+ /* @__PURE__ */ jsx(View, { style: { flexDirection: "row", flex: 1, gap: set ? 0 : 2, alignItems: "flex-end" }, children: set ? setBars : doneVelocities.map((v, i) => {
867
+ const barBackground = barColorFor(v);
868
+ const barHeightPct = scaleDenom > 0 ? Math.round(v / scaleDenom * 100) : 0;
869
+ const isLive = liveRepIndex === i;
870
+ const liveLabelSuffix = isLive ? isNewPeak ? ", latest rep, new set peak" : ", latest rep" : "";
871
+ const barStyle = expanded ? {
872
+ height: `${barHeightPct}%`,
873
+ minHeight: 2,
874
+ borderTopLeftRadius: 2,
875
+ borderTopRightRadius: 2,
876
+ backgroundColor: barBackground
877
+ } : {
878
+ minHeight: "100%",
879
+ borderTopLeftRadius: 2,
880
+ borderTopRightRadius: 2,
881
+ borderBottomLeftRadius: 0,
882
+ borderBottomRightRadius: 0,
883
+ backgroundColor: barBackground
884
+ };
885
+ const barInner = isLive ? /* @__PURE__ */ jsx(
886
+ Animated.View,
887
+ {
888
+ style: [barStyle, { transform: [{ scale: liveScale }] }],
889
+ testID: `velocity-bar-${i}`,
890
+ accessibilityRole: "image",
891
+ accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second${liveLabelSuffix}`
892
+ }
893
+ ) : /* @__PURE__ */ jsx(
894
+ View,
895
+ {
896
+ style: barStyle,
897
+ testID: `velocity-bar-${i}`,
898
+ accessibilityRole: "image",
899
+ accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second`
900
+ }
901
+ );
902
+ const bar = /* @__PURE__ */ jsxs(
903
+ View,
904
+ {
905
+ style: {
906
+ flex: 1,
907
+ height: "100%",
908
+ justifyContent: "flex-end",
909
+ position: "relative"
910
+ },
911
+ children: [
912
+ expanded && showNumbers && /* @__PURE__ */ jsx(
913
+ Animated.View,
914
+ {
915
+ style: {
916
+ opacity: labelOpacity,
917
+ alignItems: "center",
918
+ position: "absolute",
919
+ top: -13,
920
+ left: 0,
921
+ right: 0
922
+ },
923
+ accessibilityElementsHidden: true,
924
+ children: /* @__PURE__ */ jsx(
314
925
  Text,
315
926
  {
316
927
  className: "text-text-secondary",
@@ -318,30 +929,30 @@ function VelocityStrip({
318
929
  testID: `velocity-label-${i}`,
319
930
  children: formatVelocity(v)
320
931
  }
321
- ) }),
322
- barInner
323
- ]
324
- },
325
- i
326
- );
327
- if (onRepPress && expanded) {
328
- return /* @__PURE__ */ jsx(
329
- Pressable,
330
- {
331
- style: { flex: 1, height: "100%" },
332
- onPress: () => onRepPress(i, v),
333
- accessibilityRole: "button",
334
- accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second, tap for details`,
335
- testID: `velocity-bar-pressable-${i}`,
336
- children: bar
337
- },
338
- i
339
- );
340
- }
341
- return bar;
342
- })
932
+ )
933
+ }
934
+ ),
935
+ barInner
936
+ ]
937
+ },
938
+ i
939
+ );
940
+ if (onRepPress && expanded) {
941
+ return /* @__PURE__ */ jsx(
942
+ Pressable,
943
+ {
944
+ style: { flex: 1, height: "100%" },
945
+ onPress: () => onRepPress(i, v),
946
+ accessibilityRole: "button",
947
+ accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second, tap for details`,
948
+ testID: `velocity-bar-pressable-${i}`,
949
+ children: bar
950
+ },
951
+ i
952
+ );
343
953
  }
344
- ),
954
+ return bar;
955
+ }) }),
345
956
  expanded && showInfo && /* @__PURE__ */ jsxs(
346
957
  Animated.View,
347
958
  {
@@ -487,12 +1098,14 @@ function PlaceholderStrip({
487
1098
  return /* @__PURE__ */ jsx(SingleStrip, { ...props });
488
1099
  }
489
1100
 
490
- // src/components/custom/Workout/icons.tsx
491
- function DumbbellIcon({
1101
+ // src/components/icons/SvgIcon.tsx
1102
+ function SvgIcon({
492
1103
  size = 24,
493
1104
  color = "currentColor",
1105
+ strokeWidth = 2,
494
1106
  fill = "none",
495
- strokeWidth = 2
1107
+ title,
1108
+ children
496
1109
  }) {
497
1110
  return /* @__PURE__ */ jsxs(
498
1111
  "svg",
@@ -505,36 +1118,59 @@ function DumbbellIcon({
505
1118
  strokeWidth,
506
1119
  strokeLinecap: "round",
507
1120
  strokeLinejoin: "round",
1121
+ ...title ? { role: "img", "aria-label": title } : { "aria-hidden": true },
508
1122
  children: [
509
- /* @__PURE__ */ jsx("path", { d: "M14.4 14.4 9.6 9.6" }),
510
- /* @__PURE__ */ jsx("path", { d: "M18.657 21.485a2 2 0 1 1-2.829-2.828l-1.767 1.768a2 2 0 1 1-2.829-2.829l6.364-6.364a2 2 0 1 1 2.829 2.829l-1.768 1.767a2 2 0 1 1 2.828 2.829z" }),
511
- /* @__PURE__ */ jsx("path", { d: "m21.5 21.5-1.4-1.4" }),
512
- /* @__PURE__ */ jsx("path", { d: "M3.9 3.9 2.5 2.5" }),
513
- /* @__PURE__ */ jsx("path", { d: "M6.404 12.768a2 2 0 1 1-2.829-2.829l1.768-1.767a2 2 0 1 1-2.828-2.829l2.828-2.828a2 2 0 1 1 2.829 2.828l1.767-1.768a2 2 0 1 1 2.829 2.829z" })
1123
+ title ? /* @__PURE__ */ jsx("title", { children: title }) : null,
1124
+ children
514
1125
  ]
515
1126
  }
516
1127
  );
517
1128
  }
518
- function StarIcon({
519
- size = 24,
520
- color = "currentColor",
521
- fill = "none",
522
- strokeWidth = 2
523
- }) {
524
- return /* @__PURE__ */ jsx(
525
- "svg",
526
- {
527
- width: size,
528
- height: size,
529
- viewBox: "0 0 24 24",
530
- fill,
531
- stroke: color,
532
- strokeWidth,
533
- strokeLinecap: "round",
534
- strokeLinejoin: "round",
535
- children: /* @__PURE__ */ jsx("path", { d: "M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" })
536
- }
537
- );
1129
+
1130
+ // src/components/icons/icons.tsx
1131
+ function StarIcon(props) {
1132
+ return /* @__PURE__ */ jsx(SvgIcon, { ...props, children: /* @__PURE__ */ jsx("path", { d: "M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z" }) });
1133
+ }
1134
+ function ScaleIcon(props) {
1135
+ return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
1136
+ /* @__PURE__ */ jsx("path", { d: "m16 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z" }),
1137
+ /* @__PURE__ */ jsx("path", { d: "m2 16 3-8 3 8c-.87.65-1.92 1-3 1s-2.13-.35-3-1Z" }),
1138
+ /* @__PURE__ */ jsx("path", { d: "M7 21h10" }),
1139
+ /* @__PURE__ */ jsx("path", { d: "M12 3v18" }),
1140
+ /* @__PURE__ */ jsx("path", { d: "M3 7h2c2 0 5-1 7-2 2 1 5 2 7 2h2" })
1141
+ ] });
1142
+ }
1143
+ function AlertTriangleIcon(props) {
1144
+ return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
1145
+ /* @__PURE__ */ jsx("path", { d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3Z" }),
1146
+ /* @__PURE__ */ jsx("path", { d: "M12 9v4" }),
1147
+ /* @__PURE__ */ jsx("path", { d: "M12 17h.01" })
1148
+ ] });
1149
+ }
1150
+ function TrendingDownIcon(props) {
1151
+ return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
1152
+ /* @__PURE__ */ jsx("path", { d: "M16 17h6v-6" }),
1153
+ /* @__PURE__ */ jsx("path", { d: "m22 17-8.5-8.5-5 5L2 7" })
1154
+ ] });
1155
+ }
1156
+ function CircleSlashIcon(props) {
1157
+ return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
1158
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1159
+ /* @__PURE__ */ jsx("path", { d: "m9 15 6-6" })
1160
+ ] });
1161
+ }
1162
+ function AwardIcon(props) {
1163
+ return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
1164
+ /* @__PURE__ */ jsx("path", { d: "m15.477 12.89 1.515 8.526a.5.5 0 0 1-.81.47l-3.58-2.687a1 1 0 0 0-1.197 0l-3.586 2.686a.5.5 0 0 1-.81-.469l1.514-8.526" }),
1165
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "8", r: "6" })
1166
+ ] });
1167
+ }
1168
+ function InfoIcon(props) {
1169
+ return /* @__PURE__ */ jsxs(SvgIcon, { ...props, children: [
1170
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
1171
+ /* @__PURE__ */ jsx("path", { d: "M12 16v-4" }),
1172
+ /* @__PURE__ */ jsx("path", { d: "M12 8h.01" })
1173
+ ] });
538
1174
  }
539
1175
  var baseBadgeSizeConfig = {
540
1176
  sm: { fontSize: 9, paddingH: 6, paddingV: 2, iconSize: 10 },
@@ -614,105 +1250,286 @@ function BaseBadge({
614
1250
  return badge;
615
1251
  }
616
1252
 
617
- // src/components/custom/Workout/WeightBadge.tsx
618
- function WeightBadge({
619
- value,
620
- unit = "lbs",
621
- reps,
622
- delta,
623
- isPr,
624
- showIcon = true,
625
- size = "md",
626
- onPress,
627
- className,
628
- ...props
629
- }) {
630
- const config = baseBadgeSizeConfig[size];
631
- const textColor = isPr ? "#FF7900" : "#9CA3AF";
632
- const iconColor = textColor;
633
- const repMaxClause = reps != null ? `${reps} rep max` : "Estimated one rep max";
634
- const deltaLabel = delta != null ? `, ${delta >= 0 ? "+" : ""}${delta}% change` : "";
635
- const fullLabel = `${repMaxClause}: ${value} ${unit}${deltaLabel}`;
636
- return /* @__PURE__ */ jsxs(
637
- BaseBadge,
638
- {
639
- variant: isPr ? "pr" : "plain",
640
- size,
641
- onPress,
642
- className,
643
- icon: showIcon ? /* @__PURE__ */ jsx(DumbbellIcon, { size: config.iconSize, color: iconColor, strokeWidth: 2 }) : void 0,
644
- accessibilityLabel: fullLabel,
645
- testID: "weight-badge",
646
- ...props,
647
- children: [
648
- /* @__PURE__ */ jsxs(
649
- Text,
650
- {
651
- style: {
652
- fontFamily: '"Space Grotesk", sans-serif',
653
- fontWeight: "600",
654
- fontSize: config.fontSize,
655
- color: textColor
656
- },
657
- children: [
658
- isPr ? "\u2733 " : "",
659
- value,
660
- " ",
661
- unit
662
- ]
663
- }
664
- ),
665
- reps != null && /* @__PURE__ */ jsxs(
666
- Text,
667
- {
668
- style: {
669
- fontFamily: '"Space Grotesk", sans-serif',
670
- fontWeight: "600",
671
- fontSize: config.fontSize,
672
- marginLeft: 2,
673
- color: textColor,
674
- opacity: 0.7
675
- },
676
- testID: "weight-badge-repmax",
677
- children: [
678
- reps,
679
- "RM"
680
- ]
681
- }
682
- ),
683
- delta != null && /* @__PURE__ */ jsxs(
684
- Text,
685
- {
686
- style: {
687
- fontFamily: '"Space Grotesk", sans-serif',
688
- fontSize: config.fontSize,
689
- marginLeft: 4,
690
- color: delta >= 0 ? "#4caf50" : "#ef5350"
691
- },
692
- testID: "weight-badge-delta",
693
- children: [
694
- delta >= 0 ? "+" : "",
695
- delta,
696
- "%"
697
- ]
698
- }
699
- )
700
- ]
701
- }
702
- );
703
- }
704
- var typeLabels = {
705
- e1rm: "PR e1RM",
706
- weight: "PR Weight",
707
- reps: "PR Reps",
708
- volume: "PR Volume",
709
- velocity: "PR Velocity"
710
- };
711
- function PrBadge({
712
- type = "e1rm",
713
- label: labelProp,
714
- compact = false,
715
- animate = true,
1253
+ // src/theme/tokens/semantic.ts
1254
+ var semanticColorsLight = {
1255
+ // Brand colors (brand-*)
1256
+ "brand-primary": primitiveRamps.orange[400],
1257
+ "brand-primary-light": primitiveRamps.orange[300],
1258
+ "brand-primary-dark": primitiveRamps.orange[500],
1259
+ "brand-primary-subtle": "rgba(255, 121, 0, 0.08)",
1260
+ "brand-primary-hover": primitiveRamps.orange[500],
1261
+ "brand-primary-active": primitiveRamps.orange[600],
1262
+ "brand-secondary": primitiveRamps.cyan[600],
1263
+ "brand-secondary-light": primitiveRamps.cyan[500],
1264
+ "brand-secondary-dark": primitiveRamps.cyan[700],
1265
+ "brand-secondary-subtle": "rgba(48, 123, 155, 0.08)",
1266
+ "brand-secondary-hover": primitiveRamps.cyan[700],
1267
+ "brand-secondary-active": primitiveRamps.cyan[800],
1268
+ // Text on brand backgrounds (on-*)
1269
+ "on-brand-primary": primitiveColors.white,
1270
+ "on-brand-secondary": primitiveColors.white,
1271
+ // Status colors (status-*)
1272
+ "status-success": primitiveRamps.green[300],
1273
+ "status-success-light": primitiveRamps.green[200],
1274
+ "status-success-dark": primitiveRamps.green[600],
1275
+ "status-success-subtle": primitiveRamps.green[50],
1276
+ // Live-session accent — its OWN role, decoupled from success so the two can diverge
1277
+ "status-live": primitiveRamps.green[300],
1278
+ "status-live-muted": primitiveRamps.green[500],
1279
+ "status-error": primitiveRamps.red[600],
1280
+ "status-error-light": primitiveRamps.red[500],
1281
+ "status-error-dark": primitiveRamps.red[700],
1282
+ "status-error-subtle": primitiveRamps.red[50],
1283
+ "status-error-vivid": primitiveColors.redVivid[500],
1284
+ // vivid alert red
1285
+ "status-error-vivid-light": primitiveColors.redVivid[400],
1286
+ "status-error-vivid-dark": primitiveColors.redVivid[700],
1287
+ "status-error-vivid-subtle": "rgba(255, 71, 87, 0.12)",
1288
+ "status-warning": primitiveRamps.amber[300],
1289
+ "status-warning-light": primitiveRamps.amber[200],
1290
+ "status-warning-dark": primitiveRamps.amber[500],
1291
+ "status-warning-subtle": primitiveRamps.amber[50],
1292
+ "status-info": primitiveRamps.blue[500],
1293
+ "status-info-light": primitiveRamps.blue[300],
1294
+ "status-info-dark": primitiveRamps.blue[600],
1295
+ "status-info-subtle": primitiveRamps.blue[50],
1296
+ // Text on status backgrounds (on-status-*)
1297
+ "on-status-success": primitiveColors.white,
1298
+ "on-status-error": primitiveColors.white,
1299
+ "on-status-warning": primitiveColors.white,
1300
+ "on-status-info": primitiveColors.white,
1301
+ // Result/outcome indicators (result-*)
1302
+ "result-improve": "#4caf50",
1303
+ // Green - positive outcome
1304
+ "result-improve-light": "rgba(76, 175, 80, 0.12)",
1305
+ "result-improve-dark": "#248a24",
1306
+ "result-degrade": "#ef5350",
1307
+ // Red - negative outcome
1308
+ "result-degrade-light": "rgba(239, 83, 80, 0.12)",
1309
+ "result-degrade-dark": "#b30000",
1310
+ "result-inconclusive": "#9E9A97",
1311
+ // Gray - no clear result
1312
+ "result-inconclusive-light": "rgba(158, 154, 151, 0.12)",
1313
+ "result-neutral": primitiveColors.neutral[500],
1314
+ // Neutral baseline
1315
+ // Text on result backgrounds (on-result-*)
1316
+ "on-result-improve": primitiveColors.white,
1317
+ "on-result-degrade": primitiveColors.white,
1318
+ "on-result-inconclusive": primitiveColors.white,
1319
+ // Data visualization colors (data-*)
1320
+ // First 10 colors from discrete rainbow optimized for charts
1321
+ "data-1": discreteRainbow[9],
1322
+ // Blue
1323
+ "data-2": discreteRainbow[14],
1324
+ // Green
1325
+ "data-3": discreteRainbow[17],
1326
+ // Yellow
1327
+ "data-4": discreteRainbow[25],
1328
+ // Red
1329
+ "data-5": discreteRainbow[8],
1330
+ // Purple
1331
+ "data-6": discreteRainbow[20],
1332
+ // Orange
1333
+ "data-7": discreteRainbow[13],
1334
+ // Light Blue
1335
+ "data-8": discreteRainbow[15],
1336
+ // Light Green
1337
+ "data-9": discreteRainbow[3],
1338
+ // Lavender
1339
+ "data-10": discreteRainbow[22],
1340
+ // Dark Orange
1341
+ // Text colors (text-*)
1342
+ "text-primary": "#121828",
1343
+ "text-secondary": "#65748B",
1344
+ "text-tertiary": primitiveColors.neutral[400],
1345
+ "text-disabled": "rgba(55, 65, 81, 0.48)",
1346
+ "text-inverse": primitiveColors.white,
1347
+ "text-link": primitiveColors.blue[600],
1348
+ "text-link-hover": primitiveColors.blue[700],
1349
+ // Surface colors (surface-*) - for elevated containers
1350
+ "surface-base": primitiveColors.white,
1351
+ "surface-elevated": primitiveColors.neutral[50],
1352
+ // slightly off-white for elevated cards
1353
+ "surface-raised": primitiveColors.neutral[100],
1354
+ // light gray for raised cards
1355
+ "surface-overlay": primitiveColors.white,
1356
+ "surface-input": primitiveColors.neutral[50],
1357
+ // Input field background (filled variant)
1358
+ // Background colors (background-*)
1359
+ "background-base": "#EBEBEB",
1360
+ "background-default": primitiveColors.white,
1361
+ "background-subtle": primitiveColors.neutral[50],
1362
+ // Border colors (border-*)
1363
+ "border-default": "#E8E9EB",
1364
+ "border-subtle": primitiveColors.neutral[100],
1365
+ "border-strong": primitiveColors.neutral[300],
1366
+ "border-prominent": primitiveColors.neutral[400],
1367
+ // high-visibility divider
1368
+ "border-focus": primitiveColors.blue[600],
1369
+ "border-input": primitiveColors.neutral[300],
1370
+ // Input field border
1371
+ "border-input-hover": primitiveColors.neutral[400],
1372
+ // Input field border on hover
1373
+ "border-input-focus": primitiveColors.blue[600],
1374
+ // Input field border on focus
1375
+ "border-input-error": primitiveColors.red[600],
1376
+ // Input field border on error
1377
+ // Interactive states (interactive-*)
1378
+ "interactive-hover": "rgba(55, 65, 81, 0.04)",
1379
+ "interactive-focus": "rgba(55, 65, 81, 0.12)",
1380
+ "interactive-active": "rgba(55, 65, 81, 0.16)",
1381
+ "interactive-selected": "rgba(55, 65, 81, 0.08)",
1382
+ "interactive-disabled": "rgba(55, 65, 81, 0.12)",
1383
+ "interactive-disabled-text": "rgba(55, 65, 81, 0.26)",
1384
+ // Divider
1385
+ "divider": "#E8E9EB",
1386
+ // Avatar default
1387
+ "avatar-background": primitiveColors.neutral[500],
1388
+ "avatar-text": primitiveColors.white
1389
+ };
1390
+ var semanticColorsDark = {
1391
+ // Brand colors stay the same in dark mode
1392
+ "brand-primary": primitiveRamps.orange[400],
1393
+ "brand-primary-light": primitiveRamps.orange[300],
1394
+ "brand-primary-dark": primitiveRamps.orange[500],
1395
+ "brand-primary-subtle": "rgba(255, 121, 0, 0.12)",
1396
+ "brand-primary-hover": primitiveRamps.orange[300],
1397
+ "brand-primary-active": primitiveRamps.orange[200],
1398
+ "brand-secondary": primitiveRamps.cyan[600],
1399
+ "brand-secondary-light": primitiveRamps.cyan[500],
1400
+ "brand-secondary-dark": primitiveRamps.cyan[700],
1401
+ "brand-secondary-subtle": "rgba(48, 123, 155, 0.12)",
1402
+ "brand-secondary-hover": primitiveRamps.cyan[500],
1403
+ "brand-secondary-active": primitiveRamps.cyan[400],
1404
+ // Text on brand backgrounds
1405
+ "on-brand-primary": primitiveColors.white,
1406
+ "on-brand-secondary": primitiveColors.white,
1407
+ // Status colors
1408
+ "status-success": primitiveRamps.green[300],
1409
+ "status-success-light": primitiveRamps.green[200],
1410
+ "status-success-dark": primitiveRamps.green[600],
1411
+ "status-success-subtle": "rgba(46, 213, 115, 0.12)",
1412
+ // Live-session accent — its OWN role, decoupled from success so the two can diverge
1413
+ "status-live": primitiveRamps.green[300],
1414
+ "status-live-muted": primitiveRamps.green[500],
1415
+ "status-error": primitiveRamps.red[600],
1416
+ "status-error-light": primitiveRamps.red[500],
1417
+ "status-error-dark": primitiveRamps.red[700],
1418
+ "status-error-subtle": "rgba(209, 67, 67, 0.12)",
1419
+ "status-error-vivid": primitiveColors.redVivid[500],
1420
+ "status-error-vivid-light": primitiveColors.redVivid[400],
1421
+ "status-error-vivid-dark": primitiveColors.redVivid[700],
1422
+ "status-error-vivid-subtle": "rgba(255, 71, 87, 0.12)",
1423
+ "status-warning": primitiveRamps.amber[300],
1424
+ "status-warning-light": primitiveRamps.amber[200],
1425
+ "status-warning-dark": primitiveRamps.amber[500],
1426
+ "status-warning-subtle": "rgba(249, 180, 21, 0.12)",
1427
+ "status-info": primitiveRamps.blue[500],
1428
+ "status-info-light": primitiveRamps.blue[300],
1429
+ "status-info-dark": primitiveRamps.blue[600],
1430
+ "status-info-subtle": "rgba(33, 150, 243, 0.12)",
1431
+ // Text on status backgrounds
1432
+ "on-status-success": primitiveColors.white,
1433
+ "on-status-error": primitiveColors.white,
1434
+ "on-status-warning": primitiveColors.white,
1435
+ "on-status-info": primitiveColors.white,
1436
+ // Result/outcome indicators (result-*)
1437
+ "result-improve": "#4caf50",
1438
+ "result-improve-light": "rgba(76, 175, 80, 0.16)",
1439
+ "result-improve-dark": "#248a24",
1440
+ "result-degrade": "#ef5350",
1441
+ "result-degrade-light": "rgba(239, 83, 80, 0.16)",
1442
+ "result-degrade-dark": "#b30000",
1443
+ "result-inconclusive": "#9E9A97",
1444
+ "result-inconclusive-light": "rgba(158, 154, 151, 0.16)",
1445
+ "result-neutral": primitiveColors.neutral[400],
1446
+ // Text on result backgrounds
1447
+ "on-result-improve": primitiveColors.white,
1448
+ "on-result-degrade": primitiveColors.white,
1449
+ "on-result-inconclusive": primitiveColors.white,
1450
+ // Data visualization colors (same in dark mode for consistency)
1451
+ "data-1": discreteRainbow[9],
1452
+ "data-2": discreteRainbow[14],
1453
+ "data-3": discreteRainbow[17],
1454
+ "data-4": discreteRainbow[25],
1455
+ "data-5": discreteRainbow[8],
1456
+ "data-6": discreteRainbow[20],
1457
+ "data-7": discreteRainbow[13],
1458
+ "data-8": discreteRainbow[15],
1459
+ "data-9": discreteRainbow[3],
1460
+ "data-10": discreteRainbow[22],
1461
+ // Text colors - inverted for dark mode
1462
+ "text-primary": primitiveColors.neutral[100],
1463
+ "text-secondary": primitiveColors.neutral[400],
1464
+ "text-tertiary": primitiveColors.neutral[500],
1465
+ "text-disabled": "rgba(255, 255, 255, 0.38)",
1466
+ "text-inverse": primitiveColors.neutral[900],
1467
+ "text-link": "#828DF8",
1468
+ "text-link-hover": primitiveColors.blue[400],
1469
+ // Surface colors - dark backgrounds
1470
+ "surface-base": primitiveColors.charcoal[700],
1471
+ // main surface
1472
+ "surface-elevated": primitiveColors.charcoal[600],
1473
+ // elevated surface
1474
+ "surface-raised": primitiveColors.charcoal[500],
1475
+ // raised surface
1476
+ "surface-overlay": primitiveColors.charcoal[600],
1477
+ // overlay surface
1478
+ "surface-input": primitiveColors.charcoal[600],
1479
+ // input surface
1480
+ // Background colors
1481
+ "background-base": primitiveColors.charcoal[900],
1482
+ // darkest charcoal
1483
+ "background-default": primitiveColors.charcoal[700],
1484
+ // main background
1485
+ "background-subtle": primitiveColors.charcoal[500],
1486
+ // subtle background
1487
+ // Border colors
1488
+ "border-default": primitiveColors.charcoal[400],
1489
+ // default border
1490
+ "border-subtle": primitiveColors.charcoal[500],
1491
+ // subtle border
1492
+ "border-strong": primitiveColors.charcoal[300],
1493
+ // strong border
1494
+ "border-prominent": primitiveColors.charcoal[200],
1495
+ // high-visibility divider
1496
+ "border-focus": "#828DF8",
1497
+ "border-input": primitiveColors.neutral[600],
1498
+ "border-input-hover": primitiveColors.neutral[500],
1499
+ "border-input-focus": "#828DF8",
1500
+ "border-input-error": primitiveColors.red[500],
1501
+ // Interactive states
1502
+ "interactive-hover": "rgba(255, 255, 255, 0.04)",
1503
+ "interactive-focus": "rgba(255, 255, 255, 0.12)",
1504
+ "interactive-active": "rgba(255, 255, 255, 0.16)",
1505
+ "interactive-selected": "rgba(255, 255, 255, 0.08)",
1506
+ "interactive-disabled": "rgba(255, 255, 255, 0.12)",
1507
+ "interactive-disabled-text": "rgba(255, 255, 255, 0.26)",
1508
+ // Divider
1509
+ "divider": primitiveColors.charcoal[400],
1510
+ // divider color
1511
+ // Avatar default
1512
+ "avatar-background": primitiveColors.neutral[600],
1513
+ "avatar-text": primitiveColors.white
1514
+ };
1515
+ function getSemanticColors(mode) {
1516
+ return mode === "dark" ? semanticColorsDark : semanticColorsLight;
1517
+ }
1518
+
1519
+ // src/components/custom/Workout/PrBadge.tsx
1520
+ var BRAND_PRIMARY = getSemanticColors("dark")["brand-primary"];
1521
+ var typeLabels = {
1522
+ e1rm: "PR e1RM",
1523
+ weight: "PR Weight",
1524
+ reps: "PR Reps",
1525
+ volume: "PR Volume",
1526
+ velocity: "PR Velocity"
1527
+ };
1528
+ function PrBadge({
1529
+ type = "e1rm",
1530
+ label: labelProp,
1531
+ compact = false,
1532
+ animate = true,
716
1533
  className,
717
1534
  ...props
718
1535
  }) {
@@ -744,7 +1561,7 @@ function PrBadge({
744
1561
  accessibilityLabel: `Personal record: ${resolvedLabel}`,
745
1562
  testID: "pr-badge-star",
746
1563
  ...props,
747
- children: /* @__PURE__ */ jsx(StarIcon, { size: 14, color: "#FF7900", fill: "#FF7900", strokeWidth: 2 })
1564
+ children: /* @__PURE__ */ jsx(StarIcon, { size: 14, color: BRAND_PRIMARY, fill: BRAND_PRIMARY, strokeWidth: 2 })
748
1565
  }
749
1566
  ) : /* @__PURE__ */ jsx(
750
1567
  BaseBadge,
@@ -758,7 +1575,7 @@ function PrBadge({
758
1575
  {
759
1576
  style: {
760
1577
  fontSize: 12,
761
- color: "#FF7900",
1578
+ color: BRAND_PRIMARY,
762
1579
  fontWeight: "700",
763
1580
  fontFamily: "Inter, sans-serif"
764
1581
  },
@@ -783,6 +1600,204 @@ function PrBadge({
783
1600
  }
784
1601
  return badge;
785
1602
  }
1603
+ var DARK = getSemanticColors("dark");
1604
+ var TEXT_ACTIVE = DARK["text-primary"];
1605
+ var TEXT_MUTED = DARK["text-secondary"];
1606
+ var COL = { set: 36, reps: 44, load: 56, rpe: 36 };
1607
+ var cellText = { fontFamily: "Inter, sans-serif", fontSize: 13, fontWeight: "600" };
1608
+ var typeBadge = {
1609
+ fontSize: 10,
1610
+ fontWeight: "700",
1611
+ fontFamily: "Inter, sans-serif",
1612
+ color: WORKOUT_TOKENS.scale.orange,
1613
+ backgroundColor: "rgba(255,165,2,0.12)",
1614
+ paddingVertical: 1,
1615
+ paddingHorizontal: 5,
1616
+ borderRadius: 3,
1617
+ overflow: "hidden"
1618
+ };
1619
+ function displayReps(set) {
1620
+ return set.state === "done" ? set.reps : set.target.reps;
1621
+ }
1622
+ function displayWeight(set) {
1623
+ return set.state === "done" ? set.weight : set.target.weight;
1624
+ }
1625
+ function plannedReps(set) {
1626
+ if (set.state === "done") return set.velocities.length;
1627
+ if (set.state === "live") return set.target.reps;
1628
+ return set.planned ?? set.target.reps;
1629
+ }
1630
+ function accessibilityLabel(set) {
1631
+ const base = `Set ${set.setNumber}: ${displayReps(set)} reps at ${roundWeight(displayWeight(set))} ${set.unit}`;
1632
+ if (set.state === "live") return `${base}, in progress`;
1633
+ if (set.state === "todo") return `${base}, upcoming`;
1634
+ return base;
1635
+ }
1636
+ function Cell({
1637
+ width,
1638
+ children,
1639
+ testID
1640
+ }) {
1641
+ return /* @__PURE__ */ jsx(View, { style: { width, alignItems: "center", justifyContent: "center" }, testID, children });
1642
+ }
1643
+ function RowStrip({ set }) {
1644
+ const zones = set.velocityZones;
1645
+ if (set.state === "live") {
1646
+ return /* @__PURE__ */ jsx(
1647
+ VelocityStrip,
1648
+ {
1649
+ variant: "expanded",
1650
+ showNumbers: false,
1651
+ showInfo: false,
1652
+ height: 24,
1653
+ scale: "fixed",
1654
+ set: { type: "straight", velocities: set.velocities, planned: set.target.reps },
1655
+ zones
1656
+ }
1657
+ );
1658
+ }
1659
+ const velocities = set.state === "done" ? set.velocities : [];
1660
+ return /* @__PURE__ */ jsx(
1661
+ VelocityStrip,
1662
+ {
1663
+ variant: "mini",
1664
+ set: { type: "straight", velocities, planned: plannedReps(set) },
1665
+ zones
1666
+ }
1667
+ );
1668
+ }
1669
+ function SetRow(set) {
1670
+ const live = set.state === "live";
1671
+ const valueColor = live ? TEXT_ACTIVE : TEXT_MUTED;
1672
+ const rpe = set.state === "todo" ? null : set.rpe;
1673
+ return /* @__PURE__ */ jsxs(
1674
+ View,
1675
+ {
1676
+ style: { paddingVertical: 6, paddingHorizontal: 8 },
1677
+ accessibilityLabel: accessibilityLabel(set),
1678
+ testID: "set-row",
1679
+ children: [
1680
+ /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { justifyContent: "space-between" }, children: [
1681
+ /* @__PURE__ */ jsx(Cell, { width: COL.set, testID: "set-row-set-number", children: set.setType ? /* @__PURE__ */ jsx(Text, { style: typeBadge, testID: "set-row-type-badge", children: set.setType }) : /* @__PURE__ */ jsx(Text, { style: { ...cellText, color: valueColor, fontWeight: live ? "700" : "600" }, children: set.setNumber }) }),
1682
+ /* @__PURE__ */ jsx(Cell, { width: COL.reps, testID: "set-row-reps", children: /* @__PURE__ */ jsx(Text, { style: { ...cellText, color: valueColor }, children: displayReps(set) }) }),
1683
+ /* @__PURE__ */ jsx(Cell, { width: COL.load, testID: "set-row-weight", children: /* @__PURE__ */ jsx(Text, { style: { ...cellText, color: valueColor }, children: roundWeight(displayWeight(set)) }) }),
1684
+ /* @__PURE__ */ jsx(Cell, { width: COL.rpe, testID: "set-row-rpe", children: /* @__PURE__ */ jsx(Text, { style: { ...cellText, color: TEXT_MUTED }, children: rpe != null ? roundRpe(rpe) : "\u2014" }) })
1685
+ ] }),
1686
+ /* @__PURE__ */ jsx(View, { style: { marginTop: live ? 6 : 4 }, testID: "set-row-strip", children: /* @__PURE__ */ jsx(RowStrip, { set }) })
1687
+ ]
1688
+ }
1689
+ );
1690
+ }
1691
+ var PREV_COLUMN = { label: "PREV", width: void 0 };
1692
+ function buildColumns(unit, showPrevious) {
1693
+ return [
1694
+ { label: "SET", width: 36 },
1695
+ ...showPrevious ? [PREV_COLUMN] : [],
1696
+ { label: "REPS", width: 44 },
1697
+ { label: unit.toUpperCase(), width: 56 },
1698
+ { label: "RPE", width: 36 }
1699
+ ];
1700
+ }
1701
+ function SetTableHeader({
1702
+ unit = "lbs",
1703
+ showPrevious = true,
1704
+ testID = "table-header"
1705
+ }) {
1706
+ const columns = buildColumns(unit, showPrevious);
1707
+ return /* @__PURE__ */ jsx(
1708
+ View,
1709
+ {
1710
+ className: "flex-row",
1711
+ style: {
1712
+ paddingVertical: 8,
1713
+ paddingHorizontal: 8,
1714
+ paddingBottom: 4,
1715
+ ...showPrevious ? {} : { justifyContent: "space-between" }
1716
+ },
1717
+ testID,
1718
+ children: columns.map(({ label, width }) => {
1719
+ const isFlex = width === void 0;
1720
+ return /* @__PURE__ */ jsx(
1721
+ View,
1722
+ {
1723
+ style: {
1724
+ ...isFlex ? { minWidth: 44 } : { width, flexShrink: 1 },
1725
+ alignItems: "center",
1726
+ justifyContent: "center",
1727
+ gap: 8
1728
+ },
1729
+ ...isFlex ? { className: "flex-1" } : {},
1730
+ children: /* @__PURE__ */ jsx(
1731
+ Text,
1732
+ {
1733
+ className: "text-text-tertiary",
1734
+ style: {
1735
+ fontSize: 10,
1736
+ fontWeight: "600",
1737
+ fontFamily: "Inter, sans-serif",
1738
+ textTransform: "uppercase",
1739
+ letterSpacing: 0.8
1740
+ },
1741
+ children: label
1742
+ }
1743
+ )
1744
+ },
1745
+ label
1746
+ );
1747
+ })
1748
+ }
1749
+ );
1750
+ }
1751
+ var METRIC_FONT = "Inter, sans-serif";
1752
+ function MetricCell({ children, color, fontSize = 11 }) {
1753
+ return /* @__PURE__ */ jsx(
1754
+ Text,
1755
+ {
1756
+ style: {
1757
+ fontFamily: METRIC_FONT,
1758
+ fontSize,
1759
+ color,
1760
+ fontWeight: "600",
1761
+ letterSpacing: 1
1762
+ },
1763
+ children
1764
+ }
1765
+ );
1766
+ }
1767
+
1768
+ // src/components/custom/Workout/SetsRepsLoad.tsx
1769
+ var t = getSemanticColors("dark");
1770
+ var TIMES = "\xD7";
1771
+ var AT = "@";
1772
+ function SetsRepsLoad({
1773
+ sets,
1774
+ reps,
1775
+ load,
1776
+ unit = "lb",
1777
+ className,
1778
+ ...props
1779
+ }) {
1780
+ const value = t["text-primary"];
1781
+ const sep = t["text-tertiary"];
1782
+ return /* @__PURE__ */ jsxs(
1783
+ View,
1784
+ {
1785
+ className,
1786
+ style: { flexDirection: "row", alignItems: "baseline" },
1787
+ accessibilityLabel: `${sets} sets of ${reps} reps at ${load} ${unit}`,
1788
+ testID: "sets-reps-load",
1789
+ ...props,
1790
+ children: [
1791
+ /* @__PURE__ */ jsx(MetricCell, { color: value, children: sets }),
1792
+ /* @__PURE__ */ jsx(MetricCell, { color: sep, children: ` ${TIMES} ` }),
1793
+ /* @__PURE__ */ jsx(MetricCell, { color: value, children: reps }),
1794
+ /* @__PURE__ */ jsx(MetricCell, { color: sep, children: ` ${AT} ` }),
1795
+ /* @__PURE__ */ jsx(MetricCell, { color: value, children: load }),
1796
+ /* @__PURE__ */ jsx(MetricCell, { color: sep, children: ` ${unit}` })
1797
+ ]
1798
+ }
1799
+ );
1800
+ }
786
1801
  function hexToRgb(hex) {
787
1802
  const cleaned = hex.replace("#", "");
788
1803
  let r, g, b;
@@ -1092,452 +2107,54 @@ function alpha(color, opacity) {
1092
2107
  }
1093
2108
  return color;
1094
2109
  }
2110
+ var t2 = getSemanticColors("dark");
2111
+ var TEMPO_PACING = {
2112
+ behindThresholdPct: 0.15,
2113
+ minPhaseDurationMs: 500
2114
+ };
2115
+ function getTempoPacingState(elapsedMs, targetMs) {
2116
+ if (!targetMs || targetMs < TEMPO_PACING.minPhaseDurationMs) return "none";
2117
+ const ratio = elapsedMs / targetMs;
2118
+ if (ratio > 1 + TEMPO_PACING.behindThresholdPct) return "behind";
2119
+ return "on-pace";
2120
+ }
2121
+ function getTempoFillPct(elapsedMs, targetMs) {
2122
+ if (!targetMs) return 100;
2123
+ return Math.min(100, elapsedMs / targetMs * 100);
2124
+ }
2125
+ ({
2126
+ concentric: { color: t2["status-success"]},
2127
+ hold: { color: t2["brand-primary"]},
2128
+ eccentric: { color: t2["status-warning"]}
2129
+ });
1095
2130
 
1096
- // src/theme/tokens/primitives.ts
1097
- var primitiveColors = {
1098
- // Blue scale (primary brand)
1099
- blue: {
1100
- 400: "#60A5FA",
1101
- 600: "#5048E5",
1102
- // Primary main
1103
- 700: "#3832A0"},
1104
- // Teal scale (success)
1105
- teal: {
1106
- 50: "#F0FDFA",
1107
- 400: "#43C6B7",
1108
- // Success light
1109
- 500: "#14B8A6",
1110
- 700: "#0E8074"},
1111
- // Red scale (error)
1112
- red: {
1113
- 50: "#FEF2F2",
1114
- 400: "#DA6868",
1115
- // Error light
1116
- 500: "#EF4444",
1117
- 600: "#D14343",
1118
- // Error main
1119
- 700: "#922E2E"},
1120
- // Amber scale (warning)
1121
- amber: {
1122
- 50: "#FFFBEB",
1123
- 400: "#FFBF4C",
1124
- // Warning light
1125
- 500: "#FFB020",
1126
- // Warning main
1127
- 600: "#B27B16"},
1128
- // Sky/Blue scale (info)
1129
- sky: {
1130
- 50: "#F0F9FF",
1131
- 400: "#64B6F7",
1132
- // Info light
1133
- 500: "#2196F3",
1134
- 700: "#0B79D0"},
1135
- // Neutral/Gray scale
1136
- neutral: {
1137
- 50: "#FAFAFA",
1138
- 100: "#F3F4F6",
1139
- 300: "#D1D5DB",
1140
- 400: "#9CA3AF",
1141
- 500: "#6B7280",
1142
- 600: "#4B5563",
1143
- 900: "#111827"},
1144
- // Orange scale (accent/brand color)
1145
- accent: {
1146
- 200: "#FF9630",
1147
- 300: "#FF8500",
1148
- 400: "#FF7900",
1149
- 500: "#F56C00",
1150
- 600: "#E06D10",
1151
- 700: "#D0620C"},
1152
- // Charcoal scale (dark backgrounds)
1153
- charcoal: {
1154
- 300: "#2C2C2C",
1155
- 400: "#1F1F1F",
1156
- 500: "#1C1C1C",
1157
- 600: "#191919",
1158
- 700: "#161616",
1159
- 900: "#101010"
1160
- },
1161
- // Steel scale (cool accent)
1162
- steel: {
1163
- 300: "#678498",
1164
- 400: "#557488",
1165
- 500: "#406D87",
1166
- 600: "#39617A",
1167
- 700: "#32556D"},
1168
- // Pure colors
1169
- white: "#FFFFFF"};
1170
- var discreteRainbow = [
1171
- "#E8ECFB",
1172
- "#D9CCE3",
1173
- "#D1BBD7",
1174
- "#CAACCB",
1175
- "#BA8DB4",
1176
- "#AE76A3",
1177
- "#AA6F9E",
1178
- "#994F88",
1179
- "#882E72",
1180
- "#1965B0",
1181
- "#437DBF",
1182
- "#5289C7",
1183
- "#6195CF",
1184
- "#7BAFDE",
1185
- "#4EB265",
1186
- "#90C987",
1187
- "#CAE0AB",
1188
- "#F7F056",
1189
- "#F7CB45",
1190
- "#F6C141",
1191
- "#F4A736",
1192
- "#F1932D",
1193
- "#EE8026",
1194
- "#E8601C",
1195
- "#E65518",
1196
- "#DC050C",
1197
- "#A5170E",
1198
- "#72190E",
1199
- "#42150A"
1200
- ];
1201
-
1202
- // src/theme/tokens/semantic.ts
1203
- var semanticColorsLight = {
1204
- // Brand colors (brand-*)
1205
- "brand-primary": primitiveColors.accent[400],
1206
- // #FF7900
1207
- "brand-primary-light": primitiveColors.accent[200],
1208
- // #FF9630
1209
- "brand-primary-dark": primitiveColors.accent[700],
1210
- // #D0620C
1211
- "brand-primary-subtle": "rgba(255, 121, 0, 0.08)",
1212
- "brand-primary-hover": primitiveColors.accent[500],
1213
- "brand-primary-active": primitiveColors.accent[600],
1214
- "brand-secondary": primitiveColors.steel[500],
1215
- // #406D87
1216
- "brand-secondary-light": primitiveColors.steel[300],
1217
- // #678498
1218
- "brand-secondary-dark": primitiveColors.steel[700],
1219
- // #32556D
1220
- "brand-secondary-subtle": "rgba(64, 109, 135, 0.08)",
1221
- "brand-secondary-hover": primitiveColors.steel[600],
1222
- "brand-secondary-active": primitiveColors.steel[700],
1223
- // Text on brand backgrounds (on-*)
1224
- "on-brand-primary": primitiveColors.white,
1225
- "on-brand-secondary": primitiveColors.white,
1226
- // Status colors (status-*)
1227
- "status-success": primitiveColors.teal[500],
1228
- // #14B8A6
1229
- "status-success-light": primitiveColors.teal[400],
1230
- // #43C6B7
1231
- "status-success-dark": primitiveColors.teal[700],
1232
- // #0E8074
1233
- "status-success-subtle": primitiveColors.teal[50],
1234
- "status-error": primitiveColors.red[600],
1235
- // #D14343
1236
- "status-error-light": primitiveColors.red[400],
1237
- // #DA6868
1238
- "status-error-dark": primitiveColors.red[700],
1239
- // #922E2E
1240
- "status-error-subtle": primitiveColors.red[50],
1241
- "status-warning": primitiveColors.amber[500],
1242
- // #FFB020
1243
- "status-warning-light": primitiveColors.amber[400],
1244
- // #FFBF4C
1245
- "status-warning-dark": primitiveColors.amber[600],
1246
- // #B27B16
1247
- "status-warning-subtle": primitiveColors.amber[50],
1248
- "status-info": primitiveColors.sky[500],
1249
- // #2196F3
1250
- "status-info-light": primitiveColors.sky[400],
1251
- // #64B6F7
1252
- "status-info-dark": primitiveColors.sky[700],
1253
- // #0B79D0
1254
- "status-info-subtle": primitiveColors.sky[50],
1255
- // Text on status backgrounds (on-status-*)
1256
- "on-status-success": primitiveColors.white,
1257
- "on-status-error": primitiveColors.white,
1258
- "on-status-warning": primitiveColors.white,
1259
- "on-status-info": primitiveColors.white,
1260
- // Result/outcome indicators (result-*)
1261
- "result-improve": "#4caf50",
1262
- // Green - positive outcome
1263
- "result-improve-light": "rgba(76, 175, 80, 0.12)",
1264
- "result-improve-dark": "#248a24",
1265
- "result-degrade": "#ef5350",
1266
- // Red - negative outcome
1267
- "result-degrade-light": "rgba(239, 83, 80, 0.12)",
1268
- "result-degrade-dark": "#b30000",
1269
- "result-inconclusive": "#9E9A97",
1270
- // Gray - no clear result
1271
- "result-inconclusive-light": "rgba(158, 154, 151, 0.12)",
1272
- "result-neutral": primitiveColors.neutral[500],
1273
- // Neutral baseline
1274
- // Text on result backgrounds (on-result-*)
1275
- "on-result-improve": primitiveColors.white,
1276
- "on-result-degrade": primitiveColors.white,
1277
- "on-result-inconclusive": primitiveColors.white,
1278
- // Data visualization colors (data-*)
1279
- // First 10 colors from discrete rainbow optimized for charts
1280
- "data-1": discreteRainbow[9],
1281
- // #1965B0 - Blue
1282
- "data-2": discreteRainbow[14],
1283
- // #4EB265 - Green
1284
- "data-3": discreteRainbow[17],
1285
- // #F7F056 - Yellow
1286
- "data-4": discreteRainbow[25],
1287
- // #DC050C - Red
1288
- "data-5": discreteRainbow[8],
1289
- // #882E72 - Purple
1290
- "data-6": discreteRainbow[20],
1291
- // #F4A736 - Orange
1292
- "data-7": discreteRainbow[13],
1293
- // #7BAFDE - Light Blue
1294
- "data-8": discreteRainbow[15],
1295
- // #90C987 - Light Green
1296
- "data-9": discreteRainbow[3],
1297
- // #CAACCB - Lavender
1298
- "data-10": discreteRainbow[22],
1299
- // #EE8026 - Dark Orange
1300
- // Text colors (text-*)
1301
- "text-primary": "#121828",
1302
- "text-secondary": "#65748B",
1303
- "text-tertiary": primitiveColors.neutral[400],
1304
- "text-disabled": "rgba(55, 65, 81, 0.48)",
1305
- "text-inverse": primitiveColors.white,
1306
- "text-link": primitiveColors.blue[600],
1307
- "text-link-hover": primitiveColors.blue[700],
1308
- // Surface colors (surface-*) - for elevated containers
1309
- "surface-base": primitiveColors.white,
1310
- "surface-elevated": primitiveColors.neutral[50],
1311
- // #FAFAFA - slightly off-white for elevated cards
1312
- "surface-raised": primitiveColors.neutral[100],
1313
- // #F3F4F6 - light gray for raised cards
1314
- "surface-overlay": primitiveColors.white,
1315
- "surface-input": primitiveColors.neutral[50],
1316
- // Input field background (filled variant)
1317
- // Background colors (background-*)
1318
- "background-base": "#EBEBEB",
1319
- "background-default": primitiveColors.white,
1320
- "background-subtle": primitiveColors.neutral[50],
1321
- // Border colors (border-*)
1322
- "border-default": "#E8E9EB",
1323
- "border-subtle": primitiveColors.neutral[100],
1324
- "border-strong": primitiveColors.neutral[300],
1325
- "border-focus": primitiveColors.blue[600],
1326
- "border-input": primitiveColors.neutral[300],
1327
- // Input field border
1328
- "border-input-hover": primitiveColors.neutral[400],
1329
- // Input field border on hover
1330
- "border-input-focus": primitiveColors.blue[600],
1331
- // Input field border on focus
1332
- "border-input-error": primitiveColors.red[600],
1333
- // Input field border on error
1334
- // Interactive states (interactive-*)
1335
- "interactive-hover": "rgba(55, 65, 81, 0.04)",
1336
- "interactive-focus": "rgba(55, 65, 81, 0.12)",
1337
- "interactive-active": "rgba(55, 65, 81, 0.16)",
1338
- "interactive-selected": "rgba(55, 65, 81, 0.08)",
1339
- "interactive-disabled": "rgba(55, 65, 81, 0.12)",
1340
- "interactive-disabled-text": "rgba(55, 65, 81, 0.26)",
1341
- // Divider
1342
- "divider": "#E8E9EB",
1343
- // Avatar default
1344
- "avatar-background": primitiveColors.neutral[500],
1345
- "avatar-text": primitiveColors.white
1346
- };
1347
- var semanticColorsDark = {
1348
- // Brand colors stay the same in dark mode
1349
- "brand-primary": primitiveColors.accent[400],
1350
- "brand-primary-light": primitiveColors.accent[200],
1351
- "brand-primary-dark": primitiveColors.accent[700],
1352
- "brand-primary-subtle": "rgba(255, 121, 0, 0.12)",
1353
- "brand-primary-hover": primitiveColors.accent[300],
1354
- "brand-primary-active": primitiveColors.accent[200],
1355
- "brand-secondary": primitiveColors.steel[500],
1356
- "brand-secondary-light": primitiveColors.steel[300],
1357
- "brand-secondary-dark": primitiveColors.steel[700],
1358
- "brand-secondary-subtle": "rgba(64, 109, 135, 0.12)",
1359
- "brand-secondary-hover": primitiveColors.steel[400],
1360
- "brand-secondary-active": primitiveColors.steel[300],
1361
- // Text on brand backgrounds
1362
- "on-brand-primary": primitiveColors.white,
1363
- "on-brand-secondary": primitiveColors.white,
1364
- // Status colors
1365
- "status-success": primitiveColors.teal[500],
1366
- "status-success-light": primitiveColors.teal[400],
1367
- "status-success-dark": primitiveColors.teal[700],
1368
- "status-success-subtle": "rgba(20, 184, 166, 0.12)",
1369
- "status-error": primitiveColors.red[600],
1370
- "status-error-light": primitiveColors.red[400],
1371
- "status-error-dark": primitiveColors.red[700],
1372
- "status-error-subtle": "rgba(209, 67, 67, 0.12)",
1373
- "status-warning": primitiveColors.amber[500],
1374
- "status-warning-light": primitiveColors.amber[400],
1375
- "status-warning-dark": primitiveColors.amber[600],
1376
- "status-warning-subtle": "rgba(255, 176, 32, 0.12)",
1377
- "status-info": primitiveColors.sky[500],
1378
- "status-info-light": primitiveColors.sky[400],
1379
- "status-info-dark": primitiveColors.sky[700],
1380
- "status-info-subtle": "rgba(33, 150, 243, 0.12)",
1381
- // Text on status backgrounds
1382
- "on-status-success": primitiveColors.white,
1383
- "on-status-error": primitiveColors.white,
1384
- "on-status-warning": primitiveColors.white,
1385
- "on-status-info": primitiveColors.white,
1386
- // Result/outcome indicators (result-*)
1387
- "result-improve": "#4caf50",
1388
- "result-improve-light": "rgba(76, 175, 80, 0.16)",
1389
- "result-improve-dark": "#248a24",
1390
- "result-degrade": "#ef5350",
1391
- "result-degrade-light": "rgba(239, 83, 80, 0.16)",
1392
- "result-degrade-dark": "#b30000",
1393
- "result-inconclusive": "#9E9A97",
1394
- "result-inconclusive-light": "rgba(158, 154, 151, 0.16)",
1395
- "result-neutral": primitiveColors.neutral[400],
1396
- // Text on result backgrounds
1397
- "on-result-improve": primitiveColors.white,
1398
- "on-result-degrade": primitiveColors.white,
1399
- "on-result-inconclusive": primitiveColors.white,
1400
- // Data visualization colors (same in dark mode for consistency)
1401
- "data-1": discreteRainbow[9],
1402
- "data-2": discreteRainbow[14],
1403
- "data-3": discreteRainbow[17],
1404
- "data-4": discreteRainbow[25],
1405
- "data-5": discreteRainbow[8],
1406
- "data-6": discreteRainbow[20],
1407
- "data-7": discreteRainbow[13],
1408
- "data-8": discreteRainbow[15],
1409
- "data-9": discreteRainbow[3],
1410
- "data-10": discreteRainbow[22],
1411
- // Text colors - inverted for dark mode
1412
- "text-primary": primitiveColors.neutral[100],
1413
- "text-secondary": primitiveColors.neutral[400],
1414
- "text-tertiary": primitiveColors.neutral[500],
1415
- "text-disabled": "rgba(255, 255, 255, 0.38)",
1416
- "text-inverse": primitiveColors.neutral[900],
1417
- "text-link": "#828DF8",
1418
- "text-link-hover": primitiveColors.blue[400],
1419
- // Surface colors - dark backgrounds
1420
- "surface-base": primitiveColors.charcoal[700],
1421
- // #161616 - main surface
1422
- "surface-elevated": primitiveColors.charcoal[600],
1423
- // #191919 - elevated surface
1424
- "surface-raised": primitiveColors.charcoal[500],
1425
- // #1C1C1C - raised surface
1426
- "surface-overlay": primitiveColors.charcoal[600],
1427
- // #191919 - overlay surface
1428
- "surface-input": primitiveColors.charcoal[600],
1429
- // #191919 - input surface
1430
- // Background colors
1431
- "background-base": primitiveColors.charcoal[900],
1432
- // #101010 - darkest charcoal
1433
- "background-default": primitiveColors.charcoal[700],
1434
- // #161616 - main background
1435
- "background-subtle": primitiveColors.charcoal[500],
1436
- // #1C1C1C - subtle background
1437
- // Border colors
1438
- "border-default": primitiveColors.charcoal[400],
1439
- // #1F1F1F - default border
1440
- "border-subtle": primitiveColors.charcoal[500],
1441
- // #1C1C1C - subtle border
1442
- "border-strong": primitiveColors.charcoal[300],
1443
- // #2C2C2C - strong border
1444
- "border-focus": "#828DF8",
1445
- "border-input": primitiveColors.neutral[600],
1446
- "border-input-hover": primitiveColors.neutral[500],
1447
- "border-input-focus": "#828DF8",
1448
- "border-input-error": primitiveColors.red[500],
1449
- // Interactive states
1450
- "interactive-hover": "rgba(255, 255, 255, 0.04)",
1451
- "interactive-focus": "rgba(255, 255, 255, 0.12)",
1452
- "interactive-active": "rgba(255, 255, 255, 0.16)",
1453
- "interactive-selected": "rgba(255, 255, 255, 0.08)",
1454
- "interactive-disabled": "rgba(255, 255, 255, 0.12)",
1455
- "interactive-disabled-text": "rgba(255, 255, 255, 0.26)",
1456
- // Divider
1457
- "divider": primitiveColors.charcoal[400],
1458
- // #1F1F1F - divider color
1459
- // Avatar default
1460
- "avatar-background": primitiveColors.neutral[600],
1461
- "avatar-text": primitiveColors.white
1462
- };
1463
- function getSemanticColors(mode) {
1464
- return mode === "dark" ? semanticColorsDark : semanticColorsLight;
1465
- }
1466
-
1467
- // src/components/custom/Workout/TempoBar.tsx
1468
- var t = getSemanticColors("dark");
1469
- var TEMPO_PACING = {
1470
- behindThresholdPct: 0.15,
1471
- minPhaseDurationMs: 500
1472
- };
1473
- function getTempoPacingState(elapsedMs, targetMs) {
1474
- if (!targetMs || targetMs < TEMPO_PACING.minPhaseDurationMs) return "none";
1475
- const ratio = elapsedMs / targetMs;
1476
- if (ratio > 1 + TEMPO_PACING.behindThresholdPct) return "behind";
1477
- return "on-pace";
1478
- }
1479
- function getTempoFillPct(elapsedMs, targetMs) {
1480
- if (!targetMs) return 100;
1481
- return Math.min(100, elapsedMs / targetMs * 100);
1482
- }
1483
- ({
1484
- concentric: { color: t["status-success"]},
1485
- hold: { color: t["brand-primary"]},
1486
- eccentric: { color: t["status-warning"]}
1487
- });
1488
-
1489
- // src/components/custom/Workout/TempoDisplay.tsx
1490
- var INTER = "Inter, sans-serif";
1491
- var TEXT_TERTIARY = "#6B7280";
1492
- var STATUS_ERROR = "#D14343";
1493
- var phaseColors = {
1494
- eccentric: "#FFB020",
1495
- // status-warning (amber)
1496
- pauseBottom: TEXT_TERTIARY,
1497
- concentric: "#14B8A6",
1498
- // status-success (teal)
1499
- pauseTop: TEXT_TERTIARY,
1500
- dash: TEXT_TERTIARY
1501
- };
1502
- function TempoValue({
1503
- value,
1504
- color,
1505
- fontSize
1506
- }) {
1507
- return /* @__PURE__ */ jsx(
1508
- Text,
1509
- {
1510
- style: {
1511
- fontFamily: INTER,
1512
- fontSize,
1513
- color,
1514
- fontWeight: "600",
1515
- letterSpacing: 1
1516
- },
1517
- children: value
1518
- }
1519
- );
1520
- }
1521
- function TempoSeparator({ color, fontSize }) {
1522
- return /* @__PURE__ */ jsx(
1523
- Text,
1524
- {
1525
- style: {
1526
- fontFamily: INTER,
1527
- fontSize,
1528
- color,
1529
- fontWeight: "600",
1530
- letterSpacing: 1
1531
- },
1532
- children: "-"
1533
- }
1534
- );
1535
- }
1536
- var LIVE_PHASES = [
1537
- { key: "eccentric", color: phaseColors.eccentric },
1538
- { key: "pauseBottom", color: phaseColors.pauseBottom },
1539
- { key: "concentric", color: phaseColors.concentric },
1540
- { key: "pauseTop", color: phaseColors.pauseTop }
2131
+ // src/components/custom/Workout/TempoDisplay.tsx
2132
+ var t3 = getSemanticColors("dark");
2133
+ var INTER = "Inter, sans-serif";
2134
+ var TEXT_TERTIARY = "#6B7280";
2135
+ var STATUS_ERROR = t3["status-error"];
2136
+ var phaseColors = {
2137
+ eccentric: t3["status-warning"],
2138
+ pauseBottom: TEXT_TERTIARY,
2139
+ concentric: t3["status-success"],
2140
+ pauseTop: TEXT_TERTIARY,
2141
+ dash: TEXT_TERTIARY
2142
+ };
2143
+ function TempoValue({
2144
+ value,
2145
+ color,
2146
+ fontSize
2147
+ }) {
2148
+ return /* @__PURE__ */ jsx(MetricCell, { color, fontSize, children: value });
2149
+ }
2150
+ function TempoSeparator({ color, fontSize }) {
2151
+ return /* @__PURE__ */ jsx(MetricCell, { color, fontSize, children: "-" });
2152
+ }
2153
+ var LIVE_PHASES = [
2154
+ { key: "eccentric", color: phaseColors.eccentric },
2155
+ { key: "pauseBottom", color: phaseColors.pauseBottom },
2156
+ { key: "concentric", color: phaseColors.concentric },
2157
+ { key: "pauseTop", color: phaseColors.pauseTop }
1541
2158
  ];
1542
2159
  function LiveTempoCell({
1543
2160
  value,
@@ -1593,6 +2210,7 @@ function TempoDisplay({
1593
2210
  tempo,
1594
2211
  size = "md",
1595
2212
  colored = true,
2213
+ showLabel = true,
1596
2214
  showInfo = true,
1597
2215
  live,
1598
2216
  onPress,
@@ -1626,7 +2244,7 @@ function TempoDisplay({
1626
2244
  },
1627
2245
  ...props,
1628
2246
  children: [
1629
- /* @__PURE__ */ jsx(
2247
+ showLabel && /* @__PURE__ */ jsx(
1630
2248
  Text,
1631
2249
  {
1632
2250
  style: {
@@ -1704,301 +2322,177 @@ function TempoDisplay({
1704
2322
  testID: "tempo-tooltip",
1705
2323
  children: [
1706
2324
  /* @__PURE__ */ jsxs(
1707
- View,
1708
- {
1709
- style: {
1710
- backgroundColor: "#191919",
1711
- borderRadius: 6,
1712
- paddingVertical: 8,
1713
- paddingHorizontal: 12,
1714
- borderWidth: 1,
1715
- borderColor: "#2C2C2C"
1716
- },
1717
- children: [
1718
- /* @__PURE__ */ jsxs(Text, { style: { fontSize: 10, lineHeight: 16, color: "#9CA3AF", fontFamily: INTER }, children: [
1719
- "Eccentric: ",
1720
- eccentric,
1721
- "s"
1722
- ] }),
1723
- /* @__PURE__ */ jsxs(Text, { style: { fontSize: 10, lineHeight: 16, color: "#9CA3AF", fontFamily: INTER }, children: [
1724
- "Pause (bottom): ",
1725
- pauseBottom,
1726
- "s"
1727
- ] }),
1728
- /* @__PURE__ */ jsxs(Text, { style: { fontSize: 10, lineHeight: 16, color: "#9CA3AF", fontFamily: INTER }, children: [
1729
- "Concentric: ",
1730
- concentric,
1731
- "s"
1732
- ] }),
1733
- /* @__PURE__ */ jsxs(Text, { style: { fontSize: 10, lineHeight: 16, color: "#9CA3AF", fontFamily: INTER }, children: [
1734
- "Pause (top): ",
1735
- pauseTop,
1736
- "s"
1737
- ] })
1738
- ]
1739
- }
1740
- ),
1741
- /* @__PURE__ */ jsx(
1742
- View,
1743
- {
1744
- style: {
1745
- width: 0,
1746
- height: 0,
1747
- borderLeftWidth: 5,
1748
- borderRightWidth: 5,
1749
- borderTopWidth: 5,
1750
- borderLeftColor: "transparent",
1751
- borderRightColor: "transparent",
1752
- borderTopColor: "#2C2C2C"
1753
- }
1754
- }
1755
- )
1756
- ]
1757
- }
1758
- )
1759
- ]
1760
- }
1761
- );
1762
- }
1763
- function formatAccessibilityLabel(setNumber, reps, weight, unit) {
1764
- const repsText = reps != null ? `${reps} reps` : "no reps";
1765
- const weightText = weight != null ? `at ${roundWeight(weight)} ${unit}` : "";
1766
- return `Set ${setNumber}: ${repsText}${weightText ? ` ${weightText}` : ""}`;
1767
- }
1768
- function SetRow({
1769
- mode,
1770
- setNumber,
1771
- previous,
1772
- reps,
1773
- weight,
1774
- rpe,
1775
- unit,
1776
- velocities,
1777
- velocityZones,
1778
- velocityLiveRepIndex,
1779
- velocityExpanded,
1780
- onVelocityToggle,
1781
- setType,
1782
- prBadges,
1783
- isNextSet,
1784
- targets
1785
- }) {
1786
- const isActive = mode === "active";
1787
- const isCompleted = mode === "completed";
1788
- const rowStyle = {
1789
- flexDirection: "row",
1790
- alignItems: "center",
1791
- padding: 7,
1792
- paddingHorizontal: 8,
1793
- gap: 8,
1794
- borderRadius: 8
1795
- };
1796
- if (isActive && isNextSet) {
1797
- rowStyle.backgroundColor = "rgba(255,121,0,0.06)";
1798
- rowStyle.borderWidth = 1;
1799
- rowStyle.borderColor = "rgba(255,121,0,0.15)";
1800
- }
1801
- if (isCompleted && !isNextSet) {
1802
- rowStyle.opacity = 0.55;
1803
- }
1804
- return /* @__PURE__ */ jsxs(
1805
- View,
1806
- {
1807
- style: rowStyle,
1808
- accessibilityLabel: formatAccessibilityLabel(
1809
- setNumber,
1810
- reps,
1811
- weight,
1812
- unit
1813
- ),
1814
- testID: "set-row",
1815
- children: [
1816
- /* @__PURE__ */ jsx(
1817
- View,
1818
- {
1819
- style: { width: 36, alignItems: "center", justifyContent: "center" },
1820
- testID: "set-row-set-number",
1821
- children: setType ? /* @__PURE__ */ jsx(
1822
- Text,
1823
- {
1824
- style: {
1825
- fontSize: 10,
1826
- fontWeight: "700",
1827
- fontFamily: "Inter, sans-serif",
1828
- color: "#ffa502",
1829
- backgroundColor: "rgba(255,165,2,0.12)",
1830
- paddingVertical: 1,
1831
- paddingHorizontal: 5,
1832
- borderRadius: 3,
1833
- overflow: "hidden"
1834
- },
1835
- testID: "set-row-type-badge",
1836
- children: setType
1837
- }
1838
- ) : /* @__PURE__ */ jsx(
1839
- Text,
1840
- {
1841
- className: "text-text-secondary",
1842
- style: {
1843
- fontSize: 13,
1844
- fontWeight: "600",
1845
- fontFamily: "Inter, sans-serif"
1846
- },
1847
- children: setNumber
1848
- }
1849
- )
1850
- }
1851
- ),
1852
- /* @__PURE__ */ jsx(
1853
- View,
1854
- {
1855
- className: "flex-1",
1856
- testID: "set-row-previous",
1857
- children: /* @__PURE__ */ jsx(
1858
- Text,
1859
- {
1860
- className: "text-text-secondary",
1861
- style: {
1862
- fontSize: 12,
1863
- fontFamily: "Inter, sans-serif"
1864
- },
1865
- children: previous ? `${previous.reps} x ${roundWeight(previous.weight)}` : "\u2014"
1866
- }
1867
- )
1868
- }
1869
- ),
1870
- /* @__PURE__ */ jsx(
1871
- View,
1872
- {
1873
- style: { width: 44, alignItems: "center", justifyContent: "center" },
1874
- testID: "set-row-reps",
1875
- children: isActive && reps == null && targets ? /* @__PURE__ */ jsx(
1876
- Text,
1877
- {
1878
- className: "text-text-tertiary",
1879
- style: {
1880
- fontSize: 13,
1881
- fontStyle: "italic",
1882
- fontFamily: "Inter, sans-serif"
1883
- },
1884
- testID: "set-row-target-reps",
1885
- children: targets.reps
1886
- }
1887
- ) : /* @__PURE__ */ jsx(
1888
- Text,
1889
- {
1890
- className: reps != null ? "text-text-primary" : "text-text-tertiary",
1891
- style: {
1892
- fontSize: 14,
1893
- fontWeight: "600",
1894
- fontFamily: "Inter, sans-serif"
1895
- },
1896
- children: reps != null ? reps : "\u2014"
1897
- }
1898
- )
1899
- }
1900
- ),
1901
- /* @__PURE__ */ jsx(
1902
- View,
1903
- {
1904
- style: { width: 56, alignItems: "center", justifyContent: "center" },
1905
- testID: "set-row-weight",
1906
- children: isActive && weight == null && targets ? /* @__PURE__ */ jsx(
1907
- Text,
1908
- {
1909
- className: "text-text-tertiary",
1910
- style: {
1911
- fontSize: 13,
1912
- fontStyle: "italic",
1913
- fontFamily: "Inter, sans-serif"
1914
- },
1915
- testID: "set-row-target-weight",
1916
- children: roundWeight(targets.weight)
1917
- }
1918
- ) : /* @__PURE__ */ jsx(
1919
- Text,
1920
- {
1921
- className: weight != null ? "text-text-primary" : "text-text-tertiary",
1922
- style: {
1923
- fontSize: 14,
1924
- fontWeight: "600",
1925
- fontFamily: "Inter, sans-serif"
1926
- },
1927
- children: weight != null ? roundWeight(weight) : "\u2014"
1928
- }
1929
- )
1930
- }
1931
- ),
1932
- /* @__PURE__ */ jsx(
1933
- View,
1934
- {
1935
- style: { width: 36, alignItems: "center", justifyContent: "center" },
1936
- testID: "set-row-rpe",
1937
- children: /* @__PURE__ */ jsx(
1938
- Text,
1939
- {
1940
- className: rpe != null ? void 0 : "text-text-tertiary",
1941
- style: {
1942
- fontSize: 13,
1943
- fontWeight: "600",
1944
- fontFamily: "Inter, sans-serif",
1945
- // rpeColor returns a concrete hex (native-safe); only the tertiary
1946
- // fallback needs the className token.
1947
- color: rpe != null ? rpeColor(rpe) : void 0
1948
- },
1949
- children: rpe != null ? roundRpe(rpe) : "\u2014"
1950
- }
1951
- )
1952
- }
1953
- ),
1954
- prBadges && prBadges.length > 0 && /* @__PURE__ */ jsx(
1955
- View,
1956
- {
1957
- className: "flex-row items-center",
1958
- style: { gap: 4 },
1959
- testID: "set-row-pr-badges",
1960
- children: prBadges.map((badge, i) => /* @__PURE__ */ jsx(
1961
- PrBadge,
1962
- {
1963
- type: badge.type,
1964
- label: badge.label,
1965
- animate: false,
1966
- compact: true
1967
- },
1968
- i
1969
- ))
1970
- }
1971
- ),
1972
- velocities && velocities.length > 0 && /* @__PURE__ */ jsx(
1973
- View,
1974
- {
1975
- style: { position: "absolute", bottom: 0, left: 8, right: 8 },
1976
- testID: "set-row-velocity-strip",
1977
- children: /* @__PURE__ */ jsx(
1978
- VelocityStrip,
1979
- {
1980
- velocities,
1981
- zones: velocityZones,
1982
- liveRepIndex: velocityLiveRepIndex,
1983
- expanded: velocityExpanded,
1984
- onToggle: onVelocityToggle,
1985
- variant: onVelocityToggle ? "full" : "mini"
1986
- }
1987
- )
2325
+ View,
2326
+ {
2327
+ style: {
2328
+ backgroundColor: "#191919",
2329
+ borderRadius: 6,
2330
+ paddingVertical: 8,
2331
+ paddingHorizontal: 12,
2332
+ borderWidth: 1,
2333
+ borderColor: "#2C2C2C"
2334
+ },
2335
+ children: [
2336
+ /* @__PURE__ */ jsxs(Text, { style: { fontSize: 10, lineHeight: 16, color: "#9CA3AF", fontFamily: INTER }, children: [
2337
+ "Eccentric: ",
2338
+ eccentric,
2339
+ "s"
2340
+ ] }),
2341
+ /* @__PURE__ */ jsxs(Text, { style: { fontSize: 10, lineHeight: 16, color: "#9CA3AF", fontFamily: INTER }, children: [
2342
+ "Pause (bottom): ",
2343
+ pauseBottom,
2344
+ "s"
2345
+ ] }),
2346
+ /* @__PURE__ */ jsxs(Text, { style: { fontSize: 10, lineHeight: 16, color: "#9CA3AF", fontFamily: INTER }, children: [
2347
+ "Concentric: ",
2348
+ concentric,
2349
+ "s"
2350
+ ] }),
2351
+ /* @__PURE__ */ jsxs(Text, { style: { fontSize: 10, lineHeight: 16, color: "#9CA3AF", fontFamily: INTER }, children: [
2352
+ "Pause (top): ",
2353
+ pauseTop,
2354
+ "s"
2355
+ ] })
2356
+ ]
2357
+ }
2358
+ ),
2359
+ /* @__PURE__ */ jsx(
2360
+ View,
2361
+ {
2362
+ style: {
2363
+ width: 0,
2364
+ height: 0,
2365
+ borderLeftWidth: 5,
2366
+ borderRightWidth: 5,
2367
+ borderTopWidth: 5,
2368
+ borderLeftColor: "transparent",
2369
+ borderRightColor: "transparent",
2370
+ borderTopColor: "#2C2C2C"
2371
+ }
2372
+ }
2373
+ )
2374
+ ]
1988
2375
  }
1989
2376
  )
1990
2377
  ]
1991
2378
  }
1992
2379
  );
1993
2380
  }
1994
- function resolveColor(token, mode = "dark") {
1995
- return Platform.OS === "web" ? `var(--color-${token})` : getSemanticColors(mode)[token];
2381
+ var t4 = getSemanticColors("dark");
2382
+ var INDICATOR_CONFIG = {
2383
+ imbalance: { Icon: ScaleIcon, color: t4["status-error"], label: "Left/right imbalance" },
2384
+ overshoot: { Icon: AlertTriangleIcon, color: t4["status-error"], label: "Load overshoot" },
2385
+ "velocity-loss": { Icon: TrendingDownIcon, color: t4["status-warning"], label: "Velocity loss" },
2386
+ "missed-reps": { Icon: CircleSlashIcon, color: t4["status-warning"], label: "Missed reps" },
2387
+ pr: { Icon: AwardIcon, color: t4["status-success"], label: "Personal record" },
2388
+ info: { Icon: InfoIcon, color: t4["status-info"], label: "More info" }
2389
+ };
2390
+ function ExerciseIndicator({ kind, onPress, className, ...props }) {
2391
+ const { Icon, color, label } = INDICATOR_CONFIG[kind];
2392
+ const chip = /* @__PURE__ */ jsx(
2393
+ View,
2394
+ {
2395
+ className,
2396
+ style: {
2397
+ width: 16,
2398
+ height: 16,
2399
+ borderRadius: 8,
2400
+ borderWidth: 1,
2401
+ borderColor: color,
2402
+ alignItems: "center",
2403
+ justifyContent: "center"
2404
+ },
2405
+ accessibilityRole: "image",
2406
+ accessibilityLabel: label,
2407
+ testID: "exercise-indicator",
2408
+ ...props,
2409
+ children: /* @__PURE__ */ jsx(Icon, { size: 11, color })
2410
+ }
2411
+ );
2412
+ if (onPress) {
2413
+ return /* @__PURE__ */ jsx(Pressable, { onPress, accessibilityRole: "button", accessibilityLabel: label, children: chip });
2414
+ }
2415
+ return chip;
1996
2416
  }
1997
2417
 
1998
- // src/components/custom/Workout/ExerciseCard.tsx
1999
- function buildColumnHeaders(unit) {
2000
- return ["SET", "PREV", "REPS", unit.toUpperCase(), "RPE"];
2418
+ // src/components/custom/Workout/ExerciseHeading.tsx
2419
+ function headingLabel(name, sets, reps, load, unit) {
2420
+ return `${name}, ${sets}\xD7${reps} @ ${roundWeight(load)} ${unit}`;
2421
+ }
2422
+ function ExerciseHeading({
2423
+ name,
2424
+ sets,
2425
+ reps,
2426
+ load,
2427
+ unit = "lbs",
2428
+ tempo,
2429
+ indicator,
2430
+ dimmed,
2431
+ onPress
2432
+ }) {
2433
+ return /* @__PURE__ */ jsxs(View, { style: { opacity: dimmed ? 0.55 : 1 }, testID: "exercise-heading", children: [
2434
+ /* @__PURE__ */ jsxs(
2435
+ Pressable,
2436
+ {
2437
+ onPress,
2438
+ accessibilityRole: "button",
2439
+ accessibilityLabel: headingLabel(name, sets, reps, load, unit),
2440
+ className: "flex-row items-center",
2441
+ style: { gap: 8 },
2442
+ testID: "exercise-card-header",
2443
+ children: [
2444
+ /* @__PURE__ */ jsx(
2445
+ Text,
2446
+ {
2447
+ className: "text-text-primary",
2448
+ style: { fontSize: 14, fontFamily: '"Space Grotesk", sans-serif', fontWeight: "700" },
2449
+ testID: "exercise-card-name",
2450
+ children: name
2451
+ }
2452
+ ),
2453
+ /* @__PURE__ */ jsx(View, { className: "flex-1" }),
2454
+ indicator && /* @__PURE__ */ jsx(ExerciseIndicator, { kind: indicator })
2455
+ ]
2456
+ }
2457
+ ),
2458
+ /* @__PURE__ */ jsxs(
2459
+ View,
2460
+ {
2461
+ className: "flex-row items-center",
2462
+ style: { gap: 8, marginTop: 1 },
2463
+ testID: "exercise-card-summary",
2464
+ children: [
2465
+ /* @__PURE__ */ jsx(SetsRepsLoad, { sets, reps, load, unit }),
2466
+ /* @__PURE__ */ jsx(View, { className: "flex-1" }),
2467
+ tempo && /* @__PURE__ */ jsx(TempoDisplay, { tempo, size: "sm", showLabel: false, showInfo: false })
2468
+ ]
2469
+ }
2470
+ )
2471
+ ] });
2472
+ }
2473
+
2474
+ // src/components/custom/Workout/ExerciseCardHeading.tsx
2475
+ function ExerciseCardHeading({
2476
+ setStates,
2477
+ stripHeight = 8,
2478
+ dimmed,
2479
+ testID = "exercise-card",
2480
+ ...heading
2481
+ }) {
2482
+ return /* @__PURE__ */ jsxs(
2483
+ View,
2484
+ {
2485
+ style: { paddingVertical: 9, paddingHorizontal: 12, opacity: dimmed ? 0.55 : 1 },
2486
+ testID,
2487
+ children: [
2488
+ /* @__PURE__ */ jsx(ExerciseHeading, { ...heading }),
2489
+ setStates.length > 0 && /* @__PURE__ */ jsx(View, { style: { marginTop: 7 }, testID: "exercise-card-strip", children: /* @__PURE__ */ jsx(SetStrip, { sets: setStates, height: stripHeight }) })
2490
+ ]
2491
+ }
2492
+ );
2001
2493
  }
2494
+
2495
+ // src/components/custom/Workout/ExerciseCard.tsx
2002
2496
  function getSupersetBorderRadius(position) {
2003
2497
  switch (position) {
2004
2498
  case "first":
@@ -2041,7 +2535,7 @@ function formatSummary(summary) {
2041
2535
  if (!summary) return "";
2042
2536
  return `${summary.sets}\xD7${summary.reps} @ ${roundWeight(summary.weight)} ${summary.unit}`;
2043
2537
  }
2044
- function formatAccessibilityLabel2(name, summary, prescription) {
2538
+ function formatAccessibilityLabel(name, summary, prescription) {
2045
2539
  if (summary) return `${name}, ${formatSummary(summary)}`;
2046
2540
  if (prescription) return `${name}, ${prescription}`;
2047
2541
  return name;
@@ -2050,7 +2544,6 @@ function CollapsedCard({
2050
2544
  name,
2051
2545
  onToggle,
2052
2546
  summary,
2053
- e1rm,
2054
2547
  isPR,
2055
2548
  setVelocities,
2056
2549
  velocityZones,
@@ -2069,7 +2562,7 @@ function CollapsedCard({
2069
2562
  onPressIn: () => setPressed(true),
2070
2563
  onPressOut: () => setPressed(false),
2071
2564
  accessibilityRole: "button",
2072
- accessibilityLabel: formatAccessibilityLabel2(name, summary, void 0),
2565
+ accessibilityLabel: formatAccessibilityLabel(name, summary, void 0),
2073
2566
  testID: "exercise-card",
2074
2567
  children: /* @__PURE__ */ jsxs(
2075
2568
  View,
@@ -2083,100 +2576,93 @@ function CollapsedCard({
2083
2576
  ...supersetMargin
2084
2577
  },
2085
2578
  children: [
2086
- /* @__PURE__ */ jsxs(
2087
- View,
2088
- {
2089
- className: "flex-row items-center",
2090
- testID: "exercise-card-header",
2091
- children: [
2092
- /* @__PURE__ */ jsx(
2093
- Text,
2094
- {
2095
- className: "text-text-primary",
2096
- style: {
2097
- fontSize: 14,
2098
- fontFamily: '"Space Grotesk", sans-serif',
2099
- fontWeight: "700"
2100
- },
2101
- testID: "exercise-card-name",
2102
- children: name
2103
- }
2104
- ),
2105
- /* @__PURE__ */ jsx(View, { className: "flex-1" }),
2106
- summary && /* @__PURE__ */ jsx(
2107
- Text,
2108
- {
2109
- className: "text-text-secondary",
2110
- style: {
2111
- fontSize: 12,
2112
- fontFamily: "Inter, sans-serif",
2113
- marginRight: 8
2114
- },
2115
- testID: "exercise-card-summary",
2116
- children: formatSummary(summary)
2117
- }
2118
- ),
2119
- e1rm && /* @__PURE__ */ jsx(
2120
- WeightBadge,
2121
- {
2122
- value: roundWeight(e1rm.value),
2123
- unit: e1rm.unit,
2124
- size: "sm",
2125
- showIcon: false,
2126
- testID: "exercise-card-e1rm"
2127
- }
2128
- ),
2129
- isPR && /* @__PURE__ */ jsx(View, { style: { marginLeft: 4 }, children: /* @__PURE__ */ jsx(PrBadge, { type: "e1rm", compact: true, animate: false }) })
2130
- ]
2131
- }
2132
- ),
2133
- (completedSets > 0 || remaining > 0) && /* @__PURE__ */ jsxs(
2134
- View,
2135
- {
2136
- className: "flex-row",
2137
- style: { marginTop: 6, gap: 4 },
2138
- testID: "exercise-card-strips",
2139
- children: [
2140
- setVelocities?.map((velocities, i) => /* @__PURE__ */ jsx(
2141
- VelocityStrip,
2142
- {
2143
- velocities,
2144
- zones: velocityZones,
2145
- variant: "mini",
2146
- testID: `exercise-card-velocity-strip-${i}`
2147
- },
2148
- i
2149
- )),
2150
- Array.from({ length: remaining }, (_, i) => /* @__PURE__ */ jsx(
2151
- PlaceholderStrip,
2152
- {
2153
- testID: `exercise-card-placeholder-${i}`
2154
- },
2155
- `placeholder-${i}`
2156
- ))
2157
- ]
2158
- }
2159
- )
2579
+ /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", testID: "exercise-card-header", children: [
2580
+ /* @__PURE__ */ jsx(
2581
+ Text,
2582
+ {
2583
+ className: "text-text-primary",
2584
+ style: {
2585
+ fontSize: 14,
2586
+ fontFamily: '"Space Grotesk", sans-serif',
2587
+ fontWeight: "700"
2588
+ },
2589
+ testID: "exercise-card-name",
2590
+ children: name
2591
+ }
2592
+ ),
2593
+ /* @__PURE__ */ jsx(View, { className: "flex-1" }),
2594
+ summary && /* @__PURE__ */ jsx(
2595
+ Text,
2596
+ {
2597
+ className: "text-text-secondary",
2598
+ style: {
2599
+ fontSize: 12,
2600
+ fontFamily: "Inter, sans-serif",
2601
+ marginRight: 8
2602
+ },
2603
+ testID: "exercise-card-summary",
2604
+ children: formatSummary(summary)
2605
+ }
2606
+ ),
2607
+ isPR && /* @__PURE__ */ jsx(View, { style: { marginLeft: 4 }, children: /* @__PURE__ */ jsx(PrBadge, { type: "e1rm", compact: true, animate: false }) })
2608
+ ] }),
2609
+ (completedSets > 0 || remaining > 0) && /* @__PURE__ */ jsxs(View, { className: "flex-row", style: { marginTop: 6, gap: 4 }, testID: "exercise-card-strips", children: [
2610
+ setVelocities?.map((velocities, i) => /* @__PURE__ */ jsx(
2611
+ VelocityStrip,
2612
+ {
2613
+ velocities,
2614
+ zones: velocityZones,
2615
+ variant: "mini",
2616
+ testID: `exercise-card-velocity-strip-${i}`
2617
+ },
2618
+ i
2619
+ )),
2620
+ Array.from({ length: remaining }, (_, i) => /* @__PURE__ */ jsx(
2621
+ PlaceholderStrip,
2622
+ {
2623
+ testID: `exercise-card-placeholder-${i}`
2624
+ },
2625
+ `placeholder-${i}`
2626
+ ))
2627
+ ] })
2160
2628
  ]
2161
2629
  }
2162
2630
  )
2163
2631
  }
2164
2632
  );
2165
2633
  }
2634
+ var DARK2 = getSemanticColors("dark");
2635
+ var BODY_DIVIDER = DARK2["border-subtle"];
2636
+ function deriveHeaderSetStates(sets) {
2637
+ return sets.map((set) => {
2638
+ switch (set.state) {
2639
+ case "live":
2640
+ return { status: "active", velocities: set.velocities, planned: set.target.reps };
2641
+ case "done":
2642
+ return { status: "done", velocities: set.velocities };
2643
+ case "todo":
2644
+ return { status: "todo", planned: set.planned ?? set.target.reps };
2645
+ }
2646
+ });
2647
+ }
2166
2648
  function ExpandedCard({
2167
2649
  name,
2168
2650
  onToggle,
2169
2651
  summary,
2170
- e1rm,
2171
2652
  isPR,
2172
2653
  sets,
2173
2654
  tempo,
2655
+ indicator,
2656
+ setStates,
2657
+ stripHeight = 8,
2658
+ velocityZones,
2174
2659
  supersetPosition
2175
2660
  }) {
2176
2661
  const borderRadius = getSupersetBorderRadius(supersetPosition);
2177
2662
  const supersetMargin = getSupersetMargin(supersetPosition);
2178
2663
  const unit = summary?.unit ?? sets?.[0]?.unit ?? "lbs";
2179
- const columnHeaders = buildColumnHeaders(unit);
2664
+ const headerStates = setStates ?? (sets ? deriveHeaderSetStates(sets) : []);
2665
+ const headerIndicator = indicator ?? (isPR ? "pr" : void 0);
2180
2666
  return /* @__PURE__ */ jsxs(
2181
2667
  View,
2182
2668
  {
@@ -2189,114 +2675,32 @@ function ExpandedCard({
2189
2675
  testID: "exercise-card",
2190
2676
  children: [
2191
2677
  /* @__PURE__ */ jsx(
2192
- Pressable,
2678
+ ExerciseCardHeading,
2193
2679
  {
2680
+ name,
2681
+ sets: summary?.sets ?? sets?.length ?? 0,
2682
+ reps: summary?.reps ?? 0,
2683
+ load: summary?.weight ?? 0,
2684
+ unit,
2685
+ tempo,
2686
+ indicator: headerIndicator,
2687
+ setStates: headerStates,
2688
+ stripHeight,
2194
2689
  onPress: onToggle,
2195
- accessibilityRole: "button",
2196
- accessibilityLabel: formatAccessibilityLabel2(name, summary, void 0),
2197
- "aria-expanded": true,
2198
- testID: "exercise-card-header",
2199
- children: /* @__PURE__ */ jsxs(
2200
- View,
2201
- {
2202
- className: "flex-row items-center",
2203
- style: {
2204
- padding: 12,
2205
- paddingHorizontal: 14,
2206
- paddingBottom: 10,
2207
- borderBottomWidth: 1,
2208
- borderBottomColor: resolveColor("border-default")
2209
- },
2210
- children: [
2211
- /* @__PURE__ */ jsx(
2212
- Text,
2213
- {
2214
- className: "text-text-primary",
2215
- style: {
2216
- fontSize: 14,
2217
- fontFamily: '"Space Grotesk", sans-serif',
2218
- fontWeight: "700"
2219
- },
2220
- testID: "exercise-card-name",
2221
- children: name
2222
- }
2223
- ),
2224
- /* @__PURE__ */ jsx(View, { className: "flex-1" }),
2225
- summary && /* @__PURE__ */ jsx(
2226
- Text,
2227
- {
2228
- className: "text-text-secondary",
2229
- style: {
2230
- fontSize: 12,
2231
- fontFamily: "Inter, sans-serif",
2232
- marginRight: 8
2233
- },
2234
- testID: "exercise-card-summary",
2235
- children: formatSummary(summary)
2236
- }
2237
- ),
2238
- e1rm && /* @__PURE__ */ jsx(
2239
- WeightBadge,
2240
- {
2241
- value: roundWeight(e1rm.value),
2242
- unit: e1rm.unit,
2243
- size: "sm",
2244
- showIcon: false,
2245
- testID: "exercise-card-e1rm"
2246
- }
2247
- ),
2248
- isPR && /* @__PURE__ */ jsx(View, { style: { marginLeft: 4 }, children: /* @__PURE__ */ jsx(PrBadge, { type: "e1rm", compact: true, animate: false }) })
2249
- ]
2250
- }
2251
- )
2690
+ testID: "exercise-card-heading"
2252
2691
  }
2253
2692
  ),
2254
- tempo && /* @__PURE__ */ jsx(View, { style: { marginTop: 8, paddingHorizontal: 14 }, testID: "exercise-card-tempo", children: /* @__PURE__ */ jsx(TempoDisplay, { tempo, size: "sm" }) }),
2255
- /* @__PURE__ */ jsx(
2693
+ /* @__PURE__ */ jsxs(
2256
2694
  View,
2257
2695
  {
2258
- className: "flex-row",
2259
- style: {
2260
- paddingVertical: 8,
2261
- paddingHorizontal: 8,
2262
- paddingBottom: 4
2263
- },
2264
- testID: "exercise-card-column-headers",
2265
- children: columnHeaders.map((header, i) => {
2266
- const widths = [36, void 0, 44, 56, 36];
2267
- const width = widths[i];
2268
- const isFlex = width === void 0;
2269
- return /* @__PURE__ */ jsx(
2270
- View,
2271
- {
2272
- style: {
2273
- ...isFlex ? {} : { width },
2274
- alignItems: "center",
2275
- justifyContent: "center",
2276
- gap: 8
2277
- },
2278
- ...isFlex ? { className: "flex-1" } : {},
2279
- children: /* @__PURE__ */ jsx(
2280
- Text,
2281
- {
2282
- className: "text-text-tertiary",
2283
- style: {
2284
- fontSize: 10,
2285
- fontWeight: "600",
2286
- fontFamily: "Inter, sans-serif",
2287
- textTransform: "uppercase",
2288
- letterSpacing: 0.8
2289
- },
2290
- children: header
2291
- }
2292
- )
2293
- },
2294
- header
2295
- );
2296
- })
2696
+ style: { borderTopWidth: 1, borderTopColor: BODY_DIVIDER, paddingBottom: 6 },
2697
+ testID: "exercise-card-body",
2698
+ children: [
2699
+ /* @__PURE__ */ jsx(SetTableHeader, { unit, showPrevious: false, testID: "exercise-card-column-headers" }),
2700
+ sets && /* @__PURE__ */ jsx(View, { testID: "exercise-card-sets", children: sets.map((set, i) => /* @__PURE__ */ jsx(SetRow, { ...set, velocityZones: set.velocityZones ?? velocityZones }, i)) })
2701
+ ]
2297
2702
  }
2298
- ),
2299
- sets && /* @__PURE__ */ jsx(View, { testID: "exercise-card-sets", children: sets.map((setProps, i) => /* @__PURE__ */ jsx(SetRow, { ...setProps }, i)) })
2703
+ )
2300
2704
  ]
2301
2705
  }
2302
2706
  );
@@ -2305,11 +2709,12 @@ function UpcomingCard({
2305
2709
  name,
2306
2710
  prescription,
2307
2711
  previousBest,
2308
- supersetPosition
2712
+ supersetPosition,
2713
+ onToggle
2309
2714
  }) {
2310
2715
  const borderRadius = getSupersetBorderRadius(supersetPosition);
2311
2716
  const supersetMargin = getSupersetMargin(supersetPosition);
2312
- return /* @__PURE__ */ jsx(
2717
+ return /* @__PURE__ */ jsx(Pressable, { onPress: onToggle, accessibilityRole: "button", children: /* @__PURE__ */ jsx(
2313
2718
  View,
2314
2719
  {
2315
2720
  style: {
@@ -2319,7 +2724,7 @@ function UpcomingCard({
2319
2724
  ...borderRadius,
2320
2725
  ...supersetMargin
2321
2726
  },
2322
- accessibilityLabel: formatAccessibilityLabel2(name, void 0, prescription),
2727
+ accessibilityLabel: formatAccessibilityLabel(name, void 0, prescription),
2323
2728
  testID: "exercise-card",
2324
2729
  children: /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", children: [
2325
2730
  /* @__PURE__ */ jsx(
@@ -2327,6 +2732,7 @@ function UpcomingCard({
2327
2732
  {
2328
2733
  className: "text-text-primary",
2329
2734
  style: {
2735
+ flexShrink: 0,
2330
2736
  fontSize: 14,
2331
2737
  fontFamily: '"Space Grotesk", sans-serif',
2332
2738
  fontWeight: "700"
@@ -2339,7 +2745,9 @@ function UpcomingCard({
2339
2745
  Text,
2340
2746
  {
2341
2747
  className: "text-text-secondary",
2748
+ numberOfLines: 1,
2342
2749
  style: {
2750
+ flexShrink: 1,
2343
2751
  fontSize: 12,
2344
2752
  fontFamily: "Inter, sans-serif",
2345
2753
  marginLeft: 8
@@ -2348,12 +2756,14 @@ function UpcomingCard({
2348
2756
  children: prescription
2349
2757
  }
2350
2758
  ),
2351
- /* @__PURE__ */ jsx(View, { className: "flex-1" }),
2759
+ /* @__PURE__ */ jsx(View, { className: "flex-1", style: { minWidth: 8 } }),
2352
2760
  previousBest && /* @__PURE__ */ jsx(
2353
2761
  Text,
2354
2762
  {
2355
2763
  className: "text-text-tertiary",
2764
+ numberOfLines: 1,
2356
2765
  style: {
2766
+ flexShrink: 1,
2357
2767
  fontSize: 11,
2358
2768
  fontFamily: "Inter, sans-serif"
2359
2769
  },
@@ -2363,19 +2773,32 @@ function UpcomingCard({
2363
2773
  )
2364
2774
  ] })
2365
2775
  }
2366
- );
2776
+ ) });
2367
2777
  }
2368
- function ExerciseCard(props) {
2369
- switch (props.state) {
2370
- case "collapsed":
2371
- return /* @__PURE__ */ jsx(CollapsedCard, { ...props });
2372
- case "expanded":
2373
- return /* @__PURE__ */ jsx(ExpandedCard, { ...props });
2374
- case "upcoming":
2375
- return /* @__PURE__ */ jsx(UpcomingCard, { ...props });
2376
- }
2778
+ function ExerciseCard({
2779
+ upcoming,
2780
+ expanded,
2781
+ defaultExpanded,
2782
+ onExpandedChange,
2783
+ ...rest
2784
+ }) {
2785
+ const [internalExpanded, setInternalExpanded] = useState(defaultExpanded ?? false);
2786
+ const isControlled = expanded !== void 0;
2787
+ const isExpanded = isControlled ? expanded : internalExpanded;
2788
+ const onToggle = () => {
2789
+ const next = !isExpanded;
2790
+ onExpandedChange?.(next);
2791
+ if (!isControlled) setInternalExpanded(next);
2792
+ };
2793
+ if (upcoming) return /* @__PURE__ */ jsx(UpcomingCard, { ...rest, onToggle });
2794
+ return isExpanded ? /* @__PURE__ */ jsx(ExpandedCard, { ...rest, onToggle }) : /* @__PURE__ */ jsx(CollapsedCard, { ...rest, onToggle });
2377
2795
  }
2378
- var BRAND_PRIMARY = "#FF7900";
2796
+ function resolveColor(token, mode = "dark") {
2797
+ return Platform.OS === "web" ? `var(--color-${token})` : getSemanticColors(mode)[token];
2798
+ }
2799
+
2800
+ // src/components/custom/Workout/InputBar.tsx
2801
+ var BRAND_PRIMARY2 = getSemanticColors("dark")["brand-primary"];
2379
2802
  var INPUT_CLASSNAME = "bg-surface-raised border-border-strong text-text-primary";
2380
2803
  var inputStyle = {
2381
2804
  fontSize: 14,
@@ -2504,7 +2927,7 @@ function InputBar({
2504
2927
  onPress: onRecord,
2505
2928
  disabled: !canRecord,
2506
2929
  style: ({ pressed }) => ({
2507
- backgroundColor: BRAND_PRIMARY,
2930
+ backgroundColor: BRAND_PRIMARY2,
2508
2931
  borderRadius: 8,
2509
2932
  paddingVertical: 10,
2510
2933
  paddingHorizontal: 16,
@@ -2531,7 +2954,46 @@ function InputBar({
2531
2954
  }
2532
2955
  );
2533
2956
  }
2534
- var BRAND_PRIMARY2 = "#FF7900";
2957
+ function formatDuration(ms) {
2958
+ const totalSeconds = Math.max(0, Math.ceil(ms / 1e3));
2959
+ const minutes = Math.floor(totalSeconds / 60);
2960
+ const seconds = totalSeconds % 60;
2961
+ return `${minutes}:${String(seconds).padStart(2, "0")}`;
2962
+ }
2963
+ function useTimer(options = {}) {
2964
+ const {
2965
+ mode = "up",
2966
+ durationMs,
2967
+ elapsedMs: controlledElapsedMs,
2968
+ running = false,
2969
+ autoTick = false,
2970
+ tickMs = 1e3
2971
+ } = options;
2972
+ const isControlled = controlledElapsedMs != null;
2973
+ const [internalElapsedMs, setInternalElapsedMs] = useState(0);
2974
+ useEffect(() => {
2975
+ if (isControlled || !autoTick || !running) return;
2976
+ const id = setInterval(() => {
2977
+ setInternalElapsedMs((prev) => prev + tickMs);
2978
+ }, tickMs);
2979
+ return () => clearInterval(id);
2980
+ }, [isControlled, autoTick, running, tickMs]);
2981
+ const elapsedMs = isControlled ? controlledElapsedMs : internalElapsedMs;
2982
+ const hasDuration = durationMs != null && durationMs > 0;
2983
+ const remainingMs = durationMs != null ? Math.max(0, durationMs - elapsedMs) : 0;
2984
+ let progress;
2985
+ if (hasDuration) {
2986
+ progress = Math.min(1, Math.max(0, elapsedMs / durationMs));
2987
+ } else {
2988
+ progress = mode === "down" ? 1 : 0;
2989
+ }
2990
+ const label = formatDuration(mode === "down" ? remainingMs : elapsedMs);
2991
+ const done = durationMs != null && elapsedMs >= durationMs;
2992
+ return { elapsedMs, remainingMs, progress, label, done };
2993
+ }
2994
+
2995
+ // src/components/custom/Workout/RestTimer.tsx
2996
+ var BRAND_PRIMARY3 = getSemanticColors("dark")["brand-primary"];
2535
2997
  function RestTimer({
2536
2998
  totalSeconds,
2537
2999
  elapsedMs,
@@ -2541,14 +3003,18 @@ function RestTimer({
2541
3003
  visible,
2542
3004
  displayOnly = false
2543
3005
  }) {
2544
- if (!visible) return null;
2545
- const remainingMs = Math.max(0, totalSeconds * 1e3 - elapsedMs);
3006
+ const {
3007
+ remainingMs,
3008
+ progress,
3009
+ label: timeDisplay
3010
+ } = useTimer({
3011
+ mode: "down",
3012
+ durationMs: totalSeconds * 1e3,
3013
+ elapsedMs
3014
+ });
2546
3015
  const remainingSec = Math.ceil(remainingMs / 1e3);
2547
- const minutes = Math.floor(remainingSec / 60);
2548
- const seconds = remainingSec % 60;
2549
- const timeDisplay = `${minutes}:${String(seconds).padStart(2, "0")}`;
2550
- const totalMs = totalSeconds * 1e3;
2551
- const progressPct = totalMs > 0 ? Math.min(100, elapsedMs / totalMs * 100) : 100;
3016
+ const progressPct = progress * 100;
3017
+ if (!visible) return null;
2552
3018
  return /* @__PURE__ */ jsxs(
2553
3019
  View,
2554
3020
  {
@@ -2637,7 +3103,7 @@ function RestTimer({
2637
3103
  {
2638
3104
  style: {
2639
3105
  height: "100%",
2640
- backgroundColor: BRAND_PRIMARY2,
3106
+ backgroundColor: BRAND_PRIMARY3,
2641
3107
  borderRadius: 2,
2642
3108
  width: `${progressPct}%`
2643
3109
  },
@@ -2694,7 +3160,7 @@ function RestTimer({
2694
3160
  fontSize: 11,
2695
3161
  fontFamily: "Inter, sans-serif",
2696
3162
  fontWeight: "600",
2697
- color: BRAND_PRIMARY2
3163
+ color: BRAND_PRIMARY3
2698
3164
  },
2699
3165
  children: "Skip"
2700
3166
  }
@@ -2708,7 +3174,7 @@ function RestTimer({
2708
3174
  }
2709
3175
  var DEFAULTS = {
2710
3176
  label: "SS",
2711
- color: "#FF7900",
3177
+ color: getSemanticColors("dark")["brand-primary"],
2712
3178
  bgBase: "#101010"
2713
3179
  };
2714
3180
  function SupersetWrapper({
@@ -2761,7 +3227,7 @@ function SupersetWrapper({
2761
3227
  }
2762
3228
 
2763
3229
  // src/components/custom/Workout/ActiveWorkoutPage.tsx
2764
- var BRAND_PRIMARY3 = "#FF7900";
3230
+ var BRAND_PRIMARY4 = getSemanticColors("dark")["brand-primary"];
2765
3231
  function countCompletedSets(exercise) {
2766
3232
  if (exercise.setVelocities != null) return exercise.setVelocities.length;
2767
3233
  if (exercise.status === "completed") return exercise.totalPlannedSets;
@@ -2787,23 +3253,22 @@ function deriveWorkoutProgress(exercises) {
2787
3253
  function findActiveExercise(exercises) {
2788
3254
  return exercises.find((exercise) => exercise.status === "active") ?? null;
2789
3255
  }
2790
- function statusToCardState(status, focused) {
2791
- if (status === "upcoming") return "upcoming";
2792
- return focused ? "expanded" : "collapsed";
3256
+ function isUpcomingExercise(status) {
3257
+ return status === "upcoming";
2793
3258
  }
2794
3259
  function toActiveCardProps(exercise, focused, onToggle, supersetPosition = null, supersetColor) {
2795
- const state = statusToCardState(exercise.status, focused);
3260
+ const upcoming = isUpcomingExercise(exercise.status);
2796
3261
  return {
2797
3262
  name: exercise.name,
2798
- state,
2799
- onToggle,
3263
+ upcoming,
3264
+ expanded: focused,
3265
+ onExpandedChange: onToggle,
2800
3266
  summary: exercise.summary,
2801
- e1rm: exercise.e1rm,
2802
3267
  isPR: exercise.isPR,
2803
3268
  tempo: exercise.tempo,
2804
3269
  setVelocities: exercise.setVelocities,
2805
3270
  totalPlannedSets: exercise.totalPlannedSets,
2806
- sets: state === "expanded" ? exercise.sets : void 0,
3271
+ sets: focused ? exercise.sets : void 0,
2807
3272
  prescription: exercise.prescription,
2808
3273
  previousBest: exercise.previousBest,
2809
3274
  supersetPosition,
@@ -2876,7 +3341,7 @@ function WorkoutHeader({
2876
3341
  fontSize: 15,
2877
3342
  fontFamily: '"Space Grotesk", sans-serif',
2878
3343
  fontWeight: "700",
2879
- color: BRAND_PRIMARY3,
3344
+ color: BRAND_PRIMARY4,
2880
3345
  fontVariant: ["tabular-nums"]
2881
3346
  },
2882
3347
  children: `${progress.completedExercises}/${progress.totalExercises}`
@@ -2910,7 +3375,7 @@ function WorkoutHeader({
2910
3375
  style: {
2911
3376
  height: "100%",
2912
3377
  width: `${Math.round(progress.fraction * 100)}%`,
2913
- backgroundColor: BRAND_PRIMARY3,
3378
+ backgroundColor: BRAND_PRIMARY4,
2914
3379
  borderRadius: 2
2915
3380
  },
2916
3381
  testID: "active-workout-page-progress-fill"
@@ -3492,17 +3957,18 @@ function CardContent({ children, className }) {
3492
3957
  function CardFooter({ children, className }) {
3493
3958
  return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4 flex-row items-center gap-2", className), children });
3494
3959
  }
3960
+ var t5 = getSemanticColors("dark");
3495
3961
  var solidVariantColors = {
3496
- success: "#14B8A6",
3497
- warning: "#FFB020",
3498
- error: "#D14343",
3962
+ success: t5["status-success"],
3963
+ warning: t5["status-warning"],
3964
+ error: t5["status-error"],
3499
3965
  neutral: "#6B7280"
3500
3966
  };
3501
3967
  var ringVariantStyles = {
3502
3968
  "on-track": {
3503
- backgroundColor: "rgba(20,184,166,0.15)",
3969
+ backgroundColor: "rgba(46,213,115,0.15)",
3504
3970
  borderWidth: 1,
3505
- borderColor: "rgba(20,184,166,0.3)"
3971
+ borderColor: "rgba(46,213,115,0.3)"
3506
3972
  },
3507
3973
  deviation: {
3508
3974
  backgroundColor: "rgba(245,158,11,0.15)",
@@ -3517,11 +3983,11 @@ var ringVariantStyles = {
3517
3983
  }
3518
3984
  };
3519
3985
  var glowStyles = {
3520
- success: { boxShadow: "0 0 4px rgba(20,184,166,0.4)" },
3986
+ success: { boxShadow: "0 0 4px rgba(46,213,115,0.4)" },
3521
3987
  warning: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
3522
3988
  error: { boxShadow: "0 0 4px rgba(239,68,68,0.4)" },
3523
3989
  neutral: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" },
3524
- "on-track": { boxShadow: "0 0 4px rgba(20,184,166,0.4)" },
3990
+ "on-track": { boxShadow: "0 0 4px rgba(46,213,115,0.4)" },
3525
3991
  deviation: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
3526
3992
  future: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" }
3527
3993
  };
@@ -3535,8 +4001,8 @@ var iconColors = {
3535
4001
  warning: "#6B4000",
3536
4002
  error: "#5C1A1A",
3537
4003
  neutral: "#D1D5DB",
3538
- "on-track": "#14B8A6",
3539
- deviation: "#FFB020",
4004
+ "on-track": t5["status-success"],
4005
+ deviation: t5["status-warning"],
3540
4006
  future: "#6B7280"
3541
4007
  };
3542
4008
  var sizeDimensions = {
@@ -3617,20 +4083,24 @@ function StatusDot({
3617
4083
  }
3618
4084
  return /* @__PURE__ */ jsx(View, { className, ...props, children: dot });
3619
4085
  }
4086
+ var MESO_ACCENT_GRADIENT_DARK = primitiveRamps.orange[500];
4087
+ var MESO_ACCENT_GRADIENT_LIGHT = primitiveRamps.orange[300];
4088
+ var WORKOUT_PILL_DELOAD = primitiveRamps.magenta[600];
3620
4089
 
3621
4090
  // src/components/custom/Workout/MesoStatusCard.tsx
3622
- var BRAND_PRIMARY4 = "#FF7900";
3623
- var BRAND_PRIMARY_DARK = "#C45E00";
3624
- var BRAND_PRIMARY_LIGHT = "#FFB066";
3625
- var SUCCESS = "#14B8A6";
3626
- var WARNING = "#FFB020";
3627
- var ERROR = "#D14343";
3628
- var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY4, BRAND_PRIMARY_LIGHT];
4091
+ var t6 = getSemanticColors("dark");
4092
+ var BRAND_PRIMARY5 = t6["brand-primary"];
4093
+ var BRAND_PRIMARY_DARK = MESO_ACCENT_GRADIENT_DARK;
4094
+ var BRAND_PRIMARY_LIGHT = MESO_ACCENT_GRADIENT_LIGHT;
4095
+ var SUCCESS = t6["status-success"];
4096
+ var WARNING = t6["status-warning"];
4097
+ var ERROR = t6["status-error"];
4098
+ var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY5, BRAND_PRIMARY_LIGHT];
3629
4099
  var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
3630
- 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%)";
4100
+ var GAUGE_GRADIENT = "linear-gradient(90deg, rgba(46,213,115,0.25) 0%, rgba(249,180,21,0.25) 50%, rgba(209,67,67,0.25) 100%)";
3631
4101
  var STATUS_VARIANTS = {
3632
- success: { bg: "rgba(20,184,166,0.15)", border: "rgba(20,184,166,0.3)", text: SUCCESS },
3633
- warning: { bg: "rgba(255,176,32,0.15)", border: "rgba(255,176,32,0.3)", text: WARNING },
4102
+ success: { bg: "rgba(46,213,115,0.15)", border: "rgba(46,213,115,0.3)", text: SUCCESS },
4103
+ warning: { bg: "rgba(249,180,21,0.15)", border: "rgba(249,180,21,0.3)", text: WARNING },
3634
4104
  error: { bg: "rgba(209,67,67,0.15)", border: "rgba(209,67,67,0.25)", text: ERROR }
3635
4105
  };
3636
4106
  function clamp01(value) {
@@ -3696,7 +4166,7 @@ function StatusPill({ badge }) {
3696
4166
  }
3697
4167
  );
3698
4168
  }
3699
- function MetricCell({ metric }) {
4169
+ function MetricCell2({ metric }) {
3700
4170
  return /* @__PURE__ */ jsxs(View, { style: { width: "48%" }, testID: "meso-status-card-metric", children: [
3701
4171
  /* @__PURE__ */ jsx(
3702
4172
  Text,
@@ -3914,7 +4384,7 @@ function MesoStatusCard({
3914
4384
  className: "flex-row flex-wrap",
3915
4385
  style: { gap: 8 },
3916
4386
  testID: "meso-status-card-metrics",
3917
- children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell, { metric }, `${metric.label}-${index}`))
4387
+ children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell2, { metric }, `${metric.label}-${index}`))
3918
4388
  }
3919
4389
  ),
3920
4390
  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}`)) }),
@@ -3922,9 +4392,9 @@ function MesoStatusCard({
3922
4392
  View,
3923
4393
  {
3924
4394
  style: {
3925
- backgroundColor: "rgba(255,176,32,0.06)",
4395
+ backgroundColor: "rgba(249,180,21,0.06)",
3926
4396
  borderWidth: 1,
3927
- borderColor: "rgba(255,176,32,0.15)",
4397
+ borderColor: "rgba(249,180,21,0.15)",
3928
4398
  borderRadius: 8,
3929
4399
  paddingVertical: 10,
3930
4400
  paddingHorizontal: 12
@@ -3950,9 +4420,9 @@ function MesoStatusCard({
3950
4420
  className: "flex-row items-center",
3951
4421
  style: {
3952
4422
  gap: 8,
3953
- backgroundColor: "rgba(20,184,166,0.06)",
4423
+ backgroundColor: "rgba(46,213,115,0.06)",
3954
4424
  borderWidth: 1,
3955
- borderColor: "rgba(20,184,166,0.2)",
4425
+ borderColor: "rgba(46,213,115,0.2)",
3956
4426
  borderRadius: 8,
3957
4427
  paddingVertical: 10,
3958
4428
  paddingHorizontal: 12
@@ -3981,21 +4451,22 @@ function MesoStatusCard({
3981
4451
  }
3982
4452
  );
3983
4453
  }
3984
- var BRAND_PRIMARY5 = "#FF7900";
4454
+ var sem = getSemanticColors("dark");
4455
+ var BRAND_PRIMARY6 = sem["brand-primary"];
3985
4456
  var PROJECTION_LINE_COLOR = resolveColor("text-tertiary");
3986
- var STATUS_SUCCESS = "#14B8A6";
3987
- var STATUS_ERROR2 = "#D14343";
3988
- var STATUS_WARNING = "#FFB020";
4457
+ var STATUS_SUCCESS = sem["status-success"];
4458
+ var STATUS_ERROR2 = sem["status-error"];
4459
+ var STATUS_WARNING = sem["status-warning"];
3989
4460
  var GRID_LINE = "rgba(255,255,255,0.06)";
3990
- var SUCCESS_PILL_BG = "rgba(20,184,166,0.10)";
3991
- var SUCCESS_PILL_BORDER = "rgba(20,184,166,0.20)";
4461
+ var SUCCESS_PILL_BG = "rgba(46,213,115,0.10)";
4462
+ var SUCCESS_PILL_BORDER = "rgba(46,213,115,0.20)";
3992
4463
  var ERROR_PILL_BG = "rgba(209,67,67,0.10)";
3993
4464
  var ERROR_PILL_BORDER = "rgba(209,67,67,0.20)";
3994
4465
  var PLOT_LEFT = 26;
3995
4466
  var TOOLTIP_WIDTH = 124;
3996
4467
  function timeOf(dateStr) {
3997
- const t2 = Date.parse(dateStr);
3998
- return Number.isNaN(t2) ? 0 : t2;
4468
+ const t12 = Date.parse(dateStr);
4469
+ return Number.isNaN(t12) ? 0 : t12;
3999
4470
  }
4000
4471
  function formatValue(value) {
4001
4472
  return `${Math.round(value)}`;
@@ -4272,7 +4743,7 @@ function StrengthTrendChart({
4272
4743
  ChartLine,
4273
4744
  {
4274
4745
  coords: geometry.actual,
4275
- color: BRAND_PRIMARY5,
4746
+ color: BRAND_PRIMARY6,
4276
4747
  strokeWidth: 2.5,
4277
4748
  testID: "strength-trend-chart-actual-segment"
4278
4749
  }
@@ -4325,7 +4796,7 @@ function StrengthTrendChart({
4325
4796
  width: 8,
4326
4797
  height: 8,
4327
4798
  borderRadius: 1,
4328
- backgroundColor: BRAND_PRIMARY5
4799
+ backgroundColor: BRAND_PRIMARY6
4329
4800
  }
4330
4801
  },
4331
4802
  `point-${c.index}`
@@ -4455,7 +4926,7 @@ function StrengthTrendChart({
4455
4926
  testID: "strength-trend-chart-legend",
4456
4927
  children: [
4457
4928
  /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { gap: 5 }, children: [
4458
- /* @__PURE__ */ jsx(View, { style: { width: 14, height: 2.5, borderRadius: 1.5, backgroundColor: BRAND_PRIMARY5 } }),
4929
+ /* @__PURE__ */ jsx(View, { style: { width: 14, height: 2.5, borderRadius: 1.5, backgroundColor: BRAND_PRIMARY6 } }),
4459
4930
  /* @__PURE__ */ jsx(Text, { className: "text-text-secondary", style: { fontSize: 10, fontFamily: "Inter, sans-serif" }, children: "Actual" })
4460
4931
  ] }),
4461
4932
  /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { gap: 5 }, children: [
@@ -4484,13 +4955,14 @@ function StrengthTrendChart({
4484
4955
  }
4485
4956
  );
4486
4957
  }
4487
- var STATUS_SUCCESS2 = "#14B8A6";
4488
- var STATUS_WARNING2 = "#FFB020";
4489
- var STATUS_INFO = "#2196F3";
4958
+ var t7 = getSemanticColors("dark");
4959
+ var STATUS_SUCCESS2 = t7["status-success"];
4960
+ var STATUS_WARNING2 = t7["status-warning"];
4961
+ var STATUS_INFO = t7["status-info"];
4490
4962
  var DOT_BORDER = "#F3F4F6";
4491
- var BAND_FILL = "rgba(20,184,166,0.1)";
4492
- var BAND_EDGE = "rgba(20,184,166,0.45)";
4493
- var PROJECTION_FILL = "rgba(20,184,166,0.05)";
4963
+ var BAND_FILL = "rgba(46,213,115,0.1)";
4964
+ var BAND_EDGE = "rgba(46,213,115,0.45)";
4965
+ var PROJECTION_FILL = "rgba(46,213,115,0.05)";
4494
4966
  var PADDING_LEFT = 28;
4495
4967
  var PADDING_RIGHT = 10;
4496
4968
  var PADDING_TOP = 8;
@@ -4529,13 +5001,13 @@ function interpEdge(pixels, x, key) {
4529
5001
  const a = pixels[i];
4530
5002
  const b = pixels[i + 1];
4531
5003
  if (x >= a.x && x <= b.x) {
4532
- const t2 = b.x === a.x ? 0 : (x - a.x) / (b.x - a.x);
4533
- return a[key] + t2 * (b[key] - a[key]);
5004
+ const t12 = b.x === a.x ? 0 : (x - a.x) / (b.x - a.x);
5005
+ return a[key] + t12 * (b[key] - a[key]);
4534
5006
  }
4535
5007
  }
4536
5008
  return pixels[pixels.length - 1][key];
4537
5009
  }
4538
- function buildColumns(pixels, step) {
5010
+ function buildColumns2(pixels, step) {
4539
5011
  if (pixels.length < 2) return [];
4540
5012
  const start = pixels[0].x;
4541
5013
  const end = pixels[pixels.length - 1].x;
@@ -4647,7 +5119,7 @@ function CapacityBandChart({
4647
5119
  }
4648
5120
  const { toX, toY } = scale;
4649
5121
  const bandPixels = toPixels(band, toX, toY);
4650
- const columns = buildColumns(bandPixels, COLUMN_STEP);
5122
+ const columns = buildColumns2(bandPixels, COLUMN_STEP);
4651
5123
  const topEdge = buildEdges(bandPixels, "yHigh");
4652
5124
  const bottomEdge = buildEdges(bandPixels, "yLow");
4653
5125
  const lastBandPoint = band[band.length - 1];
@@ -4722,8 +5194,8 @@ function CapacityBandChart({
4722
5194
  testID: "capacity-band-chart-reveal",
4723
5195
  children: /* @__PURE__ */ jsxs(View, { style: { width, height, position: "relative" }, children: [
4724
5196
  projection && /* @__PURE__ */ jsxs(View, { testID: "capacity-band-chart-projection", children: [
4725
- renderColumns(buildColumns(trainingPixels, COLUMN_STEP), PROJECTION_FILL, "capacity-band-chart-projection-fill"),
4726
- renderColumns(buildColumns(restPixels, COLUMN_STEP), PROJECTION_FILL, "capacity-band-chart-projection-fill"),
5197
+ renderColumns(buildColumns2(trainingPixels, COLUMN_STEP), PROJECTION_FILL, "capacity-band-chart-projection-fill"),
5198
+ renderColumns(buildColumns2(restPixels, COLUMN_STEP), PROJECTION_FILL, "capacity-band-chart-projection-fill"),
4727
5199
  renderEdges(buildEdges(trainingPixels, "yHigh"), STATUS_SUCCESS2, true, "capacity-band-chart-projection-training"),
4728
5200
  renderEdges(buildEdges(trainingPixels, "yLow"), STATUS_SUCCESS2, true, "capacity-band-chart-projection-training"),
4729
5201
  renderEdges(buildEdges(restPixels, "yHigh"), STATUS_INFO, true, "capacity-band-chart-projection-rest"),
@@ -4862,7 +5334,7 @@ function CapacityBandChart({
4862
5334
  }
4863
5335
 
4864
5336
  // src/components/custom/Workout/ExerciseDetailPage.tsx
4865
- var BRAND_PRIMARY6 = "#FF7900";
5337
+ var BRAND_PRIMARY7 = getSemanticColors("dark")["brand-primary"];
4866
5338
  var CHART_WIDTH = 326;
4867
5339
  var CHART_HEIGHT = 150;
4868
5340
  var EXERCISE_DETAIL_TABS = [
@@ -4884,10 +5356,9 @@ function deriveExerciseStats(entries) {
4884
5356
  function toExerciseCardProps(entry, expanded, onToggle) {
4885
5357
  return {
4886
5358
  name: entry.title,
4887
- state: expanded ? "expanded" : "collapsed",
4888
- onToggle,
5359
+ expanded,
5360
+ onExpandedChange: onToggle,
4889
5361
  summary: entry.summary,
4890
- e1rm: entry.e1rm,
4891
5362
  isPR: entry.isPR,
4892
5363
  tempo: entry.tempo,
4893
5364
  sets: expanded ? entry.sets : void 0
@@ -4926,7 +5397,7 @@ function TabBar({ active, onSelect }) {
4926
5397
  alignItems: "center",
4927
5398
  paddingVertical: 10,
4928
5399
  borderBottomWidth: 2,
4929
- borderBottomColor: isActive ? BRAND_PRIMARY6 : "transparent"
5400
+ borderBottomColor: isActive ? BRAND_PRIMARY7 : "transparent"
4930
5401
  },
4931
5402
  testID: `exercise-detail-page-tab-${key}`,
4932
5403
  children: /* @__PURE__ */ jsx(
@@ -5248,7 +5719,7 @@ function ExerciseDetailPage({
5248
5719
  fontSize: 15,
5249
5720
  fontFamily: '"Space Grotesk", sans-serif',
5250
5721
  fontWeight: "700",
5251
- color: BRAND_PRIMARY6
5722
+ color: BRAND_PRIMARY7
5252
5723
  },
5253
5724
  children: `${exercise.currentE1rm} ${exercise.unit}`
5254
5725
  }
@@ -5314,9 +5785,9 @@ function ExerciseDetailPage({
5314
5785
  }
5315
5786
  );
5316
5787
  }
5317
- var BRAND_PRIMARY7 = "#FF7900";
5788
+ var BRAND_PRIMARY8 = getSemanticColors("dark")["brand-primary"];
5318
5789
  var segmentBgColors = {
5319
- completed: "rgba(20,184,166,0.3)",
5790
+ completed: "rgba(46,213,115,0.3)",
5320
5791
  current: "rgba(255,121,0,0.5)",
5321
5792
  upcoming: "rgba(255,255,255,0.06)"
5322
5793
  };
@@ -5366,7 +5837,7 @@ function MesoSegment({ meso, isActive, onPress }) {
5366
5837
  },
5367
5838
  isActive ? {
5368
5839
  borderWidth: 2,
5369
- borderColor: BRAND_PRIMARY7,
5840
+ borderColor: BRAND_PRIMARY8,
5370
5841
  transform: [{ scale: 1.02 }, { scale: pressScale }]
5371
5842
  } : void 0
5372
5843
  ],
@@ -5380,7 +5851,7 @@ function MesoSegment({ meso, isActive, onPress }) {
5380
5851
  top: 0,
5381
5852
  bottom: 0,
5382
5853
  width: `${progress * 100}%`,
5383
- backgroundColor: BRAND_PRIMARY7
5854
+ backgroundColor: BRAND_PRIMARY8
5384
5855
  },
5385
5856
  testID: `meso-segment-fill-${meso.id}`
5386
5857
  }
@@ -5431,9 +5902,11 @@ var colorStyles = {
5431
5902
  default: "bg-text-tertiary",
5432
5903
  primary: "bg-brand-primary",
5433
5904
  success: "bg-status-success",
5905
+ live: "bg-status-live",
5434
5906
  error: "bg-status-error",
5435
5907
  warning: "bg-status-warning",
5436
- info: "bg-status-info"
5908
+ info: "bg-status-info",
5909
+ "error-vivid": "bg-status-error-vivid"
5437
5910
  };
5438
5911
  function Indicator({
5439
5912
  size = "sm",
@@ -5441,14 +5914,40 @@ function Indicator({
5441
5914
  customColor,
5442
5915
  glow = false,
5443
5916
  ring = false,
5917
+ pulse = false,
5444
5918
  className,
5445
5919
  style,
5446
5920
  ...props
5447
5921
  }) {
5922
+ const pulseMode = pulse === true ? "opacity" : pulse || false;
5923
+ const colorClass = !customColor ? colorStyles[color] : void 0;
5924
+ const colorStyle = customColor ? { backgroundColor: customColor } : void 0;
5925
+ if (pulseMode === "ping") {
5926
+ return /* @__PURE__ */ jsxs(View, { className: cn("relative", sizeStyles[size], className), style, ...props, children: [
5927
+ /* @__PURE__ */ jsx(
5928
+ View,
5929
+ {
5930
+ className: cn("absolute inset-0 rounded-full animate-ping", colorClass),
5931
+ style: colorStyle
5932
+ }
5933
+ ),
5934
+ /* @__PURE__ */ jsx(
5935
+ View,
5936
+ {
5937
+ className: cn(
5938
+ "relative rounded-full",
5939
+ sizeStyles[size],
5940
+ colorClass,
5941
+ ring && "border-2 border-background-base"
5942
+ ),
5943
+ style: colorStyle
5944
+ }
5945
+ )
5946
+ ] });
5947
+ }
5448
5948
  const dynamicStyle = {
5449
5949
  ...typeof style === "object" ? style : {},
5450
- ...customColor ? { backgroundColor: customColor } : {},
5451
- ...glow && !customColor ? {} : {},
5950
+ ...colorStyle ?? {},
5452
5951
  ...glow && customColor ? { boxShadow: `0 0 6px ${customColor}` } : {}
5453
5952
  };
5454
5953
  return /* @__PURE__ */ jsx(
@@ -5457,12 +5956,14 @@ function Indicator({
5457
5956
  className: cn(
5458
5957
  "rounded-full shrink-0",
5459
5958
  sizeStyles[size],
5460
- !customColor && colorStyles[color],
5959
+ colorClass,
5960
+ pulseMode === "opacity" && "animate-pulse",
5461
5961
  ring && "border-2 border-background-base",
5462
- glow && !customColor && color === "success" && "shadow-[0_0_6px_rgba(20,184,166,0.6)]",
5962
+ glow && !customColor && (color === "success" || color === "live") && "shadow-[0_0_6px_rgba(46,213,115,0.6)]",
5463
5963
  glow && !customColor && color === "error" && "shadow-[0_0_6px_rgba(239,68,68,0.6)]",
5464
5964
  glow && !customColor && color === "warning" && "shadow-[0_0_6px_rgba(245,158,11,0.6)]",
5465
5965
  glow && !customColor && color === "primary" && "shadow-[0_0_6px_rgba(255,121,0,0.6)]",
5966
+ glow && !customColor && color === "error-vivid" && "shadow-[0_0_6px_rgba(255,71,87,0.6)]",
5466
5967
  className
5467
5968
  ),
5468
5969
  style: Object.keys(dynamicStyle).length > 0 ? dynamicStyle : style,
@@ -5540,31 +6041,32 @@ function Badge({
5540
6041
  }
5541
6042
  );
5542
6043
  }
6044
+ var t8 = getSemanticColors("dark");
5543
6045
  var statusBgColors = {
5544
- completed: "rgba(20,184,166,0.15)",
6046
+ completed: "rgba(46,213,115,0.15)",
5545
6047
  current: "rgba(255,121,0,0.15)",
5546
6048
  next: "transparent",
5547
6049
  upcoming: "#1C1C1C",
5548
6050
  missed: "rgba(209,67,67,0.1)",
5549
- deload: "rgba(147,51,234,0.15)"
6051
+ deload: "rgba(186,41,150,0.15)"
5550
6052
  };
5551
6053
  var statusBorderStyles = {
5552
- completed: { borderWidth: 1, borderColor: "rgba(20,184,166,0.3)" },
6054
+ completed: { borderWidth: 1, borderColor: "rgba(46,213,115,0.3)" },
5553
6055
  current: { borderWidth: 1, borderColor: "rgba(255,121,0,0.3)" },
5554
6056
  next: { borderWidth: 1, borderColor: "rgba(255,121,0,0.4)" },
5555
6057
  upcoming: { borderWidth: 1, borderColor: "#1F1F1F" },
5556
6058
  missed: { borderWidth: 1, borderColor: "rgba(209,67,67,0.25)" },
5557
- deload: { borderWidth: 1, borderColor: "rgba(147,51,234,0.3)" }
6059
+ deload: { borderWidth: 1, borderColor: "rgba(186,41,150,0.3)" }
5558
6060
  };
5559
6061
  var textColors = {
5560
- completed: "#14B8A6",
5561
- current: "#FF7900",
5562
- next: "#FF7900",
6062
+ completed: t8["status-success"],
6063
+ current: t8["brand-primary"],
6064
+ next: t8["brand-primary"],
5563
6065
  upcoming: "#6B7280",
5564
6066
  missed: "rgba(209,67,67,0.7)",
5565
- deload: "#9333ea"
6067
+ deload: WORKOUT_PILL_DELOAD
5566
6068
  };
5567
- function usePulse(enabled) {
6069
+ function usePulse2(enabled) {
5568
6070
  const [opacity] = useState(() => new Animated.Value(1));
5569
6071
  useEffect(() => {
5570
6072
  if (!enabled) {
@@ -5602,7 +6104,7 @@ function WorkoutPill({
5602
6104
  ...props
5603
6105
  }) {
5604
6106
  const shouldPulse = pulse ?? status === "current";
5605
- const pulseOpacity = usePulse(shouldPulse);
6107
+ const pulseOpacity = usePulse2(shouldPulse);
5606
6108
  const isCompleted = status === "completed";
5607
6109
  const isMissed = status === "missed";
5608
6110
  const pill = /* @__PURE__ */ jsx(
@@ -5692,23 +6194,24 @@ function WorkoutPill({
5692
6194
  }
5693
6195
  return pill;
5694
6196
  }
6197
+ var t9 = getSemanticColors("dark");
5695
6198
  var TRACK_BG = "#333333";
5696
6199
  var LABEL_COLOR = "#6B7280";
5697
6200
  var TARGET_LINE_COLOR = "rgba(33, 150, 243, 0.5)";
5698
6201
  var AT_TARGET_GLOW = "0 0 5px 1px rgba(33, 150, 243, 0.35), 0 0 10px 3px rgba(33, 150, 243, 0.15)";
5699
6202
  var ZONE = {
5700
- building: "#14B8A6",
5701
- // teal — below target ramp-up
5702
- approaching: "#FFB020",
5703
- // amber — nearing target
5704
- target: "#FF7900",
5705
- // brand — exactly at target
5706
- over1: "#D14343",
5707
- // red — mild over-target
5708
- over2: "#A62626",
5709
- // deep red — moderate over-target
5710
- over3: "#7A1C1C"
5711
- // darkest red — severe over-target
6203
+ building: t9["status-success"],
6204
+ // below target ramp-up
6205
+ approaching: t9["status-warning"],
6206
+ // nearing target
6207
+ target: t9["brand-primary"],
6208
+ // exactly at target
6209
+ over1: t9["status-error"],
6210
+ // mild over-target
6211
+ over2: WORKOUT_TOKENS.intensity.over2,
6212
+ // moderate over-target
6213
+ over3: WORKOUT_TOKENS.intensity.over3
6214
+ // severe over-target
5712
6215
  };
5713
6216
  var BULGE_SIZE = { 1: 8, 2: 10, 3: 11 };
5714
6217
  function zoneForPct(pct) {
@@ -5866,7 +6369,7 @@ function IntensityBar({
5866
6369
  }
5867
6370
 
5868
6371
  // src/components/custom/Workout/WeekRow.tsx
5869
- var BRAND_PRIMARY8 = "#FF7900";
6372
+ var BRAND_PRIMARY9 = getSemanticColors("dark")["brand-primary"];
5870
6373
  function WeekRow({
5871
6374
  weekNumber,
5872
6375
  totalWeeks,
@@ -5886,12 +6389,12 @@ function WeekRow({
5886
6389
  gap: 12
5887
6390
  };
5888
6391
  if (isDeload) {
5889
- rowStyle.backgroundColor = "rgba(147,51,234,0.06)";
6392
+ rowStyle.backgroundColor = "rgba(186,41,150,0.06)";
5890
6393
  }
5891
6394
  if (isCurrent) {
5892
6395
  rowStyle.backgroundColor = "rgba(255,121,0,0.04)";
5893
6396
  rowStyle.borderLeftWidth = 2;
5894
- rowStyle.borderLeftColor = BRAND_PRIMARY8;
6397
+ rowStyle.borderLeftColor = BRAND_PRIMARY9;
5895
6398
  }
5896
6399
  return /* @__PURE__ */ jsxs(
5897
6400
  View,
@@ -5915,7 +6418,7 @@ function WeekRow({
5915
6418
  width: 6,
5916
6419
  height: 6,
5917
6420
  borderRadius: 3,
5918
- backgroundColor: BRAND_PRIMARY8
6421
+ backgroundColor: BRAND_PRIMARY9
5919
6422
  },
5920
6423
  accessibilityElementsHidden: true,
5921
6424
  testID: "week-row-current-dot"
@@ -5929,7 +6432,7 @@ function WeekRow({
5929
6432
  fontSize: 13,
5930
6433
  fontWeight: "700",
5931
6434
  fontFamily: "Inter, sans-serif",
5932
- color: isCurrent ? BRAND_PRIMARY8 : void 0
6435
+ color: isCurrent ? BRAND_PRIMARY9 : void 0
5933
6436
  },
5934
6437
  accessibilityElementsHidden: true,
5935
6438
  children: `W${weekNumber}`
@@ -5970,11 +6473,11 @@ function WeekRow({
5970
6473
  }
5971
6474
 
5972
6475
  // src/components/custom/Workout/MesoCard.tsx
5973
- var BRAND_PRIMARY9 = "#FF7900";
5974
- var BRAND_PRIMARY_DARK2 = "#C45E00";
5975
- var BRAND_PRIMARY_LIGHT2 = "#FFB066";
6476
+ var BRAND_PRIMARY10 = getSemanticColors("dark")["brand-primary"];
6477
+ var BRAND_PRIMARY_DARK2 = MESO_ACCENT_GRADIENT_DARK;
6478
+ var BRAND_PRIMARY_LIGHT2 = MESO_ACCENT_GRADIENT_LIGHT;
5976
6479
  var BORDER_DEFAULT = "#1F1F1F";
5977
- var ACCENT_STOPS2 = [BRAND_PRIMARY_DARK2, BRAND_PRIMARY9, BRAND_PRIMARY_LIGHT2];
6480
+ var ACCENT_STOPS2 = [BRAND_PRIMARY_DARK2, BRAND_PRIMARY10, BRAND_PRIMARY_LIGHT2];
5978
6481
  function heatmapColor(percentage) {
5979
6482
  const clamped = Math.max(0, Math.min(100, percentage));
5980
6483
  const opacity = 0.12 + clamped / 100 * 0.78;
@@ -6009,7 +6512,7 @@ function MesoCard({
6009
6512
  }, [highlighted, highlight]);
6010
6513
  const borderColor = highlight.interpolate({
6011
6514
  inputRange: [0, 1],
6012
- outputRange: [BORDER_DEFAULT, BRAND_PRIMARY9]
6515
+ outputRange: [BORDER_DEFAULT, BRAND_PRIMARY10]
6013
6516
  });
6014
6517
  const header = /* @__PURE__ */ jsxs(View, { style: { paddingHorizontal: 14, paddingTop: 12, paddingBottom: 10 }, testID: "meso-card-body", children: [
6015
6518
  /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { gap: 8 }, testID: "meso-card-header", children: [
@@ -6069,7 +6572,7 @@ function MesoCard({
6069
6572
  {
6070
6573
  variant: "outline",
6071
6574
  elevation: 2,
6072
- borderColor: highlighted ? BRAND_PRIMARY9 : BORDER_DEFAULT,
6575
+ borderColor: highlighted ? BRAND_PRIMARY10 : BORDER_DEFAULT,
6073
6576
  className,
6074
6577
  style: [
6075
6578
  { borderColor },
@@ -6126,12 +6629,13 @@ function MesoCard({
6126
6629
  }
6127
6630
  ) });
6128
6631
  }
6632
+ var t10 = getSemanticColors("dark");
6129
6633
  var dotColorMap = {
6130
6634
  untrained: "#2C2C2C",
6131
- behind: "#406D87",
6132
- ontrack: "#14B8A6",
6133
- target: "#FF7900",
6134
- over: "#D14343"
6635
+ behind: t10["brand-secondary"],
6636
+ ontrack: t10["status-success"],
6637
+ target: t10["brand-primary"],
6638
+ over: t10["status-error"]
6135
6639
  };
6136
6640
  function MuscleGroupChip({
6137
6641
  name,
@@ -6205,9 +6709,10 @@ function MuscleGroupChip({
6205
6709
  }
6206
6710
 
6207
6711
  // src/components/custom/Workout/WorkoutCard.tsx
6712
+ var t11 = getSemanticColors("dark");
6208
6713
  var COLORS = {
6209
- statusSuccess: "#14B8A6",
6210
- brandPrimary: "#FF7900",
6714
+ statusSuccess: t11["status-success"],
6715
+ brandPrimary: t11["brand-primary"],
6211
6716
  borderDefault: "#1F1F1F",
6212
6717
  brandPrimarySubtle: "rgba(255,121,0,0.06)"
6213
6718
  };
@@ -6351,7 +6856,7 @@ function WorkoutCard({
6351
6856
  }
6352
6857
 
6353
6858
  // src/components/custom/Workout/ProgramPlanningPage.tsx
6354
- var BRAND_PRIMARY10 = "#FF7900";
6859
+ var BRAND_PRIMARY11 = getSemanticColors("dark")["brand-primary"];
6355
6860
  var WORKOUT_PILL_STATUS = {
6356
6861
  completed: "completed",
6357
6862
  today: "current",
@@ -6419,7 +6924,7 @@ function Breadcrumbs({ crumbs, onNavigate }) {
6419
6924
  fontSize: 12,
6420
6925
  fontFamily: "Inter, sans-serif",
6421
6926
  fontWeight: isLast ? "700" : "500",
6422
- color: isLast ? void 0 : BRAND_PRIMARY10
6927
+ color: isLast ? void 0 : BRAND_PRIMARY11
6423
6928
  },
6424
6929
  children: crumb.label
6425
6930
  }
@@ -6491,8 +6996,8 @@ function WeekLevel({ week, onSelectWorkout }) {
6491
6996
  function WorkoutLevel({ workout, expandedExercise, onToggleExercise }) {
6492
6997
  const exercises = workout.exercises.map((exercise, index) => ({
6493
6998
  ...exercise,
6494
- state: exercise.state === "upcoming" ? exercise.state : index === expandedExercise ? "expanded" : "collapsed",
6495
- onToggle: () => onToggleExercise(index)
6999
+ expanded: index === expandedExercise,
7000
+ onExpandedChange: () => onToggleExercise(index)
6496
7001
  }));
6497
7002
  return /* @__PURE__ */ jsx(View, { testID: "program-planning-page-workout-level", children: /* @__PURE__ */ jsx(
6498
7003
  WorkoutCard,
@@ -6621,6 +7126,6 @@ function ProgramPlanningPage({
6621
7126
  );
6622
7127
  }
6623
7128
 
6624
- export { ActiveWorkoutPage, EXERCISE_DETAIL_TABS, ExerciseDetailPage, ProgramPlanningPage, buildBreadcrumbs, countCompletedSets, deriveExerciseStats, deriveNavLevel, deriveWorkoutProgress, findActiveExercise, findMeso, findWeek, findWorkout, groupExercises, statusToCardState, summarizeVbt, toActiveCardProps, toExerciseCardProps, toProgressBarMesos };
7129
+ export { ActiveWorkoutPage, EXERCISE_DETAIL_TABS, ExerciseDetailPage, ProgramPlanningPage, buildBreadcrumbs, countCompletedSets, deriveExerciseStats, deriveNavLevel, deriveWorkoutProgress, findActiveExercise, findMeso, findWeek, findWorkout, groupExercises, isUpcomingExercise, summarizeVbt, toActiveCardProps, toExerciseCardProps, toProgressBarMesos };
6625
7130
  //# sourceMappingURL=pages.mjs.map
6626
7131
  //# sourceMappingURL=pages.mjs.map