@titan-design/react-ui 0.13.0 → 0.14.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 (146) hide show
  1. package/README.md +14 -0
  2. package/dist/bodymap.js +129 -76
  3. package/dist/bodymap.js.map +1 -1
  4. package/dist/bodymap.mjs +129 -76
  5. package/dist/bodymap.mjs.map +1 -1
  6. package/dist/index.d.mts +117 -26
  7. package/dist/index.d.ts +117 -26
  8. package/dist/index.js +677 -450
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +673 -451
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/{pages-_3Ajpiqu.d.ts → pages-CsjsUn0G.d.ts} +30 -13
  13. package/dist/{pages-CpW3OB3g.d.mts → pages-ZbT_pD_U.d.mts} +30 -13
  14. package/dist/pages.d.mts +1 -1
  15. package/dist/pages.d.ts +1 -1
  16. package/dist/pages.js +676 -701
  17. package/dist/pages.js.map +1 -1
  18. package/dist/pages.mjs +676 -701
  19. package/dist/pages.mjs.map +1 -1
  20. package/dist/theme/index.d.mts +31 -7
  21. package/dist/theme/index.d.ts +31 -7
  22. package/dist/theme/index.js +84 -20
  23. package/dist/theme/index.js.map +1 -1
  24. package/dist/theme/index.mjs +83 -21
  25. package/dist/theme/index.mjs.map +1 -1
  26. package/dist/theme/tokens-css.js +84 -20
  27. package/dist/theme/tokens-css.js.map +1 -1
  28. package/dist/theme/tokens-css.mjs +84 -20
  29. package/dist/theme/tokens-css.mjs.map +1 -1
  30. package/dist/theme/tokens.d.mts +56 -7
  31. package/dist/theme/tokens.d.ts +56 -7
  32. package/dist/theme/tokens.js +72 -20
  33. package/dist/theme/tokens.js.map +1 -1
  34. package/dist/theme/tokens.mjs +71 -21
  35. package/dist/theme/tokens.mjs.map +1 -1
  36. package/docs/render-testing-pattern.md +130 -0
  37. package/package.json +1 -1
  38. package/src/arch/Architecture.stories.tsx +3 -1
  39. package/src/arch/arch-graph.json +74 -72
  40. package/src/components/custom/ActiveWork/InitiativeBrief.tsx +2 -1
  41. package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +8 -3
  42. package/src/components/custom/EmptyState/EmptyState.stories.tsx +1 -1
  43. package/src/components/custom/Gauge/Gauge.stories.tsx +4 -1
  44. package/src/components/custom/Gauge/Gauge.tsx +3 -1
  45. package/src/components/custom/Scatter/Scatter.stories.tsx +10 -7
  46. package/src/components/custom/Scatter/Scatter.tsx +6 -4
  47. package/src/components/custom/Sidebar/Sidebar.stories.tsx +1 -1
  48. package/src/components/custom/Table/Table.stories.tsx +1 -1
  49. package/src/components/custom/Table/Table.tsx +2 -2
  50. package/src/components/custom/Treemap/Treemap.stories.tsx +13 -10
  51. package/src/components/custom/Treemap/Treemap.tsx +4 -1
  52. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +2 -1
  53. package/src/components/custom/Workout/BaseBadge.stories.tsx +11 -7
  54. package/src/components/custom/Workout/BaseBadge.tsx +3 -2
  55. package/src/components/custom/Workout/BodyMap.tsx +5 -3
  56. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +13 -3
  57. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +5 -3
  58. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +2 -1
  59. package/src/components/custom/Workout/CapacityBandChart.tsx +5 -3
  60. package/src/components/custom/Workout/DeviationBar.test.tsx +5 -2
  61. package/src/components/custom/Workout/DeviationBar.tsx +5 -2
  62. package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +7 -6
  63. package/src/components/custom/Workout/DualVelocityStrip.test.tsx +29 -16
  64. package/src/components/custom/Workout/ExerciseCard.stories.tsx +8 -8
  65. package/src/components/custom/Workout/ExerciseCard.test.tsx +39 -19
  66. package/src/components/custom/Workout/ExerciseCard.tsx +92 -167
  67. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +89 -6
  68. package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +189 -1
  69. package/src/components/custom/Workout/ExerciseCardHeading.tsx +167 -18
  70. package/src/components/custom/Workout/ExerciseDetailPage.tsx +3 -2
  71. package/src/components/custom/Workout/ExerciseHeading.tsx +192 -47
  72. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +6 -5
  73. package/src/components/custom/Workout/InputBar.tsx +4 -2
  74. package/src/components/custom/Workout/IntensityBar.tsx +4 -1
  75. package/src/components/custom/Workout/MesoCard.tsx +2 -1
  76. package/src/components/custom/Workout/MesoStatusCard.tsx +11 -10
  77. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +8 -3
  78. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +12 -2
  79. package/src/components/custom/Workout/README.md +58 -12
  80. package/src/components/custom/Workout/ReadinessCheck.tsx +4 -2
  81. package/src/components/custom/Workout/RestTimer.stories.tsx +13 -2
  82. package/src/components/custom/Workout/RestTimer.tsx +4 -2
  83. package/src/components/custom/Workout/SegmentedBar.stories.tsx +16 -12
  84. package/src/components/custom/Workout/SegmentedBar.tsx +4 -3
  85. package/src/components/custom/Workout/SetStrip.stories.tsx +3 -2
  86. package/src/components/custom/Workout/SetsRepsLoad.tsx +23 -9
  87. package/src/components/custom/Workout/Sparkline.stories.tsx +13 -10
  88. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +2 -1
  89. package/src/components/custom/Workout/StrengthTrendChart.tsx +8 -6
  90. package/src/components/custom/Workout/TempoDisplay.stories.tsx +4 -3
  91. package/src/components/custom/Workout/TempoDisplay.tsx +2 -0
  92. package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +3 -2
  93. package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +1 -1
  94. package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +40 -0
  95. package/src/components/custom/Workout/VelocityStrip.test.tsx +48 -6
  96. package/src/components/custom/Workout/VelocityStrip.tsx +23 -14
  97. package/src/components/custom/Workout/ZoneTrack.stories.tsx +3 -1
  98. package/src/components/custom/Workout/exerciseRowState.ts +29 -0
  99. package/src/components/custom/Workout/index.ts +12 -2
  100. package/src/components/custom/Workout/metricText.stories.tsx +9 -8
  101. package/src/components/custom/Workout/metricText.tsx +4 -2
  102. package/src/components/custom/Workout/setHeadingKit.tsx +12 -10
  103. package/src/components/custom/Workout/velocity-story-kit.tsx +2 -2
  104. package/src/components/custom/charts/README.md +5 -0
  105. package/src/components/custom/charts/SetBarChart.test.tsx +16 -0
  106. package/src/components/custom/charts/SetBarChart.tsx +14 -5
  107. package/src/components/custom/charts/flatBarGeometry.test.ts +41 -0
  108. package/src/components/custom/charts/flatBarGeometry.ts +32 -0
  109. package/src/components/custom/stepper/Stepper.tsx +8 -6
  110. package/src/components/ui/alert/Alert.stories.tsx +14 -4
  111. package/src/components/ui/alert/Alert.tsx +24 -3
  112. package/src/components/ui/button/Button.tsx +12 -12
  113. package/src/components/ui/checkbox/Checkbox.tsx +2 -2
  114. package/src/components/ui/data-row/DataRow.stories.tsx +6 -2
  115. package/src/components/ui/drawer/Drawer.tsx +4 -1
  116. package/src/components/ui/icon-box/IconBox.tsx +8 -6
  117. package/src/components/ui/indicator/Indicator.stories.tsx +4 -3
  118. package/src/components/ui/list-item/ListItem.stories.tsx +7 -4
  119. package/src/components/ui/modal/Modal.tsx +2 -0
  120. package/src/components/ui/pill/Pill.stories.tsx +53 -0
  121. package/src/components/ui/pill/Pill.tsx +10 -6
  122. package/src/components/ui/popover/Popover.stories.tsx +1 -1
  123. package/src/components/ui/progress/Progress.tsx +9 -6
  124. package/src/components/ui/radio/Radio.tsx +1 -1
  125. package/src/components/ui/section/Section.stories.tsx +10 -10
  126. package/src/components/ui/select/Select.tsx +2 -1
  127. package/src/components/ui/spinner/Spinner.tsx +3 -1
  128. package/src/components/ui/stack/Stack.stories.tsx +7 -7
  129. package/src/components/ui/surface/Surface.stories.tsx +75 -28
  130. package/src/components/ui/switch/Switch.tsx +1 -1
  131. package/src/components/ui/tabs/Tabs.tsx +4 -2
  132. package/src/components/ui/toast/Toast.tsx +6 -4
  133. package/src/components/ui/toolbar-button/ToolbarButton.tsx +13 -6
  134. package/src/stories/PresetShowcase.stories.tsx +1 -1
  135. package/src/test/no-raw-color.test.ts +39 -0
  136. package/src/theme/Alpha.stories.tsx +103 -0
  137. package/src/theme/ProposedTokensVW82.stories.tsx +414 -0
  138. package/src/theme/config.ts +12 -0
  139. package/src/theme/global.css +15 -3
  140. package/src/theme/subtle-tone-weight.test.ts +163 -0
  141. package/src/theme/tailwind-var-opacity.test.ts +163 -0
  142. package/src/theme/tokens/primitives.ts +33 -0
  143. package/src/theme/tokens/semantic-hex-guard.test.ts +322 -0
  144. package/src/theme/tokens/semantic.ts +56 -20
  145. package/src/utils/colors.alpha-adoption.test.ts +408 -0
  146. package/tailwind.config.js +50 -9
package/dist/index.js CHANGED
@@ -186,33 +186,41 @@ var statusColors = {
186
186
  subtle: "bg-status-success-subtle",
187
187
  outline: "border-2 border-status-success bg-transparent",
188
188
  solid: "bg-status-success",
189
+ onSolid: "text-on-status-success",
189
190
  border: "border-status-success",
190
191
  icon: "text-status-success",
191
- text: "text-status-success"
192
+ text: "text-status-success",
193
+ subtleText: "text-on-status-success-subtle"
192
194
  },
193
195
  info: {
194
196
  subtle: "bg-status-info-subtle",
195
197
  outline: "border-2 border-status-info bg-transparent",
196
198
  solid: "bg-status-info",
199
+ onSolid: "text-on-status-info",
197
200
  border: "border-status-info",
198
201
  icon: "text-status-info",
199
- text: "text-status-info"
202
+ text: "text-status-info",
203
+ subtleText: "text-on-status-info-subtle"
200
204
  },
201
205
  warning: {
202
206
  subtle: "bg-status-warning-subtle",
203
207
  outline: "border-2 border-status-warning bg-transparent",
204
208
  solid: "bg-status-warning",
209
+ onSolid: "text-on-status-warning",
205
210
  border: "border-status-warning",
206
211
  icon: "text-status-warning",
207
- text: "text-status-warning"
212
+ text: "text-status-warning",
213
+ subtleText: "text-on-status-warning-subtle"
208
214
  },
209
215
  error: {
210
216
  subtle: "bg-status-error-subtle",
211
217
  outline: "border-2 border-status-error bg-transparent",
212
218
  solid: "bg-status-error",
219
+ onSolid: "text-on-status-error",
213
220
  border: "border-status-error",
214
221
  icon: "text-status-error",
215
- text: "text-status-error"
222
+ text: "text-status-error",
223
+ subtleText: "text-on-status-error-subtle"
216
224
  }
217
225
  };
