heyiam 0.2.29 → 0.3.1

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 (186) hide show
  1. package/README.md +45 -0
  2. package/dist/auth.js +29 -3
  3. package/dist/config.js +10 -1
  4. package/dist/db.js +0 -1
  5. package/dist/export.js +124 -27
  6. package/dist/format-utils.js +5 -0
  7. package/dist/github.js +381 -0
  8. package/dist/index.js +168 -0
  9. package/dist/mount.js +300 -102
  10. package/dist/parsers/claude.js +2 -28
  11. package/dist/parsers/codex.js +2 -26
  12. package/dist/parsers/cursor.js +2 -26
  13. package/dist/parsers/duration.js +35 -0
  14. package/dist/parsers/gemini.js +2 -20
  15. package/dist/parsers/index.js +22 -3
  16. package/dist/parsers/types.js +0 -1
  17. package/dist/public/assets/index-Coilyhtr.css +1 -0
  18. package/dist/public/assets/index-D0noVMFu.js +44 -0
  19. package/dist/public/index.html +2 -2
  20. package/dist/redact.js +4 -104
  21. package/dist/render/build-render-data.js +9 -2
  22. package/dist/render/index.js +32 -5
  23. package/dist/render/liquid.js +147 -7
  24. package/dist/render/mock-data.js +303 -0
  25. package/dist/render/templates/aurora/portfolio.liquid +192 -0
  26. package/dist/render/templates/aurora/project.liquid +260 -0
  27. package/dist/render/templates/aurora/session.liquid +223 -0
  28. package/dist/render/templates/aurora/styles.css +1184 -0
  29. package/dist/render/templates/bauhaus/portfolio.liquid +169 -0
  30. package/dist/render/templates/bauhaus/project.liquid +300 -0
  31. package/dist/render/templates/bauhaus/session.liquid +333 -0
  32. package/dist/render/templates/bauhaus/styles.css +1645 -0
  33. package/dist/render/templates/blueprint/portfolio.liquid +153 -0
  34. package/dist/render/templates/blueprint/project.liquid +286 -0
  35. package/dist/render/templates/blueprint/session.liquid +248 -0
  36. package/dist/render/templates/blueprint/styles.css +1289 -0
  37. package/dist/render/templates/canvas/portfolio.liquid +203 -0
  38. package/dist/render/templates/canvas/project.liquid +235 -0
  39. package/dist/render/templates/canvas/session.liquid +223 -0
  40. package/dist/render/templates/canvas/styles.css +1440 -0
  41. package/dist/render/templates/carbon/portfolio.liquid +160 -0
  42. package/dist/render/templates/carbon/project.liquid +249 -0
  43. package/dist/render/templates/carbon/session.liquid +190 -0
  44. package/dist/render/templates/carbon/styles.css +1097 -0
  45. package/dist/render/templates/chalk/portfolio.liquid +189 -0
  46. package/dist/render/templates/chalk/project.liquid +245 -0
  47. package/dist/render/templates/chalk/session.liquid +215 -0
  48. package/dist/render/templates/chalk/styles.css +1161 -0
  49. package/dist/render/templates/circuit/portfolio.liquid +152 -0
  50. package/dist/render/templates/circuit/project.liquid +247 -0
  51. package/dist/render/templates/circuit/session.liquid +205 -0
  52. package/dist/render/templates/circuit/styles.css +1409 -0
  53. package/dist/render/templates/cosmos/portfolio.liquid +222 -0
  54. package/dist/render/templates/cosmos/project.liquid +327 -0
  55. package/dist/render/templates/cosmos/session.liquid +239 -0
  56. package/dist/render/templates/cosmos/styles.css +1157 -0
  57. package/dist/render/templates/daylight/portfolio.liquid +207 -0
  58. package/dist/render/templates/daylight/project.liquid +229 -0
  59. package/dist/render/templates/daylight/session.liquid +219 -0
  60. package/dist/render/templates/daylight/styles.css +1315 -0
  61. package/dist/render/templates/editorial/portfolio.liquid +110 -0
  62. package/dist/render/templates/editorial/project.liquid +202 -0
  63. package/dist/render/templates/editorial/session.liquid +171 -0
  64. package/dist/render/templates/editorial/styles.css +826 -0
  65. package/dist/render/templates/ember/portfolio.liquid +306 -0
  66. package/dist/render/templates/ember/project.liquid +232 -0
  67. package/dist/render/templates/ember/session.liquid +202 -0
  68. package/dist/render/templates/ember/styles.css +1289 -0
  69. package/dist/render/templates/glacier/portfolio.liquid +261 -0
  70. package/dist/render/templates/glacier/project.liquid +288 -0
  71. package/dist/render/templates/glacier/session.liquid +217 -0
  72. package/dist/render/templates/glacier/styles.css +1204 -0
  73. package/dist/render/templates/grid/portfolio.liquid +255 -0
  74. package/dist/render/templates/grid/project.liquid +306 -0
  75. package/dist/render/templates/grid/session.liquid +260 -0
  76. package/dist/render/templates/grid/styles.css +1445 -0
  77. package/dist/render/templates/kinetic/portfolio.liquid +158 -0
  78. package/dist/render/templates/kinetic/project.liquid +242 -0
  79. package/dist/render/templates/kinetic/session.liquid +228 -0
  80. package/dist/render/templates/kinetic/styles.css +948 -0
  81. package/dist/render/templates/meridian/portfolio.liquid +243 -0
  82. package/dist/render/templates/meridian/project.liquid +376 -0
  83. package/dist/render/templates/meridian/session.liquid +298 -0
  84. package/dist/render/templates/meridian/styles.css +1375 -0
  85. package/dist/render/templates/minimal/portfolio.liquid +71 -0
  86. package/dist/render/templates/minimal/project.liquid +154 -0
  87. package/dist/render/templates/minimal/session.liquid +140 -0
  88. package/dist/render/templates/minimal/styles.css +529 -0
  89. package/dist/render/templates/mono/portfolio.liquid +281 -0
  90. package/dist/render/templates/mono/project.liquid +275 -0
  91. package/dist/render/templates/mono/session.liquid +276 -0
  92. package/dist/render/templates/mono/styles.css +1022 -0
  93. package/dist/render/templates/neon/portfolio.liquid +207 -0
  94. package/dist/render/templates/neon/project.liquid +225 -0
  95. package/dist/render/templates/neon/session.liquid +195 -0
  96. package/dist/render/templates/neon/styles.css +1271 -0
  97. package/dist/render/templates/noir/portfolio.liquid +137 -0
  98. package/dist/render/templates/noir/project.liquid +220 -0
  99. package/dist/render/templates/noir/session.liquid +241 -0
  100. package/dist/render/templates/noir/styles.css +1229 -0
  101. package/dist/render/templates/obsidian/portfolio.liquid +247 -0
  102. package/dist/render/templates/obsidian/project.liquid +280 -0
  103. package/dist/render/templates/obsidian/session.liquid +241 -0
  104. package/dist/render/templates/obsidian/styles.css +1407 -0
  105. package/dist/render/templates/paper/portfolio.liquid +257 -0
  106. package/dist/render/templates/paper/project.liquid +235 -0
  107. package/dist/render/templates/paper/session.liquid +271 -0
  108. package/dist/render/templates/paper/styles.css +1513 -0
  109. package/dist/render/templates/parallax/portfolio.liquid +295 -0
  110. package/dist/render/templates/parallax/project.liquid +275 -0
  111. package/dist/render/templates/parallax/session.liquid +295 -0
  112. package/dist/render/templates/parallax/styles.css +1880 -0
  113. package/dist/render/templates/parchment/portfolio.liquid +280 -0
  114. package/dist/render/templates/parchment/project.liquid +289 -0
  115. package/dist/render/templates/parchment/session.liquid +346 -0
  116. package/dist/render/templates/parchment/styles.css +1401 -0
  117. package/dist/render/templates/partials/_beats.liquid +16 -0
  118. package/dist/render/templates/partials/_breadcrumb.liquid +9 -0
  119. package/dist/render/templates/partials/_footer.liquid +7 -0
  120. package/dist/render/templates/partials/_growth-chart.liquid +7 -0
  121. package/dist/render/templates/partials/_key-decisions.liquid +20 -0
  122. package/dist/render/templates/partials/_links.liquid +16 -0
  123. package/dist/render/templates/partials/_narrative.liquid +8 -0
  124. package/dist/render/templates/partials/_phases.liquid +20 -0
  125. package/dist/render/templates/partials/_portfolio-header.liquid +20 -0
  126. package/dist/render/templates/partials/_portfolio-projects.liquid +16 -0
  127. package/dist/render/templates/partials/_portfolio-stats.liquid +19 -0
  128. package/dist/render/templates/partials/_qa.liquid +13 -0
  129. package/dist/render/templates/partials/_screenshot.liquid +15 -0
  130. package/dist/render/templates/partials/_session-cards.liquid +30 -0
  131. package/dist/render/templates/partials/_session-header.liquid +39 -0
  132. package/dist/render/templates/partials/_session-sidebar.liquid +30 -0
  133. package/dist/render/templates/partials/_skills.liquid +12 -0
  134. package/dist/render/templates/partials/_source-breakdown.liquid +22 -0
  135. package/dist/render/templates/partials/_stats.liquid +38 -0
  136. package/dist/render/templates/partials/_work-timeline.liquid +7 -0
  137. package/dist/render/templates/project.liquid +7 -4
  138. package/dist/render/templates/radar/portfolio.liquid +223 -0
  139. package/dist/render/templates/radar/project.liquid +278 -0
  140. package/dist/render/templates/radar/session.liquid +300 -0
  141. package/dist/render/templates/radar/styles.css +1055 -0
  142. package/dist/render/templates/showcase/portfolio.liquid +221 -0
  143. package/dist/render/templates/showcase/project.liquid +237 -0
  144. package/dist/render/templates/showcase/session.liquid +210 -0
  145. package/dist/render/templates/showcase/styles.css +1284 -0
  146. package/dist/render/templates/signal/portfolio.liquid +217 -0
  147. package/dist/render/templates/signal/project.liquid +278 -0
  148. package/dist/render/templates/signal/session.liquid +282 -0
  149. package/dist/render/templates/signal/styles.css +1401 -0
  150. package/dist/render/templates/strata/portfolio.liquid +180 -0
  151. package/dist/render/templates/strata/project.liquid +282 -0
  152. package/dist/render/templates/strata/session.liquid +261 -0
  153. package/dist/render/templates/strata/styles.css +1354 -0
  154. package/dist/render/templates/styles.css +1190 -0
  155. package/dist/render/templates/terminal/portfolio.liquid +102 -0
  156. package/dist/render/templates/terminal/project.liquid +161 -0
  157. package/dist/render/templates/terminal/session.liquid +145 -0
  158. package/dist/render/templates/terminal/styles.css +497 -0
  159. package/dist/render/templates/verdant/portfolio.liquid +321 -0
  160. package/dist/render/templates/verdant/project.liquid +309 -0
  161. package/dist/render/templates/verdant/session.liquid +237 -0
  162. package/dist/render/templates/verdant/styles.css +1261 -0
  163. package/dist/render/templates/zen/portfolio.liquid +124 -0
  164. package/dist/render/templates/zen/project.liquid +187 -0
  165. package/dist/render/templates/zen/session.liquid +203 -0
  166. package/dist/render/templates/zen/styles.css +1211 -0
  167. package/dist/render/templates.js +90 -0
  168. package/dist/routes/auth.js +7 -3
  169. package/dist/routes/context.js +17 -10
  170. package/dist/routes/delete.js +195 -0
  171. package/dist/routes/enhance.js +57 -40
  172. package/dist/routes/export.js +14 -4
  173. package/dist/routes/github.js +254 -0
  174. package/dist/routes/index.js +2 -0
  175. package/dist/routes/portfolio-render-data.js +160 -0
  176. package/dist/routes/preview.js +555 -108
  177. package/dist/routes/projects.js +61 -24
  178. package/dist/routes/publish.js +320 -31
  179. package/dist/routes/settings.js +194 -1
  180. package/dist/routes/sse.js +9 -0
  181. package/dist/search.js +6 -0
  182. package/dist/server.js +11 -3
  183. package/dist/settings.js +112 -9
  184. package/package.json +3 -4
  185. package/dist/public/assets/index-CC9G8EF1.js +0 -21
  186. package/dist/public/assets/index-Dalqz2mC.css +0 -1
