@umriss-ui/schedule 0.42.0 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -18,6 +18,45 @@ moves from here under the rule above.
18
18
 
19
19
  ---
20
20
 
21
+ ## 0.44.0 – Malformed data says so, and the handle goes (Oct. 2026)
22
+
23
+ ### Added
24
+
25
+ - **Malformed data warns once per cause in development:** a span that does not end after it starts, an item on an undeclared lane, an unknown task or dependency end, an id that stands twice. The checks run only in development.
26
+
27
+ ### Changed
28
+
29
+ - **`ScheduleHandle` and the handle ref are removed;** 0.43.0 deprecated them. A `Schedule` ref is typed `HTMLDivElement`, and `positionAt`, `clientPointOf` and `visibleDomain` are on `useSchedule`'s return.
30
+ - Migration: replace `ref.current.positionAt(x, y)` with `positionAt(x, y)` from `const { positionAt } = useSchedule()`, and the same for `clientPointOf` and `visibleDomain`; type a ref as `HTMLDivElement`.
31
+ - **`ariaLabel` on `Schedule` is removed;** 0.43.0 renamed it `aria-label`.
32
+ - Migration: write `aria-label` (TypeScript flags every use of `ariaLabel`).
33
+ - **The peer ranges on core and charts move to `^0.44.0`.**
34
+ - Migration: install the 0.44 versions of `@umriss-ui/core` and `@umriss-ui/charts` beside it.
35
+
36
+ ## 0.43.0 – A schedule that fills its frame, and takes a finger (Oct. 2026)
37
+
38
+ ### Added
39
+
40
+ - **`loading`**, as the chart has it: a plan stays, dims after `--u-delay-stale` and starts no drag, tooltip, context menu or key intent until the answer is in; a drag begun before it finishes. With no lanes, placeholder lines stand in the lane column. The plot is `aria-busy`, also in a server's markup.
41
+ - **Touch editing:** a long press on a bar grabs it, and the finger then moves it in time and across lanes as a mouse does, with `canMoveTo`, blocked time and auto-pan; stretching and lead-in/out stay with the mouse, pen and keyboard. A second finger cancels the grab, and the page does not scroll under a grabbed bar (ADR-0070).
42
+ - **`scrollToLane(lane)`, `scrollToSubtask(id)` and `focusSubtask(id)` on `useSchedule`'s return** show a lane or a subtask picked from a list of your own. `scrollToSubtask` brings the subtask's lane and time into view - the span moves to it and keeps its width - and leaves the focus; `focusSubtask` also makes it the Active subtask and focuses the plot. All three return `false` and change nothing for an unknown lane or subtask, a lane inside a folded group (none is unfolded) and a schedule that is not mounted.
43
+ - **`positionAt`, `clientPointOf` and `visibleDomain` on `useSchedule`'s return**, the functions the handle ref carried; the first two return `null` before mount.
44
+
45
+ ### Changed
46
+
47
+ - **Without `height` a schedule fills its frame and never goes below 400 px** (ADR-0050, amended). Alone in a block it is 400 px as before, whatever its lanes; in a frame taller than that it now takes that height.
48
+ - Migration: a schedule that relied on the 400 px default in a taller frame sets `height={400}` or `style={{ height: 400 }}`.
49
+ - **The schedule's `ref` is its root `<div>`** (ADR-0068): `className`, `style`, `id` and `data-*` reach it, `aria-label` and `aria-labelledby` name it, and a caller's `aria-describedby` follows the plot's own summary.
50
+ - Migration: nothing to change for an element ref.
51
+ - **`ScheduleHandle` is deprecated; 0.44.0 removes it.** A handle ref keeps working for this minor and warns once in development on its first call.
52
+ - Migration: replace `ref.current.positionAt(x, y)` with `positionAt(x, y)` from `const { positionAt } = useSchedule()`, and the same for `clientPointOf` and `visibleDomain`.
53
+ - **`ariaLabel` on `Schedule` is renamed `aria-label`.** `ariaLabel` stays as a deprecated alias and warns once in development; 0.44.0 removes it.
54
+ - Migration: write `aria-label`.
55
+ - **A vertical swipe over the plot scrolls the page while every lane fits.** While the lanes overflow, the plot keeps the swipe and scrolls its lanes; the lane names scroll the page.
56
+ - Migration: nothing to change; on a touch device a short plan no longer traps the page's scroll.
57
+ - **The peer ranges on core and charts move to `^0.43.0`.**
58
+ - Migration: install the 0.43 versions of `@umriss-ui/core` and `@umriss-ui/charts` beside it.
59
+
21
60
  ## 0.42.0 – A schedule under test, and quiet on a server (Oct. 2026)
22
61
 
23
62
  ### Added
