@tangle-network/charts 0.21.20 → 0.21.22

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.
@@ -26,14 +26,15 @@
26
26
  --fw-kind-tool: var(--tone-cyan-icon);
27
27
  --fw-neutral-bar: color-mix(in oklab, var(--fw-text) 15%, var(--fw-surface));
28
28
  --fw-hatch: color-mix(in oklab, var(--fw-text) 22%, transparent);
29
- /* Root agent neutral, then five of Brand's categorical hues, each 3:1 or more against the card in both modes. No warm hue
30
- among the agents (amber is kept for the slowest and red for failure), and neighbours alternate cool and warm-leaning. */
29
+ /* Bar identity, not status: the root neutral, then an identity ring at one lightness and a moderate chroma, so no lane
30
+ outshouts another (critique P0 #3, round 29: Brand's icon-strength teal, pink and violet "compete", lime and pink read
31
+ olive and maroon). Blue, violet, pink, cyan, slate: no green, teal, lime, amber or red, so no lane is mistaken for a status. */
31
32
  --fw-h0: var(--chart-muted);
32
- --fw-h1: var(--tone-blue-icon);
33
- --fw-h2: var(--tone-teal-icon);
34
- --fw-h3: var(--tone-pink-icon);
35
- --fw-h4: var(--tone-violet-icon);
36
- --fw-h5: var(--tone-lime-icon);
33
+ --fw-h1: light-dark(oklch(0.55 0.11 255), oklch(0.70 0.11 255));
34
+ --fw-h2: light-dark(oklch(0.55 0.11 300), oklch(0.70 0.11 300));
35
+ --fw-h3: light-dark(oklch(0.55 0.11 335), oklch(0.70 0.11 335));
36
+ --fw-h4: light-dark(oklch(0.55 0.11 215), oklch(0.70 0.11 215));
37
+ --fw-h5: light-dark(oklch(0.55 0.03 255), oklch(0.70 0.03 255));
37
38
  --fw-ease: cubic-bezier(.2, .8, .2, 1);
38
39
  /* Bar height = row height - 16, so a centered bar sits 8 px from the row edge: 20 px in a 36 px step row. */
39
40
  --fw-bar-h: 20px;
@@ -82,7 +83,7 @@
82
83
  .fw-root .fw-title-line { display: flex; align-items: center; gap: 8px; min-width: 0; }
83
84
  .fw-root .fw-title-glyph { display: inline-flex; color: var(--fw-accent); }
84
85
  .fw-root .fw-title { font-size: 14px; line-height: 20px; font-weight: 600; letter-spacing: -.005em; white-space: nowrap; }
85
- .fw-root .fw-state { display: inline-flex; align-items: center; gap: 8px; height: 20px; padding: 0 8px; border-radius: var(--radius-pill); font-size: 12px; font-weight: 600; color: var(--fw-muted); background: var(--fw-well); flex-shrink: 0; }
86
+ .fw-root .fw-state { display: inline-flex; align-items: center; gap: 8px; height: 20px; padding: 0 8px; border-radius: var(--radius-pill); font-size: 14px; font-weight: 600; color: var(--fw-muted); background: var(--fw-well); flex-shrink: 0; }
86
87
  .fw-root .fw-state::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
87
88
  .fw-root .fw-state-live { color: var(--fw-accent); background: color-mix(in oklab, var(--fw-accent) 12%, transparent); }
88
89
  .fw-root .fw-state-live::before { animation: fw-pulse 1.6s var(--fw-ease) infinite; }
@@ -103,16 +104,16 @@
103
104
  .fw-root .fw-summary { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); border-bottom: 1px solid var(--fw-border); }
104
105
  .fw-root .fw-summary > div { padding: 12px 16px; min-width: 0; }
105
106
  .fw-root .fw-summary > div + div { border-left: 1px solid var(--fw-border); }
106
- .fw-root .fw-summary dt { font-size: 12px; line-height: 16px; color: var(--fw-muted); }
107
+ .fw-root .fw-summary dt { font-size: 14px; line-height: 18px; color: var(--fw-muted); }
107
108
  .fw-root .fw-value { margin-top: 4px; font-size: 18px; line-height: 24px; font-weight: 600; letter-spacing: -.01em; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
108
109
  .fw-root .fw-has-errors .fw-value { color: var(--fw-failed); }
109
110
 
110
111
  /* Axis */
111
- .fw-root .fw-axis { display: grid; grid-template-columns: var(--fw-label-col) minmax(0, 1fr); height: 32px; color: var(--fw-muted); font-size: 12px; }
112
+ .fw-root .fw-axis { display: grid; grid-template-columns: var(--fw-label-col) minmax(0, 1fr); height: 32px; color: var(--fw-muted); font-size: 14px; }
112
113
  .fw-root .fw-axis-top { border-bottom: 1px solid var(--fw-border); }
113
114
  .fw-root .fw-axis-label { position: relative; display: flex; align-items: center; gap: 8px; padding: 0 12px 0 16px; border-right: 1px solid var(--fw-border); min-width: 0; }
114
115
  .fw-root .fw-branch-controls { margin-left: auto; display: flex; gap: 4px; }
115
- .fw-root .fw-text-button { appearance: none; border: 0; background: transparent; height: 24px; padding: 0 8px; border-radius: var(--radius-sm); font-size: 12px; color: var(--fw-muted); cursor: pointer; white-space: nowrap; }
116
+ .fw-root .fw-text-button { appearance: none; border: 0; background: transparent; height: 24px; padding: 0 8px; border-radius: var(--radius-sm); font-size: 14px; color: var(--fw-muted); cursor: pointer; white-space: nowrap; }
116
117
  .fw-root .fw-text-button:hover { background: var(--fw-hover); color: var(--fw-text); }
117
118
  .fw-root .fw-resize { position: absolute; top: 0; right: -4px; width: 8px; height: 100%; cursor: col-resize; z-index: 2; }
118
119
  .fw-root .fw-resize:hover, .fw-root .fw-resize:focus-visible { background: linear-gradient(90deg, transparent 3px, var(--fw-accent) 3px 5px, transparent 5px); outline: 0; }
@@ -141,14 +142,14 @@
141
142
  .fw-root .fw-pause { top: 0; bottom: 0; background: color-mix(in oklab, var(--fw-text) 4%, transparent); border-inline: 1px dashed color-mix(in oklab, var(--fw-text) 18%, transparent); }
142
143
  .fw-root .fw-pause-mark { bottom: 3px; height: 6px; border-radius: 2px; cursor: help;
143
144
  background: repeating-linear-gradient(-45deg, var(--fw-hatch) 0 1px, transparent 1px 4px); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-text) 18%, transparent); }
