@titan-design/react-ui 0.12.1 → 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 (531) hide show
  1. package/README.md +60 -47
  2. package/dist/bodymap.js +856 -736
  3. package/dist/bodymap.js.map +1 -1
  4. package/dist/bodymap.mjs +858 -738
  5. package/dist/bodymap.mjs.map +1 -1
  6. package/dist/index.d.mts +1431 -237
  7. package/dist/index.d.ts +1431 -237
  8. package/dist/index.js +6506 -4781
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +6280 -4642
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/{pages-B1hqnGIC.d.ts → pages-CsjsUn0G.d.ts} +51 -16
  13. package/dist/{pages-CvsFqNtx.d.mts → pages-ZbT_pD_U.d.mts} +51 -16
  14. package/dist/pages.d.mts +1 -1
  15. package/dist/pages.d.ts +1 -1
  16. package/dist/pages.js +1919 -1937
  17. package/dist/pages.js.map +1 -1
  18. package/dist/pages.mjs +1927 -1945
  19. package/dist/pages.mjs.map +1 -1
  20. package/dist/theme/index.d.mts +225 -140
  21. package/dist/theme/index.d.ts +225 -140
  22. package/dist/theme/index.js +298 -319
  23. package/dist/theme/index.js.map +1 -1
  24. package/dist/theme/index.mjs +283 -315
  25. package/dist/theme/index.mjs.map +1 -1
  26. package/dist/theme/tokens-css.js +145 -24
  27. package/dist/theme/tokens-css.js.map +1 -1
  28. package/dist/theme/tokens-css.mjs +145 -24
  29. package/dist/theme/tokens-css.mjs.map +1 -1
  30. package/dist/theme/tokens.d.mts +128 -11
  31. package/dist/theme/tokens.d.ts +128 -11
  32. package/dist/theme/tokens.js +126 -26
  33. package/dist/theme/tokens.js.map +1 -1
  34. package/dist/theme/tokens.mjs +124 -27
  35. package/dist/theme/tokens.mjs.map +1 -1
  36. package/docs/audits/2026-09-08-critique-addenda.md +51 -0
  37. package/docs/audits/2026-09-08-library-critique.md +212 -0
  38. package/docs/library-roadmap.md +99 -0
  39. package/docs/render-testing-pattern.md +130 -0
  40. package/package.json +1 -1
  41. package/src/arch/Architecture.stories.tsx +3 -1
  42. package/src/arch/arch-graph.freshness.test.ts +52 -0
  43. package/src/arch/arch-graph.json +4989 -1583
  44. package/src/components/custom/ActiveWork/CoChangeChip.stories.tsx +44 -0
  45. package/src/components/custom/ActiveWork/CoChangeChip.test.tsx +29 -0
  46. package/src/components/custom/ActiveWork/CoChangeChip.tsx +48 -0
  47. package/src/components/custom/ActiveWork/Eyebrow.stories.tsx +25 -0
  48. package/src/components/custom/ActiveWork/Eyebrow.test.tsx +16 -0
  49. package/src/components/custom/ActiveWork/Eyebrow.tsx +26 -0
  50. package/src/components/custom/ActiveWork/FileActivityDetail.stories.tsx +50 -0
  51. package/src/components/custom/ActiveWork/FileActivityDetail.test.tsx +66 -0
  52. package/src/components/custom/ActiveWork/FileActivityDetail.tsx +202 -0
  53. package/src/components/custom/ActiveWork/FileActivityRow.stories.tsx +70 -0
  54. package/src/components/custom/ActiveWork/FileActivityRow.test.tsx +67 -0
  55. package/src/components/custom/ActiveWork/FileActivityRow.tsx +130 -0
  56. package/src/components/custom/ActiveWork/FileHistoryExplorer.stories.tsx +84 -0
  57. package/src/components/custom/ActiveWork/FileHistoryExplorer.test.tsx +99 -0
  58. package/src/components/custom/ActiveWork/FileHistoryExplorer.tsx +138 -0
  59. package/src/components/custom/ActiveWork/FilePathLabel.stories.tsx +39 -0
  60. package/src/components/custom/ActiveWork/FilePathLabel.test.tsx +53 -0
  61. package/src/components/custom/ActiveWork/FilePathLabel.tsx +63 -0
  62. package/src/components/custom/ActiveWork/InitiativeBrief.stories.tsx +50 -0
  63. package/src/components/custom/ActiveWork/InitiativeBrief.test.tsx +62 -0
  64. package/src/components/custom/ActiveWork/InitiativeBrief.tsx +182 -0
  65. package/src/components/custom/ActiveWork/InitiativeCard.stories.tsx +73 -0
  66. package/src/components/custom/ActiveWork/InitiativeCard.test.tsx +68 -0
  67. package/src/components/custom/ActiveWork/InitiativeCard.tsx +136 -0
  68. package/src/components/custom/ActiveWork/InitiativeHeader.stories.tsx +59 -0
  69. package/src/components/custom/ActiveWork/InitiativeHeader.test.tsx +40 -0
  70. package/src/components/custom/ActiveWork/InitiativeHeader.tsx +73 -0
  71. package/src/components/custom/ActiveWork/InitiativeReader.stories.tsx +145 -0
  72. package/src/components/custom/ActiveWork/OpenLoops.stories.tsx +58 -0
  73. package/src/components/custom/ActiveWork/OpenLoops.test.tsx +61 -0
  74. package/src/components/custom/ActiveWork/OpenLoops.tsx +107 -0
  75. package/src/components/custom/ActiveWork/PortfolioOverview.stories.tsx +101 -0
  76. package/src/components/custom/ActiveWork/PortfolioOverview.test.tsx +81 -0
  77. package/src/components/custom/ActiveWork/PortfolioOverview.tsx +83 -0
  78. package/src/components/custom/ActiveWork/README.md +305 -0
  79. package/src/components/custom/ActiveWork/SessionDetail.stories.tsx +71 -0
  80. package/src/components/custom/ActiveWork/SessionDetail.test.tsx +84 -0
  81. package/src/components/custom/ActiveWork/SessionDetail.tsx +180 -0
  82. package/src/components/custom/ActiveWork/SessionList.stories.tsx +69 -0
  83. package/src/components/custom/ActiveWork/SessionList.test.tsx +78 -0
  84. package/src/components/custom/ActiveWork/SessionList.tsx +103 -0
  85. package/src/components/custom/ActiveWork/SessionListItem.stories.tsx +64 -0
  86. package/src/components/custom/ActiveWork/SessionListItem.test.tsx +62 -0
  87. package/src/components/custom/ActiveWork/SessionListItem.tsx +152 -0
  88. package/src/components/custom/ActiveWork/SessionReader.stories.tsx +113 -0
  89. package/src/components/custom/ActiveWork/SeverityLabel.stories.tsx +51 -0
  90. package/src/components/custom/ActiveWork/SeverityLabel.test.tsx +68 -0
  91. package/src/components/custom/ActiveWork/SeverityLabel.tsx +97 -0
  92. package/src/components/custom/ActiveWork/TaskRow.stories.tsx +63 -0
  93. package/src/components/custom/ActiveWork/TaskRow.test.tsx +112 -0
  94. package/src/components/custom/ActiveWork/TaskRow.tsx +176 -0
  95. package/src/components/custom/ActiveWork/TaskTable.stories.tsx +123 -0
  96. package/src/components/custom/ActiveWork/TaskTable.test.tsx +233 -0
  97. package/src/components/custom/ActiveWork/TaskTable.tsx +321 -0
  98. package/src/components/custom/ActiveWork/active-work-depth.test.tsx +102 -0
  99. package/src/components/custom/ActiveWork/file-history-fixture.ts +91 -0
  100. package/src/components/custom/ActiveWork/format-time.test.ts +23 -0
  101. package/src/components/custom/ActiveWork/format-time.ts +32 -0
  102. package/src/components/custom/ActiveWork/index.ts +19 -0
  103. package/src/components/custom/ActiveWork/initiative-fixture.ts +104 -0
  104. package/src/components/custom/ActiveWork/session-fixture.ts +267 -0
  105. package/src/components/custom/ActiveWork/session-linkers.ts +56 -0
  106. package/src/components/custom/ActiveWork/task-list-fixture.ts +97 -0
  107. package/src/components/custom/CircularTimer/CircularTimer.stories.tsx +12 -6
  108. package/src/components/custom/DateTime/DateTime.stories.tsx +2 -1
  109. package/src/components/custom/DateTime/DateTime.test.tsx +3 -1
  110. package/src/components/custom/EmptyState/EmptyState.stories.tsx +22 -9
  111. package/src/components/custom/EmptyState/EmptyState.test.tsx +7 -13
  112. package/src/components/custom/EmptyState/EmptyState.tsx +4 -18
  113. package/src/components/custom/Fatigue/DualGhostSpark.stories.tsx +4 -3
  114. package/src/components/custom/Fatigue/FatigueLights.stories.tsx +2 -2
  115. package/src/components/custom/Fatigue/GhostSpark.stories.tsx +4 -3
  116. package/src/components/custom/Fatigue/LiveFatigueCard.stories.tsx +2 -2
  117. package/src/components/custom/Fatigue/LiveFatigueCard.tsx +8 -4
  118. package/src/components/custom/Fatigue/LiveFatiguePanel.stories.tsx +116 -6
  119. package/src/components/custom/Fatigue/LiveFatiguePanel.test.tsx +134 -0
  120. package/src/components/custom/Fatigue/LiveFatiguePanel.tsx +54 -83
  121. package/src/components/custom/Fatigue/README.md +40 -3
  122. package/src/components/custom/Fatigue/RomProgressionChart.stories.tsx +2 -2
  123. package/src/components/custom/Fatigue/SilverRedPalette.stories.tsx +2 -1
  124. package/src/components/custom/Fatigue/VelocityHero.stories.tsx +4 -3
  125. package/src/components/custom/Fatigue/VerdictHero.stories.tsx +2 -2
  126. package/src/components/custom/Fatigue/fatigue-mock.test.ts +0 -5
  127. package/src/components/custom/Fatigue/fatigue-mock.ts +2 -10
  128. package/src/components/custom/Fatigue/fatigue-tokens.ts +12 -0
  129. package/src/components/custom/Fatigue/index.ts +17 -5
  130. package/src/components/custom/Fatigue/panel-layout.test.ts +149 -0
  131. package/src/components/custom/Fatigue/panel-layout.ts +185 -0
  132. package/src/components/custom/Gauge/Gauge.stories.tsx +6 -3
  133. package/src/components/custom/Gauge/Gauge.test.tsx +1 -1
  134. package/src/components/custom/Gauge/Gauge.tsx +7 -2
  135. package/src/components/custom/Metric/Metric.stories.tsx +10 -1
  136. package/src/components/custom/Metric/Metric.test.tsx +1 -3
  137. package/src/components/custom/Metric/Metric.tsx +5 -20
  138. package/src/components/custom/Prose/MarkdownProse.stories.tsx +88 -0
  139. package/src/components/custom/Prose/MarkdownProse.test.tsx +87 -0
  140. package/src/components/custom/Prose/MarkdownProse.tsx +201 -0
  141. package/src/components/custom/Prose/README.md +58 -0
  142. package/src/components/custom/Prose/index.ts +1 -0
  143. package/src/components/custom/Scatter/Scatter.stories.tsx +55 -14
  144. package/src/components/custom/Scatter/Scatter.test.tsx +2 -2
  145. package/src/components/custom/Scatter/Scatter.tsx +122 -18
  146. package/src/components/custom/Sidebar/Sidebar.stories.tsx +41 -8
  147. package/src/components/custom/Sidebar/Sidebar.test.tsx +5 -1
  148. package/src/components/custom/Sidebar/Sidebar.tsx +16 -33
  149. package/src/components/custom/Table/Table.stories.tsx +99 -16
  150. package/src/components/custom/Table/Table.test.tsx +273 -86
  151. package/src/components/custom/Table/Table.tsx +159 -67
  152. package/src/components/custom/Table/column-fit.test.ts +75 -0
  153. package/src/components/custom/Table/column-fit.ts +116 -0
  154. package/src/components/custom/Table/index.ts +9 -0
  155. package/src/components/custom/TimerReadout/TimerReadout.stories.tsx +8 -6
  156. package/src/components/custom/Treemap/Treemap.stories.tsx +15 -12
  157. package/src/components/custom/Treemap/Treemap.test.tsx +1 -1
  158. package/src/components/custom/Treemap/Treemap.tsx +11 -3
  159. package/src/components/custom/Typography/Typography.stories.tsx +28 -1
  160. package/src/components/custom/Typography/Typography.test.tsx +34 -0
  161. package/src/components/custom/Typography/Typography.tsx +6 -0
  162. package/src/components/custom/Typography/index.ts +1 -8
  163. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +11 -2
  164. package/src/components/custom/Workout/BaseBadge.stories.tsx +27 -11
  165. package/src/components/custom/Workout/BaseBadge.test.tsx +31 -11
  166. package/src/components/custom/Workout/BaseBadge.tsx +6 -2
  167. package/src/components/custom/Workout/BodyMap.stories.tsx +4 -1
  168. package/src/components/custom/Workout/BodyMap.tsx +8 -4
  169. package/src/components/custom/Workout/BodyMapDetailPanel.stories.tsx +28 -6
  170. package/src/components/custom/Workout/BodyMapDetailPanel.test.tsx +11 -15
  171. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +50 -12
  172. package/src/components/custom/Workout/CapacityBandChart.stories.tsx +12 -9
  173. package/src/components/custom/Workout/CapacityBandChart.test.tsx +24 -51
  174. package/src/components/custom/Workout/CapacityBandChart.tsx +144 -111
  175. package/src/components/custom/Workout/DeviationBar.stories.tsx +1 -1
  176. package/src/components/custom/Workout/DeviationBar.test.tsx +10 -4
  177. package/src/components/custom/Workout/DeviationBar.tsx +24 -16
  178. package/src/components/custom/Workout/DualVelocityStrip.stories.tsx +183 -0
  179. package/src/components/custom/Workout/DualVelocityStrip.test.tsx +32 -18
  180. package/src/components/custom/Workout/ExerciseCard.stories.tsx +12 -11
  181. package/src/components/custom/Workout/ExerciseCard.test.tsx +52 -22
  182. package/src/components/custom/Workout/ExerciseCard.tsx +99 -183
  183. package/src/components/custom/Workout/ExerciseCardHeading.stories.tsx +95 -12
  184. package/src/components/custom/Workout/ExerciseCardHeading.test.tsx +189 -1
  185. package/src/components/custom/Workout/ExerciseCardHeading.tsx +167 -18
  186. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +9 -1
  187. package/src/components/custom/Workout/ExerciseDetailPage.tsx +3 -2
  188. package/src/components/custom/Workout/ExerciseHeading.stories.tsx +8 -8
  189. package/src/components/custom/Workout/ExerciseHeading.tsx +194 -46
  190. package/src/components/custom/Workout/ExerciseIndicator.stories.tsx +12 -9
  191. package/src/components/custom/Workout/ExerciseIndicator.test.tsx +27 -11
  192. package/src/components/custom/Workout/ExerciseIndicator.tsx +14 -15
  193. package/src/components/custom/Workout/FatigueMeter.stories.tsx +5 -5
  194. package/src/components/custom/Workout/InputBar.stories.tsx +4 -5
  195. package/src/components/custom/Workout/InputBar.tsx +4 -2
  196. package/src/components/custom/Workout/IntensityBar.stories.tsx +1 -1
  197. package/src/components/custom/Workout/IntensityBar.test.tsx +5 -1
  198. package/src/components/custom/Workout/IntensityBar.tsx +8 -3
  199. package/src/components/custom/Workout/LiveAuraFrame.stories.tsx +5 -4
  200. package/src/components/custom/Workout/MesoCard.stories.tsx +4 -1
  201. package/src/components/custom/Workout/MesoCard.test.tsx +7 -18
  202. package/src/components/custom/Workout/MesoCard.tsx +14 -10
  203. package/src/components/custom/Workout/MesoProgressBar.stories.tsx +1 -1
  204. package/src/components/custom/Workout/MesoProgressBar.test.tsx +18 -11
  205. package/src/components/custom/Workout/MesoProgressBar.tsx +15 -13
  206. package/src/components/custom/Workout/MesoStatusCard.stories.tsx +2 -1
  207. package/src/components/custom/Workout/MesoStatusCard.test.tsx +14 -44
  208. package/src/components/custom/Workout/MesoStatusCard.tsx +20 -33
  209. package/src/components/custom/Workout/MetricTiles.stories.tsx +3 -2
  210. package/src/components/custom/Workout/MuscleGroupChip.stories.tsx +2 -8
  211. package/src/components/custom/Workout/MuscleGroupChip.test.tsx +23 -31
  212. package/src/components/custom/Workout/MuscleGroupChip.tsx +28 -67
  213. package/src/components/custom/Workout/PlaceholderStrip.stories.tsx +9 -4
  214. package/src/components/custom/Workout/PlaceholderStrip.test.tsx +17 -10
  215. package/src/components/custom/Workout/PlaceholderStrip.tsx +9 -8
  216. package/src/components/custom/Workout/PrBadge.stories.tsx +2 -1
  217. package/src/components/custom/Workout/PrBadge.test.tsx +3 -9
  218. package/src/components/custom/Workout/PrBadge.tsx +13 -17
  219. package/src/components/custom/Workout/PrHistoryModal.stories.tsx +16 -3
  220. package/src/components/custom/Workout/PrHistoryModal.test.tsx +13 -36
  221. package/src/components/custom/Workout/PrHistoryModal.tsx +8 -4
  222. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +6 -1
  223. package/src/components/custom/Workout/README.md +68 -17
  224. package/src/components/custom/Workout/ReadinessCheck.stories.tsx +3 -2
  225. package/src/components/custom/Workout/ReadinessCheck.test.tsx +12 -18
  226. package/src/components/custom/Workout/ReadinessCheck.tsx +22 -4
  227. package/src/components/custom/Workout/RestTimer.stories.tsx +16 -4
  228. package/src/components/custom/Workout/RestTimer.tsx +4 -2
  229. package/src/components/custom/Workout/ScheduleTiles.stories.tsx +3 -2
  230. package/src/components/custom/Workout/ScheduleTiles.test.tsx +3 -4
  231. package/src/components/custom/Workout/ScheduleTiles.tsx +4 -7
  232. package/src/components/custom/Workout/SegmentedBar.stories.tsx +21 -17
  233. package/src/components/custom/Workout/SegmentedBar.tsx +10 -5
  234. package/src/components/custom/Workout/SegmentedProgressBar.stories.tsx +5 -5
  235. package/src/components/custom/Workout/SessionHeader.stories.tsx +6 -6
  236. package/src/components/custom/Workout/SessionHeader.tsx +12 -12
  237. package/src/components/custom/Workout/SessionRail.stories.tsx +12 -11
  238. package/src/components/custom/Workout/SessionRail.tsx +7 -9
  239. package/src/components/custom/Workout/SetBar.stories.tsx +10 -6
  240. package/src/components/custom/Workout/SetBar.test.tsx +49 -4
  241. package/src/components/custom/Workout/SetBar.tsx +38 -12
  242. package/src/components/custom/Workout/SetRow.stories.tsx +3 -2
  243. package/src/components/custom/Workout/SetRow.test.tsx +16 -2
  244. package/src/components/custom/Workout/SetRow.tsx +61 -23
  245. package/src/components/custom/Workout/SetStrip.stories.tsx +63 -7
  246. package/src/components/custom/Workout/SetStrip.test.tsx +25 -0
  247. package/src/components/custom/Workout/SetStrip.tsx +24 -4
  248. package/src/components/custom/Workout/SetTableHeader.stories.tsx +6 -6
  249. package/src/components/custom/Workout/SetTableHeader.tsx +9 -12
  250. package/src/components/custom/Workout/SetsRepsLoad.stories.tsx +7 -7
  251. package/src/components/custom/Workout/SetsRepsLoad.tsx +24 -12
  252. package/src/components/custom/Workout/Sparkline.stories.tsx +14 -11
  253. package/src/components/custom/Workout/Sparkline.test.tsx +37 -19
  254. package/src/components/custom/Workout/Sparkline.tsx +14 -18
  255. package/src/components/custom/Workout/StatusDot.stories.tsx +1 -1
  256. package/src/components/custom/Workout/StatusDot.test.tsx +44 -5
  257. package/src/components/custom/Workout/StatusDot.tsx +93 -63
  258. package/src/components/custom/Workout/StatusPill.stories.tsx +1 -1
  259. package/src/components/custom/Workout/StatusPill.test.tsx +6 -15
  260. package/src/components/custom/Workout/StatusPill.tsx +27 -38
  261. package/src/components/custom/Workout/StrengthTrendChart.stories.tsx +11 -4
  262. package/src/components/custom/Workout/StrengthTrendChart.test.tsx +15 -37
  263. package/src/components/custom/Workout/StrengthTrendChart.tsx +39 -36
  264. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +27 -64
  265. package/src/components/custom/Workout/SupersetWrapper.test.tsx +16 -14
  266. package/src/components/custom/Workout/SupersetWrapper.tsx +17 -21
  267. package/src/components/custom/Workout/TempoDisplay.stories.tsx +26 -10
  268. package/src/components/custom/Workout/TempoDisplay.test.tsx +18 -4
  269. package/src/components/custom/Workout/TempoDisplay.tsx +2 -0
  270. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +9 -1
  271. package/src/components/custom/Workout/VelocityStrip.compact.stories.tsx +4 -1
  272. package/src/components/custom/Workout/VelocityStrip.dual.stories.tsx +10 -6
  273. package/src/components/custom/Workout/VelocityStrip.expanded.stories.tsx +5 -2
  274. package/src/components/custom/Workout/VelocityStrip.hero.stories.tsx +44 -1
  275. package/src/components/custom/Workout/VelocityStrip.stories.tsx +12 -6
  276. package/src/components/custom/Workout/VelocityStrip.test.tsx +48 -6
  277. package/src/components/custom/Workout/VelocityStrip.tsx +26 -14
  278. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +6 -7
  279. package/src/components/custom/Workout/VolumeLandmarkBar.tsx +15 -6
  280. package/src/components/custom/Workout/WeekRow.stories.tsx +4 -1
  281. package/src/components/custom/Workout/WeekRow.test.tsx +18 -15
  282. package/src/components/custom/Workout/WeekRow.tsx +23 -16
  283. package/src/components/custom/Workout/WeightBadge.stories.tsx +2 -1
  284. package/src/components/custom/Workout/WeightBadge.test.tsx +50 -19
  285. package/src/components/custom/Workout/WeightBadge.tsx +28 -27
  286. package/src/components/custom/Workout/WorkoutCard.stories.tsx +6 -1
  287. package/src/components/custom/Workout/WorkoutCard.test.tsx +18 -0
  288. package/src/components/custom/Workout/WorkoutCard.tsx +35 -57
  289. package/src/components/custom/Workout/WorkoutPill.stories.tsx +5 -2
  290. package/src/components/custom/Workout/WorkoutPill.test.tsx +39 -7
  291. package/src/components/custom/Workout/WorkoutPill.tsx +88 -57
  292. package/src/components/custom/Workout/ZoneTrack.stories.tsx +10 -7
  293. package/src/components/custom/Workout/ZoneTrack.tsx +10 -9
  294. package/src/components/custom/Workout/exerciseRowState.ts +29 -0
  295. package/src/components/custom/Workout/index.ts +17 -2
  296. package/src/components/custom/Workout/metricText.stories.tsx +15 -13
  297. package/src/components/custom/Workout/metricText.tsx +8 -2
  298. package/src/components/custom/Workout/setHeadingKit.tsx +219 -36
  299. package/src/components/custom/Workout/velocity-story-kit.tsx +2 -2
  300. package/src/components/custom/charts/README.md +66 -0
  301. package/src/components/custom/charts/SetBarChart.test.tsx +46 -1
  302. package/src/components/custom/charts/SetBarChart.tsx +56 -9
  303. package/src/components/custom/charts/SparkBars.stories.tsx +55 -0
  304. package/src/components/custom/charts/SparkBars.test.tsx +69 -0
  305. package/src/components/custom/charts/SparkBars.tsx +85 -0
  306. package/src/components/custom/charts/flatBarGeometry.test.ts +41 -0
  307. package/src/components/custom/charts/flatBarGeometry.ts +32 -0
  308. package/src/components/custom/charts/index.ts +3 -0
  309. package/src/components/custom/index.ts +3 -0
  310. package/src/components/custom/stepper/Stepper.stories.tsx +13 -10
  311. package/src/components/custom/stepper/Stepper.test.tsx +1 -7
  312. package/src/components/custom/stepper/Stepper.tsx +21 -34
  313. package/src/components/icons/icons.stories.tsx +1 -1
  314. package/src/components/icons/icons.tsx +51 -0
  315. package/src/components/shell/AppShell.stories.tsx +150 -0
  316. package/src/components/shell/AppShell.test.tsx +70 -0
  317. package/src/components/shell/AppShell.tsx +90 -0
  318. package/src/components/shell/BrandLockup.stories.tsx +66 -5
  319. package/src/components/shell/BrandLockup.test.tsx +34 -1
  320. package/src/components/shell/BrandLockup.tsx +27 -11
  321. package/src/components/shell/NavItem.stories.tsx +4 -4
  322. package/src/components/shell/NavItem.test.tsx +17 -0
  323. package/src/components/shell/NavItem.tsx +17 -5
  324. package/src/components/shell/README.md +89 -26
  325. package/src/components/shell/SideNav.stories.tsx +38 -7
  326. package/src/components/shell/SideNav.test.tsx +16 -8
  327. package/src/components/shell/SideNav.tsx +17 -17
  328. package/src/components/shell/TopBar.stories.tsx +44 -19
  329. package/src/components/shell/TopBar.test.tsx +34 -12
  330. package/src/components/shell/TopBar.tsx +61 -40
  331. package/src/components/shell/brands.tsx +66 -0
  332. package/src/components/shell/index.ts +9 -8
  333. package/src/components/shell/{DeviceIndicator.stories.tsx → workout/DeviceIndicator.stories.tsx} +2 -2
  334. package/src/components/shell/{DeviceIndicator.tsx → workout/DeviceIndicator.tsx} +2 -2
  335. package/src/components/shell/{DeviceMenu.stories.tsx → workout/DeviceMenu.stories.tsx} +2 -2
  336. package/src/components/shell/{DeviceMenu.tsx → workout/DeviceMenu.tsx} +3 -3
  337. package/src/components/shell/{DeviceRow.stories.tsx → workout/DeviceRow.stories.tsx} +2 -2
  338. package/src/components/shell/{DeviceRow.tsx → workout/DeviceRow.tsx} +3 -3
  339. package/src/components/shell/{SessionStatePill.stories.tsx → workout/SessionStatePill.stories.tsx} +2 -2
  340. package/src/components/shell/{SessionStatePill.tsx → workout/SessionStatePill.tsx} +5 -3
  341. package/src/components/shell/workout/WorkoutShell.stories.tsx +71 -0
  342. package/src/components/shell/{DashboardShell.test.tsx → workout/WorkoutShell.test.tsx} +19 -8
  343. package/src/components/shell/workout/WorkoutShell.tsx +77 -0
  344. package/src/components/shell/workout/WorkoutTopBar.stories.tsx +58 -0
  345. package/src/components/shell/workout/WorkoutTopBar.test.tsx +39 -0
  346. package/src/components/shell/workout/WorkoutTopBar.tsx +52 -0
  347. package/src/components/shell/workout/index.ts +9 -0
  348. package/src/components/shell/workout/workoutNavItems.tsx +16 -0
  349. package/src/components/ui/README.md +110 -0
  350. package/src/components/ui/alert/Alert.stories.tsx +15 -5
  351. package/src/components/ui/alert/Alert.tsx +24 -3
  352. package/src/components/ui/autocomplete/Autocomplete.stories.tsx +11 -13
  353. package/src/components/ui/autocomplete/Autocomplete.test.tsx +7 -25
  354. package/src/components/ui/autocomplete/Autocomplete.tsx +21 -28
  355. package/src/components/ui/avatar/Avatar.stories.tsx +1 -1
  356. package/src/components/ui/avatar/Avatar.tsx +2 -10
  357. package/src/components/ui/badge/Badge.stories.tsx +83 -28
  358. package/src/components/ui/badge/Badge.test.tsx +19 -3
  359. package/src/components/ui/badge/Badge.tsx +48 -55
  360. package/src/components/ui/breadcrumbs/Breadcrumbs.stories.tsx +1 -1
  361. package/src/components/ui/breadcrumbs/Breadcrumbs.tsx +4 -16
  362. package/src/components/ui/button/Button.stories.tsx +46 -12
  363. package/src/components/ui/button/Button.tsx +44 -37
  364. package/src/components/ui/card/Card.stories.tsx +90 -94
  365. package/src/components/ui/card/Card.test.tsx +80 -6
  366. package/src/components/ui/card/Card.tsx +150 -203
  367. package/src/components/ui/checkbox/Checkbox.stories.tsx +1 -1
  368. package/src/components/ui/checkbox/Checkbox.tsx +7 -27
  369. package/src/components/ui/chip/Chip.stories.tsx +37 -13
  370. package/src/components/ui/chip/Chip.test.tsx +10 -6
  371. package/src/components/ui/chip/Chip.tsx +76 -91
  372. package/src/components/ui/collapse/Collapse.stories.tsx +23 -23
  373. package/src/components/ui/collapse/Collapse.tsx +6 -11
  374. package/src/components/ui/data-row/DataRow.stories.tsx +14 -3
  375. package/src/components/ui/data-row/DataRow.test.tsx +5 -15
  376. package/src/components/ui/data-row/DataRow.tsx +18 -7
  377. package/src/components/ui/divider/Divider.stories.tsx +1 -1
  378. package/src/components/ui/divider/Divider.tsx +1 -5
  379. package/src/components/ui/drawer/Drawer.stories.tsx +5 -16
  380. package/src/components/ui/drawer/Drawer.tsx +13 -27
  381. package/src/components/ui/floating-overlay-depth.test.tsx +143 -0
  382. package/src/components/ui/form-field/FormField.stories.tsx +6 -20
  383. package/src/components/ui/form-field/FormField.test.tsx +1 -5
  384. package/src/components/ui/form-field/FormField.tsx +10 -46
  385. package/src/components/ui/help-tip/HelpTip.stories.tsx +8 -19
  386. package/src/components/ui/help-tip/HelpTip.test.tsx +1 -3
  387. package/src/components/ui/help-tip/HelpTip.tsx +21 -22
  388. package/src/components/ui/help-tip/index.ts +7 -1
  389. package/src/components/ui/icon-box/IconBox.stories.tsx +1 -1
  390. package/src/components/ui/icon-box/IconBox.test.tsx +1 -7
  391. package/src/components/ui/icon-box/IconBox.tsx +10 -18
  392. package/src/components/ui/indicator/Indicator.stories.tsx +5 -4
  393. package/src/components/ui/indicator/Indicator.tsx +20 -14
  394. package/src/components/ui/input/Input.stories.tsx +3 -11
  395. package/src/components/ui/input/Input.test.tsx +2 -10
  396. package/src/components/ui/input/Input.tsx +10 -25
  397. package/src/components/ui/input/index.ts +7 -1
  398. package/src/components/ui/link/Link.stories.tsx +19 -7
  399. package/src/components/ui/list-item/ListItem.stories.tsx +17 -5
  400. package/src/components/ui/list-item/ListItem.tsx +2 -9
  401. package/src/components/ui/menu/Menu.stories.tsx +21 -15
  402. package/src/components/ui/menu/Menu.test.tsx +2 -11
  403. package/src/components/ui/menu/Menu.tsx +12 -14
  404. package/src/components/ui/menu/index.ts +8 -1
  405. package/src/components/ui/modal/Modal.stories.tsx +2 -2
  406. package/src/components/ui/modal/Modal.tsx +31 -19
  407. package/src/components/ui/pill/Pill.stories.tsx +111 -23
  408. package/src/components/ui/pill/Pill.test.tsx +101 -3
  409. package/src/components/ui/pill/Pill.tsx +168 -49
  410. package/src/components/ui/pill/index.ts +1 -1
  411. package/src/components/ui/popover/Popover.stories.tsx +6 -8
  412. package/src/components/ui/popover/Popover.test.tsx +1 -6
  413. package/src/components/ui/popover/Popover.tsx +20 -15
  414. package/src/components/ui/popover/index.ts +7 -1
  415. package/src/components/ui/progress/Progress.stories.tsx +3 -12
  416. package/src/components/ui/progress/Progress.test.tsx +1 -5
  417. package/src/components/ui/progress/Progress.tsx +9 -6
  418. package/src/components/ui/radio/Radio.stories.tsx +42 -21
  419. package/src/components/ui/radio/Radio.test.tsx +6 -2
  420. package/src/components/ui/radio/Radio.tsx +23 -22
  421. package/src/components/ui/section/Section.stories.tsx +12 -21
  422. package/src/components/ui/section/Section.test.tsx +1 -6
  423. package/src/components/ui/section/Section.tsx +1 -3
  424. package/src/components/ui/section/index.ts +1 -5
  425. package/src/components/ui/select/Select.stories.tsx +3 -13
  426. package/src/components/ui/select/Select.test.tsx +2 -11
  427. package/src/components/ui/select/Select.tsx +16 -15
  428. package/src/components/ui/skeleton/Skeleton.stories.tsx +3 -11
  429. package/src/components/ui/skeleton/Skeleton.tsx +3 -14
  430. package/src/components/ui/skeleton/index.ts +1 -7
  431. package/src/components/ui/spinner/Spinner.stories.tsx +1 -1
  432. package/src/components/ui/spinner/Spinner.tsx +4 -5
  433. package/src/components/ui/stack/Stack.stories.tsx +8 -8
  434. package/src/components/ui/stack/Stack.tsx +1 -1
  435. package/src/components/ui/surface/Surface.stories.tsx +92 -33
  436. package/src/components/ui/surface/Surface.test.tsx +88 -28
  437. package/src/components/ui/surface/Surface.tsx +37 -87
  438. package/src/components/ui/surface/SurfaceContext.ts +22 -62
  439. package/src/components/ui/surface/index.ts +8 -0
  440. package/src/components/ui/surface/resolveSurface.ts +98 -0
  441. package/src/components/ui/surface/surface.contract.test.ts +6 -1
  442. package/src/components/ui/switch/Switch.stories.tsx +1 -1
  443. package/src/components/ui/switch/Switch.tsx +7 -6
  444. package/src/components/ui/tabs/Tabs.stories.tsx +1 -1
  445. package/src/components/ui/tabs/Tabs.tsx +8 -21
  446. package/src/components/ui/tabs/index.ts +1 -7
  447. package/src/components/ui/tile/Tile.stories.tsx +1 -1
  448. package/src/components/ui/tile/Tile.tsx +3 -0
  449. package/src/components/ui/toast/Toast.stories.tsx +1 -1
  450. package/src/components/ui/toast/Toast.test.tsx +2 -8
  451. package/src/components/ui/toast/Toast.tsx +49 -57
  452. package/src/components/ui/toast/index.ts +0 -1
  453. package/src/components/ui/toolbar-button/ToolbarButton.stories.tsx +92 -71
  454. package/src/components/ui/toolbar-button/ToolbarButton.test.tsx +3 -18
  455. package/src/components/ui/toolbar-button/ToolbarButton.tsx +38 -49
  456. package/src/components/ui/tooltip/Tooltip.stories.tsx +12 -3
  457. package/src/components/ui/tooltip/Tooltip.test.tsx +21 -3
  458. package/src/components/ui/tooltip/Tooltip.tsx +55 -36
  459. package/src/components/ui/tooltip/index.ts +1 -1
  460. package/src/components/ui/trigger/TriggerSurface.test.tsx +215 -0
  461. package/src/components/ui/trigger/TriggerSurface.tsx +81 -0
  462. package/src/components/ui/trigger/index.ts +2 -0
  463. package/src/stories/PresetShowcase.stories.tsx +101 -48
  464. package/src/test/no-device-internals.test.ts +3 -3
  465. package/src/test/no-raw-color.test.ts +39 -0
  466. package/src/theme/Alpha.stories.tsx +103 -0
  467. package/src/theme/ChoosingTokens.stories.tsx +48 -0
  468. package/src/theme/ColorPalettes.stories.tsx +62 -45
  469. package/src/theme/ColorPrimitives.stories.tsx +35 -35
  470. package/src/theme/Depth.stories.tsx +132 -65
  471. package/src/theme/DepthCalibration.stories.tsx +23 -21
  472. package/src/theme/ProposedTokensVW82.stories.tsx +414 -0
  473. package/src/theme/ThemeProvider.test.tsx +4 -4
  474. package/src/theme/barrel.ts +7 -6
  475. package/src/theme/color-stories.coverage.test.ts +1 -1
  476. package/src/theme/color-utils.ts +41 -29
  477. package/src/theme/config.completeness.test.ts +1 -1
  478. package/src/theme/config.ts +40 -0
  479. package/src/theme/elevation.test.ts +82 -56
  480. package/src/theme/elevation.ts +77 -561
  481. package/src/theme/global.css +45 -5
  482. package/src/theme/grey-ramp.test.ts +24 -8
  483. package/src/theme/lift.test.ts +39 -0
  484. package/src/theme/lift.ts +102 -0
  485. package/src/theme/materials.test.ts +5 -2
  486. package/src/theme/materials.ts +38 -4
  487. package/src/theme/native-theming-guard.test.ts +5 -5
  488. package/src/theme/presets/apply.ts +4 -0
  489. package/src/theme/presets/audiobook.ts +5 -2
  490. package/src/theme/presets/default.ts +4 -0
  491. package/src/theme/presets/index.ts +14 -1
  492. package/src/theme/presets/types.ts +1 -1
  493. package/src/theme/semantic-contrast.test.ts +13 -4
  494. package/src/theme/status-distinctness.test.ts +66 -0
  495. package/src/theme/subtle-tone-weight.test.ts +163 -0
  496. package/src/theme/surface-planes.test.ts +37 -0
  497. package/src/theme/surface-planes.ts +68 -0
  498. package/src/theme/tailwind-var-opacity.test.ts +163 -0
  499. package/src/theme/token-export-guard.test.ts +1 -3
  500. package/src/theme/tokens/primitives.test.ts +15 -7
  501. package/src/theme/tokens/primitives.ts +98 -33
  502. package/src/theme/tokens/semantic-hex-guard.test.ts +322 -0
  503. package/src/theme/tokens/semantic.ts +124 -54
  504. package/src/theme/wash-ladder.test.ts +58 -0
  505. package/src/theme/workout-tokens.ts +1 -7
  506. package/src/types/jest-axe.d.ts +2 -6
  507. package/src/types/raw-md.d.ts +5 -0
  508. package/src/utils/colors.alpha-adoption.test.ts +408 -0
  509. package/src/utils/colors.ts +4 -4
  510. package/src/utils/form.ts +1 -3
  511. package/src/utils/index.ts +2 -7
  512. package/src/utils/number-format.ts +17 -0
  513. package/src/utils/workout-format.ts +15 -6
  514. package/src/web-jsx/jsx-runtime.ts +1 -5
  515. package/tailwind.config.js +55 -9
  516. package/src/components/custom/Workout/ExerciseCardUnified.stories.tsx +0 -151
  517. package/src/components/custom/Workout/RowInventory.stories.tsx +0 -408
  518. package/src/components/custom/Workout/S3FullRail.stories.tsx +0 -46
  519. package/src/components/custom/Workout/S3SessionPace.stories.tsx +0 -95
  520. package/src/components/custom/Workout/S3SessionRailHeading.stories.tsx +0 -61
  521. package/src/components/custom/Workout/S3SetTypes.stories.tsx +0 -176
  522. package/src/components/custom/Workout/S3WorkoutExpansion.stories.tsx +0 -240
  523. package/src/components/shell/DashboardShell.stories.tsx +0 -65
  524. package/src/components/shell/DashboardShell.tsx +0 -75
  525. package/src/components/shell/SessionRailSpecimen.stories.tsx +0 -753
  526. package/src/theme/elevation.stories.tsx +0 -346
  527. package/src/utils/useTheme.ts +0 -72
  528. /package/src/components/shell/{DeviceIndicator.test.tsx → workout/DeviceIndicator.test.tsx} +0 -0
  529. /package/src/components/shell/{DeviceMenu.test.tsx → workout/DeviceMenu.test.tsx} +0 -0
  530. /package/src/components/shell/{DeviceRow.test.tsx → workout/DeviceRow.test.tsx} +0 -0
  531. /package/src/components/shell/{SessionStatePill.test.tsx → workout/SessionStatePill.test.tsx} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/theme/tokens/primitives.ts","../../src/theme/tokens/semantic.ts"],"names":[],"mappings":"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","file":"tokens.mjs","sourcesContent":["/**\n * Primitive Design Tokens\n *\n * Raw values with no semantic meaning. These are the foundation of the design system\n * and should rarely be used directly in components. Use semantic tokens instead.\n */\n\n/**\n * Absolute colour keywords.\n *\n * This used to hold five scales — `blue`, `red`, `redVivid`, `neutral` and\n * `charcoal`. All five are gone (TD-07.14): the greys folded into `greyRamp`\n * below and the chromatics into the OKLCH `primitiveRamps`. What is left has no\n * scale because these three are not colours you tune, they are keywords.\n */\nexport const primitiveColors = {\n white: '#FFFFFF',\n black: '#000000',\n transparent: 'transparent',\n} as const\n\n/**\n * Unified warm-neutral grey ramp (TD-07.14)\n *\n * The ONE achromatic scale. Regenerate with `scripts/generate-grey-ramp.mjs` —\n * preserve the generator, not just the hexes.\n *\n * The surface planes ARE steps here rather than a parallel object: `850` is\n * overlay, `975` is the bezel. That is the whole point of the ramp. `grey`,\n * `neutral`, `surfaceRampDark` and `backgroundFrameDark` all resolve into it,\n * which is why every plane step below is byte-identical to the value that\n * shipped in v0.10.0 — the surfaces do not move, only their names.\n *\n * TWO THINGS ABOUT THE NUMBERING, both deliberate and both previously re-derived\n * from scratch more than once because they were never written down:\n *\n * 1. `975` sits BELOW the standard grid. `canonL` — the median L* of the seven\n * chromatic `primitiveRamps` at each step — ends at L*10.3, which is step\n * `950`. The bezel is L*3.8, darker than the grid's last rung, so there is\n * simply no step number left for it and `975` extends past the end.\n * 2. `850`/`875` are quarter-steps because overlay/raised/elevated are only\n * ~2.7 L* apart and all three collide on `900` at normal resolution. `800`\n * is a generated bridge between `700` (L*37.9) and overlay (L*22.7) so the\n * spacing stays even across the join.\n *\n * There is no `inset`. It was retired, not renamed: at ΔE 1.10 from `975` it was\n * an imperceptible duplicate of the frame, which is exactly why `<Surface pressed>`\n * (surface − 1) kept collapsing into it. `975` is the floor.\n *\n * Spec, generator and the rejected v1/v2 cuts:\n * sources/design/foundations/warm-grey-ramp/\n */\nexport const greyRamp = {\n 50: '#F9F6F3', // L*97.0 W6\n 100: '#EDEAE7', // L*92.8 W6\n 200: '#D4D1CE', // L*84.0 W6 — warm silver\n 300: '#BDBAB7', // L*75.7 W6\n 400: '#A29F9D', // L*65.7 W5\n 500: '#888684', // L*56.0 W4\n 600: '#72716F', // L*47.7 W3\n 700: '#5A5958', // L*37.9 W2\n 800: '#424140', // L*27.6 W2 — generated bridge\n 850: '#373635', // L*22.7 W2 — surface overlay\n 875: '#31302F', // L*19.9 W2 — surface raised\n 900: '#2C2A28', // L*17.2 W4 — surface elevated\n 925: '#252321', // L*13.9 W4 — surface base\n 950: '#1C1916', // L*9.0 W6 — background base / shell\n 975: '#100D0A', // L*3.8 W6 — background frame / bezel\n} as const\n\n/**\n * The surface planes, as ramp steps — the mapping `<Surface level>` resolves through.\n *\n * Ordered darkest -> lightest, which is the order `pressedLevel()` walks.\n */\nexport const SURFACE_PLANE_STEPS = {\n frame: 975,\n background: 950,\n base: 925,\n elevated: 900,\n raised: 875,\n overlay: 850,\n} as const\n\n/**\n * Derived tonal ramps (TD-05.09 color foundations)\n *\n * Seven OKLCH-generated hue ramps, 11 perceptual lightness steps each (50 -> 950).\n * Built with hue-torsion + a chroma arc, anchored through existing brand/semantic\n * hexes. `pin` marks the step each ramp flows through its anchor.\n * This is the single source of truth for chromatic hexes — the categorical palette\n * below references these steps rather than duplicating values.\n * See sources/design/foundations.\n */\nexport const primitiveRamps = {\n red: {\n 50: '#FFF4F4',\n 100: '#FFE3E5',\n 200: '#FFC2C5',\n 300: '#FF9A9D',\n 400: '#F77175',\n 500: '#E05254',\n 600: '#D14343', // pin\n 700: '#A4221C',\n 800: '#7E1002',\n 900: '#5A0900',\n 950: '#3D0400',\n },\n orange: {\n 50: '#FFF5ED',\n 100: '#FFE6D4',\n 200: '#FFC7A2',\n 300: '#FFA063',\n 400: '#FF7900', // pin\n 500: '#DA5F00',\n 600: '#B94A00',\n 700: '#983804',\n 800: '#6F290F',\n 900: '#4E1C0C',\n 950: '#331107',\n },\n amber: {\n 50: '#FFF7DD',\n 100: '#FFEAA9',\n 200: '#FFD352',\n 300: '#F9B415', // pin\n 400: '#E08C00',\n 500: '#C27400',\n 600: '#A45E00',\n 700: '#814D14',\n 800: '#5B3A1A',\n 900: '#442503',\n 950: '#301500',\n },\n green: {\n 50: '#E3FFEE',\n 100: '#B5FFD2',\n 200: '#58F69E',\n 300: '#2ED573', // pin\n 400: '#21C05D',\n 500: '#22A444',\n 600: '#298732',\n 700: '#2B6B25',\n 800: '#264D1C',\n 900: '#1B3515',\n 950: '#11220D',\n },\n cyan: {\n 50: '#E6FBFF',\n 100: '#C2F6FF',\n 200: '#62EAFF',\n 300: '#22D3EE', // pin\n 400: '#01B5D1',\n 500: '#2697B7',\n 600: '#307B9B',\n 700: '#2A617F',\n 800: '#22465F',\n 900: '#0B3149',\n 950: '#001F36',\n },\n blue: {\n 50: '#EFF8FF',\n 100: '#D9EFFF',\n 200: '#ACDBFF',\n 300: '#78C2FF',\n 400: '#3CA8FF',\n 500: '#2196F3', // pin\n 600: '#1072CB',\n 700: '#135AA8',\n 800: '#14407E',\n 900: '#112C5A',\n 950: '#091B3C',\n },\n magenta: {\n 50: '#FFF3F9',\n 100: '#FFE2F1',\n 200: '#FFBDE2',\n 300: '#FF8FD5',\n 400: '#ED69C3',\n 500: '#D548AF',\n 600: '#BA2996',\n 700: '#9C0D7A', // pin\n 800: '#77005A',\n 900: '#56003F',\n 950: '#3B0029',\n },\n} as const\n\n/**\n * Categorical (qualitative) palette — an ordered, CVD-safe series expressed as\n * references into {@link primitiveRamps} (one source of truth; the palette moves\n * with the ramps).\n *\n * Design: a single canonical hue order (blue, magenta, red, orange, green, cyan,\n * amber), with steps chosen vivid-midtone-first and fanned lighter/darker as the\n * series grows to preserve separation. The sequence is nested-stable — a chart\n * with N series uses the first N colors, and the series index is stable as N\n * changes. Colorblind-safe worst-case deuteranopia/protanopia floor 8 holds\n * through {@link CATEGORICAL_CVD_SAFE_MAX} colors; the 7th is an extended color\n * that should be paired with a legend or other secondary encoding.\n *\n * Two variants: `default` (vivid, sits on neutral/light surfaces, legible under\n * black text) and `dark` (deeper shades legible under white text on a fill). A\n * separate \"light\" variant was dropped — the vivid `default` picks already clear\n * black-text contrast, so it doubles as the light-context palette.\n */\nexport const categoricalPalette = {\n default: [\n primitiveRamps.blue[500],\n primitiveRamps.magenta[500],\n primitiveRamps.red[500],\n primitiveRamps.orange[400],\n primitiveRamps.green[300],\n primitiveRamps.cyan[300],\n primitiveRamps.amber[600], // extended (7th) — pair with a legend\n ],\n dark: [\n primitiveRamps.blue[600],\n primitiveRamps.magenta[600],\n primitiveRamps.red[500],\n primitiveRamps.orange[600],\n primitiveRamps.green[800],\n primitiveRamps.cyan[800],\n primitiveRamps.amber[500], // extended (7th) — pair with a legend\n ],\n} as const\n\n/** Largest series count that holds the CVD floor without a legend. */\nexport const CATEGORICAL_CVD_SAFE_MAX = 6\n\n/**\n * Categorical palette variant.\n * - `default` : vivid; neutral/light surfaces, legible under black text\n * - `dark` : deeper shades, legible under white text on a filled swatch\n */\nexport type CategoricalVariant = keyof typeof categoricalPalette\n\n/**\n * Get a color from the ordered categorical palette by series index.\n * The palette is nested-stable, so the color for a given index does not change\n * with the total series count; `index` simply wraps past the end.\n *\n * @param index - 0-based series index (wraps past the end)\n * @param variant - `default` (black-text / light surfaces) or `dark` (white text)\n * @returns The hex color string\n */\nexport function getCategoricalColor(index: number, variant: CategoricalVariant = 'default'): string {\n const palette = categoricalPalette[variant]\n index = Math.max(0, Math.floor(index))\n return palette[index % palette.length]\n}\n\n/**\n * Diverging status scale (BodyMap training-status: under → optimal → over) as\n * references into {@link primitiveRamps}. A true diverging shape — `optimal` is\n * the lightest center, the extremes go darker — so the signal reads in lightness\n * (colorblind-robust; worst-case deut/protanopia min ΔE ~10.9) and the direction\n * reads in the blue↔red axis (the CVD-safe hue pair).\n *\n * Tuned so every stop is dark enough for the fill yet light enough that BLACK\n * text clears 4.5:1 on all five — no per-cell white/black flipping. The value\n * valley is symmetric: the two mid-arms (maintenance / approaching) sit at equal\n * lightness (both ~0.53 relative luminance), the ends darker.\n */\nexport const divergingScale = [\n primitiveRamps.blue[500], // under\n primitiveRamps.cyan[300], // maintenance\n primitiveRamps.green[200], // optimal (light center)\n primitiveRamps.amber[300], // approaching\n primitiveRamps.red[600], // over\n] as const\n\n/**\n * Sequential \"effort\" scale (low → high intensity: green → yellow → orange → red)\n * as references into {@link primitiveRamps}. A 6-stop ordinal palette; the\n * velocity/RPE strip sub-samples it. Every adjacent pair clears the CVD floor\n * (min deut/protan ΔE ≥ 4.5), and within that the hue walk is kept smooth —\n * the amber-200 → amber-300 → orange-400 run steps the yellow→orange transition\n * gradually rather than lurching. Order encodes magnitude, so it tolerates the\n * green↔red CVD pair. Stops 0–3 take black text; the dark reds take white.\n */\nexport const sequentialEffort = [\n primitiveRamps.green[300],\n primitiveRamps.amber[200],\n primitiveRamps.amber[300],\n primitiveRamps.orange[400],\n primitiveRamps.red[600],\n primitiveRamps.red[700],\n] as const\n\n/**\n * Best-contrast text color (black or white) for a solid fill — for labels sitting\n * on categorical/diverging/effort swatches. Uses the WCAG relative-luminance ratio.\n */\nexport function bestTextColor(hex: string): '#000000' | '#FFFFFF' {\n const [r, g, b] = [0, 2, 4].map((i) => {\n const c = parseInt(hex.replace('#', '').slice(i, i + 2), 16) / 255\n return c >= 0.04045 ? ((c + 0.055) / 1.055) ** 2.4 : c / 12.92\n })\n const l = 0.2126 * r + 0.7152 * g + 0.0722 * b\n return (l + 0.05) / 0.05 >= 1.05 / (l + 0.05) ? '#000000' : '#FFFFFF'\n}\n\n/**\n * Discrete rainbow palette for data visualization\n * Based on Paul Tol's color schemes: https://personal.sron.nl/~pault/#fig:scheme_rainbow_discrete\n */\nexport const discreteRainbow = [\n '#E8ECFB',\n '#D9CCE3',\n '#D1BBD7',\n '#CAACCB',\n '#BA8DB4',\n '#AE76A3',\n '#AA6F9E',\n '#994F88',\n '#882E72',\n '#1965B0',\n '#437DBF',\n '#5289C7',\n '#6195CF',\n '#7BAFDE',\n '#4EB265',\n '#90C987',\n '#CAE0AB',\n '#F7F056',\n '#F7CB45',\n '#F6C141',\n '#F4A736',\n '#F1932D',\n '#EE8026',\n '#E8601C',\n '#E65518',\n '#DC050C',\n '#A5170E',\n '#72190E',\n '#42150A',\n] as const\n\n/**\n * Palette indices for discrete rainbow colors at different palette sizes.\n * For a given palette size (index + 1), returns the indices of colors to use.\n */\nconst discreteRainbowPalettes: number[][] = [\n [10],\n [10, 26],\n [10, 18, 26],\n [10, 15, 18, 26],\n [10, 14, 15, 18, 26],\n [10, 14, 15, 17, 18, 26],\n [9, 10, 14, 15, 17, 18, 26],\n [9, 10, 14, 15, 17, 18, 23, 26],\n [9, 10, 14, 15, 17, 18, 23, 26, 28],\n [9, 10, 14, 15, 17, 18, 21, 24, 26, 28],\n [9, 10, 12, 14, 15, 17, 18, 21, 24, 26, 28],\n [3, 6, 9, 10, 12, 14, 15, 17, 18, 21, 24, 26],\n [3, 6, 9, 10, 12, 14, 15, 16, 17, 18, 21, 24, 26],\n [3, 6, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26],\n [3, 6, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28],\n [3, 5, 7, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28],\n [3, 5, 7, 8, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28],\n [3, 5, 7, 8, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 27, 28],\n [2, 4, 5, 7, 8, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 27, 28],\n [2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 27, 28],\n [2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 26, 27, 28],\n [2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 26, 27, 28, 29],\n [1, 2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 26, 27, 28, 29],\n]\n\n/**\n * Get a color from the discrete rainbow palette for a given index and palette size.\n * Colors are optimized for visual distinction at each palette size.\n *\n * @param index - The index of the color in the series (0-based)\n * @param size - The total number of colors needed (1-23)\n * @returns The hex color string\n */\nexport function getDiscreteRainbowColor(index: number, size: number): string {\n index = Math.max(0, index)\n size = Math.min(Math.max(1, size), discreteRainbowPalettes.length)\n\n const palette = discreteRainbowPalettes[size - 1]\n if (index >= palette.length) index = index % palette.length\n\n return discreteRainbow[palette[index] - 1]\n}\n\nexport const primitiveTypography = {\n fontFamilies: {\n sans: ['Inter', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Helvetica', 'Arial', 'sans-serif'],\n body: ['Nunito Sans', 'sans-serif'],\n heading: ['Space Grotesk', 'sans-serif'],\n mono: ['SF Mono', 'Monaco', 'Inconsolata', 'Fira Mono', 'Droid Sans Mono', 'Source Code Pro', 'monospace'],\n },\n fontSizes: {\n xs: '0.75rem', // 12px\n sm: '0.875rem', // 14px\n base: '1rem', // 16px\n lg: '1.125rem', // 18px\n xl: '1.5rem', // 24px\n '2xl': '2rem', // 32px\n '3xl': '2.25rem', // 36px\n '4xl': '3rem', // 48px\n '5xl': '3.5rem', // 56px\n },\n fontWeights: {\n normal: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n lineHeights: {\n none: 1,\n tight: 1.375,\n snug: 1.5,\n normal: 1.57,\n relaxed: 1.66,\n loose: 1.75,\n },\n letterSpacing: {\n tighter: '-0.05em',\n tight: '-0.025em',\n normal: '0em',\n wide: '0.025em',\n wider: '0.05em',\n widest: '0.5px',\n },\n} as const\n\nexport const primitiveSpacing = {\n 0: '0',\n px: '1px',\n 0.5: '0.125rem', // 2px\n 1: '0.25rem', // 4px\n 1.5: '0.375rem', // 6px\n 2: '0.5rem', // 8px\n 2.5: '0.625rem', // 10px\n 3: '0.75rem', // 12px\n 3.5: '0.875rem', // 14px\n 4: '1rem', // 16px\n 5: '1.25rem', // 20px\n 6: '1.5rem', // 24px\n 7: '1.75rem', // 28px\n 8: '2rem', // 32px\n 9: '2.25rem', // 36px\n 10: '2.5rem', // 40px\n 11: '2.75rem', // 44px\n 12: '3rem', // 48px\n 14: '3.5rem', // 56px\n 16: '4rem', // 64px\n 20: '5rem', // 80px\n 24: '6rem', // 96px\n 28: '7rem', // 112px\n 32: '8rem', // 128px\n} as const\n\nexport const primitiveBorderRadius = {\n none: '0',\n sm: '4px',\n DEFAULT: '8px',\n md: '8px',\n lg: '12px',\n xl: '16px',\n '2xl': '24px',\n full: '9999px',\n} as const\n\nexport const primitiveBreakpoints = {\n xs: 0,\n sm: 600,\n md: 1000,\n lg: 1200,\n xl: 1920,\n} as const\n\nexport const primitiveZIndex = {\n hide: -1,\n auto: 'auto',\n base: 0,\n docked: 10,\n dropdown: 1000,\n sticky: 1100,\n drawer: 1100,\n banner: 1200,\n appBar: 1200,\n overlay: 1300,\n modal: 1400,\n popover: 1500,\n skipLink: 1600,\n toast: 1700,\n tooltip: 1800,\n} as const\n","/**\n * Semantic Design Tokens\n *\n * Meaningful tokens following DTCG (Design Tokens Community Group) naming conventions.\n * Pattern: {category}-{intent}-{variant?}-{state?}\n *\n * Categories:\n * - brand-* : Brand colors (primary, secondary, accent)\n * - status-* : Feedback colors (success, error, warning, info)\n * - result-* : Outcome indicators (improve, degrade, inconclusive, neutral)\n * - data-* : Data visualization colors (chart series)\n * - on-* : Text on colored backgrounds\n * - surface-* : Elevated containers (NOT \"paper\")\n * - background-* : Page backgrounds\n * - text-* : Text colors\n * - border-* : Border colors\n * - interactive-* : Hover/focus/active/disabled states\n */\n\nimport { primitiveColors as p, primitiveRamps as ramp, greyRamp, discreteRainbow } from './primitives'\n\n/**\n * GREY MAPPING (TD-07.14) — how the old cool scales resolved onto `greyRamp`.\n *\n * Every grey below came off `grey` (pure R=G=B) or `neutral` (cool, R−B\n * down to −26). They were snapped by NEAREST L*, not by matching step numbers,\n * because the two old scales were numbered incompatibly: `grey` ran\n * INVERTED and compressed (0 = #6E6E6E lightest, 900 = #101010 darkest), so\n * `grey[400]` and `greyRamp[400]` have nothing to do with each other.\n *\n * grey 200→800 300→900 400→925 500→950\n * neutral 50→50 100→100 300→200 400→400 500→600 600→700 900→950\n *\n * Surfaces move ΔE 1.9–4.8 — at or near imperceptible. The TEXT roles move\n * further (8.6–12.8), and that is the intended part of the change: they are\n * picking up the warmth the surfaces already had.\n *\n * Light gets its own column because strict L*-nearest collapsed `neutral[50]`\n * and `[100]` onto one step, flattening surface-elevated into surface-raised.\n * Light is still deferred as a design question — there is no `surfaceRampLight`.\n *\n * `border-default`, `-subtle` and `-strong` are GONE, replaced by `hairline-*`.\n * Once the planes became ramp steps, every value dark enough to read as a\n * border was also a plane's fill. Alpha composites instead of colliding.\n *\n * `text-tertiary` on dark is the one role that ignores L*-nearest; see it.\n */\n\n// Light mode semantic colors (default)\nexport const semanticColorsLight = {\n // Brand colors (brand-*)\n 'brand-primary': ramp.orange[400],\n 'brand-primary-light': ramp.orange[300],\n 'brand-primary-dark': ramp.orange[500],\n 'brand-primary-subtle': 'rgba(255, 121, 0, 0.08)',\n 'brand-primary-hover': ramp.orange[500],\n 'brand-primary-active': ramp.orange[600],\n\n 'brand-secondary': ramp.cyan[600],\n 'brand-secondary-light': ramp.cyan[500],\n 'brand-secondary-dark': ramp.cyan[700],\n 'brand-secondary-subtle': 'rgba(48, 123, 155, 0.08)',\n 'brand-secondary-hover': ramp.cyan[700],\n 'brand-secondary-active': ramp.cyan[800],\n\n // Text on brand backgrounds (on-*)\n 'on-brand-primary': p.white,\n 'on-brand-secondary': p.white,\n\n // Status colors (status-*)\n 'status-success': ramp.green[300],\n 'status-success-light': ramp.green[200],\n 'status-success-dark': ramp.green[600],\n 'status-success-subtle': ramp.green[50],\n\n // Live-session accent — its OWN role, decoupled from success so the two can diverge\n 'status-live': ramp.green[300],\n 'status-live-muted': ramp.green[500],\n\n 'status-error': ramp.red[600],\n 'status-error-light': ramp.red[500],\n 'status-error-dark': ramp.red[700],\n 'status-error-subtle': ramp.red[50],\n\n 'status-error-vivid': ramp.red[600], // vivid alert red\n 'status-error-vivid-light': ramp.red[500],\n 'status-error-vivid-dark': ramp.red[700],\n 'status-error-vivid-subtle': 'rgba(255, 71, 87, 0.12)',\n\n 'status-warning': ramp.amber[300],\n 'status-warning-light': ramp.amber[200],\n 'status-warning-dark': ramp.amber[500],\n 'status-warning-subtle': ramp.amber[50],\n\n 'status-info': ramp.blue[500],\n 'status-info-light': ramp.blue[300],\n 'status-info-dark': ramp.blue[600],\n 'status-info-subtle': ramp.blue[50],\n\n // Text on status backgrounds (on-status-*)\n 'on-status-success': p.white,\n 'on-status-error': p.white,\n 'on-status-warning': p.white,\n 'on-status-info': p.white,\n\n // Result/outcome indicators (result-*)\n 'result-improve': '#4caf50', // Green - positive outcome\n 'result-improve-light': 'rgba(76, 175, 80, 0.12)',\n 'result-improve-dark': '#248a24',\n 'result-degrade': '#ef5350', // Red - negative outcome\n 'result-degrade-light': 'rgba(239, 83, 80, 0.12)',\n 'result-degrade-dark': '#b30000',\n 'result-inconclusive': '#9E9A97', // Gray - no clear result\n 'result-inconclusive-light': 'rgba(158, 154, 151, 0.12)',\n 'result-neutral': greyRamp[600], // Neutral baseline\n\n // Text on result backgrounds (on-result-*)\n 'on-result-improve': p.white,\n 'on-result-degrade': p.white,\n 'on-result-inconclusive': p.white,\n\n // Data visualization colors (data-*)\n // First 10 colors from discrete rainbow optimized for charts\n 'data-1': discreteRainbow[9], // Blue\n 'data-2': discreteRainbow[14], // Green\n 'data-3': discreteRainbow[17], // Yellow\n 'data-4': discreteRainbow[25], // Red\n 'data-5': discreteRainbow[8], // Purple\n 'data-6': discreteRainbow[20], // Orange\n 'data-7': discreteRainbow[13], // Light Blue\n 'data-8': discreteRainbow[15], // Light Green\n 'data-9': discreteRainbow[3], // Lavender\n 'data-10': discreteRainbow[22], // Dark Orange\n\n // Text colors (text-*)\n 'text-primary': '#121828',\n 'text-secondary': '#65748B',\n 'text-tertiary': greyRamp[400],\n 'text-disabled': 'rgba(55, 65, 81, 0.48)',\n 'text-inverse': p.white,\n 'text-link': ramp.blue[600],\n 'text-link-hover': ramp.blue[700],\n\n // Surface colors (surface-*) - for elevated containers\n 'surface-base': p.white,\n 'surface-elevated': greyRamp[50], // slightly off-white for elevated cards\n 'surface-raised': greyRamp[100], // light gray for raised cards\n 'surface-overlay': p.white,\n 'surface-input': greyRamp[50], // Input field background (filled variant)\n\n // Background colors (background-*)\n 'background-base': '#EBEBEB',\n 'background-default': p.white,\n 'background-subtle': greyRamp[50],\n // Frame/bezel chrome — top bar + side nav shell, one step below\n // `background-base`. Placeholder pairing for light mode, which is deferred.\n 'background-frame': greyRamp[400],\n\n // Border colors (border-*)\n 'border-prominent': greyRamp[400], // high-visibility divider\n 'border-focus': ramp.blue[600],\n 'border-input': greyRamp[200], // Input field border\n 'border-input-hover': greyRamp[400], // Input field border on hover\n 'border-input-focus': ramp.blue[600], // Input field border on focus\n 'border-input-error': ramp.red[600], // Input field border on error\n\n // Alpha hairline separators (surface-independent — composite toward black on\n // light surfaces, mirroring the dark-mode white-alpha family). See §4/S-2.\n 'hairline-subtle': 'rgba(0, 0, 0, 0.06)',\n 'hairline-default': 'rgba(0, 0, 0, 0.09)',\n 'hairline-strong': 'rgba(0, 0, 0, 0.14)',\n\n // Interactive states (interactive-*)\n 'interactive-hover': 'rgba(55, 65, 81, 0.04)',\n 'interactive-focus': 'rgba(55, 65, 81, 0.12)',\n 'interactive-active': 'rgba(55, 65, 81, 0.16)',\n 'interactive-selected': 'rgba(55, 65, 81, 0.08)',\n 'interactive-disabled': 'rgba(55, 65, 81, 0.12)',\n 'interactive-disabled-text': 'rgba(55, 65, 81, 0.26)',\n\n // Divider\n 'divider': '#E8E9EB',\n\n // Avatar default\n 'avatar-background': greyRamp[600],\n 'avatar-text': p.white,\n} as const\n\n// Dark mode semantic colors\nexport const semanticColorsDark = {\n // Brand colors stay the same in dark mode\n 'brand-primary': ramp.orange[400],\n 'brand-primary-light': ramp.orange[300],\n 'brand-primary-dark': ramp.orange[500],\n 'brand-primary-subtle': 'rgba(255, 121, 0, 0.12)',\n 'brand-primary-hover': ramp.orange[300],\n 'brand-primary-active': ramp.orange[200],\n\n 'brand-secondary': ramp.cyan[600],\n 'brand-secondary-light': ramp.cyan[500],\n 'brand-secondary-dark': ramp.cyan[700],\n 'brand-secondary-subtle': 'rgba(48, 123, 155, 0.12)',\n 'brand-secondary-hover': ramp.cyan[500],\n 'brand-secondary-active': ramp.cyan[400],\n\n // Text on brand backgrounds\n 'on-brand-primary': p.white,\n 'on-brand-secondary': p.white,\n\n // Status colors\n 'status-success': ramp.green[300],\n 'status-success-light': ramp.green[200],\n 'status-success-dark': ramp.green[600],\n 'status-success-subtle': 'rgba(46, 213, 115, 0.12)',\n\n // Live-session accent — its OWN role, decoupled from success so the two can diverge\n 'status-live': ramp.green[300],\n 'status-live-muted': ramp.green[500],\n\n 'status-error': ramp.red[600],\n 'status-error-light': ramp.red[500],\n 'status-error-dark': ramp.red[700],\n 'status-error-subtle': 'rgba(209, 67, 67, 0.12)',\n\n 'status-error-vivid': ramp.red[600],\n 'status-error-vivid-light': ramp.red[500],\n 'status-error-vivid-dark': ramp.red[700],\n 'status-error-vivid-subtle': 'rgba(255, 71, 87, 0.12)',\n\n 'status-warning': ramp.amber[300],\n 'status-warning-light': ramp.amber[200],\n 'status-warning-dark': ramp.amber[500],\n 'status-warning-subtle': 'rgba(249, 180, 21, 0.12)',\n\n 'status-info': ramp.blue[500],\n 'status-info-light': ramp.blue[300],\n 'status-info-dark': ramp.blue[600],\n 'status-info-subtle': 'rgba(33, 150, 243, 0.12)',\n\n // Text on status backgrounds\n 'on-status-success': p.white,\n 'on-status-error': p.white,\n 'on-status-warning': p.white,\n 'on-status-info': p.white,\n\n // Result/outcome indicators (result-*)\n 'result-improve': '#4caf50',\n 'result-improve-light': 'rgba(76, 175, 80, 0.16)',\n 'result-improve-dark': '#248a24',\n 'result-degrade': '#ef5350',\n 'result-degrade-light': 'rgba(239, 83, 80, 0.16)',\n 'result-degrade-dark': '#b30000',\n 'result-inconclusive': '#9E9A97',\n 'result-inconclusive-light': 'rgba(158, 154, 151, 0.16)',\n 'result-neutral': greyRamp[400],\n\n // Text on result backgrounds\n 'on-result-improve': p.white,\n 'on-result-degrade': p.white,\n 'on-result-inconclusive': p.white,\n\n // Data visualization colors (same in dark mode for consistency)\n 'data-1': discreteRainbow[9],\n 'data-2': discreteRainbow[14],\n 'data-3': discreteRainbow[17],\n 'data-4': discreteRainbow[25],\n 'data-5': discreteRainbow[8],\n 'data-6': discreteRainbow[20],\n 'data-7': discreteRainbow[13],\n 'data-8': discreteRainbow[15],\n 'data-9': discreteRainbow[3],\n 'data-10': discreteRainbow[22],\n\n // Text colors - inverted for dark mode\n 'text-primary': greyRamp[50],\n 'text-secondary': greyRamp[400],\n // Deliberately ONE step lighter than the L*-nearest match (`greyRamp[600]`).\n // The colour this replaced failed WCAG large-text outright on the three\n // lightest planes — 2.96 / 2.72 / 2.49 against elevated / raised / overlay —\n // and `600` carried that failure forward almost exactly (2.93 / 2.70 / 2.47).\n // `500` clears 3:1 everywhere (3.32–5.34). Contrast beats colour fidelity for\n // text roles; borders and surfaces still use strict L*-nearest. See\n // semantic-contrast.test.ts, which fails if this is moved back down.\n 'text-tertiary': greyRamp[500],\n 'text-disabled': 'rgba(255, 255, 255, 0.38)',\n 'text-inverse': greyRamp[950],\n 'text-link': '#828DF8',\n 'text-link-hover': ramp.blue[400],\n\n // Surface colors - dark backgrounds — warm-tapered DERIVED ramp (TD-surface-tokens,\n // S-1, re-spaced S-3). Shipped verbatim from `deriveSurfaceRamp()` — see\n // `surfaceRampDark` in primitives.ts for the full derivation note. `surface-overlay`\n // and `surface-elevated` are distinct (were both #191919 pre-S-1); `surface-input`\n // tracks one plane above `surface-base`, same relative position as before the remap.\n // `background-base` backs `Surface level=\"background\"` (SurfaceContext.SURFACE_LEVEL_TOKEN),\n // so it takes the ramp's shell role. The deepest plane is `background-frame`,\n // which is also the `SurfaceLevel` floor a pressed surface clamps at.\n 'surface-base': greyRamp[925], // main surface (#252321, L*13.9)\n 'surface-elevated': greyRamp[900], // elevated surface (#2C2A28, L*17.2 — nav/rail)\n 'surface-raised': greyRamp[875], // raised surface (#31302F, L*19.9 — cards)\n 'surface-overlay': greyRamp[850], // overlay surface (#373635, L*22.7 — hero/popover)\n 'surface-input': greyRamp[900], // input surface (#2C2A28 — one plane above base)\n\n // Background colors — same ramp, the frame/shell end of it.\n 'background-base': greyRamp[950], // shell (#1C1916, L*9 — Surface level=\"background\")\n 'background-default': greyRamp[925], // main background (#252321, L*13.9 — matches surface-base)\n 'background-subtle': greyRamp[900], // subtle background (#2C2A28, L*17.2 — matches surface-elevated)\n // Frame/bezel chrome — the top bar + side nav shell, one step BELOW\n // `background-base`. It used to be described as sitting OUTSIDE the ramp; it\n // is simply the ramp's last step now, and the floor `<Surface pressed>` clamps at.\n 'background-frame': greyRamp[975], // frame / bezel (#100D0A, L*3.8)\n\n // Border colors — solid dark borders are RETIRED (TD-07.14). Not a preference — a structural\n // consequence of one ramp. Every step from 850 to 975 is now a surface plane,\n // so a solid border dark enough to read as a border necessarily equals some\n // plane's fill, which is exactly the collision `surface.contract.test.ts` R2\n // forbids. The only non-plane steps left in that band are 800 and 700, and\n // borders there jump from L*~10-25 to L*~28-38 — a restyle, not a migration.\n //\n // So separation moves to the alpha hairlines, which dark mode already called\n // \"the primary separation cue\". Being alpha, they composite against whatever\n // plane they land on and cannot collide with any of them — the problem stops\n // existing rather than being re-solved per plane. The three solid tokens were\n // deleted outright; consumers point at the `hairline-*` family below.\n //\n // `border-prominent` stays SOLID: it is the one border meant to be seen\n // outright (4 call sites, high-visibility dividers), and grey-800 is not a\n // plane, so it keeps its job without collision.\n 'border-prominent': greyRamp[800], // high-visibility divider\n 'border-focus': '#828DF8',\n 'border-input': greyRamp[700],\n 'border-input-hover': greyRamp[600],\n 'border-input-focus': '#828DF8',\n 'border-input-error': ramp.red[500],\n\n // Alpha hairline separators — the primary separation cue (§4/S-2). Self-\n // normalizing: composites toward white by ~the same amount on ANY plane, so\n // one family works at every elevation instead of per-surface border tokens.\n // Shadows are demoted to floating-overlay use only (not shipped as a fill\n // separator here — see elevation.ts, follow-up S-4).\n //\n // RETUNED on the wall (VW-99, S-6). The original .06/.09/.14 were set at a\n // desk. On the panel at ~3 m `subtle` rendered but was indiscernible, and\n // `default` — the load-bearing one, with no solid-border fallback since\n // TD-07.14 — went weak on the lightest plane. `strong` read cleanly with room\n // to spare, which is what made raising the whole family viable.\n //\n // Each tier steps up onto the next MEASURED-GOOD rung rather than an\n // interpolated one: the new `subtle` is the old `default`, and the new\n // `default` is the old `strong` — a value just confirmed legible on all four\n // planes. Spacing goes 1 : 1.56 : 2.33, against the original 1 : 1.5 : 2.33.\n //\n // RUN 2 (VW-99): all three tiers were seen on all four planes — the retune\n // worked — but `subtle` was still \"a bit hard to read\", so the whole family\n // took a further +.01. That is a comfort margin on a passing row, not a fix\n // for a failing one, which is why it is a flat offset: the 1 : 1.56 : 2.33\n // spacing that the run validated is preserved rather than re-derived.\n //\n // Keep these to TWO decimals. react-native-web quantises alpha to 8 bits, so\n // a 3-decimal value silently rounds on the way to the DOM (.135 renders as\n // .13) — the token would say one thing and paint another.\n //\n // DARK ONLY. The light family above composites toward BLACK on light planes,\n // which this run says nothing about — do not mirror these numbers into it\n // without its own verification.\n 'hairline-subtle': 'rgba(255, 255, 255, 0.10)',\n 'hairline-default': 'rgba(255, 255, 255, 0.15)',\n 'hairline-strong': 'rgba(255, 255, 255, 0.22)',\n\n // Interactive states\n 'interactive-hover': 'rgba(255, 255, 255, 0.04)',\n 'interactive-focus': 'rgba(255, 255, 255, 0.12)',\n 'interactive-active': 'rgba(255, 255, 255, 0.16)',\n 'interactive-selected': 'rgba(255, 255, 255, 0.08)',\n 'interactive-disabled': 'rgba(255, 255, 255, 0.12)',\n 'interactive-disabled-text': 'rgba(255, 255, 255, 0.26)',\n\n // Divider\n 'divider': 'rgba(255, 255, 255, 0.09)',\n\n // Avatar default\n 'avatar-background': greyRamp[700],\n 'avatar-text': p.white,\n} as const\n\n// Typography tokens matching existing app\nexport const semanticTypography = {\n // Headings (Space Grotesk)\n h1: {\n fontFamily: 'heading',\n fontSize: '3.5rem',\n fontWeight: 700,\n lineHeight: 1.375,\n },\n h2: {\n fontFamily: 'heading',\n fontSize: '3rem',\n fontWeight: 700,\n lineHeight: 1.375,\n },\n h3: {\n fontFamily: 'heading',\n fontSize: '2.25rem',\n fontWeight: 700,\n lineHeight: 1.375,\n },\n h4: {\n fontFamily: 'heading',\n fontSize: '2rem',\n fontWeight: 700,\n lineHeight: 1.375,\n },\n h5: {\n fontFamily: 'heading',\n fontSize: '1.5rem',\n fontWeight: 600,\n lineHeight: 1.375,\n },\n h6: {\n fontFamily: 'heading',\n fontSize: '1.125rem',\n fontWeight: 600,\n lineHeight: 1.375,\n },\n\n // Body text (Nunito Sans)\n body1: {\n fontFamily: 'body',\n fontSize: '1rem',\n fontWeight: 400,\n lineHeight: 1.5,\n },\n body2: {\n fontFamily: 'body',\n fontSize: '0.875rem',\n fontWeight: 400,\n lineHeight: 1.57,\n },\n subtitle1: {\n fontFamily: 'body',\n fontSize: '1rem',\n fontWeight: 500,\n lineHeight: 1.75,\n },\n subtitle2: {\n fontFamily: 'body',\n fontSize: '0.875rem',\n fontWeight: 500,\n lineHeight: 1.57,\n },\n caption: {\n fontFamily: 'body',\n fontSize: '0.75rem',\n fontWeight: 400,\n lineHeight: 1.66,\n },\n overline: {\n fontFamily: 'body',\n fontSize: '0.75rem',\n fontWeight: 600,\n lineHeight: 2.5,\n letterSpacing: '0.5px',\n textTransform: 'uppercase' as const,\n },\n button: {\n fontFamily: 'sans',\n fontSize: '0.875rem',\n fontWeight: 600,\n lineHeight: 1.75,\n },\n} as const\n\n// Button size tokens\nexport const buttonSizes = {\n sm: {\n paddingX: '16px',\n paddingY: '6px',\n fontSize: '0.875rem',\n },\n md: {\n paddingX: '20px',\n paddingY: '8px',\n fontSize: '0.875rem',\n },\n lg: {\n paddingX: '24px',\n paddingY: '11px',\n fontSize: '1rem',\n },\n} as const\n\n// Export type for theme mode\nexport type ThemeMode = 'light' | 'dark'\n\n// Helper to get semantic colors based on mode\nexport function getSemanticColors(mode: ThemeMode) {\n return mode === 'dark' ? semanticColorsDark : semanticColorsLight\n}\n"]}
1
+ {"version":3,"sources":["../../src/theme/tokens/primitives.ts","../../src/theme/tokens/semantic.ts"],"names":[],"mappings":"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","file":"tokens.mjs","sourcesContent":["/**\n * Primitive Design Tokens\n *\n * Raw values with no semantic meaning. These are the foundation of the design system\n * and should rarely be used directly in components. Use semantic tokens instead.\n */\n\n/**\n * Absolute colour keywords.\n *\n * This used to hold five scales — `blue`, `red`, `redVivid`, `neutral` and\n * `charcoal`. All five are gone (TD-07.14): the greys folded into `greyRamp`\n * below and the chromatics into the OKLCH `primitiveRamps`. What is left has no\n * scale because these three are not colours you tune, they are keywords.\n */\nexport const primitiveColors = {\n white: '#FFFFFF',\n black: '#000000',\n transparent: 'transparent',\n} as const\n\n/**\n * The vivid alert red: the one chromatic anchor outside the OKLCH ramps.\n *\n * It survived the TD-07.14 fold of the old `redVivid` scale only as the\n * `-rgb`, `-subtle` and glow encodings of `status-error-vivid`, while the token\n * itself was pinned to `red[600]` and collapsed onto `status-error`. Owning it\n * here means the semantic layer references a primitive instead of carrying a\n * literal. The red ramp has no step this saturated, and adding one means\n * regenerating the ramp, so it stays a pin.\n */\nexport const alertRedVivid = '#FF4757' as const\n\n/**\n * Result/outcome palette anchors (VW-83): Material-style green/red/grey chosen\n * for the result-improve/-degrade/-inconclusive tokens. No `primitiveRamps` step\n * matches any of these exactly (the ramps are OKLCH-generated with a different\n * hue/chroma arc), so they are pinned by name here rather than left as raw hex\n * in semantic.ts — same pattern as {@link alertRedVivid}.\n */\nexport const resultPaletteColors = {\n improve: '#4caf50',\n improveDark: '#248a24',\n degrade: '#ef5350',\n degradeDark: '#b30000',\n inconclusive: '#9E9A97',\n} as const\n\n/**\n * One-off semantic literals (VW-83) with no exact `greyRamp`/`primitiveRamps`\n * match, pinned by name instead of left as raw hex in semantic.ts.\n */\nexport const semanticPins = {\n // Cool navy-black; darker and more blue-shifted than any warm greyRamp step.\n textPrimaryLight: '#121828',\n // Cool blue-grey; outside greyRamp's warm (R>=G>=B) scale.\n textSecondaryLight: '#65748B',\n // Pure neutral grey (R=G=B); no warm greyRamp step lands on it exactly.\n backgroundBaseLight: '#EBEBEB',\n // Near-neutral grey, kept one step off backgroundBaseLight by design.\n dividerLight: '#E8E9EB',\n // Periwinkle/indigo; more purple than any primitiveRamps.blue step. Shared by\n // dark-mode text-link, border-focus and border-input-focus.\n focusIndigoDark: '#828DF8',\n} as const\n\n/**\n * Unified warm-neutral grey ramp (TD-07.14)\n *\n * The ONE achromatic scale. Regenerate with `scripts/generate-grey-ramp.mjs` —\n * preserve the generator, not just the hexes.\n *\n * The surface planes ARE steps here rather than a parallel object: `850` is\n * overlay, `975` is the bezel. That is the whole point of the ramp. `grey`,\n * `neutral`, `surfaceRampDark` and `backgroundFrameDark` all resolve into it,\n * which is why every plane step below is byte-identical to the value that\n * shipped in v0.10.0 — the surfaces do not move, only their names.\n *\n * TWO THINGS ABOUT THE NUMBERING, both deliberate and both previously re-derived\n * from scratch more than once because they were never written down:\n *\n * 1. `975` sits BELOW the standard grid. `canonL` — the median L* of the seven\n * chromatic `primitiveRamps` at each step — ends at L*10.3, which is step\n * `950`. The bezel is L*3.8, darker than the grid's last rung, so there is\n * simply no step number left for it and `975` extends past the end.\n * 2. `850`/`875` are quarter-steps because overlay/raised/elevated are only\n * ~2.7 L* apart and all three collide on `900` at normal resolution. `800`\n * is a generated bridge between `700` (L*37.9) and overlay (L*22.7) so the\n * spacing stays even across the join.\n *\n * There is no `inset`. It was retired, not renamed: at ΔE 1.10 from `975` it was\n * an imperceptible duplicate of the frame, which is exactly why `<Surface pressed>`\n * (surface − 1) kept collapsing into it. `975` is the floor.\n *\n * Spec, generator and the rejected v1/v2 cuts:\n * sources/design/foundations/warm-grey-ramp/\n */\nexport const greyRamp = {\n 50: '#F9F6F3', // L*97.0 W6\n 100: '#EDEAE7', // L*92.8 W6\n 200: '#D4D1CE', // L*84.0 W6 — warm silver\n 300: '#BDBAB7', // L*75.7 W6\n 400: '#A29F9D', // L*65.7 W5\n 500: '#888684', // L*56.0 W4\n 600: '#72716F', // L*47.7 W3\n 700: '#5A5958', // L*37.9 W2\n 800: '#424140', // L*27.6 W2 — generated bridge\n 850: '#373635', // L*22.7 W2 — surface overlay\n 875: '#31302F', // L*19.9 W2 — surface raised\n 900: '#2C2A28', // L*17.2 W4 — surface elevated\n 925: '#252321', // L*13.9 W4 — surface base\n 950: '#1C1916', // L*9.0 W6 — background base / shell\n 975: '#100D0A', // L*3.8 W6 — background frame / bezel\n} as const\n\n/**\n * The surface planes, as ramp steps — the mapping `<Surface level>` resolves through.\n *\n * Ordered darkest -> lightest, which is the order `pressedLevel()` walks.\n */\nexport const SURFACE_PLANE_STEPS = {\n frame: 975,\n background: 950,\n base: 925,\n elevated: 900,\n raised: 875,\n overlay: 850,\n} as const\n\n/**\n * Derived tonal ramps (TD-05.09 color foundations)\n *\n * Seven OKLCH-generated hue ramps, 11 perceptual lightness steps each (50 -> 950).\n * Built with hue-torsion + a chroma arc, anchored through existing brand/semantic\n * hexes. `pin` marks the step each ramp flows through its anchor.\n * This is the single source of truth for chromatic hexes — the categorical palette\n * below references these steps rather than duplicating values.\n * See sources/design/foundations.\n */\nexport const primitiveRamps = {\n red: {\n 50: '#FFF4F4',\n 100: '#FFE3E5',\n 200: '#FFC2C5',\n 300: '#FF9A9D',\n 400: '#F77175',\n 500: '#E05254',\n 600: '#D14343', // pin\n 700: '#A4221C',\n 800: '#7E1002',\n 900: '#5A0900',\n 950: '#3D0400',\n },\n orange: {\n 50: '#FFF5ED',\n 100: '#FFE6D4',\n 200: '#FFC7A2',\n 300: '#FFA063',\n 400: '#FF7900', // pin\n 500: '#DA5F00',\n 600: '#B94A00',\n 700: '#983804',\n 800: '#6F290F',\n 900: '#4E1C0C',\n 950: '#331107',\n },\n amber: {\n 50: '#FFF7DD',\n 100: '#FFEAA9',\n 200: '#FFD352',\n 300: '#F9B415', // pin\n 400: '#E08C00',\n 500: '#C27400',\n 600: '#A45E00',\n 700: '#814D14',\n 800: '#5B3A1A',\n 900: '#442503',\n 950: '#301500',\n },\n green: {\n 50: '#E3FFEE',\n 100: '#B5FFD2',\n 200: '#58F69E',\n 300: '#2ED573', // pin\n 400: '#21C05D',\n 500: '#22A444',\n 600: '#298732',\n 700: '#2B6B25',\n 800: '#264D1C',\n 900: '#1B3515',\n 950: '#11220D',\n },\n cyan: {\n 50: '#E6FBFF',\n 100: '#C2F6FF',\n 200: '#62EAFF',\n 300: '#22D3EE', // pin\n 400: '#01B5D1',\n 500: '#2697B7',\n 600: '#307B9B',\n 700: '#2A617F',\n 800: '#22465F',\n 900: '#0B3149',\n 950: '#001F36',\n },\n blue: {\n 50: '#EFF8FF',\n 100: '#D9EFFF',\n 200: '#ACDBFF',\n 300: '#78C2FF',\n 400: '#3CA8FF',\n 500: '#2196F3', // pin\n 600: '#1072CB',\n 700: '#135AA8',\n 800: '#14407E',\n 900: '#112C5A',\n 950: '#091B3C',\n },\n magenta: {\n 50: '#FFF3F9',\n 100: '#FFE2F1',\n 200: '#FFBDE2',\n 300: '#FF8FD5',\n 400: '#ED69C3',\n 500: '#D548AF',\n 600: '#BA2996',\n 700: '#9C0D7A', // pin\n 800: '#77005A',\n 900: '#56003F',\n 950: '#3B0029',\n },\n} as const\n\n/**\n * Categorical (qualitative) palette — an ordered, CVD-safe series expressed as\n * references into {@link primitiveRamps} (one source of truth; the palette moves\n * with the ramps).\n *\n * Design: a single canonical hue order (blue, magenta, red, orange, green, cyan,\n * amber), with steps chosen vivid-midtone-first and fanned lighter/darker as the\n * series grows to preserve separation. The sequence is nested-stable — a chart\n * with N series uses the first N colors, and the series index is stable as N\n * changes. Colorblind-safe worst-case deuteranopia/protanopia floor 8 holds\n * through {@link CATEGORICAL_CVD_SAFE_MAX} colors; the 7th is an extended color\n * that should be paired with a legend or other secondary encoding.\n *\n * Two variants: `default` (vivid, sits on neutral/light surfaces, legible under\n * black text) and `dark` (deeper shades legible under white text on a fill). A\n * separate \"light\" variant was dropped — the vivid `default` picks already clear\n * black-text contrast, so it doubles as the light-context palette.\n */\nexport const categoricalPalette = {\n default: [\n primitiveRamps.blue[500],\n primitiveRamps.magenta[500],\n primitiveRamps.red[500],\n primitiveRamps.orange[400],\n primitiveRamps.green[300],\n primitiveRamps.cyan[300],\n primitiveRamps.amber[600], // extended (7th) — pair with a legend\n ],\n dark: [\n primitiveRamps.blue[600],\n primitiveRamps.magenta[600],\n primitiveRamps.red[500],\n primitiveRamps.orange[600],\n primitiveRamps.green[800],\n primitiveRamps.cyan[800],\n primitiveRamps.amber[500], // extended (7th) — pair with a legend\n ],\n} as const\n\n/** Largest series count that holds the CVD floor without a legend. */\nexport const CATEGORICAL_CVD_SAFE_MAX = 6\n\n/**\n * Categorical palette variant.\n * - `default` : vivid; neutral/light surfaces, legible under black text\n * - `dark` : deeper shades, legible under white text on a filled swatch\n */\nexport type CategoricalVariant = keyof typeof categoricalPalette\n\n/**\n * Get a color from the ordered categorical palette by series index.\n * The palette is nested-stable, so the color for a given index does not change\n * with the total series count; `index` simply wraps past the end.\n *\n * @param index - 0-based series index (wraps past the end)\n * @param variant - `default` (black-text / light surfaces) or `dark` (white text)\n * @returns The hex color string\n */\nexport function getCategoricalColor(\n index: number,\n variant: CategoricalVariant = 'default'\n): string {\n const palette = categoricalPalette[variant]\n index = Math.max(0, Math.floor(index))\n return palette[index % palette.length]\n}\n\n/**\n * Diverging status scale (BodyMap training-status: under → optimal → over) as\n * references into {@link primitiveRamps}. A true diverging shape — `optimal` is\n * the lightest center, the extremes go darker — so the signal reads in lightness\n * (colorblind-robust; worst-case deut/protanopia min ΔE ~10.9) and the direction\n * reads in the blue↔red axis (the CVD-safe hue pair).\n *\n * Tuned so every stop is dark enough for the fill yet light enough that BLACK\n * text clears 4.5:1 on all five — no per-cell white/black flipping. The value\n * valley is symmetric: the two mid-arms (maintenance / approaching) sit at equal\n * lightness (both ~0.53 relative luminance), the ends darker.\n */\nexport const divergingScale = [\n primitiveRamps.blue[500], // under\n primitiveRamps.cyan[300], // maintenance\n primitiveRamps.green[200], // optimal (light center)\n primitiveRamps.amber[300], // approaching\n primitiveRamps.red[600], // over\n] as const\n\n/**\n * Sequential \"effort\" scale (low → high intensity: green → yellow → orange → red)\n * as references into {@link primitiveRamps}. A 6-stop ordinal palette; the\n * velocity/RPE strip sub-samples it. Every adjacent pair clears the CVD floor\n * (min deut/protan ΔE ≥ 4.5), and within that the hue walk is kept smooth —\n * the amber-200 → amber-300 → orange-400 run steps the yellow→orange transition\n * gradually rather than lurching. Order encodes magnitude, so it tolerates the\n * green↔red CVD pair. Stops 0–3 take black text; the dark reds take white.\n */\nexport const sequentialEffort = [\n primitiveRamps.green[300],\n primitiveRamps.amber[200],\n primitiveRamps.amber[300],\n primitiveRamps.orange[400],\n primitiveRamps.red[600],\n primitiveRamps.red[700],\n] as const\n\n/**\n * Best-contrast text color (black or white) for a solid fill — for labels sitting\n * on categorical/diverging/effort swatches. Uses the WCAG relative-luminance ratio.\n */\nexport function bestTextColor(hex: string): '#000000' | '#FFFFFF' {\n const [r, g, b] = [0, 2, 4].map((i) => {\n const c = parseInt(hex.replace('#', '').slice(i, i + 2), 16) / 255\n return c >= 0.04045 ? ((c + 0.055) / 1.055) ** 2.4 : c / 12.92\n })\n const l = 0.2126 * r + 0.7152 * g + 0.0722 * b\n return (l + 0.05) / 0.05 >= 1.05 / (l + 0.05) ? '#000000' : '#FFFFFF'\n}\n\n/**\n * Discrete rainbow palette for data visualization\n * Based on Paul Tol's color schemes: https://personal.sron.nl/~pault/#fig:scheme_rainbow_discrete\n */\nexport const discreteRainbow = [\n '#E8ECFB',\n '#D9CCE3',\n '#D1BBD7',\n '#CAACCB',\n '#BA8DB4',\n '#AE76A3',\n '#AA6F9E',\n '#994F88',\n '#882E72',\n '#1965B0',\n '#437DBF',\n '#5289C7',\n '#6195CF',\n '#7BAFDE',\n '#4EB265',\n '#90C987',\n '#CAE0AB',\n '#F7F056',\n '#F7CB45',\n '#F6C141',\n '#F4A736',\n '#F1932D',\n '#EE8026',\n '#E8601C',\n '#E65518',\n '#DC050C',\n '#A5170E',\n '#72190E',\n '#42150A',\n] as const\n\n/**\n * Palette indices for discrete rainbow colors at different palette sizes.\n * For a given palette size (index + 1), returns the indices of colors to use.\n */\nconst discreteRainbowPalettes: number[][] = [\n [10],\n [10, 26],\n [10, 18, 26],\n [10, 15, 18, 26],\n [10, 14, 15, 18, 26],\n [10, 14, 15, 17, 18, 26],\n [9, 10, 14, 15, 17, 18, 26],\n [9, 10, 14, 15, 17, 18, 23, 26],\n [9, 10, 14, 15, 17, 18, 23, 26, 28],\n [9, 10, 14, 15, 17, 18, 21, 24, 26, 28],\n [9, 10, 12, 14, 15, 17, 18, 21, 24, 26, 28],\n [3, 6, 9, 10, 12, 14, 15, 17, 18, 21, 24, 26],\n [3, 6, 9, 10, 12, 14, 15, 16, 17, 18, 21, 24, 26],\n [3, 6, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26],\n [3, 6, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28],\n [3, 5, 7, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28],\n [3, 5, 7, 8, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 28],\n [3, 5, 7, 8, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 27, 28],\n [2, 4, 5, 7, 8, 9, 10, 12, 14, 15, 16, 17, 18, 20, 22, 24, 26, 27, 28],\n [2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 27, 28],\n [2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 26, 27, 28],\n [2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 26, 27, 28, 29],\n [1, 2, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 26, 27, 28, 29],\n]\n\n/**\n * Get a color from the discrete rainbow palette for a given index and palette size.\n * Colors are optimized for visual distinction at each palette size.\n *\n * @param index - The index of the color in the series (0-based)\n * @param size - The total number of colors needed (1-23)\n * @returns The hex color string\n */\nexport function getDiscreteRainbowColor(index: number, size: number): string {\n index = Math.max(0, index)\n size = Math.min(Math.max(1, size), discreteRainbowPalettes.length)\n\n const palette = discreteRainbowPalettes[size - 1]\n if (index >= palette.length) index = index % palette.length\n\n return discreteRainbow[palette[index] - 1]\n}\n\nexport const primitiveTypography = {\n fontFamilies: {\n sans: [\n 'Inter',\n '-apple-system',\n 'BlinkMacSystemFont',\n 'Segoe UI',\n 'Helvetica',\n 'Arial',\n 'sans-serif',\n ],\n body: ['Nunito Sans', 'sans-serif'],\n heading: ['Space Grotesk', 'sans-serif'],\n mono: [\n 'SF Mono',\n 'Monaco',\n 'Inconsolata',\n 'Fira Mono',\n 'Droid Sans Mono',\n 'Source Code Pro',\n 'monospace',\n ],\n },\n fontSizes: {\n '2xs': '0.625rem', // 10px\n xs: '0.75rem', // 12px\n sm: '0.875rem', // 14px\n base: '1rem', // 16px\n lg: '1.125rem', // 18px\n xl: '1.5rem', // 24px\n '2xl': '2rem', // 32px\n '3xl': '2.25rem', // 36px\n '4xl': '3rem', // 48px\n '5xl': '3.5rem', // 56px\n },\n fontWeights: {\n normal: 400,\n medium: 500,\n semibold: 600,\n bold: 700,\n },\n lineHeights: {\n none: 1,\n tight: 1.375,\n snug: 1.5,\n normal: 1.57,\n relaxed: 1.66,\n loose: 1.75,\n },\n letterSpacing: {\n tighter: '-0.05em',\n tight: '-0.025em',\n normal: '0em',\n wide: '0.025em',\n wider: '0.05em',\n widest: '0.5px',\n },\n} as const\n\nexport const primitiveSpacing = {\n 0: '0',\n px: '1px',\n 0.5: '0.125rem', // 2px\n 1: '0.25rem', // 4px\n 1.5: '0.375rem', // 6px\n 2: '0.5rem', // 8px\n 2.5: '0.625rem', // 10px\n 3: '0.75rem', // 12px\n 3.5: '0.875rem', // 14px\n 4: '1rem', // 16px\n 5: '1.25rem', // 20px\n 6: '1.5rem', // 24px\n 7: '1.75rem', // 28px\n 8: '2rem', // 32px\n 9: '2.25rem', // 36px\n 10: '2.5rem', // 40px\n 11: '2.75rem', // 44px\n 12: '3rem', // 48px\n 14: '3.5rem', // 56px\n 16: '4rem', // 64px\n 20: '5rem', // 80px\n 24: '6rem', // 96px\n 28: '7rem', // 112px\n 32: '8rem', // 128px\n} as const\n\nexport const primitiveBorderRadius = {\n none: '0',\n sm: '4px',\n DEFAULT: '8px',\n md: '8px',\n lg: '12px',\n xl: '16px',\n '2xl': '24px',\n full: '9999px',\n} as const\n\nexport const primitiveBreakpoints = {\n xs: 0,\n sm: 600,\n md: 1000,\n lg: 1200,\n xl: 1920,\n} as const\n\nexport const primitiveZIndex = {\n hide: -1,\n auto: 'auto',\n base: 0,\n docked: 10,\n dropdown: 1000,\n sticky: 1100,\n drawer: 1100,\n banner: 1200,\n appBar: 1200,\n overlay: 1300,\n modal: 1400,\n popover: 1500,\n skipLink: 1600,\n toast: 1700,\n tooltip: 1800,\n} as const\n","/**\n * Semantic Design Tokens\n *\n * Meaningful tokens following DTCG (Design Tokens Community Group) naming conventions.\n * Pattern: {category}-{intent}-{variant?}-{state?}\n *\n * Categories:\n * - brand-* : Brand colors (primary, secondary, accent)\n * - status-* : Feedback colors (success, error, warning, info)\n * - result-* : Outcome indicators (improve, degrade, inconclusive, neutral)\n * - data-* : Data visualization colors (chart series)\n * - on-* : Text on colored backgrounds\n * - surface-* : Elevated containers (NOT \"paper\")\n * - background-* : Page backgrounds\n * - text-* : Text colors\n * - border-* : Border colors\n * - interactive-* : Hover/focus/active/disabled states\n */\n\nimport {\n primitiveColors as p,\n primitiveRamps as ramp,\n greyRamp,\n discreteRainbow,\n alertRedVivid,\n resultPaletteColors,\n semanticPins,\n} from './primitives'\n\n/**\n * GREY MAPPING (TD-07.14) — how the old cool scales resolved onto `greyRamp`.\n *\n * Every grey below came off `grey` (pure R=G=B) or `neutral` (cool, R−B\n * down to −26). They were snapped by NEAREST L*, not by matching step numbers,\n * because the two old scales were numbered incompatibly: `grey` ran\n * INVERTED and compressed (0 = #6E6E6E lightest, 900 = #101010 darkest), so\n * `grey[400]` and `greyRamp[400]` have nothing to do with each other.\n *\n * grey 200→800 300→900 400→925 500→950\n * neutral 50→50 100→100 300→200 400→400 500→600 600→700 900→950\n *\n * Surfaces move ΔE 1.9–4.8 — at or near imperceptible. The TEXT roles move\n * further (8.6–12.8), and that is the intended part of the change: they are\n * picking up the warmth the surfaces already had.\n *\n * Light gets its own column because strict L*-nearest collapsed `neutral[50]`\n * and `[100]` onto one step, flattening surface-elevated into surface-raised.\n * Light is still deferred as a design question — there is no `surfaceRampLight`.\n *\n * `border-default`, `-subtle` and `-strong` are GONE, replaced by `hairline-*`.\n * Once the planes became ramp steps, every value dark enough to read as a\n * border was also a plane's fill. Alpha composites instead of colliding.\n *\n * `text-tertiary` on dark is the one role that ignores L*-nearest; see it.\n */\n\n// Light mode semantic colors (default)\nexport const semanticColorsLight = {\n // Brand colors (brand-*)\n 'brand-primary': ramp.orange[400],\n 'brand-primary-light': ramp.orange[300],\n 'brand-primary-dark': ramp.orange[500],\n 'brand-primary-subtle': 'rgba(255, 121, 0, 0.08)',\n 'brand-primary-muted': 'rgba(255, 121, 0, 0.30)',\n 'brand-primary-strong': 'rgba(255, 121, 0, 0.50)',\n 'brand-primary-hover': ramp.orange[500],\n 'brand-primary-active': ramp.orange[600],\n\n 'brand-secondary': ramp.cyan[600],\n 'brand-secondary-light': ramp.cyan[500],\n 'brand-secondary-dark': ramp.cyan[700],\n 'brand-secondary-subtle': 'rgba(48, 123, 155, 0.08)',\n 'brand-secondary-muted': 'rgba(48, 123, 155, 0.30)',\n 'brand-secondary-strong': 'rgba(48, 123, 155, 0.50)',\n 'brand-secondary-hover': ramp.cyan[700],\n 'brand-secondary-active': ramp.cyan[800],\n\n // Text on brand backgrounds (on-*)\n 'on-brand-primary': p.white,\n 'on-brand-secondary': p.white,\n\n // Text ON a `-subtle` fill. Light mode keeps today's pairing (the base token) so\n // nothing moves here: light has the same disease mirrored — a light rung on a\n // near-white ramp[50] fill — but correcting it belongs with the light-mode pass\n // in AW-121, not this one.\n 'on-brand-primary-subtle': ramp.orange[400],\n 'on-brand-secondary-subtle': ramp.cyan[600],\n\n // Status colors (status-*)\n 'status-success': ramp.green[300],\n 'status-success-light': ramp.green[200],\n 'status-success-dark': ramp.green[600],\n 'status-success-subtle': ramp.green[50],\n 'status-success-muted': 'rgba(46, 213, 115, 0.30)',\n 'status-success-strong': 'rgba(46, 213, 115, 0.50)',\n\n // Live-session accent — its OWN role, decoupled from success so the two can diverge\n 'status-live': ramp.green[300],\n 'status-live-muted': ramp.green[500],\n\n 'status-error': ramp.red[600],\n 'status-error-light': ramp.red[500],\n 'status-error-dark': ramp.red[700],\n 'status-error-subtle': ramp.red[50],\n 'status-error-muted': 'rgba(209, 67, 67, 0.30)',\n 'status-error-strong': 'rgba(209, 67, 67, 0.50)',\n\n 'status-error-vivid': alertRedVivid, // NOT red[600], that is status-error\n 'status-error-vivid-light': ramp.red[500],\n 'status-error-vivid-dark': ramp.red[700],\n 'status-error-vivid-subtle': 'rgba(255, 71, 87, 0.12)',\n 'status-error-vivid-muted': 'rgba(255, 71, 87, 0.30)',\n 'status-error-vivid-strong': 'rgba(255, 71, 87, 0.50)',\n\n 'status-warning': ramp.amber[300],\n 'status-warning-light': ramp.amber[200],\n 'status-warning-dark': ramp.amber[500],\n 'status-warning-subtle': ramp.amber[50],\n 'status-warning-muted': 'rgba(249, 180, 21, 0.30)',\n 'status-warning-strong': 'rgba(249, 180, 21, 0.50)',\n\n 'status-info': ramp.blue[500],\n 'status-info-light': ramp.blue[300],\n 'status-info-dark': ramp.blue[600],\n 'status-info-subtle': ramp.blue[50],\n 'status-info-muted': 'rgba(33, 150, 243, 0.30)',\n 'status-info-strong': 'rgba(33, 150, 243, 0.50)',\n\n // Text ON a `-subtle` fill — see the on-brand-*-subtle note above.\n 'on-status-success-subtle': ramp.green[300],\n 'on-status-error-subtle': ramp.red[600],\n 'on-status-warning-subtle': ramp.amber[300],\n 'on-status-info-subtle': ramp.blue[500],\n\n // Text on status backgrounds (on-status-*)\n 'on-status-success': p.white,\n 'on-status-error': p.white,\n 'on-status-warning': p.white,\n 'on-status-info': p.white,\n\n // Result/outcome indicators (result-*)\n 'result-improve': resultPaletteColors.improve, // Green - positive outcome\n 'result-improve-light': 'rgba(76, 175, 80, 0.12)',\n 'result-improve-dark': resultPaletteColors.improveDark,\n 'result-degrade': resultPaletteColors.degrade, // Red - negative outcome\n 'result-degrade-light': 'rgba(239, 83, 80, 0.12)',\n 'result-degrade-dark': resultPaletteColors.degradeDark,\n 'result-inconclusive': resultPaletteColors.inconclusive, // Gray - no clear result\n 'result-inconclusive-light': 'rgba(158, 154, 151, 0.12)',\n 'result-neutral': greyRamp[600], // Neutral baseline\n\n // Text on result backgrounds (on-result-*)\n 'on-result-improve': p.white,\n 'on-result-degrade': p.white,\n 'on-result-inconclusive': p.white,\n\n // Data visualization colors (data-*)\n // First 10 colors from discrete rainbow optimized for charts\n 'data-1': discreteRainbow[9], // Blue\n 'data-2': discreteRainbow[14], // Green\n 'data-3': discreteRainbow[17], // Yellow\n 'data-4': discreteRainbow[25], // Red\n 'data-5': discreteRainbow[8], // Purple\n 'data-6': discreteRainbow[20], // Orange\n 'data-7': discreteRainbow[13], // Light Blue\n 'data-8': discreteRainbow[15], // Light Green\n 'data-9': discreteRainbow[3], // Lavender\n 'data-10': discreteRainbow[22], // Dark Orange\n\n // Text colors (text-*)\n 'text-primary': semanticPins.textPrimaryLight,\n 'text-secondary': semanticPins.textSecondaryLight,\n 'text-tertiary': greyRamp[400],\n 'text-disabled': 'rgba(55, 65, 81, 0.48)',\n 'text-inverse': p.white,\n 'text-link': ramp.blue[600],\n 'text-link-hover': ramp.blue[700],\n\n // Surface colors (surface-*) - for elevated containers\n 'surface-base': p.white,\n 'surface-elevated': greyRamp[50], // slightly off-white for elevated cards\n 'surface-raised': greyRamp[100], // light gray for raised cards\n 'surface-overlay': p.white,\n 'surface-input': greyRamp[50], // Input field background (filled variant)\n\n // Background colors (background-*)\n 'background-base': semanticPins.backgroundBaseLight,\n 'background-default': p.white,\n 'background-subtle': greyRamp[50],\n // Frame/bezel chrome — top bar + side nav shell, one step below\n // `background-base`. Placeholder pairing for light mode, which is deferred.\n 'background-frame': greyRamp[400],\n\n // Border colors (border-*)\n 'border-prominent': greyRamp[400], // high-visibility divider\n 'border-focus': ramp.blue[600],\n 'border-input': greyRamp[200], // Input field border\n 'border-input-hover': greyRamp[400], // Input field border on hover\n 'border-input-focus': ramp.blue[600], // Input field border on focus\n 'border-input-error': ramp.red[600], // Input field border on error\n\n // Alpha hairline separators (surface-independent — composite toward black on\n // light surfaces, mirroring the dark-mode white-alpha family). See §4/S-2.\n 'hairline-subtle': 'rgba(0, 0, 0, 0.06)',\n 'hairline-default': 'rgba(0, 0, 0, 0.09)',\n 'hairline-strong': 'rgba(0, 0, 0, 0.14)',\n\n // Interactive states (interactive-*)\n 'interactive-hover': 'rgba(55, 65, 81, 0.04)',\n 'interactive-focus': 'rgba(55, 65, 81, 0.12)',\n 'interactive-active': 'rgba(55, 65, 81, 0.16)',\n 'interactive-selected': 'rgba(55, 65, 81, 0.08)',\n 'interactive-disabled': 'rgba(55, 65, 81, 0.12)',\n 'interactive-disabled-text': 'rgba(55, 65, 81, 0.26)',\n\n // Divider\n divider: semanticPins.dividerLight,\n\n // Avatar default\n 'avatar-background': greyRamp[600],\n 'avatar-text': p.white,\n} as const\n\n// Dark mode semantic colors\nexport const semanticColorsDark = {\n // Brand colors stay the same in dark mode\n 'brand-primary': ramp.orange[400],\n 'brand-primary-light': ramp.orange[300],\n 'brand-primary-dark': ramp.orange[500],\n 'brand-primary-subtle': 'rgba(255, 121, 0, 0.12)',\n 'brand-primary-muted': 'rgba(255, 121, 0, 0.30)',\n 'brand-primary-strong': 'rgba(255, 121, 0, 0.50)',\n 'brand-primary-hover': ramp.orange[300],\n 'brand-primary-active': ramp.orange[200],\n\n 'brand-secondary': ramp.cyan[600],\n 'brand-secondary-light': ramp.cyan[500],\n 'brand-secondary-dark': ramp.cyan[700],\n 'brand-secondary-subtle': 'rgba(34, 211, 238, 0.12)',\n 'brand-secondary-muted': 'rgba(48, 123, 155, 0.30)',\n 'brand-secondary-strong': 'rgba(48, 123, 155, 0.50)',\n 'brand-secondary-hover': ramp.cyan[500],\n 'brand-secondary-active': ramp.cyan[400],\n\n // Text on brand backgrounds\n 'on-brand-primary': p.white,\n 'on-brand-secondary': p.white,\n\n // Text ON a `-subtle` fill. Its own role: `brand-primary` and friends are tuned to\n // carry a white label as a solid fill, which makes the two deepest of them\n // (cyan[600], red[600]) too dark to read as text on a dark plane. Levelling the\n // family at rung 300 puts every tone within OKLCH L 0.769-0.813 instead of\n // 0.550-0.813. Brand is deliberately left at its own orange[400] (operator, AW-133)\n // so the Voltras tone never drifts; it is the one tone under AA on a raised card.\n 'on-brand-primary-subtle': ramp.orange[400],\n 'on-brand-secondary-subtle': ramp.cyan[300],\n\n // Status colors\n 'status-success': ramp.green[300],\n 'status-success-light': ramp.green[200],\n 'status-success-dark': ramp.green[600],\n 'status-success-subtle': 'rgba(46, 213, 115, 0.12)',\n 'status-success-muted': 'rgba(46, 213, 115, 0.30)',\n 'status-success-strong': 'rgba(46, 213, 115, 0.50)',\n\n // Live-session accent — its OWN role, decoupled from success so the two can diverge\n 'status-live': ramp.green[300],\n 'status-live-muted': ramp.green[500],\n\n 'status-error': ramp.red[600],\n 'status-error-light': ramp.red[500],\n 'status-error-dark': ramp.red[700],\n // Alpha 0.08, not the family's 0.12: error's label is red[400], a rung darker than\n // its siblings so it reads RED rather than pink (rung 300 has only 0.121 chroma).\n // Thinning the fill buys back the contrast that extra darkness costs. See AW-133.\n 'status-error-subtle': 'rgba(247, 113, 117, 0.08)',\n 'status-error-muted': 'rgba(209, 67, 67, 0.30)',\n 'status-error-strong': 'rgba(209, 67, 67, 0.50)',\n\n 'status-error-vivid': alertRedVivid,\n 'status-error-vivid-light': ramp.red[500],\n 'status-error-vivid-dark': ramp.red[700],\n 'status-error-vivid-subtle': 'rgba(255, 71, 87, 0.12)',\n 'status-error-vivid-muted': 'rgba(255, 71, 87, 0.30)',\n 'status-error-vivid-strong': 'rgba(255, 71, 87, 0.50)',\n\n 'status-warning': ramp.amber[300],\n 'status-warning-light': ramp.amber[200],\n 'status-warning-dark': ramp.amber[500],\n 'status-warning-subtle': 'rgba(249, 180, 21, 0.12)',\n 'status-warning-muted': 'rgba(249, 180, 21, 0.30)',\n 'status-warning-strong': 'rgba(249, 180, 21, 0.50)',\n\n 'status-info': ramp.blue[500],\n 'status-info-light': ramp.blue[300],\n 'status-info-dark': ramp.blue[600],\n 'status-info-subtle': 'rgba(120, 194, 255, 0.12)',\n 'status-info-muted': 'rgba(33, 150, 243, 0.30)',\n 'status-info-strong': 'rgba(33, 150, 243, 0.50)',\n\n // Text on status backgrounds\n 'on-status-success': p.white,\n 'on-status-error': p.white,\n 'on-status-warning': p.white,\n 'on-status-info': p.white,\n\n // Text ON a `-subtle` fill — see the on-brand-*-subtle note above. Error is the\n // second deliberate exception to the rung-300 rule (operator, AW-133): red[300]\n // levelled perfectly but read PINK, because a red that light can only hold 0.121\n // chroma. red[400] carries 0.165 and reads red; its fill is thinned to compensate.\n 'on-status-success-subtle': ramp.green[300],\n 'on-status-error-subtle': ramp.red[400],\n 'on-status-warning-subtle': ramp.amber[300],\n 'on-status-info-subtle': ramp.blue[300],\n\n // Result/outcome indicators (result-*)\n 'result-improve': resultPaletteColors.improve,\n 'result-improve-light': 'rgba(76, 175, 80, 0.16)',\n 'result-improve-dark': resultPaletteColors.improveDark,\n 'result-degrade': resultPaletteColors.degrade,\n 'result-degrade-light': 'rgba(239, 83, 80, 0.16)',\n 'result-degrade-dark': resultPaletteColors.degradeDark,\n 'result-inconclusive': resultPaletteColors.inconclusive,\n 'result-inconclusive-light': 'rgba(158, 154, 151, 0.16)',\n 'result-neutral': greyRamp[400],\n\n // Text on result backgrounds\n 'on-result-improve': p.white,\n 'on-result-degrade': p.white,\n 'on-result-inconclusive': p.white,\n\n // Data visualization colors (same in dark mode for consistency)\n 'data-1': discreteRainbow[9],\n 'data-2': discreteRainbow[14],\n 'data-3': discreteRainbow[17],\n 'data-4': discreteRainbow[25],\n 'data-5': discreteRainbow[8],\n 'data-6': discreteRainbow[20],\n 'data-7': discreteRainbow[13],\n 'data-8': discreteRainbow[15],\n 'data-9': discreteRainbow[3],\n 'data-10': discreteRainbow[22],\n\n // Text colors - inverted for dark mode\n 'text-primary': greyRamp[50],\n 'text-secondary': greyRamp[400],\n // Deliberately ONE step lighter than the L*-nearest match (`greyRamp[600]`).\n // The colour this replaced failed WCAG large-text outright on the three\n // lightest planes — 2.96 / 2.72 / 2.49 against elevated / raised / overlay —\n // and `600` carried that failure forward almost exactly (2.93 / 2.70 / 2.47).\n // `500` clears 3:1 everywhere (3.32–5.34). Contrast beats colour fidelity for\n // text roles; borders and surfaces still use strict L*-nearest. See\n // semantic-contrast.test.ts, which fails if this is moved back down.\n 'text-tertiary': greyRamp[500],\n 'text-disabled': 'rgba(255, 255, 255, 0.38)',\n 'text-inverse': greyRamp[950],\n 'text-link': semanticPins.focusIndigoDark,\n 'text-link-hover': ramp.blue[400],\n\n // Surface colors - dark backgrounds — warm-tapered DERIVED ramp (TD-surface-tokens,\n // S-1, re-spaced S-3). Shipped verbatim from `deriveSurfaceRamp()` — see\n // `surfaceRampDark` in primitives.ts for the full derivation note. `surface-overlay`\n // and `surface-elevated` are distinct (were both #191919 pre-S-1); `surface-input`\n // tracks one plane above `surface-base`, same relative position as before the remap.\n // `background-base` backs `Surface level=\"background\"` (SurfaceContext.SURFACE_LEVEL_TOKEN),\n // so it takes the ramp's shell role. The deepest plane is `background-frame`,\n // which is also the `SurfaceLevel` floor a pressed surface clamps at.\n 'surface-base': greyRamp[925], // main surface (#252321, L*13.9)\n 'surface-elevated': greyRamp[900], // elevated surface (#2C2A28, L*17.2 — nav/rail)\n 'surface-raised': greyRamp[875], // raised surface (#31302F, L*19.9 — cards)\n 'surface-overlay': greyRamp[850], // overlay surface (#373635, L*22.7 — hero/popover)\n 'surface-input': greyRamp[900], // input surface (#2C2A28 — one plane above base)\n\n // Background colors — same ramp, the frame/shell end of it.\n 'background-base': greyRamp[950], // shell (#1C1916, L*9 — Surface level=\"background\")\n 'background-default': greyRamp[925], // main background (#252321, L*13.9 — matches surface-base)\n 'background-subtle': greyRamp[900], // subtle background (#2C2A28, L*17.2 — matches surface-elevated)\n // Frame/bezel chrome — the top bar + side nav shell, one step BELOW\n // `background-base`. It used to be described as sitting OUTSIDE the ramp; it\n // is simply the ramp's last step now, and the floor `<Surface pressed>` clamps at.\n 'background-frame': greyRamp[975], // frame / bezel (#100D0A, L*3.8)\n\n // Border colors — solid dark borders are RETIRED (TD-07.14). Not a preference — a structural\n // consequence of one ramp. Every step from 850 to 975 is now a surface plane,\n // so a solid border dark enough to read as a border necessarily equals some\n // plane's fill, which is exactly the collision `surface.contract.test.ts` R2\n // forbids. The only non-plane steps left in that band are 800 and 700, and\n // borders there jump from L*~10-25 to L*~28-38 — a restyle, not a migration.\n //\n // So separation moves to the alpha hairlines, which dark mode already called\n // \"the primary separation cue\". Being alpha, they composite against whatever\n // plane they land on and cannot collide with any of them — the problem stops\n // existing rather than being re-solved per plane. The three solid tokens were\n // deleted outright; consumers point at the `hairline-*` family below.\n //\n // `border-prominent` stays SOLID: it is the one border meant to be seen\n // outright (4 call sites, high-visibility dividers), and grey-800 is not a\n // plane, so it keeps its job without collision.\n 'border-prominent': greyRamp[800], // high-visibility divider\n 'border-focus': semanticPins.focusIndigoDark,\n 'border-input': greyRamp[700],\n 'border-input-hover': greyRamp[600],\n 'border-input-focus': semanticPins.focusIndigoDark,\n 'border-input-error': ramp.red[500],\n\n // Alpha hairline separators — the primary separation cue (§4/S-2). Self-\n // normalizing: composites toward white by ~the same amount on ANY plane, so\n // one family works at every elevation instead of per-surface border tokens.\n // Shadows are demoted to floating-overlay use only (not shipped as a fill\n // separator here — see elevation.ts, follow-up S-4).\n //\n // RETUNED on the wall (VW-99, S-6). The original .06/.09/.14 were set at a\n // desk. On the panel at ~3 m `subtle` rendered but was indiscernible, and\n // `default` — the load-bearing one, with no solid-border fallback since\n // TD-07.14 — went weak on the lightest plane. `strong` read cleanly with room\n // to spare, which is what made raising the whole family viable.\n //\n // Each tier steps up onto the next MEASURED-GOOD rung rather than an\n // interpolated one: the new `subtle` is the old `default`, and the new\n // `default` is the old `strong` — a value just confirmed legible on all four\n // planes. Spacing goes 1 : 1.56 : 2.33, against the original 1 : 1.5 : 2.33.\n //\n // RUN 2 (VW-99): all three tiers were seen on all four planes — the retune\n // worked — but `subtle` was still \"a bit hard to read\", so the whole family\n // took a further +.01. That is a comfort margin on a passing row, not a fix\n // for a failing one, which is why it is a flat offset: the 1 : 1.56 : 2.33\n // spacing that the run validated is preserved rather than re-derived.\n //\n // Keep these to TWO decimals. react-native-web quantises alpha to 8 bits, so\n // a 3-decimal value silently rounds on the way to the DOM (.135 renders as\n // .13) — the token would say one thing and paint another.\n //\n // DARK ONLY. The light family above composites toward BLACK on light planes,\n // which this run says nothing about — do not mirror these numbers into it\n // without its own verification.\n 'hairline-subtle': 'rgba(255, 255, 255, 0.10)',\n 'hairline-default': 'rgba(255, 255, 255, 0.15)',\n 'hairline-strong': 'rgba(255, 255, 255, 0.22)',\n\n // Interactive states\n 'interactive-hover': 'rgba(255, 255, 255, 0.04)',\n 'interactive-focus': 'rgba(255, 255, 255, 0.12)',\n 'interactive-active': 'rgba(255, 255, 255, 0.16)',\n 'interactive-selected': 'rgba(255, 255, 255, 0.08)',\n 'interactive-disabled': 'rgba(255, 255, 255, 0.12)',\n 'interactive-disabled-text': 'rgba(255, 255, 255, 0.26)',\n\n // Divider\n divider: 'rgba(255, 255, 255, 0.09)',\n\n // Avatar default\n 'avatar-background': greyRamp[700],\n 'avatar-text': p.white,\n} as const\n\n// Typography tokens matching existing app\nexport const semanticTypography = {\n // Headings (Space Grotesk)\n h1: {\n fontFamily: 'heading',\n fontSize: '3.5rem',\n fontWeight: 700,\n lineHeight: 1.375,\n },\n h2: {\n fontFamily: 'heading',\n fontSize: '3rem',\n fontWeight: 700,\n lineHeight: 1.375,\n },\n h3: {\n fontFamily: 'heading',\n fontSize: '2.25rem',\n fontWeight: 700,\n lineHeight: 1.375,\n },\n h4: {\n fontFamily: 'heading',\n fontSize: '2rem',\n fontWeight: 700,\n lineHeight: 1.375,\n },\n h5: {\n fontFamily: 'heading',\n fontSize: '1.5rem',\n fontWeight: 600,\n lineHeight: 1.375,\n },\n h6: {\n fontFamily: 'heading',\n fontSize: '1.125rem',\n fontWeight: 600,\n lineHeight: 1.375,\n },\n\n // Body text (Nunito Sans)\n body1: {\n fontFamily: 'body',\n fontSize: '1rem',\n fontWeight: 400,\n lineHeight: 1.5,\n },\n body2: {\n fontFamily: 'body',\n fontSize: '0.875rem',\n fontWeight: 400,\n lineHeight: 1.57,\n },\n subtitle1: {\n fontFamily: 'body',\n fontSize: '1rem',\n fontWeight: 500,\n lineHeight: 1.75,\n },\n subtitle2: {\n fontFamily: 'body',\n fontSize: '0.875rem',\n fontWeight: 500,\n lineHeight: 1.57,\n },\n caption: {\n fontFamily: 'body',\n fontSize: '0.75rem',\n fontWeight: 400,\n lineHeight: 1.66,\n },\n overline: {\n fontFamily: 'body',\n fontSize: '0.75rem',\n fontWeight: 600,\n lineHeight: 2.5,\n letterSpacing: '0.5px',\n textTransform: 'uppercase' as const,\n },\n button: {\n fontFamily: 'sans',\n fontSize: '0.875rem',\n fontWeight: 600,\n lineHeight: 1.75,\n },\n} as const\n\n// Button size tokens\nexport const buttonSizes = {\n sm: {\n paddingX: '16px',\n paddingY: '6px',\n fontSize: '0.875rem',\n },\n md: {\n paddingX: '20px',\n paddingY: '8px',\n fontSize: '0.875rem',\n },\n lg: {\n paddingX: '24px',\n paddingY: '11px',\n fontSize: '1rem',\n },\n} as const\n\n// Export type for theme mode\nexport type ThemeMode = 'light' | 'dark'\n\n// Helper to get semantic colors based on mode\nexport function getSemanticColors(mode: ThemeMode) {\n return mode === 'dark' ? semanticColorsDark : semanticColorsLight\n}\n"]}
@@ -0,0 +1,51 @@
1
+ # Addenda to the 2026-09-08 library critique
2
+
3
+ Two read-only follow-on audits (research briefs D1 and D2), condensed from the
4
+ agents' reports. Reviewed on `main` at 4267d69.
5
+
6
+ ## D1 · External consumers of `@titan-design/react-ui`
7
+
8
+ Seven downstream checkouts, all consuming by package name (zero relative
9
+ imports into `packages/ui`):
10
+
11
+ | Checkout | Pin | Shape |
12
+ |---|---|---|
13
+ | audiobook/frontend | `file:../../titan-design/packages/ui` | source link, tracks HEAD |
14
+ | agent-chat | ^0.12.1 | tokens only (`/theme/tokens`); keeps local Pill/Badge/Section/Card |
15
+ | voltras-mcp | ^0.12.0 | heaviest component consumer |
16
+ | voltras-mcp-wave0 | ^0.9.3 | stale fork of voltras-mcp |
17
+ | voltras/mobile | ^0.6.0 | `getSemanticColors`/`alpha` + Card/Metric/Section |
18
+ | codewatch, codewatch-wt-c76 | ^0.2.7 | very old pin, worktree dupe |
19
+
20
+ Externally used: Pill, Badge, Chip, StatusPill (+ `StatusPillStatus` type),
21
+ PrBadge, MuscleGroupChip, Metric (heavy), MetricTiles (one site, plus the
22
+ `MetricTileData` type), Section, SectionHeader.
23
+
24
+ Externally dead: BaseBadge, WorkoutPill, SessionStatePill, WeightBadge,
25
+ SeverityLabel, CoChangeChip, HelpTip, LabelWithHelp, MetricCell, Tile,
26
+ Indicator, StatusDot.
27
+
28
+ Caveat: five of seven pin old versions, so "no consumer" for a recent export
29
+ can mean "nobody upgraded". Only audiobook, voltras-mcp and agent-chat see
30
+ current exports.
31
+
32
+ ## D2 · Workout per-file drift ranking
33
+
34
+ Drift = `getSemanticColors` + `fontSize:` + raw hex + `rgba(` + raw `<Text` +
35
+ `greyRamp[` + `ramp.` + `boxShadow` + `backgroundColor:` per file, across 54
36
+ non-test, non-story files.
37
+
38
+ Highest: MesoStatusCard 40, setHeadingKit 34 (utility, not exported),
39
+ StatusDot 31, TempoDisplay 29, BodyMapDetailPanel 28, StrengthTrendChart 26.
40
+ Clean (0): ExerciseCardHeading, FatigueMeter, icons, metricText, MetricTiles,
41
+ SetStrip.
42
+
43
+ Render-path theme bug: only `WeightBadge.tsx` calls `getSemanticColors('dark')`
44
+ inside the component body (lines 46, 105-106). The other 37 files hoist it to
45
+ module scope: the same dark-only limitation, less acute.
46
+
47
+ Pattern to copy: `BodyMap.tsx` (three correct `resolveColor()` calls; one
48
+ leftover module-scope constant, `BRAND_PRIMARY`).
49
+
50
+ Zero of 168 Workout files use `Typography`. Port batches B1-B5 are in
51
+ `docs/library-roadmap.md` E3.
@@ -0,0 +1,212 @@
1
+ # titan-design `packages/ui` — deep critique and fix roadmap
2
+
3
+ Reviewed on `main` at 4267d69, 2026-09-08. Read-only. Gates on main: `tsc` 0 errors, prettier clean, eslint 0 errors / 81 warnings, targeted depth tests 115/115 pass.
4
+ Scope: 191 story files, 170 test files (~2,196 `it()`), 143 shipped component files (38 `ui/` dirs, 96 `custom/` files, 9 `shell/`).
5
+
6
+ ---
7
+
8
+ ## A. Executive findings (ranked by impact on cohesive application of the fundamentals)
9
+
10
+ **1. The foundations are sound, but only ~3 families consume them; Workout (the largest family, 54 components) is frozen to the pre-ramp era.**
11
+ Workout carries 39 files with module-scope `const t = getSemanticColors('dark')` (55 such constants repo-wide, 71 call sites in components), 149 literal `fontSize:` values, 81 `rgba(` literals, 34 raw hex, 31 files setting `backgroundColor:` inline, 16 inline `boxShadow`, 12 files indexing `greyRamp[...]` directly, 19 raw `<Text>` and zero `Typography`. It is the family with the highest drift and the highest consumer count. Only ActiveWork, Prose and charts are held to the token-pure lint (`eslint.config.js:215-219`); Workout is exempt from every rule except the ratchet.
12
+
13
+ **2. `Card` is not on the surface system at all.** It reads theme from a DOM class observer (`utils/useTheme.ts`, its only consumer is `Card.tsx:96,373`), never touches `SurfaceContext`, derives its fill from the deleted-tomorrow `lighten()` ladder, and writes `backgroundColor` into `style` (`Card.tsx:190`) so a caller's `bg-*` class is discarded. `filled` and `elevated` are byte-identical (`Card.tsx:46-52`), `outline`/`accent`/`subtle` silently clamp to level 1 or 0 (`Card.tsx:102-104,117-119`), and light mode is a hard-coded `#FAFAFA` (`Card.tsx:115`). 13 shipped files import it. No test covers the className override (`Card.test.tsx` asserts variants render, not what they render).
14
+
15
+ **3. Four container primitives compete and none is the default.** `Card` (13 consumers), `Surface` (3 shipped: DashboardShell, SessionHeader, SessionRail), `Tile` (3, hand-rolls `bg-surface-raised` + 10px uppercase label), `Section` (0). ActiveWork lists set `bg-surface-raised` on plain `View`s for selection (`SessionListItem.tsx:138`, `FileActivityRow.tsx:96`) because no primitive expresses "one plane up". The north-star §5b asked for exactly one un-misconfigurable `<Card>`; the repo has four ways and 58 loose `bg-surface-*` classes across 25 families.
16
+
17
+ **4. Twelve pill-shaped components.** `Pill`, `Badge`, `Chip`, `BaseBadge`, `StatusPill`, `WorkoutPill`, `SessionStatePill`, `WeightBadge`, `PrBadge`, `MuscleGroupChip`, `SeverityLabel`, `CoChangeChip`. In-repo consumers: Pill 6, Badge 2, SeverityLabel 2, the rest 0-1. `Chip.tsx:38-41` styles with `bg-neutral-600`/`text-neutral-700` (Tailwind's default cool grey, since the config is in `extend` mode) plus `text-white` ×7; `WorkoutPill.tsx` carries 10 `rgba(` literals. Five Workout badges are titled under `Components/Atoms/*` while the family's other 49 stories sit under `Workout/*`.
18
+
19
+ **5. Storybook has no single tree.** Nine top-level groups (Components 487 entries, Workout 326, Lab 125, Custom 54, Foundations 40, ActiveWork 30, Shell 27, Pages 16, Docs 1). ActiveWork alone is split four ways (`ActiveWork/*` 7, `Custom/ActiveWork/*` 11, `Components/Molecules/Eyebrow`, `Lab/ActiveWork/*` 6 stale duplicates of the hardened readers). Eight `Lab/`-titled story files live in shipped dirs (`Workout/S3*.stories.tsx` ×5, `ExerciseCardUnified`, `RowInventory`, `shell/SessionRailSpecimen`) and therefore publish to npm, because `package.json` `files` only excludes `src/lab`. Three titles use `·`, which `gotchas.md #8` says mangles story ids. 833 story exports across ~140 component story files (Input 15, Card 14, Alert 14) against the skill's "one Default args story + controls".
20
+
21
+ **6. Every governance signal is inert or stale.** Zero of 191 story files carry a `status:` tag; all 1,106 Storybook entries read `status:review`, so the sidebar filter MATURITY.md is built around slices nothing. `arch-graph.json` was last regenerated 2026-07-09 (91 components; now ~143), omits the entire ActiveWork family, `Tile`, `SetBarChart`, `SparkBars`, `LiveFatigueCard`, `MarkdownProse`, and its `dead` list names `Pill` (6 consumers today), `Tooltip` (8), `Modal`, `Collapse`, `SideNav`, `TopBar`. The workflow skill's Gate 1 requires a current graph. `REJECTED.md` has 3 entries; the Storybook has 10 archived directions with none.
22
+
23
+ **7. Colour math is copied, not shared.** `hexToRgb` ×4 (`theme/color-utils.ts:27`, `Fatigue/fatigue-tokens.ts:133`, `lab/north-star/fatigue-lab-shared.tsx:262`, `lab/archive/GrindingLine…:205`), `mixHex` ×4, `perceivedLuminance` ×3 (`materials.ts:87`, `lab/north-star/surfaces.ts:15`, `DualGhostLine…:45`), `lstar` ×3 (all in tests/lab, none exported from theme though the north-star makes ΔL\* the sanctioned metric), `parseHex` (`materials.ts:69`) beside `hexToRgb`. `lab/north-star/surfaces.ts` is a verbatim fork of `materials.ts` (`paperSheet`/`insetWell`/`grainForTone`) and `DualGhostLine` has a third copy.
24
+
25
+ **8. `ui/*` atoms cannot use `Typography` because it lives in `custom/`.** 81 raw `<Text>` in `ui/*`, 0 `Typography`; `CardTitle`, `SectionHeader` (`Section.tsx:29`), `Menu.tsx:210`, `Tile` all hand-roll heading/eyebrow styles. `Eyebrow` exists but only ActiveWork uses it. The tier order (ui → custom) forbids the fix the skill prescribes.
26
+
27
+ **9. 185 functions exceed 30 lines (29 exceed 100).** Workout 78, ui 31. Top: `BodyMapDetailPanel` 371, `StrengthTrendChart` 368, `CapacityBandChart` 328, `VelocityStrip` 313 (file is 1,468 lines), `Autocomplete` 204, `Tooltip` 161, `Card` 136, `calculateElevationShadow` 91. Two story-only kits ship as components: `Workout/velocity-story-kit.tsx` (438 lines) and `Workout/setHeadingKit.tsx` (364 lines, raw HTML `<div>`, 15 hex literals, no tests, no stories).
28
+
29
+ **10. Tests pin implementation and skip a11y where the rules say they must not.** 16 component test files have no `axe` (all four shell sub-parts, six Fatigue, five Workout pages, TimerReadout) despite CLAUDE.md's "every component test file must include an accessibility test". 43 assertions compare to literal hex (`Surface.test.tsx:79,97-100,139-140` pins `#2C2A28`/`#31302F`, so the depth change breaks them by design, not by behaviour). Comments describe deleted code: `SessionRail.stories.tsx:40` cites `neumorphicShadows`, `utils/colors.ts:4` cites `shadows.ts`, `SurfaceContext.ts:19-20` lists pre-re-space hexes, `Surface.tsx:27-35,63,90` documents the lighten model, `elevation.ts:19` says light from upper-right while the offsets are top-left.
30
+
31
+ ---
32
+
33
+ ## B. Competing systems and operator questions
34
+
35
+ | # | Pair | What each does / who uses it | Question for the operator |
36
+ |---|---|---|---|
37
+ | 1 | `Card` vs `Surface` vs `Tile` vs `Section` | Card: lighten ladder + 5 variants, 13 consumers. Surface: named planes + on-surface context, 3 shipped. Tile: bare View + `bg-surface-raised`, 3. Section: 0. | Is `Card` the only content container app code may use (Surface reserved for shell roots; Tile becomes a Card preset; Section deleted)? |
38
+ | 2 | numeric `elevation` vs named `level` | `elevation=` 15 uses (Card + Surface stories); `level=` 31 uses. Both public. | After the depth fix, does the public API expose only named planes plus a relative "one up", with numeric elevation internal? |
39
+ | 3 | 12 pill/badge/chip components | Pill 6 consumers, Badge 2, SeverityLabel 2, others 0-1. Three token-impure. | One `Pill` primitive (tone/size/icon/dot slots) with domain pills as thin wrappers, or keep domain pills as separate components? |
40
+ | 4 | `Divider` vs hairline border classes | Divider 5 consumers; 21 hand-rolled `h-px`/`border-t border-hairline` rules in 9 families; 56 `border-hairline*` uses. | Is every rule a `Divider`, with `border-hairline` reserved for the opt-in `outline` edge? |
41
+ | 5 | `Tooltip` vs `HelpTip` vs `Popover` | Tooltip 8 consumers, HelpTip 0 (+ `LabelWithHelp`), Popover 1. HelpTip is a Tooltip preset. | Delete HelpTip, or keep it as a documented Tooltip preset? |
42
+ | 6 | `useTheme` (DOM observer) vs `SurfaceContext`/`ThemeProvider` | useTheme: Card only. Context: Surface, Typography-adjacent, charts. | Is the Surface/ThemeProvider context the single theme source, so `utils/useTheme.ts` is deleted? |
43
+ | 7 | `getSemanticColors('dark')` constants vs `resolveColor` vs `className` tokens | 55 module constants (Workout 39, Fatigue 9); resolveColor in 14 files. TOKENS.md calls it a "known migration". | Are Workout and Fatigue dark-only by design (document and exempt) or must they be theme-correct (migrate 55 files)? |
44
+ | 8 | colour math ×5 modules | `theme/color-utils` (HSV), `utils/colors` (`alpha`, 137 call sites), `materials` (`parseHex`, Rec.601 luminance), `fatigue-tokens` (`mixHex`), `SetBarChart` (`mixHex`), 3 lab forks, 3 test `lstar`. | One `theme/color-math` module with CIELAB L\* as the sanctioned metric, everything else re-exported or deleted? |
45
+ | 9 | `Typography` (custom) vs raw `<Text>` in `ui/*` | 81 raw Text in ui, 0 Typography. Tier order forbids the import. | Move `Typography` (and `Eyebrow`) into `ui/` so atoms compose it, or exempt `ui/*` from the Typography rule? |
46
+ | 10 | `Indicator` vs `StatusDot` | 6 vs 5 consumers. Skill 03 says "standardize on Indicator"; `Fatigue/README.md:41` says fatigue lights are `StatusDot`. Contradiction is live. | Which dot survives? |
47
+ | 11 | `Metric` vs `MetricCell` vs `MetricTiles`+`Tile` vs Gauge value | Four label-over-value lockups; Metric 3 consumers, MetricCell 3, MetricTiles 1. | One stat primitive with `size`/`align`/`trend`, or keep Workout's `MetricCell` separate? |
48
+ | 12 | `materials.ts` vs `lab/north-star/surfaces.ts` fork vs elevation shadows | materials: 4 shipped call sites. Fork: lab only. Depth decision 2 makes paperSheet's rim the default. | Is `paperSheet` still hero-only (materials header) once every lifted plane carries the rim, or does it collapse into the depth recipe? |
49
+ | 13 | Formatters | `utils/number-format` (2), `utils/workout-format` (7), `ActiveWork/format-time` (2), `DateTime.formatDateTime`, 8 local `formatX` in components, 14 `toFixed`. | One `utils/format` module per domain (number / time / workout), with components forbidden from local formatters? |
50
+ | 14 | Storybook groups ×9 | Components/Atoms\|Molecules\|Organisms\|DataViz\|Charts, Custom/, Workout/, ActiveWork/, Pages/, Docs/, Shell/, Foundations/, Lab/. | Approve the target tree in §C-E4, or name a different top level for domain families? |
51
+ | 15 | Lint mechanisms ×3 | `titan/no-raw-color` ratchet (baseline JSON, 0 errors), family-scoped `no-restricted-syntax` errors (3 families), shell/icons warn. | One mechanism: extend the per-family error block to every family and retire the baseline, or keep the ratchet and delete the scoped blocks? |
52
+ | 16 | Light mode | `semantic.ts` defines a full light map; Workout has 1 file that mentions light; Card hard-codes light hex. | Is light mode a supported target for every family, or only for `ui/*` + Foundations? |
53
+
54
+ ---
55
+
56
+ ## C. Epics and task lists
57
+
58
+ Sizes: S ≤ half a day, M ≤ 2 days, L > 2 days. "Depends" refers to epic.task ids or operator questions Q#.
59
+
60
+ ### E1. Depth correction (in flight, aw-depth) — blast-radius inventory
61
+
62
+ Everything below is what the four depth decisions touch. Nothing in E2-E6 may edit these files until E1 lands.
63
+
64
+ **Consumers by family (shipped source, excluding tests/stories):**
65
+
66
+ | Family | `<Card>` | `<Surface>` | `bg-surface-*` | inline `boxShadow` | tailwind `shadow-*` | materials |
67
+ |---|---|---|---|---|---|---|
68
+ | ActiveWork | 6 files (CoChangeChip filled; FileActivityDetail subtle; FileHistoryExplorer subtle; InitiativeCard accent/outline; PortfolioOverview filled; SessionDetail outline) | 0 | 2 (SessionListItem:138, FileActivityRow:96) | 0 | 0 | `insetWell()` FileActivityDetail:124 |
69
+ | Workout | 4 (MesoCard outline e2 + borderColor + style boxShadow:191; MesoStatusCard outline e1 + borderColor; ReadinessCheck outline e2; WorkoutCard accent e1 + bgColor) | 2 (SessionHeader level=background; SessionRail level=elevated + `insetWell(surface-base)`:137) | 14 files | 16 lines (StatusDot:55-61 ×7 glows; DeviationBar:75; MesoStatusCard:275; BodyMapDetailPanel:337; BodyMap:200; ZoneTrack:241; IntensityBar:181; PrHistoryModal:84; setHeadingKit:308) | 0 | SessionRail |
70
+ | Fatigue | 0 | 0 | 0 | 0 | 0 | `barPaper` LiveFatigueCard:58 |
71
+ | charts | 0 | 0 (uses `useSurface`) | 0 | 0 | 0 | `barPaper` SetBarChart:494 |
72
+ | shell | 0 | 1 (DashboardShell:67 level=base) | 2 | 0 | 0 | 0 |
73
+ | ui/* floating overlays | — | — | 14 files | Indicator:92 glow; ToolbarButton:264 | 13 files: autocomplete, drawer, help-tip, indicator (5 arbitrary glow shadows), menu, modal, popover, select, switch, tabs, toast, toolbar-button, tooltip (`shadow-lg` ×9, `-sm` ×2, `-xl`, `-2xl`) | 0 |
74
+ | theme stories | — | 4 | 1 | 10 | 0 | Depth.stories:130-141, DepthCalibration:396-588 (+ local `Card` at :480) |
75
+ | lab | 21 story uses of Card | 0 | 2 | 12 | 0 | 17 call sites + 2 forks |
76
+
77
+ Prop-form totals across all files: `variant=` outline 19 / filled 16 / subtle 5 / accent 2 / elevated 1; Card `elevation=` {1}×2 {2}×6 {3}×3; `CardInset` −1×3 −2×3 (stories/tests only); Surface `level=` background 14 / base 9 / raised 5 / elevated 3; `elevation={2}` ×5, `{3}` ×1; `pressed` ×23. Elevation helpers (`getElevationSurface/Shadow`, `getBaseSurfaceColor`, `getValidatedElevation`, `getPressedRecessShadow`, `getGlowShadow`) are called only from `Card.tsx` and `Surface.tsx`; the blast radius of deleting `lighten()` is contained to those two files plus `elevation.test.ts` and `Depth*.stories.tsx`.
78
+
79
+ Tasks (for aw-depth's plan, not a redesign):
80
+ - **E1.1** Card reads `useSurface()` and resolves parent+1; delete `utils/useTheme.ts`. Files: `Card.tsx`, `utils/useTheme.ts`, `utils/index.ts`. S. Done when: no `useTheme` import remains and `Card` inside `<Surface level="base">` renders `surface-elevated`.
81
+ - **E1.2** Fix className/style precedence bug + regression test. Files: `Card.tsx:187-205`, `Card.test.tsx`. S. Done when: `<Card className="bg-surface-raised">` computed background is greyRamp[875] in jsdom.
82
+ - **E1.3** Collapse variants: `filled` = `elevated`; `outline` becomes opt-in edge, not a level clamp. `Card.tsx:46-52,102-104`. Depends Q1. S.
83
+ - **E1.4** Floating overlays (13 ui files) move from `shadow-lg` + `border-hairline` to the level-4/5 recipe. M. Done when: `grep -rE "shadow-(sm|md|lg|xl|2xl)" src/components/ui` = 0.
84
+ - **E1.5** Replace hex pins in `Surface.test.tsx`, `surface.contract.test.ts`, `elevation.test.ts` with `greyRamp[...]` references. S.
85
+ - **E1.6** Purge stale comments: `Surface.tsx:27-35,63,90`, `SurfaceContext.ts:19-20`, `SessionRail.stories.tsx:40`, `utils/colors.ts:4`, `elevation.ts:19`, `gotchas.md` "Neumorphic depth" section, `SessionRail.tsx:16-17`. S.
86
+ - **E1.7** Delete `lab/north-star/surfaces.ts` fork and `DualGhostLine` local copies; point lab at `theme/materials`. S.
87
+ - **E1.8** Decide glow shadows (StatusDot ×7, Indicator, MesoCard, BodyMap, ZoneTrack, IntensityBar, PrHistoryModal): they are emphasis, not depth. Route through `getGlowShadow` or leave. Depends on aw-depth. S.
88
+ - **E1.9** Rewrite `Foundations/Depth` and `Depth Calibration` to the new model; delete DepthCalibration's local `Card`. M.
89
+
90
+ ### E2. One container, one pill, one dot (depends E1; Q1, Q3, Q4, Q5, Q10, Q11)
91
+ - **E2.1** `Card` becomes the sole content container: fold `Tile` into a `Card` stat preset, delete `Section`/`SectionHeader` (0 consumers) or make `SectionHeader` compose `Eyebrow`. M.
92
+ - **E2.2** Replace loose `bg-surface-*` on `View`s with the container (58 sites, 25 families; start ActiveWork 2, shell 2, ui 14). L.
93
+ - **E2.3** `Pill` gains `tone`/`size`/`leading` slots; `Badge`, `Chip`, `BaseBadge`, `StatusPill`, `WorkoutPill`, `WeightBadge`, `PrBadge`, `MuscleGroupChip`, `SeverityLabel`, `SessionStatePill`, `CoChangeChip` become wrappers or are deleted per Q3. L. Done when: `Chip.tsx` has no `neutral-*`/`text-white`, and each survivor's story is titled under the same parent.
94
+ - **E2.4** `Divider` everywhere: replace 21 hand-rolled rules. S.
95
+ - **E2.5** `Indicator` vs `StatusDot`: migrate the loser's 5-6 consumers; fix `Fatigue/README.md:41`. M.
96
+ - **E2.6** `HelpTip` → Tooltip preset or delete. S.
97
+ - **E2.7** Stat lockup: `Metric` absorbs `MetricCell` + `MetricTiles`. M.
98
+
99
+ ### E3. Port Workout and Fatigue onto the foundations (depends E1; Q7, Q8, Q9, Q15, Q16)
100
+ - **E3.1** Move `Typography` + `Eyebrow` to `ui/`; leave re-export shims in `custom/`. S.
101
+ - **E3.2** `theme/color-math.ts`: single `hexToRgb`, `mixHex`, `alpha`, `lstar`, `deltaL`; delete 4 duplicate `hexToRgb`, 4 `mixHex`, 3 `perceivedLuminance`, 3 test `lstar`. M.
102
+ - **E3.3** Workout: replace 39 module-scope `getSemanticColors('dark')` with `resolveColor`/`useOnSurfaceColor` (or document dark-only per Q7). L.
103
+ - **E3.4** Workout: 149 literal `fontSize:` → `Typography` variants; 19 raw `<Text>`. L. Files ranked by count: ReadinessCheck 7, TempoDisplay 10, ExerciseCard 5, VelocityStrip 4.
104
+ - **E3.5** Fatigue: 9 module constants, 9 `fontSize:`, local `hexToRgb/mixHex`. M.
105
+ - **E3.6** `ui/*`: 81 raw `<Text>` → `Typography`; `Button` 6× `#ffffff` + `text-white`, `Alert` `bg-black`, `Tooltip` `bg-neutral-800`, `Spinner` hex. M.
106
+ - **E3.7** Lint: add every family to the token-pure error block (or per Q15 keep only the ratchet); delete `raw-color-baseline.json` when it reaches zero; update TOKENS.md §6 to list Prose and `no-raw-color`. S.
107
+ - **E3.8** Delete `Workout/velocity-story-kit.tsx` and `setHeadingKit.tsx` from `components/` (move to `src/lab/` or into the stories that use them). S.
108
+
109
+ ### E4. Storybook reorganisation (independent of E1; Q14)
110
+ Target tree:
111
+ ```
112
+ Foundations/{Color,Typography,Icons,Depth,Spacing,Choosing Tokens}
113
+ Components/Atoms|Molecules|Organisms/<Name> (ui/* only, one Default + controls)
114
+ Custom/<Family>/<Name> (ActiveWork, Workout, Fatigue, Charts, Prose, DataViz)
115
+ Shell/<Name>
116
+ Pages/<Name>
117
+ Lab/<Family>/<Name> (src/lab only; status:lab)
118
+ Docs/Architecture
119
+ ```
120
+ - **E4.1** Retitle: `ActiveWork/*` and `Components/Molecules/Eyebrow` → `Custom/ActiveWork/*`; `Workout/*` and the 5 Workout atoms under `Components/Atoms/*` → `Custom/Workout/*`; `Workout/Fatigue/*` → `Custom/Fatigue/*`; `Components/Charts|DataViz` → `Custom/Charts`. Fix `Composes` links. M.
121
+ - **E4.2** Move the 8 `Lab/`-titled files out of `components/` into `src/lab/` (or delete: `S3*` explorations are superseded by hardened SessionRail). S.
122
+ - **E4.3** Delete duplicates: `Lab/ActiveWork/*` (6), `Lab/Components/{Ghost Spark,Velocity Hero,Verdict Hero}` (3), `Lab/Archive/Surface` vs `Lab/North Star/1 · Surface System`. Record each in REJECTED.md. S.
123
+ - **E4.4** Rename `·` titles to ASCII; normalise spaces vs PascalCase within a family (`Initiative Reader` vs `InitiativeBrief`). S.
124
+ - **E4.5** Add `tags: ['autodocs']` to the 11 hardened ActiveWork stories and the 43 other files without it; add a `Composes` line to the 142 story files lacking one (ui/* first). M.
125
+ - **E4.6** Decorators compose `<Surface>`; today 0 do and ~30 hand-roll `backgroundColor`/`bg-*` (`SessionRail.stories.tsx:26-29` also uses `#6B7280`). M.
126
+ - **E4.7** Thin per-state stories to one `Default` + controls where the skill says so (Input 15, Card 14, Alert 14, Toast 13). M.
127
+
128
+ ### E5. Governance refresh (independent)
129
+ - **E5.1** Regenerate `arch-graph.json` via `scripts/arch-graph.mjs`; add a CI check that fails when the graph is older than the newest `index.ts`. S.
130
+ - **E5.2** REJECTED.md entries for: Fable Directions, Feature Explorations, Foundations (superseded), Screen Prototypes, Shell Specimens, Curves ×2, Grinding Line, Rep Breakdown, Hero Tempo, retired `inset` level, `tonalFill`/`ditherTile`, `data-1..10`. S.
131
+ - **E5.3** Apply `status:` tags: `status:lab` on every `src/lab` story, `status:candidate` on ported items, and run the MATURITY review session for `ui/*` (MATURITY says "~52 primitives"; there are 38). M. Depends E4.
132
+ - **E5.4** README per family for ui/*, ActiveWork (exists), Fatigue (exists, fix StatusDot line), charts, Prose. M.
133
+ - **E5.5** Update the skill: `gotchas.md` cites `neumorphicShadows`/`shadows.ts`/`charcoal`/`neutral-100` (none exist); `06-lint-guardrails.md` predates the ratchet. S.
134
+
135
+ ### E6. Code quality floor (independent)
136
+ - **E6.1** Split the 29 functions over 100 lines (start with the four charts >300 lines and `VelocityStrip.tsx` 1,468 lines). L.
137
+ - **E6.2** eslint warnings 81 → 0 (39 unused-vars, 37 explicit-any; `elevation.ts` 5, `useTheme.ts` 4). S.
138
+ - **E6.3** `axe` in the 16 test files lacking it. S.
139
+ - **E6.4** Dead-export decision after external-consumer check (brief D1): 40+ components with 0 in-repo consumers. Delete or mark `status:candidate`. M. Depends D1.
140
+ - **E6.5** Delete the 18 gitignored `tmp-*.mjs` in the package root. S.
141
+
142
+ Sequencing: E1 → (E2, E3) in parallel; E4, E5, E6 can start now on files E1 does not list. E5.3 waits for E4.1 so tags land on final titles.
143
+
144
+ ---
145
+
146
+ ## D. Follow-on research briefs (read-only explorer)
147
+
148
+ **D1. External consumers of the barrel.** Path: the voltras-mcp SPA and the mobile app checkouts (locate via `active-work paths`). For each name in `packages/ui/src/components/ui/index.ts` and `custom/index.ts`, count imports from `@titan-design/react-ui`. Output: table name → external files. Purpose: settle E6.4 and Q3/Q5/Q11 with real usage, since in-repo counts show 40+ zero-consumer exports.
149
+
150
+ **D2. Workout per-file token audit.** Path: `packages/ui/src/components/custom/Workout/*.tsx` (exclude tests/stories). For each file count: `getSemanticColors(`, `fontSize:`, `#[0-9a-f]{6}`, `rgba(`, `<Text`, `greyRamp[`, `primitiveRamps`, `boxShadow`, `backgroundColor:`, functions >30 lines. Rank; propose the port order for E3.3-E3.4 (smallest, most-consumed first).
151
+
152
+ **D3. Story duplicate and lab audit against the live index.** `curl localhost:6006/index.json`; group entries by component import path; list titles whose component is also rendered under another title; list every `Lab/` entry whose `importPath` is under `src/components`. Output: delete/move list for E4.2-E4.3.
153
+
154
+ **D4. Test quality sample.** For 20 test files chosen by highest `toHaveStyle(` count, classify each `it()` as behaviour / implementation / smoke. Count assertions on literal hex or pixel values that would break under a token re-space. Output: list for E1.5 beyond the three files already named.
155
+
156
+ **D5. Theme presets liveness.** Path: `src/theme/presets/*`, `src/stories/ThemePresets.stories.tsx`, `PresetShowcase.stories.tsx`. Does anything outside stories call `applyPreset`? Does `audiobook.ts` reference retired tokens? Output: keep / move to Lab / delete recommendation and a REJECTED.md draft.
157
+
158
+ **D6. Light-mode reality.** Render `Pages/*` and `Custom/Workout/*` docs pages with the Storybook theme toggle set to light (Playwright, do not restart the server). Screenshot 10; list components whose fills or text stay dark-frozen. Output: evidence for Q16.
159
+
160
+ ---
161
+
162
+ ## E. Evidence appendix (run from `packages/ui`; zsh needs `bash -c` or `noglob` for `--include`)
163
+
164
+ ```
165
+ # story titles → tree tally
166
+ grep -rnoE "^\s*title:\s*['\"][^'\"]+['\"]" src --include='*.stories.tsx' | perl -pe 's/^([^:]+):(\d+):\s*title:\s*[\x27"]([^\x27"]+)[\x27"]/$3\t$1:$2/' | sort
167
+ → 191 meta titles; top-level: Components 54 files, Workout 53, Lab 37, Custom 14, Shell 10, Foundations 9, ActiveWork 7, Pages 5, Docs 1
168
+ curl -s localhost:6006/index.json → 1106 entries (969 stories, 137 docs); all tagged status:review
169
+ grep -rlE "status:[a-z]+" src --include='*.stories.tsx' | wc -l → 0
170
+ grep -rLE "'autodocs'" src --include='*.stories.tsx' | wc -l → 54 ; grep -rlE "Composes" … → 49
171
+ grep -rnE "title: 'Lab/" src/components --include='*.stories.tsx' → 8 files
172
+
173
+ # depth inventory (SRC = *.ts/*.tsx minus tests/stories)
174
+ grep -rlE "<Card[ >]" src $SRC → ActiveWork 6 (+Card.tsx), Workout 4 ; imports of Card: 13 shipped files
175
+ grep -rhoE "<Card[^>]*variant=\"[a-z]+\"" src --include='*.tsx' → outline 19, filled 16, subtle 5, accent 2, elevated 1
176
+ grep -rhoE "bg-surface-[a-z]+" src $SRC | sort | uniq -c → elevated 28, raised 22, base 6, input 2 (58; 118 incl stories)
177
+ grep -rnE "boxShadow" src $SRC | grep -v ^src/theme → Workout 16, lab 12, ui 2
178
+ grep -rhoE "\bshadow-(sm|md|lg|xl|2xl|inner|\[[^]]*\])" src $SRC → 13 ui files
179
+ grep -rnE "paperSheet\(|insetWell\(|barPaper\(|grainForTone\(" src → 4 shipped call sites, 17 lab, 2 forks
180
+ grep -rnE "getElevationShadow|getElevationSurface|getBaseSurfaceColor|getValidatedElevation" src | grep -v ^src/theme → Card.tsx, Surface.tsx only
181
+ grep -rhoE "border(-[trblxy])?-hairline(-[a-z]+)?" src $SRC → default 38, strong 13, subtle 5
182
+
183
+ # drift
184
+ grep -rnE "^const [a-zA-Z_]+ = getSemanticColors\('dark'\)" src $SRC | wc -l → 55 (Workout 39, Fatigue 9)
185
+ grep -rE "getSemanticColors\(" src/components src/lab $SRC | wc -l → 71
186
+ grep -rnE "fontSize: [0-9]" src $SRC → Workout 149, lab/surface 56, lab/north-star 28, Fatigue 9
187
+ grep -rnoE "#[0-9a-fA-F]{6}\b" src $SRC | grep -v ^src/theme → lab/surface 63, Workout 34, ui 21
188
+ grep -rnoE "rgba\(" src $SRC | grep -v ^src/theme → Workout 81, lab/surface 31
189
+ raw <Text vs <Typography per dir → ui 81/0, Workout 19/0, ActiveWork 0/47, Table 9/0
190
+ grep -rnE "neutral" src/components/ui/chip/Chip.tsx → lines 38-41 ; tailwind.config.js:7 `extend:`
191
+ grep -rnE "^(export )?function (hexToRgb|mixHex|perceivedLuminance|lstar|parseHex)" src → 4/4/3/3/1 copies
192
+
193
+ # consumers (files in src/components + src/lab rendering <X, excluding own file)
194
+ Pill 6, Badge 2, Chip 0, BaseBadge 0, StatusPill 1, WorkoutPill 0, WeightBadge 0, PrBadge 1, MuscleGroupChip 0, SeverityLabel 2, CoChangeChip 1
195
+ Card 4 (+9 more via import), Surface 3, Tile 3, Section 0, Stack 0, HStack 2
196
+ Indicator 6, StatusDot 5, Tooltip 8, HelpTip 0, Popover 1, Divider 5, Eyebrow 8, Typography 22
197
+ Metric 3, MetricCell 3, MetricTiles 1
198
+
199
+ # code quality
200
+ TypeScript-AST scan (scratchpad longfn.mjs) → 185 functions >30 lines in 114 files; 29 >100
201
+ pnpm exec eslint src/ -f json → 0 errors, 81 warnings (no-unused-vars 39, no-explicit-any 37, no-restricted-syntax 4)
202
+ grep -rL "axe(" $(find src/components -name '*.test.tsx') | wc -l → 16 of 139
203
+ grep -rE "toHaveStyle\([^)]*#[0-9a-fA-F]" src --include='*.test.tsx' | wc -l → 43
204
+ grep -rnE "\b(TODO|FIXME|HACK)\b" src → 1 (a test name) ; commented-out code candidates → 0
205
+ ls tmp-*.mjs | wc -l → 18 (gitignored)
206
+
207
+ # governance
208
+ git log -1 --format='%cs %h' -- packages/ui/src/arch/arch-graph.json → 2026-07-09 bc3aeb4 ; components 91, edges 72, no timestamp field
209
+ node -e "…summary.dead" → Autocomplete, Avatar, Breadcrumbs, Chip, Collapse, HelpTip, IconBox, Link, Menu, Modal, Pill, ReadinessCheck, SideNav, Skeleton, Spinner, Stepper, Switch, Tabs, Toast, ToolbarButton, Tooltip, TopBar, Treemap
210
+ REJECTED.md → 3 entries, last 2026-07-27 ; MATURITY.md → 2026-09-03 ; TOKENS.md → 2026-08-29
211
+ gates: pnpm exec tsc --noEmit → 0 ; prettier --check → clean ; vitest (card, surface, elevation, materials, grey-ramp) → 115 passed
212
+ ```