@umriss-ui/charts 0.3.2 → 0.4.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.
package/CHANGELOG.md CHANGED
@@ -29,6 +29,225 @@ interface was still expected to move before `0.3.0`.
29
29
 
30
30
  ---
31
31
 
32
+ ## 0.4.1 – The axis band after the web font (Sep. 2026)
33
+
34
+ ### Fixed
35
+
36
+ - **An axis band no longer keeps the width of the fallback font.** A chart
37
+ laid out before its web font had arrived remembered the wider band under the
38
+ hysteresis (R-3.4) and kept it - the plot stood up to seven pixels too far in,
39
+ or not, depending on which came first. The band is now measured anew once the
40
+ font is there, and on a change of theme.
41
+
42
+ ---
43
+
44
+ ## 0.4.0 – The charts examined (Sep. 2026)
45
+
46
+ The result of a review of the whole package (`.scratch/charts-review/spec.md`),
47
+ delivered in three parts: the bugs it found and the removal of `Span`
48
+ (`charts-fixes`), what a plant screen expects of a chart
49
+ (`charts-essentials`), and long courses (`charts-long-series`). **`Span` is
50
+ gone** - occupancy is drawn by `@umriss-ui/schedule` (ADR-0026).
51
+
52
+ ### Changed
53
+
54
+ - **`Span` is removed** (breaking, ADR-0026). Occupancy - jobs on machines,
55
+ idle time, double bookings - is drawn by `@umriss-ui/schedule`, with lanes,
56
+ groups and editing. With it go `SpanProps`, `SpanSeriesConfig`, the series
57
+ kind `"span"`, the second x channel `x1` of `MaterializedSeries` and
58
+ `open` in a tooltip point's `segment`.
59
+ - **A state band and a matrix take no palette colour.** They colour themselves,
60
+ and each used up a place of the palette all the same: a line after a state
61
+ band came out in the palette's second colour, after three bands in its
62
+ fourth. It now gets the first. A series without a `name` counts its position
63
+ among the series that take a colour.
64
+ - **The operating-time axis labels in en-GB by level.** Without a
65
+ `tickFormat` it wrote every tick as `dd.MM. HH:mm`; it now labels as the
66
+ time axis does - `15:00`, and the date on the first tick of a new day,
67
+ `17 Mar 06:00` - and the tooltip's x value as `17 Mar 15:23`. Its ticks
68
+ stand on the same local boundaries, across a clock change too.
69
+ - **Lines and areas downsample on their own.** Above two points per pixel
70
+ column of the plot they draw four per column - where the course entered it,
71
+ its lowest and highest value, where it left - and a gap in a column stays a
72
+ gap. They draw only the window of the x domain, and one point beyond each
73
+ edge. The picture is the same; three lines of 1,000,000 points draw in about
74
+ 8 ms instead of 47. Bars and scatters are never thinned, and the tooltip
75
+ still searches every point.
76
+ - **A caller's colour is resolved for the canvas.** A series' `color`, a
77
+ state's, a limit's and a gradient stop reached the canvas as the text they
78
+ were given: `var(--…)` or `light-dark(…)` drew nothing, or in the colour
79
+ drawn before. They now go through the theme's probe as the palette does,
80
+ and are resolved anew when the colour scheme changes.
81
+ - **A state band's last state ends at the latest reading.** It ran to the end
82
+ of the x domain - with `domain="nice"` a rounding of the axis, and with
83
+ `domain="data"` nothing at all. It now ends at the last x of any visible
84
+ series on its x axis; where the band reports last, one median step of its
85
+ own x values after its last point; never beyond the domain. The band's x
86
+ extent reaches that step too. The last state is no longer hit beyond it.
87
+ - **The first tick of a time axis carries its date.** A clock tick names the
88
+ day, a day tick the year - a zoomed axis whose first tick is a midnight, or
89
+ that crosses none, named no day at all.
90
+
91
+ ### Added
92
+
93
+ - **`TooltipPoint.xValue`**: a point's own x value. With several x axes it can
94
+ differ from the hit's.
95
+ - **`localOffset(instant)`**: the time zone's offset at an instant, as the
96
+ shift of a tick grid onto local time. It moved here from
97
+ `@umriss-ui/schedule`, which takes it from here now.
98
+ - **`XAxis time`**: the values are instants. Ticks on local boundaries from
99
+ the minute to the month, labels by level in en-GB with a 24-hour clock -
100
+ `15:00`, `17 Mar`, `Mar 2026` - and the date on the first tick of a new
101
+ day. `domain="nice"` widens to the step's boundaries. A `tickFormat` is
102
+ handed the instant, which is how the axis speaks German. `calendar` implies
103
+ `time`.
104
+ - **`format` on `Line`, `Area`, `Bar`, `Scatter`, `Matrix` and
105
+ `ControlChart`**: `(value: number) => string`, the value as the tooltip
106
+ writes it - "806.4 °C" without a render prop. Without it the y axis'
107
+ `tickFormat`, then the default; a matrix' value has no axis format and goes
108
+ to the default. `ControlChart` passes it on to its line and its violations.
109
+ - **`Line step`**: sample-and-hold. Each value holds as a horizontal until
110
+ the next sample and jumps there - a set point, a digital signal. A gap ends
111
+ the hold at its x. The tooltip reports the sample the hold began with, not
112
+ the nearer one after it.
113
+ - **`hidden` on `Line`, `Area`, `Bar`, `Scatter`, `StateBand` and `Matrix`**,
114
+ controlled: a hidden series is not drawn, not hit and does not count for its
115
+ axes' extent - a fixed `domain` keeps the axis still. Its legend entry stays,
116
+ struck through with a faint chip. A hidden bar leaves no empty place in its
117
+ group.
118
+ - **`Legend onToggle(name)`**: with it every entry is a button
119
+ (`aria-pressed`) that hands the caller the series' name, or a state's label.
120
+ Without it the legend is not clickable, as before.
121
+ - **`Chart empty`**: what the plot area says when no visible series has a
122
+ point to show - no data, only gaps, or every series hidden. Default
123
+ `"No data"`, centred; axes and frame stay. Before, such a chart drew an
124
+ empty frame on [0, 1] and said nothing. A time axis over less than a minute
125
+ - the [0, 1] of an axis without data - draws no ticks.
126
+ - **`tone` on `Area`, `Bar` and `ControlChart`**, as on `Line` and
127
+ `Scatter`: a role the theme resolves. On `ControlChart` it colours the line;
128
+ the violations stay "alarm".
129
+ - **`Area dash`**: a dash pattern for the outline, in CSS pixels; the fill
130
+ stays whole.
131
+ - Every size prop's comment names its unit (CSS pixels, a fraction of the
132
+ step, domain units of the axis).
133
+ - **`XAxis onDomainChange`**: zoom and pan, controlled. Ctrl or ⌘ with the
134
+ wheel - and a pinch - zoom around the pointer; a drag, a horizontal wheel or
135
+ Shift with the wheel pan; a double click proposes the whole data range. The
136
+ axis only proposes a domain in its own units; the caller passes it back as
137
+ `domain`, clamped as it likes. Without a handler nothing zooms, and the
138
+ plain wheel always scrolls the page.
139
+ - **`YAxis domain="visible"`**: the extent of what the series show inside
140
+ their x axis' domain, widened to ticks as `"nice"` is - a zoomed hour gets
141
+ the hour's range, not the week's. A fixed foot (area, bar) and the limits
142
+ count as before; where the x domain is not fixed, every point is shown and
143
+ counts.
144
+ - **`Chart syncId`**: charts with the same id share the pointer's x
145
+ position, in domain units. Each draws its crosshair there, on its x axis of
146
+ the same id or its first; the tooltip stays with the chart under the
147
+ pointer. Zoom is not shared - pass every chart the same controlled
148
+ `domain`.
149
+ - **`YAxis alignTicks`**: on a further y axis, take the first y axis' tick
150
+ count and widen this axis' domain until its ticks stand on that one's grid
151
+ lines, the steps still 1, 2 or 5. One grid then serves two quantities. The
152
+ DEV warning about several grids names it.
153
+
154
+ ### Fixed
155
+
156
+ - **The sortedness check sees every series.** In DEV it ran for the first
157
+ series only, and warned falsely where that was a matrix, whose cells run
158
+ row-major. It now checks every series but the matrix, once per change of its
159
+ data, and names the series it warns about.
160
+ - **A matrix explains its own colours.** Its legend entry showed a palette
161
+ colour it never draws; it now shows the gradient's steps or the limit set's
162
+ three colours, and the tooltip's chip shows the colour of the cell.
163
+ - **A state several bands share highlights all of them.** Hovering "Fault" in
164
+ the legend of three machines highlighted the first band only.
165
+ - **The tooltip writes a value in its axis' format.** It formatted every value
166
+ with a fixed default, so beside ticks reading "40 %" the tooltip wrote a
167
+ bare "42". A value now takes its y axis' `tickFormat`, and the default only
168
+ without one. A point on another x axis than the header's names its own x
169
+ value, in its own axis' format, beside its name.
170
+ - **An infinity is a gap.** `±Infinity` out of any accessor - y, baseline,
171
+ a matrix' value, x - entered the extent, which was then no longer finite, and
172
+ the axis fell back to [0, 1] with every other value pressed against its edge.
173
+ It is now treated like `null` or `NaN`: a gap, outside the extent. An x
174
+ that is no number - an infinity or `NaN` - takes the place of the point
175
+ before it, so that the x values stay ascending; in the middle of a series,
176
+ or as `-Infinity`, it used to raise a false DEV warning about unsorted data
177
+ and mislead the hit test.
178
+ - **A point between two gaps is drawn.** On a line it was a lone move of the
179
+ pen and drew nothing, and above 60 points `markers="auto"` drew no marker for
180
+ it either - a reading a gap isolates vanished. It now always keeps its marker;
181
+ only `markers="never"` drops it. On an area it is a stroke from its foot to
182
+ its value, with or without an outline.
183
+ - **A control chart reports its violations once per change.** An inline
184
+ `accessor` or `origin` recomputed the limits on every render, and
185
+ `onViolations` was called after each - a caller that kept the violations in
186
+ state rendered forever. The accessor is now compared by its source text, the
187
+ origin by its values, and `onViolations` is called only when the violations
188
+ differ in content.
189
+ - **A limit on the x axis finds its axis.** `LimitLine` and `LimitBand` with
190
+ `orientation="x"` and no `axisId` looked for an axis "y" among the x axes,
191
+ found none and drew nothing, silently. Without an `axisId` a limit now binds
192
+ to the first axis of its orientation - an `<XAxis id="time">` too - and an
193
+ unknown `axisId` is a DEV error, as it is for a series.
194
+ - **The operating-time axis stands on the local clock.** Its day and half-day
195
+ ticks fell on UTC's midnight and were labelled in local time - "01:00"
196
+ where a day begins, in CET. They now fall on local midnight and noon. Explicit
197
+ `ticks` and the value of an x limit are named on the wall clock, like the
198
+ data, and mapped into operating time as the data are; before, both were taken
199
+ as operating time and landed far off, or pulled the axis out of shape.
200
+ - **Hit testing where areas and points meet.** Under `mode="nearest"` a state
201
+ band or a matrix cell under the pointer counted as distance zero and beat
202
+ every point; a point within 12 px of the pointer now wins, and the area
203
+ answers where none is. A chart of bands or cells only pinned crosshair and
204
+ tooltip to the beginning of the section; they now stay with the pointer. And
205
+ a scatter under `"nearest"` was hit by x alone - the sample straight above
206
+ the pointer beat the one beside it; it is now measured in x and y.
207
+ - **Change detection.** An inline `calendar` array is new on every render, and
208
+ was compared by reference: every render mapped every point again. It is now
209
+ compared by its intervals. Functions are compared by their source text, and
210
+ every native or bound function reads the same - two bound
211
+ `Intl.NumberFormat#format` counted as equal, and swapping one for the other
212
+ left the axis in the old format. Such a function is now compared by identity.
213
+ The known limit stays and is now documented at the props: two functions of
214
+ the same text that read different captured values count as equal.
215
+ - **A control chart over a constant reference window finds no outliers.**
216
+ Sigma is 0 there, the limits lie on the centre line, and every value off it
217
+ was an outlier - and two of three beyond "two sigma". Both rules now find
218
+ nothing without a spread, and DEV warns that the limits are degenerate - for
219
+ a given sigma of 0 or below as well, where the rules find nothing either.
220
+ - **`Chart.height` says its default.** The comment promised the host's height;
221
+ the default is and was 300.
222
+ - **A matrix buckets its cells once per change**, not on every redraw of the
223
+ series layer - a legend hover redraws it - and its tooltip chip no longer
224
+ scans every cell on each pointer move.
225
+ - **Hovering a hidden series' legend entry dims nothing.** It highlighted the
226
+ series that is not drawn, and every visible one was dimmed.
227
+ - **A time axis over years labels a year as `2026`**, by level, not as
228
+ `Jan 2026`.
229
+ - **The legend's focus ring couples through `--uc-focus-ring`**, like every
230
+ other value of the stylesheet, with `--u-focus-ring` and a literal behind
231
+ it.
232
+ - **A downsampled course keeps a gap at the end of a pixel column.** Only the
233
+ first gap of a column was kept: a column running gap - points - gap lost the
234
+ second, and the line bridged to data far away.
235
+ - **The cursor sync.** A chart without a `Tooltip` shared no position; it now
236
+ shares the pointer's x. A chart that leaves its group - another `syncId`, or
237
+ unmounted - no longer keeps the crosshair the group last sent it.
238
+ - **An x limit's label stays inside the container** at the right edge, as a
239
+ tick label does; it ran past it.
240
+ - **No hover marker outside the plot.** At a zoomed edge the nearest reading
241
+ can lie beyond it, and its marker stood on the axis.
242
+ - **The tooltip header on a time axis carries the seconds** where the
243
+ readings under the pointer lie less than a minute apart - readings a second
244
+ apart shared one header. Otherwise it stays `17 Mar 15:23`.
245
+ - **A double click proposes no domain without width.** Over a single point
246
+ the data range is one value; the double click handed it to
247
+ `onDomainChange` all the same, where a wheel step checks for that.
248
+
249
+ ---
250
+
32
251
  ## 0.3.2 – Phones, touch and a review (Sep. 2026)
