@titan-design/react-ui 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (509) hide show
  1. package/README.md +46 -47
  2. package/dist/bodymap.js +768 -701
  3. package/dist/bodymap.js.map +1 -1
  4. package/dist/bodymap.mjs +770 -703
  5. package/dist/bodymap.mjs.map +1 -1
  6. package/dist/index.d.mts +1320 -215
  7. package/dist/index.d.ts +1320 -215
  8. package/dist/index.js +5996 -4498
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +5773 -4357
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/{pages-CvsFqNtx.d.mts → pages-CpW3OB3g.d.mts} +21 -3
  13. package/dist/{pages-B1hqnGIC.d.ts → pages-_3Ajpiqu.d.ts} +21 -3
  14. package/dist/pages.d.mts +1 -1
  15. package/dist/pages.d.ts +1 -1
  16. package/dist/pages.js +1435 -1428
  17. package/dist/pages.js.map +1 -1
  18. package/dist/pages.mjs +1443 -1436
  19. package/dist/pages.mjs.map +1 -1
  20. package/dist/theme/index.d.mts +202 -1042
  21. package/dist/theme/index.d.ts +202 -1042
  22. package/dist/theme/index.js +215 -300
  23. package/dist/theme/index.js.map +1 -1
  24. package/dist/theme/index.mjs +202 -296
  25. package/dist/theme/index.mjs.map +1 -1
  26. package/dist/theme/tokens-css.js +62 -5
  27. package/dist/theme/tokens-css.js.map +1 -1
  28. package/dist/theme/tokens-css.mjs +62 -5
  29. package/dist/theme/tokens-css.mjs.map +1 -1
  30. package/dist/theme/tokens.d.mts +972 -0
  31. package/dist/theme/tokens.d.ts +972 -0
  32. package/dist/theme/tokens.js +904 -0
  33. package/dist/theme/tokens.js.map +1 -0
  34. package/dist/theme/tokens.mjs +880 -0
  35. package/dist/theme/tokens.mjs.map +1 -0
  36. package/docs/audits/2026-09-08-critique-addenda.md +51 -0
  37. package/docs/audits/2026-09-08-library-critique.md +212 -0
  38. package/docs/library-roadmap.md +99 -0
  39. package/package.json +7 -1
  40. package/src/arch/arch-graph.freshness.test.ts +52 -0
  41. package/src/arch/arch-graph.json +5021 -1617
  42. package/src/components/custom/ActiveWork/CoChangeChip.stories.tsx +44 -0
  43. package/src/components/custom/ActiveWork/CoChangeChip.test.tsx +29 -0
  44. package/src/components/custom/ActiveWork/CoChangeChip.tsx +48 -0
  45. package/src/components/custom/ActiveWork/Eyebrow.stories.tsx +25 -0
  46. package/src/components/custom/ActiveWork/Eyebrow.test.tsx +16 -0
  47. package/src/components/custom/ActiveWork/Eyebrow.tsx +26 -0
  48. package/src/components/custom/ActiveWork/FileActivityDetail.stories.tsx +50 -0
  49. package/src/components/custom/ActiveWork/FileActivityDetail.test.tsx +66 -0
  50. package/src/components/custom/ActiveWork/FileActivityDetail.tsx +202 -0
  51. package/src/components/custom/ActiveWork/FileActivityRow.stories.tsx +70 -0
  52. package/src/components/custom/ActiveWork/FileActivityRow.test.tsx +67 -0
  53. package/src/components/custom/ActiveWork/FileActivityRow.tsx +130 -0
  54. package/src/components/custom/ActiveWork/FileHistoryExplorer.stories.tsx +84 -0
  55. package/src/components/custom/ActiveWork/FileHistoryExplorer.test.tsx +99 -0
  56. package/src/components/custom/ActiveWork/FileHistoryExplorer.tsx +138 -0
  57. package/src/components/custom/ActiveWork/FilePathLabel.stories.tsx +39 -0
  58. package/src/components/custom/ActiveWork/FilePathLabel.test.tsx +53 -0
  59. package/src/components/custom/ActiveWork/FilePathLabel.tsx +63 -0
  60. package/src/components/custom/ActiveWork/InitiativeBrief.stories.tsx +50 -0
  61. package/src/components/custom/ActiveWork/InitiativeBrief.test.tsx +62 -0
  62. package/src/components/custom/ActiveWork/InitiativeBrief.tsx +181 -0
  63. package/src/components/custom/ActiveWork/InitiativeCard.stories.tsx +73 -0
  64. package/src/components/custom/ActiveWork/InitiativeCard.test.tsx +68 -0
  65. package/src/components/custom/ActiveWork/InitiativeCard.tsx +136 -0
  66. package/src/components/custom/ActiveWork/InitiativeHeader.stories.tsx +59 -0
  67. package/src/components/custom/ActiveWork/InitiativeHeader.test.tsx +40 -0
  68. package/src/components/custom/ActiveWork/InitiativeHeader.tsx +73 -0
  69. package/src/components/custom/ActiveWork/InitiativeReader.stories.tsx +145 -0
  70. package/src/components/custom/ActiveWork/OpenLoops.stories.tsx +58 -0
  71. package/src/components/custom/ActiveWork/OpenLoops.test.tsx +61 -0
  72. package/src/components/custom/ActiveWork/OpenLoops.tsx +107 -0
  73. package/src/components/custom/ActiveWork/PortfolioOverview.stories.tsx +101 -0
  74. package/src/components/custom/ActiveWork/PortfolioOverview.test.tsx +81 -0
  75. package/src/components/custom/ActiveWork/PortfolioOverview.tsx +83 -0
  76. package/src/components/custom/ActiveWork/README.md +305 -0
  77. package/src/components/custom/ActiveWork/SessionDetail.stories.tsx +71 -0
  78. package/src/components/custom/ActiveWork/SessionDetail.test.tsx +84 -0
  79. package/src/components/custom/ActiveWork/SessionDetail.tsx +180 -0
  80. package/src/components/custom/ActiveWork/SessionList.stories.tsx +69 -0
  81. package/src/components/custom/ActiveWork/SessionList.test.tsx +78 -0
  82. package/src/components/custom/ActiveWork/SessionList.tsx +103 -0
  83. package/src/components/custom/ActiveWork/SessionListItem.stories.tsx +64 -0
  84. package/src/components/custom/ActiveWork/SessionListItem.test.tsx +62 -0
  85. package/src/components/custom/ActiveWork/SessionListItem.tsx +152 -0
  86. package/src/components/custom/ActiveWork/SessionReader.stories.tsx +113 -0
  87. package/src/components/custom/ActiveWork/SeverityLabel.stories.tsx +51 -0
  88. package/src/components/custom/ActiveWork/SeverityLabel.test.tsx +68 -0
  89. package/src/components/custom/ActiveWork/SeverityLabel.tsx +97 -0
  90. package/src/components/custom/ActiveWork/TaskRow.stories.tsx +63 -0
  91. package/src/components/custom/ActiveWork/TaskRow.test.tsx +112 -0
  92. package/src/components/custom/ActiveWork/TaskRow.tsx +176 -0
  93. package/src/components/custom/ActiveWork/TaskTable.stories.tsx +123 -0
  94. package/src/components/custom/ActiveWork/TaskTable.test.tsx +233 -0
  95. package/src/components/custom/ActiveWork/TaskTable.tsx +321 -0
  96. package/src/components/custom/ActiveWork/active-work-depth.test.tsx +102 -0
  97. package/src/components/custom/ActiveWork/file-history-fixture.ts +91 -0
  98. package/src/components/custom/ActiveWork/format-time.test.ts +23 -0
  99. package/src/components/custom/ActiveWork/format-time.ts +32 -0
  100. package/src/components/custom/ActiveWork/index.ts +19 -0
  101. package/src/components/custom/ActiveWork/initiative-fixture.ts +104 -0
  102. package/src/components/custom/ActiveWork/session-fixture.ts +267 -0
  103. package/src/components/custom/ActiveWork/session-linkers.ts +56 -0
  104. package/src/components/custom/ActiveWork/task-list-fixture.ts +97 -0
  105. package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +4 -3
  106. package/src/components/custom/DateTime/DateTime.stories.tsx +2 -1
  107. package/src/components/custom/DateTime/DateTime.test.tsx +3 -1
  108. package/src/components/custom/EmptyState/EmptyState.stories.tsx +22 -9
  109. package/src/components/custom/EmptyState/EmptyState.test.tsx +7 -13
  110. package/src/components/custom/EmptyState/EmptyState.tsx +4 -18
  111. package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +4 -3
  112. package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
  113. package/src/components/custom/Fatigue/GhostSpark.stories.tsx +4 -3
  114. package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +2 -2
  115. package/src/components/custom/Fatigue/LiveFatigueCard.tsx +8 -4
  116. package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +116 -6
  117. package/src/components/custom/Fatigue/LiveFatiguePanel.test.tsx +134 -0
  118. package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +54 -83
  119. package/src/components/custom/Fatigue/README.md +40 -3
  120. package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
  121. package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +2 -1
  122. package/src/components/custom/Fatigue/VelocityHero.stories.tsx +4 -3
  123. package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
  124. package/src/components/custom/Fatigue/fatigue-mock.test.ts +0 -5
  125. package/src/components/custom/Fatigue/fatigue-mock.ts +2 -10
  126. package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -0
  127. package/src/components/custom/Fatigue/index.ts +17 -5
  128. package/src/components/custom/Fatigue/panel-layout.test.ts +149 -0
  129. package/src/components/custom/Fatigue/panel-layout.ts +185 -0
  130. package/src/components/custom/Gauge/Gauge.stories.tsx +2 -2
  131. package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
  132. package/src/components/custom/Gauge/Gauge.tsx +4 -1
  133. package/src/components/custom/Metric/Metric.stories.tsx +10 -1
  134. package/src/components/custom/Metric/Metric.test.tsx +1 -3
  135. package/src/components/custom/Metric/Metric.tsx +5 -20
  136. package/src/components/custom/Prose/MarkdownProse.stories.tsx +88 -0
  137. package/src/components/custom/Prose/MarkdownProse.test.tsx +87 -0
  138. package/src/components/custom/Prose/MarkdownProse.tsx +201 -0
  139. package/src/components/custom/Prose/README.md +58 -0
  140. package/src/components/custom/Prose/index.ts +1 -0
  141. package/src/components/custom/Scatter/Scatter.stories.tsx +46 -8
  142. package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
  143. package/src/components/custom/Scatter/Scatter.tsx +116 -14
  144. package/src/components/custom/Sidebar/Sidebar.stories.tsx +40 -7
  145. package/src/components/custom/Sidebar/Sidebar.test.tsx +5 -1
  146. package/src/components/custom/Sidebar/Sidebar.tsx +16 -33
  147. package/src/components/custom/Table/Table.stories.tsx +98 -15
  148. package/src/components/custom/Table/Table.test.tsx +273 -86
  149. package/src/components/custom/Table/Table.tsx +159 -67
  150. package/src/components/custom/Table/column-fit.test.ts +75 -0
  151. package/src/components/custom/Table/column-fit.ts +116 -0
  152. package/src/components/custom/Table/index.ts +9 -0
  153. package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +8 -6
  154. package/src/components/custom/Treemap/Treemap.stories.tsx +2 -2
  155. package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
  156. package/src/components/custom/Treemap/Treemap.tsx +7 -2
  157. package/src/components/custom/Typography/Typography.stories.tsx +28 -1
  158. package/src/components/custom/Typography/Typography.test.tsx +34 -0
  159. package/src/components/custom/Typography/Typography.tsx +6 -0
  160. package/src/components/custom/Typography/index.ts +1 -8
  161. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +9 -1
  162. package/src/components/custom/Workout/BaseBadge.stories.tsx +19 -7
  163. package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
  164. package/src/components/custom/Workout/BaseBadge.tsx +3 -0
  165. package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
  166. package/src/components/custom/Workout/BodyMap.tsx +3 -1
  167. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +16 -4
  168. package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
  169. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +45 -9
  170. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +10 -8
  171. package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
  172. package/src/components/custom/Workout/CapacityBandChart.tsx +139 -108
  173. package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
  174. package/src/components/custom/Workout/DeviationBar.test.tsx +5 -2
  175. package/src/components/custom/Workout/DeviationBar.tsx +21 -16
  176. package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +182 -0
  177. package/src/components/custom/Workout/DualVelocityStrip.test.tsx +3 -2
  178. package/src/components/custom/Workout/ExerciseCard.stories.tsx +8 -7
  179. package/src/components/custom/Workout/ExerciseCard.test.tsx +13 -3
  180. package/src/components/custom/Workout/ExerciseCard.tsx +42 -51
  181. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +7 -7
  182. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
  183. package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
  184. package/src/components/custom/Workout/ExerciseHeading.tsx +8 -5
  185. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +6 -4
  186. package/src/components/custom/Workout/ExerciseIndicator.test.tsx +27 -11
  187. package/src/components/custom/Workout/ExerciseIndicator.tsx +14 -15
  188. package/src/components/custom/Workout/FatigueMeter.stories.tsx +5 -5
  189. package/src/components/custom/Workout/InputBar.stories.tsx +4 -5
  190. package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
  191. package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
  192. package/src/components/custom/Workout/IntensityBar.tsx +4 -2
  193. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +5 -4
  194. package/src/components/custom/Workout/MesoCard.stories.tsx +4 -1
  195. package/src/components/custom/Workout/MesoCard.test.tsx +7 -18
  196. package/src/components/custom/Workout/MesoCard.tsx +12 -9
  197. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
  198. package/src/components/custom/Workout/MesoProgressBar.test.tsx +18 -11
  199. package/src/components/custom/Workout/MesoProgressBar.tsx +15 -13
  200. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +2 -1
  201. package/src/components/custom/Workout/MesoStatusCard.test.tsx +14 -44
  202. package/src/components/custom/Workout/MesoStatusCard.tsx +9 -23
  203. package/src/components/custom/Workout/MetricTiles.stories.tsx +3 -2
  204. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +2 -8
  205. package/src/components/custom/Workout/MuscleGroupChip.test.tsx +23 -31
  206. package/src/components/custom/Workout/MuscleGroupChip.tsx +28 -67
  207. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +1 -1
  208. package/src/components/custom/Workout/PlaceholderStrip.test.tsx +17 -10
  209. package/src/components/custom/Workout/PlaceholderStrip.tsx +9 -8
  210. package/src/components/custom/Workout/PrBadge.stories.tsx +2 -1
  211. package/src/components/custom/Workout/PrBadge.test.tsx +3 -9
  212. package/src/components/custom/Workout/PrBadge.tsx +13 -17
  213. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +4 -1
  214. package/src/components/custom/Workout/PrHistoryModal.test.tsx +13 -36
  215. package/src/components/custom/Workout/PrHistoryModal.tsx +8 -4
  216. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +6 -1
  217. package/src/components/custom/Workout/README.md +12 -7
  218. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +3 -2
  219. package/src/components/custom/Workout/ReadinessCheck.test.tsx +12 -18
  220. package/src/components/custom/Workout/ReadinessCheck.tsx +19 -3
  221. package/src/components/custom/Workout/RestTimer.stories.tsx +3 -2
  222. package/src/components/custom/Workout/ScheduleTiles.stories.tsx +3 -2
  223. package/src/components/custom/Workout/ScheduleTiles.test.tsx +3 -4
  224. package/src/components/custom/Workout/ScheduleTiles.tsx +4 -7
  225. package/src/components/custom/Workout/SegmentedBar.stories.tsx +5 -5
  226. package/src/components/custom/Workout/SegmentedBar.tsx +6 -2
  227. package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +5 -5
  228. package/src/components/custom/Workout/SessionHeader.stories.tsx +6 -6
  229. package/src/components/custom/Workout/SessionHeader.tsx +12 -12
  230. package/src/components/custom/Workout/SessionRail.stories.tsx +12 -11
  231. package/src/components/custom/Workout/SessionRail.tsx +7 -9
  232. package/src/components/custom/Workout/SetBar.stories.tsx +10 -6
  233. package/src/components/custom/Workout/SetBar.test.tsx +49 -4
  234. package/src/components/custom/Workout/SetBar.tsx +38 -12
  235. package/src/components/custom/Workout/SetRow.stories.tsx +3 -2
  236. package/src/components/custom/Workout/SetRow.test.tsx +16 -2
  237. package/src/components/custom/Workout/SetRow.tsx +61 -23
  238. package/src/components/custom/Workout/SetStrip.stories.tsx +60 -5
  239. package/src/components/custom/Workout/SetStrip.test.tsx +25 -0
  240. package/src/components/custom/Workout/SetStrip.tsx +24 -4
  241. package/src/components/custom/Workout/SetTableHeader.stories.tsx +6 -6
  242. package/src/components/custom/Workout/SetTableHeader.tsx +9 -12
  243. package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +7 -7
  244. package/src/components/custom/Workout/SetsRepsLoad.tsx +3 -5
  245. package/src/components/custom/Workout/Sparkline.stories.tsx +1 -1
  246. package/src/components/custom/Workout/Sparkline.test.tsx +37 -19
  247. package/src/components/custom/Workout/Sparkline.tsx +14 -18
  248. package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
  249. package/src/components/custom/Workout/StatusDot.test.tsx +44 -5
  250. package/src/components/custom/Workout/StatusDot.tsx +93 -63
  251. package/src/components/custom/Workout/StatusPill.stories.tsx +1 -1
  252. package/src/components/custom/Workout/StatusPill.test.tsx +6 -15
  253. package/src/components/custom/Workout/StatusPill.tsx +27 -38
  254. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +9 -3
  255. package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
  256. package/src/components/custom/Workout/StrengthTrendChart.tsx +31 -30
  257. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +27 -64
  258. package/src/components/custom/Workout/SupersetWrapper.test.tsx +16 -14
  259. package/src/components/custom/Workout/SupersetWrapper.tsx +17 -21
  260. package/src/components/custom/Workout/TempoDisplay.stories.tsx +22 -7
  261. package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
  262. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +9 -1
  263. package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +4 -1
  264. package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +7 -4
  265. package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +4 -1
  266. package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +4 -1
  267. package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
  268. package/src/components/custom/Workout/VelocityStrip.tsx +3 -0
  269. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +6 -7
  270. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +15 -6
  271. package/src/components/custom/Workout/WeekRow.stories.tsx +4 -1
  272. package/src/components/custom/Workout/WeekRow.test.tsx +18 -15
  273. package/src/components/custom/Workout/WeekRow.tsx +23 -16
  274. package/src/components/custom/Workout/WeightBadge.stories.tsx +2 -1
  275. package/src/components/custom/Workout/WeightBadge.test.tsx +50 -19
  276. package/src/components/custom/Workout/WeightBadge.tsx +28 -27
  277. package/src/components/custom/Workout/WorkoutCard.stories.tsx +6 -1
  278. package/src/components/custom/Workout/WorkoutCard.test.tsx +18 -0
  279. package/src/components/custom/Workout/WorkoutCard.tsx +35 -57
  280. package/src/components/custom/Workout/WorkoutPill.stories.tsx +5 -2
  281. package/src/components/custom/Workout/WorkoutPill.test.tsx +39 -7
  282. package/src/components/custom/Workout/WorkoutPill.tsx +88 -57
  283. package/src/components/custom/Workout/ZoneTrack.stories.tsx +7 -6
  284. package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
  285. package/src/components/custom/Workout/index.ts +5 -0
  286. package/src/components/custom/Workout/metricText.stories.tsx +6 -5
  287. package/src/components/custom/Workout/metricText.tsx +4 -0
  288. package/src/components/custom/Workout/setHeadingKit.tsx +207 -26
  289. package/src/components/custom/charts/README.md +61 -0
  290. package/src/components/custom/charts/SetBarChart.test.tsx +30 -1
  291. package/src/components/custom/charts/SetBarChart.tsx +42 -4
  292. package/src/components/custom/charts/SparkBars.stories.tsx +55 -0
  293. package/src/components/custom/charts/SparkBars.test.tsx +69 -0
  294. package/src/components/custom/charts/SparkBars.tsx +85 -0
  295. package/src/components/custom/charts/index.ts +3 -0
  296. package/src/components/custom/index.ts +3 -0
  297. package/src/components/custom/stepper/Stepper.stories.tsx +13 -10
  298. package/src/components/custom/stepper/Stepper.test.tsx +1 -7
  299. package/src/components/custom/stepper/Stepper.tsx +13 -28
  300. package/src/components/icons/icons.stories.tsx +1 -1
  301. package/src/components/icons/icons.tsx +51 -0
  302. package/src/components/shell/AppShell.stories.tsx +150 -0
  303. package/src/components/shell/AppShell.test.tsx +70 -0
  304. package/src/components/shell/AppShell.tsx +90 -0
  305. package/src/components/shell/BrandLockup.stories.tsx +66 -5
  306. package/src/components/shell/BrandLockup.test.tsx +34 -1
  307. package/src/components/shell/BrandLockup.tsx +27 -11
  308. package/src/components/shell/NavItem.stories.tsx +4 -4
  309. package/src/components/shell/NavItem.test.tsx +17 -0
  310. package/src/components/shell/NavItem.tsx +17 -5
  311. package/src/components/shell/README.md +90 -27
  312. package/src/components/shell/SideNav.stories.tsx +38 -7
  313. package/src/components/shell/SideNav.test.tsx +16 -8
  314. package/src/components/shell/SideNav.tsx +17 -17
  315. package/src/components/shell/TopBar.stories.tsx +44 -19
  316. package/src/components/shell/TopBar.test.tsx +34 -12
  317. package/src/components/shell/TopBar.tsx +61 -40
  318. package/src/components/shell/brands.tsx +66 -0
  319. package/src/components/shell/index.ts +9 -8
  320. package/src/components/shell/{DeviceIndicator.stories.tsx → workout/DeviceIndicator.stories.tsx} +2 -2
  321. package/src/components/shell/{DeviceIndicator.tsx → workout/DeviceIndicator.tsx} +2 -2
  322. package/src/components/shell/{DeviceMenu.stories.tsx → workout/DeviceMenu.stories.tsx} +2 -2
  323. package/src/components/shell/{DeviceMenu.tsx → workout/DeviceMenu.tsx} +3 -3
  324. package/src/components/shell/{DeviceRow.stories.tsx → workout/DeviceRow.stories.tsx} +2 -2
  325. package/src/components/shell/{DeviceRow.tsx → workout/DeviceRow.tsx} +3 -3
  326. package/src/components/shell/{SessionStatePill.stories.tsx → workout/SessionStatePill.stories.tsx} +2 -2
  327. package/src/components/shell/{SessionStatePill.tsx → workout/SessionStatePill.tsx} +5 -3
  328. package/src/components/shell/workout/WorkoutShell.stories.tsx +71 -0
  329. package/src/components/shell/{DashboardShell.test.tsx → workout/WorkoutShell.test.tsx} +19 -8
  330. package/src/components/shell/workout/WorkoutShell.tsx +77 -0
  331. package/src/components/shell/workout/WorkoutTopBar.stories.tsx +58 -0
  332. package/src/components/shell/workout/WorkoutTopBar.test.tsx +39 -0
  333. package/src/components/shell/workout/WorkoutTopBar.tsx +52 -0
  334. package/src/components/shell/workout/index.ts +9 -0
  335. package/src/components/shell/workout/workoutNavItems.tsx +16 -0
  336. package/src/components/ui/README.md +110 -0
  337. package/src/components/ui/alert/Alert.stories.tsx +1 -1
  338. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +11 -13
  339. package/src/components/ui/autocomplete/Autocomplete.test.tsx +7 -25
  340. package/src/components/ui/autocomplete/Autocomplete.tsx +21 -28
  341. package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
  342. package/src/components/ui/avatar/Avatar.tsx +2 -10
  343. package/src/components/ui/badge/Badge.stories.tsx +83 -28
  344. package/src/components/ui/badge/Badge.test.tsx +19 -3
  345. package/src/components/ui/badge/Badge.tsx +48 -55
  346. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  347. package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +4 -16
  348. package/src/components/ui/button/Button.stories.tsx +46 -12
  349. package/src/components/ui/button/Button.tsx +32 -25
  350. package/src/components/ui/card/Card.stories.tsx +90 -94
  351. package/src/components/ui/card/Card.test.tsx +80 -6
  352. package/src/components/ui/card/Card.tsx +150 -203
  353. package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
  354. package/src/components/ui/checkbox/Checkbox.tsx +6 -26
  355. package/src/components/ui/chip/Chip.stories.tsx +37 -13
  356. package/src/components/ui/chip/Chip.test.tsx +10 -6
  357. package/src/components/ui/chip/Chip.tsx +76 -91
  358. package/src/components/ui/collapse/Collapse.stories.tsx +23 -23
  359. package/src/components/ui/collapse/Collapse.tsx +6 -11
  360. package/src/components/ui/data-row/DataRow.stories.tsx +9 -2
  361. package/src/components/ui/data-row/DataRow.test.tsx +5 -15
  362. package/src/components/ui/data-row/DataRow.tsx +18 -7
  363. package/src/components/ui/divider/Divider.stories.tsx +1 -1
  364. package/src/components/ui/divider/Divider.tsx +1 -5
  365. package/src/components/ui/drawer/Drawer.stories.tsx +5 -16
  366. package/src/components/ui/drawer/Drawer.tsx +13 -30
  367. package/src/components/ui/floating-overlay-depth.test.tsx +143 -0
  368. package/src/components/ui/form-field/FormField.stories.tsx +6 -20
  369. package/src/components/ui/form-field/FormField.test.tsx +1 -5
  370. package/src/components/ui/form-field/FormField.tsx +10 -46
  371. package/src/components/ui/help-tip/HelpTip.stories.tsx +8 -19
  372. package/src/components/ui/help-tip/HelpTip.test.tsx +1 -3
  373. package/src/components/ui/help-tip/HelpTip.tsx +21 -22
  374. package/src/components/ui/help-tip/index.ts +7 -1
  375. package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
  376. package/src/components/ui/icon-box/IconBox.test.tsx +1 -7
  377. package/src/components/ui/icon-box/IconBox.tsx +2 -12
  378. package/src/components/ui/indicator/Indicator.stories.tsx +1 -1
  379. package/src/components/ui/indicator/Indicator.tsx +20 -14
  380. package/src/components/ui/input/Input.stories.tsx +3 -11
  381. package/src/components/ui/input/Input.test.tsx +2 -10
  382. package/src/components/ui/input/Input.tsx +10 -25
  383. package/src/components/ui/input/index.ts +7 -1
  384. package/src/components/ui/link/Link.stories.tsx +19 -7
  385. package/src/components/ui/list-item/ListItem.stories.tsx +11 -2
  386. package/src/components/ui/list-item/ListItem.tsx +2 -9
  387. package/src/components/ui/menu/Menu.stories.tsx +21 -15
  388. package/src/components/ui/menu/Menu.test.tsx +2 -11
  389. package/src/components/ui/menu/Menu.tsx +12 -14
  390. package/src/components/ui/menu/index.ts +8 -1
  391. package/src/components/ui/modal/Modal.stories.tsx +2 -2
  392. package/src/components/ui/modal/Modal.tsx +29 -19
  393. package/src/components/ui/pill/Pill.stories.tsx +58 -23
  394. package/src/components/ui/pill/Pill.test.tsx +101 -3
  395. package/src/components/ui/pill/Pill.tsx +164 -49
  396. package/src/components/ui/pill/index.ts +1 -1
  397. package/src/components/ui/popover/Popover.stories.tsx +5 -7
  398. package/src/components/ui/popover/Popover.test.tsx +1 -6
  399. package/src/components/ui/popover/Popover.tsx +20 -15
  400. package/src/components/ui/popover/index.ts +7 -1
  401. package/src/components/ui/progress/Progress.stories.tsx +3 -12
  402. package/src/components/ui/progress/Progress.test.tsx +1 -5
  403. package/src/components/ui/radio/Radio.stories.tsx +42 -21
  404. package/src/components/ui/radio/Radio.test.tsx +6 -2
  405. package/src/components/ui/radio/Radio.tsx +23 -22
  406. package/src/components/ui/section/Section.stories.tsx +5 -14
  407. package/src/components/ui/section/Section.test.tsx +1 -6
  408. package/src/components/ui/section/Section.tsx +1 -3
  409. package/src/components/ui/section/index.ts +1 -5
  410. package/src/components/ui/select/Select.stories.tsx +3 -13
  411. package/src/components/ui/select/Select.test.tsx +2 -11
  412. package/src/components/ui/select/Select.tsx +14 -14
  413. package/src/components/ui/skeleton/Skeleton.stories.tsx +3 -11
  414. package/src/components/ui/skeleton/Skeleton.tsx +3 -14
  415. package/src/components/ui/skeleton/index.ts +1 -7
  416. package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
  417. package/src/components/ui/spinner/Spinner.tsx +1 -4
  418. package/src/components/ui/stack/Stack.stories.tsx +1 -1
  419. package/src/components/ui/stack/Stack.tsx +1 -1
  420. package/src/components/ui/surface/Surface.stories.tsx +17 -5
  421. package/src/components/ui/surface/Surface.test.tsx +88 -28
  422. package/src/components/ui/surface/Surface.tsx +37 -87
  423. package/src/components/ui/surface/SurfaceContext.ts +22 -62
  424. package/src/components/ui/surface/index.ts +8 -0
  425. package/src/components/ui/surface/resolveSurface.ts +98 -0
  426. package/src/components/ui/surface/surface.contract.test.ts +6 -1
  427. package/src/components/ui/switch/Switch.stories.tsx +1 -1
  428. package/src/components/ui/switch/Switch.tsx +7 -6
  429. package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
  430. package/src/components/ui/tabs/Tabs.tsx +7 -22
  431. package/src/components/ui/tabs/index.ts +1 -7
  432. package/src/components/ui/tile/Tile.stories.tsx +1 -1
  433. package/src/components/ui/tile/Tile.tsx +3 -0
  434. package/src/components/ui/toast/Toast.stories.tsx +1 -1
  435. package/src/components/ui/toast/Toast.test.tsx +2 -8
  436. package/src/components/ui/toast/Toast.tsx +43 -53
  437. package/src/components/ui/toast/index.ts +0 -1
  438. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +92 -71
  439. package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +3 -18
  440. package/src/components/ui/toolbar-button/ToolbarButton.tsx +25 -43
  441. package/src/components/ui/tooltip/Tooltip.stories.tsx +12 -3
  442. package/src/components/ui/tooltip/Tooltip.test.tsx +21 -3
  443. package/src/components/ui/tooltip/Tooltip.tsx +55 -36
  444. package/src/components/ui/tooltip/index.ts +1 -1
  445. package/src/components/ui/trigger/TriggerSurface.test.tsx +215 -0
  446. package/src/components/ui/trigger/TriggerSurface.tsx +81 -0
  447. package/src/components/ui/trigger/index.ts +2 -0
  448. package/src/stories/PresetShowcase.stories.tsx +100 -47
  449. package/src/test/no-device-internals.test.ts +3 -3
  450. package/src/theme/ChoosingTokens.stories.tsx +48 -0
  451. package/src/theme/ColorPalettes.stories.tsx +62 -45
  452. package/src/theme/ColorPrimitives.stories.tsx +35 -35
  453. package/src/theme/Depth.stories.tsx +132 -65
  454. package/src/theme/DepthCalibration.stories.tsx +24 -22
  455. package/src/theme/ThemeProvider.test.tsx +4 -4
  456. package/src/theme/barrel.ts +7 -6
  457. package/src/theme/color-stories.coverage.test.ts +1 -1
  458. package/src/theme/color-utils.ts +41 -29
  459. package/src/theme/config.completeness.test.ts +1 -1
  460. package/src/theme/config.ts +28 -0
  461. package/src/theme/elevation.test.ts +82 -56
  462. package/src/theme/elevation.ts +77 -561
  463. package/src/theme/global.css +30 -2
  464. package/src/theme/grey-ramp.test.ts +24 -8
  465. package/src/theme/lift.test.ts +39 -0
  466. package/src/theme/lift.ts +102 -0
  467. package/src/theme/materials.test.ts +5 -2
  468. package/src/theme/materials.ts +38 -4
  469. package/src/theme/native-theming-guard.test.ts +5 -5
  470. package/src/theme/presets/apply.ts +4 -0
  471. package/src/theme/presets/audiobook.ts +5 -2
  472. package/src/theme/presets/default.ts +4 -0
  473. package/src/theme/presets/index.ts +14 -1
  474. package/src/theme/presets/types.ts +1 -1
  475. package/src/theme/semantic-contrast.test.ts +13 -4
  476. package/src/theme/status-distinctness.test.ts +66 -0
  477. package/src/theme/surface-planes.test.ts +37 -0
  478. package/src/theme/surface-planes.ts +68 -0
  479. package/src/theme/token-export-guard.test.ts +102 -0
  480. package/src/theme/tokens/primitives.test.ts +15 -7
  481. package/src/theme/tokens/primitives.ts +67 -35
  482. package/src/theme/tokens/semantic.ts +71 -37
  483. package/src/theme/wash-ladder.test.ts +58 -0
  484. package/src/theme/workout-tokens.ts +1 -7
  485. package/src/types/jest-axe.d.ts +2 -6
  486. package/src/types/raw-md.d.ts +5 -0
  487. package/src/utils/colors.ts +4 -4
  488. package/src/utils/form.ts +1 -3
  489. package/src/utils/index.ts +2 -7
  490. package/src/utils/number-format.ts +17 -0
  491. package/src/utils/workout-format.ts +15 -6
  492. package/src/web-jsx/jsx-runtime.ts +1 -5
  493. package/tailwind.config.js +5 -0
  494. package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +0 -151
  495. package/src/components/custom/Workout/RowInventory.stories.tsx +0 -408
  496. package/src/components/custom/Workout/S3FullRail.stories.tsx +0 -46
  497. package/src/components/custom/Workout/S3SessionPace.stories.tsx +0 -95
  498. package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +0 -61
  499. package/src/components/custom/Workout/S3SetTypes.stories.tsx +0 -176
  500. package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +0 -240
  501. package/src/components/shell/DashboardShell.stories.tsx +0 -65
  502. package/src/components/shell/DashboardShell.tsx +0 -75
  503. package/src/components/shell/SessionRailSpecimen.stories.tsx +0 -753
  504. package/src/theme/elevation.stories.tsx +0 -346
  505. package/src/utils/useTheme.ts +0 -72
  506. /package/src/components/shell/{DeviceIndicator.test.tsx → workout/DeviceIndicator.test.tsx} +0 -0
  507. /package/src/components/shell/{DeviceMenu.test.tsx → workout/DeviceMenu.test.tsx} +0 -0
  508. /package/src/components/shell/{DeviceRow.test.tsx → workout/DeviceRow.test.tsx} +0 -0
  509. /package/src/components/shell/{SessionStatePill.test.tsx → workout/SessionStatePill.test.tsx} +0 -0