package/dist/mount.js CHANGED
@@ -22003,7 +22003,9 @@
22003
22003
  ].join(" ");
22004
22004
  }
22005
22005
  var DEFAULT_MAX_CONCURRENT = 8;
22006
- function layoutSegments(segments, maxConcurrent = DEFAULT_MAX_CONCURRENT) {
22006
+ function layoutSegments(segments, maxConcurrent = DEFAULT_MAX_CONCURRENT, themeColors) {
22007
+ const _mainColor = themeColors?.main ?? MAIN_COLOR;
22008
+ const _textMuted = themeColors?.muted ?? TEXT_MUTED;
22007
22009
  const nodes = [];
22008
22010
  const tracks = [];
22009
22011
  const sessionRanges = [];
@@ -22019,7 +22021,7 @@
22019
22021
  for (const seg of segments) {
22020
22022
  if (seg.type === "gap") {
22021
22023
  const gapW = 72;
22022
- tracks.push({ path: `M ${cx} ${cY} L ${cx + gapW} ${cY}`, color: TEXT_MUTED, width: 1.5, dashed: true });
22024
+ tracks.push({ path: `M ${cx} ${cY} L ${cx + gapW} ${cY}`, color: _textMuted, width: 1.5, dashed: true });
22023
22025
  nodes.push({ kind: "gap", pos: { x: cx, y: cY + 16 }, label: formatGap(seg.durationMs), durationMs: seg.durationMs });
22024
22026
  bound(cY - 8, 40);
22025
22027
  cx += gapW + SEG_GAP;
@@ -22046,16 +22048,16 @@
22046
22048
  const waves = groupIntoWaves(visible, parentStartMs);
22047
22049
  const maxConcurrentInWave = Math.max(...waves.map((w2) => w2.children.length), 1);
22048
22050
  const gap = laneGap(maxConcurrentInWave);
22049
- const maxSpread = Math.min((maxConcurrentInWave - 1) * gap, 300);
22051
+ const maxSpread = Math.min((maxConcurrentInWave - 1) * gap, 120);
22050
22052
  const forkX = cx;
22051
22053
  const joinX = cx + w;
22052
22054
  const topLaneY = cY - maxSpread / 2;
22053
- const titleY = topLaneY - 32;
22055
+ const titleY = topLaneY - 16;
22054
22056
  const flatStartX = forkX + CURVE_CP * 2;
22055
- nodes.push({ kind: "label", pos: { x: flatStartX + 8, y: titleY }, title: truncate(s.title, MAX_TITLE), sub, timestamp: ts, color: MAIN_COLOR, above: true, session: s, tooltip });
22056
- bound(titleY - 4, 28);
22057
- nodes.push({ kind: "dot", pos: { x: forkX, y: cY }, color: MAIN_COLOR, size: "lg", tooltip });
22058
- tracks.push({ path: `M ${forkX} ${cY} L ${joinX} ${cY}`, color: MAIN_COLOR, width: 1.5 });
22057
+ nodes.push({ kind: "label", pos: { x: flatStartX + 8, y: titleY }, title: truncate(s.title, MAX_TITLE), sub, timestamp: ts, color: _mainColor, above: true, session: s, tooltip });
22058
+ bound(titleY - 4, 16);
22059
+ nodes.push({ kind: "dot", pos: { x: forkX, y: cY }, color: _mainColor, size: "lg", tooltip });
22060
+ tracks.push({ path: `M ${forkX} ${cY} L ${joinX} ${cY}`, color: _mainColor, width: 1.5 });
22059
22061
  for (const wave of waves) {
22060
22062
  const n = wave.children.length;
22061
22063
  const waveSpread = Math.min((n - 1) * gap, maxSpread);
@@ -22072,15 +22074,15 @@
22072
22074
  bound(laneY - 2, 4);
22073
22075
  });
22074
22076
  }
22075
- nodes.push({ kind: "dot", pos: { x: joinX, y: cY }, color: MAIN_COLOR, size: "lg", tooltip });
22077
+ nodes.push({ kind: "dot", pos: { x: joinX, y: cY }, color: _mainColor, size: "lg", tooltip });
22076
22078
  sessionRanges.push({ session: s, xStart: forkX, xEnd: joinX });
22077
22079
  cx = joinX + SEG_GAP;
22078
22080
  } else {
22079
- nodes.push({ kind: "label", pos: { x: cx + 14, y: cY - 28 }, title: truncate(s.title, MAX_TITLE), sub, timestamp: ts, color: MAIN_COLOR, above: true, session: s, tooltip });
22080
- bound(cY - 32, 28);
22081
- nodes.push({ kind: "dot", pos: { x: cx, y: cY }, color: MAIN_COLOR, size: "sm", tooltip });
22082
- nodes.push({ kind: "dot", pos: { x: cx + w, y: cY }, color: MAIN_COLOR, size: "sm", tooltip });
22083
- tracks.push({ path: `M ${cx} ${cY} L ${cx + w} ${cY}`, color: MAIN_COLOR, width: 3 });
22081
+ nodes.push({ kind: "label", pos: { x: cx + 14, y: cY - 16 }, title: truncate(s.title, MAX_TITLE), sub, timestamp: ts, color: _mainColor, above: true, session: s, tooltip });
22082
+ bound(cY - 20, 16);
22083
+ nodes.push({ kind: "dot", pos: { x: cx, y: cY }, color: _mainColor, size: "sm", tooltip });
22084
+ nodes.push({ kind: "dot", pos: { x: cx + w, y: cY }, color: _mainColor, size: "sm", tooltip });
22085
+ tracks.push({ path: `M ${cx} ${cY} L ${cx + w} ${cY}`, color: _mainColor, width: 3 });
22084
22086
  sessionRanges.push({ session: s, xStart: cx, xEnd: cx + w });
22085
22087
  cx += w + SEG_GAP;
22086
22088
  }
@@ -22124,12 +22126,12 @@
22124
22126
  const titleY = topAgentY - 32;
22125
22127
  const hasRoom = laneLabelRight[lane] === 0 || sXStart >= laneLabelRight[lane];
22126
22128
  if (hasRoom) {
22127
- nodes.push({ kind: "label", pos: { x: sXStart + 8, y: titleY }, title: truncate(s.title, MAX_TITLE), sub, timestamp: ts, color: MAIN_COLOR, above: true, session: s, tooltip });
22129
+ nodes.push({ kind: "label", pos: { x: sXStart + 8, y: titleY }, title: truncate(s.title, MAX_TITLE), sub, timestamp: ts, color: _mainColor, above: true, session: s, tooltip });
22128
22130
  laneLabelRight[lane] = sXStart + MIN_LABEL_GAP;
22129
22131
  }
22130
22132
  bound(titleY - 4, 28);
22131
- nodes.push({ kind: "dot", pos: { x: sXStart, y: trackY }, color: MAIN_COLOR, size: "lg", tooltip });
22132
- tracks.push({ path: `M ${sXStart} ${trackY} L ${sXEnd} ${trackY}`, color: MAIN_COLOR, width: 1.5 });
22133
+ nodes.push({ kind: "dot", pos: { x: sXStart, y: trackY }, color: _mainColor, size: "lg", tooltip });
22134
+ tracks.push({ path: `M ${sXStart} ${trackY} L ${sXEnd} ${trackY}`, color: _mainColor, width: 1.5 });
22133
22135
  const agentOpacity = agentLaneCount > 15 ? 0.4 : agentLaneCount > 8 ? 0.6 : 0.8;
22134
22136
  const agentWidth = agentLaneCount > 15 ? 1 : 1.5;
22135
22137
  agentVisible.forEach((kid) => {
@@ -22144,32 +22146,32 @@
22144
22146
  tracks.push({ path: bezierForkJoin(kidForkX, Math.min(adjustedJoinX, sXEnd), trackY, agentY), color, width: agentWidth, opacity: agentOpacity });
22145
22147
  bound(agentY - 2, 4);
22146
22148
  });
22147
- nodes.push({ kind: "dot", pos: { x: sXEnd, y: trackY }, color: MAIN_COLOR, size: "lg", tooltip });
22149
+ nodes.push({ kind: "dot", pos: { x: sXEnd, y: trackY }, color: _mainColor, size: "lg", tooltip });
22148
22150
  sessionRanges.push({ session: s, xStart: sXStart, xEnd: sXEnd });
22149
22151
  } else {
22150
22152
  const hasRoom = laneLabelRight[lane] === 0 || sXStart >= laneLabelRight[lane];
22151
22153
  if (hasRoom) {
22152
- nodes.push({ kind: "label", pos: { x: sXStart + 8, y: trackY - 28 }, title: truncate(s.title, MAX_TITLE), sub, timestamp: ts, color: MAIN_COLOR, above: true, session: s, tooltip });
22154
+ nodes.push({ kind: "label", pos: { x: sXStart + 8, y: trackY - 28 }, title: truncate(s.title, MAX_TITLE), sub, timestamp: ts, color: _mainColor, above: true, session: s, tooltip });
22153
22155
  laneLabelRight[lane] = sXStart + MIN_LABEL_GAP;
22154
22156
  }
22155
22157
  bound(trackY - 32, 28);
22156
- nodes.push({ kind: "dot", pos: { x: sXStart, y: trackY }, color: MAIN_COLOR, size: "sm", tooltip });
22157
- nodes.push({ kind: "dot", pos: { x: sXEnd, y: trackY }, color: MAIN_COLOR, size: "sm", tooltip });
22158
- tracks.push({ path: `M ${sXStart} ${trackY} L ${sXEnd} ${trackY}`, color: MAIN_COLOR, width: 3 });
22158
+ nodes.push({ kind: "dot", pos: { x: sXStart, y: trackY }, color: _mainColor, size: "sm", tooltip });
22159
+ nodes.push({ kind: "dot", pos: { x: sXEnd, y: trackY }, color: _mainColor, size: "sm", tooltip });
22160
+ tracks.push({ path: `M ${sXStart} ${trackY} L ${sXEnd} ${trackY}`, color: _mainColor, width: 3 });
22159
22161
  sessionRanges.push({ session: s, xStart: sXStart, xEnd: sXEnd });
22160
22162
  }