144
- .fw-root .fw-marker-label { position: absolute; top: 2px; left: 3px; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 4px; border-radius: var(--radius-tag); font-size: 12px; line-height: 16px; color: var(--fw-marker); background: var(--fw-surface); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-marker) 40%, transparent); }
145
+ .fw-root .fw-marker-label { position: absolute; top: 2px; left: 3px; max-width: 160px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 4px; border-radius: var(--radius-tag); font-size: 14px; line-height: 18px; color: var(--fw-marker); background: var(--fw-surface); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-marker) 40%, transparent); }
145
146
  .fw-root .fw-marker-label-left { left: auto; right: 3px; }
146
147
  .fw-root .fw-marker[data-tone="warn"], .fw-root .fw-event[data-tone="warn"] { --fw-marker: var(--fw-amber); }
147
148
  /* The event track: one dot per marker on the axis; click or N/P moves the cursor there. */
148
149
  .fw-root .fw-event { --fw-marker: var(--fw-muted); position: absolute; bottom: 2px; width: 8px; height: 8px; margin-left: -4px; padding: 0; border: 0; border-radius: 50%; background: var(--fw-marker); box-shadow: 0 0 0 2px var(--fw-surface); cursor: pointer; z-index: 4; left: calc(var(--fw-pad) + (var(--s) - var(--fw-v0)) * var(--fw-k) * 1px); }
149
150
  .fw-root .fw-event[data-tone="ok"] { --fw-marker: var(--fw-ok); }
150
151
  .fw-root .fw-event[aria-pressed="true"] { box-shadow: 0 0 0 2px var(--fw-surface), 0 0 0 4px var(--fw-marker); }
151
- .fw-root .fw-event-label { position: absolute; bottom: 14px; z-index: 5; transform: translateX(-50%); left: calc(var(--fw-pad) + (var(--s) - var(--fw-v0)) * var(--fw-k) * 1px); padding: 0 8px; border-radius: var(--radius-tag); background: var(--fw-surface); box-shadow: inset 0 0 0 1px var(--fw-border); color: var(--fw-text); font-size: 12px; line-height: 20px; white-space: nowrap; pointer-events: none; }
152
+ .fw-root .fw-event-label { position: absolute; bottom: 14px; z-index: 5; transform: translateX(-50%); left: calc(var(--fw-pad) + (var(--s) - var(--fw-v0)) * var(--fw-k) * 1px); padding: 0 8px; border-radius: var(--radius-tag); background: var(--fw-surface); box-shadow: inset 0 0 0 1px var(--fw-border); color: var(--fw-text); font-size: 14px; line-height: 20px; white-space: nowrap; pointer-events: none; }
152
153
  .fw-root .fw-event[data-tone="failed"] { --fw-marker: var(--fw-failed); }
153
154
  .fw-root .fw-event:hover, .fw-root .fw-event:focus-visible { transform: scale(1.4); outline: 0; }
154
155
  .fw-root .fw-cursor { position: absolute; top: 0; bottom: 0; width: 1px; background: color-mix(in oklab, var(--fw-text) 70%, transparent); left: calc(var(--fw-pad) + (var(--fw-t) - var(--fw-v0)) * var(--fw-k) * 1px); }
@@ -187,7 +188,7 @@
187
188
  .fw-root .fw-detail { color: var(--fw-muted); overflow: hidden; min-width: 0; display: inline-flex; align-items: center; gap: 4px; max-width: 100%; }
188
189
  .fw-root .fw-detail-icon { display: inline-flex; }
189
190
  .fw-root .fw-detail-icon :is(svg, img) { width: 12px; height: 12px; }
190
- .fw-root .fw-count { flex-shrink: 0; height: 18px; padding: 0 8px; border-radius: var(--radius-pill); background: var(--fw-well); border: 1px solid var(--fw-border); color: var(--fw-muted); font-size: 12px; line-height: 16px; font-variant-numeric: tabular-nums; }
191
+ .fw-root .fw-count { flex-shrink: 0; height: 18px; padding: 0 8px; border-radius: var(--radius-pill); background: var(--fw-well); border: 1px solid var(--fw-border); color: var(--fw-muted); font-size: 14px; line-height: 18px; font-variant-numeric: tabular-nums; }
191
192
  .fw-root .fw-alert { display: inline-flex; color: var(--fw-failed); flex-shrink: 0; }
192
193
  .fw-root .fw-alert svg { width: 13px; height: 13px; }