33
252
 
34
253
  ### Fixed
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @umriss-ui/charts
2
2
 
3
3
  Canvas-based charts for data-dense applications: few chart kinds, each one drawn
4
- properly. Lines, areas, bars, scatters, state bands, matrices and spans compose
5
- into one chart on shared axes — together with the instruments a plant screen is
4
+ properly. Lines, areas, bars, scatters, state bands and matrices compose into
5
+ one chart on shared axes — together with the instruments a plant screen is
6
6
  made of: limit lines and bands, a control chart, a Pareto and an operating-time
7
7
  axis.
8
8
 
@@ -74,8 +74,9 @@ loaded: Geist when the application has it, the system fonts otherwise.
74
74
 
75
75
  ## What it can do
76
76
 
77
- * **Seven series kinds** in one chart on shared axes: `Line`, `Area`, `Bar`,
78
- `Scatter`, `StateBand`, `Matrix`, `Span`.
77
+ * **Six series kinds** in one chart on shared axes: `Line`, `Area`, `Bar`,
78
+ `Scatter`, `StateBand`, `Matrix`. Occupancy — jobs on machines, idle time,
79
+ double bookings — is `@umriss-ui/schedule`'s (ADR-0026).
79
80
  * **Several axes per orientation**, each with its own extent; only the first