22161
22163
  bound(trackY - 4, 8);
22162
22164
  }
22163
22165
  if (hidden > 0) {
22164
22166
  const overflowY = cY + laneCount * dynamicTrackGap;
22165
- nodes.push({ kind: "label", pos: { x: segXStart + 8, y: overflowY }, title: `+${hidden} more sessions`, color: TEXT_MUTED, above: false });
22167
+ nodes.push({ kind: "label", pos: { x: segXStart + 8, y: overflowY }, title: `+${hidden} more sessions`, color: _textMuted, above: false });
22166
22168
  bound(overflowY, 16);
22167
22169
  }
22168
22170
  cx = segXEnd + SEG_GAP;
22169
22171
  }
22170
22172
  }
22171
22173
  const threadEnd = cx - SEG_GAP;
22172
- const pad = 36;
22174
+ const pad = 4;
22173
22175
  const yShift = -minY + pad;
22174
22176
  const totalH = maxY - minY + pad * 2;
22175
22177
  return {
@@ -22199,8 +22201,10 @@
22199
22201
  }
22200
22202
  return best;
22201
22203
  }
22202
- function Legend({ entry }) {
22204
+ function Legend({ entry, textSecondaryColor, textMutedColor }) {
22203
22205
  if (!entry || entry.agents.length === 0) return null;
22206
+ const _textSecondary = textSecondaryColor ?? TEXT_SECONDARY;
22207
+ const _textMuted = textMutedColor ?? TEXT_MUTED;
22204
22208
  const visible = entry.agents.slice(0, MAX_LEGEND_ROLES);
22205
22209
  const hiddenRoles = entry.agents.length - visible.length;
22206
22210
  const isLegendary = entry.totalAgents >= LEGENDARY_THRESHOLD;
@@ -22217,7 +22221,7 @@
22217
22221
  "LEGENDARY AGENTIC USE \u2014 ",
22218
22222
  entry.totalAgents,
22219
22223
  " agents:"
22220
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { fontSize: 10, color: TEXT_SECONDARY, fontWeight: 600, flexShrink: 0 }, children: [
22224
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { fontSize: 10, color: _textSecondary, fontWeight: 600, flexShrink: 0 }, children: [
22221
22225
  entry.totalAgents,
22222
22226
  " agents:"
22223
22227
  ] }),
@@ -22232,13 +22236,13 @@
22232
22236
  flexShrink: 0
22233
22237
  } }),