193
194
  .fw-root .fw-spinner { width: 10px; height: 10px; border-radius: 50%; border: 1.5px solid color-mix(in oklab, var(--fw-accent) 30%, transparent); border-top-color: var(--fw-accent); animation: fw-spin .8s linear infinite; flex-shrink: 0; }
@@ -197,14 +198,16 @@
197
198
  .fw-root .fw-view-agents .fw-names { flex-direction: column; align-items: flex-start; gap: 0; }
198
199
  .fw-root .fw-view-agents .fw-span-name { font-weight: 600; line-height: 18px; }
199
200
  /* One 16 px line that wraps its last parts out of sight: when the line is full a count drops whole, never "48 …". */
200
- .fw-root .fw-view-agents .fw-subtitle { display: flex; align-items: center; column-gap: 4px; height: 16px; overflow: hidden; max-width: 100%; min-width: 0; color: var(--fw-muted); font-size: 12px; line-height: 16px; }
201
+ .fw-root .fw-view-agents .fw-subtitle { display: flex; align-items: center; column-gap: 4px; height: 18px; overflow: hidden; max-width: 100%; min-width: 0; color: var(--fw-muted); font-size: 14px; line-height: 18px; }
201
202
  .fw-root .fw-view-agents .fw-subtitle-extra { flex: none; white-space: nowrap; }
202
203
  /* Only the tail wraps, so the first part is always on its line and shrinks with an ellipsis; later parts wrap out of sight. */
203
- .fw-root .fw-view-agents .fw-subtitle-tail { display: flex; flex-wrap: wrap; column-gap: 4px; height: 16px; overflow: hidden; min-width: 0; flex: 0 1 auto; }
204
+ .fw-root .fw-view-agents .fw-subtitle-tail { display: flex; flex-wrap: wrap; column-gap: 4px; height: 18px; overflow: hidden; min-width: 0; flex: 0 1 auto; }
204
205
  .fw-root .fw-view-agents .fw-subtitle-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
205
206
  .fw-root .fw-view-agents .fw-detail-icon { flex: none; width: 16px; height: 16px; align-items: center; justify-content: center; overflow: hidden; }
206
- .fw-root .fw-view-agents .fw-detail { font-size: 12px; line-height: 16px; }
207
+ .fw-root .fw-view-agents .fw-detail { font-size: 14px; line-height: 18px; }
207
208
  .fw-root .fw-agent-dot { flex: 0 0 8px; width: 8px; height: 8px; border-radius: 50%; background: var(--line, var(--fw-muted)); }
209
+ /* The dot is outcome only (critique P0 #3): an agent with no recorded outcome gets a hollow ring, never its lane hue. */
210
+ .fw-root .fw-row:not([data-outcome]) .fw-agent-dot:not([data-outcome]) { background: transparent; box-shadow: inset 0 0 0 1.5px var(--fw-muted); }
208
211
 
209
212
  /* Lanes and marks */
210
213
  .fw-root .fw-lane { position: relative; overflow: hidden; min-width: 0; }
@@ -265,20 +268,20 @@
265
268
  .fw-root [data-outcome="failed"], .fw-root [data-outcome="failed"] [data-tone] { --tone: var(--fw-failed); }
266
269
  .fw-root [data-outcome="warn"], .fw-root [data-outcome="warn"] [data-tone] { --tone: var(--fw-amber); }
267
270
  .fw-root [data-outcome="neutral"], .fw-root [data-outcome="neutral"] [data-tone] { --tone: var(--fw-muted); }
268
- .fw-root .fw-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 8px 0 0; padding: 0; list-style: none; color: var(--fw-muted); font-size: 12px; line-height: 16px; }
271
+ .fw-root .fw-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin: 8px 0 0; padding: 0; list-style: none; color: var(--fw-muted); font-size: 14px; line-height: 18px; }
269
272
  .fw-root .fw-legend li { display: inline-flex; align-items: center; gap: 8px; }
270
273
  .fw-root .fw-legends { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 24px; margin-top: 8px; }
271
274
  .fw-root .fw-legends .fw-legend { margin: 0; }
272
275
  .fw-root .fw-kinds { margin: 0; padding: 0; justify-content: flex-start; color: var(--fw-muted); }
273
276
  .fw-root .fw-kinds .fw-swatch-model { width: 12px; height: 8px; border-radius: 2px; background: var(--fw-kind-model); }
274
277
  /* With per-agent hues the key shows kind as shade, as the bars do: darker for a model call, lighter for a tool call. */
275
- .fw-root.fw-fill-agent .fw-kinds .fw-swatch-model { background: light-dark(oklch(0.50 0 0), oklch(0.72 0 0)); }
276
- .fw-root.fw-fill-agent .fw-kinds .fw-swatch-tool { background: light-dark(oklch(0.80 0 0), oklch(0.46 0 0)); }
278
+ .fw-root.fw-fill-agent .fw-kinds .fw-swatch-model { background: light-dark(oklch(0.50 0 0), oklch(0.82 0 0)); }
279
+ .fw-root.fw-fill-agent .fw-kinds .fw-swatch-tool { background: light-dark(oklch(0.80 0 0), oklch(0.64 0 0)); }
277
280
  .fw-root .fw-kinds .fw-swatch-tool { width: 12px; height: 8px; border-radius: 2px; background: var(--fw-kind-tool); }
278
281
  .fw-root .fw-kinds .fw-swatch-wait { width: 12px; height: 8px; border-radius: 2px; background: color-mix(in oklab, var(--fw-text) 12%, transparent); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-text) 18%, transparent); }