package/dist/bodymap.mjs CHANGED
@@ -1,9 +1,9 @@
1
- import { useMemo, useState, useEffect, Fragment as Fragment$1, useSyncExternalStore } from 'react';
1
+ import { createContext, useMemo, useState, useEffect, Fragment, useContext } from 'react';
2
2
  import { Platform, Animated, Easing, View, Text, Pressable, ScrollView } from 'react-native';
3
3
  import BodyHighlighter from 'react-native-body-highlighter';
4
4
  import { clsx } from 'clsx';
5
5
  import { twMerge } from 'tailwind-merge';
6
- import { Fragment, jsx as jsx$1, jsxs as jsxs$1 } from 'react/jsx-runtime';
6
+ import { Fragment as Fragment$1, jsx as jsx$1, jsxs as jsxs$1 } from 'react/jsx-runtime';
7
7
 
8
8
  // src/components/custom/Workout/BodyMap.tsx
9
9
  function cn(...inputs) {
@@ -13,6 +13,7 @@ function cn(...inputs) {
13
13
  // src/theme/tokens/primitives.ts
14
14
  var primitiveColors = {
15
15
  white: "#FFFFFF"};
16
+ var alertRedVivid = "#FF4757";
16
17
  var greyRamp = {
17
18
  50: "#F9F6F3",
18
19
  // L*97.0 W6
@@ -135,12 +136,16 @@ var semanticColorsLight = {
135
136
  "brand-primary-light": primitiveRamps.orange[300],
136
137
  "brand-primary-dark": primitiveRamps.orange[500],
137
138
  "brand-primary-subtle": "rgba(255, 121, 0, 0.08)",
139
+ "brand-primary-muted": "rgba(255, 121, 0, 0.30)",
140
+ "brand-primary-strong": "rgba(255, 121, 0, 0.50)",
138
141
  "brand-primary-hover": primitiveRamps.orange[500],
139
142
  "brand-primary-active": primitiveRamps.orange[600],
140
143
  "brand-secondary": primitiveRamps.cyan[600],
141
144
  "brand-secondary-light": primitiveRamps.cyan[500],
142
145
  "brand-secondary-dark": primitiveRamps.cyan[700],
143
146
  "brand-secondary-subtle": "rgba(48, 123, 155, 0.08)",
147
+ "brand-secondary-muted": "rgba(48, 123, 155, 0.30)",
148
+ "brand-secondary-strong": "rgba(48, 123, 155, 0.50)",
144
149
  "brand-secondary-hover": primitiveRamps.cyan[700],
145
150
  "brand-secondary-active": primitiveRamps.cyan[800],
146
151
  // Text on brand backgrounds (on-*)
@@ -151,6 +156,8 @@ var semanticColorsLight = {
151
156
  "status-success-light": primitiveRamps.green[200],
152
157
  "status-success-dark": primitiveRamps.green[600],
153
158
  "status-success-subtle": primitiveRamps.green[50],
159
+ "status-success-muted": "rgba(46, 213, 115, 0.30)",
160
+ "status-success-strong": "rgba(46, 213, 115, 0.50)",
154
161
  // Live-session accent — its OWN role, decoupled from success so the two can diverge
155
162
  "status-live": primitiveRamps.green[300],
156
163
  "status-live-muted": primitiveRamps.green[500],
@@ -158,19 +165,27 @@ var semanticColorsLight = {
158
165
  "status-error-light": primitiveRamps.red[500],
159
166
  "status-error-dark": primitiveRamps.red[700],
160
167
  "status-error-subtle": primitiveRamps.red[50],
161
- "status-error-vivid": primitiveRamps.red[600],
162
- // vivid alert red
168
+ "status-error-muted": "rgba(209, 67, 67, 0.30)",
169
+ "status-error-strong": "rgba(209, 67, 67, 0.50)",
170
+ "status-error-vivid": alertRedVivid,
171
+ // NOT red[600], that is status-error
163
172
  "status-error-vivid-light": primitiveRamps.red[500],
164
173
  "status-error-vivid-dark": primitiveRamps.red[700],
165
174
  "status-error-vivid-subtle": "rgba(255, 71, 87, 0.12)",
175
+ "status-error-vivid-muted": "rgba(255, 71, 87, 0.30)",
176
+ "status-error-vivid-strong": "rgba(255, 71, 87, 0.50)",
166
177
  "status-warning": primitiveRamps.amber[300],
167
178
  "status-warning-light": primitiveRamps.amber[200],
168
179
  "status-warning-dark": primitiveRamps.amber[500],
169
180
  "status-warning-subtle": primitiveRamps.amber[50],
181
+ "status-warning-muted": "rgba(249, 180, 21, 0.30)",
182
+ "status-warning-strong": "rgba(249, 180, 21, 0.50)",
170
183
  "status-info": primitiveRamps.blue[500],
171
184
  "status-info-light": primitiveRamps.blue[300],
172
185
  "status-info-dark": primitiveRamps.blue[600],
173
186
  "status-info-subtle": primitiveRamps.blue[50],
187
+ "status-info-muted": "rgba(33, 150, 243, 0.30)",
188
+ "status-info-strong": "rgba(33, 150, 243, 0.50)",
174
189
  // Text on status backgrounds (on-status-*)
175
190
  "on-status-success": primitiveColors.white,
176
191
  "on-status-error": primitiveColors.white,
@@ -265,7 +280,7 @@ var semanticColorsLight = {
265
280
  "interactive-disabled": "rgba(55, 65, 81, 0.12)",
266
281
  "interactive-disabled-text": "rgba(55, 65, 81, 0.26)",
267
282
  // Divider
268
- "divider": "#E8E9EB",
283
+ divider: "#E8E9EB",
269
284
  // Avatar default
270
285
  "avatar-background": greyRamp[600],
271
286
  "avatar-text": primitiveColors.white
@@ -276,12 +291,16 @@ var semanticColorsDark = {
276
291
  "brand-primary-light": primitiveRamps.orange[300],
277
292
  "brand-primary-dark": primitiveRamps.orange[500],
278
293
  "brand-primary-subtle": "rgba(255, 121, 0, 0.12)",
294
+ "brand-primary-muted": "rgba(255, 121, 0, 0.30)",
295
+ "brand-primary-strong": "rgba(255, 121, 0, 0.50)",
279
296
  "brand-primary-hover": primitiveRamps.orange[300],
280
297
  "brand-primary-active": primitiveRamps.orange[200],
281
298
  "brand-secondary": primitiveRamps.cyan[600],
282
299
  "brand-secondary-light": primitiveRamps.cyan[500],
283
300
  "brand-secondary-dark": primitiveRamps.cyan[700],
284
301
  "brand-secondary-subtle": "rgba(48, 123, 155, 0.12)",
302
+ "brand-secondary-muted": "rgba(48, 123, 155, 0.30)",
303
+ "brand-secondary-strong": "rgba(48, 123, 155, 0.50)",
285
304
  "brand-secondary-hover": primitiveRamps.cyan[500],
286
305
  "brand-secondary-active": primitiveRamps.cyan[400],
287
306
  // Text on brand backgrounds
@@ -292,6 +311,8 @@ var semanticColorsDark = {
292
311
  "status-success-light": primitiveRamps.green[200],
293
312
  "status-success-dark": primitiveRamps.green[600],
294
313
  "status-success-subtle": "rgba(46, 213, 115, 0.12)",
314
+ "status-success-muted": "rgba(46, 213, 115, 0.30)",
315
+ "status-success-strong": "rgba(46, 213, 115, 0.50)",
295
316
  // Live-session accent — its OWN role, decoupled from success so the two can diverge
296
317
  "status-live": primitiveRamps.green[300],
297
318
  "status-live-muted": primitiveRamps.green[500],
@@ -299,18 +320,26 @@ var semanticColorsDark = {
299
320
  "status-error-light": primitiveRamps.red[500],
300
321
  "status-error-dark": primitiveRamps.red[700],
301
322
  "status-error-subtle": "rgba(209, 67, 67, 0.12)",
302
- "status-error-vivid": primitiveRamps.red[600],
323
+ "status-error-muted": "rgba(209, 67, 67, 0.30)",
324
+ "status-error-strong": "rgba(209, 67, 67, 0.50)",
325
+ "status-error-vivid": alertRedVivid,
303
326
  "status-error-vivid-light": primitiveRamps.red[500],
304
327
  "status-error-vivid-dark": primitiveRamps.red[700],
305
328
  "status-error-vivid-subtle": "rgba(255, 71, 87, 0.12)",
329
+ "status-error-vivid-muted": "rgba(255, 71, 87, 0.30)",
330
+ "status-error-vivid-strong": "rgba(255, 71, 87, 0.50)",
306
331
  "status-warning": primitiveRamps.amber[300],
307
332
  "status-warning-light": primitiveRamps.amber[200],
308
333
  "status-warning-dark": primitiveRamps.amber[500],
309
334
  "status-warning-subtle": "rgba(249, 180, 21, 0.12)",
335
+ "status-warning-muted": "rgba(249, 180, 21, 0.30)",
336
+ "status-warning-strong": "rgba(249, 180, 21, 0.50)",
310
337
  "status-info": primitiveRamps.blue[500],
311
338
  "status-info-light": primitiveRamps.blue[300],
312
339
  "status-info-dark": primitiveRamps.blue[600],
313
340
  "status-info-subtle": "rgba(33, 150, 243, 0.12)",
341
+ "status-info-muted": "rgba(33, 150, 243, 0.30)",
342
+ "status-info-strong": "rgba(33, 150, 243, 0.50)",
314
343
  // Text on status backgrounds
315
344
  "on-status-success": primitiveColors.white,
316
345
  "on-status-error": primitiveColors.white,
@@ -450,7 +479,7 @@ var semanticColorsDark = {
450
479
  "interactive-disabled": "rgba(255, 255, 255, 0.12)",
451
480
  "interactive-disabled-text": "rgba(255, 255, 255, 0.26)",
452
481
  // Divider
453
- "divider": "rgba(255, 255, 255, 0.09)",
482
+ divider: "rgba(255, 255, 255, 0.09)",
454
483
  // Avatar default
455
484
  "avatar-background": greyRamp[700],
456
485
  "avatar-text": primitiveColors.white
@@ -464,6 +493,150 @@ function resolveColor(token, mode = "dark") {
464
493
  return Platform.OS === "web" ? `var(--color-${token})` : getSemanticColors(mode)[token];
465
494
  }
466
495
 
496
+ // src/theme/color-utils.ts
497
+ function hexToRgb(hex) {
498
+ const cleaned = hex.replace("#", "");
499
+ let r, g, b;
500
+ if (cleaned.length === 3) {
501
+ r = parseInt(cleaned[0] + cleaned[0], 16);
502
+ g = parseInt(cleaned[1] + cleaned[1], 16);
503
+ b = parseInt(cleaned[2] + cleaned[2], 16);
504
+ } else if (cleaned.length === 6) {
505
+ r = parseInt(cleaned.slice(0, 2), 16);
506
+ g = parseInt(cleaned.slice(2, 4), 16);
507
+ b = parseInt(cleaned.slice(4, 6), 16);
508
+ } else {
509
+ return null;
510
+ }
511
+ return { r, g, b };
512
+ }
513
+
514
+ // src/theme/materials.ts
515
+ var c = getSemanticColors("dark");
516
+ function insetWell(tone = c["surface-input"]) {
517
+ return {
518
+ backgroundColor: tone,
519
+ boxShadow: "inset 0 2px 6px rgba(0,0,0,0.55), inset 0 -1px 0 rgba(255,255,255,0.12)"
520
+ };
521
+ }
522
+ var FLOATING_LIFT_MIN = 4;
523
+ var LIFT_RIM_ALPHA = { dark: 0.12, light: 0.9 };
524
+ var AMBIENT = {
525
+ 1: [
526
+ { y: 1, blur: 2, alpha: 0.35 },
527
+ { y: 2, blur: 6, alpha: 0.3 }
528
+ ],
529
+ 2: [
530
+ { y: 1, blur: 2, alpha: 0.35 },
531
+ { y: 4, blur: 12, alpha: 0.32 }
532
+ ],
533
+ 3: [
534
+ { y: 2, blur: 4, alpha: 0.35 },
535
+ { y: 8, blur: 22, alpha: 0.35 }
536
+ ],
537
+ 4: [
538
+ { y: 1, blur: 2, alpha: 0.35 },
539
+ { y: 10, blur: 24, alpha: 0.3 },
540
+ { y: 24, blur: 48, alpha: 0.2 }
541
+ ],
542
+ 5: [
543
+ { y: 2, blur: 4, alpha: 0.4 },
544
+ { y: 16, blur: 32, alpha: 0.35 },
545
+ { y: 32, blur: 64, alpha: 0.25 }
546
+ ]
547
+ };
548
+ var AMBIENT_ALPHA_SCALE = { dark: 1, light: 0.4 };
549
+ function ambientLayers(step, mode) {
550
+ const scale = AMBIENT_ALPHA_SCALE[mode];
551
+ return AMBIENT[step].map(
552
+ ({ y, blur, alpha: alpha2 }) => `0 ${y}px ${blur}px rgba(0,0,0,${(alpha2 * scale).toFixed(2)})`
553
+ );
554
+ }
555
+ function liftShadow(step, mode = "dark", opts = {}) {
556
+ const rim = opts.rim ?? LIFT_RIM_ALPHA[mode];
557
+ const layers = ambientLayers(step, mode);
558
+ if (rim > 0) layers.unshift(`inset 0 1px 0 rgba(255,255,255,${rim.toFixed(2)})`);
559
+ return layers.join(", ");
560
+ }
561
+ function liftStyle(step, mode = "dark", opts = {}) {
562
+ const deepest = AMBIENT[step][AMBIENT[step].length - 1];
563
+ return Platform.select({
564
+ web: { boxShadow: liftShadow(step, mode, opts) },
565
+ default: {
566
+ shadowColor: "#000",
567
+ shadowOffset: { width: 0, height: Math.round(deepest.y / 2) },
568
+ shadowOpacity: deepest.alpha * AMBIENT_ALPHA_SCALE[mode],
569
+ shadowRadius: deepest.blur / 2,
570
+ elevation: step
571
+ }
572
+ });
573
+ }
574
+
575
+ // src/theme/surface-planes.ts
576
+ var SURFACE_LEVEL_TOKEN = {
577
+ frame: "background-frame",
578
+ background: "background-base",
579
+ base: "surface-base",
580
+ elevated: "surface-elevated",
581
+ raised: "surface-raised",
582
+ overlay: "surface-overlay"
583
+ };
584
+ var PLANE_ORDER = [
585
+ "frame",
586
+ "background",
587
+ "base",
588
+ "elevated",
589
+ "raised",
590
+ "overlay"
591
+ ];
592
+ function surfaceBackground(level, mode) {
593
+ return getSemanticColors(mode)[SURFACE_LEVEL_TOKEN[level]];
594
+ }
595
+ function stepPlane(from, delta) {
596
+ const index = PLANE_ORDER.indexOf(from);
597
+ const clamped = Math.min(PLANE_ORDER.length - 1, Math.max(0, index + delta));
598
+ return PLANE_ORDER[clamped];
599
+ }
600
+ function pressedLevel(parent) {
601
+ return stepPlane(parent, -1);
602
+ }
603
+ function raisedLevel(parent, steps) {
604
+ return stepPlane(parent, Math.max(0, steps));
605
+ }
606
+
607
+ // src/theme/elevation.ts
608
+ var FLOATING_ELEVATION_MIN = FLOATING_LIFT_MIN;
609
+ function getPressedRecessShadow(fillColor, _mode = "dark") {
610
+ const { boxShadow } = insetWell(fillColor);
611
+ return Platform.select({
612
+ web: { boxShadow },
613
+ default: {}
614
+ });
615
+ }
616
+ var glowConfig = {
617
+ tight: { blur: 4, spread: 0, opacity: 0.4 },
618
+ subtle: { blur: 12, spread: 0, opacity: 0.25 },
619
+ medium: { blur: 20, spread: 2, opacity: 0.4 },
620
+ strong: { blur: 30, spread: 4, opacity: 0.55 }
621
+ };
622
+ function getGlowShadow(color, intensity = "medium") {
623
+ const config = glowConfig[intensity];
624
+ const rgb = hexToRgb(color);
625
+ if (!rgb) return {};
626
+ return Platform.select({
627
+ web: {
628
+ boxShadow: `0 0 ${config.blur}px ${config.spread}px rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${config.opacity})`
629
+ },
630
+ default: {
631
+ shadowColor: color,
632
+ shadowOffset: { width: 0, height: 0 },
633
+ shadowOpacity: config.opacity,
634
+ shadowRadius: config.blur / 2,
635
+ elevation: 0
636
+ }
637
+ });
638
+ }
639
+
467
640
  // src/theme/workout-tokens.ts
468
641
  var WORKOUT_TOKENS = {
469
642
  // BodyMap volume heatmap — the canonical `divergingScale` (under → optimal →
@@ -791,7 +964,8 @@ function BodyMap({
791
964
  alignSelf: "center",
792
965
  transform: [{ scale }]
793
966
  },
794
- glowColor ? { boxShadow: `0 0 14px 2px ${glowColor}` } : void 0
967
+ // The highlight halo is emphasis, not depth.
968
+ glowColor ? getGlowShadow(glowColor, "medium") : void 0
795
969
  ],
796
970
  "aria-hidden": true,
797
971
  accessibilityElementsHidden: true,
@@ -953,6 +1127,17 @@ var colorStyles = {
953
1127
  info: "bg-status-info",
954
1128
  "error-vivid": "bg-status-error-vivid"
955
1129
  };
1130
+ var t = getSemanticColors("dark");
1131
+ var glowColors = {
1132
+ default: greyRamp[500],
1133
+ primary: t["brand-primary"],
1134
+ success: t["status-success"],
1135
+ live: t["status-live"],
1136
+ error: t["status-error"],
1137
+ warning: t["status-warning"],
1138
+ info: t["status-info"],
1139
+ "error-vivid": t["status-error-vivid"]
1140
+ };
956
1141
  function Indicator({
957
1142
  size = "sm",
958
1143
  color = "default",
@@ -990,11 +1175,7 @@ function Indicator({
990
1175
  )
991
1176
  ] });
992
1177
  }
993
- const dynamicStyle = {
994
- ...typeof style === "object" ? style : {},
995
- ...colorStyle ?? {},
996
- ...glow && customColor ? { boxShadow: `0 0 6px ${customColor}` } : {}
997
- };
1178
+ const glowStyle = glow ? getGlowShadow(customColor ?? glowColors[color], "subtle") : null;
998
1179
  return /* @__PURE__ */ jsx(
999
1180
  View,
1000
1181
  {
@@ -1004,54 +1185,165 @@ function Indicator({
1004
1185
  colorClass,
1005
1186
  pulseMode === "opacity" && "animate-pulse",
1006
1187
  ring && "border-2 border-background-base",
1007
- glow && !customColor && (color === "success" || color === "live") && "shadow-[0_0_6px_rgba(46,213,115,0.6)]",
1008
- glow && !customColor && color === "error" && "shadow-[0_0_6px_rgba(239,68,68,0.6)]",
1009
- glow && !customColor && color === "warning" && "shadow-[0_0_6px_rgba(245,158,11,0.6)]",
1010
- glow && !customColor && color === "primary" && "shadow-[0_0_6px_rgba(255,121,0,0.6)]",
1011
- glow && !customColor && color === "error-vivid" && "shadow-[0_0_6px_rgba(255,71,87,0.6)]",
1012
1188
  className
1013
1189
  ),
1014
- style: Object.keys(dynamicStyle).length > 0 ? dynamicStyle : style,
1190
+ style: [style, colorStyle, glowStyle],
1015
1191
  ...props
1016
1192
  }
1017
1193
  );
1018
1194
  }
1019
-
1020
- // src/components/ui/badge/Badge.tsx
1021
- var variantColorStyles = {
1195
+ var colorToTone = {
1196
+ default: "neutral",
1197
+ primary: "brand",
1198
+ secondary: "brand-secondary",
1199
+ success: "success",
1200
+ error: "error",
1201
+ warning: "warning",
1202
+ info: "info"
1203
+ };
1204
+ var toneStyles = {
1022
1205
  solid: {
1023
- default: "bg-hairline-strong text-text-inverse",
1024
- primary: "bg-brand-primary text-text-inverse",
1025
- secondary: "bg-brand-secondary text-text-inverse",
1026
- success: "bg-status-success text-text-inverse",
1027
- error: "bg-status-error text-text-inverse",
1028
- warning: "bg-status-warning text-text-inverse",
1029
- info: "bg-status-info text-text-inverse"
1206
+ neutral: "bg-hairline-strong border-transparent text-text-inverse",
1207
+ brand: "bg-brand-primary border-transparent text-text-inverse",
1208
+ "brand-secondary": "bg-brand-secondary border-transparent text-text-inverse",
1209
+ success: "bg-status-success border-transparent text-text-inverse",
1210
+ warning: "bg-status-warning border-transparent text-text-inverse",
1211
+ error: "bg-status-error border-transparent text-text-inverse",
1212
+ info: "bg-status-info border-transparent text-text-inverse"
1030
1213
  },
1031
1214
  subtle: {
1032
- default: "bg-surface-raised text-text-secondary",
1033
- primary: "bg-brand-primary-subtle text-brand-primary",
1034
- secondary: "bg-brand-secondary-subtle text-brand-secondary",
1035
- success: "bg-status-success-subtle text-status-success",
1036
- error: "bg-status-error-subtle text-status-error",
1037
- warning: "bg-status-warning-subtle text-status-warning",
1038
- info: "bg-status-info-subtle text-status-info"
1215
+ // Alpha-white rather than a ramp step: a pill sits on whatever plane its
1216
+ // host is, and an alpha fill composites by the same amount on all of them.
1217
+ // A `surface-*` fill would vanish on the plane it names. Borderless like the
1218
+ // six coloured tones — the fill carries the capsule, not a ring.
1219
+ neutral: "bg-hairline-subtle border-transparent text-text-secondary",
1220
+ brand: "bg-brand-primary-subtle border-transparent text-brand-primary",
1221
+ "brand-secondary": "bg-brand-secondary-subtle border-transparent text-brand-secondary",
1222
+ success: "bg-status-success-subtle border-transparent text-status-success",
1223
+ warning: "bg-status-warning-subtle border-transparent text-status-warning",
1224
+ error: "bg-status-error-subtle border-transparent text-status-error",
1225
+ info: "bg-status-info-subtle border-transparent text-status-info"
1039
1226
  },
1040
1227
  outline: {
1041
- default: "border border-hairline-strong text-text-secondary",
1042
- primary: "border border-brand-primary text-brand-primary",
1043
- secondary: "border border-brand-secondary text-brand-secondary",
1044
- success: "border border-status-success text-status-success",
1045
- error: "border border-status-error text-status-error",
1046
- warning: "border border-status-warning text-status-warning",
1047
- info: "border border-status-info text-status-info"
1228
+ neutral: "border-hairline text-text-secondary",
1229
+ brand: "border-brand-primary text-brand-primary",
1230
+ "brand-secondary": "border-brand-secondary text-brand-secondary",
1231
+ success: "border-status-success text-status-success",
1232
+ warning: "border-status-warning text-status-warning",
1233
+ error: "border-status-error text-status-error",
1234
+ info: "border-status-info text-status-info"
1048
1235
  }
1049
1236
  };
1237
+ var dotToneStyles = {
1238
+ neutral: "bg-text-tertiary",
1239
+ brand: "bg-brand-primary",
1240
+ "brand-secondary": "bg-brand-secondary",
1241
+ success: "bg-status-success",
1242
+ warning: "bg-status-warning",
1243
+ error: "bg-status-error",
1244
+ info: "bg-status-info"
1245
+ };
1050
1246
  var sizeStyles2 = {
1051
- sm: "px-1.5 py-0.5 text-xs",
1052
- md: "px-2 py-0.5 text-xs",
1053
- lg: "px-2.5 py-1 text-sm"
1247
+ xs: { container: "px-1 py-px", text: "text-3xs" },
1248
+ sm: { container: "px-2 py-0.5", text: "text-2xs" },
1249
+ md: { container: "px-2.5 py-1", text: "text-xs" },
1250
+ lg: { container: "px-3 py-1.5", text: "text-sm" },
1251
+ xl: { container: "px-4 py-2", text: "text-base" }
1252
+ };
1253
+ function PillDot({ tone, testID }) {
1254
+ return /* @__PURE__ */ jsx(
1255
+ View,
1256
+ {
1257
+ className: cn("w-1.5 h-1.5 rounded-full shrink-0", dotToneStyles[tone]),
1258
+ accessibilityElementsHidden: true,
1259
+ testID: testID ? `${testID}-dot` : "pill-dot"
1260
+ }
1261
+ );
1262
+ }
1263
+ function containerClasses(p, tone) {
1264
+ return cn(
1265
+ "flex-row items-center gap-1 border self-start shrink-0",
1266
+ p.rounded === false ? "rounded" : "rounded-full",
1267
+ toneStyles[p.variant ?? "subtle"][tone],
1268
+ sizeStyles2[p.size ?? "sm"].container,
1269
+ p.isDisabled && "opacity-50",
1270
+ p.className
1271
+ );
1272
+ }
1273
+ function PillContent({ tone, ...p }) {
1274
+ const textClasses = cn(
1275
+ "font-heading font-semibold text-inherit",
1276
+ sizeStyles2[p.size ?? "sm"].text,
1277
+ p.textClassName
1278
+ );
1279
+ const slot = p.leading ?? p.leftElement;
1280
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
1281
+ slot === "dot" ? /* @__PURE__ */ jsx(PillDot, { tone: p.dotTone ?? tone, testID: p.testID }) : slot,
1282
+ typeof p.children === "string" ? /* @__PURE__ */ jsx(Text, { className: textClasses, children: p.children }) : p.children,
1283
+ p.trailing
1284
+ ] });
1285
+ }
1286
+ function Pill(props) {
1287
+ const {
1288
+ variant,
1289
+ tone,
1290
+ color,
1291
+ size,
1292
+ rounded,
1293
+ leading,
1294
+ dotTone,
1295
+ leftElement,
1296
+ trailing,
1297
+ onPress,
1298
+ isDisabled,
1299
+ className,
1300
+ textClassName,
1301
+ children,
1302
+ ...viewProps
1303
+ } = props;
1304
+ const resolvedTone = tone ?? (color ? colorToTone[color] : "neutral");
1305
+ const classes = containerClasses(props, resolvedTone);
1306
+ const content = /* @__PURE__ */ jsx(PillContent, { ...props, tone: resolvedTone });
1307
+ if (onPress) {
1308
+ return /* @__PURE__ */ jsx(
1309
+ Pressable,
1310
+ {
1311
+ onPress,
1312
+ disabled: isDisabled,
1313
+ accessibilityRole: "button",
1314
+ className: classes,
1315
+ ...viewProps,
1316
+ children: content
1317
+ }
1318
+ );
1319
+ }
1320
+ return /* @__PURE__ */ jsx(View, { className: classes, ...viewProps, children: content });
1321
+ }
1322
+
1323
+ // src/components/ui/badge/Badge.tsx
1324
+ var colorToTone2 = {
1325
+ default: "neutral",
1326
+ primary: "brand",
1327
+ secondary: "brand-secondary",
1328
+ success: "success",
1329
+ error: "error",
1330
+ warning: "warning",
1331
+ info: "info"
1332
+ };
1333
+ var sizeStyles3 = {
1334
+ sm: "px-1.5 py-0.5",
1335
+ md: "px-2 py-0.5",
1336
+ lg: "px-2.5 py-1"
1054
1337
  };
1338
+ var textSizeStyles = {
1339
+ sm: "text-xs",
1340
+ md: "text-xs",
1341
+ lg: "text-sm"
1342
+ };
1343
+ function dotIndicatorColor(color, dotColor) {
1344
+ if (dotColor) return dotColor;
1345
+ return color === "default" || color === "secondary" ? "default" : color;
1346
+ }
1055
1347
  function Badge({
1056
1348
  variant = "subtle",
1057
1349
  color = "default",
@@ -1062,31 +1354,116 @@ function Badge({
1062
1354
  children,
1063
1355
  ...props
1064
1356
  }) {
1065
- return /* @__PURE__ */ jsxs(
1066
- View,
1357
+ return /* @__PURE__ */ jsx(
1358
+ Pill,
1067
1359
  {
1360
+ variant,
1361
+ tone: colorToTone2[color],
1362
+ leading: dot ? /* @__PURE__ */ jsx(Indicator, { size: "xs", color: dotIndicatorColor(color, dotColor), className: "mr-0.5" }) : void 0,
1068
1363
  className: cn(
1069
- "inline-flex items-center justify-center rounded-full font-medium",
1070
- variantColorStyles[variant][color],
1071
- sizeStyles2[size],
1364
+ "justify-center self-auto gap-0",
1365
+ variant === "outline" ? "border" : "border-0",
1366
+ sizeStyles3[size],
1072
1367
  className
1073
1368
  ),
1369
+ textClassName: cn("font-sans font-medium", textSizeStyles[size]),
1074
1370
  ...props,
1075
- children: [
1076
- dot && /* @__PURE__ */ jsx(
1077
- Indicator,
1078
- {
1079
- size: "xs",
1080
- color: dotColor ?? (color === "default" || color === "secondary" ? "default" : color),
1081
- className: "mr-0.5"
1082
- }
1083
- ),
1084
- typeof children === "string" ? /* @__PURE__ */ jsx(Text, { className: "text-inherit font-medium", children }) : children
1085
- ]
1371
+ children
1372
+ }
1373
+ );
1374
+ }
1375
+ var variantStyles = {
1376
+ h1: "font-heading text-5xl font-bold leading-tight",
1377
+ h2: "font-heading text-4xl font-bold leading-tight",
1378
+ h3: "font-heading text-3xl font-bold leading-tight",
1379
+ h4: "font-heading text-2xl font-bold leading-tight",
1380
+ h5: "font-heading text-xl font-semibold leading-tight",
1381
+ h6: "font-heading text-lg font-semibold leading-tight",
1382
+ body1: "font-body text-base font-normal leading-normal",
1383
+ body2: "font-body text-sm font-normal leading-normal",
1384
+ subtitle1: "font-body text-base font-medium leading-relaxed",
1385
+ subtitle2: "font-body text-sm font-medium leading-normal",
1386
+ caption: "font-body text-xs font-normal leading-loose",
1387
+ overline: "font-body text-xs font-semibold uppercase tracking-widest leading-relaxed",
1388
+ button: "font-sans text-sm font-semibold leading-relaxed",
1389
+ // Monospace technical readouts (clocks, ids, metrics) and their all-caps label form.
1390
+ mono: "font-mono text-xs font-normal leading-normal",
1391
+ monoLabel: "font-mono text-xs font-bold uppercase tracking-wide leading-normal",
1392
+ // The sans (Inter) label pair: 10px for dense table/column headers, 12px bold for
1393
+ // badge and row labels. `overline` is the 12px font-body form of the same idea.
1394
+ microLabel: "font-sans text-2xs font-semibold uppercase tracking-widest leading-normal",
1395
+ boldLabel: "font-sans text-xs font-bold leading-normal"
1396
+ };
1397
+ var colorStyles2 = {
1398
+ primary: "text-text-primary",
1399
+ secondary: "text-text-secondary",
1400
+ tertiary: "text-text-tertiary",
1401
+ disabled: "text-text-disabled",
1402
+ inverse: "text-text-inverse",
1403
+ success: "text-status-success",
1404
+ error: "text-status-error",
1405
+ warning: "text-status-warning",
1406
+ info: "text-status-info",
1407
+ inherit: ""
1408
+ // No color class, inherit from parent
1409
+ };
1410
+ var alignStyles = {
1411
+ left: "text-left",
1412
+ center: "text-center",
1413
+ right: "text-right",
1414
+ justify: "text-justify"
1415
+ };
1416
+ var headingVariants = ["h1", "h2", "h3", "h4", "h5", "h6"];
1417
+ var marginBottomStyles = {
1418
+ none: "",
1419
+ sm: "mb-1",
1420
+ md: "mb-2",
1421
+ lg: "mb-4"
1422
+ };
1423
+ function Typography({
1424
+ variant = "body1",
1425
+ color = "primary",
1426
+ align,
1427
+ truncate = false,
1428
+ noWrap = false,
1429
+ // deprecated, kept for backward compatibility
1430
+ marginBottom,
1431
+ gutterBottom = false,
1432
+ // deprecated, kept for backward compatibility
1433
+ maxLines,
1434
+ className,
1435
+ children,
1436
+ ...props
1437
+ }) {
1438
+ const isHeading = headingVariants.includes(variant);
1439
+ const shouldTruncate = truncate || noWrap;
1440
+ const mb = marginBottom || (gutterBottom ? "md" : "none");
1441
+ let numLines;
1442
+ if (maxLines) {
1443
+ numLines = maxLines;
1444
+ } else if (shouldTruncate) {
1445
+ numLines = 1;
1446
+ }
1447
+ return /* @__PURE__ */ jsx(
1448
+ Text,
1449
+ {
1450
+ accessibilityRole: isHeading ? "header" : "text",
1451
+ numberOfLines: numLines,
1452
+ className: cn(
1453
+ variantStyles[variant],
1454
+ color !== "inherit" && colorStyles2[color],
1455
+ align && alignStyles[align],
1456
+ shouldTruncate && "truncate",
1457
+ marginBottomStyles[mb],
1458
+ className
1459
+ ),
1460
+ ...props,
1461
+ children
1086
1462
  }
1087
1463
  );
1088
1464
  }
1089
- var BRAND_PRIMARY2 = getSemanticColors("dark")["brand-primary"];
1465
+
1466
+ // src/components/custom/Workout/Sparkline.tsx
1090
1467
  function normalizeData(data, height) {
1091
1468
  if (data.length === 0) return [];
1092
1469
  const min = Math.min(...data);
@@ -1123,7 +1500,7 @@ function Sparkline({
1123
1500
  }
1124
1501
  );
1125
1502
  }
1126
- const resolvedColor = color ?? BRAND_PRIMARY2;
1503
+ const resolvedColor = color ?? resolveColor("brand-primary");
1127
1504
  const normalized = normalizeData(data, height);
1128
1505
  const stepX = data.length > 1 ? width / (data.length - 1) : 0;
1129
1506
  const dotSize = 3;
@@ -1163,14 +1540,19 @@ function Sparkline({
1163
1540
  ],
1164
1541
  accessibilityElementsHidden: true,
1165
1542
  testID: `sparkline-reference-${i}`,
1166
- children: line.label && /* @__PURE__ */ jsx(
1167
- Text,
1543
+ children: line.label && // `3xs` (9px) is the scale floor; the label was 7px, which is off it
1544
+ // entirely (TOKENS.md §4). The line box stays unpinned, as the raw
1545
+ // <Text> this replaced was, so the absolute offset still lands.
1546
+ /* @__PURE__ */ jsx(
1547
+ Typography,
1168
1548
  {
1549
+ variant: "caption",
1550
+ color: "inherit",
1551
+ className: "text-3xs leading-[normal]",
1169
1552
  style: {
1170
1553
  position: "absolute",
1171
1554
  right: 0,
1172
1555
  top: -10,
1173
- fontSize: 7,
1174
1556
  color: line.color,
1175
1557
  opacity: 1
1176
1558
  },
@@ -1239,9 +1621,9 @@ function Sparkline({
1239
1621
  }
1240
1622
 
1241
1623
  // src/components/custom/Workout/BodyMapDetailPanel.tsx
1242
- var t = getSemanticColors("dark");
1243
- var BRAND_PRIMARY3 = t["brand-primary"];
1244
- var VOLUME_GRADIENT = `linear-gradient(90deg, ${t["status-info"]} 0%, ${t["status-success"]} 50%, ${t["status-error"]} 100%)`;
1624
+ var t2 = getSemanticColors("dark");
1625
+ var BRAND_PRIMARY2 = t2["brand-primary"];
1626
+ var VOLUME_GRADIENT = `linear-gradient(90deg, ${t2["status-info"]} 0%, ${t2["status-success"]} 50%, ${t2["status-error"]} 100%)`;
1245
1627
  var SLIDE_OFFSET = 400;
1246
1628
  var BACKDROP_OPACITY = 0.4;
1247
1629
  var STATUS_BADGE_COLOR = {
@@ -1306,7 +1688,14 @@ function BodyMapDetailPanel({
1306
1688
  return /* @__PURE__ */ jsxs(
1307
1689
  View,
1308
1690
  {
1309
- style: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, justifyContent: "flex-end" },
1691
+ style: {
1692
+ position: "absolute",
1693
+ top: 0,
1694
+ left: 0,
1695
+ right: 0,
1696
+ bottom: 0,
1697
+ justifyContent: "flex-end"
1698
+ },
1310
1699
  testID: "body-map-detail-panel-root",
1311
1700
  children: [
1312
1701
  /* @__PURE__ */ jsx(
@@ -1441,8 +1830,22 @@ function BodyMapDetailPanel({
1441
1830
  style: { marginBottom: 6 },
1442
1831
  accessibilityElementsHidden: true,
1443
1832
  children: [
1444
- /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary", style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" }, children: `MEV ${landmarks.mev}` }),
1445
- /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary", style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" }, children: `MRV ${landmarks.mrv}` })
1833
+ /* @__PURE__ */ jsx(
1834
+ Text,
1835
+ {
1836
+ className: "text-text-tertiary",
1837
+ style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" },
1838
+ children: `MEV ${landmarks.mev}`
1839
+ }
1840
+ ),
1841
+ /* @__PURE__ */ jsx(
1842
+ Text,
1843
+ {
1844
+ className: "text-text-tertiary",
1845
+ style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" },
1846
+ children: `MRV ${landmarks.mrv}`
1847
+ }
1848
+ )
1446
1849
  ]
1447
1850
  }
1448
1851
  ),
@@ -1477,7 +1880,8 @@ function BodyMapDetailPanel({
1477
1880
  height: 14,
1478
1881
  borderRadius: 7,
1479
1882
  borderWidth: 2,
1480
- boxShadow: "0 0 4px rgba(0,0,0,0.5)"
1883
+ // A knob resting on the volume bar: lift, with the ring as its edge.
1884
+ ...liftStyle(1, "dark", { rim: 0 })
1481
1885
  },
1482
1886
  accessibilityElementsHidden: true,
1483
1887
  testID: "body-map-detail-panel-volume-marker"
@@ -1560,7 +1964,12 @@ function BodyMapDetailPanel({
1560
1964
  Text,
1561
1965
  {
1562
1966
  className: "text-text-primary",
1563
- style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600" },
1967
+ style: {
1968
+ flex: 1,
1969
+ fontSize: 13,
1970
+ fontFamily: "Inter, sans-serif",
1971
+ fontWeight: "600"
1972
+ },
1564
1973
  testID: `body-map-detail-panel-contributing-${index}-name`,
1565
1974
  children: exercise.name
1566
1975
  }
@@ -1604,7 +2013,12 @@ function BodyMapDetailPanel({
1604
2013
  Text,
1605
2014
  {
1606
2015
  className: "text-text-primary",
1607
- style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600" },
2016
+ style: {
2017
+ flex: 1,
2018
+ fontSize: 13,
2019
+ fontFamily: "Inter, sans-serif",
2020
+ fontWeight: "600"
2021
+ },
1608
2022
  testID: `body-map-detail-panel-upcoming-${index}-name`,
1609
2023
  children: exercise.name
1610
2024
  }
@@ -1639,7 +2053,18 @@ function BodyMapDetailPanel({
1639
2053
  borderColor: "rgba(255,121,0,0.3)"
1640
2054
  },
1641
2055
  testID: "body-map-detail-panel-view-exercises",
1642
- children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "700", color: BRAND_PRIMARY3 }, children: "View exercises" })
2056
+ children: /* @__PURE__ */ jsx(
2057
+ Text,
2058
+ {
2059
+ style: {
2060
+ fontSize: 13,
2061
+ fontFamily: "Inter, sans-serif",
2062
+ fontWeight: "700",
2063
+ color: BRAND_PRIMARY2
2064
+ },
2065
+ children: "View exercises"
2066
+ }
2067
+ )
1643
2068
  }
1644
2069
  )
1645
2070
  ]
@@ -1652,439 +2077,81 @@ function BodyMapDetailPanel({
1652
2077
  }
1653
2078
  );
1654
2079
  }
1655
-
1656
- // src/theme/color-utils.ts
1657
- function hexToRgb(hex) {
1658
- const cleaned = hex.replace("#", "");
1659
- let r, g, b;
1660
- if (cleaned.length === 3) {
1661
- r = parseInt(cleaned[0] + cleaned[0], 16);
1662
- g = parseInt(cleaned[1] + cleaned[1], 16);
1663
- b = parseInt(cleaned[2] + cleaned[2], 16);
1664
- } else if (cleaned.length === 6) {
1665
- r = parseInt(cleaned.slice(0, 2), 16);
1666
- g = parseInt(cleaned.slice(2, 4), 16);
1667
- b = parseInt(cleaned.slice(4, 6), 16);
1668
- } else {
1669
- return null;
1670
- }
1671
- return { r, g, b };
1672
- }
1673
- function rgbToHsv(r, g, b) {
1674
- const rNorm = r / 255;
1675
- const gNorm = g / 255;
1676
- const bNorm = b / 255;
1677
- const max = Math.max(rNorm, gNorm, bNorm);
1678
- const min = Math.min(rNorm, gNorm, bNorm);
1679
- const delta = max - min;
1680
- const v = max;
1681
- const s = max === 0 ? 0 : delta / max;
1682
- let h = 0;
1683
- if (delta !== 0) {
1684
- if (max === rNorm) {
1685
- h = 60 * ((gNorm - bNorm) / delta % 6);
1686
- } else if (max === gNorm) {
1687
- h = 60 * ((bNorm - rNorm) / delta + 2);
1688
- } else {
1689
- h = 60 * ((rNorm - gNorm) / delta + 4);
1690
- }
1691
- }
1692
- if (h < 0) h += 360;
1693
- return { h, s, v };
1694
- }
1695
- function hsvToRgb(h, s, v) {
1696
- const c = v * s;
1697
- const x = c * (1 - Math.abs(h / 60 % 2 - 1));
1698
- const m = v - c;
1699
- let rPrime, gPrime, bPrime;
1700
- if (h >= 0 && h < 60) {
1701
- rPrime = c;
1702
- gPrime = x;
1703
- bPrime = 0;
1704
- } else if (h >= 60 && h < 120) {
1705
- rPrime = x;
1706
- gPrime = c;
1707
- bPrime = 0;
1708
- } else if (h >= 120 && h < 180) {
1709
- rPrime = 0;
1710
- gPrime = c;
1711
- bPrime = x;
1712
- } else if (h >= 180 && h < 240) {
1713
- rPrime = 0;
1714
- gPrime = x;
1715
- bPrime = c;
1716
- } else if (h >= 240 && h < 300) {
1717
- rPrime = x;
1718
- gPrime = 0;
1719
- bPrime = c;
1720
- } else {
1721
- rPrime = c;
1722
- gPrime = 0;
1723
- bPrime = x;
1724
- }
1725
- return {
1726
- r: Math.round((rPrime + m) * 255),
1727
- g: Math.round((gPrime + m) * 255),
1728
- b: Math.round((bPrime + m) * 255)
1729
- };
2080
+ var DEFAULT_CONTEXT = { mode: "dark", level: "base" };
2081
+ var SurfaceContext = createContext(DEFAULT_CONTEXT);
2082
+ function useSurface() {
2083
+ return useContext(SurfaceContext);
1730
2084
  }
1731
- function rgbToHex(r, g, b) {
1732
- const toHex = (n) => {
1733
- const clamped = Math.max(0, Math.min(255, Math.round(n)));
1734
- return clamped.toString(16).padStart(2, "0");
1735
- };
1736
- return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
1737
- }
1738
- function lighten(hex, amount = 0.1) {
1739
- const rgb = hexToRgb(hex);
1740
- if (!rgb) return hex;
1741
- const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
1742
- const newV = Math.min(1, hsv.v + amount);
1743
- const newRgb = hsvToRgb(hsv.h, hsv.s, newV);
1744
- return rgbToHex(newRgb.r, newRgb.g, newRgb.b);
1745
- }
1746
- var elevationSystem = {
1747
- // Deep inset (recessed input fields, deeply pressed buttons)
1748
- [-2]: {
1749
- name: "deep-inset",
1750
- colorAdjustment: 0,
1751
- shadowIntensity: "strong",
1752
- shadowStyle: "pressed",
1753
- description: "Deeply recessed elements (e.g., input fields, deeply pressed buttons)"
1754
- },
1755
- // Shallow inset (pressed buttons, sunken panels)
1756
- [-1]: {
1757
- name: "inset",
1758
- colorAdjustment: 0,
1759
- shadowIntensity: "medium",
1760
- shadowStyle: "pressed",
1761
- description: "Shallow inset elements (e.g., pressed buttons, sunken panels within cards)"
1762
- },
1763
- // Base level (page background, default surface)
1764
- [0]: {
1765
- name: "base",
1766
- colorAdjustment: 0,
1767
- shadowIntensity: "subtle",
1768
- shadowStyle: "raised",
1769
- description: "Base surface level (page background, default containers)"
1770
- },
1771
- // Level 1: Subtle elevation (outline cards, subtle containers)
1772
- [1]: {
1773
- name: "subtle",
1774
- // The whole ladder was re-spaced in TD-07.16. It used to run
1775
- // 0.01/0.02/0.04/0.06/0.08, where the first step was ~2 RGB values — under
1776
- // the perceptual floor, so level 1 existed in the type system and nowhere on
1777
- // screen. With drop-shadow now gated off below FLOATING_ELEVATION_MIN, TONE
1778
- // is the only thing separating 0-3, so every step has to actually land.
1779
- // Even 0.025 spacing, verified in elevation.test.ts as ΔL* > 1 per step.
1780
- colorAdjustment: 0.025,
1781
- shadowIntensity: "subtle",
1782
- shadowStyle: "raised",
1783
- description: "Subtle elevation (outline cards, subtle containers)"
1784
- },
1785
- // Level 2: Standard elevation (default cards, buttons)
1786
- [2]: {
1787
- name: "standard",
1788
- colorAdjustment: 0.05,
1789
- shadowIntensity: "medium",
1790
- shadowStyle: "raised",
1791
- description: "Standard elevation (default cards, raised buttons)"
1792
- },
1793
- // Level 3: Prominent elevation (important cards, modals)
1794
- [3]: {
1795
- name: "prominent",
1796
- colorAdjustment: 0.075,
1797
- shadowIntensity: "strong",
1798
- shadowStyle: "raised",
1799
- description: "Prominent elevation (important cards, modals, dropdowns)"
1800
- },
1801
- // Level 4: High elevation (overlays, popovers)
1802
- [4]: {
1803
- name: "high",
1804
- colorAdjustment: 0.1,
1805
- shadowIntensity: "strong",
1806
- shadowStyle: "raised",
1807
- description: "High elevation (overlays, popovers, tooltips)"
1808
- },
1809
- // Level 5: Floating (toasts, floating action buttons)
1810
- [5]: {
1811
- name: "floating",
1812
- colorAdjustment: 0.13,
1813
- shadowIntensity: "strong",
1814
- shadowStyle: "raised",
1815
- description: "Floating elevation (toasts, floating action buttons, highest z-index)"
1816
- }
1817
- };
1818
- function calculateRimLightColor(baseColor, level) {
1819
- const rgb = hexToRgb(baseColor);
1820
- if (!rgb) {
1821
- return "rgba(255, 255, 255, 0.5)";
1822
- }
1823
- const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
1824
- const isLight = hsv.v > 0.6;
1825
- const isSaturated = hsv.s > 0.3;
1826
- const absLevel = Math.abs(level);
1827
- const opacityBoost = Math.max(0, (absLevel - 1) * 0.05);
1828
- if (isSaturated) {
1829
- const rimLightValue = 0.95;
1830
- const rimLightRgb = hsvToRgb(hsv.h, hsv.s * 0.3, rimLightValue);
1831
- const baseOpacity = isLight ? 0.9 : 0.5;
1832
- const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
1833
- return `rgba(${rimLightRgb.r}, ${rimLightRgb.g}, ${rimLightRgb.b}, ${finalOpacity.toFixed(2)})`;
1834
- } else {
1835
- const baseOpacity = isLight ? 0.9 : 0.12;
1836
- const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
1837
- return `rgba(255, 255, 255, ${finalOpacity.toFixed(2)})`;
1838
- }
2085
+ function recessDepth(inherited, planesDown, mode) {
2086
+ let plane = inherited.level;
2087
+ for (let i = 0; i < planesDown; i++) plane = pressedLevel(plane);
2088
+ const backgroundColor = surfaceBackground(plane, mode);
2089
+ return { plane, backgroundColor, depthStyle: getPressedRecessShadow(backgroundColor, mode) };
1839
2090
  }
1840
- function calculateDarkShadowColors(surfaceColor) {
1841
- const rgb = hexToRgb(surfaceColor);
1842
- if (!rgb) {
1843
- return {
1844
- dark: "rgba(0, 0, 0, 0.3)",
1845
- darker: "rgba(0, 0, 0, 0.4)"
1846
- };
2091
+ function resolveSurfaceDepth(inherited, props) {
2092
+ const mode = props.theme ?? inherited.mode;
2093
+ const elevation = props.elevation ?? 0;
2094
+ if (props.pressed || elevation < 0) {
2095
+ const down = props.pressed ? 1 : -elevation;
2096
+ return { mode, step: 0, lifted: false, ...recessDepth(inherited, down, mode) };
1847
2097
  }
1848
- const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
1849
- const isLight = hsv.v > 0.6;
1850
- const isSaturated = hsv.s > 0.3;
1851
- if (isSaturated) {
1852
- const darkShadowValue = 0.15;
1853
- const darkShadowRgb = hsvToRgb(hsv.h, hsv.s, darkShadowValue);
1854
- if (isLight) {
1855
- return {
1856
- dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.3)`,
1857
- darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.4)`
1858
- };
1859
- } else {
1860
- return {
1861
- dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.5)`,
1862
- darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.6)`
1863
- };
1864
- }
1865
- } else {
1866
- if (isLight) {
1867
- return {
1868
- dark: "rgba(0, 0, 0, 0.2)",
1869
- darker: "rgba(0, 0, 0, 0.3)"
1870
- };
1871
- } else {
1872
- return {
1873
- dark: "rgba(0, 0, 0, 0.5)",
1874
- darker: "rgba(0, 0, 0, 0.6)"
1875
- };
1876
- }
1877
- }
1878
- }
1879
- function getRimLightConfig() {
1880
- return {
1881
- offset: 1,
1882
- // Fixed 1px for crisp rim
1883
- blur: 1
1884
- // Tight blur for crisp edge
1885
- };
1886
- }
1887
- var elevationSurfaceCache = /* @__PURE__ */ new Map();
1888
- var MAX_CACHE_SIZE = 100;
1889
- function getCacheKey(baseColor, level, theme) {
1890
- return `${baseColor}-${level}-${theme}`;
2098
+ const step = props.level != null ? 0 : props.raise ?? elevation;
2099
+ const floating = step >= FLOATING_ELEVATION_MIN;
2100
+ const plane = props.level ?? (floating ? "overlay" : raisedLevel(inherited.level, step));
2101
+ const lifted = props.lift ?? step > 0;
2102
+ const liftStep = Math.max(1, Math.min(5, step));
2103
+ const depthStyle = lifted ? liftStyle(liftStep, mode, props.liftOptions) : {};
2104
+ return { mode, plane, backgroundColor: surfaceBackground(plane, mode), depthStyle, step, lifted };
1891
2105
  }
1892
- function calculateElevationSurface(baseColor, level, theme) {
1893
- const config = elevationSystem[level];
1894
- if (config.colorAdjustment === 0) {
1895
- return baseColor;
1896
- }
1897
- if (level < 0) {
1898
- return baseColor;
1899
- }
1900
- return lighten(baseColor, config.colorAdjustment);
1901
- }
1902
- function getElevationSurface(baseColor, level, theme) {
1903
- const cacheKey = getCacheKey(baseColor, level, theme);
1904
- if (elevationSurfaceCache.has(cacheKey)) {
1905
- return elevationSurfaceCache.get(cacheKey);
1906
- }
1907
- const result = calculateElevationSurface(baseColor, level);
1908
- if (elevationSurfaceCache.size >= MAX_CACHE_SIZE) {
1909
- const firstKey = elevationSurfaceCache.keys().next().value;
1910
- elevationSurfaceCache.delete(firstKey);
1911
- }
1912
- elevationSurfaceCache.set(cacheKey, result);
1913
- return result;
1914
- }
1915
- var elevationShadowCache = /* @__PURE__ */ new Map();
1916
- var MAX_SHADOW_CACHE_SIZE = 50;
1917
- function getShadowCacheKey(baseColor, level, theme, isHovered) {
1918
- return `${baseColor}-${level}-${theme}-${isHovered}`;
1919
- }
1920
- function calculateElevationShadow(baseColor, level, theme, isHovered = false) {
1921
- const config = elevationSystem[level];
1922
- if (level === 0) {
1923
- return {};
1924
- }
1925
- const elevatedSurfaceColor = calculateElevationSurface(baseColor, level);
1926
- const rimLightColor = calculateRimLightColor(baseColor, level);
1927
- const darkShadowColors = calculateDarkShadowColors(elevatedSurfaceColor);
1928
- const intensityConfig = {
1929
- subtle: { offset: 1, blur: 2 },
1930
- medium: { offset: 2, blur: 4 },
1931
- strong: { offset: 2, blur: 5 }
1932
- };
1933
- const { offset, blur } = intensityConfig[config.shadowIntensity];
1934
- const rimConfig = getRimLightConfig();
1935
- if (config.shadowStyle === "pressed") {
1936
- if (isHovered) {
1937
- const hoverOffset = Math.max(1, Math.round(offset / 2));
1938
- const hoverBlur = Math.max(1, Math.round(blur / 2));
1939
- return Platform.select({
1940
- web: {
1941
- boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
1942
- },
1943
- default: {
1944
- shadowOpacity: 0,
1945
- elevation: 0
1946
- }
1947
- });
1948
- }
1949
- return Platform.select({
1950
- web: {
1951
- boxShadow: `inset ${offset}px ${offset}px ${blur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
1952
- },
1953
- default: {
1954
- shadowOpacity: 0,
1955
- elevation: 0
1956
- }
1957
- });
1958
- } else {
1959
- if (isHovered) {
1960
- const hoverOffset = Math.max(1, Math.round(offset / 2));
1961
- const hoverBlur = Math.max(1, Math.round(blur / 2));
1962
- return Platform.select({
1963
- web: {
1964
- boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
1965
- },
1966
- default: {
1967
- shadowColor: "#000",
1968
- shadowOffset: { width: hoverOffset, height: hoverOffset },
1969
- shadowOpacity: 0.2,
1970
- shadowRadius: hoverBlur / 2,
1971
- elevation: hoverOffset
1972
- }
1973
- });
1974
- }
1975
- return Platform.select({
1976
- web: {
1977
- boxShadow: `${offset}px ${offset}px ${blur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
1978
- },
1979
- default: {
1980
- shadowColor: "#000",
1981
- shadowOffset: { width: offset, height: offset },
1982
- shadowOpacity: 0.3,
1983
- shadowRadius: blur / 2,
1984
- elevation: offset
1985
- }
1986
- });
1987
- }
1988
- }
1989
- var FLOATING_ELEVATION_MIN = 4;
1990
- function getElevationShadow(baseColor, level, theme, isHovered = false) {
1991
- const cacheKey = getShadowCacheKey(baseColor, level, theme, isHovered);
1992
- if (elevationShadowCache.has(cacheKey)) {
1993
- return elevationShadowCache.get(cacheKey);
1994
- }
1995
- const result = level > 0 && level < FLOATING_ELEVATION_MIN ? {} : calculateElevationShadow(baseColor, level, theme, isHovered);
1996
- if (elevationShadowCache.size >= MAX_SHADOW_CACHE_SIZE) {
1997
- const firstKey = elevationShadowCache.keys().next().value;
1998
- elevationShadowCache.delete(firstKey);
1999
- }
2000
- elevationShadowCache.set(cacheKey, result);
2001
- return result;
2002
- }
2003
- function getBaseSurfaceColor(theme) {
2004
- return theme === "light" ? semanticColorsLight["surface-raised"] : semanticColorsDark["surface-elevated"];
2005
- }
2006
- var componentElevationRanges = {
2007
- button: {
2008
- allowed: [2],
2009
- default: 2,
2010
- hover: 3
2011
- },
2012
- card: {
2013
- allowed: [1, 2, 3],
2014
- default: 2,
2015
- hover: 3
2016
- },
2017
- input: {
2018
- allowed: [-2, -1, 0],
2019
- default: -1
2020
- },
2021
- overlay: {
2022
- allowed: [4, 5],
2023
- default: 4
2024
- }
2025
- };
2026
- function getValidatedElevation(component, requested) {
2027
- const range = componentElevationRanges[component];
2028
- if (range.allowed.includes(requested)) {
2029
- return requested;
2030
- }
2031
- const sorted = [...range.allowed].sort((a, b) => a - b);
2032
- if (requested < sorted[0]) return sorted[0];
2033
- if (requested > sorted[sorted.length - 1]) return sorted[sorted.length - 1];
2034
- return sorted.reduce(
2035
- (prev, curr) => Math.abs(curr - requested) < Math.abs(prev - requested) ? curr : prev
2106
+ function useResolvedSurface(props) {
2107
+ const inherited = useSurface();
2108
+ const { level, raise, elevation, pressed, lift, liftOptions, theme } = props;
2109
+ return useMemo(
2110
+ () => resolveSurfaceDepth(inherited, {
2111
+ level,
2112
+ raise,
2113
+ elevation,
2114
+ pressed,
2115
+ lift,
2116
+ liftOptions,
2117
+ theme
2118
+ }),
2119
+ [inherited, level, raise, elevation, pressed, lift, liftOptions, theme]
2036
2120
  );
2037
2121
  }
2038
- function getTheme() {
2039
- if (typeof document === "undefined") return "dark";
2040
- return document.documentElement.classList.contains("light") ? "light" : "dark";
2041
- }
2042
- var listeners = [];
2043
- function subscribe(listener) {
2044
- listeners = [...listeners, listener];
2045
- if (typeof document !== "undefined" && listeners.length === 1) {
2046
- const observer = new MutationObserver((mutations) => {
2047
- for (const mutation of mutations) {
2048
- if (mutation.type === "attributes" && mutation.attributeName === "class") {
2049
- listeners.forEach((l) => l());
2050
- }
2051
- }
2052
- });
2053
- observer.observe(document.documentElement, {
2054
- attributes: true,
2055
- attributeFilter: ["class"]
2056
- });
2057
- subscribe._observer = observer;
2058
- }
2059
- return () => {
2060
- listeners = listeners.filter((l) => l !== listener);
2061
- if (listeners.length === 0 && subscribe._observer) {
2062
- subscribe._observer.disconnect();
2063
- subscribe._observer = null;
2064
- }
2065
- };
2066
- }
2067
- function getSnapshot() {
2068
- return getTheme();
2069
- }
2070
- function getServerSnapshot() {
2071
- return "dark";
2072
- }
2073
- function useTheme() {
2074
- return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2075
- }
2076
2122
 
2077
2123
  // src/components/ui/card/Card.tsx
2078
- var variantStyles = {
2124
+ var EDGE_CLASS = {
2079
2125
  elevated: "",
2080
- // Will be set dynamically via elevation system
2081
- outline: "border-2 border-hairline-strong",
2082
- // Thicker border with stronger contrast
2126
+ accent: "",
2083
2127
  filled: "",
2084
- // Will be set dynamically via elevation system
2085
- accent: "border border-hairline",
2128
+ outline: "border border-hairline-strong",
2086
2129
  subtle: "border border-hairline-subtle"
2087
2130
  };
2131
+ var LIFTED = {
2132
+ elevated: true,
2133
+ accent: true,
2134
+ filled: false,
2135
+ outline: false,
2136
+ subtle: false
2137
+ };
2138
+ var STAYS_ON_HOST = {
2139
+ elevated: false,
2140
+ accent: false,
2141
+ filled: false,
2142
+ outline: true,
2143
+ subtle: true
2144
+ };
2145
+ function useCardDepth(variant, elevation, hovered) {
2146
+ const raise = STAYS_ON_HOST[variant] ? void 0 : elevation;
2147
+ const resolved = useResolvedSurface({ raise, lift: LIFTED[variant] });
2148
+ const depthStyle = useMemo(() => {
2149
+ if (!hovered || !LIFTED[variant]) return resolved.depthStyle;
2150
+ const hoverStep = Math.min(3, resolved.step + 1);
2151
+ return liftStyle(hoverStep, resolved.mode);
2152
+ }, [hovered, variant, resolved]);
2153
+ return { ...resolved, depthStyle };
2154
+ }
2088
2155
  function Card({
2089
2156
  variant = "elevated",
2090
2157
  elevation = 2,
@@ -2105,89 +2172,54 @@ function Card({
2105
2172
  }) {
2106
2173
  const isClickable = isInteractive || !!onPress;
2107
2174
  const [isHovered, setIsHovered] = useState(false);
2108
- const theme = useTheme();
2109
- const elevationLevel = useMemo(() => {
2110
- const validated = getValidatedElevation("card", elevation);
2111
- if (variant === "outline" || variant === "accent" || variant === "subtle") {
2112
- return 1;
2113
- }
2114
- return validated;
2115
- }, [variant, elevation]);
2116
- const baseColor = useMemo(() => getBaseSurfaceColor(theme), [theme]);
2117
- const surfaceColor = useMemo(() => {
2118
- if ((variant === "outline" || variant === "accent") && theme === "light") {
2119
- return "#FAFAFA";
2120
- }
2121
- if (variant === "subtle") {
2122
- return getElevationSurface(baseColor, 0, theme);
2123
- }
2124
- return getElevationSurface(baseColor, elevationLevel, theme);
2125
- }, [baseColor, elevationLevel, theme, variant]);
2126
- const shadowStyle = useMemo(() => {
2127
- const shouldHover = isHovered && isClickable;
2128
- return getElevationShadow(baseColor, elevationLevel, theme, shouldHover);
2129
- }, [baseColor, elevationLevel, theme, isHovered, isClickable]);
2130
- const cardContent = isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
2131
- skeletonHasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
2132
- /* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
2133
- /* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
2134
- ] }),
2135
- /* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: skeletonContentLines }).map((_, i) => /* @__PURE__ */ jsx(
2136
- View,
2137
- {
2138
- className: cn(
2139
- "h-4 bg-interactive-disabled rounded",
2140
- i < skeletonContentLines - 1 ? "mb-2 w-full" : "w-4/5"
2141
- )
2142
- },
2143
- i
2144
- )) }),
2145
- skeletonHasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
2146
- ] }) : children;
2175
+ const depth = useCardDepth(variant, elevation, isHovered && isClickable);
2147
2176
  const baseClassName = cn(
2148
2177
  "rounded-lg overflow-hidden relative",
2149
- // Apply variant styles, but only use default border color if no custom borderColor
2150
- variant === "outline" ? borderColor ? "border-2" : variantStyles[variant] : variantStyles[variant],
2151
- // Remove Tailwind shadow classes - we're using elevation shadows via style prop
2178
+ borderColor ? "border" : EDGE_CLASS[variant],
2152
2179
  isClickable && "web:cursor-pointer web:transition-all web:duration-150",
2153
2180
  isClickable && "web:hover:-translate-y-0.5 active:scale-[0.99]",
2154
2181
  isLoading && "pointer-events-none animate-pulse",
2155
2182
  className
2156
2183
  );
2157
- const accentStyle = useMemo(() => variant === "accent" ? {
2158
- borderLeftWidth: accentWidth ?? 3,
2159
- borderLeftColor: accentColor ?? "var(--color-brand-primary)"
2160
- } : {}, [variant, accentWidth, accentColor]);
2161
2184
  const mergedStyle = useMemo(() => {
2162
- const elevationStyle = {
2163
- backgroundColor: bgColor || surfaceColor,
2185
+ const own = {
2186
+ backgroundColor: bgColor || depth.backgroundColor,
2164
2187
  borderRadius: 8,
2165
2188
  overflow: "hidden",
2166
- ...shadowStyle,
2167
- ...accentStyle
2189
+ ...depth.depthStyle
2168
2190
  };
2169
- if (borderColor) {
2170
- elevationStyle.borderColor = borderColor;
2191
+ if (variant === "accent") {
2192
+ own.borderLeftWidth = accentWidth ?? 3;
2193
+ own.borderLeftColor = accentColor ?? "var(--color-brand-primary)";
2171
2194
  }
2172
- if (!style) return elevationStyle;
2173
- return [elevationStyle, style];
2174
- }, [style, surfaceColor, shadowStyle, borderColor, bgColor, accentStyle]);
2175
- if (isClickable) {
2176
- return /* @__PURE__ */ jsx(
2177
- Pressable,
2178
- {
2179
- onPress,
2180
- onHoverIn: () => setIsHovered(true),
2181
- onHoverOut: () => setIsHovered(false),
2182
- accessibilityRole: "button",
2183
- className: baseClassName,
2184
- style: mergedStyle,
2185
- ...props,
2186
- children: cardContent
2187
- }
2188
- );
2189
- }
2190
- return /* @__PURE__ */ jsx(View, { className: baseClassName, style: mergedStyle, ...props, children: cardContent });
2195
+ if (borderColor) own.borderColor = borderColor;
2196
+ return style ? [own, style] : own;
2197
+ }, [style, depth, bgColor, borderColor, variant, accentWidth, accentColor]);
2198
+ const context = useMemo(
2199
+ () => ({ mode: depth.mode, level: depth.plane }),
2200
+ [depth.mode, depth.plane]
2201
+ );
2202
+ const content = isLoading ? /* @__PURE__ */ jsx(
2203
+ SkeletonBody,
2204
+ {
2205
+ hasHeader: skeletonHasHeader,
2206
+ hasFooter: skeletonHasFooter,
2207
+ contentLines: skeletonContentLines
2208
+ }
2209
+ ) : children;
2210
+ return /* @__PURE__ */ jsx(SurfaceContext.Provider, { value: context, children: isClickable ? /* @__PURE__ */ jsx(
2211
+ Pressable,
2212
+ {
2213
+ onPress,
2214
+ onHoverIn: () => setIsHovered(true),
2215
+ onHoverOut: () => setIsHovered(false),
2216
+ accessibilityRole: "button",
2217
+ className: baseClassName,
2218
+ style: mergedStyle,
2219
+ ...props,
2220
+ children: content
2221
+ }
2222
+ ) : /* @__PURE__ */ jsx(View, { className: baseClassName, style: mergedStyle, ...props, children: content }) });
2191
2223
  }
2192
2224
  function CardHeader({ children, className }) {
2193
2225
  return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-6", className), children });
@@ -2198,60 +2230,122 @@ function CardContent({ children, className }) {
2198
2230
  function CardFooter({ children, className }) {
2199
2231
  return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4 flex-row items-center gap-2", className), children });
2200
2232
  }
2201
- var t2 = getSemanticColors("dark");
2202
- var solidVariantColors = {
2203
- success: t2["status-success"],
2204
- warning: t2["status-warning"],
2205
- error: t2["status-error"],
2206
- neutral: greyRamp[500]
2207
- };
2208
- var ringVariantStyles = {
2209
- "on-track": {
2210
- backgroundColor: "rgba(46,213,115,0.15)",
2211
- borderWidth: 1,
2212
- borderColor: "rgba(46,213,115,0.3)"
2213
- },
2214
- deviation: {
2215
- backgroundColor: "rgba(245,158,11,0.15)",
2216
- borderWidth: 1,
2217
- borderColor: "rgba(245,158,11,0.25)"
2218
- },
2219
- future: {
2220
- backgroundColor: "rgba(107,114,128,0.1)",
2221
- borderWidth: 1,
2222
- borderStyle: "dashed",
2223
- borderColor: "rgba(107,114,128,0.2)"
2233
+ function SkeletonBody({ hasHeader, hasFooter, contentLines }) {
2234
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
2235
+ hasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
2236
+ /* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
2237
+ /* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
2238
+ ] }),
2239
+ /* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: contentLines }).map((_, i) => /* @__PURE__ */ jsx(
2240
+ View,
2241
+ {
2242
+ className: cn(
2243
+ "h-4 bg-interactive-disabled rounded",
2244
+ i < contentLines - 1 ? "mb-2 w-full" : "w-4/5"
2245
+ )
2246
+ },
2247
+ i
2248
+ )) }),
2249
+ hasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
2250
+ ] });
2251
+ }
2252
+
2253
+ // src/utils/colors.ts
2254
+ function alpha(color, opacity) {
2255
+ const clampedOpacity = Math.max(0, Math.min(1, opacity));
2256
+ if (color.startsWith("#")) {
2257
+ const hex = color.slice(1);
2258
+ let r, g, b;
2259
+ if (hex.length === 3) {
2260
+ r = parseInt(hex[0] + hex[0], 16);
2261
+ g = parseInt(hex[1] + hex[1], 16);
2262
+ b = parseInt(hex[2] + hex[2], 16);
2263
+ } else if (hex.length === 6) {
2264
+ r = parseInt(hex.slice(0, 2), 16);
2265
+ g = parseInt(hex.slice(2, 4), 16);
2266
+ b = parseInt(hex.slice(4, 6), 16);
2267
+ } else {
2268
+ return color;
2269
+ }
2270
+ return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
2271
+ }
2272
+ const rgbMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
2273
+ if (rgbMatch) {
2274
+ const [, r, g, b] = rgbMatch;
2275
+ return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
2224
2276
  }
2277
+ const rgbaMatch = color.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/);
2278
+ if (rgbaMatch) {
2279
+ const [, r, g, b] = rgbaMatch;
2280
+ return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
2281
+ }
2282
+ return color;
2283
+ }
2284
+
2285
+ // src/components/custom/Workout/StatusDot.tsx
2286
+ var solidFillToken = {
2287
+ success: "status-success",
2288
+ warning: "status-warning",
2289
+ error: "status-error",
2290
+ neutral: "text-tertiary"
2225
2291
  };
2226
- var glowStyles = {
2227
- success: { boxShadow: "0 0 4px rgba(46,213,115,0.4)" },
2228
- warning: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
2229
- error: { boxShadow: "0 0 4px rgba(239,68,68,0.4)" },
2230
- neutral: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" },
2231
- "on-track": { boxShadow: "0 0 4px rgba(46,213,115,0.4)" },
2232
- deviation: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
2233
- future: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" }
2292
+ var ringWashToken = {
2293
+ "on-track": { fill: "status-success-subtle", border: "status-success-muted" },
2294
+ deviation: { fill: "status-warning-subtle", border: "status-warning-muted" }
2234
2295
  };
2296
+ var FUTURE_FILL = alpha(greyRamp[500], 0.1);
2297
+ var FUTURE_BORDER = alpha(greyRamp[500], 0.2);
2298
+ var glyphToken = {
2299
+ success: "text-inverse",
2300
+ warning: "text-inverse",
2301
+ error: "text-inverse",
2302
+ neutral: "text-inverse",
2303
+ "on-track": "status-success",
2304
+ deviation: "status-warning",
2305
+ future: "text-tertiary"
2306
+ };
2307
+ var glowColors2 = {
2308
+ success: semanticColorsDark["status-success"],
2309
+ warning: semanticColorsDark["status-warning"],
2310
+ error: semanticColorsDark["status-error"],
2311
+ neutral: greyRamp[500],
2312
+ "on-track": semanticColorsDark["status-success"],
2313
+ deviation: semanticColorsDark["status-warning"],
2314
+ future: greyRamp[500]
2315
+ };
2316
+ var glowStyles = Object.fromEntries(
2317
+ Object.entries(glowColors2).map(([variant, color]) => [variant, getGlowShadow(color, "subtle")])
2318
+ );
2235
2319
  var iconChars = {
2236
2320
  check: "\u2713",
2237
2321
  exclamation: "!",
2238
2322
  dash: "\u2014"
2239
2323
  };
2240
- var iconColors = {
2241
- success: "#0A5C52",
2242
- warning: "#6B4000",
2243
- error: "#5C1A1A",
2244
- neutral: greyRamp[200],
2245
- "on-track": t2["status-success"],
2246
- deviation: t2["status-warning"],
2247
- future: greyRamp[500]
2248
- };
2249
2324
  var sizeDimensions = {
2250
2325
  sm: { size: 8, showIcon: false },
2251
2326
  md: { size: 18, showIcon: true }
2252
2327
  };
2253
2328
  function isSolidVariant(variant) {
2254
- return variant in solidVariantColors;
2329
+ return variant in solidFillToken;
2330
+ }
2331
+ function ringStyle(variant) {
2332
+ if (variant === "future") {
2333
+ return {
2334
+ backgroundColor: FUTURE_FILL,
2335
+ borderWidth: 1,
2336
+ borderStyle: "dashed",
2337
+ borderColor: FUTURE_BORDER
2338
+ };
2339
+ }
2340
+ if (variant === "on-track" || variant === "deviation") {
2341
+ const tokens = ringWashToken[variant];
2342
+ return {
2343
+ backgroundColor: resolveColor(tokens.fill),
2344
+ borderWidth: 1,
2345
+ borderColor: resolveColor(tokens.border)
2346
+ };
2347
+ }
2348
+ return void 0;
2255
2349
  }
2256
2350
  function StatusDot({
2257
2351
  variant,
@@ -2264,7 +2358,7 @@ function StatusDot({
2264
2358
  }) {
2265
2359
  const config = sizeDimensions[size];
2266
2360
  const solid = isSolidVariant(variant);
2267
- const ring = ringVariantStyles[variant];
2361
+ const ring = ringStyle(variant);
2268
2362
  const glowStyle = glow ? glowStyles[variant] : null;
2269
2363
  const dot = /* @__PURE__ */ jsx(
2270
2364
  View,
@@ -2278,22 +2372,22 @@ function StatusDot({
2278
2372
  justifyContent: "center",
2279
2373
  flexShrink: 0
2280
2374
  },
2281
- solid ? { backgroundColor: solidVariantColors[variant] } : void 0,
2282
- ring ? ring : void 0,
2375
+ solid ? { backgroundColor: resolveColor(solidFillToken[variant]) } : void 0,
2376
+ ring,
2283
2377
  glowStyle ? glowStyle : void 0
2284
2378
  ],
2285
2379
  accessibilityRole: "image",
2286
2380
  accessibilityLabel: `${variant} status`,
2287
2381
  testID: "status-dot",
2288
- children: config.showIcon && icon && /* @__PURE__ */ jsx(
2289
- Text,
2382
+ children: config.showIcon && icon && // The glyph was 11px/900, off the type scale (TOKENS.md §4); `boldLabel` is
2383
+ // the 12px sans label step and `font-black` keeps the original weight.
2384
+ /* @__PURE__ */ jsx(
2385
+ Typography,
2290
2386
  {
2291
- style: {
2292
- fontSize: 11,
2293
- lineHeight: 11,
2294
- fontWeight: "900",
2295
- color: iconColors[variant]
2296
- },
2387
+ variant: "boldLabel",
2388
+ color: "inherit",
2389
+ className: "font-black leading-none",
2390
+ style: { color: resolveColor(glyphToken[variant]) },
2297
2391
  accessibilityElementsHidden: true,
2298
2392
  children: iconChars[icon]
2299
2393
  }
@@ -2311,9 +2405,11 @@ function StatusDot({
2311
2405
  children: [
2312
2406
  /* @__PURE__ */ jsx(View, { accessibilityElementsHidden: true, children: dot }),
2313
2407
  /* @__PURE__ */ jsx(
2314
- Text,
2408
+ Typography,
2315
2409
  {
2316
- style: { fontSize: 12, lineHeight: 16, color: greyRamp[400] },
2410
+ variant: "caption",
2411
+ color: "secondary",
2412
+ className: "leading-4",
2317
2413
  accessibilityElementsHidden: true,
2318
2414
  children: label
2319
2415
  }
@@ -2329,13 +2425,13 @@ var MESO_ACCENT_GRADIENT_LIGHT = primitiveRamps.orange[300];
2329
2425
 
2330
2426
  // src/components/custom/Workout/MesoStatusCard.tsx
2331
2427
  var t3 = getSemanticColors("dark");
2332
- var BRAND_PRIMARY4 = t3["brand-primary"];
2428
+ var BRAND_PRIMARY3 = t3["brand-primary"];
2333
2429
  var BRAND_PRIMARY_DARK = MESO_ACCENT_GRADIENT_DARK;
2334
2430
  var BRAND_PRIMARY_LIGHT = MESO_ACCENT_GRADIENT_LIGHT;
2335
2431
  var SUCCESS = t3["status-success"];
2336
2432
  var WARNING = t3["status-warning"];
2337
2433
  var ERROR = t3["status-error"];
2338
- var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY4, BRAND_PRIMARY_LIGHT];
2434
+ var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY3, BRAND_PRIMARY_LIGHT];
2339
2435
  var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
2340
2436
  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%)";
2341
2437
  var STATUS_VARIANTS = {
@@ -2360,15 +2456,7 @@ function renderCoachingText(text, highlights) {
2360
2456
  if (escaped.length === 0) return text;
2361
2457
  const regex = new RegExp(`(${escaped.join("|")})`, "g");
2362
2458
  return text.split(regex).map(
2363
- (part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(
2364
- Text,
2365
- {
2366
- className: "text-text-primary",
2367
- style: { fontWeight: "700" },
2368
- children: part
2369
- },
2370
- `${part}-${index}`
2371
- ) : /* @__PURE__ */ jsx(Fragment$1, { children: part }, `t-${index}`)
2459
+ (part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(Text, { className: "text-text-primary", style: { fontWeight: "700" }, children: part }, `${part}-${index}`) : /* @__PURE__ */ jsx(Fragment, { children: part }, `t-${index}`)
2372
2460
  );
2373
2461
  }
2374
2462
  function StatusPill({ badge }) {
@@ -2453,41 +2541,34 @@ function Gauge({ gauge }) {
2453
2541
  "aria-valuemax": 100,
2454
2542
  testID: "meso-status-card-gauge",
2455
2543
  children: [
2456
- /* @__PURE__ */ jsxs(
2457
- View,
2458
- {
2459
- className: "flex-row items-center justify-between",
2460
- accessibilityElementsHidden: true,
2461
- children: [
2462
- /* @__PURE__ */ jsx(
2463
- Text,
2464
- {
2465
- className: "text-text-secondary",
2466
- style: {
2467
- fontSize: 10,
2468
- fontFamily: "Inter, sans-serif",
2469
- fontWeight: "500",
2470
- letterSpacing: 0.5,
2471
- textTransform: "uppercase"
2472
- },
2473
- children: gauge.label
2474
- }
2475
- ),
2476
- gauge.sublabel != null && /* @__PURE__ */ jsx(
2477
- Text,
2478
- {
2479
- className: "text-text-tertiary",
2480
- style: {
2481
- fontSize: 10,
2482
- fontFamily: "Inter, sans-serif",
2483
- fontWeight: "500"
2484
- },
2485
- children: gauge.sublabel
2486
- }
2487
- )
2488
- ]
2489
- }
2490
- ),
2544
+ /* @__PURE__ */ jsxs(View, { className: "flex-row items-center justify-between", accessibilityElementsHidden: true, children: [
2545
+ /* @__PURE__ */ jsx(
2546
+ Text,
2547
+ {
2548
+ className: "text-text-secondary",
2549
+ style: {
2550
+ fontSize: 10,
2551
+ fontFamily: "Inter, sans-serif",
2552
+ fontWeight: "500",
2553
+ letterSpacing: 0.5,
2554
+ textTransform: "uppercase"
2555
+ },
2556
+ children: gauge.label
2557
+ }
2558
+ ),
2559
+ gauge.sublabel != null && /* @__PURE__ */ jsx(
2560
+ Text,
2561
+ {
2562
+ className: "text-text-tertiary",
2563
+ style: {
2564
+ fontSize: 10,
2565
+ fontFamily: "Inter, sans-serif",
2566
+ fontWeight: "500"
2567
+ },
2568
+ children: gauge.sublabel
2569
+ }
2570
+ )
2571
+ ] }),
2491
2572
  /* @__PURE__ */ jsxs(
2492
2573
  View,
2493
2574
  {
@@ -2528,7 +2609,8 @@ function Gauge({ gauge }) {
2528
2609
  borderRadius: 9999,
2529
2610
  borderWidth: 2,
2530
2611
  backgroundColor: markerColor,
2531
- boxShadow: "0 0 4px rgba(0,0,0,0.5)"
2612
+ // A knob resting on the gauge: lift, with the ring as its edge.
2613
+ ...liftStyle(1, "dark", { rim: 0 })
2532
2614
  },
2533
2615
  testID: "meso-status-card-gauge-marker"
2534
2616
  }
@@ -2580,30 +2662,23 @@ function MesoStatusCard({
2580
2662
  ),
2581
2663
  /* @__PURE__ */ jsxs(View, { style: { padding: 14, gap: 14 }, testID: "meso-status-card-body", children: [
2582
2664
  /* @__PURE__ */ jsxs(View, { testID: "meso-status-card-header", children: [
2583
- /* @__PURE__ */ jsxs(
2584
- View,
2585
- {
2586
- className: "flex-row items-center justify-between",
2587
- style: { gap: 8 },
2588
- children: [
2589
- /* @__PURE__ */ jsx(
2590
- Text,
2591
- {
2592
- className: "text-text-primary",
2593
- style: {
2594
- flexShrink: 1,
2595
- fontSize: 15,
2596
- fontFamily: '"Space Grotesk", sans-serif',
2597
- fontWeight: "700"
2598
- },
2599
- testID: "meso-status-card-name",
2600
- children: mesoName
2601
- }
2602
- ),
2603
- /* @__PURE__ */ jsx(StatusPill, { badge: statusBadge })
2604
- ]
2605
- }
2606
- ),
2665
+ /* @__PURE__ */ jsxs(View, { className: "flex-row items-center justify-between", style: { gap: 8 }, children: [
2666
+ /* @__PURE__ */ jsx(
2667
+ Text,
2668
+ {
2669
+ className: "text-text-primary",
2670
+ style: {
2671
+ flexShrink: 1,
2672
+ fontSize: 15,
2673
+ fontFamily: '"Space Grotesk", sans-serif',
2674
+ fontWeight: "700"
2675
+ },
2676
+ testID: "meso-status-card-name",
2677
+ children: mesoName
2678
+ }
2679
+ ),
2680
+ /* @__PURE__ */ jsx(StatusPill, { badge: statusBadge })
2681
+ ] }),
2607
2682
  /* @__PURE__ */ jsx(
2608
2683
  Text,
2609
2684
  {
@@ -2618,15 +2693,7 @@ function MesoStatusCard({
2618
2693
  }
2619
2694
  )
2620
2695
  ] }),
2621
- metrics.length > 0 && /* @__PURE__ */ jsx(
2622
- View,
2623
- {
2624
- className: "flex-row flex-wrap",
2625
- style: { gap: 8 },
2626
- testID: "meso-status-card-metrics",
2627
- children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell, { metric }, `${metric.label}-${index}`))
2628
- }
2629
- ),
2696
+ metrics.length > 0 && /* @__PURE__ */ jsx(View, { className: "flex-row flex-wrap", style: { gap: 8 }, testID: "meso-status-card-metrics", children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell, { metric }, `${metric.label}-${index}`)) }),
2630
2697
  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}`)) }),
2631
2698
  coaching != null && /* @__PURE__ */ jsx(
2632
2699
  View,