22234
22238
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontWeight: 600, color: a.color, letterSpacing: "0.03em" }, children: a.role.toUpperCase() }),
22235
- a.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { color: TEXT_MUTED }, children: [
22239
+ a.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { color: _textMuted }, children: [
22236
22240
  "\xD7",
22237
22241
  a.count
22238
22242
  ] }),
22239
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: TEXT_MUTED }, children: a.duration })
22243
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: _textMuted }, children: a.duration })
22240
22244
  ] }, a.role)),
22241
- hiddenRoles > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { color: TEXT_MUTED, fontStyle: "italic" }, children: [
22245
+ hiddenRoles > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { color: _textMuted, fontStyle: "italic" }, children: [
22242
22246
  "+",
22243
22247
  hiddenRoles,
22244
22248
  " more"
@@ -22279,14 +22283,20 @@
22279
22283
  ] })
22280
22284
  ] });
22281
22285
  }
22282
- function WorkTimeline({ sessions, onSessionClick, maxHeight }) {
22286
+ function WorkTimeline({ sessions, onSessionClick, maxHeight, accentColor, isDark }) {
22287
+ const mainColor = accentColor ?? (isDark ? "#f97316" : MAIN_COLOR);
22288
+ const threadColor = isDark ? "rgba(255,255,255,0.15)" : THREAD_COLOR;
22289
+ const textSecondary = isDark ? "rgba(255,255,255,0.65)" : TEXT_SECONDARY;
22290
+ const textMuted = isDark ? "rgba(255,255,255,0.4)" : TEXT_MUTED;
22291
+ const bgSurface = isDark ? "#111" : "#f8f9fb";
22283
22292
  const segments = (0, import_react.useMemo)(() => computeSegments(sessions), [sessions]);
22284
22293
  const [expanded, setExpanded] = (0, import_react.useState)(false);
22285
22294
  const [fullscreen, setFullscreen] = (0, import_react.useState)(false);
22286
22295
  const [playing, setPlaying] = (0, import_react.useState)(false);
22287
22296
  const playRef = (0, import_react.useRef)(null);
22288
22297
  const concurrentLimit = expanded ? 999 : DEFAULT_MAX_CONCURRENT;
22289
- const L = (0, import_react.useMemo)(() => layoutSegments(segments, concurrentLimit), [segments, concurrentLimit]);
22298
+ const themeColors = (0, import_react.useMemo)(() => ({ main: mainColor, muted: textMuted }), [mainColor, textMuted]);
22299
+ const L = (0, import_react.useMemo)(() => layoutSegments(segments, concurrentLimit, themeColors), [segments, concurrentLimit, themeColors]);
22290
22300
  const legendEntries = (0, import_react.useMemo)(() => buildLegendEntries(segments, L.sessionRanges), [segments, L.sessionRanges]);
22291
22301
  const scrollRef = (0, import_react.useRef)(null);
22292
22302
  const [hovered, setHovered] = (0, import_react.useState)(null);
@@ -22342,17 +22352,17 @@
22342
22352
  }, []);
22343
22353
  const clearHover = (0, import_react.useCallback)(() => setHovered(null), []);
22344
22354
  if (!sessions.length) {
22345
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-testid": "work-timeline-empty", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontFamily: FONT, fontSize: "0.8125rem", color: TEXT_SECONDARY }, children: "No sessions to display." }) });
22355
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { "data-testid": "work-timeline-empty", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontFamily: FONT, fontSize: "0.8125rem", color: textSecondary }, children: "No sessions to display." }) });
22346
22356
  }
22347
22357
  const hasAgents = legendEntries.some((e) => e.agents.length > 0);
22348
22358
  const btnStyle = (active) => ({
22349
22359
  padding: "3px 10px",
22350
22360
  fontSize: 10,
22351
22361
  fontWeight: 600,
22352
- border: `1px solid ${THREAD_COLOR}`,
22362
+ border: `1px solid ${threadColor}`,
22353
22363
  borderRadius: 4,
22354
- background: active ? MAIN_COLOR : "#fff",
22355
- color: active ? "#fff" : MAIN_COLOR,
22364
+ background: active ? mainColor : isDark ? "rgba(255,255,255,0.08)" : "#fff",
22365
+ color: active ? "#fff" : mainColor,
22356
22366
  cursor: "pointer",
22357
22367
  fontFamily: FONT,
22358
22368
  letterSpacing: "0.03em",
@@ -22360,7 +22370,7 @@
22360
22370
  });
22361
22371
  const timelineContent = /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
22362
22372
  /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }, children: [
22363
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, minWidth: 0 }, children: hasAgents && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Legend, { entry: focusedEntry }) }),
22373
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: 1, minWidth: 0 }, children: hasAgents && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Legend, { entry: focusedEntry, textSecondaryColor: textSecondary, textMutedColor: textMuted }) }),
22364
22374
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", gap: 6, flexShrink: 0 }, children: L.totalW > 600 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: togglePlay, style: btnStyle(playing), children: playing ? "PAUSE" : "PLAY" }) })
22365
22375
  ] }),
22366
22376
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -22378,7 +22388,7 @@
22378
22388
  y1: L.centerY,
22379
22389
  x2: L.threadEnd,
22380
22390
  y2: L.centerY,
22381
- stroke: THREAD_COLOR,
22391
+ stroke: threadColor,
22382
22392
  strokeWidth: 1.5
22383
22393
  }
22384
22394
  ),
@@ -22413,9 +22423,9 @@
22413
22423
  onMouseLeave: node.tooltip ? clearHover : void 0,