279
282
  .fw-root .fw-kinds .fw-swatch-handoff { width: 10px; height: 8px; border-left: 1.5px solid var(--fw-muted); border-bottom: 1.5px solid var(--fw-muted); border-bottom-left-radius: 3px; }
280
283
  .fw-root .fw-description { margin: 0; color: var(--fw-muted); font-size: 14px; line-height: 20px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
281
- .fw-root .fw-legend .fw-swatch { width: 12px; height: 8px; border-radius: 2px; background: var(--fill); box-shadow: inset 0 0 0 1px var(--line); }
284
+ .fw-root .fw-legend .fw-swatch { width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
282
285
  .fw-root .fw-legend b { color: var(--fw-text); font-weight: 600; font-variant-numeric: tabular-nums; }
283
286
  .fw-root .fw-legend .fw-swatch-step { display: inline-grid; place-items: center; width: 12px; height: 12px; border-radius: 3px; background: var(--fw-well); color: var(--fw-failed); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-failed) 50%, transparent); }
284
287
  .fw-root .fw-legend .fw-swatch-step svg { width: 8px; height: 8px; }
@@ -293,17 +296,18 @@
293
296
  .fw-root:is(.fw-fill-muted, .fw-fill-outcome) .fw-view-agents .fw-seg-tool { background: var(--fw-kind-tool); box-shadow: none; }
294
297
  /* Per-agent hues: a step's kind is a fixed lightness on its agent's hue, the same for every hue, so kind reads by lightness
295
298
  against the surface and never contradicts the key (critique P0 #4: dark tool steps were lighter than model steps, and the
296
- step varied with hue). Model is the stronger step on either surface; chroma is capped at 0.10, never raised, so a neutral (the root's grey) stays
299
+ step varied with hue). On dark both steps are light pastels, model 0.82 and tool 0.64: round 27's pastel dark fills scored
300
+ 39/252, and the critique's darker 0.72/0.46 read muddy to round 29's judges. Model is the stronger step on either surface; chroma is capped at 0.10, never raised, so a neutral (the root's grey) stays
297
301
  neutral instead of taking a red cast from its undefined hue. */
298
- .fw-root.fw-fill-agent .fw-view-agents .fw-seg-model { background: light-dark(oklch(from var(--tone) 0.50 min(c, 0.10) h), oklch(from var(--tone) 0.72 min(c, 0.10) h)); box-shadow: none; }
299
- .fw-root.fw-fill-agent .fw-view-agents :is(.fw-seg-tool, .fw-seg-failed) { background: light-dark(oklch(from var(--tone) 0.80 min(c, 0.10) h), oklch(from var(--tone) 0.46 min(c, 0.10) h)); box-shadow: none; }
302
+ .fw-root.fw-fill-agent .fw-view-agents .fw-seg-model { background: light-dark(oklch(from var(--tone) 0.50 min(c, 0.10) h), oklch(from var(--tone) 0.82 min(c, 0.10) h)); box-shadow: none; }
303
+ .fw-root.fw-fill-agent .fw-view-agents :is(.fw-seg-tool, .fw-seg-failed) { background: light-dark(oklch(from var(--tone) 0.80 min(c, 0.10) h), oklch(from var(--tone) 0.64 min(c, 0.10) h)); box-shadow: none; }
300
304
  /* A failed turn is still the agent's work: it keeps the agent's hue, and the red cross on the ending turn says it failed. */
301
305
  .fw-root.fw-fill-agent .fw-view-agents .fw-seg-failed { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--fw-failed) 55%, transparent); }
302
- .fw-root .fw-view-agents .fw-seg { container-type: inline-size; justify-content: flex-start; font-size: 12px; line-height: 16px; white-space: nowrap; color: var(--fw-seg-ink); }
303
- /* Label ink holds 4.5:1 on its fill: the model step is dark on light and bright on dark, the tool step the reverse, so ink flips
304
- with it: page-light on L 0.50 and L 0.46, page-dark on L 0.72 and L 0.80. */
306
+ .fw-root .fw-view-agents .fw-seg { container-type: inline-size; justify-content: flex-start; font-size: 14px; line-height: 18px; white-space: nowrap; color: var(--fw-seg-ink); }
307
+ /* Label ink holds 4.5:1 on its fill: page-light on the dark light-theme model step (L 0.50), page-dark on every other step
308
+ (light tool 0.80, dark pastels 0.82 and 0.64). */
305
309
  .fw-root .fw-view-agents .fw-seg-model { --fw-seg-ink: light-dark(var(--fw-surface), hsl(var(--hsl-background))); }
306
- .fw-root .fw-view-agents :is(.fw-seg-tool, .fw-seg-failed) { --fw-seg-ink: var(--fw-text); }
310
+ .fw-root .fw-view-agents :is(.fw-seg-tool, .fw-seg-failed) { --fw-seg-ink: light-dark(var(--fw-text), hsl(var(--hsl-background))); }
307
311
  .fw-root .fw-view-agents .fw-seg > * { pointer-events: none; }
308
312
  /* One line, 6 px in from each end; a part that does not fit whole wraps to the hidden second line, so trailing parts drop first. */
309
313
  .fw-root .fw-seg-label { flex: 1; min-width: 0; height: 16px; margin: 0 6px; display: flex; flex-wrap: wrap; align-items: center; column-gap: 4px; overflow: hidden; }
