fleetlens 0.4.0 → 0.6.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 (440) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/app-path-routes-manifest.json +16 -7
  3. package/app/apps/web/.next/build-manifest.json +7 -7
  4. package/app/apps/web/.next/prerender-manifest.json +3 -3
  5. package/app/apps/web/.next/required-server-files.json +2 -1
  6. package/app/apps/web/.next/routes-manifest.json +86 -24
  7. package/app/apps/web/.next/server/app/_global-error/page/build-manifest.json +4 -4
  8. package/app/apps/web/.next/server/app/_global-error/page.js +1 -1
  9. package/app/apps/web/.next/server/app/_global-error/page.js.nft.json +1 -1
  10. package/app/apps/web/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  11. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  12. package/app/apps/web/.next/server/app/_global-error.rsc +7 -7
  13. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +2 -2
  14. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
  15. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +3 -3
  16. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +3 -3
  17. package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  18. package/app/apps/web/.next/server/app/_not-found/page/build-manifest.json +4 -4
  19. package/app/apps/web/.next/server/app/_not-found/page.js +5 -4
  20. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  21. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  22. package/app/apps/web/.next/server/app/api/digest/day/[date]/route/app-paths-manifest.json +3 -0
  23. package/app/apps/web/.next/server/app/api/digest/day/[date]/route.js +9 -0
  24. package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/day/[date]}/route.js.nft.json +1 -1
  25. package/app/apps/web/.next/server/app/api/digest/day/[date]/route_client-reference-manifest.js +3 -0
  26. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route/app-paths-manifest.json +3 -0
  27. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js +9 -0
  28. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route.js.nft.json +1 -0
  29. package/app/apps/web/.next/server/app/api/digest/month/[yearMonth]/route_client-reference-manifest.js +3 -0
  30. package/app/apps/web/.next/server/app/api/digest/month-index/route/app-paths-manifest.json +3 -0
  31. package/app/apps/web/.next/server/app/api/digest/month-index/route.js +7 -0
  32. package/app/apps/web/.next/server/app/api/{insights/months-index → digest/month-index}/route.js.nft.json +1 -1
  33. package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route_client-reference-manifest.js +1 -1
  34. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route/app-paths-manifest.json +3 -0
  35. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js +9 -0
  36. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route.js.nft.json +1 -0
  37. package/app/apps/web/.next/server/app/api/digest/week/[startDate]/route_client-reference-manifest.js +3 -0
  38. package/app/apps/web/.next/server/app/api/digest/week-index/route/app-paths-manifest.json +3 -0
  39. package/app/apps/web/.next/server/app/api/digest/week-index/route.js +7 -0
  40. package/app/apps/web/.next/server/app/api/{insights/weeks-index → digest/week-index}/route.js.nft.json +1 -1
  41. package/app/apps/web/.next/server/app/api/digest/week-index/route_client-reference-manifest.js +3 -0
  42. package/app/apps/web/.next/server/app/api/jobs/route/app-paths-manifest.json +3 -0
  43. package/app/apps/web/.next/server/app/api/jobs/route.js +6 -0
  44. package/app/apps/web/.next/server/app/api/jobs/route.js.nft.json +1 -0
  45. package/app/apps/web/.next/server/app/api/jobs/route_client-reference-manifest.js +3 -0
  46. package/app/apps/web/.next/server/app/api/runs/[runId]/route/app-paths-manifest.json +3 -0
  47. package/app/apps/web/.next/server/app/api/runs/[runId]/route/build-manifest.json +9 -0
  48. package/app/apps/web/.next/server/app/api/runs/[runId]/route.js +6 -0
  49. package/app/apps/web/.next/server/app/api/{insights/saved → runs/[runId]}/route.js.nft.json +1 -1
  50. package/app/apps/web/.next/server/app/api/runs/[runId]/route_client-reference-manifest.js +3 -0
  51. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route/app-paths-manifest.json +3 -0
  52. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route/build-manifest.json +9 -0
  53. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route/server-reference-manifest.json +4 -0
  54. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js +6 -0
  55. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route.js.map +5 -0
  56. package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → runs/[runId]/stream}/route.js.nft.json +1 -1
  57. package/app/apps/web/.next/server/app/api/runs/[runId]/stream/route_client-reference-manifest.js +3 -0
  58. package/app/apps/web/.next/server/app/api/runs/route/app-paths-manifest.json +3 -0
  59. package/app/apps/web/.next/server/app/api/runs/route/build-manifest.json +9 -0
  60. package/app/apps/web/.next/server/app/api/runs/route/server-reference-manifest.json +4 -0
  61. package/app/apps/web/.next/server/app/api/runs/route.js +6 -0
  62. package/app/apps/web/.next/server/app/api/runs/route.js.map +5 -0
  63. package/app/apps/web/.next/server/app/api/{insights → runs}/route.js.nft.json +1 -1
  64. package/app/apps/web/.next/server/app/api/runs/route_client-reference-manifest.js +3 -0
  65. package/app/apps/web/.next/server/app/api/settings/route/app-paths-manifest.json +3 -0
  66. package/app/apps/web/.next/server/app/api/settings/route/build-manifest.json +9 -0
  67. package/app/apps/web/.next/server/app/api/settings/route/server-reference-manifest.json +4 -0
  68. package/app/apps/web/.next/server/app/api/settings/route.js +10 -0
  69. package/app/apps/web/.next/server/app/api/settings/route.js.map +5 -0
  70. package/app/apps/web/.next/server/app/api/settings/route.js.nft.json +1 -0
  71. package/app/apps/web/.next/server/app/api/{insights → settings}/route_client-reference-manifest.js +1 -1
  72. package/app/apps/web/.next/server/app/day/[date]/page/app-paths-manifest.json +3 -0
  73. package/app/apps/web/.next/server/app/{insights/print/[key] → day/[date]}/page/build-manifest.json +4 -4
  74. package/app/apps/web/.next/server/app/day/[date]/page/server-reference-manifest.json +4 -0
  75. package/app/apps/web/.next/server/app/day/[date]/page.js +18 -0
  76. package/app/apps/web/.next/server/app/day/[date]/page.js.map +5 -0
  77. package/app/apps/web/.next/server/app/day/[date]/page.js.nft.json +1 -0
  78. package/app/apps/web/.next/server/app/day/[date]/page_client-reference-manifest.js +3 -0
  79. package/app/apps/web/.next/server/app/day/page/app-paths-manifest.json +3 -0
  80. package/app/apps/web/.next/server/app/day/page/build-manifest.json +17 -0
  81. package/app/apps/web/.next/server/app/day/page/next-font-manifest.json +6 -0
  82. package/app/apps/web/.next/server/app/day/page/react-loadable-manifest.json +1 -0
  83. package/app/apps/web/.next/server/app/day/page/server-reference-manifest.json +4 -0
  84. package/app/apps/web/.next/server/app/{insights/print/[key] → day}/page.js +11 -10
  85. package/app/apps/web/.next/server/app/day/page.js.map +5 -0
  86. package/app/apps/web/.next/server/app/day/page.js.nft.json +1 -0
  87. package/app/apps/web/.next/server/app/day/page_client-reference-manifest.js +3 -0
  88. package/app/apps/web/.next/server/app/digest/[date]/page/app-paths-manifest.json +3 -0
  89. package/app/apps/web/.next/server/app/digest/[date]/page/build-manifest.json +17 -0
  90. package/app/apps/web/.next/server/app/digest/[date]/page/next-font-manifest.json +6 -0
  91. package/app/apps/web/.next/server/app/digest/[date]/page/react-loadable-manifest.json +1 -0
  92. package/app/apps/web/.next/server/app/digest/[date]/page/server-reference-manifest.json +4 -0
  93. package/app/apps/web/.next/server/app/digest/[date]/page.js +17 -0
  94. package/app/apps/web/.next/server/app/digest/[date]/page.js.map +5 -0
  95. package/app/apps/web/.next/server/app/digest/[date]/page.js.nft.json +1 -0
  96. package/app/apps/web/.next/server/app/digest/[date]/page_client-reference-manifest.js +3 -0
  97. package/app/apps/web/.next/server/app/digest/page/app-paths-manifest.json +3 -0
  98. package/app/apps/web/.next/server/app/digest/page/build-manifest.json +17 -0
  99. package/app/apps/web/.next/server/app/digest/page/next-font-manifest.json +6 -0
  100. package/app/apps/web/.next/server/app/digest/page/react-loadable-manifest.json +1 -0
  101. package/app/apps/web/.next/server/app/digest/page/server-reference-manifest.json +4 -0
  102. package/app/apps/web/.next/server/app/digest/page.js +17 -0
  103. package/app/apps/web/.next/server/app/digest/page.js.map +5 -0
  104. package/app/apps/web/.next/server/app/digest/page.js.nft.json +1 -0
  105. package/app/apps/web/.next/server/app/digest/page_client-reference-manifest.js +3 -0
  106. package/app/apps/web/.next/server/app/insights/[key]/page/build-manifest.json +4 -4
  107. package/app/apps/web/.next/server/app/insights/[key]/page.js +7 -5
  108. package/app/apps/web/.next/server/app/insights/[key]/page.js.nft.json +1 -1
  109. package/app/apps/web/.next/server/app/insights/[key]/page_client-reference-manifest.js +1 -1
  110. package/app/apps/web/.next/server/app/insights/page/build-manifest.json +4 -4
  111. package/app/apps/web/.next/server/app/insights/page.js +7 -5
  112. package/app/apps/web/.next/server/app/insights/page.js.nft.json +1 -1
  113. package/app/apps/web/.next/server/app/insights/page_client-reference-manifest.js +1 -1
  114. package/app/apps/web/.next/server/app/page/build-manifest.json +4 -4
  115. package/app/apps/web/.next/server/app/page.js +7 -6
  116. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  117. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  118. package/app/apps/web/.next/server/app/parallelism/page/build-manifest.json +4 -4
  119. package/app/apps/web/.next/server/app/parallelism/page.js +6 -5
  120. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  121. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  122. package/app/apps/web/.next/server/app/projects/[slug]/page/build-manifest.json +4 -4
  123. package/app/apps/web/.next/server/app/projects/[slug]/page.js +6 -5
  124. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  125. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  126. package/app/apps/web/.next/server/app/projects/page/build-manifest.json +4 -4
  127. package/app/apps/web/.next/server/app/projects/page.js +5 -4
  128. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  129. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  130. package/app/apps/web/.next/server/app/runs/page/app-paths-manifest.json +3 -0
  131. package/app/apps/web/.next/server/app/runs/page/build-manifest.json +17 -0
  132. package/app/apps/web/.next/server/app/runs/page/next-font-manifest.json +6 -0
  133. package/app/apps/web/.next/server/app/runs/page/react-loadable-manifest.json +1 -0
  134. package/app/apps/web/.next/server/app/runs/page/server-reference-manifest.json +4 -0
  135. package/app/apps/web/.next/server/app/runs/page.js +17 -0
  136. package/app/apps/web/.next/server/app/runs/page.js.map +5 -0
  137. package/app/apps/web/.next/server/app/runs/page.js.nft.json +1 -0
  138. package/app/apps/web/.next/server/app/runs/page_client-reference-manifest.js +3 -0
  139. package/app/apps/web/.next/server/app/sessions/[id]/page/build-manifest.json +4 -4
  140. package/app/apps/web/.next/server/app/sessions/[id]/page.js +5 -4
  141. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  142. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  143. package/app/apps/web/.next/server/app/sessions/page/build-manifest.json +4 -4
  144. package/app/apps/web/.next/server/app/sessions/page.js +5 -4
  145. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  146. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  147. package/app/apps/web/.next/server/app/settings/page/app-paths-manifest.json +3 -0
  148. package/app/apps/web/.next/server/app/settings/page/build-manifest.json +17 -0
  149. package/app/apps/web/.next/server/app/settings/page/next-font-manifest.json +6 -0
  150. package/app/apps/web/.next/server/app/settings/page/react-loadable-manifest.json +1 -0
  151. package/app/apps/web/.next/server/app/settings/page/server-reference-manifest.json +4 -0
  152. package/app/apps/web/.next/server/app/settings/page.js +18 -0
  153. package/app/apps/web/.next/server/app/settings/page.js.map +5 -0
  154. package/app/apps/web/.next/server/app/settings/page.js.nft.json +1 -0
  155. package/app/apps/web/.next/server/app/settings/page_client-reference-manifest.js +3 -0
  156. package/app/apps/web/.next/server/app/usage/page/build-manifest.json +4 -4
  157. package/app/apps/web/.next/server/app/usage/page.js +6 -5
  158. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  159. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  160. package/app/apps/web/.next/server/app-paths-manifest.json +16 -7
  161. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_digest_week_[startDate]_route_actions_0klqqsh.js +3 -0
  162. package/app/apps/web/.next/server/chunks/09og__next-internal_server_app_api_digest_month_[yearMonth]_route_actions_0i4ielu.js +3 -0
  163. package/app/apps/web/.next/server/chunks/[externals]__0o43ejh._.js +3 -0
  164. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0-vgrh1._.js +3 -0
  165. package/app/apps/web/.next/server/chunks/[root-of-the-server]__00n3f9y._.js +3 -0
  166. package/app/apps/web/.next/server/chunks/[root-of-the-server]__02zukjw._.js +3 -0
  167. package/app/apps/web/.next/server/chunks/[root-of-the-server]__067~im1._.js +6 -0
  168. package/app/apps/web/.next/server/chunks/[root-of-the-server]__06b4cj-._.js +3 -0
  169. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0_8zh-i._.js +9 -0
  170. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0e8n_x4._.js +3 -0
  171. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ej_p3s._.js +9 -0
  172. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0jprdks._.js +9 -0
  173. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_digest_day_[date]_route_actions_09sxie5.js +3 -0
  174. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_digest_month-index_route_actions_0wldpbu.js +3 -0
  175. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_digest_week-index_route_actions_12c2wj2.js +3 -0
  176. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_jobs_route_actions_08kx~8-.js +3 -0
  177. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_runs_[runId]_route_actions_0dfcghc.js +3 -0
  178. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_runs_[runId]_stream_route_actions_0.8e8-k.js +3 -0
  179. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_runs_route_actions_0xyx82f.js +3 -0
  180. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_settings_route_actions_0.xv7sx.js +3 -0
  181. package/app/apps/web/.next/server/chunks/node_modules_next_036my~r._.js +49 -0
  182. package/app/apps/web/.next/server/chunks/packages_0e7q9u_._.js +3 -0
  183. package/app/apps/web/.next/server/chunks/packages_0n6p2ot._.js +3 -0
  184. package/app/apps/web/.next/server/chunks/packages_entries_dist_node_0bckr7-.js +379 -0
  185. package/app/apps/web/.next/server/chunks/packages_parser_dist_fs_0bc7ptm.js +1 -1
  186. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0-1_njm._.js +3 -0
  187. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0-94ji~._.js +3 -0
  188. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__13xpdx0._.js → [root-of-the-server]__03uoeiw._.js} +2 -2
  189. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0_6.inc._.js +1 -1
  190. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0d~2~le._.js +8 -0
  191. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0gio_ck._.js +1 -1
  192. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__08.d5ia._.js → [root-of-the-server]__0jdyefm._.js} +10 -10
  193. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ln9jsw._.js +3 -0
  194. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0z45d0g._.js → [root-of-the-server]__0lz4a~g._.js} +2 -48
  195. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0o1_g.~._.js +3 -0
  196. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0r4tks8._.js +3 -0
  197. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0rvzdnx._.js +3 -0
  198. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0euu8sa._.js → [root-of-the-server]__0u39afl._.js} +2 -2
  199. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0u5d7de._.js +12 -0
  200. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +3 -3
  201. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0wwa6gh._.js +3 -0
  202. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0xy1qim._.js +3 -0
  203. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~_8vff._.js +3 -0
  204. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__10srpu0._.js +3 -0
  205. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__11v.eqw._.js +1 -1
  206. package/app/apps/web/.next/server/chunks/ssr/_02s1n-x._.js +8 -0
  207. package/app/apps/web/.next/server/chunks/ssr/_0fjbf--._.js +3 -0
  208. package/app/apps/web/.next/server/chunks/ssr/_0jw2sm7._.js +3 -0
  209. package/app/apps/web/.next/server/chunks/ssr/_0wj750k._.js +3 -0
  210. package/app/apps/web/.next/server/chunks/ssr/_0woap-3._.js +1 -1
  211. package/app/apps/web/.next/server/chunks/ssr/{_0xies90._.js → _0xu2pvc._.js} +2 -2
  212. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_day_[date]_page_actions_0u2kxb..js +3 -0
  213. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_day_page_actions_1042maj.js +3 -0
  214. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_digest_[date]_page_actions_0olu967.js +3 -0
  215. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_digest_page_actions_0bl.eil.js +3 -0
  216. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_runs_page_actions_0485qy7.js +3 -0
  217. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_settings_page_actions_0f6epye.js +3 -0
  218. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_day_[date]_day-view_tsx_0wjoe1u._.js +3 -0
  219. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_settings_ai-features-form_tsx_01p699p._.js +3 -0
  220. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0b-4-4j._.js +1 -1
  221. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0ly1xes._.js +6 -0
  222. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0txtsv5._.js +16 -0
  223. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0xs658s._.js +10 -0
  224. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_runs-live-board_tsx_0r6dkdq._.js +3 -0
  225. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_usage-charts-dashboard_tsx_0bgr_uv._.js +1 -1
  226. package/app/apps/web/.next/server/chunks/ssr/apps_web_lib_usage-data_ts_0xtv99n._.js +3 -0
  227. package/app/apps/web/.next/server/chunks/ssr/node_modules_0i2xw~e._.js +3 -0
  228. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_0e1izl_._.js +1 -1
  229. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0d3d4wn.js +4 -0
  230. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0edz1ko.js +4 -0
  231. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0eq.n-n.js +4 -0
  232. package/app/apps/web/.next/server/chunks/ssr/{node_modules_next_dist_esm_build_templates_app-page_0vz7_px.js → node_modules_next_dist_esm_build_templates_app-page_0hcvt-s.js} +3 -3
  233. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_0nd5zu0.js +4 -0
  234. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_11j1qy0.js +4 -0
  235. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_esm_build_templates_app-page_12n1lw_.js +1 -1
  236. package/app/apps/web/.next/server/chunks/ssr/packages_entries_dist_node_0_271yr.js +3 -0
  237. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0-jvt~a._.js +1 -1
  238. package/app/apps/web/.next/server/functions-config-manifest.json +11 -6
  239. package/app/apps/web/.next/server/middleware-build-manifest.js +7 -7
  240. package/app/apps/web/.next/server/pages/500.html +1 -1
  241. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  242. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  243. package/app/apps/web/.next/static/chunks/0-yc2_pjxwwuq.js +1 -0
  244. package/app/apps/web/.next/static/chunks/0257pdz1-imal.js +2 -0
  245. package/app/apps/web/.next/static/chunks/05m.oz3kmf1p7.js +1 -0
  246. package/app/apps/web/.next/static/chunks/{0pqt~8bl3ukh4.js → 073081qv4uyn8.js} +1 -1
  247. package/app/apps/web/.next/static/chunks/{0018dy-m-kusj.js → 07lbm-sdh9c2j.js} +1 -1
  248. package/app/apps/web/.next/static/chunks/0858bgw2i4vob.js +1 -0
  249. package/app/apps/web/.next/static/chunks/0_7303jr0sf0w.js +10 -0
  250. package/app/apps/web/.next/static/chunks/0byz8fqw.exef.js +1 -0
  251. package/app/apps/web/.next/static/chunks/0coa1800xqgfj.js +1 -0
  252. package/app/apps/web/.next/static/chunks/0fs3gxea5h0s3.css +1 -0
  253. package/app/apps/web/.next/static/chunks/0k1psab.bybh9.js +14 -0
  254. package/app/apps/web/.next/static/chunks/0k9pksi_i.odf.js +1 -0
  255. package/app/apps/web/.next/static/chunks/0m62vx92~0_0d.js +1 -0
  256. package/app/apps/web/.next/static/chunks/0mc8aa8z.0-5l.js +8 -0
  257. package/app/apps/web/.next/static/chunks/0mykrrv810ra-.js +31 -0
  258. package/app/apps/web/.next/static/chunks/0o9ayt8sknubd.js +1 -0
  259. package/app/apps/web/.next/static/chunks/0osdgl2.9cl1q.js +6 -0
  260. package/app/apps/web/.next/static/chunks/0xfu09fn_358k.js +4 -0
  261. package/app/apps/web/.next/static/chunks/171za22fv684..js +6 -0
  262. package/app/apps/web/.next/static/chunks/17u2ww8ya5dv1.js +6 -0
  263. package/app/apps/web/.next/static/chunks/{turbopack-169w-1._23ra_.js → turbopack-0_p36yduv.waj.js} +1 -1
  264. package/app/apps/web/app/api/digest/day/[date]/route.ts +152 -0
  265. package/app/apps/web/app/api/digest/month/[yearMonth]/route.ts +147 -0
  266. package/app/apps/web/app/api/digest/month-index/route.ts +103 -0
  267. package/app/apps/web/app/api/digest/week/[startDate]/route.ts +149 -0
  268. package/app/apps/web/app/api/{insights/weeks-index → digest/week-index}/route.ts +45 -33
  269. package/app/apps/web/app/api/jobs/route.ts +8 -0
  270. package/app/apps/web/app/api/runs/[runId]/route.ts +64 -0
  271. package/app/apps/web/app/api/runs/[runId]/stream/route.ts +154 -0
  272. package/app/apps/web/app/api/runs/route.ts +266 -0
  273. package/app/apps/web/app/api/settings/route.ts +35 -0
  274. package/app/apps/web/app/day/[date]/day-view.tsx +193 -0
  275. package/app/apps/web/app/day/[date]/page.tsx +175 -0
  276. package/app/apps/web/app/day/page.tsx +8 -0
  277. package/app/apps/web/app/digest/[date]/page.tsx +15 -0
  278. package/app/apps/web/app/digest/page.tsx +7 -0
  279. package/app/apps/web/app/insights/[key]/page.tsx +106 -48
  280. package/app/apps/web/app/insights/page.tsx +133 -3
  281. package/app/apps/web/app/layout.tsx +23 -3
  282. package/app/apps/web/app/page.tsx +33 -4
  283. package/app/apps/web/app/parallelism/gantt-chart.tsx +67 -1
  284. package/app/apps/web/app/parallelism/page.tsx +8 -278
  285. package/app/apps/web/app/projects/[slug]/page.tsx +153 -0
  286. package/app/apps/web/app/projects/page.tsx +49 -4
  287. package/app/apps/web/app/projects/projects-view.tsx +79 -68
  288. package/app/apps/web/app/runs/page.tsx +21 -0
  289. package/app/apps/web/app/sessions/[id]/page.tsx +12 -1
  290. package/app/apps/web/app/sessions/[id]/session-view.tsx +569 -21
  291. package/app/apps/web/app/sessions/page.tsx +19 -3
  292. package/app/apps/web/app/sessions/sessions-grid.tsx +172 -131
  293. package/app/apps/web/app/settings/ai-features-form.tsx +45 -0
  294. package/app/apps/web/app/settings/page.tsx +20 -0
  295. package/app/apps/web/app/usage/page.tsx +45 -3
  296. package/app/apps/web/components/auto-generate-yesterday.tsx +96 -0
  297. package/app/apps/web/components/backfill-drawer.tsx +309 -0
  298. package/app/apps/web/components/dashboard-view.tsx +4 -2
  299. package/app/apps/web/components/date-nav.tsx +385 -0
  300. package/app/apps/web/components/day-digest-view.tsx +180 -0
  301. package/app/apps/web/components/day-digest.tsx +489 -0
  302. package/app/apps/web/components/flag-chip.tsx +54 -0
  303. package/app/apps/web/components/goal-bar.tsx +63 -0
  304. package/app/apps/web/components/heatmap.tsx +78 -1
  305. package/app/apps/web/components/helpfulness-sparkline.tsx +82 -0
  306. package/app/apps/web/components/insights-history.tsx +211 -0
  307. package/app/apps/web/components/insights-top-bar.tsx +216 -0
  308. package/app/apps/web/components/job-queue-widget.tsx +274 -0
  309. package/app/apps/web/components/live-sessions-widget.tsx +38 -3
  310. package/app/apps/web/components/month-digest-view.tsx +138 -0
  311. package/app/apps/web/components/month-digest.tsx +216 -0
  312. package/app/apps/web/components/outcome-mix-row.tsx +37 -0
  313. package/app/apps/web/components/outcome-pill.tsx +101 -0
  314. package/app/apps/web/components/previous-cycles-trend.tsx +155 -0
  315. package/app/apps/web/components/recent-days-panel.tsx +83 -0
  316. package/app/apps/web/components/runs-live-board.tsx +513 -0
  317. package/app/apps/web/components/sidebar.tsx +38 -4
  318. package/app/apps/web/components/usage-chart-range.tsx +58 -6
  319. package/app/apps/web/components/usage-chart.tsx +94 -7
  320. package/app/apps/web/components/usage-charts-dashboard.tsx +20 -1
  321. package/app/apps/web/components/week-digest-view.tsx +226 -0
  322. package/app/apps/web/components/week-digest.tsx +2128 -0
  323. package/app/apps/web/components/yesterday-hero.tsx +110 -0
  324. package/app/apps/web/lib/auto-week-fire.ts +37 -0
  325. package/app/apps/web/lib/calibration-data.ts +171 -0
  326. package/app/apps/web/lib/entries-index.ts +174 -0
  327. package/app/apps/web/lib/entries.ts +72 -0
  328. package/app/apps/web/lib/inflight-coalesce.test.ts +43 -0
  329. package/app/apps/web/lib/inflight-coalesce.ts +19 -0
  330. package/app/apps/web/lib/jobs.ts +170 -0
  331. package/app/apps/web/lib/usage-data.ts +37 -0
  332. package/app/apps/web/lib/validate-settings.test.ts +25 -0
  333. package/app/apps/web/lib/validate-settings.ts +9 -0
  334. package/app/apps/web/next.config.ts +1 -1
  335. package/app/apps/web/package.json +4 -2
  336. package/app/apps/web/server.js +1 -1
  337. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  338. package/app/apps/web/vitest.config.ts +9 -0
  339. package/dist/daemon-worker.js +1758 -713
  340. package/dist/index.js +11308 -1888
  341. package/package.json +4 -1
  342. package/app/apps/web/.next/server/app/api/insights/months-index/route/app-paths-manifest.json +0 -3
  343. package/app/apps/web/.next/server/app/api/insights/months-index/route.js +0 -7
  344. package/app/apps/web/.next/server/app/api/insights/months-index/route_client-reference-manifest.js +0 -3
  345. package/app/apps/web/.next/server/app/api/insights/pdf/[key]/route/app-paths-manifest.json +0 -3
  346. package/app/apps/web/.next/server/app/api/insights/pdf/[key]/route.js +0 -6
  347. package/app/apps/web/.next/server/app/api/insights/route/app-paths-manifest.json +0 -3
  348. package/app/apps/web/.next/server/app/api/insights/route.js +0 -8
  349. package/app/apps/web/.next/server/app/api/insights/saved/[key]/route/app-paths-manifest.json +0 -3
  350. package/app/apps/web/.next/server/app/api/insights/saved/[key]/route.js +0 -6
  351. package/app/apps/web/.next/server/app/api/insights/saved/[key]/route_client-reference-manifest.js +0 -3
  352. package/app/apps/web/.next/server/app/api/insights/saved/route/app-paths-manifest.json +0 -3
  353. package/app/apps/web/.next/server/app/api/insights/saved/route.js +0 -6
  354. package/app/apps/web/.next/server/app/api/insights/saved/route_client-reference-manifest.js +0 -3
  355. package/app/apps/web/.next/server/app/api/insights/weeks-index/route/app-paths-manifest.json +0 -3
  356. package/app/apps/web/.next/server/app/api/insights/weeks-index/route.js +0 -7
  357. package/app/apps/web/.next/server/app/api/insights/weeks-index/route_client-reference-manifest.js +0 -3
  358. package/app/apps/web/.next/server/app/insights/print/[key]/page/app-paths-manifest.json +0 -3
  359. package/app/apps/web/.next/server/app/insights/print/[key]/page.js.nft.json +0 -1
  360. package/app/apps/web/.next/server/app/insights/print/[key]/page_client-reference-manifest.js +0 -3
  361. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_insights_months-index_route_actions_0~h~zci.js +0 -3
  362. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_insights_saved_[key]_route_actions_0a5j9yw.js +0 -3
  363. package/app/apps/web/.next/server/chunks/02dz_web__next-internal_server_app_api_insights_weeks-index_route_actions_0hh-1c7.js +0 -3
  364. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0.hmj0z._.js +0 -3
  365. package/app/apps/web/.next/server/chunks/[root-of-the-server]__01h_g-p._.js +0 -3
  366. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0nh-z10._.js +0 -3
  367. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0ri7q~r._.js +0 -3
  368. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0rr1~~x._.js +0 -3
  369. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0s0gv.0._.js +0 -3
  370. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_insights_pdf_[key]_route_actions_0lu-lnx.js +0 -3
  371. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_insights_route_actions_0h8l5lz.js +0 -3
  372. package/app/apps/web/.next/server/chunks/apps_web__next-internal_server_app_api_insights_saved_route_actions_13rlblw.js +0 -3
  373. package/app/apps/web/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_00t2xj6.js +0 -68
  374. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0.tsxpj._.js +0 -3
  375. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__00z7zlm._.js +0 -3
  376. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__08pen0k._.js +0 -3
  377. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0b323~k._.js +0 -8
  378. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0gx-4qa._.js +0 -3
  379. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0wv27wt._.js +0 -3
  380. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__13itnvx._.js +0 -3
  381. package/app/apps/web/.next/server/chunks/ssr/_09n75_5._.js +0 -8
  382. package/app/apps/web/.next/server/chunks/ssr/_0r~__0v._.js +0 -12
  383. package/app/apps/web/.next/server/chunks/ssr/apps_web__next-internal_server_app_insights_print_[key]_page_actions_0a853fw.js +0 -3
  384. package/app/apps/web/.next/server/chunks/ssr/apps_web_app_parallelism_08vub.0._.js +0 -3
  385. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_06j3c.0._.js +0 -8
  386. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_0bbo_pd._.js +0 -8
  387. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_insight-report_tsx_13q2a-c._.js +0 -12
  388. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_insights-view_tsx_11730ta._.js +0 -6
  389. package/app/apps/web/.next/server/chunks/ssr/node_modules_lucide-react_dist_esm_icons_0nqz8dw._.js +0 -3
  390. package/app/apps/web/.next/server/chunks/ssr/node_modules_next_dist_0t-hj0x._.js +0 -3
  391. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_analytics_0k4dgst.js +0 -3
  392. package/app/apps/web/.next/static/chunks/028_pmk40b69_.js +0 -6
  393. package/app/apps/web/.next/static/chunks/03.mv4y4.w-vb.js +0 -6
  394. package/app/apps/web/.next/static/chunks/03_7xtpi9sv4g.js +0 -4
  395. package/app/apps/web/.next/static/chunks/03g5dw5eskotd.js +0 -6
  396. package/app/apps/web/.next/static/chunks/063oimt30jeo9.js +0 -10
  397. package/app/apps/web/.next/static/chunks/08c1pcrocqq5s.js +0 -6
  398. package/app/apps/web/.next/static/chunks/0e-wrhqh4h3r5.js +0 -2
  399. package/app/apps/web/.next/static/chunks/0fc6dk2qtokwh.js +0 -1
  400. package/app/apps/web/.next/static/chunks/0i7er7_bfab36.js +0 -10
  401. package/app/apps/web/.next/static/chunks/0ipytyi01h0ta.js +0 -1
  402. package/app/apps/web/.next/static/chunks/0lsznd4_avzhv.js +0 -6
  403. package/app/apps/web/.next/static/chunks/0lty3v_i9mde7.js +0 -1
  404. package/app/apps/web/.next/static/chunks/0vekjjj4pidlz.css +0 -1
  405. package/app/apps/web/.next/static/chunks/137uw2-qbro07.js +0 -31
  406. package/app/apps/web/app/api/insights/months-index/route.ts +0 -80
  407. package/app/apps/web/app/api/insights/pdf/[key]/route.ts +0 -45
  408. package/app/apps/web/app/api/insights/route.ts +0 -508
  409. package/app/apps/web/app/api/insights/saved/[key]/route.ts +0 -11
  410. package/app/apps/web/app/api/insights/saved/route.ts +0 -9
  411. package/app/apps/web/app/insights/print/[key]/page.tsx +0 -73
  412. package/app/apps/web/components/insight-report.tsx +0 -1031
  413. package/app/apps/web/components/insights-view.tsx +0 -647
  414. package/app/apps/web/lib/ai/insights-prompt.ts +0 -71
  415. package/app/apps/web/lib/ai/saved-reports.ts +0 -83
  416. /package/app/apps/web/.next/server/app/api/{insights/months-index → digest/day/[date]}/route/build-manifest.json +0 -0
  417. /package/app/apps/web/.next/server/app/api/{insights/months-index → digest/day/[date]}/route/server-reference-manifest.json +0 -0
  418. /package/app/apps/web/.next/server/app/api/{insights/months-index → digest/day/[date]}/route.js.map +0 -0
  419. /package/app/apps/web/.next/server/app/api/{insights → digest/month/[yearMonth]}/route/build-manifest.json +0 -0
  420. /package/app/apps/web/.next/server/app/api/{insights → digest/month/[yearMonth]}/route/server-reference-manifest.json +0 -0
  421. /package/app/apps/web/.next/server/app/api/{insights → digest/month/[yearMonth]}/route.js.map +0 -0
  422. /package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route/build-manifest.json +0 -0
  423. /package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route/server-reference-manifest.json +0 -0
  424. /package/app/apps/web/.next/server/app/api/{insights/pdf/[key] → digest/month-index}/route.js.map +0 -0
  425. /package/app/apps/web/.next/server/app/api/{insights/saved → digest/week/[startDate]}/route/build-manifest.json +0 -0
  426. /package/app/apps/web/.next/server/app/api/{insights/saved → digest/week/[startDate]}/route/server-reference-manifest.json +0 -0
  427. /package/app/apps/web/.next/server/app/api/{insights/saved → digest/week/[startDate]}/route.js.map +0 -0
  428. /package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/week-index}/route/build-manifest.json +0 -0
  429. /package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/week-index}/route/server-reference-manifest.json +0 -0
  430. /package/app/apps/web/.next/server/app/api/{insights/saved/[key] → digest/week-index}/route.js.map +0 -0
  431. /package/app/apps/web/.next/server/app/api/{insights/weeks-index → jobs}/route/build-manifest.json +0 -0
  432. /package/app/apps/web/.next/server/app/api/{insights/weeks-index → jobs}/route/server-reference-manifest.json +0 -0
  433. /package/app/apps/web/.next/server/app/api/{insights/weeks-index → jobs}/route.js.map +0 -0
  434. /package/app/apps/web/.next/server/app/{insights/print/[key]/page → api/runs/[runId]/route}/server-reference-manifest.json +0 -0
  435. /package/app/apps/web/.next/server/app/{insights/print/[key]/page.js.map → api/runs/[runId]/route.js.map} +0 -0
  436. /package/app/apps/web/.next/server/app/{insights/print/[key] → day/[date]}/page/next-font-manifest.json +0 -0
  437. /package/app/apps/web/.next/server/app/{insights/print/[key] → day/[date]}/page/react-loadable-manifest.json +0 -0
  438. /package/app/apps/web/.next/static/{G_4ofKI9v9ARC_lb9JILZ → 8tTWPvUhtatZEoocIhamh}/_buildManifest.js +0 -0
  439. /package/app/apps/web/.next/static/{G_4ofKI9v9ARC_lb9JILZ → 8tTWPvUhtatZEoocIhamh}/_clientMiddlewareManifest.js +0 -0
  440. /package/app/apps/web/.next/static/{G_4ofKI9v9ARC_lb9JILZ → 8tTWPvUhtatZEoocIhamh}/_ssgManifest.js +0 -0