22414
22424
  children: [
22415
22425
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: 12, fontWeight: 700, color: node.color, letterSpacing: "0.01em", display: "block" }, children: node.title }),
22416
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { fontSize: 10, color: TEXT_MUTED, display: "flex", gap: 8, marginTop: 1 }, children: [
22426
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { fontSize: 10, color: textMuted, display: "flex", gap: 8, marginTop: 1 }, children: [
22417
22427
  node.sub && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: node.sub }),
22418
- node.timestamp && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: TEXT_SECONDARY }, children: node.timestamp })
22428
+ node.timestamp && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: textSecondary }, children: node.timestamp })
22419
22429
  ] })
22420
22430
  ]
22421
22431
  },
@@ -22456,7 +22466,7 @@
22456
22466
  alignItems: "center",
22457
22467
  justifyContent: "center",
22458
22468
  fontSize: 10,
22459
- color: TEXT_MUTED,
22469
+ color: textMuted,
22460
22470
  letterSpacing: "0.04em"
22461
22471
  }, children: node.label }, `g-${i}`);
22462
22472
  }
@@ -22472,7 +22482,7 @@
22472
22482
  position: "fixed",
22473
22483
  inset: 0,
22474
22484
  zIndex: 9998,
22475
- background: "#f8f9fb",
22485
+ background: bgSurface,
22476
22486
  display: "flex",
22477
22487
  flexDirection: "column",
22478
22488
  padding: "16px 24px"
@@ -22485,10 +22495,10 @@
22485
22495
  padding: "6px 14px",
22486
22496
  fontSize: 12,
22487
22497
  fontWeight: 700,
22488
- border: `1px solid ${THREAD_COLOR}`,
22498
+ border: `1px solid ${threadColor}`,
22489
22499
  borderRadius: 4,
22490
- background: "#fff",
22491
- color: MAIN_COLOR,
22500
+ background: isDark ? "rgba(255,255,255,0.08)" : "#fff",
22501
+ color: mainColor,
22492
22502
  cursor: "pointer",
22493
22503
  fontFamily: FONT
22494
22504
  }, children: "Close" }),
@@ -22504,7 +22514,7 @@
22504
22514
  left: 0,
22505
22515
  right: 0,
22506
22516
  height: 64,
22507
- background: "linear-gradient(transparent, #f8f9fb)",
22517
+ background: `linear-gradient(transparent, ${bgSurface})`,
22508
22518
  display: "flex",
22509
22519
  alignItems: "flex-end",
22510
22520
  justifyContent: "center",
@@ -22516,14 +22526,14 @@
22516
22526
  padding: "5px 16px",
22517
22527
  fontSize: 11,
22518
22528
  fontWeight: 700,
22519
- border: `1px solid ${THREAD_COLOR}`,
22529
+ border: `1px solid ${threadColor}`,
22520
22530
  borderRadius: 4,
22521
- background: "#fff",
22522
- color: MAIN_COLOR,
22531
+ background: isDark ? "rgba(255,255,255,0.08)" : "#fff",
22532
+ color: mainColor,
22523
22533
  cursor: "pointer",
22524
22534
  fontFamily: FONT,
22525
22535
  letterSpacing: "0.03em",
22526
- boxShadow: "0 2px 8px rgba(0,0,0,0.08)"
22536
+ boxShadow: isDark ? "0 2px 8px rgba(0,0,0,0.3)" : "0 2px 8px rgba(0,0,0,0.08)"
22527
22537
  }, children: "EXPAND TIMELINE" }) })
22528
22538
  ] });
22529
22539
  }
@@ -22531,6 +22541,7 @@
22531
22541
  // src/GrowthChart.tsx
22532
22542
  var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
22533
22543
  var FONT2 = "'IBM Plex Mono', monospace";
22544
+ var PRIMARY = "#084471";
22534
22545
  var GREEN = "#16a34a";
22535
22546
  var RED = "#dc2626";
22536
22547
  var TEXT_MUTED2 = "#9ca3af";
@@ -22633,10 +22644,31 @@
22633
22644
  }
22634
22645
  return dividers;
22635
22646
  }
22636
- function GrowthChart({ sessions, totalLoc, totalFiles, keyMoments, onSessionClick }) {
22647
+ function GrowthChart({ sessions, totalLoc, totalFiles, keyMoments, onSessionClick, accentColor, isDark, dualPositive = true }) {
22648
+ const colors = isDark ? {
22649
+ textMuted: "rgba(255,255,255,0.4)",
22650
+ textSecondary: "rgba(255,255,255,0.65)",
22651
+ grid: "rgba(255,255,255,0.06)",
22652
+ text: "#fafafa",
22653
+ green: GREEN,
22654
+ red: RED,
22655
+ accent: accentColor || "#f97316",
22656
+ dotStroke: "rgba(0,0,0,0.3)",
22657
+ border: "rgba(255,255,255,0.06)"
22658
+ } : {
22659
+ textMuted: TEXT_MUTED2,
22660
+ textSecondary: TEXT_SECONDARY2,
22661
+ grid: GRID_COLOR,
22662
+ text: "#191c1e",
22663
+ green: GREEN,
22664
+ red: RED,
22665
+ accent: accentColor || PRIMARY,
22666
+ dotStroke: "#fff",
22667
+ border: GRID_COLOR
22668
+ };
22637
22669
  const points = buildTimeSeries(sessions);
22638
22670
  if (points.length === 0) {
22639
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontFamily: FONT2, fontSize: "0.75rem", color: TEXT_SECONDARY2, padding: 16 }, children: "No session data available for growth chart." });
22671
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontFamily: FONT2, fontSize: "0.75rem", color: colors.textSecondary, padding: 16 }, children: "No session data available for growth chart." });
22640
22672
  }
22641
22673
  const { visualTimes, totalVisualTime } = compressTime(points);
22642
22674
  const momentMap = /* @__PURE__ */ new Map();
@@ -22646,26 +22678,49 @@
22646
22678
  const totalAdded = points[points.length - 1].cumulativeAdded;
22647
22679
  const totalDeleted = points[points.length - 1].cumulativeDeleted;
22648
22680
  const hasDeleteData = totalDeleted > 0;
22649
- const maxVal = Math.max(totalAdded, 1);
22650
- const ticks = computeAxisTicks(maxVal);
22651
- const axisMax = ticks[ticks.length - 1] || 1;
22652
- const deleteTicks = hasDeleteData ? computeAxisTicks(totalDeleted) : [];
22653
- const deleteAxisMax = hasDeleteData ? deleteTicks[deleteTicks.length - 1] || 1 : 0;
22654
22681
  const baseWidth = 700;
22655
- const svgWidth = Math.max(baseWidth, Math.round(totalVisualTime / 6e4 * 0.8) + 120);
22682
+ const timeBasedWidth = Math.round(totalVisualTime / 6e4 * 0.8) + 120;
22683
+ const pointBasedWidth = points.length * 12 + 120;
22684
+ const svgWidth = Math.max(baseWidth, timeBasedWidth, pointBasedWidth);
22656
22685
  const padLeft = 48;
22657
22686
  const padRight = 16;
22658
22687
  const padTop = 24;
22659
- const addChartH = 140;
22660
- const delChartH = hasDeleteData ? 50 : 0;
22661
- const gapH = hasDeleteData ? 2 : 0;
22662
22688
  const padBottom = 36;
22663
- const svgHeight = padTop + addChartH + gapH + delChartH + padBottom;
22664
- const baseline = padTop + addChartH;
22665
22689
  const maxVT = totalVisualTime || 1;
22666
22690
  const toX = (vt) => padLeft + vt / maxVT * (svgWidth - padLeft - padRight);