@@ -329,9 +333,9 @@
329
333
  .fw-root .fw-end { z-index: 2; display: inline-flex; align-items: center; gap: 8px; top: calc(50% + var(--fw-bar-shift) - var(--fw-bar-h) / 2); height: var(--fw-bar-h);
330
334
  left: min(calc(var(--x0) + max(var(--w), 3px) + 4px), calc(100% - var(--fw-end-w, 0px) - 4px)); padding: 0 4px; border-radius: var(--radius-tag);
331
335
  background: linear-gradient(var(--fw-tint, transparent) 0 0), var(--fw-surface); white-space: nowrap; pointer-events: none; }
332
- .fw-root .fw-duration { font-size: 12px; color: var(--fw-muted); font-variant-numeric: tabular-nums; }
336
+ .fw-root .fw-duration { font-size: 14px; color: var(--fw-muted); font-variant-numeric: tabular-nums; }
333
337
  .fw-root .fw-k-failed ~ .fw-end .fw-duration { color: var(--fw-failed); }
334
- .fw-root .fw-badge { height: 18px; padding: 0 8px; border-radius: var(--radius-pill); font-size: 12px; line-height: 16px; font-weight: 600; color: var(--fw-amber); background: color-mix(in oklab, var(--fw-amber) 13%, transparent); border: 1px solid color-mix(in oklab, var(--fw-amber) 28%, transparent); }
338
+ .fw-root .fw-badge { height: 18px; padding: 0 8px; border-radius: var(--radius-pill); font-size: 14px; line-height: 18px; font-weight: 600; color: var(--fw-amber); background: color-mix(in oklab, var(--fw-amber) 13%, transparent); border: 1px solid color-mix(in oklab, var(--fw-amber) 28%, transparent); }
335
339
 
336
340
  /* Handoff elbows: 1.5 px stroke, 6 px radius, a 5 px dot where the handoff leaves its sender. */
337
341
  /* Under the rows (which follow it), so end labels and badges always sit above the connectors. */
@@ -365,13 +369,13 @@
365
369
  /* A hover card never covers the next mark: only a pinned card (a dialog) takes the pointer. */
366
370
  .fw-root .fw-card[role="tooltip"] { pointer-events: none; }
367
371
  .fw-root .fw-card-above .fw-card { transform: translateY(-100%); animation-name: fw-arrive-above; }
368
- .fw-root .fw-card-agent { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; font-size: 12px; font-weight: 600; }
372
+ .fw-root .fw-card-agent { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; font-size: 14px; font-weight: 600; }
369
373
  .fw-root .fw-card-agent .fw-agent-dot { align-self: center; }
370
374
  .fw-root .fw-card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
371
375
  .fw-root .fw-card-head .fw-icon-tile { flex-basis: 28px; width: 28px; height: 28px; border-radius: var(--radius-md); }
372
376
  .fw-root .fw-card-head .fw-icon-tile :is(svg, img) { width: 16px; height: 16px; }
373
377
  .fw-root .fw-card-name { flex: 1; min-width: 0; font-size: 14px; line-height: 20px; font-weight: 600; overflow-wrap: anywhere; }
374
- .fw-root .fw-pill { flex-shrink: 0; height: 20px; padding: 0 8px; border-radius: var(--radius-pill); font-size: 12px; line-height: 20px; font-weight: 600; }
378
+ .fw-root .fw-pill { flex-shrink: 0; height: 20px; padding: 0 8px; border-radius: var(--radius-pill); font-size: 14px; line-height: 20px; font-weight: 600; }
375
379
  .fw-root .fw-pill-done { color: var(--fw-ok); background: color-mix(in oklab, var(--fw-ok) 13%, transparent); }
376
380
  .fw-root .fw-pill-running { color: var(--fw-accent); background: color-mix(in oklab, var(--fw-accent) 13%, transparent); }
377
381
  .fw-root .fw-pill-failed { color: var(--fw-failed); background: color-mix(in oklab, var(--fw-failed) 13%, transparent); }
@@ -379,9 +383,9 @@
379
383
  .fw-root .fw-icon-button:hover:not(:disabled) { background: var(--fw-hover); color: var(--fw-text); }
380
384
  .fw-root .fw-card-close { width: 20px; height: 20px; margin-right: -4px; }
381
385
  /* The card's table: label and value on one line each, every value with its unit; a tool breakdown sits under its total. */
382
- .fw-root .fw-card-table { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 16px; padding-top: 8px; border-top: 1px solid var(--fw-border); font-size: 12px; line-height: 16px; }
386
+ .fw-root .fw-card-table { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 6px 16px; padding-top: 8px; border-top: 1px solid var(--fw-border); font-size: 14px; line-height: 18px; }
383
387
  .fw-root .fw-card-table > div { display: contents; }
384
- .fw-root .fw-card-table dt, .fw-root .fw-card-label { font-size: 12px; line-height: 16px; color: var(--fw-muted); }
388
+ .fw-root .fw-card-table dt, .fw-root .fw-card-label { font-size: 14px; line-height: 18px; color: var(--fw-muted); }
385
389
  .fw-root .fw-card-table dd { min-width: 0; font-weight: 500; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
386
390
  /* A value of several parts wraps between parts, never inside one ("4.0M" / "cached"). */
387
391
  .fw-root .fw-card-parts { display: flex; flex-wrap: wrap; column-gap: 4px; }
@@ -395,7 +399,7 @@
395
399
  .fw-root .fw-card-compact .fw-card-agent { font-size: 14px; line-height: 20px; }
396
400
  .fw-root .fw-card-who { min-width: 0; flex: 1; overflow: hidden; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
397
401
  .fw-root .fw-pill-outcome { color: var(--line); background: color-mix(in oklab, var(--tone) 16%, transparent); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--tone) 35%, transparent); }