218
226
  var defaultIcons = {
@@ -256,7 +264,7 @@ function Alert({
256
264
  className: cn(
257
265
  "font-bold",
258
266
  isCompact ? "text-base" : "text-lg",
259
- isSolid ? "text-white" : colors.icon
267
+ isSolid ? colors.onSolid : variant === "subtle" ? colors.subtleText : colors.icon
260
268
  ),
261
269
  children: defaultIcons[status]
262
270
  }
@@ -265,7 +273,10 @@ function Alert({
265
273
  message != null && /* @__PURE__ */ jsx(
266
274
  reactNative.Text,
267
275
  {
268
- className: cn("text-sm font-semibold", isSolid ? "text-white" : colors.text),
276
+ className: cn(
277
+ "text-sm font-semibold",
278
+ isSolid ? colors.onSolid : variant === "subtle" ? colors.subtleText : colors.text
279
+ ),
269
280
  testID: "alert-message",
270
281
  children: message
271
282
  }
@@ -279,7 +290,16 @@ function Alert({
279
290
  accessibilityRole: "button",
280
291
  accessibilityLabel: "Close alert",
281
292
  className: "ml-2 p-1 rounded web:hover:bg-black/10 active:bg-black/20",
282
- children: /* @__PURE__ */ jsx(reactNative.Text, { className: cn("text-lg", isSolid ? "text-white/70" : "text-text-secondary"), children: "\xD7" })
293
+ children: /* @__PURE__ */ jsx(
294
+ reactNative.Text,
295
+ {
296
+ className: cn(
297
+ "text-lg",
298
+ isSolid ? cn(colors.onSolid, "opacity-70") : "text-text-secondary"
299
+ ),
300
+ children: "\xD7"
301
+ }
302
+ )
283
303
  }
284
304
  )
285
305
  ]
@@ -300,6 +320,26 @@ var primitiveColors = {
300
320
  transparent: "transparent"
301
321
  };
302
322
  var alertRedVivid = "#FF4757";
323
+ var resultPaletteColors = {
324
+ improve: "#4caf50",
325
+ improveDark: "#248a24",
326
+ degrade: "#ef5350",
327
+ degradeDark: "#b30000",
328
+ inconclusive: "#9E9A97"
329
+ };
330
+ var semanticPins = {
331
+ // Cool navy-black; darker and more blue-shifted than any warm greyRamp step.
332
+ textPrimaryLight: "#121828",
333
+ // Cool blue-grey; outside greyRamp's warm (R>=G>=B) scale.
334
+ textSecondaryLight: "#65748B",
335
+ // Pure neutral grey (R=G=B); no warm greyRamp step lands on it exactly.
336
+ backgroundBaseLight: "#EBEBEB",
337
+ // Near-neutral grey, kept one step off backgroundBaseLight by design.
338
+ dividerLight: "#E8E9EB",
339
+ // Periwinkle/indigo; more purple than any primitiveRamps.blue step. Shared by
340
+ // dark-mode text-link, border-focus and border-input-focus.
341
+ focusIndigoDark: "#828DF8"
342
+ };
303
343
  var greyRamp = {
304
344
  50: "#F9F6F3",
305
345
  // L*97.0 W6
@@ -732,6 +772,12 @@ var semanticColorsLight = {
732
772
  // Text on brand backgrounds (on-*)
733
773
  "on-brand-primary": primitiveColors.white,
734
774
  "on-brand-secondary": primitiveColors.white,
775
+ // Text ON a `-subtle` fill. Light mode keeps today's pairing (the base token) so
776
+ // nothing moves here: light has the same disease mirrored — a light rung on a
777
+ // near-white ramp[50] fill — but correcting it belongs with the light-mode pass
778
+ // in AW-121, not this one.
779
+ "on-brand-primary-subtle": primitiveRamps.orange[400],
780
+ "on-brand-secondary-subtle": primitiveRamps.cyan[600],
735
781
  // Status colors (status-*)
736
782
  "status-success": primitiveRamps.green[300],
737
783
  "status-success-light": primitiveRamps.green[200],
@@ -767,21 +813,26 @@ var semanticColorsLight = {
767
813
  "status-info-subtle": primitiveRamps.blue[50],
768
814
  "status-info-muted": "rgba(33, 150, 243, 0.30)",
769
815
  "status-info-strong": "rgba(33, 150, 243, 0.50)",
816
+ // Text ON a `-subtle` fill — see the on-brand-*-subtle note above.
817
+ "on-status-success-subtle": primitiveRamps.green[300],
818
+ "on-status-error-subtle": primitiveRamps.red[600],
819
+ "on-status-warning-subtle": primitiveRamps.amber[300],
820
+ "on-status-info-subtle": primitiveRamps.blue[500],
770
821
  // Text on status backgrounds (on-status-*)
771
822
  "on-status-success": primitiveColors.white,
772
823
  "on-status-error": primitiveColors.white,
773
824
  "on-status-warning": primitiveColors.white,
774
825
  "on-status-info": primitiveColors.white,
775
826
  // Result/outcome indicators (result-*)
776
- "result-improve": "#4caf50",
827
+ "result-improve": resultPaletteColors.improve,
777
828
  // Green - positive outcome
778
829
  "result-improve-light": "rgba(76, 175, 80, 0.12)",
779
- "result-improve-dark": "#248a24",
780
- "result-degrade": "#ef5350",
830
+ "result-improve-dark": resultPaletteColors.improveDark,
831
+ "result-degrade": resultPaletteColors.degrade,
781
832
  // Red - negative outcome
782
833
  "result-degrade-light": "rgba(239, 83, 80, 0.12)",
783
- "result-degrade-dark": "#b30000",
784
- "result-inconclusive": "#9E9A97",
834
+ "result-degrade-dark": resultPaletteColors.degradeDark,
835
+ "result-inconclusive": resultPaletteColors.inconclusive,
785
836
  // Gray - no clear result
786
837
  "result-inconclusive-light": "rgba(158, 154, 151, 0.12)",
787
838
  "result-neutral": greyRamp[600],
@@ -813,8 +864,8 @@ var semanticColorsLight = {
813
864
  "data-10": discreteRainbow[22],
814
865
  // Dark Orange
815
866
  // Text colors (text-*)
816
- "text-primary": "#121828",
817
- "text-secondary": "#65748B",
867
+ "text-primary": semanticPins.textPrimaryLight,
868
+ "text-secondary": semanticPins.textSecondaryLight,
818
869
  "text-tertiary": greyRamp[400],
819
870
  "text-disabled": "rgba(55, 65, 81, 0.48)",
820
871
  "text-inverse": primitiveColors.white,
@@ -830,7 +881,7 @@ var semanticColorsLight = {
830
881
  "surface-input": greyRamp[50],
831
882
  // Input field background (filled variant)
832
883
  // Background colors (background-*)
833
- "background-base": "#EBEBEB",
884
+ "background-base": semanticPins.backgroundBaseLight,
834
885
  "background-default": primitiveColors.white,
835
886
  "background-subtle": greyRamp[50],
836
887
  // Frame/bezel chrome — top bar + side nav shell, one step below
@@ -861,7 +912,7 @@ var semanticColorsLight = {
861
912
  "interactive-disabled": "rgba(55, 65, 81, 0.12)",
862
913
  "interactive-disabled-text": "rgba(55, 65, 81, 0.26)",
863
914
  // Divider
864
- divider: "#E8E9EB",
915
+ divider: semanticPins.dividerLight,
865
916
  // Avatar default
866
917
  "avatar-background": greyRamp[600],
867
918
  "avatar-text": primitiveColors.white
@@ -879,7 +930,7 @@ var semanticColorsDark = {
879
930
  "brand-secondary": primitiveRamps.cyan[600],
880
931
  "brand-secondary-light": primitiveRamps.cyan[500],
881
932
  "brand-secondary-dark": primitiveRamps.cyan[700],
882
- "brand-secondary-subtle": "rgba(48, 123, 155, 0.12)",
933
+ "brand-secondary-subtle": "rgba(34, 211, 238, 0.12)",
883
934
  "brand-secondary-muted": "rgba(48, 123, 155, 0.30)",
884
935
  "brand-secondary-strong": "rgba(48, 123, 155, 0.50)",
885
936
  "brand-secondary-hover": primitiveRamps.cyan[500],
@@ -887,6 +938,14 @@ var semanticColorsDark = {
887
938
  // Text on brand backgrounds
888
939
  "on-brand-primary": primitiveColors.white,
889
940
  "on-brand-secondary": primitiveColors.white,
941
+ // Text ON a `-subtle` fill. Its own role: `brand-primary` and friends are tuned to
942
+ // carry a white label as a solid fill, which makes the two deepest of them
943
+ // (cyan[600], red[600]) too dark to read as text on a dark plane. Levelling the
944
+ // family at rung 300 puts every tone within OKLCH L 0.769-0.813 instead of
945
+ // 0.550-0.813. Brand is deliberately left at its own orange[400] (operator, AW-133)
946
+ // so the Voltras tone never drifts; it is the one tone under AA on a raised card.
947
+ "on-brand-primary-subtle": primitiveRamps.orange[400],
948
+ "on-brand-secondary-subtle": primitiveRamps.cyan[300],
890
949
  // Status colors
891
950
  "status-success": primitiveRamps.green[300],
892
951
  "status-success-light": primitiveRamps.green[200],
@@ -900,7 +959,10 @@ var semanticColorsDark = {
900
959
  "status-error": primitiveRamps.red[600],
901
960
  "status-error-light": primitiveRamps.red[500],
902
961
  "status-error-dark": primitiveRamps.red[700],
903
- "status-error-subtle": "rgba(209, 67, 67, 0.12)",
962
+ // Alpha 0.08, not the family's 0.12: error's label is red[400], a rung darker than
963
+ // its siblings so it reads RED rather than pink (rung 300 has only 0.121 chroma).
964
+ // Thinning the fill buys back the contrast that extra darkness costs. See AW-133.
965
+ "status-error-subtle": "rgba(247, 113, 117, 0.08)",
904
966
  "status-error-muted": "rgba(209, 67, 67, 0.30)",
905
967
  "status-error-strong": "rgba(209, 67, 67, 0.50)",
906
968
  "status-error-vivid": alertRedVivid,
@@ -918,7 +980,7 @@ var semanticColorsDark = {
918
980
  "status-info": primitiveRamps.blue[500],
919
981
  "status-info-light": primitiveRamps.blue[300],
920
982
  "status-info-dark": primitiveRamps.blue[600],
921
- "status-info-subtle": "rgba(33, 150, 243, 0.12)",
983
+ "status-info-subtle": "rgba(120, 194, 255, 0.12)",
922
984
  "status-info-muted": "rgba(33, 150, 243, 0.30)",
923
985
  "status-info-strong": "rgba(33, 150, 243, 0.50)",
924
986
  // Text on status backgrounds
@@ -926,14 +988,22 @@ var semanticColorsDark = {
926
988
  "on-status-error": primitiveColors.white,
927
989
  "on-status-warning": primitiveColors.white,
928
990
  "on-status-info": primitiveColors.white,
991
+ // Text ON a `-subtle` fill — see the on-brand-*-subtle note above. Error is the
992
+ // second deliberate exception to the rung-300 rule (operator, AW-133): red[300]
993
+ // levelled perfectly but read PINK, because a red that light can only hold 0.121
994
+ // chroma. red[400] carries 0.165 and reads red; its fill is thinned to compensate.
995
+ "on-status-success-subtle": primitiveRamps.green[300],
996
+ "on-status-error-subtle": primitiveRamps.red[400],
997
+ "on-status-warning-subtle": primitiveRamps.amber[300],
998
+ "on-status-info-subtle": primitiveRamps.blue[300],
929
999
  // Result/outcome indicators (result-*)
930
- "result-improve": "#4caf50",
1000
+ "result-improve": resultPaletteColors.improve,
931
1001
  "result-improve-light": "rgba(76, 175, 80, 0.16)",
932
- "result-improve-dark": "#248a24",
933
- "result-degrade": "#ef5350",
1002
+ "result-improve-dark": resultPaletteColors.improveDark,
1003
+ "result-degrade": resultPaletteColors.degrade,
934
1004
  "result-degrade-light": "rgba(239, 83, 80, 0.16)",
935
- "result-degrade-dark": "#b30000",
936
- "result-inconclusive": "#9E9A97",
1005
+ "result-degrade-dark": resultPaletteColors.degradeDark,
1006
+ "result-inconclusive": resultPaletteColors.inconclusive,
937
1007
  "result-inconclusive-light": "rgba(158, 154, 151, 0.16)",
938
1008
  "result-neutral": greyRamp[400],
939
1009
  // Text on result backgrounds
@@ -964,7 +1034,7 @@ var semanticColorsDark = {
964
1034
  "text-tertiary": greyRamp[500],
965
1035
  "text-disabled": "rgba(255, 255, 255, 0.38)",
966
1036
  "text-inverse": greyRamp[950],
967
- "text-link": "#828DF8",
1037
+ "text-link": semanticPins.focusIndigoDark,
968
1038
  "text-link-hover": primitiveRamps.blue[400],
969
1039
  // Surface colors - dark backgrounds — warm-tapered DERIVED ramp (TD-surface-tokens,
970
1040
  // S-1, re-spaced S-3). Shipped verbatim from `deriveSurfaceRamp()` — see
@@ -1014,10 +1084,10 @@ var semanticColorsDark = {
1014
1084
  // plane, so it keeps its job without collision.
1015
1085
  "border-prominent": greyRamp[800],
1016
1086
  // high-visibility divider
1017
- "border-focus": "#828DF8",
1087
+ "border-focus": semanticPins.focusIndigoDark,
1018
1088
  "border-input": greyRamp[700],
1019
1089
  "border-input-hover": greyRamp[600],
1020
- "border-input-focus": "#828DF8",
1090
+ "border-input-focus": semanticPins.focusIndigoDark,
1021
1091
  "border-input-error": primitiveRamps.red[500],
1022
1092
  // Alpha hairline separators — the primary separation cue (§4/S-2). Self-
1023
1093
  // normalizing: composites toward white by ~the same amount on ANY plane, so
@@ -1173,12 +1243,12 @@ function getSemanticColors(mode) {
1173
1243
  // src/components/ui/button/Button.tsx
1174
1244
  var textColorMap = {
1175
1245
  solid: {
1176
- primary: "#FFFFFF",
1177
- secondary: "#FFFFFF",
1178
- success: "#FFFFFF",
1179
- error: "#FFFFFF",
1180
- warning: "#FFFFFF",
1181
- info: "#FFFFFF"
1246
+ primary: semanticColorsDark["on-brand-primary"],
1247
+ secondary: semanticColorsDark["on-brand-secondary"],
1248
+ success: semanticColorsDark["on-status-success"],
1249
+ error: semanticColorsDark["on-status-error"],
1250
+ warning: semanticColorsDark["on-status-warning"],
1251
+ info: semanticColorsDark["on-status-info"]
1182
1252
  },
1183
1253
  outline: {
1184
1254
  primary: semanticColorsDark["brand-primary"],
@@ -1249,12 +1319,12 @@ var variantStyles = {
1249
1319
  };
1250
1320
  var textStyles = {
1251
1321
  solid: {
1252
- primary: "text-white",
1253
- secondary: "text-white",
1254
- success: "text-white",
1255
- error: "text-white",
1256
- warning: "text-white",
1257
- info: "text-white"
1322
+ primary: "text-on-brand-primary",
1323
+ secondary: "text-on-brand-secondary",
1324
+ success: "text-on-status-success",
1325
+ error: "text-on-status-error",
1326
+ warning: "text-on-status-warning",
1327
+ info: "text-on-status-info"
1258
1328
  },
1259
1329
  outline: {
1260
1330
  primary: "text-brand-primary",
@@ -2202,13 +2272,16 @@ var toneStyles = {
2202
2272
  // host is, and an alpha fill composites by the same amount on all of them.
2203
2273
  // A `surface-*` fill would vanish on the plane it names. Borderless like the
2204
2274
  // six coloured tones — the fill carries the capsule, not a ring.
2275
+ // Label comes from `on-*-subtle`, not the base tone token: the base is tuned to
2276
+ // carry a white label as a solid fill, which left error and accent unreadable
2277
+ // here (AW-133). The on-subtle tokens level the family at one weight.
2205
2278
  neutral: "bg-hairline-subtle border-transparent text-text-secondary",
2206
- brand: "bg-brand-primary-subtle border-transparent text-brand-primary",
2207
- "brand-secondary": "bg-brand-secondary-subtle border-transparent text-brand-secondary",
2208
- success: "bg-status-success-subtle border-transparent text-status-success",
2209
- warning: "bg-status-warning-subtle border-transparent text-status-warning",
2210
- error: "bg-status-error-subtle border-transparent text-status-error",
2211
- info: "bg-status-info-subtle border-transparent text-status-info"
2279
+ brand: "bg-brand-primary-subtle border-transparent text-on-brand-primary-subtle",
2280
+ "brand-secondary": "bg-brand-secondary-subtle border-transparent text-on-brand-secondary-subtle",
2281
+ success: "bg-status-success-subtle border-transparent text-on-status-success-subtle",
2282
+ warning: "bg-status-warning-subtle border-transparent text-on-status-warning-subtle",
2283
+ error: "bg-status-error-subtle border-transparent text-on-status-error-subtle",
2284
+ info: "bg-status-info-subtle border-transparent text-on-status-info-subtle"
2212
2285
  },
2213
2286
  outline: {
2214
2287
  neutral: "border-hairline text-text-secondary",
@@ -2377,7 +2450,8 @@ var sizeMap = {
2377
2450
  var colorMap = {
2378
2451
  primary: SPINNER_PRIMARY,
2379
2452
  secondary: SPINNER_SECONDARY,
2380
- white: "#FFFFFF",
2453
+ white: primitiveColors.white,
2454
+ // VW-82: Tailwind gray-500; no titan grey matches. Left raw, proposed in the PR.
2381
2455
  default: "#6B7280"
2382
2456
  };
2383
2457
  var containerSizes = {
@@ -2578,8 +2652,8 @@ var Checkbox = React26.forwardRef(function Checkbox2({
2578
2652
  !isDisabled && "web:hover:border-brand-primary"
2579
2653
  ),
2580
2654
  children: [
2581
- isChecked && !isIndeterminate && /* @__PURE__ */ jsx(reactNative.View, { className: cn("bg-white rounded-sm", styles2.icon), children: /* @__PURE__ */ jsx(reactNative.Text, { className: "text-brand-primary font-bold text-center leading-none", children: "\u2713" }) }),
2582
- isIndeterminate && /* @__PURE__ */ jsx(reactNative.View, { className: cn("bg-white h-0.5 w-2/3 rounded") })
2655
+ isChecked && !isIndeterminate && /* @__PURE__ */ jsx(reactNative.View, { className: cn("bg-on-brand-primary rounded-sm", styles2.icon), children: /* @__PURE__ */ jsx(reactNative.Text, { className: "text-brand-primary font-bold text-center leading-none", children: "\u2713" }) }),
2656
+ isIndeterminate && /* @__PURE__ */ jsx(reactNative.View, { className: cn("bg-on-brand-primary h-0.5 w-2/3 rounded") })
2583
2657
  ]
2584
2658
  }
2585
2659
  ),
@@ -2636,7 +2710,7 @@ var Switch = React26.forwardRef(function Switch2({
2636
2710
  reactNative.View,
2637
2711
  {
2638
2712
  className: cn(
2639
- "rounded-full bg-white transition-transform",
2713
+ "rounded-full bg-on-brand-primary transition-transform",
2640
2714
  styles2.thumb,
2641
2715
  isChecked && styles2.translate
2642
2716
  ),
@@ -2696,6 +2770,8 @@ function Modal({
2696
2770
  onPress: handleBackdropPress,
2697
2771
  className: cn(
2698
2772
  "flex-1 items-center justify-center",
2773
+ // VW-82: scrims stay raw — Tailwind v3 drops the `/n` modifier on a
2774
+ // `var()` colour, so a translucent role has to be its own token (proposed).
2699
2775
  backdropBlur ? "bg-black/30 web:backdrop-blur-sm" : "bg-black/50",
2700
2776
  backdropClassName
2701
2777
  ),
@@ -2991,7 +3067,7 @@ function Tab({ index = 0, isDisabled = false, className, children }) {
2991
3067
  ),
2992
3068
  "soft-rounded": cn(
2993
3069
  "px-4 py-2 rounded-full",
2994
- isActive ? "bg-brand-primary text-white" : "text-text-secondary web:hover:text-text-primary"
3070
+ isActive ? "bg-brand-primary text-on-brand-primary" : "text-text-secondary web:hover:text-text-primary"
2995
3071
  )
2996
3072
  };
2997
3073
  return /* @__PURE__ */ jsx(
@@ -3012,7 +3088,7 @@ function Tab({ index = 0, isDisabled = false, className, children }) {
3012
3088
  {
3013
3089
  className: cn(
3014
3090
  "font-medium",
3015
- isActive ? variant === "soft-rounded" ? "text-white" : "text-text-primary" : "text-text-secondary"
3091
+ isActive ? variant === "soft-rounded" ? "text-on-brand-primary" : "text-text-primary" : "text-text-secondary"
3016
3092
  ),
3017
3093
  children
3018
3094
  }
@@ -3879,6 +3955,7 @@ function Select({
3879
3955
  accessibilityState: { expanded: isOpen, disabled: isDisabled },
3880
3956
  className: cn(
3881
3957
  "flex-row items-center justify-between px-4 py-2.5 rounded-md border",
3958
+ // VW-82: scrim-style fill, left raw (see Modal.tsx).
3882
3959
  variant === "filled" ? "bg-black/30" : "bg-surface-base",
3883
3960
  isInvalid ? "border-border-input-error" : variant === "filled" ? "border-hairline-subtle" : "border-border-input",
3884
3961
  !isDisabled && !isInvalid && "web:hover:border-border-input-hover",
@@ -3952,7 +4029,7 @@ function SelectOption({ option }) {
3952
4029
  "w-4 h-4 mr-3 rounded border",
3953
4030
  selected ? "bg-brand-primary border-brand-primary" : "border-hairline-strong"
3954
4031
  ),
3955
- children: selected && /* @__PURE__ */ jsx(reactNative.Text, { className: "text-white text-xs text-center", children: "\u2713" })
4032
+ children: selected && /* @__PURE__ */ jsx(reactNative.Text, { className: "text-on-brand-primary text-xs text-center", children: "\u2713" })
3956
4033
  }
3957
4034
  ),
3958
4035
  /* @__PURE__ */ jsx(
@@ -4009,6 +4086,8 @@ var lightThemeCSSVars = {
4009
4086
  "--color-brand-secondary-strong": semanticColorsLight["brand-secondary-strong"],
4010
4087
  "--color-on-brand-primary": semanticColorsLight["on-brand-primary"],
4011
4088
  "--color-on-brand-secondary": semanticColorsLight["on-brand-secondary"],
4089
+ "--color-on-brand-primary-subtle": semanticColorsLight["on-brand-primary-subtle"],
4090
+ "--color-on-brand-secondary-subtle": semanticColorsLight["on-brand-secondary-subtle"],
4012
4091
  "--color-status-success": semanticColorsLight["status-success"],
4013
4092
  "--color-status-success-subtle": semanticColorsLight["status-success-subtle"],
4014
4093
  "--color-status-success-muted": semanticColorsLight["status-success-muted"],
@@ -4070,6 +4149,10 @@ var lightThemeCSSVars = {
4070
4149
  "--color-on-status-error": semanticColorsLight["on-status-error"],
4071
4150
  "--color-on-status-warning": semanticColorsLight["on-status-warning"],
4072
4151
  "--color-on-status-info": semanticColorsLight["on-status-info"],
4152
+ "--color-on-status-success-subtle": semanticColorsLight["on-status-success-subtle"],
4153
+ "--color-on-status-error-subtle": semanticColorsLight["on-status-error-subtle"],
4154
+ "--color-on-status-warning-subtle": semanticColorsLight["on-status-warning-subtle"],
4155
+ "--color-on-status-info-subtle": semanticColorsLight["on-status-info-subtle"],
4073
4156
  "--color-result-improve": semanticColorsLight["result-improve"],
4074
4157
  "--color-result-improve-light": semanticColorsLight["result-improve-light"],
4075
4158
  "--color-result-improve-dark": semanticColorsLight["result-improve-dark"],
@@ -4122,6 +4205,8 @@ var darkThemeCSSVars = {
4122
4205
  "--color-brand-secondary-strong": semanticColorsDark["brand-secondary-strong"],
4123
4206
  "--color-on-brand-primary": semanticColorsDark["on-brand-primary"],
4124
4207
  "--color-on-brand-secondary": semanticColorsDark["on-brand-secondary"],
4208
+ "--color-on-brand-primary-subtle": semanticColorsDark["on-brand-primary-subtle"],
4209
+ "--color-on-brand-secondary-subtle": semanticColorsDark["on-brand-secondary-subtle"],
4125
4210
  "--color-status-success": semanticColorsDark["status-success"],
4126
4211
  "--color-status-success-subtle": semanticColorsDark["status-success-subtle"],
4127
4212
  "--color-status-success-muted": semanticColorsDark["status-success-muted"],
@@ -4183,6 +4268,10 @@ var darkThemeCSSVars = {
4183
4268
  "--color-on-status-error": semanticColorsDark["on-status-error"],
4184
4269
  "--color-on-status-warning": semanticColorsDark["on-status-warning"],
4185
4270
  "--color-on-status-info": semanticColorsDark["on-status-info"],
4271
+ "--color-on-status-success-subtle": semanticColorsDark["on-status-success-subtle"],
4272
+ "--color-on-status-error-subtle": semanticColorsDark["on-status-error-subtle"],
4273
+ "--color-on-status-warning-subtle": semanticColorsDark["on-status-warning-subtle"],
4274
+ "--color-on-status-info-subtle": semanticColorsDark["on-status-info-subtle"],
4186
4275
  "--color-result-improve": semanticColorsDark["result-improve"],
4187
4276
  "--color-result-improve-light": semanticColorsDark["result-improve-light"],
4188
4277
  "--color-result-improve-dark": semanticColorsDark["result-improve-dark"],
@@ -4530,7 +4619,67 @@ var audiobookPreset = {
4530
4619
  rootClasses: ["atmosphere-warm", "grain"]
4531
4620
  };
4532
4621
 
4622
+ // src/utils/colors.ts
4623
+ function getStatusColor(status) {
4624
+ return `var(--color-status-${status})`;
4625
+ }
4626
+ function getResultColor(result) {
4627
+ return `var(--color-result-${result})`;
4628
+ }
4629
+ function alpha(color, opacity) {
4630
+ const clampedOpacity = Math.max(0, Math.min(1, opacity));
4631
+ if (color.startsWith("#")) {
4632
+ const hex = color.slice(1);
4633
+ let r, g, b;
4634
+ if (hex.length === 3) {
4635
+ r = parseInt(hex[0] + hex[0], 16);
4636
+ g = parseInt(hex[1] + hex[1], 16);
4637
+ b = parseInt(hex[2] + hex[2], 16);
4638
+ } else if (hex.length === 6) {
4639
+ r = parseInt(hex.slice(0, 2), 16);
4640
+ g = parseInt(hex.slice(2, 4), 16);
4641
+ b = parseInt(hex.slice(4, 6), 16);
4642
+ } else {
4643
+ return color;
4644
+ }
4645
+ return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
4646
+ }
4647
+ const rgbMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
4648
+ if (rgbMatch) {
4649
+ const [, r, g, b] = rgbMatch;
4650
+ return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
4651
+ }
4652
+ const rgbaMatch = color.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/);
4653
+ if (rgbaMatch) {
4654
+ const [, r, g, b] = rgbaMatch;
4655
+ return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
4656
+ }
4657
+ return color;
4658
+ }
4659
+ function getLuminance(color) {
4660
+ if (!color.startsWith("#")) return "dark";
4661
+ const hex = color.slice(1);
4662
+ let r, g, b;
4663
+ if (hex.length === 3) {
4664
+ r = parseInt(hex[0] + hex[0], 16);
4665
+ g = parseInt(hex[1] + hex[1], 16);
4666
+ b = parseInt(hex[2] + hex[2], 16);
4667
+ } else if (hex.length === 6) {
4668
+ r = parseInt(hex.slice(0, 2), 16);
4669
+ g = parseInt(hex.slice(2, 4), 16);
4670
+ b = parseInt(hex.slice(4, 6), 16);
4671
+ } else {
4672
+ return "dark";
4673
+ }
4674
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
4675
+ return luminance > 0.5 ? "light" : "dark";
4676
+ }
4677
+ function getContrastText(backgroundColor) {
4678
+ return getLuminance(backgroundColor) === "light" ? "#000000" : "#FFFFFF";
4679
+ }
4680
+
4533
4681
  // src/components/ui/toolbar-button/ToolbarButton.tsx
4682
+ var ICON_IDLE = "#D1D1D1";
4534
4683
  var ToolbarButtonContext = React26.createContext({
4535
4684
  isOpen: false,
4536
4685
  setIsOpen: () => {
@@ -4580,7 +4729,7 @@ function ToolbarButton({
4580
4729
  const showActive = isActive !== false;
4581
4730
  const getIconColor = () => {
4582
4731
  if (isActive === true) return resolveColor("brand-primary");
4583
- return showActive ? "#FFFFFF" : "#D1D1D1";
4732
+ return showActive ? primitiveColors.white : ICON_IDLE;
4584
4733
  };
4585
4734
  const getRaisedStyle = () => {
4586
4735
  if (isDisabled) return styles.disabledBg;
@@ -4669,7 +4818,7 @@ function ToolbarButton({
4669
4818
  var styles = reactNative.StyleSheet.create({
4670
4819
  // Disabled - flat gray background, no shadows
4671
4820
  disabledBg: {
4672
- backgroundColor: "rgba(255, 255, 255, 0.12)",
4821
+ backgroundColor: alpha(primitiveColors.white, 0.12),
4673
4822
  ...reactNative.Platform.select({
4674
4823
  web: { boxShadow: "none" },
4675
4824
  default: { shadowOpacity: 0, elevation: 0 }
@@ -4820,7 +4969,7 @@ function Radio({
4820
4969
  isChecked ? checked : unchecked,
4821
4970
  !isDisabled && !isChecked && "web:hover:border-brand-primary"
4822
4971
  ),
4823
- children: isChecked && /* @__PURE__ */ jsx(reactNative.View, { className: cn("rounded-full bg-white", inner) })
4972
+ children: isChecked && /* @__PURE__ */ jsx(reactNative.View, { className: cn("rounded-full bg-on-brand-primary", inner) })
4824
4973
  }
4825
4974
  ),
4826
4975
  children && /* @__PURE__ */ jsx(reactNative.Text, { className: cn("ml-2 text-text-primary", text), children })
@@ -4883,7 +5032,13 @@ function Drawer({
4883
5032
  }
4884
5033
  };
4885
5034
  return /* @__PURE__ */ jsx(reactNative.Modal, { visible: isOpen, transparent: true, animationType: "fade", onRequestClose: onClose, children: /* @__PURE__ */ jsxs(reactNative.View, { className: "flex-1", children: [
4886
- /* @__PURE__ */ jsx(reactNative.Pressable, { onPress: handleOverlayPress, className: "absolute inset-0 bg-black/50" }),
5035
+ /* @__PURE__ */ jsx(
5036
+ reactNative.Pressable,
5037
+ {
5038
+ onPress: handleOverlayPress,
5039
+ className: "absolute inset-0 bg-black/50"
5040
+ }
5041
+ ),
4887
5042
  /* @__PURE__ */ jsxs(
4888
5043
  Surface,
4889
5044
  {
@@ -4961,12 +5116,12 @@ var colorStyles4 = {
4961
5116
  info: "bg-status-info"
4962
5117
  };
4963
5118
  var trackColorStyles = {
4964
- primary: "bg-brand-primary/20",
4965
- secondary: "bg-brand-secondary/20",
4966
- success: "bg-status-success/20",
4967
- error: "bg-status-error/20",
4968
- warning: "bg-status-warning/20",
4969
- info: "bg-status-info/20"
5119
+ primary: "bg-brand-primary-muted",
5120
+ secondary: "bg-brand-secondary-muted",
5121
+ success: "bg-status-success-muted",
5122
+ error: "bg-status-error-muted",
5123
+ warning: "bg-status-warning-muted",
5124
+ info: "bg-status-info-muted"
4970
5125
  };
4971
5126
  function Progress({
4972
5127
  value = 0,
@@ -5203,7 +5358,7 @@ function ToastProvider({
5203
5358
  [defaultDuration, maxToasts]
5204
5359
  );
5205
5360
  const removeToast = React26.useCallback((id) => {
5206
- setToasts((prev) => prev.filter((t18) => t18.id !== id));
5361
+ setToasts((prev) => prev.filter((t19) => t19.id !== id));
5207
5362
  }, []);
5208
5363
  const removeAllToasts = React26.useCallback(() => {
5209
5364
  setToasts([]);
@@ -5239,22 +5394,22 @@ function useToast() {
5239
5394
  }
5240
5395
  var statusStyles = {
5241
5396
  success: {
5242
- bg: "bg-status-success/10",
5397
+ bg: "bg-status-success-subtle",
5243
5398
  border: "border-status-success",
5244
5399
  icon: "\u2713"
5245
5400
  },
5246
5401
  error: {
5247
- bg: "bg-status-error/10",
5402
+ bg: "bg-status-error-subtle",
5248
5403
  border: "border-status-error",
5249
5404
  icon: "\u2715"
5250
5405
  },
5251
5406
  warning: {
5252
- bg: "bg-status-warning/10",
5407
+ bg: "bg-status-warning-subtle",
5253
5408
  border: "border-status-warning",
5254
5409
  icon: "\u26A0"
5255
5410
  },
5256
5411
  info: {
5257
- bg: "bg-status-info/10",
5412
+ bg: "bg-status-info-subtle",
5258
5413
  border: "border-status-info",
5259
5414
  icon: "\u2139"
5260
5415
  }
@@ -5864,12 +6019,12 @@ function DataRow({
5864
6019
  ] });
5865
6020
  }
5866
6021
  var colorClasses = {
5867
- primary: { bg: "bg-brand-primary/10", icon: "text-brand-primary" },
5868
- secondary: { bg: "bg-brand-secondary/10", icon: "text-brand-secondary" },
5869
- success: { bg: "bg-status-success/10", icon: "text-status-success" },
5870
- error: { bg: "bg-status-error/10", icon: "text-status-error" },
5871
- warning: { bg: "bg-status-warning/10", icon: "text-status-warning" },
5872
- info: { bg: "bg-status-info/10", icon: "text-status-info" },
6022
+ primary: { bg: "bg-brand-primary-subtle", icon: "text-brand-primary" },
6023
+ secondary: { bg: "bg-brand-secondary-subtle", icon: "text-brand-secondary" },
6024
+ success: { bg: "bg-status-success-subtle", icon: "text-status-success" },
6025
+ error: { bg: "bg-status-error-subtle", icon: "text-status-error" },
6026
+ warning: { bg: "bg-status-warning-subtle", icon: "text-status-warning" },
6027
+ info: { bg: "bg-status-info-subtle", icon: "text-status-info" },
5873
6028
  neutral: { bg: "bg-surface-elevated", icon: "text-text-secondary" }
5874
6029
  };
5875
6030
  var sizeClasses = {
@@ -6643,6 +6798,12 @@ function StepIndicator({
6643
6798
  upcoming: "bg-surface-base border-hairline-strong",
6644
6799
  error: "bg-status-error border-status-error"
6645
6800
  };
6801
+ const glyphStyles = {
6802
+ completed: "text-on-brand-primary",
6803
+ active: "text-on-brand-primary",
6804
+ upcoming: "text-text-secondary",
6805
+ error: "text-on-status-error"
6806
+ };
6646
6807
  return /* @__PURE__ */ jsx(
6647
6808
  reactNative.View,
6648
6809
  {
@@ -6651,16 +6812,7 @@ function StepIndicator({
6651
6812
  statusStyles2[status],
6652
6813
  className
6653
6814
  ),
6654
- children: icon || /* @__PURE__ */ jsx(
6655
- reactNative.Text,
6656
- {
6657
- className: cn(
6658
- "text-sm font-semibold",
6659
- status === "upcoming" ? "text-text-secondary" : "text-white"
6660
- ),
6661
- children: status === "completed" ? "\u2713" : index + 1
6662
- }
6663
- )
6815
+ children: icon || /* @__PURE__ */ jsx(reactNative.Text, { className: cn("text-sm font-semibold", glyphStyles[status]), children: status === "completed" ? "\u2713" : index + 1 })
6664
6816
  }
6665
6817
  );
6666
6818
  }
@@ -7030,8 +7182,8 @@ var baseBadgeSizeConfig = {
7030
7182
  var variantColors = {
7031
7183
  plain: { backgroundColor: t2["surface-raised"], borderColor: t2["hairline-default"] },
7032
7184
  pr: {
7033
- backgroundColor: "rgba(255, 121, 0, 0.12)",
7034
- borderColor: "rgba(255, 121, 0, 0.3)"
7185
+ backgroundColor: alpha(t2["brand-primary"], 0.12),
7186
+ borderColor: alpha(t2["brand-primary"], 0.3)
7035
7187
  }
7036
7188
  };
7037
7189
  function BaseBadge({
@@ -7261,67 +7413,6 @@ function PrBadge({
7261
7413
  }
7262
7414
  return badge;
7263
7415
  }
7264
-
7265
- // src/utils/colors.ts
7266
- function getStatusColor(status) {
7267
- return `var(--color-status-${status})`;
7268
- }
7269
- function getResultColor(result) {
7270
- return `var(--color-result-${result})`;
7271
- }
7272
- function alpha(color, opacity) {
7273
- const clampedOpacity = Math.max(0, Math.min(1, opacity));
7274
- if (color.startsWith("#")) {
7275
- const hex = color.slice(1);
7276
- let r, g, b;
7277
- if (hex.length === 3) {
7278
- r = parseInt(hex[0] + hex[0], 16);
7279
- g = parseInt(hex[1] + hex[1], 16);
7280
- b = parseInt(hex[2] + hex[2], 16);
7281
- } else if (hex.length === 6) {
7282
- r = parseInt(hex.slice(0, 2), 16);
7283
- g = parseInt(hex.slice(2, 4), 16);
7284
- b = parseInt(hex.slice(4, 6), 16);
7285
- } else {
7286
- return color;
7287
- }
7288
- return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
7289
- }
7290
- const rgbMatch = color.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);
7291
- if (rgbMatch) {
7292
- const [, r, g, b] = rgbMatch;
7293
- return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
7294
- }
7295
- const rgbaMatch = color.match(/rgba\((\d+),\s*(\d+),\s*(\d+),\s*[\d.]+\)/);
7296
- if (rgbaMatch) {
7297
- const [, r, g, b] = rgbaMatch;
7298
- return `rgba(${r}, ${g}, ${b}, ${clampedOpacity})`;
7299
- }
7300
- return color;
7301
- }
7302
- function getLuminance(color) {
7303
- if (!color.startsWith("#")) return "dark";
7304
- const hex = color.slice(1);
7305
- let r, g, b;
7306
- if (hex.length === 3) {
7307
- r = parseInt(hex[0] + hex[0], 16);
7308
- g = parseInt(hex[1] + hex[1], 16);
7309
- b = parseInt(hex[2] + hex[2], 16);
7310
- } else if (hex.length === 6) {
7311
- r = parseInt(hex.slice(0, 2), 16);
7312
- g = parseInt(hex.slice(2, 4), 16);
7313
- b = parseInt(hex.slice(4, 6), 16);
7314
- } else {
7315
- return "dark";
7316
- }
7317
- const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
7318
- return luminance > 0.5 ? "light" : "dark";
7319
- }
7320
- function getContrastText(backgroundColor) {
7321
- return getLuminance(backgroundColor) === "light" ? "#000000" : "#FFFFFF";
7322
- }
7323
-
7324
- // src/components/custom/Workout/StatusDot.tsx
7325
7416
  var solidFillToken = {
7326
7417
  success: "status-success",
7327
7418
  warning: "status-warning",
@@ -7617,7 +7708,7 @@ function formatPrescription(p) {
7617
7708
  return full.length > 0 ? full : null;
7618
7709
  }
7619
7710
  var METRIC_FONT = "Inter, sans-serif";
7620
- function MetricCell({ children, color, fontSize = 11 }) {
7711
+ function MetricCell({ children, color, fontSize = 11, weight = 600 }) {
7621
7712
  return /* @__PURE__ */ jsx(
7622
7713
  reactNative.Text,
7623
7714
  {
@@ -7625,7 +7716,7 @@ function MetricCell({ children, color, fontSize = 11 }) {
7625
7716
  fontFamily: METRIC_FONT,
7626
7717
  fontSize,
7627
7718
  color,
7628
- fontWeight: "600",
7719
+ fontWeight: String(weight),
7629
7720
  letterSpacing: 1
7630
7721
  },
7631
7722
  children
@@ -7972,7 +8063,10 @@ function DeviationBar({ deviation, width, className, ...props }) {
7972
8063
  width: resolvedWidth,
7973
8064
  borderRadius: 3,
7974
8065
  // react-native-web renders backgroundImage at runtime; not in RN ViewStyle types
7975
- backgroundImage: "linear-gradient(90deg, rgba(46,213,115,0.25) 0%, rgba(107,114,128,0.15) 50%, rgba(249,180,21,0.25) 100%)"
8066
+ // rgba(107,114,128,0.15) at 50% has no exact token match (nearest:
8067
+ // semanticPins.textSecondaryLight #65748B, ΔRGB ~12.7) — left as a
8068
+ // raw literal (VW-78).
8069
+ backgroundImage: `linear-gradient(90deg, ${alpha(t4["status-success"], 0.25)} 0%, rgba(107,114,128,0.15) 50%, ${alpha(t4["status-warning"], 0.25)} 100%)`
7976
8070
  }
7977
8071
  }
7978
8072
  ),
@@ -8003,7 +8097,7 @@ function DeviationBar({ deviation, width, className, ...props }) {
8003
8097
  var t5 = getSemanticColors("dark");
8004
8098
  var TRACK_BG = "#333333";
8005
8099
  var LABEL_COLOR = "#6B7280";
8006
- var TARGET_LINE_COLOR = "rgba(33, 150, 243, 0.5)";
8100
+ var TARGET_LINE_COLOR = alpha(t5["status-info"], 0.5);
8007
8101
  var AT_TARGET_GLOW = getGlowShadow(t5["status-info"], "subtle");
8008
8102
  var ZONE = {
8009
8103
  building: t5["status-success"],
@@ -8397,15 +8491,31 @@ function useLiveRepGrowth(active, liveRepIndex, liveVelocity, isNewPeak) {
8397
8491
  return liveGrowth;
8398
8492
  }
8399
8493
 
8494
+ // src/components/custom/charts/flatBarGeometry.ts
8495
+ var SET_LEVEL_FLAT_BAR = {
8496
+ /** Track height (px). */
8497
+ height: 8,
8498
+ /** Gap between segment slots (px) — also SetStrip's between-set gap, see `SEGMENTED_BAR_GAP`. */
8499
+ gap: 5,
8500
+ /** Corner radius (px). */
8501
+ radius: 2
8502
+ };
8503
+ var REP_LEVEL_FLAT_BAR = {
8504
+ /** Inter-bar gap is proportional (`gapRatio · barWidth`), floored at this many px. */
8505
+ gapFloor: 2,
8506
+ /** Corner radius (px) default. */
8507
+ radius: 5
8508
+ };
8509
+
8400
8510
  // src/components/custom/charts/SetBarChart.tsx
8401
- function mixHex(a, b, t18) {
8511
+ function mixHex(a, b, t19) {
8402
8512
  const parse = (h) => {
8403
8513
  const s = h.replace("#", "");
8404
8514
  return [parseInt(s.slice(0, 2), 16), parseInt(s.slice(2, 4), 16), parseInt(s.slice(4, 6), 16)];
8405
8515
  };
8406
8516
  const [ar, ag, ab] = parse(a);
8407
8517
  const [br, bg, bb] = parse(b);
8408
- const ch = (x, y) => Math.round(x + (y - x) * t18).toString(16).padStart(2, "0");
8518
+ const ch = (x, y) => Math.round(x + (y - x) * t19).toString(16).padStart(2, "0");
8409
8519
  return `#${ch(ar, br)}${ch(ag, bg)}${ch(ab, bb)}`;
8410
8520
  }
8411
8521
  var VARIABLE_FILL = primitiveRamps.cyan[900];
@@ -8413,7 +8523,7 @@ var CONTINUE_OUTLINE = primitiveRamps.cyan[800];
8413
8523
  var FIXED_MAX_VALUE = 1.15;
8414
8524
  var PEAK_HEADROOM = 1.03;
8415
8525
  function scaleDenominator(scale, maxValue) {
8416
- return scale === "fixed" ? FIXED_MAX_VALUE : maxValue * PEAK_HEADROOM;
8526
+ return (scale === "fixed" ? FIXED_MAX_VALUE : maxValue) * PEAK_HEADROOM;
8417
8527
  }
8418
8528
  function valueLabelFontSize(height) {
8419
8529
  return Math.round(Math.max(8, Math.min(12, height * 0.11)));
@@ -8429,12 +8539,12 @@ var SET_BAR_DEFAULT_HEIGHT = 220;
8429
8539
  var LABEL_ROW_HEIGHT = 16;
8430
8540
  var LABEL_GAP = 3;
8431
8541
  var GAP_RATIO = 0.08;
8432
- var MIN_BAR_GAP = 2;
8542
+ var MIN_BAR_GAP = REP_LEVEL_FLAT_BAR.gapFloor;
8433
8543
  var CHUNK_NOTCH_RATIO = 0.25;
8434
8544
  var CHUNK_NOTCH_MIN_PX = 10;
8435
8545
  var BAR_MAX_WIDTH = 120;
8436
8546
  var LABEL_MIN_BAR_WIDTH = 30;
8437
- var DEFAULT_BAR_RADIUS = 5;
8547
+ var DEFAULT_BAR_RADIUS = REP_LEVEL_FLAT_BAR.radius;
8438
8548
  var MIN_BAR_HEIGHT = 4;
8439
8549
  var FLAT_BAR_FRACTION = 0.5;
8440
8550
  var STUB_HEIGHT = 9;
@@ -9257,7 +9367,8 @@ function DualVelocityStrip({
9257
9367
  className,
9258
9368
  ...props
9259
9369
  }) {
9260
- const resolvedHeight = height ?? (variant === "hero" ? DUAL_HERO_HEIGHT : variant === "compact" ? DUAL_COMPACT_HEIGHT : DUAL_RAIL_HEIGHT);
9370
+ const resolvedVariant = variant === "rail" ? "dual-expanded" : variant;
9371
+ const resolvedHeight = height ?? (resolvedVariant === "hero" ? DUAL_HERO_HEIGHT : resolvedVariant === "compact" ? DUAL_COMPACT_HEIGHT : DUAL_RAIL_HEIGHT);
9261
9372
  const leftDone = streamDone(left);
9262
9373
  const rightDone = streamDone(right);
9263
9374
  const label = `Dual velocity chart, left ${leftDone.length} of ${Math.max(leftDone.length, targetReps ?? leftDone.length)} reps, right ${rightDone.length} of ${Math.max(rightDone.length, targetReps ?? rightDone.length)} reps`;
@@ -9277,8 +9388,9 @@ function DualVelocityStrip({
9277
9388
  label,
9278
9389
  viewProps: props
9279
9390
  };
9280
- if (variant === "rail") return /* @__PURE__ */ jsx(DualVelocityRail, { ...shared, liveRepIndex });
9281
- if (variant === "compact") return /* @__PURE__ */ jsx(DualVelocityCompactStrip, { ...shared });
9391
+ if (resolvedVariant === "dual-expanded")
9392
+ return /* @__PURE__ */ jsx(DualVelocityRail, { ...shared, liveRepIndex });
9393
+ if (resolvedVariant === "compact") return /* @__PURE__ */ jsx(DualVelocityCompactStrip, { ...shared });
9282
9394
  return /* @__PURE__ */ jsx(DualVelocityHero, { ...shared, liveRepIndex });
9283
9395
  }
9284
9396
  function VelocityStrip({
@@ -9891,7 +10003,9 @@ function SetRow(set) {
9891
10003
  }
9892
10004
  );
9893
10005
  }
9894
- var BRAND_PRIMARY = getSemanticColors("dark")["brand-primary"];
10006
+ var t6 = getSemanticColors("dark");
10007
+ var BRAND_PRIMARY = t6["brand-primary"];
10008
+ var ON_BRAND_PRIMARY = t6["on-brand-primary"];
9895
10009
  var INPUT_CLASSNAME = "bg-surface-raised border-hairline-strong text-text-primary";
9896
10010
  var inputStyle = {
9897
10011
  fontSize: 14,
@@ -10036,7 +10150,7 @@ function InputBar({
10036
10150
  fontSize: 13,
10037
10151
  fontWeight: "700",
10038
10152
  fontFamily: "Inter, sans-serif",
10039
- color: "#FFFFFF"
10153
+ color: ON_BRAND_PRIMARY
10040
10154
  },
10041
10155
  children: "Record"
10042
10156
  }
@@ -10056,7 +10170,7 @@ function RestActions({ onAddTime, onSkip }) {
10056
10170
  {
10057
10171
  onPress: onAddTime,
10058
10172
  style: {
10059
- backgroundColor: "rgba(255,255,255,0.06)",
10173
+ backgroundColor: alpha(primitiveColors.white, 0.06),
10060
10174
  paddingVertical: 8,
10061
10175
  paddingHorizontal: 20,
10062
10176
  borderRadius: 8
@@ -10079,7 +10193,7 @@ function RestActions({ onAddTime, onSkip }) {
10079
10193
  {
10080
10194
  onPress: onSkip,
10081
10195
  style: {
10082
- backgroundColor: "rgba(255,121,0,0.12)",
10196
+ backgroundColor: alpha(BRAND_PRIMARY2, 0.12),
10083
10197
  paddingVertical: 8,
10084
10198
  paddingHorizontal: 20,
10085
10199
  borderRadius: 8
@@ -10291,11 +10405,17 @@ function SetsRepsLoad({
10291
10405
  load,
10292
10406
  unit = "lb",
10293
10407
  fontSize,
10408
+ muted = false,
10294
10409
  className,
10295
10410
  ...props
10296
10411
  }) {
10297
- const value = useOnSurfaceColor("primary");
10298
- const sep = useOnSurfaceColor("tertiary");
10412
+ const primary = useOnSurfaceColor("primary");
10413
+ const tertiary = useOnSurfaceColor("tertiary");
10414
+ const secondary = useOnSurfaceColor("secondary");
10415
+ const value = muted ? secondary : primary;
10416
+ const sep = muted ? secondary : tertiary;
10417
+ const weight = muted ? 400 : 600;
10418
+ const times = muted ? TIMES : ` ${TIMES} `;
10299
10419
  return /* @__PURE__ */ jsxs(
10300
10420
  reactNative.View,
10301
10421
  {
@@ -10305,19 +10425,19 @@ function SetsRepsLoad({
10305
10425
  testID: "sets-reps-load",
10306
10426
  ...props,
10307
10427
  children: [
10308
- /* @__PURE__ */ jsx(MetricCell, { color: value, fontSize, children: sets }),
10309
- /* @__PURE__ */ jsx(MetricCell, { color: sep, fontSize, children: ` ${TIMES} ` }),
10310
- /* @__PURE__ */ jsx(MetricCell, { color: value, fontSize, children: reps }),
10311
- /* @__PURE__ */ jsx(MetricCell, { color: sep, fontSize, children: ` ${AT} ` }),
10312
- /* @__PURE__ */ jsx(MetricCell, { color: value, fontSize, children: load }),
10313
- /* @__PURE__ */ jsx(MetricCell, { color: sep, fontSize, children: ` ${unit}` })
10428
+ /* @__PURE__ */ jsx(MetricCell, { color: value, fontSize, weight, children: sets }),
10429
+ /* @__PURE__ */ jsx(MetricCell, { color: sep, fontSize, weight, children: times }),
10430
+ /* @__PURE__ */ jsx(MetricCell, { color: value, fontSize, weight, children: reps }),
10431
+ /* @__PURE__ */ jsx(MetricCell, { color: sep, fontSize, weight, children: ` ${AT} ` }),
10432
+ /* @__PURE__ */ jsx(MetricCell, { color: value, fontSize, weight, children: load }),
10433
+ /* @__PURE__ */ jsx(MetricCell, { color: sep, fontSize, weight, children: ` ${unit}` })
10314
10434
  ]
10315
10435
  }
10316
10436
  );
10317
10437
  }
10318
10438
  var PULSE_HALF_MS = 950;
10319
10439
  var PULSE_MIN_OPACITY = 0.45;
10320
- var SEGMENTED_BAR_GAP = 5;
10440
+ var SEGMENTED_BAR_GAP = SET_LEVEL_FLAT_BAR.gap;
10321
10441
  function usePulse2(active) {
10322
10442
  const [value] = React26.useState(() => new reactNative.Animated.Value(0));
10323
10443
  React26.useEffect(() => {
@@ -10345,9 +10465,9 @@ function usePulse2(active) {
10345
10465
  }
10346
10466
  function SegmentedBar({
10347
10467
  segments,
10348
- height = 8,
10468
+ height = SET_LEVEL_FLAT_BAR.height,
10349
10469
  gap = SEGMENTED_BAR_GAP,
10350
- radius = 2,
10470
+ radius = SET_LEVEL_FLAT_BAR.radius,
10351
10471
  marker = null,
10352
10472
  segmentTestID,
10353
10473
  style,
@@ -10708,41 +10828,102 @@ function ExerciseIndicator({ kind, onPress, className, ...props }) {
10708
10828
  }
10709
10829
  return chip;
10710
10830
  }
10711
- function headingLabel(name, sets, reps, load, unit) {
10712
- const loadLabel = typeof load === "number" ? roundWeight(load) : load;
10713
- return `${name}, ${sets}\xD7${reps} @ ${loadLabel} ${unit}`;
10831
+
10832
+ // src/components/custom/Workout/exerciseRowState.ts
10833
+ var ROW_STATE_TOKEN = {
10834
+ hovered: "interactive-hover",
10835
+ selected: "interactive-selected",
10836
+ pressed: "interactive-active"
10837
+ };
10838
+ function exerciseRowStateColor(state, mode = "dark") {
10839
+ return getSemanticColors(mode)[ROW_STATE_TOKEN[state]];
10840
+ }
10841
+ function exerciseLiveColor(mode = "dark") {
10842
+ return getSemanticColors(mode)["status-live"];
10843
+ }
10844
+
10845
+ // src/components/custom/Workout/ExerciseHeading.tsx
10846
+ var DIMMED_OPACITY = 0.55;
10847
+ function prescriptionText(p, unit) {
10848
+ if (p.prescription !== void 0) return p.prescription;
10849
+ if (p.sets === void 0) return void 0;
10850
+ const loadLabel = typeof p.load === "number" ? roundWeight(p.load) : p.load;
10851
+ return `${p.sets}\xD7${p.reps} @ ${loadLabel} ${unit}`;
10852
+ }
10853
+ function exerciseHeadingLabel(p, unit = p.unit ?? "lbs") {
10854
+ const prescription = prescriptionText(p, unit);
10855
+ return prescription ? `${p.name}, ${prescription}` : p.name;
10856
+ }
10857
+ function pressProps(p, unit) {
10858
+ return {
10859
+ onPress: p.onPress,
10860
+ onPressIn: p.onPressIn,
10861
+ onPressOut: p.onPressOut,
10862
+ onHoverIn: p.onHoverIn,
10863
+ onHoverOut: p.onHoverOut,
10864
+ accessibilityRole: "button",
10865
+ accessibilityLabel: exerciseHeadingLabel(p, unit)
10866
+ };
10714
10867
  }
10715
- function ExerciseHeading({
10868
+ function HeadingName({
10716
10869
  name,
10717
- sets,
10718
- reps,
10719
- load,
10720
- unit = "lbs",
10721
- tempo,
10722
- indicator,
10723
- dimmed,
10724
- onPress
10870
+ nameStyle,
10871
+ className
10725
10872
  }) {
10726
- return /* @__PURE__ */ jsxs(reactNative.View, { style: { opacity: dimmed ? 0.55 : 1 }, testID: "exercise-heading", children: [
10873
+ return (
10874
+ // The row is a button label, not a heading, so `boldLabel` carries the weight and
10875
+ // no header role has to be undone. Size and the Space Grotesk face are pinned.
10876
+ /* @__PURE__ */ jsx(
10877
+ Typography,
10878
+ {
10879
+ variant: "boldLabel",
10880
+ color: nameStyle ? "inherit" : "primary",
10881
+ style: nameStyle,
10882
+ className: cn("font-heading text-sm leading-[normal]", className),
10883
+ testID: "exercise-card-name",
10884
+ children: name
10885
+ }
10886
+ )
10887
+ );
10888
+ }
10889
+ function prescriptionNode(p, unit) {
10890
+ if (p.prescription !== void 0) {
10891
+ return /* @__PURE__ */ jsx(
10892
+ Typography,
10893
+ {
10894
+ variant: "caption",
10895
+ color: "secondary",
10896
+ maxLines: 1,
10897
+ className: "font-sans shrink leading-[normal]",
10898
+ testID: "exercise-card-prescription",
10899
+ children: p.prescription
10900
+ }
10901
+ );
10902
+ }
10903
+ if (p.sets === void 0) return null;
10904
+ return /* @__PURE__ */ jsx(
10905
+ SetsRepsLoad,
10906
+ {
10907
+ sets: p.sets,
10908
+ reps: p.reps,
10909
+ load: p.load,
10910
+ unit,
10911
+ muted: p.mutedPrescription
10912
+ }
10913
+ );
10914
+ }
10915
+ function StackedHeading({ heading, nameStyle }) {
10916
+ const { unit = "lbs", tempo, indicator } = heading;
10917
+ return /* @__PURE__ */ jsxs(jsxRuntime.Fragment, { children: [
10727
10918
  /* @__PURE__ */ jsxs(
10728
10919
  reactNative.Pressable,
10729
10920
  {
10730
- onPress,
10731
- accessibilityRole: "button",
10732
- accessibilityLabel: headingLabel(name, sets, reps, load, unit),
10921
+ ...pressProps(heading, unit),
10733
10922
  className: "flex-row items-center",
10734
10923
  style: { gap: 8 },
10735
10924
  testID: "exercise-card-header",
10736
10925
  children: [
10737
- /* @__PURE__ */ jsx(
10738
- Typography,
10739
- {
10740
- variant: "boldLabel",
10741
- className: "font-heading text-sm leading-[normal]",
10742
- testID: "exercise-card-name",
10743
- children: name
10744
- }
10745
- ),
10926
+ /* @__PURE__ */ jsx(HeadingName, { name: heading.name, nameStyle }),
10746
10927
  /* @__PURE__ */ jsx(reactNative.View, { className: "flex-1" }),
10747
10928
  indicator && /* @__PURE__ */ jsx(ExerciseIndicator, { kind: indicator })
10748
10929
  ]
@@ -10755,7 +10936,7 @@ function ExerciseHeading({
10755
10936
  style: { gap: 8, marginTop: 1 },
10756
10937
  testID: "exercise-card-summary",
10757
10938
  children: [
10758
- /* @__PURE__ */ jsx(SetsRepsLoad, { sets, reps, load, unit }),
10939
+ prescriptionNode(heading, unit),
10759
10940
  /* @__PURE__ */ jsx(reactNative.View, { className: "flex-1" }),
10760
10941
  tempo && /* @__PURE__ */ jsx(TempoDisplay, { tempo, size: "sm", showLabel: false, showInfo: false })
10761
10942
  ]
@@ -10763,20 +10944,148 @@ function ExerciseHeading({
10763
10944
  )
10764
10945
  ] });
10765
10946
  }
10766
- function ExerciseCardHeading({
10767
- setStates,
10768
- stripHeight = 8,
10769
- dimmed,
10770
- testID = "exercise-card",
10771
- ...heading
10772
- }) {
10947
+ function InlineHeading({ heading, nameStyle }) {
10948
+ const { unit = "lbs", indicator, previousBest } = heading;
10949
+ const Row = heading.pressTarget === "ancestor" ? reactNative.View : reactNative.Pressable;
10773
10950
  return /* @__PURE__ */ jsxs(
10774
- reactNative.View,
10951
+ Row,
10952
+ {
10953
+ ...heading.pressTarget === "ancestor" ? {} : pressProps(heading, unit),
10954
+ className: "flex-row items-center",
10955
+ style: { gap: 8 },
10956
+ testID: "exercise-card-header",
10957
+ children: [
10958
+ /* @__PURE__ */ jsx(HeadingName, { name: heading.name, nameStyle, className: "shrink-0" }),
10959
+ /* @__PURE__ */ jsx(reactNative.View, { className: "shrink flex-row items-center", testID: "exercise-card-summary", children: prescriptionNode(heading, unit) }),
10960
+ /* @__PURE__ */ jsx(reactNative.View, { className: "flex-1", style: { minWidth: 8 } }),
10961
+ indicator && /* @__PURE__ */ jsx(ExerciseIndicator, { kind: indicator }),
10962
+ previousBest && /* @__PURE__ */ jsx(
10963
+ Typography,
10964
+ {
10965
+ variant: "caption",
10966
+ color: "tertiary",
10967
+ maxLines: 1,
10968
+ className: "font-sans shrink text-2xs leading-[normal]",
10969
+ testID: "exercise-card-previous-best",
10970
+ children: previousBest
10971
+ }
10972
+ )
10973
+ ]
10974
+ }
10975
+ );
10976
+ }
10977
+ function ExerciseHeading(props) {
10978
+ const mode = useSurfaceMode();
10979
+ const nameStyle = props.isLive ? { color: exerciseLiveColor(mode) } : void 0;
10980
+ return /* @__PURE__ */ jsx(reactNative.View, { style: { opacity: props.dimmed ? DIMMED_OPACITY : 1 }, testID: "exercise-heading", children: props.layout === "inline" ? /* @__PURE__ */ jsx(InlineHeading, { heading: props, nameStyle }) : /* @__PURE__ */ jsx(StackedHeading, { heading: props, nameStyle }) });
10981
+ }
10982
+ var DENSITY = {
10983
+ rail: {
10984
+ paddingVertical: 9,
10985
+ paddingHorizontal: 12,
10986
+ layout: "stacked",
10987
+ dimOpacity: 0.55,
10988
+ dimByDefault: false,
10989
+ mutedPrescription: false
10990
+ },
10991
+ compact: {
10992
+ paddingVertical: 12,
10993
+ paddingHorizontal: 14,
10994
+ layout: "inline",
10995
+ dimOpacity: 0.55,
10996
+ dimByDefault: false,
10997
+ mutedPrescription: true
10998
+ },
10999
+ upcoming: {
11000
+ paddingVertical: 12,
11001
+ paddingHorizontal: 14,
11002
+ layout: "inline",
11003
+ dimOpacity: 0.6,
11004
+ dimByDefault: true,
11005
+ mutedPrescription: true
11006
+ }
11007
+ };
11008
+ function useRowInteraction() {
11009
+ const { hovered: rowHovered, hoverProps } = useHoverState();
11010
+ const [headingHovered, setHeadingHovered] = React26.useState(false);
11011
+ const [pressed, setPressed] = React26.useState(false);
11012
+ return {
11013
+ hoverProps,
11014
+ pressed,
11015
+ hovered: rowHovered || headingHovered,
11016
+ headingHandlers: {
11017
+ onHoverIn: () => setHeadingHovered(true),
11018
+ onHoverOut: () => setHeadingHovered(false),
11019
+ onPressIn: () => setPressed(true),
11020
+ onPressOut: () => setPressed(false)
11021
+ }
11022
+ };
11023
+ }
11024
+ function rowWash(mode, state) {
11025
+ if (state.pressed) return exerciseRowStateColor("pressed", mode);
11026
+ if (state.isSelected) return exerciseRowStateColor("selected", mode);
11027
+ if (state.hovered) return exerciseRowStateColor("hovered", mode);
11028
+ return void 0;
11029
+ }
11030
+ function prescriptionProps(p) {
11031
+ const base = { name: p.name };
11032
+ if (p.prescription !== void 0) return { ...base, prescription: p.prescription };
11033
+ if (p.sets === void 0) return base;
11034
+ return { ...base, sets: p.sets, reps: p.reps, load: p.load };
11035
+ }
11036
+ function ExerciseCardHeading(props) {
11037
+ const {
11038
+ density = "rail",
11039
+ setStates = [],
11040
+ stripHeight = 8,
11041
+ dimmed,
11042
+ isSelected = false,
11043
+ isLive = false,
11044
+ testID = "exercise-card",
11045
+ style
11046
+ } = props;
11047
+ const spec = DENSITY[density];
11048
+ const { hoverProps, pressed, hovered, headingHandlers } = useRowInteraction();
11049
+ const wash = rowWash(useSurfaceMode(), { pressed, isSelected, hovered });
11050
+ const rowIsButton = spec.layout === "inline";
11051
+ const Root = rowIsButton ? reactNative.Pressable : reactNative.View;
11052
+ const rootPress = rowIsButton ? {
11053
+ ...headingHandlers,
11054
+ onPress: props.onPress,
11055
+ accessibilityRole: "button",
11056
+ accessibilityLabel: exerciseHeadingLabel(props)
11057
+ } : {};
11058
+ return /* @__PURE__ */ jsxs(
11059
+ Root,
10775
11060
  {
10776
- style: { paddingVertical: 9, paddingHorizontal: 12, opacity: dimmed ? 0.55 : 1 },
11061
+ ...hoverProps,
11062
+ ...rootPress,
11063
+ style: [
11064
+ {
11065
+ paddingVertical: spec.paddingVertical,
11066
+ paddingHorizontal: spec.paddingHorizontal,
11067
+ opacity: dimmed ?? spec.dimByDefault ? spec.dimOpacity : 1
11068
+ },
11069
+ wash ? { backgroundColor: wash } : null,
11070
+ style
11071
+ ],
10777
11072
  testID,
10778
11073
  children: [
10779
- /* @__PURE__ */ jsx(ExerciseHeading, { ...heading }),
11074
+ /* @__PURE__ */ jsx(
11075
+ ExerciseHeading,
11076
+ {
11077
+ ...prescriptionProps(props),
11078
+ ...rowIsButton ? { pressTarget: "ancestor" } : headingHandlers,
11079
+ unit: props.unit,
11080
+ tempo: props.tempo,
11081
+ indicator: props.indicator,
11082
+ previousBest: props.previousBest,
11083
+ onPress: rowIsButton ? void 0 : props.onPress,
11084
+ layout: spec.layout,
11085
+ mutedPrescription: spec.mutedPrescription,
11086
+ isLive
11087
+ }
11088
+ ),
10780
11089
  setStates.length > 0 && /* @__PURE__ */ jsx(reactNative.View, { style: { marginTop: 7 }, testID: "exercise-card-strip", children: /* @__PURE__ */ jsx(SetStrip, { sets: setStates, height: stripHeight }) })
10781
11090
  ]
10782
11091
  }
@@ -10870,103 +11179,58 @@ function getSupersetMargin(position) {
10870
11179
  }
10871
11180
  return {};
10872
11181
  }
10873
- function formatSummary(summary) {
10874
- if (!summary) return "";
10875
- return `${summary.sets}\xD7${summary.reps} @ ${roundWeight(summary.weight)} ${summary.unit}`;
11182
+ function supersetChrome(position) {
11183
+ return { ...getSupersetBorderRadius(position), ...getSupersetMargin(position) };
10876
11184
  }
10877
- function formatAccessibilityLabel(name, summary, prescription) {
10878
- if (summary) return `${name}, ${formatSummary(summary)}`;
10879
- if (prescription) return `${name}, ${prescription}`;
10880
- return name;
11185
+ function deriveCollapsedSetStates(setVelocities, totalPlannedSets, plannedReps2) {
11186
+ const done = (setVelocities ?? []).map(
11187
+ (velocities) => ({ status: "done", velocities })
11188
+ );
11189
+ const remaining = Math.max(0, (totalPlannedSets ?? 0) - done.length);
11190
+ return [
11191
+ ...done,
11192
+ ...Array.from(
11193
+ { length: remaining },
11194
+ () => ({ status: "todo", planned: plannedReps2 })
11195
+ )
11196
+ ];
10881
11197
  }
10882
11198
  function CollapsedCard({
10883
11199
  name,
10884
11200
  onToggle,
10885
11201
  summary,
10886
11202
  isPR,
11203
+ indicator,
10887
11204
  setVelocities,
10888
- velocityZones,
11205
+ setStates,
10889
11206
  totalPlannedSets,
10890
- supersetPosition
11207
+ stripHeight,
11208
+ supersetPosition,
11209
+ isSelected,
11210
+ isLive
10891
11211
  }) {
10892
- const [pressed, setPressed] = React26.useState(false);
10893
- const completedSets = setVelocities?.length ?? 0;
10894
- const remaining = Math.max(0, (totalPlannedSets ?? 0) - completedSets);
10895
- const borderRadius = getSupersetBorderRadius(supersetPosition);
10896
- const supersetMargin = getSupersetMargin(supersetPosition);
10897
- return /* @__PURE__ */ jsx(
10898
- reactNative.Pressable,
11212
+ const plannedReps2 = typeof summary?.reps === "number" ? summary.reps : 0;
11213
+ const row = {
11214
+ density: "compact",
11215
+ name,
11216
+ indicator: indicator ?? (isPR ? "pr" : void 0),
11217
+ setStates: setStates ?? deriveCollapsedSetStates(setVelocities, totalPlannedSets, plannedReps2),
11218
+ stripHeight,
11219
+ isSelected,
11220
+ isLive,
11221
+ onPress: onToggle,
11222
+ style: supersetChrome(supersetPosition)
11223
+ };
11224
+ return summary ? /* @__PURE__ */ jsx(
11225
+ ExerciseCardHeading,
10899
11226
  {
10900
- onPress: onToggle,
10901
- onPressIn: () => setPressed(true),
10902
- onPressOut: () => setPressed(false),
10903
- accessibilityRole: "button",
10904
- accessibilityLabel: formatAccessibilityLabel(name, summary, void 0),
10905
- testID: "exercise-card",
10906
- children: /* @__PURE__ */ jsxs(
10907
- reactNative.View,
10908
- {
10909
- className: pressed ? "bg-surface-raised" : void 0,
10910
- style: {
10911
- padding: 12,
10912
- paddingHorizontal: 14,
10913
- cursor: "pointer",
10914
- ...borderRadius,
10915
- ...supersetMargin
10916
- },
10917
- children: [
10918
- /* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-center", testID: "exercise-card-header", children: [
10919
- /* @__PURE__ */ jsx(
10920
- Typography,
10921
- {
10922
- variant: "h6",
10923
- color: "primary",
10924
- className: "text-sm font-bold leading-[normal]",
10925
- testID: "exercise-card-name",
10926
- children: name
10927
- }
10928
- ),
10929
- /* @__PURE__ */ jsx(reactNative.View, { className: "flex-1" }),
10930
- summary && /* The demo's "body" face is Inter, which is the library's `font-sans`
10931
- (the mapping B1 established for PrBadge), not Typography's `font-body`. */
10932
- /* @__PURE__ */ jsx(
10933
- Typography,
10934
- {
10935
- variant: "caption",
10936
- color: "secondary",
10937
- className: "font-sans mr-2 leading-[normal]",
10938
- testID: "exercise-card-summary",
10939
- children: formatSummary(summary)
10940
- }
10941
- ),
10942
- isPR && /* @__PURE__ */ jsx(reactNative.View, { style: { marginLeft: 4 }, children: /* @__PURE__ */ jsx(PrBadge, { type: "e1rm", compact: true, animate: false }) })
10943
- ] }),
10944
- (completedSets > 0 || remaining > 0) && /* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row", style: { marginTop: 6, gap: 4 }, testID: "exercise-card-strips", children: [
10945
- setVelocities?.map((velocities, i) => /* @__PURE__ */ jsx(
10946
- VelocityStrip,
10947
- {
10948
- velocities,
10949
- zones: velocityZones,
10950
- variant: "compact",
10951
- height: 8,
10952
- hideBaseline: true,
10953
- testID: `exercise-card-velocity-strip-${i}`
10954
- },
10955
- i
10956
- )),
10957
- Array.from({ length: remaining }, (_, i) => /* @__PURE__ */ jsx(
10958
- PlaceholderStrip,
10959
- {
10960
- testID: `exercise-card-placeholder-${i}`
10961
- },
10962
- `placeholder-${i}`
10963
- ))
10964
- ] })
10965
- ]
10966
- }
10967
- )
11227
+ ...row,
11228
+ sets: summary.sets,
11229
+ reps: summary.reps,
11230
+ load: summary.weight,
11231
+ unit: summary.unit
10968
11232
  }
10969
- );
11233
+ ) : /* @__PURE__ */ jsx(ExerciseCardHeading, { ...row });
10970
11234
  }
10971
11235
  function deriveHeaderSetStates(sets) {
10972
11236
  return sets.map((set) => {
@@ -10991,10 +11255,9 @@ function ExpandedCard({
10991
11255
  setStates,
10992
11256
  stripHeight = 8,
10993
11257
  velocityZones,
10994
- supersetPosition
11258
+ supersetPosition,
11259
+ isLive
10995
11260
  }) {
10996
- const borderRadius = getSupersetBorderRadius(supersetPosition);
10997
- const supersetMargin = getSupersetMargin(supersetPosition);
10998
11261
  const unit = summary?.unit ?? sets?.[0]?.unit ?? "lbs";
10999
11262
  const headerStates = setStates ?? (sets ? deriveHeaderSetStates(sets) : []);
11000
11263
  const headerIndicator = indicator ?? (isPR ? "pr" : void 0);
@@ -11002,11 +11265,7 @@ function ExpandedCard({
11002
11265
  reactNative.View,
11003
11266
  {
11004
11267
  className: "bg-surface-elevated border-hairline",
11005
- style: {
11006
- borderWidth: 1,
11007
- ...borderRadius,
11008
- ...supersetMargin
11009
- },
11268
+ style: { borderWidth: 1, ...supersetChrome(supersetPosition) },
11010
11269
  testID: "exercise-card",
11011
11270
  children: [
11012
11271
  /* @__PURE__ */ jsx(
@@ -11021,6 +11280,7 @@ function ExpandedCard({
11021
11280
  indicator: headerIndicator,
11022
11281
  setStates: headerStates,
11023
11282
  stripHeight,
11283
+ isLive,
11024
11284
  onPress: onToggle,
11025
11285
  testID: "exercise-card-heading"
11026
11286
  }
@@ -11048,62 +11308,21 @@ function UpcomingCard({
11048
11308
  name,
11049
11309
  prescription,
11050
11310
  previousBest,
11311
+ indicator,
11051
11312
  supersetPosition,
11313
+ isSelected,
11052
11314
  onToggle
11053
11315
  }) {
11054
- const borderRadius = getSupersetBorderRadius(supersetPosition);
11055
- const supersetMargin = getSupersetMargin(supersetPosition);
11056
- return /* @__PURE__ */ jsx(reactNative.Pressable, { onPress: onToggle, accessibilityRole: "button", children: /* @__PURE__ */ jsx(
11057
- reactNative.View,
11058
- {
11059
- style: {
11060
- opacity: 0.6,
11061
- padding: 12,
11062
- paddingHorizontal: 14,
11063
- ...borderRadius,
11064
- ...supersetMargin
11065
- },
11066
- accessibilityLabel: formatAccessibilityLabel(name, void 0, prescription),
11067
- testID: "exercise-card",
11068
- children: /* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-center", children: [
11069
- /* @__PURE__ */ jsx(
11070
- Typography,
11071
- {
11072
- variant: "h6",
11073
- color: "primary",
11074
- className: "shrink-0 text-sm font-bold leading-[normal]",
11075
- testID: "exercise-card-name",
11076
- children: name
11077
- }
11078
- ),
11079
- prescription && /* @__PURE__ */ jsx(
11080
- Typography,
11081
- {
11082
- variant: "caption",
11083
- color: "secondary",
11084
- maxLines: 1,
11085
- className: "font-sans shrink ml-2 leading-[normal]",
11086
- testID: "exercise-card-prescription",
11087
- children: prescription
11088
- }
11089
- ),
11090
- /* @__PURE__ */ jsx(reactNative.View, { className: "flex-1", style: { minWidth: 8 } }),
11091
- previousBest && /* 11px is off the type scale; `2xs` (10px) is the step below, as B2's
11092
- WorkoutCard date took for the same size. */
11093
- /* @__PURE__ */ jsx(
11094
- Typography,
11095
- {
11096
- variant: "caption",
11097
- color: "tertiary",
11098
- maxLines: 1,
11099
- className: "font-sans shrink text-2xs leading-[normal]",
11100
- testID: "exercise-card-previous-best",
11101
- children: previousBest
11102
- }
11103
- )
11104
- ] })
11105
- }
11106
- ) });
11316
+ const row = {
11317
+ density: "upcoming",
11318
+ name,
11319
+ previousBest,
11320
+ indicator,
11321
+ isSelected,
11322
+ onPress: onToggle,
11323
+ style: supersetChrome(supersetPosition)
11324
+ };
11325
+ return prescription !== void 0 ? /* @__PURE__ */ jsx(ExerciseCardHeading, { ...row, prescription }) : /* @__PURE__ */ jsx(ExerciseCardHeading, { ...row });
11107
11326
  }
11108
11327
  function ExerciseCard({
11109
11328
  upcoming,
@@ -11711,7 +11930,7 @@ var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY3, BRAND_PRIMARY_LIGHT];
11711
11930
  function heatmapColor(percentage) {
11712
11931
  const clamped = Math.max(0, Math.min(100, percentage));
11713
11932
  const opacity = 0.12 + clamped / 100 * 0.78;
11714
- return `rgba(255,121,0,${opacity.toFixed(3)})`;
11933
+ return alpha(BRAND_PRIMARY3, opacity);
11715
11934
  }
11716
11935
  function MesoCard({
11717
11936
  name,
@@ -12054,12 +12273,13 @@ function PrHistoryModal({
12054
12273
  }
12055
12274
  );
12056
12275
  }
12057
- var t6 = getSemanticColors("dark");
12058
- var BRAND_PRIMARY5 = t6["brand-primary"];
12059
- var BRAND_PRIMARY_SUBTLE = "rgba(255,121,0,0.12)";
12060
- var STATUS_SUCCESS2 = t6["status-success"];
12061
- var STATUS_WARNING2 = t6["status-warning"];
12062
- var STATUS_ERROR2 = t6["status-error"];
12276
+ var t7 = getSemanticColors("dark");
12277
+ var BRAND_PRIMARY5 = t7["brand-primary"];
12278
+ var ON_BRAND_PRIMARY2 = t7["on-brand-primary"];
12279
+ var BRAND_PRIMARY_SUBTLE = alpha(BRAND_PRIMARY5, 0.12);
12280
+ var STATUS_SUCCESS2 = t7["status-success"];
12281
+ var STATUS_WARNING2 = t7["status-warning"];
12282
+ var STATUS_ERROR2 = t7["status-error"];
12063
12283
  var EMOJI_SETS = {
12064
12284
  sleep: ["\u{1F634}", "\u{1F610}", "\u{1F642}", "\u{1F60A}", "\u{1F929}"],
12065
12285
  soreness: ["\u{1F635}", "\u{1F623}", "\u{1F610}", "\u{1F642}", "\u{1F4AA}"],
@@ -12256,7 +12476,7 @@ function ReadinessCheck({
12256
12476
  fontSize: 13,
12257
12477
  fontWeight: "700",
12258
12478
  fontFamily: "Inter, sans-serif",
12259
- color: "#FFFFFF"
12479
+ color: ON_BRAND_PRIMARY2
12260
12480
  },
12261
12481
  children: "Start Workout"
12262
12482
  }
@@ -12265,20 +12485,20 @@ function ReadinessCheck({
12265
12485
  )
12266
12486
  ] }) });
12267
12487
  }
12268
- var t7 = getSemanticColors("dark");
12269
- var BRAND_PRIMARY6 = t7["brand-primary"];
12488
+ var t8 = getSemanticColors("dark");
12489
+ var BRAND_PRIMARY6 = t8["brand-primary"];
12270
12490
  var BRAND_PRIMARY_DARK2 = MESO_ACCENT_GRADIENT_DARK;
12271
12491
  var BRAND_PRIMARY_LIGHT2 = MESO_ACCENT_GRADIENT_LIGHT;
12272
- var SUCCESS = t7["status-success"];
12273
- var WARNING = t7["status-warning"];
12274
- var ERROR = t7["status-error"];
12492
+ var SUCCESS = t8["status-success"];
12493
+ var WARNING = t8["status-warning"];
12494
+ var ERROR = t8["status-error"];
12275
12495
  var ACCENT_STOPS2 = [BRAND_PRIMARY_DARK2, BRAND_PRIMARY6, BRAND_PRIMARY_LIGHT2];
12276
12496
  var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
12277
- 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%)";
12497
+ var GAUGE_GRADIENT = `linear-gradient(90deg, ${alpha(SUCCESS, 0.25)} 0%, ${alpha(WARNING, 0.25)} 50%, ${alpha(ERROR, 0.25)} 100%)`;
12278
12498
  var STATUS_VARIANTS = {
12279
- success: { bg: "rgba(46,213,115,0.15)", border: "rgba(46,213,115,0.3)", text: SUCCESS },
12280
- warning: { bg: "rgba(249,180,21,0.15)", border: "rgba(249,180,21,0.3)", text: WARNING },
12281
- error: { bg: "rgba(209,67,67,0.15)", border: "rgba(209,67,67,0.25)", text: ERROR }
12499
+ success: { bg: alpha(SUCCESS, 0.15), border: alpha(SUCCESS, 0.3), text: SUCCESS },
12500
+ warning: { bg: alpha(WARNING, 0.15), border: alpha(WARNING, 0.3), text: WARNING },
12501
+ error: { bg: alpha(ERROR, 0.15), border: alpha(ERROR, 0.25), text: ERROR }
12282
12502
  };
12283
12503
  function clamp01(value) {
12284
12504
  if (!Number.isFinite(value)) return 0;
@@ -12431,7 +12651,7 @@ function Gauge({ gauge }) {
12431
12651
  bottom: 0,
12432
12652
  width: 1,
12433
12653
  marginLeft: -0.5,
12434
- backgroundColor: "rgba(255,255,255,0.3)"
12654
+ backgroundColor: alpha(primitiveColors.white, 0.3)
12435
12655
  },
12436
12656
  testID: "meso-status-card-gauge-center"
12437
12657
  }
@@ -12540,9 +12760,9 @@ function MesoStatusCard({
12540
12760
  reactNative.View,
12541
12761
  {
12542
12762
  style: {
12543
- backgroundColor: "rgba(249,180,21,0.06)",
12763
+ backgroundColor: alpha(WARNING, 0.06),
12544
12764
  borderWidth: 1,
12545
- borderColor: "rgba(249,180,21,0.15)",
12765
+ borderColor: alpha(WARNING, 0.15),
12546
12766
  borderRadius: 8,
12547
12767
  paddingVertical: 10,
12548
12768
  paddingHorizontal: 12
@@ -12568,9 +12788,9 @@ function MesoStatusCard({
12568
12788
  className: "flex-row items-center",
12569
12789
  style: {
12570
12790
  gap: 8,
12571
- backgroundColor: "rgba(46,213,115,0.06)",
12791
+ backgroundColor: alpha(SUCCESS, 0.06),
12572
12792
  borderWidth: 1,
12573
- borderColor: "rgba(46,213,115,0.2)",
12793
+ borderColor: alpha(SUCCESS, 0.2),
12574
12794
  borderRadius: 8,
12575
12795
  paddingVertical: 10,
12576
12796
  paddingHorizontal: 12
@@ -12605,16 +12825,16 @@ var PROJECTION_LINE_COLOR = resolveColor("text-tertiary");
12605
12825
  var STATUS_SUCCESS3 = sem["status-success"];
12606
12826
  var STATUS_ERROR3 = sem["status-error"];
12607
12827
  var STATUS_WARNING3 = sem["status-warning"];
12608
- var GRID_LINE = "rgba(255,255,255,0.06)";
12609
- var SUCCESS_PILL_BG = "rgba(46,213,115,0.10)";
12610
- var SUCCESS_PILL_BORDER = "rgba(46,213,115,0.20)";
12611
- var ERROR_PILL_BG = "rgba(209,67,67,0.10)";
12612
- var ERROR_PILL_BORDER = "rgba(209,67,67,0.20)";
12828
+ var GRID_LINE = alpha(primitiveColors.white, 0.06);
12829
+ var SUCCESS_PILL_BG = alpha(STATUS_SUCCESS3, 0.1);
12830
+ var SUCCESS_PILL_BORDER = alpha(STATUS_SUCCESS3, 0.2);
12831
+ var ERROR_PILL_BG = alpha(STATUS_ERROR3, 0.1);
12832
+ var ERROR_PILL_BORDER = alpha(STATUS_ERROR3, 0.2);
12613
12833
  var PLOT_LEFT = 26;
12614
12834
  var TOOLTIP_WIDTH = 124;
12615
12835
  function timeOf(dateStr) {
12616
- const t18 = Date.parse(dateStr);
12617
- return Number.isNaN(t18) ? 0 : t18;
12836
+ const t19 = Date.parse(dateStr);
12837
+ return Number.isNaN(t19) ? 0 : t19;
12618
12838
  }
12619
12839
  function formatValue(value) {
12620
12840
  return `${Math.round(value)}`;
@@ -12854,7 +13074,7 @@ function StrengthTrendChart({
12854
13074
  height,
12855
13075
  borderLeftWidth: 1,
12856
13076
  borderStyle: "dashed",
12857
- borderLeftColor: "rgba(255,255,255,0.10)"
13077
+ borderLeftColor: alpha(primitiveColors.white, 0.1)
12858
13078
  }
12859
13079
  },
12860
13080
  `boundary-${i}`
@@ -13122,14 +13342,14 @@ function StrengthTrendChart({
13122
13342
  )
13123
13343
  ] });
13124
13344
  }
13125
- var t8 = getSemanticColors("dark");
13126
- var STATUS_SUCCESS4 = t8["status-success"];
13127
- var STATUS_WARNING4 = t8["status-warning"];
13128
- var STATUS_INFO = t8["status-info"];
13345
+ var t9 = getSemanticColors("dark");
13346
+ var STATUS_SUCCESS4 = t9["status-success"];
13347
+ var STATUS_WARNING4 = t9["status-warning"];
13348
+ var STATUS_INFO = t9["status-info"];
13129
13349
  var DOT_BORDER = "#F3F4F6";
13130
- var BAND_FILL = "rgba(46,213,115,0.1)";
13131
- var BAND_EDGE = "rgba(46,213,115,0.45)";
13132
- var PROJECTION_FILL = "rgba(46,213,115,0.05)";
13350
+ var BAND_FILL = alpha(STATUS_SUCCESS4, 0.1);
13351
+ var BAND_EDGE = alpha(STATUS_SUCCESS4, 0.45);
13352
+ var PROJECTION_FILL = alpha(STATUS_SUCCESS4, 0.05);
13133
13353
  var PADDING_LEFT = 28;
13134
13354
  var PADDING_RIGHT = 10;
13135
13355
  var PADDING_TOP = 8;
@@ -13168,8 +13388,8 @@ function interpEdge(pixels, x, key) {
13168
13388
  const a = pixels[i];
13169
13389
  const b = pixels[i + 1];
13170
13390
  if (x >= a.x && x <= b.x) {
13171
- const t18 = b.x === a.x ? 0 : (x - a.x) / (b.x - a.x);
13172
- return a[key] + t18 * (b[key] - a[key]);
13391
+ const t19 = b.x === a.x ? 0 : (x - a.x) / (b.x - a.x);
13392
+ return a[key] + t19 * (b[key] - a[key]);
13173
13393
  }
13174
13394
  }
13175
13395
  return pixels[pixels.length - 1][key];
@@ -13534,10 +13754,10 @@ function CapacityBandChart({
13534
13754
  }
13535
13755
  );
13536
13756
  }
13537
- var t9 = getSemanticColors("dark");
13757
+ var t10 = getSemanticColors("dark");
13538
13758
  var DEFAULT_TRACK_COLOR = greyRamp[800];
13539
13759
  var DEFAULT_MARKER_COLOR2 = primitiveColors.white;
13540
- var TICK_COLOR = t9["text-tertiary"];
13760
+ var TICK_COLOR = t10["text-tertiary"];
13541
13761
  var ZONE_SIZES = {
13542
13762
  default: {
13543
13763
  trackHeight: 14,
@@ -13720,7 +13940,7 @@ function ZoneTrack({
13720
13940
  ),
13721
13941
  ticks?.map((tick, i) => {
13722
13942
  const emphasized = tick.emphasized === true;
13723
- const lineColor = tick.color ?? (emphasized ? t9["brand-primary"] : TICK_COLOR);
13943
+ const lineColor = tick.color ?? (emphasized ? t10["brand-primary"] : TICK_COLOR);
13724
13944
  const lineWidth = emphasized ? s.tickLineEmphasized : s.tickLineNormal;
13725
13945
  return /* @__PURE__ */ jsx(
13726
13946
  reactNative.View,
@@ -13751,7 +13971,7 @@ function ZoneTrack({
13751
13971
  if (tick.label == null) return null;
13752
13972
  const emphasized = tick.emphasized === true;
13753
13973
  if (!showTickLabel(i, emphasized)) return null;
13754
- const labelColor = tick.color ?? (emphasized ? t9["brand-primary"] : TICK_COLOR);
13974
+ const labelColor = tick.color ?? (emphasized ? t10["brand-primary"] : TICK_COLOR);
13755
13975
  const labelNode = /* @__PURE__ */ jsx(
13756
13976
  reactNative.Text,
13757
13977
  {
@@ -13983,7 +14203,7 @@ function StatusPill2({ status, label, className, ...props }) {
13983
14203
  }
13984
14204
  );
13985
14205
  }
13986
- var t10 = getSemanticColors("dark");
14206
+ var t11 = getSemanticColors("dark");
13987
14207
  var categoryToken = {
13988
14208
  productive: null,
13989
14209
  threshold: "status-warning",
@@ -13996,7 +14216,7 @@ var floodOpacity = {
13996
14216
  };
13997
14217
  function liveAuraColor(category) {
13998
14218
  const token = categoryToken[category];
13999
- return token ? t10[token] : null;
14219
+ return token ? t11[token] : null;
14000
14220
  }
14001
14221
  function LiveAuraFrame({
14002
14222
  category,
@@ -14025,9 +14245,9 @@ function LiveAuraFrame({
14025
14245
  position: "relative",
14026
14246
  overflow: "hidden",
14027
14247
  borderRadius: 10,
14028
- backgroundColor: t10["background-base"],
14248
+ backgroundColor: t11["background-base"],
14029
14249
  borderWidth: 1,
14030
- borderColor: t10["hairline-default"]
14250
+ borderColor: t11["hairline-default"]
14031
14251
  },
14032
14252
  style
14033
14253
  ],
@@ -14134,14 +14354,14 @@ function panelBodySplit(bodyHeight, layout) {
14134
14354
  }
14135
14355
 
14136
14356
  // src/components/custom/Fatigue/fatigue-tokens.ts
14137
- var t11 = getSemanticColors("dark");
14357
+ var t12 = getSemanticColors("dark");
14138
14358
  var FONT_HEAD = '"Space Grotesk", sans-serif';
14139
14359
  var FONT_UI = '"Nunito Sans", sans-serif';
14140
14360
  var FONT_MONO = "monospace";
14141
14361
  var TONE_COLOR = {
14142
- ok: t11["status-success"],
14143
- warn: t11["status-warning"],
14144
- alarm: t11["status-error"]
14362
+ ok: t12["status-success"],
14363
+ warn: t12["status-warning"],
14364
+ alarm: t12["status-error"]
14145
14365
  };
14146
14366
  var STATE_LABEL = {
14147
14367
  good: "Good",
@@ -14200,13 +14420,13 @@ function auraForVerdict(state) {
14200
14420
  }
14201
14421
 
14202
14422
  // src/components/custom/Fatigue/VerdictHero.tsx
14203
- var t12 = getSemanticColors("dark");
14423
+ var t13 = getSemanticColors("dark");
14204
14424
  function formatRpe(rpe) {
14205
14425
  if (rpe == null) return "\u2014";
14206
14426
  return (Math.round(rpe * 2) / 2).toFixed(1);
14207
14427
  }
14208
14428
  function VerdictHero({ rpe, verdict }) {
14209
- const tone = verdict ? TONE_COLOR[verdict.tone] : t12["text-tertiary"];
14429
+ const tone = verdict ? TONE_COLOR[verdict.tone] : t13["text-tertiary"];
14210
14430
  const word = verdict ? STATE_LABEL[verdict.state] : "Warming up";
14211
14431
  return /* @__PURE__ */ jsxs(reactNative.View, { style: { gap: 6 }, testID: "verdict-hero", children: [
14212
14432
  /* @__PURE__ */ jsx(
@@ -14216,7 +14436,7 @@ function VerdictHero({ rpe, verdict }) {
14216
14436
  fontSize: 9,
14217
14437
  letterSpacing: 1.5,
14218
14438
  fontFamily: FONT_MONO,
14219
- color: t12["text-tertiary"]
14439
+ color: t13["text-tertiary"]
14220
14440
  },
14221
14441
  children: "FATIGUE"
14222
14442
  }
@@ -14255,7 +14475,7 @@ function VerdictHero({ rpe, verdict }) {
14255
14475
  ] })
14256
14476
  ] });
14257
14477
  }
14258
- var t13 = getSemanticColors("dark");
14478
+ var t14 = getSemanticColors("dark");
14259
14479
  var TONE_VARIANT = {
14260
14480
  ok: "success",
14261
14481
  warn: "warning",
@@ -14283,7 +14503,7 @@ function Light({
14283
14503
  fontSize: 9,
14284
14504
  letterSpacing: 0.6,
14285
14505
  fontFamily: FONT_MONO,
14286
- color: t13["text-secondary"]
14506
+ color: t14["text-secondary"]
14287
14507
  },
14288
14508
  children: label
14289
14509
  }
@@ -14392,14 +14612,14 @@ function RomProgressionChart({
14392
14612
  }
14393
14613
 
14394
14614
  // src/components/custom/Fatigue/tempo-pacing.ts
14395
- var t14 = getSemanticColors("dark");
14615
+ var t15 = getSemanticColors("dark");
14396
14616
  var ON_TARGET_MS2 = 100;
14397
14617
  function phaseFillFraction(elapsedMs, targetMs) {
14398
14618
  if (targetMs == null || targetMs <= 0) return 1;
14399
14619
  return Math.min(1, Math.max(0, elapsedMs / targetMs));
14400
14620
  }
14401
14621
  function pacingTone(elapsedMs, targetMs) {
14402
- if (targetMs == null || targetMs <= 0) return t14["text-primary"];
14622
+ if (targetMs == null || targetMs <= 0) return t15["text-primary"];
14403
14623
  const remainingMs = targetMs - elapsedMs;
14404
14624
  if (remainingMs > ON_TARGET_MS2) return PACING_TONE.ahead;
14405
14625
  if (remainingMs >= -ON_TARGET_MS2) return PACING_TONE.onPace;
@@ -14415,11 +14635,11 @@ function prescribedSegments(tempo) {
14415
14635
  ["hold", pauseTop]
14416
14636
  ];
14417
14637
  const out = [];
14418
- let t18 = 0;
14638
+ let t19 = 0;
14419
14639
  for (const [phase, seconds] of order) {
14420
14640
  const ms = seconds * 1e3;
14421
- if (ms > 0) out.push({ phase, startMs: t18, endMs: t18 + ms });
14422
- t18 += ms;
14641
+ if (ms > 0) out.push({ phase, startMs: t19, endMs: t19 + ms });
14642
+ t19 += ms;
14423
14643
  }
14424
14644
  return out;
14425
14645
  }
@@ -14443,7 +14663,7 @@ function phaseTargetsMs(phases, tempo) {
14443
14663
  }
14444
14664
 
14445
14665
  // src/components/custom/Fatigue/GhostBand.tsx
14446
- var t15 = getSemanticColors("dark");
14666
+ var t16 = getSemanticColors("dark");
14447
14667
  var BAND_H = 16;
14448
14668
  var BAND_GAP = 4;
14449
14669
  var PHASE_LABEL = {
@@ -14463,7 +14683,7 @@ function GhostBand({
14463
14683
  top,
14464
14684
  height = BAND_H,
14465
14685
  showLabels = false,
14466
- labelColor = t15["text-primary"],
14686
+ labelColor = t16["text-primary"],
14467
14687
  targetTempoSeconds = null,
14468
14688
  prescribed = false
14469
14689
  }) {
@@ -14578,8 +14798,8 @@ function GhostBand({
14578
14798
  ] })
14579
14799
  ] });
14580
14800
  }
14581
- var t16 = getSemanticColors("dark");
14582
- var PARCH = t16["text-primary"];
14801
+ var t17 = getSemanticColors("dark");
14802
+ var PARCH = t17["text-primary"];
14583
14803
  function smoothPath(pts) {
14584
14804
  if (pts.length < 2) return pts.length ? `M ${pts[0][0]} ${pts[0][1]}` : "";
14585
14805
  let d = `M ${pts[0][0].toFixed(1)} ${pts[0][1].toFixed(1)}`;
@@ -14725,7 +14945,7 @@ function GhostSpark({
14725
14945
  var PAD = 18;
14726
14946
  var GHOST_GUTTER = 4;
14727
14947
  function LiveFatigueCard({ model, width = 318, height }) {
14728
- const t18 = getSemanticColors(useSurfaceMode());
14948
+ const t19 = getSemanticColors(useSurfaceMode());
14729
14949
  const chartW = width - PAD * 2 - GHOST_GUTTER * 2;
14730
14950
  const chartH = cardChartHeight(height);
14731
14951
  return /* @__PURE__ */ jsxs(
@@ -14739,8 +14959,8 @@ function LiveFatigueCard({ model, width = 318, height }) {
14739
14959
  borderRadius: 14,
14740
14960
  padding: PAD,
14741
14961
  borderWidth: 1,
14742
- borderColor: t18["hairline-default"],
14743
- ...barPaper(t18["surface-base"])
14962
+ borderColor: t19["hairline-default"],
14963
+ ...barPaper(t19["surface-base"])
14744
14964
  },
14745
14965
  children: [
14746
14966
  /* @__PURE__ */ jsxs(reactNative.View, { style: { gap: 12 }, children: [
@@ -14843,7 +15063,7 @@ function LiveFatiguePanel({
14843
15063
  }
14844
15064
  );
14845
15065
  }
14846
- var t17 = getSemanticColors("dark");
15066
+ var t18 = getSemanticColors("dark");
14847
15067
  function phaseAt(segments, ms) {
14848
15068
  const hit = segments.find((s) => ms >= s.startMs && ms < s.endMs);
14849
15069
  return hit ? hit.phase : null;
@@ -14908,7 +15128,7 @@ function DualGhostSpark({
14908
15128
  cur,
14909
15129
  current: cur ? toPts(cur) : [],
14910
15130
  ghosts: curves.slice(0, -1).map(toPts),
14911
- tint: cur ? ghostLineColor(cur.tempoDeviation, cur.grindSignature) : t17["text-tertiary"]
15131
+ tint: cur ? ghostLineColor(cur.tempoDeviation, cur.grindSignature) : t18["text-tertiary"]
14912
15132
  };
14913
15133
  };
14914
15134
  const up = wing(left);
@@ -14942,7 +15162,7 @@ function DualGhostSpark({
14942
15162
  x,
14943
15163
  top: bandTop,
14944
15164
  showLabels: true,
14945
- labelColor: alpha(t17["text-primary"], 0.92),
15165
+ labelColor: alpha(t18["text-primary"], 0.92),
14946
15166
  targetTempoSeconds
14947
15167
  }
14948
15168
  ),
@@ -14956,7 +15176,7 @@ function DualGhostSpark({
14956
15176
  fontWeight: 800,
14957
15177
  letterSpacing: 1,
14958
15178
  fontFamily: FONT_UI,
14959
- fill: t17["text-tertiary"],
15179
+ fill: t18["text-tertiary"],
14960
15180
  children: leftLabel
14961
15181
  }
14962
15182
  ),
@@ -14969,7 +15189,7 @@ function DualGhostSpark({
14969
15189
  fontWeight: 800,
14970
15190
  letterSpacing: 1,
14971
15191
  fontFamily: FONT_UI,
14972
- fill: t17["text-tertiary"],
15192
+ fill: t18["text-tertiary"],
14973
15193
  children: rightLabel
14974
15194
  }
14975
15195
  )
@@ -15060,6 +15280,7 @@ function Treemap({
15060
15280
  {
15061
15281
  id: "__more__",
15062
15282
  value: restValue,
15283
+ // VW-82: no token at this value (nearest surface-overlay #373635); proposed, not swapped.
15063
15284
  color: "#3a3a3a",
15064
15285
  label: `+${clean.length - (maxTiles - 1)} more`
15065
15286
  }
@@ -15087,20 +15308,21 @@ function Treemap({
15087
15308
  borderRadius: 3,
15088
15309
  opacity: selected ? 1 : 0.9,
15089
15310
  borderWidth: selected ? 2 : 0,
15090
- borderColor: "#ffffff",
15311
+ borderColor: primitiveColors.white,
15091
15312
  padding: 4,
15092
15313
  overflow: "hidden"
15093
15314
  },
15094
- children: labelFits2 && /* @__PURE__ */ jsx(reactNative.Text, { numberOfLines: 2, className: "text-[10px] font-semibold text-[#0b0b0b]", children: r.datum.label ?? r.datum.id })
15315
+ children: labelFits2 && // VW-82: label on a data-coloured tile; no on-data token exists yet.
15316
+ /* @__PURE__ */ jsx(reactNative.Text, { numberOfLines: 2, className: "text-[10px] font-semibold text-[#0b0b0b]", children: r.datum.label ?? r.datum.id })
15095
15317
  },
15096
15318
  r.datum.id
15097
15319
  );
15098
15320
  }) });
15099
15321
  }
15100
15322
  var PALETTE2 = DATAVIZ_CATEGORICAL_PALETTE;
15101
- var GRID_LINE2 = "rgba(255,255,255,0.07)";
15102
- var AXIS_LINE = "rgba(255,255,255,0.18)";
15103
- var DIAGONAL_LINE = "rgba(255,255,255,0.28)";
15323
+ var GRID_LINE2 = alpha(primitiveColors.white, 0.07);
15324
+ var AXIS_LINE = alpha(primitiveColors.white, 0.18);
15325
+ var DIAGONAL_LINE = alpha(primitiveColors.white, 0.28);
15104
15326
  var DEFAULT_R = 6;
15105
15327
  var PLOT_LEFT2 = 40;
15106
15328
  var PLOT_RIGHT = 12;
@@ -15195,8 +15417,8 @@ function Scatter({
15195
15417
  testID: "scatter-canvas",
15196
15418
  style: { position: "absolute", top: 0, left: 0, width, height, overflow: "hidden" },
15197
15419
  children: [
15198
- ticksOf(yd, TICK_COUNT).map((t18, i) => {
15199
- const y = toY(t18);
15420
+ ticksOf(yd, TICK_COUNT).map((t19, i) => {
15421
+ const y = toY(t19);
15200
15422
  return /* @__PURE__ */ jsx(
15201
15423
  reactNative.View,
15202
15424
  {
@@ -15221,15 +15443,15 @@ function Scatter({
15221
15443
  width: PLOT_LEFT2 - 6,
15222
15444
  textAlign: "right"
15223
15445
  },
15224
- children: formatTick(t18)
15446
+ children: formatTick(t19)
15225
15447
  }
15226
15448
  )
15227
15449
  },
15228
15450
  `y-${i}`
15229
15451
  );
15230
15452
  }),
15231
- ticksOf(xd, TICK_COUNT).map((t18, i) => {
15232
- const x = toX(t18);
15453
+ ticksOf(xd, TICK_COUNT).map((t19, i) => {
15454
+ const x = toX(t19);
15233
15455
  return /* @__PURE__ */ jsx(
15234
15456
  reactNative.View,
15235
15457
  {
@@ -15254,7 +15476,7 @@ function Scatter({
15254
15476
  width: 32,
15255
15477
  textAlign: "center"
15256
15478
  },
15257
- children: formatTick(t18)
15479
+ children: formatTick(t19)
15258
15480
  }
15259
15481
  )
15260
15482
  },
@@ -15360,7 +15582,7 @@ function Scatter({
15360
15582
  backgroundColor: p.color,
15361
15583
  opacity: selected ? 1 : 0.82,
15362
15584
  borderWidth: selected ? 2 : 0,
15363
- borderColor: "#ffffff"
15585
+ borderColor: primitiveColors.white
15364
15586
  },
15365
15587
  children: showLabel && /* @__PURE__ */ jsx(
15366
15588
  reactNative.Text,
@@ -15388,7 +15610,7 @@ var sem2 = getSemanticColors("dark");
15388
15610
  var STATUS_SUCCESS5 = sem2["status-success"];
15389
15611
  var STATUS_WARNING5 = sem2["status-warning"];
15390
15612
  var STATUS_ERROR4 = sem2["status-error"];
15391
- var TRACK = "rgba(255,255,255,0.08)";
15613
+ var TRACK = alpha(primitiveColors.white, 0.08);
15392
15614
  var DEFAULT_THRESHOLDS2 = [
15393
15615
  { value: 0, color: STATUS_ERROR4 },
15394
15616
  { value: 60, color: STATUS_WARNING5 },
@@ -15459,23 +15681,23 @@ function Gauge2({
15459
15681
  testID: "gauge",
15460
15682
  ...props,
15461
15683
  children: [
15462
- ticks.map((t18) => /* @__PURE__ */ jsx(
15684
+ ticks.map((t19) => /* @__PURE__ */ jsx(
15463
15685
  reactNative.View,
15464
15686
  {
15465
15687
  accessibilityElementsHidden: true,
15466
15688
  testID: "gauge-segment",
15467
15689
  style: {
15468
15690
  position: "absolute",
15469
- left: t18.left - tickThickness / 2,
15470
- top: t18.top - tickLength / 2,
15691
+ left: t19.left - tickThickness / 2,
15692
+ top: t19.top - tickLength / 2,
15471
15693
  width: tickThickness,
15472
15694
  height: tickLength,
15473
15695
  borderRadius: tickThickness / 2,
15474
- backgroundColor: t18.color,
15475
- transform: [{ rotate: t18.rotate }]
15696
+ backgroundColor: t19.color,
15697
+ transform: [{ rotate: t19.rotate }]
15476
15698
  }
15477
15699
  },
15478
- t18.key
15700
+ t19.key
15479
15701
  )),
15480
15702
  /* @__PURE__ */ jsxs(
15481
15703
  reactNative.View,
@@ -16124,7 +16346,7 @@ var TASK_COMPARATORS = {
16124
16346
  function SeverityLegend({ tasks }) {
16125
16347
  const counts = React26.useMemo(() => {
16126
16348
  const c2 = { critical: 0, high: 0, medium: 0, low: 0 };
16127
- for (const t18 of tasks) if (t18.severity) c2[t18.severity]++;
16349
+ for (const t19 of tasks) if (t19.severity) c2[t19.severity]++;
16128
16350
  return c2;
16129
16351
  }, [tasks]);
16130
16352
  return /* @__PURE__ */ jsx(reactNative.View, { className: "flex-row items-center gap-3", children: SEVERITY_ORDER.map((severity) => /* @__PURE__ */ jsxs(reactNative.View, { className: "flex-row items-center gap-1.5", children: [
@@ -16546,7 +16768,7 @@ function SessionDetail({
16546
16768
  }) {
16547
16769
  const refs = React26.useMemo(() => extractTaskRefs(session.body), [session.body]);
16548
16770
  const touched = React26.useMemo(
16549
- () => refs.map((id) => tasks.find((t18) => t18.id === id)).filter((t18) => !!t18),
16771
+ () => refs.map((id) => tasks.find((t19) => t19.id === id)).filter((t19) => !!t19),
16550
16772
  [refs, tasks]
16551
16773
  );
16552
16774
  const body = React26.useMemo(() => stripLeadingHeading(session.body), [session.body]);
@@ -16630,7 +16852,7 @@ function StepButton({
16630
16852
  Typography,
16631
16853
  {
16632
16854
  variant: "body2",
16633
- className: cn("leading-none", disabled ? "text-text-tertiary/40" : "text-text-secondary"),
16855
+ className: cn("leading-none", disabled ? "text-text-disabled" : "text-text-secondary"),
16634
16856
  children: glyph
16635
16857
  }
16636
16858
  )
@@ -17600,6 +17822,9 @@ exports.defaultPreset = defaultPreset;
17600
17822
  exports.discreteRainbow = discreteRainbow;
17601
17823
  exports.divergingScale = divergingScale;
17602
17824
  exports.elevationPlane = elevationPlane;
17825
+ exports.exerciseHeadingLabel = exerciseHeadingLabel;
17826
+ exports.exerciseLiveColor = exerciseLiveColor;
17827
+ exports.exerciseRowStateColor = exerciseRowStateColor;
17603
17828
  exports.extractTaskRefs = extractTaskRefs;
17604
17829
  exports.fitColumns = fitColumns;
17605
17830
  exports.formatCompact = formatCompact;
@@ -17672,6 +17897,7 @@ exports.raisedLevel = raisedLevel;
17672
17897
  exports.resolveColor = resolveColor;
17673
17898
  exports.resolveIndicator = resolveIndicator;
17674
17899
  exports.resolveSurfaceDepth = resolveSurfaceDepth;
17900
+ exports.resultPaletteColors = resultPaletteColors;
17675
17901
  exports.rgbToHex = rgbToHex;
17676
17902
  exports.rgbToHsv = rgbToHsv;
17677
17903
  exports.roundRpe = roundRpe;
@@ -17680,6 +17906,7 @@ exports.roundWeight = roundWeight;
17680
17906
  exports.rpeColor = rpeColor;
17681
17907
  exports.semanticColorsDark = semanticColorsDark;
17682
17908
  exports.semanticColorsLight = semanticColorsLight;
17909
+ exports.semanticPins = semanticPins;
17683
17910
  exports.semanticTypography = semanticTypography;
17684
17911
  exports.sequentialEffort = sequentialEffort;
17685
17912
  exports.sessionLinkers = sessionLinkers;