22667
- const toYAdd = (val) => baseline - val / axisMax * addChartH;
22668
- const toYDel = (val) => baseline + gapH + val / deleteAxisMax * delChartH;
22691
+ let addChartH, delChartH, gapH, svgHeight;
22692
+ let baseline;
22693
+ let axisMax, deleteAxisMax;
22694
+ let ticks, deleteTicks;
22695
+ let toYAdd;
22696
+ let toYDel;
22697
+ if (dualPositive) {
22698
+ const maxVal = Math.max(totalAdded, totalDeleted, 1);
22699
+ ticks = computeAxisTicks(maxVal);
22700
+ axisMax = ticks[ticks.length - 1] || 1;
22701
+ deleteTicks = [];
22702
+ deleteAxisMax = 0;
22703
+ addChartH = 160;
22704
+ delChartH = 0;
22705
+ gapH = 0;
22706
+ svgHeight = padTop + addChartH + padBottom;
22707
+ baseline = padTop + addChartH;
22708
+ toYAdd = (val) => baseline - val / axisMax * addChartH;
22709
+ toYDel = toYAdd;
22710
+ } else {
22711
+ const maxVal = Math.max(totalAdded, 1);
22712
+ ticks = computeAxisTicks(maxVal);
22713
+ axisMax = ticks[ticks.length - 1] || 1;
22714
+ deleteTicks = hasDeleteData ? computeAxisTicks(totalDeleted) : [];
22715
+ deleteAxisMax = hasDeleteData ? deleteTicks[deleteTicks.length - 1] || 1 : 0;
22716
+ addChartH = 140;
22717
+ delChartH = hasDeleteData ? 50 : 0;
22718
+ gapH = hasDeleteData ? 2 : 0;
22719
+ svgHeight = padTop + addChartH + gapH + delChartH + padBottom;
22720
+ baseline = padTop + addChartH;
22721
+ toYAdd = (val) => baseline - val / axisMax * addChartH;
22722
+ toYDel = (val) => baseline + gapH + val / deleteAxisMax * delChartH;
22723
+ }
22669
22724
  const addCoords = points.map((p, i) => ({ x: toX(visualTimes[i]), y: toYAdd(p.cumulativeAdded) }));
22670
22725
  const delCoords = hasDeleteData ? points.map((p, i) => ({ x: toX(visualTimes[i]), y: toYDel(p.cumulativeDeleted) })) : [];
22671
22726
  function stepPath(coords) {
@@ -22680,7 +22735,7 @@
22680
22735
  const addPath = stepPath(addCoords);
22681
22736
  const addAreaPath = addPath + ` L${addCoords[addCoords.length - 1].x.toFixed(1)},${baseline} L${addCoords[0].x.toFixed(1)},${baseline} Z`;
22682
22737
  const delPath = hasDeleteData ? stepPath(delCoords) : "";
22683
- const delAreaPath = hasDeleteData ? delPath + ` L${delCoords[delCoords.length - 1].x.toFixed(1)},${baseline + gapH} L${delCoords[0].x.toFixed(1)},${baseline + gapH} Z` : "";
22738
+ const delAreaPath = hasDeleteData ? delPath + ` L${delCoords[delCoords.length - 1].x.toFixed(1)},${baseline + (dualPositive ? 0 : gapH)} L${delCoords[0].x.toFixed(1)},${baseline + (dualPositive ? 0 : gapH)} Z` : "";
22684
22739
  const MIN_LABEL_GAP2 = 90;
22685
22740
  const labelledIndices = /* @__PURE__ */ new Set();
22686
22741
  let lastLabelX = -Infinity;
@@ -22701,20 +22756,20 @@
22701
22756
  justifyContent: "space-between",
22702
22757
  alignItems: "baseline",
22703
22758
  padding: "8px 12px",
22704
- borderBottom: `1px solid ${GRID_COLOR}`,
22759
+ borderBottom: `1px solid ${colors.border}`,
22705
22760
  fontFamily: FONT2
22706
22761
  }, children: [
22707
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: 10, fontWeight: 700, color: TEXT_MUTED2, textTransform: "uppercase", letterSpacing: "0.06em" }, children: "Code Changes Over Time" }),
22762
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: 10, fontWeight: 700, color: colors.textMuted, textTransform: "uppercase", letterSpacing: "0.06em" }, children: dualPositive ? "Lines Changed" : "Code Changes Over Time" }),
22708
22763
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 16, fontSize: 11, fontWeight: 600 }, children: [
22709
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: GREEN }, children: [
22764
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: dualPositive ? colors.accent : colors.green }, children: [
22710
22765
  "+",
22711
22766
  formatLoc(totalAdded)
22712
22767
  ] }),
22713
- hasDeleteData && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: RED }, children: [
22768
+ hasDeleteData && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: dualPositive ? colors.textSecondary : colors.red }, children: [
22714
22769
  "-",
22715
22770
  formatLoc(totalDeleted)
22716
22771
  ] }),
22717
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: "#191c1e" }, children: [
22772
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: { color: colors.text }, children: [
22718
22773
  formatLoc(totalLoc),
22719
22774
  " total"
22720
22775
  ] })
@@ -22731,12 +22786,12 @@
22731
22786
  children: [
22732
22787
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("defs", { children: [
22733
22788
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("linearGradient", { id: "addGrad", x1: "0", y1: "0", x2: "0", y2: "1", children: [
22734
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: "0%", stopColor: GREEN, stopOpacity: 0.12 }),
22735
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: "100%", stopColor: GREEN, stopOpacity: 0.02 })
22789
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: "0%", stopColor: dualPositive ? colors.accent : colors.green, stopOpacity: 0.12 }),
22790
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: "100%", stopColor: dualPositive ? colors.accent : colors.green, stopOpacity: 0.02 })
22736
22791
  ] }),
22737
22792
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("linearGradient", { id: "delGrad", x1: "0", y1: "0", x2: "0", y2: "1", children: [
22738
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: "0%", stopColor: RED, stopOpacity: 0.02 }),
22739
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: "100%", stopColor: RED, stopOpacity: 0.1 })
22793
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: "0%", stopColor: dualPositive ? colors.accent : colors.red, stopOpacity: dualPositive ? 0.12 : 0.02 }),
22794
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: "100%", stopColor: dualPositive ? colors.accent : colors.red, stopOpacity: dualPositive ? 0.02 : 0.1 })
22740
22795
  ] })
22741
22796
  ] }),
22742
22797
  ticks.map((tick) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
@@ -22747,7 +22802,7 @@
22747
22802
  y1: toYAdd(tick),
22748
22803
  x2: svgWidth - padRight,
22749
22804
  y2: toYAdd(tick),
22750
- stroke: GRID_COLOR,
22805
+ stroke: colors.grid,
22751
22806
  strokeWidth: "0.5",
22752
22807
  strokeDasharray: "4,4"
22753
22808
  }
@@ -22760,8 +22815,8 @@
22760
22815
  textAnchor: "end",
22761
22816
  fontFamily: FONT2,
22762
22817
  fontSize: "8",
22763
- fill: TEXT_MUTED2,
22764
- children: tick === 0 ? "" : `+${formatLocAxis(tick)}`
22818
+ fill: colors.textMuted,
22819
+ children: tick === 0 ? "" : dualPositive ? formatLocAxis(tick) : `+${formatLocAxis(tick)}`
22765
22820
  }
22766
22821
  )
22767
22822
  ] }, `ya-${tick}`)),
@@ -22772,7 +22827,7 @@
22772
22827
  y1: baseline,
22773
22828
  x2: svgWidth - padRight,
22774
22829
  y2: baseline,
22775
- stroke: GRID_COLOR,
22830
+ stroke: colors.grid,
22776
22831
  strokeWidth: "1"