package/README.md CHANGED
@@ -50,7 +50,7 @@ const dependencies: Dependency[] = [{ id: "move", from: "cut", to: "mill", lag:
50
50
  export function Plan() {
51
51
  const { Schedule, Lane, Subtasks, Dependencies } = useSchedule({ initialView: { domain: [at(5), at(12)] } });
52
52
  return (
53
- <Schedule ariaLabel="Plan of Tuesday">
53
+ <Schedule aria-label="Plan of Tuesday">
54
54
  <Lane id="saw" label="Saw" />
55
55
  <Lane id="mill" label="Mill" />
56
56
  <Dependencies data={dependencies} />
@@ -60,6 +60,8 @@ export function Plan() {
60
60
  }
61
61
  ```
62
62
 
63
+ Malformed data - a subtask that does not end after it starts, an item on a lane no `Lane` declares, a dependency naming no subtask, an id that stands twice - warns in development, once per cause, and is left out in production. An application with imported data checks it where it imports it.
64
+
63
65
  ## Editing is controlled
64
66
 
65
67
  The schedule draws the data it is given and changes none of it (ADR-0023). A
@@ -136,10 +138,20 @@ A tooltip on a hovered subtask or dependency names the order, the times, lead-in
136
138
  and lead-out and the findings; `tooltip` replaces its content or switches it
137
139
  off. `now` draws the present across the lanes. The wheel over the schedule,
138
140
  lane headers included, scrolls the lanes and releases the page at their end,
139
- Ctrl or ⌘ and a pinch zoom, Shift pans; on a touch screen one finger pans and a
140
- tap selects. The lane headers take at most 40 % of the width, so that on a
141
- phone the plot keeps the larger part; a ref handle turns a client point into a
142
- time and a lane and back.
141
+ Ctrl or ⌘ and a pinch zoom, Shift pans; on a touch screen one finger pans, a
142
+ tap selects and a long press on a bar grabs it (with `"move"` or `"lane"` in `intents`), and a vertical swipe scrolls the page while all lanes fit (when they
143
+ overflow, the lane names scroll the page). The lane headers take at most 40 % of the width, so that on a
144
+ phone the plot keeps the larger part; `positionAt` and `clientPointOf`, on what
145
+ `useSchedule` hands back, turn a client point into a time and a lane and back.
146
+
147
+ ## Its size
148
+
149
+ The width is the host's. Without `height`, a schedule fills its frame - a stretched grid cell, a card the
150
+ grid stretches, a container of definite height - and never goes below 400 px, which is also its height in
151
+ a frame without one: alone in a block it is 400 px however many lanes it holds, and the lanes beyond the
152
+ plot scroll inside it (ADR-0050). A number stays a fixed height. A different floor goes through `style`'s
153
+ `minHeight`, and `style` wins over the schedule's own sizing. A wrapper of your own between the frame and
154
+ the schedule passes the height on with `height: 100%`.
143
155
 
144
156
  ## The view
145
157
 
@@ -149,7 +161,11 @@ reports what the planner does, always the whole view; two schedules keep in
149
161
  step by sending each other what they report through `setView`, which is not
150
162
  reported in turn. Without a span the schedule shows the extent of its subtasks.
151
163
  `view`, `setView`, `setDomain`, `toggleGroup`, `foldAll` and `unfoldAll` stand on what the
152
- hook hands back.
164
+ hook hands back. `setDomain(span)` zooms to a span of two instants; `setDomain(null)` fits the work.
165
+
166
+ The schedule is a composite: its `ref`, `className`, `style`, `id` and `data-*` reach the root `<div>`;
167
+ `aria-label` (required) and `aria-labelledby` name the figure and the plot, and your `aria-describedby`
168
+ is joined to the plot's summary.
153
169
 
154
170
  ## Blocked time
155
171
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { CalendarInput } from '@umriss-ui/charts';
2
- import { CSSProperties } from 'react';
2
+ import { HTMLAttributes } from 'react';
3
3
  import { ReactNode } from 'react';
4
4
  import { Ref } from 'react';
5
5
 
@@ -345,24 +345,6 @@ export declare interface ResolvedAppearance {
345
345
  bounded number of pushes instead of running on. */
346
346
  export declare function ripple(subtasks: readonly Subtask[], dependencies: readonly Dependency[], intent: Intent): MoveIntent[];
347
347
 
348
- /** What a schedule offers a caller imperatively: the arithmetic between a
349
- point on the screen and a time on a lane. Everything else is props. */
350
- export declare interface ScheduleHandle {
351
- /** The time and the lane at a client point, or null outside the plot. */
352
- positionAt: (clientX: number, clientY: number) => {
353
- time: number;
354
- lane: string | null;
355
- } | null;
356
- /** The client point of a time - on the middle of a lane where one is named -
357
- or null while the schedule is not on screen. */
358
- clientPointOf: (time: number, lane?: string) => {
359
- x: number;
360
- y: number;
361
- } | null;
362
- /** The visible span, as two wall-clock instants. */
363
- visibleDomain: () => readonly [number, number];
364
- }
365
-
366
348
  /** What a pointer is on. */
367
349
  export declare type ScheduleHit = {
368
350
  readonly kind: "subtask";
@@ -413,43 +395,15 @@ export declare interface ScheduleOptions {
413
395
  onViewChange?: (view: ScheduleView) => void;
414
396
  }
415
397
 
416
- /** What `useSchedule` hands back: the schedule and what is declared inside
417
- it, its view and the setters that change it. */
418
- export declare interface ScheduleParts {
419
- /** The schedule. One per `useSchedule`: a second schedule is a second call. */
420
- Schedule: (props: ScheduleProps) => ReactNode;
421
- Lane: typeof Lane;
422
- LaneGroup: typeof LaneGroup;
423
- Subtasks: typeof Subtasks;
424
- Dependencies: typeof Dependencies;
425
- BlockedTimes: typeof BlockedTimes;
426
- Milestones: typeof Milestones;
427
- /** How the planner is looking at the plan: the span and the folded groups. */
428
- view: ScheduleView;
429
- /** Goes to a whole view; what it leaves out is shown whole again. Not
430
- reported through `onViewChange`: two schedules kept in step by
431
- `onViewChange: (v) => other.setView(v)` in both directions do not answer
432
- each other. A view with the content already shown changes nothing. */
433
- setView: (view: ScheduleView) => void;
434
- /** Puts a span of two wall-clock instants in view; `null` shows the
435
- subtasks' extent. */
436
- setDomain: (span: readonly [number, number] | null) => void;
437
- /** Folds or unfolds one **Lane group**. */
438
- toggleGroup: (id: string) => void;
439
- /** Folds every group. */
440
- foldAll: () => void;
441
- /** Unfolds every group. */
442
- unfoldAll: () => void;
443
- }
444
-
445
- /** The props of `Schedule`. */
446
- export declare interface ScheduleProps {
447
- /** Receives the `ScheduleHandle` - not an element. */
448
- ref?: Ref<ScheduleHandle>;
449
- /** What the schedule shows, for a screen reader: "Plan of week 38". */
450
- ariaLabel: string;
451
- /** Height in CSS pixels, both bands included. The width is the host's.
452
- @default 400 */
398
+ declare interface ScheduleOwnProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "aria-label"> {
399
+ /** Receives the root element. */
400
+ ref?: Ref<HTMLDivElement> | undefined;
401
+ /** Height in CSS pixels, both bands included, fixed. Left out, the schedule
402
+ fills its frame - a stretched grid cell, a card the grid stretches, a
403
+ container of definite height - and never goes below 400 px, which is also
404
+ its height in a frame without one. A different floor goes through
405
+ `style`'s `minHeight` (ADR-0050). The width is the host's.
406
+ @default fills the frame, at least 400 px */
453
407
  height?: number;
454
408
  /** Height of one lane in pixels at the default font size of 16 px; the
455
409
  schedule multiplies it by the root font size over 16 px when that ratio
@@ -545,15 +499,83 @@ export declare interface ScheduleProps {
545
499
  the minute, an instant fixes it there.
546
500
  @default false */
547
501
  now?: boolean | number;
548
- /** Goes to the root element. */
549
- className?: string;
550
- /** Goes to the root element. */
551
- style?: CSSProperties;
502
+ /** The plan is on its way, as the chart's `loading` says (ADR-0042). A plan
503
+ already drawn stays: it dims after a moment and takes no pointer - no new
504
+ drag, no tooltip, no intent by key - until the answer is in; a drag
505
+ begun before finishes and reports. The keys still walk it. With no lanes,
506
+ placeholder lines stand in the lane column. The plot is `aria-busy`
507
+ meanwhile.
508
+ @default false */
509
+ loading?: boolean;
552
510
  /** `Lane`, `Dependencies` and `Subtasks`, in the order they are to stand and
553
511
  be drawn. */
554
512
  children?: ReactNode;
555
513
  }
556
514
 
515
+ /** What `useSchedule` hands back: the schedule and what is declared inside
516
+ it, its view and the setters that change it. */
517
+ export declare interface ScheduleParts {
518
+ /** The schedule. One per `useSchedule`: a second schedule is a second call. */
519
+ Schedule: (props: ScheduleProps) => ReactNode;
520
+ Lane: typeof Lane;
521
+ LaneGroup: typeof LaneGroup;
522
+ Subtasks: typeof Subtasks;
523
+ Dependencies: typeof Dependencies;
524
+ BlockedTimes: typeof BlockedTimes;
525
+ Milestones: typeof Milestones;
526
+ /** How the planner is looking at the plan: the span and the folded groups. */
527
+ view: ScheduleView;
528
+ /** Goes to a whole view; what it leaves out is shown whole again. Not
529
+ reported through `onViewChange`: two schedules kept in step by
530
+ `onViewChange: (v) => other.setView(v)` in both directions do not answer
531
+ each other. A view with the content already shown changes nothing. */
532
+ setView: (view: ScheduleView) => void;
533
+ /** Puts a span of two wall-clock instants in view; `null` shows the
534
+ subtasks' extent. */
535
+ setDomain: (span: readonly [number, number] | null) => void;
536
+ /** Folds or unfolds one **Lane group**. */
537
+ toggleGroup: (id: string) => void;
538
+ /** The time and the lane at a client point, or null outside the plot - and
539
+ null while no schedule is mounted. */
540
+ positionAt: (clientX: number, clientY: number) => {
541
+ time: number;
542
+ lane: string | null;
543
+ } | null;
544
+ /** The client point of a time - on the middle of a lane where one is named -
545
+ or null while the schedule is not on screen. */
546
+ clientPointOf: (time: number, lane?: string) => {
547
+ x: number;
548
+ y: number;
549
+ } | null;
550
+ /** The visible span, as two wall-clock instants. */
551
+ visibleDomain: () => readonly [number, number];
552
+ /** Scrolls the lanes until the lane's row is in view, and returns `true`; `false`
553
+ and nothing changed for an unknown lane, one inside a folded **Lane group**
554
+ (none is unfolded), or while no schedule is mounted. */
555
+ scrollToLane: (lane: string) => boolean;
556
+ /** Brings the subtask's lane and time into view, the span moving to it and keeping its
557
+ width as `setDomain` would, and leaves the focus where it is; `false` and nothing
558
+ changed in the cases of `scrollToLane`. */
559
+ scrollToSubtask: (id: string) => boolean;
560
+ /** Does what `scrollToSubtask` does, then makes the subtask the **Active subtask** and
561
+ moves the focus to the plot, where the live region reads it out as the arrow keys do;
562
+ `false` and nothing changed in the cases of `scrollToLane`. */
563
+ focusSubtask: (id: string) => boolean;
564
+ /** Folds every group. */
565
+ foldAll: () => void;
566
+ /** Unfolds every group. */
567
+ unfoldAll: () => void;
568
+ }
569
+
570
+ /** The props of `Schedule`: the attributes of a `<div>` and what the schedule
571
+ reads itself. `ref`, `className`, `style` and the rest reach the root; the
572
+ name (`aria-label`, `aria-labelledby`) reaches the figure root and the plot,
573
+ and a `aria-describedby` of yours is joined to the plot's summary. */
574
+ export declare type ScheduleProps = ScheduleOwnProps & {
575
+ /** What the schedule shows, for a screen reader: "Plan of week 38". */
576
+ "aria-label": string;
577
+ };
578
+
557
579
  /** What a tooltip is about: the hovered subtask or dependency, with what the
558
580
  schedule knows about it. */
559
581
  export declare type ScheduleTooltipTarget = {
@@ -698,7 +720,8 @@ export declare interface Task {
698
720
  /** Declares a schedule: hands back `Schedule` and the parts declared inside it
699
721
  - `Lane`, `LaneGroup`, `Subtasks`, `Dependencies`, `BlockedTimes`, `Milestones` -, its
700
722
  `view` and the setters `setView`, `setDomain`, `toggleGroup`, `foldAll` and
701
- `unfoldAll`. A ref on `Schedule` still gives the `ScheduleHandle`. */
723
+ `unfoldAll`, `positionAt`, `clientPointOf` and `visibleDomain`, and `scrollToLane`, `scrollToSubtask` and
724
+ `focusSubtask`. */
702
725
  export declare function useSchedule(options?: ScheduleOptions): ScheduleParts;
703
726
 
704
727
  /** Every dependency whose successor is to be reached before the predecessor's
package/dist/schedule.css CHANGED
@@ -1 +1 @@
1
- @layer umriss.tokens,umriss.base,umriss.components;@layer umriss.base{._text_18806_22{font-family:var(--u-font-sans);font-size:var(--u-text-md);line-height:var(--u-leading-normal);color:var(--u-color-text);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}@media(pointer:fine){._dense_18806_38{--u-control-height-sm: var(--u-control-height-xs)}}._ink_18806_49{--u-color-text: var(--u-color-bg);--u-color-text-secondary: color-mix(in srgb, var(--u-color-bg) 75%, transparent);--u-color-text-muted: color-mix(in srgb, var(--u-color-bg) 60%, transparent)}._extent_18806_75{--_chars: 20;--_extra: 0;--_tracking: 0px;--_chrome: 0px;min-inline-size:0;max-inline-size:100%;contain:inline-size;contain-intrinsic-inline-size:calc((var(--_chars) + var(--_extra)) * (1ch + var(--_tracking)) + var(--_chrome))}._field_18806_90{caret-color:var(--u-color-accent)}._scroll_18806_96{scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--u-color-text) 25%,transparent) transparent}._scroll_18806_96::-webkit-scrollbar{width:10px;height:10px}._scroll_18806_96::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--u-color-text) 22%,transparent);border-radius:var(--u-radius-full);border:3px solid transparent;background-clip:content-box}._scroll_18806_96::-webkit-scrollbar-track{background:transparent}}@layer umriss.components{._ring_18806_125:focus-visible{outline:2px solid transparent;box-shadow:var(--u-focus-ring)}@media(pointer:coarse){._field_18806_90._field_18806_90,._fieldRoot_18806_145._fieldRoot_18806_145{font-size:16px}}._field_18806_90:-webkit-autofill,._field_18806_90:-webkit-autofill:hover,._field_18806_90:-webkit-autofill:focus{-webkit-box-shadow:inset 0 0 0 1000px var(--u-color-surface),0 0 0 1px var(--u-edge-color-strong);-webkit-text-fill-color:var(--u-color-text);caret-color:var(--u-color-accent)}}@layer umriss.components{._root_1g7hg_4,._root_1g7hg_4:before,._root_1g7hg_4:after{box-sizing:border-box}._corner_1g7hg_19,._corner_1g7hg_19:before,._corner_1g7hg_19:after{box-sizing:border-box}._dayBand_1g7hg_23,._dayBand_1g7hg_23:before,._dayBand_1g7hg_23:after{box-sizing:border-box}._tickBand_1g7hg_24,._tickBand_1g7hg_24:before,._tickBand_1g7hg_24:after{box-sizing:border-box}._day_1g7hg_23,._day_1g7hg_23:before,._day_1g7hg_23:after{box-sizing:border-box}._dayLabel_1g7hg_50,._dayLabel_1g7hg_50:before,._dayLabel_1g7hg_50:after{box-sizing:border-box}._tick_1g7hg_24,._tick_1g7hg_24:before,._tick_1g7hg_24:after{box-sizing:border-box}._tickLabel_1g7hg_71,._tickLabel_1g7hg_71:before,._tickLabel_1g7hg_71:after{box-sizing:border-box}._headers_1g7hg_79,._headers_1g7hg_79:before,._headers_1g7hg_79:after{box-sizing:border-box}._header_1g7hg_79,._header_1g7hg_79:before,._header_1g7hg_79:after{box-sizing:border-box}._headerLabel_1g7hg_97,._headerLabel_1g7hg_97:before,._headerLabel_1g7hg_97:after{box-sizing:border-box}._headerCount_1g7hg_133,._headerCount_1g7hg_133:before,._headerCount_1g7hg_133:after{box-sizing:border-box}._chevron_1g7hg_142,._chevron_1g7hg_142:before,._chevron_1g7hg_142:after{box-sizing:border-box}._plot_1g7hg_197,._plot_1g7hg_197:before,._plot_1g7hg_197:after{box-sizing:border-box}._focusRing_1g7hg_204,._focusRing_1g7hg_204:before,._focusRing_1g7hg_204:after{box-sizing:border-box}._layer_1g7hg_222,._layer_1g7hg_222:before,._layer_1g7hg_222:after{box-sizing:border-box}._grip_1g7hg_231,._grip_1g7hg_231:before,._grip_1g7hg_231:after{box-sizing:border-box}._ghostLabel_1g7hg_241,._ghostLabel_1g7hg_241:before,._ghostLabel_1g7hg_241:after{box-sizing:border-box}._finding_1g7hg_254,._finding_1g7hg_254:before,._finding_1g7hg_254:after{box-sizing:border-box}._refusal_1g7hg_262,._refusal_1g7hg_262:before,._refusal_1g7hg_262:after{box-sizing:border-box}._tooltip_1g7hg_266,._tooltip_1g7hg_266:before,._tooltip_1g7hg_266:after{box-sizing:border-box}._tooltipHead_1g7hg_285,._tooltipHead_1g7hg_285:before,._tooltipHead_1g7hg_285:after{box-sizing:border-box}._tooltipTimes_1g7hg_290,._tooltipTimes_1g7hg_290:before,._tooltipTimes_1g7hg_290:after{box-sizing:border-box}._now_1g7hg_299,._now_1g7hg_299:before,._now_1g7hg_299:after{box-sizing:border-box}._barLabel_1g7hg_313,._barLabel_1g7hg_313:before,._barLabel_1g7hg_313:after{box-sizing:border-box}._barLabelText_1g7hg_326,._barLabelText_1g7hg_326:before,._barLabelText_1g7hg_326:after{box-sizing:border-box}._root_1g7hg_4{display:grid;grid-template-rows:28px minmax(0,1fr) 28px;width:100%;font-size:var(--u-text-sm);background:var(--u-color-surface);outline:1px solid transparent;box-shadow:var(--u-edge);border-radius:var(--u-radius-md);corner-shape:squircle;overflow:hidden;font-variant-numeric:tabular-nums;user-select:none}._corner_1g7hg_19{background:var(--u-color-surface)}._dayBand_1g7hg_23,._tickBand_1g7hg_24{position:relative;overflow:hidden;color:var(--u-color-text-muted);font-size:var(--u-text-xs)}._dayBand_1g7hg_23{border-bottom:1px solid var(--u-hairline-strong)}._tickBand_1g7hg_24{border-top:1px solid var(--u-hairline-strong)}._day_1g7hg_23{position:absolute;top:0;bottom:0;border-left:1px solid var(--u-hairline-strong);overflow:hidden}._dayLabel_1g7hg_50{position:absolute;z-index:1;left:var(--u-space-1);padding:0 var(--u-space-1);background:var(--u-color-surface);top:50%;transform:translateY(-50%);white-space:nowrap;color:var(--u-color-text);font-weight:var(--u-weight-medium)}._tick_1g7hg_24{position:absolute;top:0;bottom:0;width:1px;background:var(--u-hairline)}._tickLabel_1g7hg_71{position:absolute;top:50%;left:0;transform:translate(-50%,-50%);white-space:nowrap}._headers_1g7hg_79{position:relative;overflow:hidden;border-right:1px solid var(--u-hairline-strong)}._header_1g7hg_79{display:flex;align-items:center;gap:var(--u-space-2);padding-right:var(--u-space-3);border-bottom:1px solid var(--u-hairline);overflow:hidden;white-space:nowrap}._headerLabel_1g7hg_97{min-width:0;overflow:hidden;text-overflow:ellipsis}._header_1g7hg_79[data-row=lane],._header_1g7hg_79[data-row=miniature]{container:lane-header / size}@container lane-header (height >= 2.5rem){._headerLabel_1g7hg_97:not(:has(*)){display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;white-space:normal;text-wrap:balance}}._header_1g7hg_79[data-row=groupHead],._header_1g7hg_79[data-row=miniature]{font-weight:var(--u-weight-medium)}._headerCount_1g7hg_133{flex:none;color:var(--u-color-text-muted);font-size:var(--u-text-xs);font-variant-numeric:tabular-nums}._chevron_1g7hg_142{flex:none;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;border-radius:var(--u-radius-xs);corner-shape:squircle;background:transparent;color:var(--u-color-text-secondary);cursor:pointer;transition:background-color var(--u-transition),color var(--u-transition)}._chevron_1g7hg_142:hover{background:var(--u-color-surface-sunken);color:var(--u-color-text)}._chevron_1g7hg_142:active{background:var(--u-color-surface-pressed)}._chevron_1g7hg_142:focus-visible{outline:2px solid transparent;box-shadow:var(--u-focus-ring)}._chevron_1g7hg_142 svg{box-sizing:border-box}._chevron_1g7hg_142 svg{transition:transform var(--u-transition-path)}._chevron_1g7hg_142 svg[data-open]{box-sizing:border-box}._chevron_1g7hg_142 svg[data-open]{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){._chevron_1g7hg_142 svg{transition:none}}._header_1g7hg_79[data-refused]{color:var(--u-color-text-muted)}._plot_1g7hg_197{position:relative;overflow:hidden;touch-action:none}._plot_1g7hg_197:focus{outline:none}._focusRing_1g7hg_204{position:absolute;inset:2px;border-radius:var(--u-radius-md);corner-shape:squircle;pointer-events:none}._plot_1g7hg_197:focus-visible>._focusRing_1g7hg_204{outline:2px solid transparent;box-shadow:var(--u-focus-ring)}._layer_1g7hg_222{position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none}._grip_1g7hg_231{position:absolute;width:9px;margin-left:-4px;border-radius:var(--u-radius-xs);corner-shape:squircle;background:var(--u-color-surface);box-shadow:inset 0 0 0 1.5px var(--u-color-text);cursor:ew-resize}._ghostLabel_1g7hg_241{position:absolute;display:inline-flex;gap:var(--u-space-2);padding:1px var(--u-space-2);border-radius:var(--u-radius-sm);corner-shape:squircle;background:var(--u-color-text);color:var(--u-color-surface);font-size:var(--u-text-xs);white-space:nowrap;pointer-events:none}._finding_1g7hg_254{font-weight:var(--u-weight-semibold);color:var(--u-color-danger-subtle)}._refusal_1g7hg_262{font-weight:var(--u-weight-semibold)}._tooltip_1g7hg_266{position:absolute;z-index:1;display:flex;flex-direction:column;gap:1px;max-width:260px;padding:var(--u-space-2) var(--u-space-3);border-radius:var(--u-radius-sm);corner-shape:squircle;background:var(--u-color-surface);outline:1px solid transparent;box-shadow:var(--u-shadow-overlay);color:var(--u-color-text-secondary);font-size:var(--u-text-xs);line-height:var(--u-leading-tight);pointer-events:none;white-space:nowrap}._tooltipHead_1g7hg_285{color:var(--u-color-text);font-weight:var(--u-weight-semibold)}._tooltipTimes_1g7hg_290{color:var(--u-color-text)}._tooltip_1g7hg_266 ._finding_1g7hg_254{color:var(--u-color-danger-text)}._now_1g7hg_299{position:absolute;top:0;width:0;height:0;margin-left:-4px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:6px solid var(--u-color-accent)}._barLabel_1g7hg_313{position:absolute;display:flex;align-items:center;padding:0 var(--u-space-1);overflow:hidden;font-size:var(--u-text-xs);line-height:var(--u-leading-tight);pointer-events:none}._barLabelText_1g7hg_326{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}._barLabel_1g7hg_313[data-on=dark]{color:var(--u-color-on-accent)}._barLabel_1g7hg_313[data-on=light]{color:var(--u-color-text)}@media(forced-colors:active){._grip_1g7hg_231{outline:2px solid CanvasText;outline-offset:-2px}._ghostLabel_1g7hg_241{outline:1px solid CanvasText}}}
1
+ @layer umriss.tokens,umriss.base,umriss.components;@layer umriss.base{._text_18806_22{font-family:var(--u-font-sans);font-size:var(--u-text-md);line-height:var(--u-leading-normal);color:var(--u-color-text);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}@media(pointer:fine){._dense_18806_38{--u-control-height-sm: var(--u-control-height-xs)}}._ink_18806_49{--u-color-text: var(--u-color-bg);--u-color-text-secondary: color-mix(in srgb, var(--u-color-bg) 75%, transparent);--u-color-text-muted: color-mix(in srgb, var(--u-color-bg) 60%, transparent)}._extent_18806_75{--_chars: 20;--_extra: 0;--_tracking: 0px;--_chrome: 0px;min-inline-size:0;max-inline-size:100%;contain:inline-size;contain-intrinsic-inline-size:calc((var(--_chars) + var(--_extra)) * (1ch + var(--_tracking)) + var(--_chrome))}._field_18806_90{caret-color:var(--u-color-accent)}._scroll_18806_96{scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--u-color-text) 25%,transparent) transparent}._scroll_18806_96::-webkit-scrollbar{width:10px;height:10px}._scroll_18806_96::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--u-color-text) 22%,transparent);border-radius:var(--u-radius-full);border:3px solid transparent;background-clip:content-box}._scroll_18806_96::-webkit-scrollbar-track{background:transparent}}@layer umriss.components{._ring_18806_125:focus-visible{outline:2px solid transparent;box-shadow:var(--u-focus-ring)}@media(pointer:coarse){._field_18806_90._field_18806_90,._fieldRoot_18806_145._fieldRoot_18806_145{font-size:16px}}._field_18806_90:-webkit-autofill,._field_18806_90:-webkit-autofill:hover,._field_18806_90:-webkit-autofill:focus{-webkit-box-shadow:inset 0 0 0 1000px var(--u-color-surface),0 0 0 1px var(--u-edge-color-strong);-webkit-text-fill-color:var(--u-color-text);caret-color:var(--u-color-accent)}}@layer umriss.components{._root_mm9nj_4,._root_mm9nj_4:before,._root_mm9nj_4:after{box-sizing:border-box}._corner_mm9nj_19,._corner_mm9nj_19:before,._corner_mm9nj_19:after{box-sizing:border-box}._dayBand_mm9nj_23,._dayBand_mm9nj_23:before,._dayBand_mm9nj_23:after{box-sizing:border-box}._tickBand_mm9nj_24,._tickBand_mm9nj_24:before,._tickBand_mm9nj_24:after{box-sizing:border-box}._day_mm9nj_23,._day_mm9nj_23:before,._day_mm9nj_23:after{box-sizing:border-box}._dayLabel_mm9nj_50,._dayLabel_mm9nj_50:before,._dayLabel_mm9nj_50:after{box-sizing:border-box}._tick_mm9nj_24,._tick_mm9nj_24:before,._tick_mm9nj_24:after{box-sizing:border-box}._tickLabel_mm9nj_71,._tickLabel_mm9nj_71:before,._tickLabel_mm9nj_71:after{box-sizing:border-box}._headers_mm9nj_81,._headers_mm9nj_81:before,._headers_mm9nj_81:after{box-sizing:border-box}._header_mm9nj_81,._header_mm9nj_81:before,._header_mm9nj_81:after{box-sizing:border-box}._headerLabel_mm9nj_100,._headerLabel_mm9nj_100:before,._headerLabel_mm9nj_100:after{box-sizing:border-box}._headerCount_mm9nj_136,._headerCount_mm9nj_136:before,._headerCount_mm9nj_136:after{box-sizing:border-box}._chevron_mm9nj_145,._chevron_mm9nj_145:before,._chevron_mm9nj_145:after{box-sizing:border-box}._plot_mm9nj_223,._plot_mm9nj_223:before,._plot_mm9nj_223:after{box-sizing:border-box}._focusRing_mm9nj_237,._focusRing_mm9nj_237:before,._focusRing_mm9nj_237:after{box-sizing:border-box}._layer_mm9nj_255,._layer_mm9nj_255:before,._layer_mm9nj_255:after{box-sizing:border-box}._grip_mm9nj_282,._grip_mm9nj_282:before,._grip_mm9nj_282:after{box-sizing:border-box}._ghostLabel_mm9nj_292,._ghostLabel_mm9nj_292:before,._ghostLabel_mm9nj_292:after{box-sizing:border-box}._finding_mm9nj_305,._finding_mm9nj_305:before,._finding_mm9nj_305:after{box-sizing:border-box}._refusal_mm9nj_313,._refusal_mm9nj_313:before,._refusal_mm9nj_313:after{box-sizing:border-box}._tooltip_mm9nj_317,._tooltip_mm9nj_317:before,._tooltip_mm9nj_317:after{box-sizing:border-box}._tooltipHead_mm9nj_336,._tooltipHead_mm9nj_336:before,._tooltipHead_mm9nj_336:after{box-sizing:border-box}._tooltipTimes_mm9nj_341,._tooltipTimes_mm9nj_341:before,._tooltipTimes_mm9nj_341:after{box-sizing:border-box}._now_mm9nj_350,._now_mm9nj_350:before,._now_mm9nj_350:after{box-sizing:border-box}._barLabel_mm9nj_364,._barLabel_mm9nj_364:before,._barLabel_mm9nj_364:after{box-sizing:border-box}._barLabelText_mm9nj_377,._barLabelText_mm9nj_377:before,._barLabelText_mm9nj_377:after{box-sizing:border-box}._root_mm9nj_4{display:grid;grid-template-rows:28px minmax(0,1fr) 28px;width:100%;font-size:var(--u-text-sm);background:var(--u-color-surface);outline:1px solid transparent;box-shadow:var(--u-edge);border-radius:var(--u-radius-md);corner-shape:squircle;overflow:hidden;font-variant-numeric:tabular-nums;user-select:none}._corner_mm9nj_19{background:var(--u-color-surface)}._dayBand_mm9nj_23,._tickBand_mm9nj_24{position:relative;overflow:hidden;color:var(--u-color-text-muted);font-size:var(--u-text-xs)}._dayBand_mm9nj_23{border-bottom:1px solid var(--u-hairline-strong)}._tickBand_mm9nj_24{border-top:1px solid var(--u-hairline-strong)}._day_mm9nj_23{position:absolute;top:0;bottom:0;border-left:1px solid var(--u-hairline-strong);overflow:hidden}._dayLabel_mm9nj_50{position:absolute;z-index:1;left:var(--u-space-1);padding:0 var(--u-space-1);background:var(--u-color-surface);top:50%;transform:translateY(-50%);white-space:nowrap;color:var(--u-color-text);font-weight:var(--u-weight-medium)}._tick_mm9nj_24{position:absolute;top:0;bottom:0;width:1px;background:var(--u-hairline)}._tickLabel_mm9nj_71{position:absolute;top:50%;left:0;transform:translate(-50%,-50%);white-space:nowrap}._headers_mm9nj_81{contain:size;position:relative;overflow:hidden;border-right:1px solid var(--u-hairline-strong)}._header_mm9nj_81{display:flex;align-items:center;gap:var(--u-space-2);padding-right:var(--u-space-3);border-bottom:1px solid var(--u-hairline);overflow:hidden;white-space:nowrap}._headerLabel_mm9nj_100{min-width:0;overflow:hidden;text-overflow:ellipsis}._header_mm9nj_81[data-row=lane],._header_mm9nj_81[data-row=miniature]{container:lane-header / size}@container lane-header (height >= 2.5rem){._headerLabel_mm9nj_100:not(:has(*)){display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;white-space:normal;text-wrap:balance}}._header_mm9nj_81[data-row=groupHead],._header_mm9nj_81[data-row=miniature]{font-weight:var(--u-weight-medium)}._headerCount_mm9nj_136{flex:none;color:var(--u-color-text-muted);font-size:var(--u-text-xs);font-variant-numeric:tabular-nums}._chevron_mm9nj_145{flex:none;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;border-radius:var(--u-radius-xs);corner-shape:squircle;background:transparent;color:var(--u-color-text-secondary);cursor:pointer;transition:background-color var(--u-transition),color var(--u-transition)}._chevron_mm9nj_145:hover{background:var(--u-color-surface-sunken);color:var(--u-color-text)}._chevron_mm9nj_145:active{background:var(--u-color-surface-pressed)}._chevron_mm9nj_145:focus-visible{outline:2px solid transparent;box-shadow:var(--u-focus-ring)}._chevron_mm9nj_145 svg{box-sizing:border-box}._chevron_mm9nj_145 svg{transition:transform var(--u-transition-path)}._chevron_mm9nj_145 svg[data-open]{box-sizing:border-box}._chevron_mm9nj_145 svg[data-open]{transform:rotate(90deg)}@media(pointer:coarse){._chevron_mm9nj_145{position:relative}._chevron_mm9nj_145:after{content:"";position:absolute;inset:-4px}._header_mm9nj_81[data-row=groupHead]{overflow:clip;overflow-clip-margin:2px}}@media(prefers-reduced-motion:reduce){._chevron_mm9nj_145 svg{transition:none}}._header_mm9nj_81[data-refused]{color:var(--u-color-text-muted)}._plot_mm9nj_223{contain:size;position:relative;overflow:hidden;touch-action:none;-webkit-touch-callout:none;user-select:none}._plot_mm9nj_223:focus{outline:none}._focusRing_mm9nj_237{position:absolute;inset:2px;border-radius:var(--u-radius-md);corner-shape:squircle;pointer-events:none}._plot_mm9nj_223:focus-visible>._focusRing_mm9nj_237{outline:2px solid transparent;box-shadow:var(--u-focus-ring)}._layer_mm9nj_255{position:absolute;inset:0;width:100%;height:100%;display:block;pointer-events:none}._plot_mm9nj_223[data-stale]{pointer-events:none}._plot_mm9nj_223[data-stale]>:not(._focusRing_mm9nj_237){opacity:.5;transition:opacity var(--u-transition, .12s cubic-bezier(.22, 1, .36, 1)) var(--u-delay-stale, .2s)}@media(prefers-reduced-motion:reduce){._plot_mm9nj_223[data-stale]>:not(._focusRing_mm9nj_237){transition-duration:0s}}._grip_mm9nj_282{position:absolute;width:9px;margin-left:-4px;border-radius:var(--u-radius-xs);corner-shape:squircle;background:var(--u-color-surface);box-shadow:inset 0 0 0 1.5px var(--u-color-text);cursor:ew-resize}._ghostLabel_mm9nj_292{position:absolute;display:inline-flex;gap:var(--u-space-2);padding:1px var(--u-space-2);border-radius:var(--u-radius-sm);corner-shape:squircle;background:var(--u-color-text);color:var(--u-color-surface);font-size:var(--u-text-xs);white-space:nowrap;pointer-events:none}._finding_mm9nj_305{font-weight:var(--u-weight-semibold);color:var(--u-color-danger-subtle)}._refusal_mm9nj_313{font-weight:var(--u-weight-semibold)}._tooltip_mm9nj_317{position:absolute;z-index:1;display:flex;flex-direction:column;gap:1px;max-width:260px;padding:var(--u-space-2) var(--u-space-3);border-radius:var(--u-radius-sm);corner-shape:squircle;background:var(--u-color-surface);outline:1px solid transparent;box-shadow:var(--u-shadow-overlay);color:var(--u-color-text-secondary);font-size:var(--u-text-xs);line-height:var(--u-leading-tight);pointer-events:none;white-space:nowrap}._tooltipHead_mm9nj_336{color:var(--u-color-text);font-weight:var(--u-weight-semibold)}._tooltipTimes_mm9nj_341{color:var(--u-color-text)}._tooltip_mm9nj_317 ._finding_mm9nj_305{color:var(--u-color-danger-text)}._now_mm9nj_350{position:absolute;top:0;width:0;height:0;margin-left:-4px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:6px solid var(--u-color-accent)}._barLabel_mm9nj_364{position:absolute;display:flex;align-items:center;padding:0 var(--u-space-1);overflow:hidden;font-size:var(--u-text-xs);line-height:var(--u-leading-tight);pointer-events:none}._barLabelText_mm9nj_377{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}._barLabel_mm9nj_364[data-on=dark]{color:var(--u-color-on-accent)}._barLabel_mm9nj_364[data-on=light]{color:var(--u-color-text)}@media(forced-colors:active){._grip_mm9nj_282{outline:2px solid CanvasText;outline-offset:-2px}._ghostLabel_mm9nj_292{outline:1px solid CanvasText}}}