398
- .fw-root .fw-card-step { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--fw-border); color: var(--fw-muted); font-size: 12px; line-height: 16px; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
402
+ .fw-root .fw-card-step { margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--fw-border); color: var(--fw-muted); font-size: 14px; line-height: 18px; font-variant-numeric: tabular-nums; overflow-wrap: anywhere; }
399
403
  .fw-root .fw-card-result { margin-top: 8px; font-size: 14px; line-height: 20px; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
400
404
  .fw-root .fw-card-text p { margin-top: 4px; color: var(--fw-text); overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
401
405
 
@@ -3411,7 +3411,7 @@ function Segment({ mark, events, agentView, ending }) {
3411
3411
  className: "fw-seg-name",
3412
3412
  children: name
3413
3413
  }),
3414
- mark.count > 1 && /* @__PURE__ */ jsxs("span", {
3414
+ mark.count > 1 && name && /* @__PURE__ */ jsxs("span", {
3415
3415
  className: "fw-seg-chip",
3416
3416
  children: ["×", mark.count]
3417
3417
  }),
@@ -3586,11 +3586,6 @@ const FlowRow = memo(function FlowRow(props) {
3586
3586
  "aria-label": `${row.descendants} hidden steps`,
3587
3587
  children: ["+", row.descendants]
3588
3588
  }),
3589
- family && !props.expanded && /* @__PURE__ */ jsxs("span", {
3590
- className: "fw-count",
3591
- "aria-label": `${row.descendants} agents folded`,
3592
- children: ["+", row.descendants]
3593
- }),
3594
3589
  !row.ok && !agentView && /* @__PURE__ */ jsx("span", {
3595
3590
  className: "fw-alert",
3596
3591
  children: /* @__PURE__ */ jsx(AlertGlyph, { label: "failed" })
@@ -3661,8 +3656,9 @@ const FlowRow = memo(function FlowRow(props) {
3661
3656
  });
3662
3657
  }, (a, b) => a.row === b.row && a.view === b.view && a.top === b.top && a.collapsed === b.collapsed && a.searching === b.searching && a.slowest === b.slowest && a.costliest === b.costliest && a.critical === b.critical && a.matched === b.matched && a.active === b.active && a.focusable === b.focusable && a.selected === b.selected && a.sticky === b.sticky && a.motion === b.motion && a.renderIcon === b.renderIcon && a.fillByAgent === b.fillByAgent && a.sharedDetail === b.sharedDetail && a.sharedOutcome === b.sharedOutcome && a.expanded === b.expanded && (a.clockMs === b.clockMs || !open(a.row, a.clockMs) && !open(b.row, b.clockMs)));
3663
3658
  /** An elbow connector between two rows at one moment, drawn in the row's tone; appears when the clock reaches it. */
3664
- function LinkMark({ link, rowHeight, hot }) {
3665
- const upper = Math.min(link.from, link.to), lower = Math.max(link.from, link.to);
3659
+ /** `short`: only the last row of the connector, an elbow into the row it reaches. */
3660
+ function LinkMark({ link, rowHeight, hot, short }) {
3661
+ const lower = Math.max(link.from, link.to), upper = short ? Math.max(Math.min(link.from, link.to), lower - 1) : Math.min(link.from, link.to);
3666
3662
  const style = {
3667
3663
  ...at(link.atMs, link.atMs),
3668
3664
  top: upper * rowHeight + rowHeight / 2 + 5,
@@ -4192,11 +4188,16 @@ function FlowBody(props) {
4192
4188
  children: [/* @__PURE__ */ jsx("div", {
4193
4189
  className: "fw-links",
4194
4190
  "aria-hidden": true,
4195
- children: links.filter((link) => Math.max(link.from, link.to) >= first && Math.min(link.from, link.to) <= last).map((link) => /* @__PURE__ */ jsx(LinkMark, {
4196
- link,
4197
- rowHeight,
4198
- hot: props.focusId !== void 0 && (rows[link.from]?.id === props.focusId || rows[link.to]?.id === props.focusId)
4199
- }, link.id))
4191
+ children: links.filter((link) => Math.max(link.from, link.to) >= first && Math.min(link.from, link.to) <= last).map((link) => {
4192
+ const hot = props.focusId !== void 0 && (rows[link.from]?.id === props.focusId || rows[link.to]?.id === props.focusId);
4193
+ if (view === "agents" && !hot && link.id.startsWith("r-")) return null;
4194
+ return /* @__PURE__ */ jsx(LinkMark, {
4195
+ link,
4196
+ rowHeight,
4197
+ hot,
4198
+ short: view === "agents" && !hot
4199
+ }, link.id);
4200
+ })
4200
4201
  }), rows.slice(first, last).map((item, offset) => row(item, first + offset))]
4201
4202
  }), rows.length === 0 && /* @__PURE__ */ jsx("p", {
4202
4203
  role: "status",
@@ -4866,15 +4867,17 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
4866
4867
  if (!box) return;
4867
4868
  const hostTop = root.current.getBoundingClientRect().top;
4868
4869
  const room = {
4869
- above: hostTop + card.anchorTop - 16,
4870
+ above: card.anchorTop - 16,
4870
4871
  below: globalThis.innerHeight - (hostTop + card.anchorBottom) - 16
4871
4872
  };
4872
4873
  const preferred = card.above ? room.above : room.below;
4873
4874
  const other = card.above ? room.below : room.above;
4875
+ const above = box.height <= preferred || box.height > other && preferred >= other ? card.above : !card.above;
4874
4876
  setCard({
4875
4877
  ...card,
4876
4878
  fitted: true,
4877
- above: box.height <= preferred || box.height > other && preferred >= other ? card.above : !card.above
4879
+ above,
4880
+ top: above ? Math.max(8, card.anchorTop - 8 - box.height) : card.anchorBottom + 8
4878
4881
  });
4879
4882
  }, [card, cardId]);
4880
4883
  latest.current.inspect = (target, element, x) => {
@@ -5150,7 +5153,7 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
5150
5153
  onCollapseAll: () => setCollapsed(new Set(rows.filter((row) => row.hasChildren).map((row) => row.id)))
5151
5154
  }),
5152
5155
  card && cardRow && /* @__PURE__ */ jsx("div", {
5153
- className: `fw-card-anchor${card.above ? " fw-card-above" : ""}`,
5156
+ className: `fw-card-anchor${card.above && card.top === void 0 ? " fw-card-above" : ""}`,
5154
5157
  onPointerEnter: () => clearTimeout(hideTimer.current),
5155
5158
  onPointerLeave: card.pinned ? void 0 : leave,
5156
5159
  children: /* @__PURE__ */ jsx(SpanCard, {
@@ -5159,7 +5162,7 @@ function FlowWaterfall({ trace, live, startedAt, label = "Trace waterfall", defa
5159
5162
  agent: cardAgent,
5160
5163
  clockMs,
5161
5164
  left: card.left,
5162
- top: card.above ? card.anchorTop - 8 : card.anchorBottom + 8,
5165
+ top: card.top ?? (card.above ? card.anchorTop - 8 : card.anchorBottom + 8),
5163
5166
  pinned: card.pinned,
5164
5167
  onClose: closeCard,
5165
5168
  renderIcon,
@@ -1,30 +1,30 @@
1
1
  /* Shared live charts. Consumers may set --chart-live-* tokens on an ancestor. Sizes are px on the 12/14 type scale and a
2
2
  4 px grid, so a host's font size never rescales them. */
3
- .ov-empty { margin: 0; color: var(--chart-live-faint, #777); font-size: 12px; }
3
+ .ov-empty { margin: 0; color: var(--chart-live-faint, #777); font-size: 14px; }
4
4
  .ov-plot { position: relative; min-width: 0; }
5
5
  .ov-plot svg { display: block; overflow: visible; }
6
6
  line.ov-gridline { stroke: color-mix(in srgb, var(--chart-live-faint, #777) 22%, transparent); stroke-width: 1; }
7
7
  .ov-axis { fill: var(--chart-live-muted, #666); font: 12px/16px var(--chart-live-font-mono, monospace); font-variant-numeric: tabular-nums; }
8
8
  .ov-crosshair { stroke: var(--chart-live-faint, #777); stroke-dasharray: 3 3; }
9
- .ov-tip { position: absolute; z-index: 4; display: grid; gap: 4px; min-width: 160px; max-width: 240px; padding: 8px 12px; background: var(--chart-live-raised, #fff); border: 1px solid var(--chart-live-border, #aaa); border-radius: 8px; box-shadow: 0 10px 24px -12px #000; font-size: 12px; line-height: 16px; pointer-events: none; }
9
+ .ov-tip { position: absolute; z-index: 4; display: grid; gap: 4px; min-width: 160px; max-width: 240px; padding: 8px 12px; background: var(--chart-live-raised, #fff); border: 1px solid var(--chart-live-border, #aaa); border-radius: 8px; box-shadow: 0 10px 24px -12px #000; font-size: 14px; line-height: 20px; pointer-events: none; }
10
10
  .ov-tip-line { display: grid; grid-template-columns: auto 1fr auto; gap: 8px; align-items: center; color: var(--chart-live-muted, #666); }
11
11
  .ov-tip-line b { color: var(--chart-live-fg, #222); font-variant-numeric: tabular-nums; }
12
12
  .ov-hbars { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, max-content) minmax(33%, 1fr) max-content; gap: 4px 12px; }
13
13
  .ov-hbars li { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; }
14
14
  .ov-hbars li > a, .ov-hbars li > div { display: grid; grid-column: 1 / -1; grid-template-columns: subgrid; row-gap: 0; align-items: center; padding: 4px; border-radius: 6px; color: inherit; text-decoration: none; }
15
- .ov-hbars-more { grid-column: 1 / -1; padding: 0 4px; font-size: 12px; color: var(--chart-live-faint, #777); }
15
+ .ov-hbars-more { grid-column: 1 / -1; padding: 0 4px; font-size: 14px; color: var(--chart-live-faint, #777); }
16
16
  .ov-hbars li > a:hover, .ov-hbars li > div:hover { background: var(--chart-live-hover, #eee); text-decoration: none; }
17
17
  .ov-hbar-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; line-height: 20px; color: var(--chart-live-fg, #222); }
18
18
  .ov-hbar-track { height: 8px; border-radius: 3px; background: color-mix(in srgb, var(--chart-live-faint, #777) 14%, transparent); overflow: hidden; }
19
19
  .ov-hbar-track > span { display: block; height: 100%; border-radius: 3px; }
20
20
  .ov-hbar-value { font: 12px/16px var(--chart-live-font-mono, monospace); font-variant-numeric: tabular-nums; text-align: right; color: var(--chart-live-fg, #222); }
21
- .ov-hbar-note { grid-column: 1 / -1; font-size: 12px; color: var(--chart-live-faint, #777); }
21
+ .ov-hbar-note { grid-column: 1 / -1; font-size: 14px; color: var(--chart-live-faint, #777); }
22
22
  .ov-meter { display: grid; gap: 4px; min-width: 0; }
23
23
  .ov-meter-track { display: block; height: 8px; border-radius: 3px; background: color-mix(in srgb, var(--chart-live-faint, #777) 14%, transparent); overflow: hidden; }
24
24
  .ov-meter-track > span { display: block; height: 100%; border-radius: 3px; }
25
25
  .ov-meter-text { font: 12px/16px var(--chart-live-font-mono, monospace); font-variant-numeric: tabular-nums; color: var(--chart-live-muted, #666); }
26
26
  .ov-spark { display: block; width: 112px; height: 24px; }
27
- .ov-spark-empty { font-size: 12px; color: var(--chart-live-faint, #777); }
27
+ .ov-spark-empty { font-size: 14px; color: var(--chart-live-faint, #777); }
28
28
  .ov-tip-line i { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 4px; vertical-align: 0; }
29
29
  /* Recorded events and spans. Colours come from Brand tokens; kinds also differ by stroke pattern and glyph. */
30
30
  .ov-mark { stroke-width: 1.5; fill: none; }
@@ -45,7 +45,7 @@ line.ov-gridline { stroke: color-mix(in srgb, var(--chart-live-faint, #777) 22%,
45
45
  .ov-verdict-fail .ov-mark-head { fill: var(--chart-live-danger, var(--chart-breach, var(--status-error))); }
46
46
  .ov-verdict-unknown .ov-mark { stroke: var(--chart-live-faint, var(--chart-muted)); }
47
47
  .ov-verdict-unknown .ov-mark-head { fill: var(--chart-live-faint, var(--chart-muted)); }
48
- .ov-mark-label { fill: var(--chart-live-fg, var(--chart-ink)); font-size: 12px; paint-order: stroke; stroke: var(--chart-live-surface, var(--chart-canvas)); stroke-width: 3px; stroke-linejoin: round; }
48
+ .ov-mark-label { fill: var(--chart-live-fg, var(--chart-ink)); font-size: 14px; paint-order: stroke; stroke: var(--chart-live-surface, var(--chart-canvas)); stroke-width: 3px; stroke-linejoin: round; }
49
49
  .ov-band-after-pass { fill: color-mix(in srgb, var(--chart-live-pass, var(--chart-pass, var(--status-running))) 12%, transparent); }
50
50
  .ov-band-idle { fill: var(--chart-live-hover, var(--chart-shade)); }
51
51
  .ov-band-blocked { fill: color-mix(in srgb, var(--chart-live-danger, var(--chart-breach, var(--status-error))) 9%, transparent); }
@@ -57,7 +57,7 @@ line.ov-gridline { stroke: color-mix(in srgb, var(--chart-live-faint, #777) 22%,
57
57
  .ov-hatched { background: repeating-linear-gradient(135deg, var(--chart-live-faint, var(--chart-muted)) 0 1px, transparent 1px 5px), color-mix(in srgb, var(--chart-live-faint, var(--chart-muted)) 10%, transparent); }
58
58
  .ov-now { stroke: var(--chart-live-fg, var(--chart-ink)); stroke-width: 1.5; }
59
59
  .ov-gantt-open { stroke: var(--chart-live-fg, var(--chart-ink)); stroke-width: 1.5; stroke-dasharray: 3 2; }
60
- .ov-events, .ov-key, .ov-meter-key { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 12px; line-height: 16px; color: var(--chart-live-muted, var(--chart-ink-muted)); }
60
+ .ov-events, .ov-key, .ov-meter-key { list-style: none; margin: 4px 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px 16px; font-size: 14px; line-height: 20px; color: var(--chart-live-muted, var(--chart-ink-muted)); }
61
61
  .ov-key li, .ov-events li, .ov-meter-key li { display: inline-flex; align-items: center; gap: 8px; }
62
62
  .ov-meter-key b { font-weight: 600; color: var(--chart-live-fg, var(--chart-ink)); font-family: var(--chart-live-font-mono, monospace); font-variant-numeric: tabular-nums; }
63
63
  .ov-meter-key i, .ov-event-swatch { display: inline-block; width: 12px; height: 12px; border-radius: 2px; }
@@ -73,7 +73,7 @@ line.ov-gridline { stroke: color-mix(in srgb, var(--chart-live-faint, #777) 22%,
73
73
  .ov-event-after-pass { background: color-mix(in srgb, var(--chart-live-pass, var(--chart-pass, var(--status-running))) 25%, transparent); }
74
74
  .ov-event-idle { background: var(--chart-live-hover, var(--chart-shade)); }
75
75
  .ov-event-missing { background: repeating-linear-gradient(135deg, var(--chart-live-faint, var(--chart-muted)) 0 1px, transparent 1px 4px); }
76
- .ov-refusal { margin: 0; color: var(--chart-live-muted, var(--chart-ink-muted)); font-size: 12px; }
76
+ .ov-refusal { margin: 0; color: var(--chart-live-muted, var(--chart-ink-muted)); font-size: 14px; }
77
77
 
78
78
  /*
79
79
  * DotMap: thousands of dots on one canvas. A categorical lens names at most three categories in colour, the first
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/charts",
3
- "version": "0.21.20",
3
+ "version": "0.21.22",
4
4
  "description": "Static SVG and HTML figures for benchmarks and operational timing. Draws from producer data and refuses what it cannot draw honestly.",
5
5
  "type": "module",
6
6
  "license": "MIT",