@@ -0,0 +1,489 @@
1
+ "use client";
2
+
3
+ import { useState, type ReactNode } from "react";
4
+ import { ChevronDown, ChevronRight } from "lucide-react";
5
+ import type { DayDigest as DayDigestType, DaySignals, Entry } from "@claude-lens/entries";
6
+ import { OutcomePill } from "./outcome-pill";
7
+ import { GoalBar } from "./goal-bar";
8
+
9
+ const SHAPE_LABELS: Record<string, string> = {
10
+ "spec-review-loop": "Spec-review loop",
11
+ "chunk-implementation": "Chunk implementation",
12
+ "research-then-build": "Research-then-build",
13
+ "reviewer-triad": "Reviewer triad",
14
+ "background-coordinated": "Background-coordinated",
15
+ "solo-continuation": "Solo continuation",
16
+ "solo-design": "Solo design",
17
+ "solo-build": "Solo build",
18
+ "mixed": "Mixed",
19
+ };
20
+
21
+ const FRAME_LABELS: Record<string, string> = {
22
+ "teammate": "<teammate-message>",
23
+ "task-notification": "<task-notification>",
24
+ "local-command-caveat": "<local-command-caveat>",
25
+ "image-attached": "[Image #N]",
26
+ "slash-command": "/command",
27
+ "handoff-prose": "Handoff prose",
28
+ };
29
+
30
+ export function DayDigest({
31
+ digest, entries, aiEnabled, actions,
32
+ }: {
33
+ digest: DayDigestType;
34
+ entries: Entry[];
35
+ aiEnabled: boolean;
36
+ /** Optional inline-right cluster (e.g. Generate / Re-roll buttons). */
37
+ actions?: ReactNode;
38
+ }) {
39
+ const [showDetails, setShowDetails] = useState(false);
40
+ const fmtDate = new Date(`${digest.key}T12:00:00`).toLocaleDateString("en-US", {
41
+ weekday: "long", month: "short", day: "numeric", year: "numeric",
42
+ });
43
+ const hrs = digest.agent_min / 60;
44
+ const timeStr = hrs >= 1 ? `${hrs.toFixed(1)}h` : `${Math.round(digest.agent_min)}m`;
45
+
46
+ // Sort entries chronologically (most recent first)
47
+ const sortedEntries = [...entries].sort(
48
+ (a, b) => Date.parse(b.start_iso) - Date.parse(a.start_iso),
49
+ );
50
+
51
+ return (
52
+ <div style={{ maxWidth: 980, margin: "0 auto", padding: "24px 40px" }}>
53
+ {/* Hero: date + outcome + stats on one row, headline below */}
54
+ <header style={{ marginBottom: 28 }}>
55
+ <div style={{
56
+ display: "flex", alignItems: "center", gap: 10, marginBottom: 8,
57
+ fontSize: 12, color: "var(--af-text-tertiary)", fontWeight: 500,
58
+ flexWrap: "wrap",
59
+ }}>
60
+ <span>{fmtDate}</span>
61
+ <OutcomePill outcome={digest.outcome_day} size="lg" />
62
+ <span style={{ color: "var(--af-text-tertiary)" }}>·</span>
63
+ <span style={{ fontFamily: "var(--font-mono)", color: "var(--af-text-secondary)" }}>
64
+ {timeStr} agent time · {digest.projects.length} project{digest.projects.length === 1 ? "" : "s"} · {digest.shipped.length} PR{digest.shipped.length === 1 ? "" : "s"} shipped
65
+ {digest.concurrency_peak > 1 && ` · peak concurrency ×${digest.concurrency_peak}`}
66
+ </span>
67
+ {actions && (
68
+ <div style={{ marginLeft: "auto", display: "inline-flex", alignItems: "center", gap: 8 }}>
69
+ {actions}
70
+ </div>
71
+ )}
72
+ </div>
73
+ {digest.headline ? (
74
+ <h1 style={{
75
+ fontSize: 26, fontWeight: 700, lineHeight: 1.3, letterSpacing: "-0.02em",
76
+ margin: "0 0 8px", maxWidth: 820, color: "var(--af-text)",
77
+ }}>
78
+ {digest.headline}
79
+ </h1>
80
+ ) : (
81
+ <h1 style={{ fontSize: 20, color: "var(--af-text-secondary)", margin: "0 0 14px" }}>
82
+ {aiEnabled ? "No narrative yet — click Regenerate." : `Worked ${timeStr} across ${digest.projects.length} project${digest.projects.length === 1 ? "" : "s"}.`}
83
+ </h1>
84
+ )}
85
+ {digest.day_signature && (
86
+ <p style={{
87
+ margin: "0 0 14px", fontSize: 14, fontStyle: "italic",
88
+ color: "var(--af-text-secondary)", maxWidth: 820, lineHeight: 1.5,
89
+ }}>
90
+ {digest.day_signature}
91
+ </p>
92
+ )}
93
+ </header>
94
+
95
+ {/* AI-off nudge */}
96
+ {!aiEnabled && (
97
+ <div style={{
98
+ padding: 14, marginBottom: 24, background: "var(--af-accent-subtle)",
99
+ borderRadius: 8, fontSize: 13, color: "var(--af-text)",
100
+ }}>
101
+ Enable AI features in <a href="/settings" style={{ color: "var(--af-accent)" }}>Settings</a> to see daily narratives.
102
+ </div>
103
+ )}
104
+
105
+ {/* "How today worked" — deterministic per-day classification, anchors the narrative below. */}
106
+ {digest.day_signals && <DaySignalsSection signals={digest.day_signals} />}
107
+
108
+ {/* Went-well / Friction bands (no panel chrome) */}
109
+ {(digest.what_went_well || digest.what_hit_friction) && (
110
+ <section style={{
111
+ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24, marginBottom: 28,
112
+ }}>
113
+ <Band glyph="✓" color="#48bb78" text={digest.what_went_well} emptyLabel="(smooth)" />
114
+ <Band glyph="⚠" color="#ed8936" text={digest.what_hit_friction} emptyLabel="(no friction)" />
115
+ </section>
116
+ )}
117
+
118
+ {/* Narrative */}
119
+ {digest.narrative && (
120
+ <section style={{
121
+ marginBottom: 28, padding: "4px 0",
122
+ fontSize: 15, lineHeight: 1.6, color: "var(--af-text)",
123
+ maxWidth: 760,
124
+ }}>
125
+ {digest.narrative}
126
+ </section>
127
+ )}
128
+
129
+ {/* Show-more toggle: by default we keep the page short — only headline,
130
+ bands, narrative are visible. Suggestion + work breakdown + shipped +
131
+ sessions + goal-mix collapse behind this button so the timeline section
132
+ below stays close to the fold. */}
133
+ <div style={{ marginBottom: 18 }}>
134
+ <button
135
+ type="button"
136
+ onClick={() => setShowDetails((v) => !v)}
137
+ style={{
138
+ display: "inline-flex",
139
+ alignItems: "center",
140
+ gap: 6,
141
+ padding: "5px 10px",
142
+ background: "transparent",
143
+ border: "1px solid var(--af-border-subtle)",
144
+ borderRadius: 6,
145
+ fontSize: 11,
146
+ color: "var(--af-text-secondary)",
147
+ cursor: "pointer",
148
+ }}
149
+ >
150
+ {showDetails ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
151
+ {showDetails ? "Hide details" : "Show more details"}
152
+ </button>
153
+ </div>
154
+
155
+ {showDetails && (<>
156
+
157
+ {/* Suggestion */}
158
+ {digest.suggestion && (
159
+ <section style={{
160
+ borderLeft: "3px solid var(--af-accent)", paddingLeft: 16, marginBottom: 32,
161
+ }}>
162
+ <div style={{ fontSize: 11, color: "var(--af-text-tertiary)", textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600, marginBottom: 6 }}>
163
+ Tomorrow
164
+ </div>
165
+ <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 4, color: "var(--af-text)" }}>
166
+ {digest.suggestion.headline}
167
+ </div>
168
+ <div style={{ fontSize: 13, color: "var(--af-text-secondary)", lineHeight: 1.5, maxWidth: 760 }}>
169
+ {digest.suggestion.body}
170
+ </div>
171
+ </section>
172
+ )}
173
+
174
+ {/* Work breakdown */}
175
+ {digest.projects.length > 0 && (
176
+ <section style={{ marginBottom: 32 }}>
177
+ <SectionLabel>Work breakdown</SectionLabel>
178
+ <div style={{ display: "grid", gap: 6 }}>
179
+ {digest.projects.map(p => {
180
+ const shippedForProj = digest.shipped.filter(s => s.project === p.display_name);
181
+ return (
182
+ <div key={p.name} style={{
183
+ display: "grid",
184
+ gridTemplateColumns: "140px 1fr 56px 72px",
185
+ gap: 12, alignItems: "center", padding: "6px 0",
186
+ borderBottom: "1px solid var(--af-border-subtle)",
187
+ fontSize: 13,
188
+ }}>
189
+ <span title={p.name} style={{ overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
190
+ {p.display_name}
191
+ </span>
192
+ <ShareBar pct={p.share_pct} />
193
+ <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--af-text-tertiary)", textAlign: "right" }}>
194
+ {p.share_pct.toFixed(0)}%
195
+ </span>
196
+ <span style={{ fontSize: 11, color: "var(--af-text-tertiary)", textAlign: "right" }}>
197
+ {shippedForProj.length > 0 ? `${shippedForProj.length} PR${shippedForProj.length === 1 ? "" : "s"}` : "—"}
198
+ </span>
199
+ </div>
200
+ );
201
+ })}
202
+ </div>
203
+ </section>
204
+ )}
205
+
206
+ {/* Shipped PRs list */}
207
+ {digest.shipped.length > 0 && (
208
+ <section style={{ marginBottom: 32 }}>
209
+ <SectionLabel>Shipped</SectionLabel>
210
+ <ul style={{ margin: 0, padding: 0, listStyle: "none" }}>
211
+ {digest.shipped.map((s, i) => (
212
+ <li key={i} style={{
213
+ padding: "6px 0", fontSize: 13, borderBottom: "1px solid var(--af-border-subtle)",
214
+ display: "flex", gap: 10, alignItems: "baseline",
215
+ }}>
216
+ <span style={{ color: "#48bb78", fontSize: 12 }}>✓</span>
217
+ <span style={{ flex: 1 }}>{s.title}</span>
218
+ <span style={{ fontSize: 11, color: "var(--af-text-tertiary)" }}>{s.project}</span>
219
+ </li>
220
+ ))}
221
+ </ul>
222
+ </section>
223
+ )}
224
+
225
+ {/* Sessions — brief_summary as primary, session UUID hidden */}
226
+ {sortedEntries.length > 0 && (
227
+ <section style={{ marginBottom: 32 }}>
228
+ <SectionLabel>Sessions · {sortedEntries.length}</SectionLabel>
229
+ <div style={{ display: "flex", flexDirection: "column" }}>
230
+ {sortedEntries.map(e => <SessionRow key={e.session_id} entry={e} />)}
231
+ </div>
232
+ </section>
233
+ )}
234
+
235
+ {/* Goal mix (footer) */}
236
+ {digest.top_goal_categories.length > 0 && (
237
+ <section style={{ marginTop: 40, paddingTop: 20, borderTop: "1px solid var(--af-border-subtle)" }}>
238
+ <div style={{ fontSize: 11, color: "var(--af-text-tertiary)", marginBottom: 6 }}>
239
+ Goal mix
240
+ </div>
241
+ <GoalBar goals={digest.top_goal_categories} total={digest.agent_min} />
242
+ </section>
243
+ )}
244
+
245
+ </>)}
246
+ </div>
247
+ );
248
+ }
249
+
250
+ function SectionLabel({ children }: { children: React.ReactNode }) {
251
+ return (
252
+ <div style={{
253
+ fontSize: 10, color: "var(--af-text-tertiary)", textTransform: "uppercase",
254
+ letterSpacing: "0.08em", fontWeight: 600, marginBottom: 10,
255
+ }}>
256
+ {children}
257
+ </div>
258
+ );
259
+ }
260
+
261
+ function Band({ glyph, color, text, emptyLabel }: { glyph: string; color: string; text: string | null; emptyLabel: string }) {
262
+ return (
263
+ <div
264
+ style={{
265
+ fontSize: 14,
266
+ lineHeight: 1.55,
267
+ display: "flex",
268
+ gap: 8,
269
+ alignItems: "flex-start",
270
+ }}
271
+ >
272
+ <span style={{ fontSize: 16, color, lineHeight: 1.4, flexShrink: 0 }}>
273
+ {glyph}
274
+ </span>
275
+ {text ? (
276
+ <span style={{ color: "var(--af-text)" }}>{text}</span>
277
+ ) : (
278
+ <span style={{ color: "var(--af-text-tertiary)", fontStyle: "italic" }}>{emptyLabel}</span>
279
+ )}
280
+ </div>
281
+ );
282
+ }
283
+
284
+ function ShareBar({ pct }: { pct: number }) {
285
+ return (
286
+ <div style={{ height: 6, background: "var(--af-border-subtle)", borderRadius: 99, overflow: "hidden" }}>
287
+ <div style={{
288
+ width: `${Math.min(100, Math.max(0, pct))}%`, height: "100%",
289
+ background: "var(--af-accent)", transition: "width 0.2s",
290
+ }} />
291
+ </div>
292
+ );
293
+ }
294
+
295
+ function DaySignalsSection({ signals }: { signals: DaySignals }) {
296
+ const hasShape = signals.dominant_shape !== null;
297
+ const hasShapeMix = Object.keys(signals.shape_distribution).length > 0;
298
+ const hasSubagentRoles =
299
+ signals.user_authored_subagents_used.length > 0
300
+ || Object.keys(signals.shape_distribution).length > 0;
301
+ const stockSkills = signals.skills_loaded.filter(s => s.origin === "stock");
302
+ const userSkills = signals.skills_loaded.filter(s => s.origin === "user");
303
+ const claudeFrames = signals.prompt_frames.filter(f => f.origin === "claude-feature");
304
+ const personalFrames = signals.prompt_frames.filter(f => f.origin === "personal-habit");
305
+ const cs = signals.comm_style;
306
+ const verbositySum = cs.verbosity_distribution.short + cs.verbosity_distribution.medium
307
+ + cs.verbosity_distribution.long + cs.verbosity_distribution.very_long;
308
+ const steeringSum = cs.steering.interrupts + cs.steering.frustrated + cs.steering.dissatisfied;
309
+
310
+ if (!hasShape && !hasShapeMix && stockSkills.length === 0 && userSkills.length === 0
311
+ && signals.user_authored_subagents_used.length === 0
312
+ && claudeFrames.length === 0 && personalFrames.length === 0
313
+ && verbositySum === 0 && cs.external_refs.length === 0 && steeringSum === 0
314
+ && signals.brainstorm_warmup_session_count === 0
315
+ && signals.todo_ops_total === 0 && !signals.plan_mode_used) {
316
+ return null;
317
+ }
318
+
319
+ return (
320
+ <section style={{
321
+ marginBottom: 28, padding: "14px 16px", borderRadius: 8,
322
+ background: "var(--af-surface)", border: "1px solid var(--af-border-subtle)",
323
+ }}>
324
+ <div style={{
325
+ fontSize: 10, color: "var(--af-text-tertiary)", textTransform: "uppercase",
326
+ letterSpacing: "0.08em", fontWeight: 600, marginBottom: 10,
327
+ }}>
328
+ How today worked
329
+ </div>
330
+
331
+ {hasShape && (
332
+ <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap", marginBottom: 8 }}>
333
+ <span style={{
334
+ display: "inline-flex", alignItems: "center", padding: "3px 10px",
335
+ borderRadius: 999, fontSize: 12, fontWeight: 600,
336
+ background: "var(--af-accent-subtle)", color: "var(--af-accent)",
337
+ }}>
338
+ {SHAPE_LABELS[signals.dominant_shape!] ?? signals.dominant_shape}
339
+ </span>
340
+ {hasShapeMix && (
341
+ <span style={{ fontSize: 12, color: "var(--af-text-secondary)", fontFamily: "var(--font-mono)" }}>
342
+ {Object.entries(signals.shape_distribution)
343
+ .sort((a, b) => b[1] - a[1])
344
+ .map(([s, n]) => `${n} ${s}`)
345
+ .join(" · ")}
346
+ </span>
347
+ )}
348
+ </div>
349
+ )}
350
+
351
+ {hasSubagentRoles && signals.user_authored_subagents_used.length > 0 && (
352
+ <SignalsRow label="Your subagents">
353
+ {signals.user_authored_subagents_used.slice(0, 4).map(sa => (
354
+ <Chip key={sa.type} title={sa.sample_prompt_preview}>
355
+ {sa.type}{sa.count > 1 ? ` ×${sa.count}` : ""}
356
+ </Chip>
357
+ ))}
358
+ </SignalsRow>
359
+ )}
360
+
361
+ {(stockSkills.length > 0 || userSkills.length > 0) && (
362
+ <SignalsRow label="Skills loaded">
363
+ {userSkills.slice(0, 4).map(s => (
364
+ <Chip key={s.skill} tone="user">{s.skill}{s.count > 1 ? ` ×${s.count}` : ""}</Chip>
365
+ ))}
366
+ {stockSkills.slice(0, 4).map(s => (
367
+ <Chip key={s.skill} tone="stock">{s.skill}{s.count > 1 ? ` ×${s.count}` : ""}</Chip>
368
+ ))}
369
+ </SignalsRow>
370
+ )}
371
+
372
+ {(claudeFrames.length > 0 || personalFrames.length > 0) && (
373
+ <SignalsRow label="Prompt frames">
374
+ {personalFrames.map(f => (
375
+ <Chip key={f.frame} tone="user">
376
+ {FRAME_LABELS[f.frame] ?? f.frame}{f.count > 1 ? ` ×${f.count}` : ""}
377
+ </Chip>
378
+ ))}
379
+ {claudeFrames.map(f => (
380
+ <Chip key={f.frame} tone="stock">
381
+ {FRAME_LABELS[f.frame] ?? f.frame}{f.count > 1 ? ` ×${f.count}` : ""}
382
+ </Chip>
383
+ ))}
384
+ </SignalsRow>
385
+ )}
386
+
387
+ {(verbositySum > 0 || cs.external_refs.length > 0 || steeringSum > 0) && (
388
+ <SignalsRow label="Comm style">
389
+ {verbositySum > 0 && (
390
+ <span style={{ fontSize: 12, color: "var(--af-text-secondary)", fontFamily: "var(--font-mono)" }}>
391
+ {[
392
+ cs.verbosity_distribution.short && `${cs.verbosity_distribution.short} short`,
393
+ cs.verbosity_distribution.medium && `${cs.verbosity_distribution.medium} med`,
394
+ cs.verbosity_distribution.long && `${cs.verbosity_distribution.long} long`,
395
+ cs.verbosity_distribution.very_long && `${cs.verbosity_distribution.very_long} v.long`,
396
+ ].filter(Boolean).join(" · ")}
397
+ </span>
398
+ )}
399
+ {cs.external_refs.length > 0 && (
400
+ <Chip>{cs.external_refs.length} external ref{cs.external_refs.length === 1 ? "" : "s"}</Chip>
401
+ )}
402
+ {cs.steering.interrupts > 0 && <Chip>{cs.steering.interrupts} interrupts</Chip>}
403
+ {cs.steering.sessions_with_mid_run_redirect > 0 && (
404
+ <Chip>{cs.steering.sessions_with_mid_run_redirect} mid-run redirect{cs.steering.sessions_with_mid_run_redirect === 1 ? "" : "s"}</Chip>
405
+ )}
406
+ </SignalsRow>
407
+ )}
408
+
409
+ {(signals.brainstorm_warmup_session_count > 0 || signals.todo_ops_total > 0 || signals.plan_mode_used) && (
410
+ <SignalsRow label="Discipline">
411
+ {signals.brainstorm_warmup_session_count > 0 && (
412
+ <Chip>brainstorm warmup ×{signals.brainstorm_warmup_session_count}</Chip>
413
+ )}
414
+ {signals.todo_ops_total > 0 && <Chip>{signals.todo_ops_total} TodoWrite ops</Chip>}
415
+ {signals.plan_mode_used && <Chip tone="user">Plan Mode used</Chip>}
416
+ </SignalsRow>
417
+ )}
418
+ </section>
419
+ );
420
+ }
421
+
422
+ function SignalsRow({ label, children }: { label: string; children: ReactNode }) {
423
+ return (
424
+ <div style={{
425
+ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap",
426
+ padding: "4px 0", fontSize: 12,
427
+ }}>
428
+ <span style={{
429
+ minWidth: 100, color: "var(--af-text-tertiary)", fontWeight: 500,
430
+ fontSize: 11, textTransform: "uppercase", letterSpacing: "0.04em",
431
+ }}>
432
+ {label}
433
+ </span>
434
+ <div style={{ display: "flex", gap: 6, flexWrap: "wrap", flex: 1 }}>{children}</div>
435
+ </div>
436
+ );
437
+ }
438
+
439
+ function Chip({ children, tone, title }: { children: ReactNode; tone?: "user" | "stock"; title?: string }) {
440
+ const bg = tone === "user" ? "var(--af-accent-subtle)" : "var(--af-border-subtle)";
441
+ const fg = tone === "user" ? "var(--af-accent)" : "var(--af-text-secondary)";
442
+ return (
443
+ <span title={title} style={{
444
+ display: "inline-flex", alignItems: "center", padding: "2px 8px",
445
+ borderRadius: 999, fontSize: 11, fontFamily: "var(--font-mono)",
446
+ background: bg, color: fg, whiteSpace: "nowrap",
447
+ maxWidth: 280, overflow: "hidden", textOverflow: "ellipsis",
448
+ }}>
449
+ {children}
450
+ </span>
451
+ );
452
+ }
453
+
454
+ function SessionRow({ entry }: { entry: Entry }) {
455
+ const startTime = new Date(entry.start_iso).toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false });
456
+ const durMin = Math.round(entry.numbers.active_min);
457
+ const projectLabel = entry.project.split("/").filter(Boolean).slice(-1)[0] ?? entry.project;
458
+ const outcome = entry.enrichment.outcome;
459
+ const summary = entry.enrichment.brief_summary;
460
+
461
+ return (
462
+ <a href={`/sessions/${entry.session_id}`} style={{
463
+ display: "block", padding: "8px 0", borderBottom: "1px solid var(--af-border-subtle)",
464
+ fontSize: 13, color: "var(--af-text)", textDecoration: "none",
465
+ }}>
466
+ <div style={{ display: "flex", alignItems: "baseline", gap: 10 }}>
467
+ <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--af-text-tertiary)", width: 48 }}>
468
+ {startTime}
469
+ </span>
470
+ <span style={{ fontSize: 11, color: "var(--af-text-tertiary)", minWidth: 110, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
471
+ {projectLabel}
472
+ </span>
473
+ <span style={{ fontSize: 11, fontFamily: "var(--font-mono)", color: "var(--af-text-tertiary)", width: 40, textAlign: "right" }}>
474
+ {durMin}m
475
+ </span>
476
+ {outcome && <OutcomePill outcome={outcome} size="sm" label="text" />}
477
+ </div>
478
+ {summary && (
479
+ <div style={{
480
+ marginTop: 3, marginLeft: 58, fontSize: 13, color: "var(--af-text-secondary)",
481
+ lineHeight: 1.45, maxWidth: 820,
482
+ }}>
483
+ {summary}
484
+ </div>
485
+ )}
486
+ </a>
487
+ );
488
+ }
489
+
@@ -0,0 +1,54 @@
1
+ "use client";
2
+
3
+ import { flagDef, FLAG_GLOSSARY } from "@claude-lens/entries";
4
+ import type { ReactNode } from "react";
5
+
6
+ const TONE_COLOR: Record<"warn" | "info" | "ok", string> = {
7
+ warn: "#ed8936",
8
+ info: "#4299e1",
9
+ ok: "#48bb78",
10
+ };
11
+
12
+ /** Inline chip rendering an internal flag token using the user-facing label
13
+ * from FLAG_GLOSSARY, with the technical definition exposed via tooltip. */
14
+ export function FlagChip({ token, count }: { token: string; count?: number }) {
15
+ const def = flagDef(token);
16
+ const c = TONE_COLOR[def.tone];
17
+ return (
18
+ <span
19
+ title={`${def.token} — ${def.description}`}
20
+ style={{
21
+ display: "inline-flex", alignItems: "center", gap: 4,
22
+ padding: "2px 8px", borderRadius: 999,
23
+ background: `color-mix(in srgb, ${c} 12%, transparent)`,
24
+ border: `1px solid color-mix(in srgb, ${c} 28%, transparent)`,
25
+ fontSize: 10, fontWeight: 600,
26
+ color: c, fontFamily: "var(--font-mono)",
27
+ whiteSpace: "nowrap",
28
+ }}
29
+ >
30
+ {def.label}
31
+ {typeof count === "number" && (
32
+ <span style={{ opacity: 0.7, fontWeight: 500 }}>×{count}</span>
33
+ )}
34
+ </span>
35
+ );
36
+ }
37
+
38
+ /** Replace any raw flag tokens in a string with <FlagChip> for inline rendering.
39
+ * Defensive against LLM output that slipped a token through despite the
40
+ * system-prompt forbidding it. Token list mirrors FLAG_GLOSSARY exactly. */
41
+ export function renderWithFlagChips(text: string): ReactNode[] {
42
+ const tokens = Object.keys(FLAG_GLOSSARY);
43
+ const pattern = new RegExp(`\\b(${tokens.join("|")})\\b`, "g");
44
+ const out: ReactNode[] = [];
45
+ let lastIdx = 0;
46
+ let match: RegExpExecArray | null;
47
+ while ((match = pattern.exec(text)) !== null) {
48
+ if (match.index > lastIdx) out.push(text.slice(lastIdx, match.index));
49
+ out.push(<FlagChip key={`${match.index}-${match[1]}`} token={match[1]!} />);
50
+ lastIdx = pattern.lastIndex;
51
+ }
52
+ if (lastIdx < text.length) out.push(text.slice(lastIdx));
53
+ return out.length > 0 ? out : [text];
54
+ }
@@ -0,0 +1,63 @@
1
+ "use client";
2
+
3
+ /** Stacked horizontal bar showing time spent across goal-categories.
4
+ * Used by both day and week digests. */
5
+
6
+ export const GOAL_COLORS: Record<string, string> = {
7
+ build: "var(--af-accent)",
8
+ plan: "#9f7aea",
9
+ debug: "#ed8936",
10
+ review: "#4299e1",
11
+ refactor: "#38b2ac",
12
+ test: "#48bb78",
13
+ release: "#ed64a6",
14
+ research: "#a0aec0",
15
+ steer: "#f6ad55",
16
+ meta: "#718096",
17
+ warmup_minimal: "#cbd5e0",
18
+ };
19
+
20
+ export function GoalBar({
21
+ goals, total, height = 12,
22
+ }: {
23
+ goals: Array<{ category: string; minutes: number }>;
24
+ total: number;
25
+ height?: number;
26
+ }) {
27
+ if (total === 0 || goals.length === 0) {
28
+ return <p style={{ fontSize: 12, color: "var(--af-text-tertiary)", margin: 0 }}>No goal data.</p>;
29
+ }
30
+ return (
31
+ <div>
32
+ <div style={{ display: "flex", gap: 2, height, borderRadius: 3, overflow: "hidden" }}>
33
+ {goals.map(g => {
34
+ const pct = (g.minutes / total) * 100;
35
+ return (
36
+ <div
37
+ key={g.category}
38
+ style={{
39
+ width: `${pct}%`,
40
+ background: GOAL_COLORS[g.category] ?? "#888",
41
+ }}
42
+ title={`${g.category}: ${Math.round(g.minutes)}m (${pct.toFixed(0)}%)`}
43
+ />
44
+ );
45
+ })}
46
+ </div>
47
+ <div style={{
48
+ display: "flex", gap: 14, marginTop: 8, flexWrap: "wrap",
49
+ fontSize: 11, color: "var(--af-text-tertiary)",
50
+ }}>
51
+ {goals.map(g => (
52
+ <span key={g.category} style={{ display: "inline-flex", alignItems: "center", gap: 5 }}>
53
+ <span style={{
54
+ width: 8, height: 8, borderRadius: 2,
55
+ background: GOAL_COLORS[g.category] ?? "#888",
56
+ }} />
57
+ {g.category} {Math.round(g.minutes)}m
58
+ </span>
59
+ ))}
60
+ </div>
61
+ </div>
62
+ );
63
+ }