22777
22832
  }
22778
22833
  ),
@@ -22784,12 +22839,12 @@
22784
22839
  textAnchor: "end",
22785
22840
  fontFamily: FONT2,
22786
22841
  fontSize: "8",
22787
- fill: TEXT_SECONDARY2,
22842
+ fill: colors.textSecondary,
22788
22843
  fontWeight: "600",
22789
22844
  children: "0"
22790
22845
  }
22791
22846
  ),
22792
- hasDeleteData && deleteTicks.filter((t) => t > 0).map((tick) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
22847
+ !dualPositive && hasDeleteData && deleteTicks.filter((t) => t > 0).map((tick) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { children: [
22793
22848
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
22794
22849
  "line",
22795
22850
  {
@@ -22797,7 +22852,7 @@
22797
22852
  y1: toYDel(tick),
22798
22853
  x2: svgWidth - padRight,
22799
22854
  y2: toYDel(tick),
22800
- stroke: GRID_COLOR,
22855
+ stroke: colors.grid,
22801
22856
  strokeWidth: "0.5",
22802
22857
  strokeDasharray: "4,4"
22803
22858
  }
@@ -22810,7 +22865,7 @@
22810
22865
  textAnchor: "end",
22811
22866
  fontFamily: FONT2,
22812
22867
  fontSize: "8",
22813
- fill: TEXT_MUTED2,
22868
+ fill: colors.textMuted,
22814
22869
  children: `-${formatLocAxis(tick)}`
22815
22870
  }
22816
22871
  )
@@ -22822,17 +22877,17 @@
22822
22877
  y1: padTop,
22823
22878
  x2: div.x,
22824
22879
  y2: baseline + gapH + delChartH,
22825
- stroke: GRID_COLOR,
22880
+ stroke: colors.grid,
22826
22881
  strokeWidth: "0.5",
22827
22882
  strokeDasharray: "2,4"
22828
22883
  },
22829
22884
  `m-${i}`
22830
22885
  )),
22831
22886
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: addAreaPath, fill: "url(#addGrad)" }),
22832
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: addPath, fill: "none", stroke: GREEN, strokeWidth: "1.5" }),
22887
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: addPath, fill: "none", stroke: dualPositive ? colors.accent : colors.green, strokeWidth: "1.5" }),
22833
22888
  hasDeleteData && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
22834
22889
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: delAreaPath, fill: "url(#delGrad)" }),
22835
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: delPath, fill: "none", stroke: RED, strokeWidth: "1.5" })
22890
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: delPath, fill: "none", stroke: dualPositive ? `${colors.accent}66` : colors.red, strokeWidth: "1.5" })
22836
22891
  ] }),
22837
22892
  points.map((p, i) => {
22838
22893
  const x = toX(visualTimes[i]);
@@ -22850,12 +22905,12 @@
22850
22905
  cx: x,
22851
22906
  cy: toYAdd(p.cumulativeAdded),
22852
22907
  r: "5",
22853
- fill: GREEN,
22854
- stroke: "#fff",
22908
+ fill: dualPositive ? colors.accent : colors.green,
22909
+ stroke: colors.dotStroke,
22855
22910
  strokeWidth: "2"
22856
22911
  }
22857
- ) : showLabel ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: x, cy: toYAdd(p.cumulativeAdded), r: "3", fill: GREEN }) : null,
22858
- hasDeleteData && p.cumulativeDeleted > 0 && showLabel && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: x, cy: toYDel(p.cumulativeDeleted), r: "2.5", fill: RED }),
22912
+ ) : showLabel ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: x, cy: toYAdd(p.cumulativeAdded), r: "3", fill: dualPositive ? colors.accent : colors.green }) : null,
22913
+ hasDeleteData && p.cumulativeDeleted > 0 && showLabel && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: x, cy: toYDel(p.cumulativeDeleted), r: "2.5", fill: dualPositive ? `${colors.accent}66` : colors.red }),
22859
22914
  isKey && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
22860
22915
  "text",
22861
22916
  {
@@ -22864,7 +22919,7 @@
22864
22919
  textAnchor: "middle",
22865
22920
  fontFamily: FONT2,
22866
22921
  fontSize: "8",
22867
- fill: TEXT_SECONDARY2,
22922
+ fill: colors.textSecondary,
22868
22923
  children: momentMap.get(p.sessionId)
22869
22924
  }
22870
22925
  ),
@@ -22876,7 +22931,7 @@
22876
22931
  textAnchor: "middle",
22877
22932
  fontFamily: FONT2,
22878
22933
  fontSize: "8",
22879
- fill: TEXT_MUTED2,
22934
+ fill: colors.textMuted,
22880
22935
  children: new Date(p.dateMs).toLocaleDateString("en-US", { month: "short", day: "numeric" })
22881
22936
  }
22882
22937
  )
@@ -22892,35 +22947,35 @@
22892
22947
  display: "flex",
22893
22948
  gap: 24,
22894
22949
  padding: "8px 12px",
22895
- borderTop: `1px solid ${GRID_COLOR}`,
22950
+ borderTop: `1px solid ${colors.border}`,
22896
22951
  fontFamily: FONT2,
22897
22952
  fontSize: 10
22898
22953
  }, children: [
22899
22954
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
22900
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { fontSize: 14, fontWeight: 700, color: GREEN }, children: [
22955
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { fontSize: 14, fontWeight: 700, color: dualPositive ? colors.accent : colors.green }, children: [
22901
22956
  "+",
22902
22957
  formatLoc(totalAdded)
22903
22958
  ] }),
22904
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: TEXT_MUTED2, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Added" })
22959
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: colors.textMuted, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Added" })
22905
22960
  ] }),
22906
22961
  hasDeleteData && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
22907
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { fontSize: 14, fontWeight: 700, color: RED }, children: [
22962
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { fontSize: 14, fontWeight: 700, color: dualPositive ? colors.textSecondary : colors.red }, children: [
22908
22963
  "-",
22909
22964
  formatLoc(totalDeleted)
22910
22965
  ] }),
22911
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: TEXT_MUTED2, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Deleted" })
22966
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: colors.textMuted, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Deleted" })
22912
22967
  ] }),
22913
22968
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
22914
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 14, fontWeight: 700, color: "#191c1e" }, children: formatLoc(totalLoc) }),
22915
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: TEXT_MUTED2, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Total LOC" })
22969
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 14, fontWeight: 700, color: colors.text }, children: formatLoc(totalLoc) }),
22970
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: colors.textMuted, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Total LOC" })
22916
22971
  ] }),
22917
22972
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
22918
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 14, fontWeight: 700, color: "#191c1e" }, children: totalFiles }),
22919
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: TEXT_MUTED2, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Files" })
22973
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 14, fontWeight: 700, color: colors.text }, children: totalFiles }),
22974
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: colors.textMuted, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Files" })
22920
22975
  ] }),
22921
22976
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
22922
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 14, fontWeight: 700, color: "#191c1e" }, children: points.length }),
22923
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: TEXT_MUTED2, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Sessions" })
22977
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 14, fontWeight: 700, color: colors.text }, children: points.length }),
22978
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { color: colors.textMuted, textTransform: "uppercase", letterSpacing: "0.06em", fontWeight: 600 }, children: "Sessions" })
22924
22979
  ] })
22925
22980
  ] })
22926
22981
  ] });
@@ -23063,6 +23118,21 @@
23063
23118
  return [];
23064
23119
  }
23065
23120
  }