80
81
  registered axis per orientation draws a grid.
81
82
  * **The instruments**: `LimitLine` and `LimitBand`, `ControlChart` with its four
package/dist/charts.css CHANGED
@@ -1 +1 @@
1
- @layer umriss.tokens,umriss.base,umriss.components;@layer umriss.components{.uc-root,.uc-root:before,.uc-root:after{box-sizing:border-box}.uc-plot,.uc-plot:before,.uc-plot:after{box-sizing:border-box}.uc-axes,.uc-axes:before,.uc-axes:after{box-sizing:border-box}.uc-axis,.uc-axis:before,.uc-axis:after{box-sizing:border-box}.uc-axis-line,.uc-axis-line:before,.uc-axis-line:after{box-sizing:border-box}.uc-axis-y,.uc-axis-y:before,.uc-axis-y:after{box-sizing:border-box}.uc-axis-left,.uc-axis-left:before,.uc-axis-left:after{box-sizing:border-box}.uc-axis-right,.uc-axis-right:before,.uc-axis-right:after{box-sizing:border-box}.uc-axis-x,.uc-axis-x:before,.uc-axis-x:after{box-sizing:border-box}.uc-axis-bottom,.uc-axis-bottom:before,.uc-axis-bottom:after{box-sizing:border-box}.uc-axis-top,.uc-axis-top:before,.uc-axis-top:after{box-sizing:border-box}.uc-tick,.uc-tick:before,.uc-tick:after{box-sizing:border-box}.uc-tick-mark,.uc-tick-mark:before,.uc-tick-mark:after{box-sizing:border-box}.uc-tick-label,.uc-tick-label:before,.uc-tick-label:after{box-sizing:border-box}.uc-axis-title,.uc-axis-title:before,.uc-axis-title:after{box-sizing:border-box}.uc-legend,.uc-legend:before,.uc-legend:after{box-sizing:border-box}.uc-legend-top,.uc-legend-top:before,.uc-legend-top:after{box-sizing:border-box}.uc-legend-bottom,.uc-legend-bottom:before,.uc-legend-bottom:after{box-sizing:border-box}.uc-legend-item,.uc-legend-item:before,.uc-legend-item:after{box-sizing:border-box}.uc-legend-chip,.uc-legend-chip:before,.uc-legend-chip:after{box-sizing:border-box}.uc-tooltip,.uc-tooltip:before,.uc-tooltip:after{box-sizing:border-box}.uc-tooltip-head,.uc-tooltip-head:before,.uc-tooltip-head:after{box-sizing:border-box}.uc-tooltip-list,.uc-tooltip-list:before,.uc-tooltip-list:after{box-sizing:border-box}.uc-tooltip-row,.uc-tooltip-row:before,.uc-tooltip-row:after{box-sizing:border-box}.uc-tooltip-chip,.uc-tooltip-chip:before,.uc-tooltip-chip:after{box-sizing:border-box}.uc-tooltip-name,.uc-tooltip-name:before,.uc-tooltip-name:after{box-sizing:border-box}.uc-tooltip-value,.uc-tooltip-value:before,.uc-tooltip-value:after{box-sizing:border-box}.uc-measure,.uc-measure:before,.uc-measure:after{box-sizing:border-box}.uc-limit-label,.uc-limit-label:before,.uc-limit-label:after{box-sizing:border-box}.uc-break,.uc-break:before,.uc-break:after{box-sizing:border-box}.uc-root{--uc-color-axis: var(--u-edge-color-strong, rgba(23, 23, 23, .17));--uc-color-grid: var(--u-hairline, rgba(23, 23, 23, .06));--uc-color-text: var(--u-color-text-muted, #71717a);--uc-color-bg: var(--u-color-surface, #ffffff);--uc-font: var( --u-font-sans, "Geist Sans", "Geist", -apple-system, "Segoe UI", system-ui, sans-serif );--uc-font-mono: var( --u-font-mono, "Geist Mono", ui-monospace, "Cascadia Mono", "Consolas", monospace );--uc-color-warning: var(--u-color-warning, #8a5c00);--uc-color-alarm: var(--u-color-danger, #b13636);--uc-color-ok: var(--u-color-success, #217a4b);--uc-series-1: var(--u-chart-1, #2563eb);--uc-series-2: var(--u-chart-2, #db2777);--uc-series-3: var(--u-chart-3, #059669);--uc-series-4: var(--u-chart-4, #d97706);--uc-series-5: var(--u-chart-5, #7c3aed);--uc-series-6: var(--u-chart-6, #0891b2);--uc-size-tick: 11.5px;--uc-size-title: 12px;--uc-size-legend: 12.5px;--uc-radius: 6px;--uc-shadow: 0 1px 2px rgba(0, 0, 0, .06), 0 4px 12px rgba(0, 0, 0, .08);position:relative;display:flex;flex-direction:column;font-family:var(--uc-font);color:var(--uc-color-text);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}.uc-plot{position:relative;flex:1 1 auto;min-height:0;min-width:0}.uc-plot>canvas{box-sizing:border-box}.uc-plot>canvas{position:absolute;top:0;right:0;bottom:0;left:0;display:block;pointer-events:none}.uc-axes{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.uc-axis{position:absolute}.uc-axis-line{position:absolute;background:var(--uc-color-axis)}.uc-axis-y>.uc-axis-line{top:0;width:1px;height:100%}.uc-axis-left>.uc-axis-line{right:0}.uc-axis-right>.uc-axis-line{left:0}.uc-axis-x>.uc-axis-line{left:0;width:100%;height:1px}.uc-axis-bottom>.uc-axis-line{top:0}.uc-axis-top>.uc-axis-line{bottom:0}.uc-tick{position:absolute}.uc-axis-y>.uc-tick{left:0;right:0;height:1px}.uc-axis-x>.uc-tick{top:0;bottom:0;width:1px}.uc-tick-mark{position:absolute;background:var(--uc-color-axis)}.uc-axis-y>.uc-tick>.uc-tick-mark{top:0;width:5px;height:1px}.uc-axis-left>.uc-tick>.uc-tick-mark{right:0}.uc-axis-right>.uc-tick>.uc-tick-mark{left:0}.uc-axis-x>.uc-tick>.uc-tick-mark{left:0;width:1px;height:5px}.uc-axis-bottom>.uc-tick>.uc-tick-mark{top:0}.uc-axis-top>.uc-tick>.uc-tick-mark{bottom:0}.uc-tick-label{position:absolute;white-space:pre;font-size:var(--uc-size-tick);line-height:1.25;letter-spacing:.005em;color:var(--uc-color-text)}.uc-axis-y>.uc-tick>.uc-tick-label{top:50%;transform:translateY(-50%)}.uc-axis-left>.uc-tick>.uc-tick-label{text-align:right}.uc-axis-right>.uc-tick>.uc-tick-label{text-align:left}.uc-axis-title{position:absolute;white-space:pre;font-size:var(--uc-size-title);line-height:1.25;letter-spacing:.01em;color:var(--uc-color-text)}.uc-axis-x>.uc-axis-title{left:0;right:0;text-align:center}.uc-axis-bottom>.uc-axis-title{bottom:0}.uc-axis-top>.uc-axis-title{top:0}.uc-axis-y>.uc-axis-title{top:50%;writing-mode:vertical-rl}.uc-axis-left>.uc-axis-title{left:0;transform:translateY(-50%) rotate(180deg)}.uc-axis-right>.uc-axis-title{right:0;transform:translateY(-50%)}.uc-legend{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:var(--uc-size-legend);line-height:1.35;color:var(--uc-color-text)}.uc-legend-top{order:-1;padding-bottom:8px}.uc-legend-bottom{order:1;padding-top:8px}.uc-legend-item{display:inline-flex;align-items:center;gap:6px;cursor:default}.uc-legend-chip{display:inline-block;width:10px;height:10px;border-radius:2px;corner-shape:squircle}.uc-tooltip{position:absolute;top:0;left:0;z-index:2;pointer-events:none;opacity:0;transition:opacity 80ms ease-out;min-width:96px;padding:7px 9px;border:1px solid var(--uc-color-axis);border-radius:var(--uc-radius);corner-shape:squircle;background:var(--uc-color-bg);box-shadow:var(--uc-shadow);font-size:12px;line-height:1.35;color:var(--uc-color-text)}.uc-tooltip-head{font-family:var(--uc-font-mono);font-size:11.5px;letter-spacing:.01em;padding-bottom:5px;margin-bottom:5px;border-bottom:1px solid var(--uc-color-grid)}.uc-tooltip-list{display:grid;grid-template-columns:auto 1fr auto;gap:3px 8px;align-items:center}.uc-tooltip-row{display:contents}.uc-tooltip-chip{width:8px;height:8px;border-radius:2px;corner-shape:squircle}.uc-tooltip-name{white-space:nowrap}.uc-tooltip-value{font-family:var(--uc-font-mono);text-align:right;white-space:nowrap}@media(prefers-reduced-motion:reduce){.uc-tooltip{transition:none}}.uc-measure{position:absolute;top:0;left:0;right:auto;bottom:auto;transform:none;visibility:hidden;pointer-events:none;white-space:pre;writing-mode:horizontal-tb}.uc-limit-label{position:absolute;font-size:var(--uc-size-tick);line-height:1.25;white-space:nowrap;font-variant-numeric:tabular-nums;background:var(--uc-color-bg);padding:0 2px}.uc-limit-label[data-severity=warning]{color:var(--uc-color-warning)}.uc-limit-label[data-severity=alarm]{color:var(--uc-color-alarm)}.uc-limit-label[data-role=control],.uc-limit-label[data-role=zone]{color:var(--uc-color-text)}.uc-axis-y .uc-limit-label{transform:translateY(-50%)}.uc-axis-left .uc-limit-label{right:9px}.uc-axis-right .uc-limit-label{left:9px}.uc-break{position:absolute;top:0;width:7px;height:9px;margin-left:-3.5px;color:var(--uc-color-text)}.uc-break:before,.uc-break:after{content:"";position:absolute;top:0;width:1px;height:9px;background:currentColor;opacity:.55;transform:skew(-20deg)}.uc-break:before{left:1px}.uc-break:after{left:4px}}
1
+ @layer umriss.tokens,umriss.base,umriss.components;@layer umriss.components{.uc-root,.uc-root:before,.uc-root:after{box-sizing:border-box}.uc-plot,.uc-plot:before,.uc-plot:after{box-sizing:border-box}.uc-axes,.uc-axes:before,.uc-axes:after{box-sizing:border-box}.uc-axis,.uc-axis:before,.uc-axis:after{box-sizing:border-box}.uc-axis-line,.uc-axis-line:before,.uc-axis-line:after{box-sizing:border-box}.uc-axis-y,.uc-axis-y:before,.uc-axis-y:after{box-sizing:border-box}.uc-axis-left,.uc-axis-left:before,.uc-axis-left:after{box-sizing:border-box}.uc-axis-right,.uc-axis-right:before,.uc-axis-right:after{box-sizing:border-box}.uc-axis-x,.uc-axis-x:before,.uc-axis-x:after{box-sizing:border-box}.uc-axis-bottom,.uc-axis-bottom:before,.uc-axis-bottom:after{box-sizing:border-box}.uc-axis-top,.uc-axis-top:before,.uc-axis-top:after{box-sizing:border-box}.uc-tick,.uc-tick:before,.uc-tick:after{box-sizing:border-box}.uc-tick-mark,.uc-tick-mark:before,.uc-tick-mark:after{box-sizing:border-box}.uc-tick-label,.uc-tick-label:before,.uc-tick-label:after{box-sizing:border-box}.uc-axis-title,.uc-axis-title:before,.uc-axis-title:after{box-sizing:border-box}.uc-empty,.uc-empty:before,.uc-empty:after{box-sizing:border-box}.uc-legend,.uc-legend:before,.uc-legend:after{box-sizing:border-box}.uc-legend-top,.uc-legend-top:before,.uc-legend-top:after{box-sizing:border-box}.uc-legend-bottom,.uc-legend-bottom:before,.uc-legend-bottom:after{box-sizing:border-box}.uc-legend-item,.uc-legend-item:before,.uc-legend-item:after{box-sizing:border-box}.uc-legend-chip,.uc-legend-chip:before,.uc-legend-chip:after{box-sizing:border-box}.uc-tooltip,.uc-tooltip:before,.uc-tooltip:after{box-sizing:border-box}.uc-tooltip-head,.uc-tooltip-head:before,.uc-tooltip-head:after{box-sizing:border-box}.uc-tooltip-list,.uc-tooltip-list:before,.uc-tooltip-list:after{box-sizing:border-box}.uc-tooltip-row,.uc-tooltip-row:before,.uc-tooltip-row:after{box-sizing:border-box}.uc-tooltip-chip,.uc-tooltip-chip:before,.uc-tooltip-chip:after{box-sizing:border-box}.uc-tooltip-name,.uc-tooltip-name:before,.uc-tooltip-name:after{box-sizing:border-box}.uc-tooltip-x,.uc-tooltip-x:before,.uc-tooltip-x:after{box-sizing:border-box}.uc-tooltip-value,.uc-tooltip-value:before,.uc-tooltip-value:after{box-sizing:border-box}.uc-measure,.uc-measure:before,.uc-measure:after{box-sizing:border-box}.uc-limit-label,.uc-limit-label:before,.uc-limit-label:after{box-sizing:border-box}.uc-break,.uc-break:before,.uc-break:after{box-sizing:border-box}.uc-root{--uc-color-axis: var(--u-edge-color-strong, rgba(23, 23, 23, .17));--uc-color-grid: var(--u-hairline, rgba(23, 23, 23, .06));--uc-color-text: var(--u-color-text-muted, #71717a);--uc-color-bg: var(--u-color-surface, #ffffff);--uc-font: var( --u-font-sans, "Geist Sans", "Geist", -apple-system, "Segoe UI", system-ui, sans-serif );--uc-font-mono: var( --u-font-mono, "Geist Mono", ui-monospace, "Cascadia Mono", "Consolas", monospace );--uc-color-warning: var(--u-color-warning, #8a5c00);--uc-color-alarm: var(--u-color-danger, #b13636);--uc-color-ok: var(--u-color-success, #217a4b);--uc-series-1: var(--u-chart-1, #2563eb);--uc-series-2: var(--u-chart-2, #db2777);--uc-series-3: var(--u-chart-3, #059669);--uc-series-4: var(--u-chart-4, #d97706);--uc-series-5: var(--u-chart-5, #7c3aed);--uc-series-6: var(--u-chart-6, #0891b2);--uc-size-tick: 11.5px;--uc-size-title: 12px;--uc-size-legend: 12.5px;--uc-radius: 6px;--uc-shadow: 0 1px 2px rgba(0, 0, 0, .06), 0 4px 12px rgba(0, 0, 0, .08);--uc-focus-ring: var(--u-focus-ring, 0 0 0 2px #0e7d72);position:relative;display:flex;flex-direction:column;font-family:var(--uc-font);color:var(--uc-color-text);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}.uc-plot{position:relative;flex:1 1 auto;min-height:0;min-width:0}.uc-plot>canvas{box-sizing:border-box}.uc-plot>canvas{position:absolute;top:0;right:0;bottom:0;left:0;display:block;pointer-events:none}.uc-axes{position:absolute;top:0;right:0;bottom:0;left:0;pointer-events:none}.uc-axis{position:absolute}.uc-axis-line{position:absolute;background:var(--uc-color-axis)}.uc-axis-y>.uc-axis-line{top:0;width:1px;height:100%}.uc-axis-left>.uc-axis-line{right:0}.uc-axis-right>.uc-axis-line{left:0}.uc-axis-x>.uc-axis-line{left:0;width:100%;height:1px}.uc-axis-bottom>.uc-axis-line{top:0}.uc-axis-top>.uc-axis-line{bottom:0}.uc-tick{position:absolute}.uc-axis-y>.uc-tick{left:0;right:0;height:1px}.uc-axis-x>.uc-tick{top:0;bottom:0;width:1px}.uc-tick-mark{position:absolute;background:var(--uc-color-axis)}.uc-axis-y>.uc-tick>.uc-tick-mark{top:0;width:5px;height:1px}.uc-axis-left>.uc-tick>.uc-tick-mark{right:0}.uc-axis-right>.uc-tick>.uc-tick-mark{left:0}.uc-axis-x>.uc-tick>.uc-tick-mark{left:0;width:1px;height:5px}.uc-axis-bottom>.uc-tick>.uc-tick-mark{top:0}.uc-axis-top>.uc-tick>.uc-tick-mark{bottom:0}.uc-tick-label{position:absolute;white-space:pre;font-size:var(--uc-size-tick);line-height:1.25;letter-spacing:.005em;color:var(--uc-color-text)}.uc-axis-y>.uc-tick>.uc-tick-label{top:50%;transform:translateY(-50%)}.uc-axis-left>.uc-tick>.uc-tick-label{text-align:right}.uc-axis-right>.uc-tick>.uc-tick-label{text-align:left}.uc-axis-title{position:absolute;white-space:pre;font-size:var(--uc-size-title);line-height:1.25;letter-spacing:.01em;color:var(--uc-color-text)}.uc-axis-x>.uc-axis-title{left:0;right:0;text-align:center}.uc-axis-bottom>.uc-axis-title{bottom:0}.uc-axis-top>.uc-axis-title{top:0}.uc-axis-y>.uc-axis-title{top:50%;writing-mode:vertical-rl}.uc-axis-left>.uc-axis-title{left:0;transform:translateY(-50%) rotate(180deg)}.uc-axis-right>.uc-axis-title{right:0;transform:translateY(-50%)}.uc-empty{position:absolute;display:flex;align-items:center;justify-content:center;text-align:center;font-size:var(--uc-size-legend);color:var(--uc-color-text)}.uc-legend{display:flex;flex-wrap:wrap;gap:4px 14px;font-size:var(--uc-size-legend);line-height:1.35;color:var(--uc-color-text)}.uc-legend-top{order:-1;padding-bottom:8px}.uc-legend-bottom{order:1;padding-top:8px}.uc-legend-item{display:inline-flex;align-items:center;gap:6px;cursor:default}.uc-legend-chip{display:inline-block;width:10px;height:10px;border-radius:2px;corner-shape:squircle}button.uc-legend-item{box-sizing:border-box}button.uc-legend-item{padding:0;border:0;border-radius:2px;corner-shape:squircle;background:none;font:inherit;color:inherit;cursor:pointer}button.uc-legend-item:focus-visible{box-sizing:border-box}button.uc-legend-item:focus-visible{outline:none;box-shadow:var(--uc-focus-ring)}.uc-legend-item[data-hidden]{text-decoration:line-through}.uc-legend-item[data-hidden]>.uc-legend-chip{opacity:.3}.uc-tooltip{position:absolute;top:0;left:0;z-index:2;pointer-events:none;opacity:0;transition:opacity 80ms ease-out;min-width:96px;padding:7px 9px;border:1px solid var(--uc-color-axis);border-radius:var(--uc-radius);corner-shape:squircle;background:var(--uc-color-bg);box-shadow:var(--uc-shadow);font-size:12px;line-height:1.35;color:var(--uc-color-text)}.uc-tooltip-head{font-family:var(--uc-font-mono);font-size:11.5px;letter-spacing:.01em;padding-bottom:5px;margin-bottom:5px;border-bottom:1px solid var(--uc-color-grid)}.uc-tooltip-list{display:grid;grid-template-columns:auto 1fr auto;gap:3px 8px;align-items:center}.uc-tooltip-row{display:contents}.uc-tooltip-chip{width:8px;height:8px;border-radius:2px;corner-shape:squircle}.uc-tooltip-name{white-space:nowrap}.uc-tooltip-x{margin-left:6px;font-family:var(--uc-font-mono)}.uc-tooltip-value{font-family:var(--uc-font-mono);text-align:right;white-space:nowrap}@media(prefers-reduced-motion:reduce){.uc-tooltip{transition:none}}.uc-measure{position:absolute;top:0;left:0;right:auto;bottom:auto;transform:none;visibility:hidden;pointer-events:none;white-space:pre;writing-mode:horizontal-tb}.uc-limit-label{position:absolute;font-size:var(--uc-size-tick);line-height:1.25;white-space:nowrap;font-variant-numeric:tabular-nums;background:var(--uc-color-bg);padding:0 2px}.uc-limit-label[data-severity=warning]{color:var(--uc-color-warning)}.uc-limit-label[data-severity=alarm]{color:var(--uc-color-alarm)}.uc-limit-label[data-role=control],.uc-limit-label[data-role=zone]{color:var(--uc-color-text)}.uc-axis-y .uc-limit-label{transform:translateY(-50%)}.uc-axis-left .uc-limit-label{right:9px}.uc-axis-right .uc-limit-label{left:9px}.uc-break{position:absolute;top:0;width:7px;height:9px;margin-left:-3.5px;color:var(--uc-color-text)}.uc-break:before,.uc-break:after{content:"";position:absolute;top:0;width:1px;height:9px;background:currentColor;opacity:.55;transform:skew(-20deg)}.uc-break:before{left:1px}.uc-break:after{left:4px}}