23121
+ function detectTheme() {
23122
+ const wrapper = document.querySelector("[data-accent]");
23123
+ if (wrapper) {
23124
+ return {
23125
+ isDark: wrapper.getAttribute("data-mode") === "dark",
23126
+ accentColor: wrapper.getAttribute("data-accent") || void 0
23127
+ };
23128
+ }
23129
+ const bg = window.getComputedStyle(document.body).backgroundColor;
23130
+ const match = bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
23131
+ if (!match) return { isDark: false };
23132
+ const [, r, g, b] = match.map(Number);
23133
+ const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
23134
+ return { isDark: luminance < 0.5 };
23135
+ }
23066
23136
  var allSessions = /* @__PURE__ */ new Map();
23067
23137
  var showOverlay = null;
23068
23138
  function OverlayRoot({ sessions }) {
@@ -23093,6 +23163,7 @@
23093
23163
  );
23094
23164
  }
23095
23165
  function mountVisualizations() {
23166
+ const { isDark, accentColor } = detectTheme();
23096
23167
  document.querySelectorAll("[data-work-timeline]").forEach((el) => {
23097
23168
  const sessions = parseSessions(el);
23098
23169
  if (sessions.length === 0) return;
@@ -23101,6 +23172,8 @@
23101
23172
  import_react3.default.createElement(WorkTimeline, {
23102
23173
  sessions,
23103
23174
  maxHeight: 300,
23175
+ isDark,
23176
+ accentColor,
23104
23177
  onSessionClick: (session) => {
23105
23178
  if (showOverlay) showOverlay(session);
23106
23179
  }
@@ -23118,6 +23191,8 @@
23118
23191
  sessions,
23119
23192
  totalLoc,
23120
23193
  totalFiles,
23194
+ isDark,
23195
+ accentColor,
23121
23196
  onSessionClick: (session) => {
23122
23197
  if (showOverlay) showOverlay(session);
23123
23198
  }
@@ -23136,6 +23211,9 @@
23136
23211
  }
23137
23212
  });
23138
23213
  });
23214
+ mountCounterAnimations();
23215
+ mountScrollReveals();
23216
+ mountBarAnimations();
23139
23217
  if (allSessions.size > 0) {
23140
23218
  const overlayEl = document.createElement("div");
23141
23219
  overlayEl.id = "heyiam-overlay-root";
@@ -23145,6 +23223,126 @@
23145
23223
  );
23146
23224
  }
23147
23225
  }
23226
+ var REDUCED_MOTION = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
23227
+ function mountCounterAnimations() {
23228
+ const selectors = [
23229
+ ".counter[data-target]",
23230
+ ".stat-value[data-target]",
23231
+ ".stat-number[data-target]",
23232
+ ".value[data-target]",
23233
+ "[data-count-to]",
23234
+ ".dl-stat-number[data-target]",
23235
+ "[data-animate][data-target]"
23236
+ ];
23237
+ const els = document.querySelectorAll(selectors.join(","));
23238
+ if (els.length === 0) return;
23239
+ function formatNumber(n, fmt) {
23240
+ if (fmt === "comma") return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
23241
+ if (fmt === "decimal" || fmt === "1") return n.toFixed(1);
23242
+ return Math.round(n).toString();
23243
+ }
23244
+ function animateCounter(el) {
23245
+ const target = parseFloat(el.getAttribute("data-target") ?? el.getAttribute("data-count-to") ?? "0");
23246
+ const fmt = el.getAttribute("data-format") ?? "";
23247
+ const suffix = el.getAttribute("data-suffix") ?? "";
23248
+ const isDecimal = fmt === "decimal" || fmt === "1";
23249
+ if (REDUCED_MOTION) {
23250
+ el.textContent = formatNumber(target, fmt) + suffix;
23251
+ return;
23252
+ }
23253
+ const duration = 1200;
23254
+ let startTime = null;
23255
+ function step(timestamp) {
23256
+ if (!startTime) startTime = timestamp;
23257
+ const progress = Math.min((timestamp - startTime) / duration, 1);
23258
+ const eased = 1 - Math.pow(1 - progress, 3);
23259
+ const current = isDecimal ? eased * target : Math.round(eased * target);
23260
+ el.textContent = formatNumber(current, fmt) + suffix;
23261
+ if (progress < 1) requestAnimationFrame(step);
23262
+ }
23263
+ requestAnimationFrame(step);
23264
+ }
23265
+ const observer = new IntersectionObserver((entries) => {
23266
+ for (const entry of entries) {
23267
+ if (entry.isIntersecting) {
23268
+ animateCounter(entry.target);
23269
+ observer.unobserve(entry.target);
23270
+ }
23271
+ }
23272
+ }, { threshold: 0.3 });
23273
+ els.forEach((el) => observer.observe(el));
23274
+ }
23275
+ function mountScrollReveals() {
23276
+ const selectors = [
23277
+ ".fade-in",
23278
+ ".fade-up",
23279
+ ".reveal",
23280
+ ".section-reveal",
23281
+ ".sc-section",
23282
+ ".sc-stagger",
23283
+ ".mono-section",
23284
+ ".ember-section",
23285
+ ".radar-section",
23286
+ ".cos-section",
23287
+ ".strata-layer",
23288
+ ".dl-bounce",
23289
+ ".vd-section",
23290
+ ".fly-left",
23291
+ ".fly-right",
23292
+ ".phase-item",
23293
+ ".growth-line",
23294
+ ".growth-area",
23295
+ ".growth-dot",
23296
+ ".session-card",
23297
+ ".beat-item",
23298
+ ".qa-card"
23299
+ ];
23300
+ document.querySelectorAll(".parallax").forEach((el) => {
23301
+ el.classList.add("parallax--mounted");
23302
+ });
23303
+ const els = document.querySelectorAll(selectors.join(","));
23304
+ if (els.length === 0) return;
23305
+ if (REDUCED_MOTION) {
23306
+ els.forEach((el) => el.classList.add("visible"));
23307
+ return;
23308
+ }
23309
+ const observer = new IntersectionObserver((entries) => {
23310
+ for (const entry of entries) {
23311
+ if (entry.isIntersecting) {
23312
+ entry.target.classList.add("visible");
23313
+ observer.unobserve(entry.target);
23314
+ }
23315
+ }
23316
+ }, { threshold: 0.15 });
23317
+ els.forEach((el) => observer.observe(el));
23318
+ }
23319
+ function mountBarAnimations() {
23320
+ const els = document.querySelectorAll(
23321
+ "[data-width], [data-bar-width], [data-target-width]"
23322
+ );
23323
+ if (els.length === 0) return;
23324
+ if (REDUCED_MOTION) {
23325
+ els.forEach((el) => {
23326
+ const w = el.getAttribute("data-width") ?? el.getAttribute("data-bar-width") ?? el.getAttribute("data-target-width") ?? "";
23327
+ if (w) el.style.width = w.includes("%") ? w : `${w}%`;
23328
+ });
23329
+ return;
23330
+ }
23331
+ const observer = new IntersectionObserver((entries) => {
23332
+ for (const entry of entries) {
23333
+ if (entry.isIntersecting) {
23334
+ const el = entry.target;
23335
+ const w = el.getAttribute("data-width") ?? el.getAttribute("data-bar-width") ?? el.getAttribute("data-target-width") ?? "";
23336
+ if (w) {
23337
+ el.style.transition = "width 0.6s ease-out";
23338
+ el.style.width = w.includes("%") ? w : `${w}%`;
23339
+ }
23340
+ observer.unobserve(el);
23341
+ }
23342
+ }
23343
+ }, { threshold: 0.2 });
23344
+ els.forEach((el) => observer.observe(el));
23345
+ }
23148
23346
  if (typeof document !== "undefined") {
23149
23347
  if (document.readyState === "loading") {
23150
23348
  document.addEventListener("DOMContentLoaded", mountVisualizations);