@timebraid/vue 1.16.0 → 1.18.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/README.md CHANGED
@@ -35,6 +35,8 @@ Import `@timebraid/tokens/styles.css` once in `main.ts` (or `@timebraid/vue/styl
35
35
  | `TField` | Filled text field |
36
36
  | `TSelect` | Trailing-value select with `chevrons-up-down`, used inside `TRow`; name the control with `label` (rendered visually hidden) or `ariaLabel` |
37
37
  | `TBadge` | Status pill: neutral, running, green, red, soon |
38
+ | `TKbd` | A keycap: "⌘K", "↵" or "esc" in mono on `--fill` inside a `--sep-strong` ring, 20px (`md` 24px); the palette's rows and foot use it |
39
+ | `TBanner` | Full-width bar for a standing notice such as "Signed in as Mia Okafor" while an admin acts as another person: an optional icon, a bold title with the text (or the default slot) under it, and a pill `action` on the right; `inverse` (the tooltip's `--label` and `--bg` pairing) by default or `accent`, `compact` for the phone sizes |
38
40
  | `TBar` | Animated value bar |
39
41
  | `TBudgetBar` | A budget bar for Reports: used fills the track, the gap up to where the budget stands by now is tinted and marked, time past the budget runs red |
40
42
  | `TGoalBar` | Today's goal bar: done fills a `--fill` track in green and the catch-up share of the target is hatched in orange at the right end until the goal is met |
@@ -49,10 +51,11 @@ Import `@timebraid/tokens/styles.css` once in `main.ts` (or `@timebraid/vue/styl
49
51
  | `TPill` | The floating always-visible timer pill: count first, the longest timer leads; the `popover` slot (scoped with `running`) replaces the popover body, grouped by workspace then project, and `open` is consumer-owned through `update:open`; with several timers its stop control opens the popover, where Stop all sits top right |
50
52
  | `TWsIcon` | Workspace glyph: a coloured initial square, or the app mark when `all` |
51
53
  | `TWsTag` | Small workspace label, the square plus its name; appears only in the All-workspaces scope |
52
- | `TWorkspaceSwitcher` | Scope selector: All workspaces or one |
53
- | `TWorkspaceMenu` | The workspace list shared by the switcher's popover and the drawer; `embedded` drops its shadow for inline use |
54
- | `TWorkspaceDrawer` | Full-height phone workspace list; drag the panel to dismiss |
54
+ | `TWorkspaceSwitcher` | Scope selector: All workspaces or one; `actions` adds rows such as Admin portal under the list, each closing the menu and emitting `action` with its id |
55
+ | `TWorkspaceMenu` | The workspace list shared by the switcher's popover and the drawer; `embedded` drops its shadow for inline use; `actions` sit between two hairlines above New workspace |
56
+ | `TWorkspaceDrawer` | Full-height phone workspace list; drag the panel to dismiss; `actions` pin above Add a workspace and emit `action` with the id, then `close` |
55
57
  | `TTimerBar` | Phone bottom timer bar: takes the full `timers` array, count first with the longest leading; with several timers its stop control emits `open` for the running sheet instead of stopping them all |
58
+ | `TAuthBackdrop` | The sign-in stage from the app icon: brand field, oversized stopwatch dial, sweeping orange hand |
56
59
  | `TStrokes` | Oversized faded tally strokes behind sign-in and empty states |
57
60
  | `TStartHero` | The pill-shaped start field that opens Today: "Start a timer" with "Quick start" chips on desktop when nothing runs, "Start another timer" with a "Runs in parallel" hint (chips kept) when `hasRunning`, the bare pill when `mobile` |
58
61
  | `TIOSNav` | iOS nav bar under the status-bar inset (`--inset-top`); the `leading` control, the large title and the `right` actions share one line and the title collapses in place on scroll |
@@ -71,6 +74,7 @@ Import `@timebraid/tokens/styles.css` once in `main.ts` (or `@timebraid/vue/styl
71
74
  | `TPeriodStepper` | ‹ This week › at the top of a chart card: the arrows step one day, week or month, the label opens a `TMenu` of Day, Week, Month and Custom range…, and a text link returns to the current period |
72
75
  | `TMenu` | A small choice menu: a 230px popover under its anchor on the desktop, a bottom sheet of rows on the phone, the chosen item in accent with a check |
73
76
  | `TSearchField` | Page search field with a `/` keycap that focuses it from anywhere, a clear button once there is text, and Escape to clear and blur; `size="sm"` for lists in sheets, `busy` for a spinner |
77
+ | `TCommandPalette` | The ⌘K search: a centred dialog on a scrim with a combobox head, grouped option rows led by an avatar, a colour dot or an icon tile with the query marked in every title, hints and keycaps on the right, arrow keys, Enter and Escape, an empty state and a foot of keycap hints; `mobile` fills the screen with Cancel; `paletteIds` and `stepActive` walk the groups |
74
78
  | `TParallelMark` | Two short running bars, titled "Ran alongside {names}"; replaces the "in parallel" chip on rows |
75
79
  | `TAutoStopMark` | An orange `timer-off`, titled "Stopped automatically. Check the end time"; replaces that chip on rows |
76
80
  | `TFilterButton` | The Filters button beside search; accent with a count badge when filters are on, icon-only with a corner badge when `compact` |
@@ -78,8 +82,11 @@ Import `@timebraid/tokens/styles.css` once in `main.ts` (or `@timebraid/vue/styl
78
82
  | `TFilterSheet` | The Filters sheet of Entries and Reports: an accordion of Workspace, Project, Task and Person (each a `TPickList` fed by `fetchOptions`), Show only (switch rows) and Notes (a check list), with each value on the right; picks cascade through `parentOf`, it keeps a draft and emits `apply` |
79
83
  | `TPickList` | A long multi-pick list that stays five rows tall: debounced server search with a spinner and dimmed old rows, picked rows first and frozen while open, 20 more rows per page as you scroll, and a fade at the bottom until the end |
80
84
  | `THighlight` | Text with every word of a query marked in `--accent-soft-2` |
85
+ | `TPager` | The strip under a paged list: a flat, right-aligned stepper ‹ 10 per page ▾ › under a hairline (a menu of 10, 25 and 50, arrows through the pages) with the range ("1–10 of 34") small on the left; `pageSlice` and `pageable` do the paging |
86
+ | `TSkeleton` | A shimmering placeholder block (text line, block, circle or pill) for a page that has not drawn yet; `.t-skeleton` in the tokens paints the shimmer |
87
+ | `TSkeletonList` | The skeleton of a list card: rows of a leading mark, two lines of differing length and a short right block |
81
88
 
82
- Also exported: `formatDuration(seconds, 'clock' | 'short' | 'compact' | 'friendly')`, the timeline helpers (`timelineSpan`, `isRunningEntry`, `parallelMinutes`, `parallelPartners`), the task colours (`taskSwatches`, `swatchFill`, `swatchInk`, `SWATCH_COLORS`, `STRIPES`, `RUNNING_SHEEN`), `hourLabel`, `minutesToAmPm`, `toggleId`, the filter helpers (`emptyFilters`, `copyFilters`, `filterCount`, `entriesText`, `ENTRY_FLAGS`, `NOTE_FILTERS`, `DIMENSION_KEYS`, `FLAG_LABELS`, `FLAG_HINTS`, `NOTE_LABELS`) and their types, `PickItem` and `PickPage`, `highlightSegments`, `PROJECT_COLORS`, `TIMEBRAID_ICON_BASE`, `DEFAULT_ICON_BASE`, `resolveTheme`, `applyTheme`, `watchTheme`, `THEME_PREFERENCES`.
89
+ Also exported: `formatDuration(seconds, 'clock' | 'short' | 'compact' | 'friendly')`, the timeline helpers (`timelineSpan`, `isRunningEntry`, `parallelMinutes`, `parallelPartners`), the task colours (`taskSwatches`, `swatchFill`, `swatchInk`, `SWATCH_COLORS`, `STRIPES`, `RUNNING_SHEEN`), `hourLabel`, `minutesToAmPm`, `toggleId`, the filter helpers (`emptyFilters`, `copyFilters`, `filterCount`, `entriesText`, `ENTRY_FLAGS`, `NOTE_FILTERS`, `DIMENSION_KEYS`, `FLAG_LABELS`, `FLAG_HINTS`, `NOTE_LABELS`) and their types, `PickItem` and `PickPage`, `highlightSegments`, the palette helpers (`paletteIds`, `stepActive`) and their types `PaletteItem` and `PaletteGroup`, `PROJECT_COLORS`, `TIMEBRAID_ICON_BASE`, `DEFAULT_ICON_BASE`, `resolveTheme`, `applyTheme`, `watchTheme`, `THEME_PREFERENCES`.
83
90
 
84
91
  `TIcon` ships its glyphs: `scripts/glyphs.mjs` writes the Lucide paths for every name the products use into `packages/vue/src/icons/glyphs.ts`, and the component renders them inline in `currentColor`. Nothing is fetched at runtime. To add a glyph, add its name to `NAMES` in the script and run `pnpm glyphs`. `ICON_NAMES` and `hasIcon()` are exported so an app can assert every name it uses is bundled. A name missing from the table still masks from `TIMEBRAID_ICON_BASE` (or the `base` prop) with a dev warning, so nothing breaks while the table catches up.
85
92
 
package/dist/index.d.ts CHANGED
@@ -12,19 +12,20 @@ plainTitle: boolean;
12
12
  declare const __VLS_component_10: DefineComponent<__VLS_Props_34, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
13
13
  stop: (id: string) => any;
14
14
  start: () => any;
15
+ openApp: () => any;
15
16
  "update:open": (v: boolean) => any;
16
17
  stopAll: () => any;
17
- openApp: () => any;
18
18
  }, string, PublicProps, Readonly<__VLS_Props_34> & Readonly<{
19
19
  onStop?: ((id: string) => any) | undefined;
20
20
  onStart?: (() => any) | undefined;
21
+ onOpenApp?: (() => any) | undefined;
21
22
  "onUpdate:open"?: ((v: boolean) => any) | undefined;
22
23
  onStopAll?: (() => any) | undefined;
23
- onOpenApp?: (() => any) | undefined;
24
24
  }>, {
25
25
  compact: boolean;
26
26
  open: boolean;
27
27
  paused: boolean;
28
+ openApp: boolean;
28
29
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
29
30
 
30
31
  declare const __VLS_component_11: DefineComponent<__VLS_Props_41, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_41> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
@@ -57,6 +58,18 @@ multiple: boolean;
57
58
  addLabel: string;
58
59
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
59
60
 
61
+ declare const __VLS_component_16: DefineComponent<__VLS_Props_66, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
62
+ action: () => any;
63
+ }, string, PublicProps, Readonly<__VLS_Props_66> & Readonly<{
64
+ onAction?: (() => any) | undefined;
65
+ }>, {
66
+ text: string;
67
+ icon: string;
68
+ tone: keyof typeof TONES_5;
69
+ action: string;
70
+ compact: boolean;
71
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
72
+
60
73
  declare const __VLS_component_2: DefineComponent<__VLS_Props_2, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
61
74
  click: (event: MouseEvent | KeyboardEvent) => any;
62
75
  }, string, PublicProps, Readonly<__VLS_Props_2> & Readonly<{
@@ -371,6 +384,7 @@ declare type __VLS_Props_34 = {
371
384
  compact?: boolean;
372
385
  paused?: boolean;
373
386
  open?: boolean;
387
+ openApp?: boolean;
374
388
  };
375
389
 
376
390
  declare type __VLS_Props_35 = {
@@ -378,6 +392,7 @@ declare type __VLS_Props_35 = {
378
392
  modelValue: string;
379
393
  showAll?: boolean;
380
394
  teleport?: boolean;
395
+ actions?: readonly WorkspaceAction[];
381
396
  };
382
397
 
383
398
  declare type __VLS_Props_36 = {
@@ -385,6 +400,7 @@ declare type __VLS_Props_36 = {
385
400
  modelValue: string;
386
401
  showAll?: boolean;
387
402
  embedded?: boolean;
403
+ actions?: readonly WorkspaceAction[];
388
404
  };
389
405
 
390
406
  declare type __VLS_Props_37 = {
@@ -394,6 +410,7 @@ declare type __VLS_Props_37 = {
394
410
  showAll?: boolean;
395
411
  teleport?: boolean;
396
412
  user?: DrawerUser | null;
413
+ actions?: readonly WorkspaceAction[];
397
414
  };
398
415
 
399
416
  declare type __VLS_Props_38 = {
@@ -619,6 +636,44 @@ declare type __VLS_Props_62 = {
619
636
  query?: string;
620
637
  };
621
638
 
639
+ declare type __VLS_Props_63 = {
640
+ page: number;
641
+ pageSize: number;
642
+ total: number;
643
+ sizes?: readonly number[];
644
+ compact?: boolean;
645
+ mobile?: boolean;
646
+ teleport?: boolean;
647
+ last?: boolean;
648
+ };
649
+
650
+ declare type __VLS_Props_64 = {
651
+ width?: string;
652
+ height?: number;
653
+ shape?: keyof typeof RADIUS;
654
+ };
655
+
656
+ declare type __VLS_Props_65 = {
657
+ rows?: number;
658
+ leading?: keyof typeof LEADING;
659
+ trailing?: boolean;
660
+ subtitle?: boolean;
661
+ };
662
+
663
+ declare type __VLS_Props_66 = {
664
+ title: string;
665
+ text?: string;
666
+ icon?: string;
667
+ action?: string;
668
+ tone?: keyof typeof TONES_5;
669
+ compact?: boolean;
670
+ };
671
+
672
+ declare type __VLS_Props_67 = {
673
+ keys: string;
674
+ size?: keyof typeof SIZES_3;
675
+ };
676
+
622
677
  declare type __VLS_Props_7 = {
623
678
  modelValue: string;
624
679
  options: {
@@ -728,6 +783,15 @@ declare function __VLS_template_15(): {
728
783
  rootEl: HTMLDivElement;
729
784
  };
730
785
 
786
+ declare function __VLS_template_16(): {
787
+ attrs: Partial<{}>;
788
+ slots: {
789
+ default?(_: {}): any;
790
+ };
791
+ refs: {};
792
+ rootEl: HTMLDivElement;
793
+ };
794
+
731
795
  declare function __VLS_template_2(): {
732
796
  attrs: Partial<{}>;
733
797
  slots: {
@@ -826,6 +890,8 @@ declare type __VLS_TemplateResult_14 = ReturnType<typeof __VLS_template_14>;
826
890
 
827
891
  declare type __VLS_TemplateResult_15 = ReturnType<typeof __VLS_template_15>;
828
892
 
893
+ declare type __VLS_TemplateResult_16 = ReturnType<typeof __VLS_template_16>;
894
+
829
895
  declare type __VLS_TemplateResult_2 = ReturnType<typeof __VLS_template_2>;
830
896
 
831
897
  declare type __VLS_TemplateResult_3 = ReturnType<typeof __VLS_template_3>;
@@ -884,6 +950,12 @@ declare type __VLS_WithTemplateSlots_15<T, S> = T & {
884
950
  };
885
951
  };
886
952
 
953
+ declare type __VLS_WithTemplateSlots_16<T, S> = T & {
954
+ new (): {
955
+ $slots: S;
956
+ };
957
+ };
958
+
887
959
  declare type __VLS_WithTemplateSlots_2<T, S> = T & {
888
960
  new (): {
889
961
  $slots: S;
@@ -953,6 +1025,8 @@ export declare function clampOffset(x: number, y: number, z: number, stage: numb
953
1025
  y: number;
954
1026
  };
955
1027
 
1028
+ export declare const clampPage: (page: number, total: number, size: number) => number;
1029
+
956
1030
  export declare const clampZoom: (z: number) => number;
957
1031
 
958
1032
  export declare function clockToMinutes(clock: string): number | null;
@@ -977,6 +1051,8 @@ export declare interface CustomRange {
977
1051
  /** Where TIcon masks from when nothing overrides it. */
978
1052
  export declare const DEFAULT_ICON_BASE = "https://unpkg.com/lucide-static@0.545.0/icons/";
979
1053
 
1054
+ export declare const DEFAULT_PAGE_SIZE = 10;
1055
+
980
1056
  export declare const DIMENSION_KEYS: Readonly<Record<FilterDimension, 'workspaces' | 'projects' | 'tasks' | 'people'>>;
981
1057
 
982
1058
  export declare interface DrawerUser {
@@ -1088,6 +1164,25 @@ declare const KINDS: {
1088
1164
  };
1089
1165
  };
1090
1166
 
1167
+ declare const LEADING: {
1168
+ readonly none: null;
1169
+ readonly dot: {
1170
+ readonly width: "10px";
1171
+ readonly height: 10;
1172
+ readonly shape: "circle";
1173
+ };
1174
+ readonly avatar: {
1175
+ readonly width: "30px";
1176
+ readonly height: 30;
1177
+ readonly shape: "circle";
1178
+ };
1179
+ readonly square: {
1180
+ readonly width: "var(--icon-square)";
1181
+ readonly height: 30;
1182
+ readonly shape: "block";
1183
+ };
1184
+ };
1185
+
1091
1186
  export declare function longestTimer(timers: PillTimer[]): PillTimer | null;
1092
1187
 
1093
1188
  export declare const MASK_INSET = 6;
@@ -1133,6 +1228,54 @@ export declare function orderRange(a: string, b: string): {
1133
1228
 
1134
1229
  export declare const OUTPUT_SIZE = 512;
1135
1230
 
1231
+ export declare const PAGE_SIZES: readonly number[];
1232
+
1233
+ export declare const pageable: (total: number, sizes?: readonly number[]) => boolean;
1234
+
1235
+ export declare interface PageBounds {
1236
+ page: number;
1237
+ pages: number;
1238
+ from: number;
1239
+ to: number;
1240
+ }
1241
+
1242
+ export declare function pageBounds(page: number, total: number, size: number): PageBounds;
1243
+
1244
+ export declare const pageCount: (total: number, size: number) => number;
1245
+
1246
+ export declare const pageRangeLabel: ({ from, to }: Pick<PageBounds, "from" | "to">, total: number) => string;
1247
+
1248
+ export declare const pageSizeLabel: (size: number) => string;
1249
+
1250
+ export declare interface PageSlice<T> extends PageBounds {
1251
+ rows: T[];
1252
+ total: number;
1253
+ }
1254
+
1255
+ export declare function pageSlice<T>(items: readonly T[], page: number, size: number): PageSlice<T>;
1256
+
1257
+ export declare interface PaletteGroup {
1258
+ id: string;
1259
+ title: string;
1260
+ items: readonly PaletteItem[];
1261
+ }
1262
+
1263
+ export declare const paletteIds: (groups: readonly PaletteGroup[]) => string[];
1264
+
1265
+ export declare interface PaletteItem {
1266
+ id: string;
1267
+ title: string;
1268
+ subtitle?: string;
1269
+ icon?: string;
1270
+ color?: string;
1271
+ avatar?: {
1272
+ name: string;
1273
+ src?: string;
1274
+ };
1275
+ hint?: string;
1276
+ kbd?: string;
1277
+ }
1278
+
1136
1279
  export declare function parallelMinutes(spans: readonly TimelineSpan[]): number;
1137
1280
 
1138
1281
  export declare function parallelPartners(spans: readonly TimelineSpan[]): Map<string, string[]>;
@@ -1214,6 +1357,13 @@ export declare function presetRange(kind: RangePreset, today: string): {
1214
1357
  /** Okabe-Ito, the only palette permitted for projects and charts. */
1215
1358
  export declare const PROJECT_COLORS: string[];
1216
1359
 
1360
+ declare const RADIUS: {
1361
+ readonly text: "6px";
1362
+ readonly block: "var(--r-btn)";
1363
+ readonly circle: "50%";
1364
+ readonly pill: "var(--r-pill)";
1365
+ };
1366
+
1217
1367
  export declare const RANGE_PRESETS: {
1218
1368
  value: RangePreset;
1219
1369
  label: string;
@@ -1221,6 +1371,9 @@ export declare const RANGE_PRESETS: {
1221
1371
 
1222
1372
  export declare type RangePreset = 'today' | 'week' | 'last7' | 'month';
1223
1373
 
1374
+ /** Draws an SVG document onto a square canvas and hands back a PNG, the way the sheet saves an uploaded icon. */
1375
+ export declare function rasterizeSvg(svg: string, size?: number): Promise<Blob>;
1376
+
1224
1377
  export declare interface RecentTask {
1225
1378
  id: string;
1226
1379
  task: string;
@@ -1289,10 +1442,23 @@ declare const SIZES_2: {
1289
1442
  };
1290
1443
  };
1291
1444
 
1445
+ declare const SIZES_3: {
1446
+ readonly sm: {
1447
+ readonly height: 20;
1448
+ readonly font: 11;
1449
+ };
1450
+ readonly md: {
1451
+ readonly height: 24;
1452
+ readonly font: 12;
1453
+ };
1454
+ };
1455
+
1292
1456
  export declare function spanLabel(from: string, to: string, today: string): string;
1293
1457
 
1294
1458
  export declare function startOfWeekIso(iso: string): string;
1295
1459
 
1460
+ export declare const stepActive: (groups: readonly PaletteGroup[], activeId: string | null, delta: 1 | -1) => string | null;
1461
+
1296
1462
  export declare const STRIPES = "repeating-linear-gradient(135deg, rgba(255,255,255,.55) 0 2px, transparent 2px 5px)";
1297
1463
 
1298
1464
  export declare const SWATCH_COLORS: readonly string[];
@@ -1332,6 +1498,8 @@ export declare interface TaskSwatch {
1332
1498
 
1333
1499
  export declare function taskSwatches(ids: readonly string[]): Map<string, TaskSwatch>;
1334
1500
 
1501
+ export declare const TAuthBackdrop: DefineComponent< {}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, HTMLDivElement>;
1502
+
1335
1503
  export declare const TAuthCard: __VLS_WithTemplateSlots_13<typeof __VLS_component_13, __VLS_TemplateResult_13["slots"]>;
1336
1504
 
1337
1505
  export declare const TAutoStopMark: DefineComponent< {}, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, true, {}, HTMLSpanElement>;
@@ -1347,6 +1515,8 @@ max: number;
1347
1515
 
1348
1516
  export declare const TBadge: __VLS_WithTemplateSlots_7<typeof __VLS_component_7, __VLS_TemplateResult_7["slots"]>;
1349
1517
 
1518
+ export declare const TBanner: __VLS_WithTemplateSlots_16<typeof __VLS_component_16, __VLS_TemplateResult_16["slots"]>;
1519
+
1350
1520
  export declare const TBar: DefineComponent<__VLS_Props_20, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_20> & Readonly<{}>, {
1351
1521
  color: string;
1352
1522
  to: string | string[];
@@ -1394,6 +1564,47 @@ modelValue: string;
1394
1564
  autofocus: boolean;
1395
1565
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
1396
1566
 
1567
+ export declare const TCommandPalette: DefineComponent< {
1568
+ open: boolean;
1569
+ query: string;
1570
+ groups: readonly PaletteGroup[];
1571
+ activeId: string | null;
1572
+ placeholder?: string;
1573
+ empty?: string;
1574
+ mobile?: boolean;
1575
+ teleport?: boolean;
1576
+ busy?: boolean;
1577
+ }, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
1578
+ close: () => any;
1579
+ pick: (id: string) => any;
1580
+ "update:query": (value: string) => any;
1581
+ "update:activeId": (id: string | null) => any;
1582
+ }, string, PublicProps, Readonly<{
1583
+ open: boolean;
1584
+ query: string;
1585
+ groups: readonly PaletteGroup[];
1586
+ activeId: string | null;
1587
+ placeholder?: string;
1588
+ empty?: string;
1589
+ mobile?: boolean;
1590
+ teleport?: boolean;
1591
+ busy?: boolean;
1592
+ }> & Readonly<{
1593
+ onClose?: (() => any) | undefined;
1594
+ onPick?: ((id: string) => any) | undefined;
1595
+ "onUpdate:query"?: ((value: string) => any) | undefined;
1596
+ "onUpdate:activeId"?: ((id: string | null) => any) | undefined;
1597
+ }>, {
1598
+ placeholder: string;
1599
+ teleport: boolean;
1600
+ mobile: boolean;
1601
+ empty: string;
1602
+ busy: boolean;
1603
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {
1604
+ input: HTMLInputElement;
1605
+ list: HTMLDivElement;
1606
+ }, any>;
1607
+
1397
1608
  export declare const TConfirmButton: __VLS_WithTemplateSlots_4<typeof __VLS_component_4, __VLS_TemplateResult_4["slots"]>;
1398
1609
 
1399
1610
  export declare const TConfirmRow: __VLS_WithTemplateSlots_3<typeof __VLS_component_3, __VLS_TemplateResult_3["slots"]>;
@@ -1625,6 +1836,10 @@ export declare const TIOSTabBar: DefineComponent<__VLS_Props_42, {}, {}, {}, {},
1625
1836
  indicator: boolean;
1626
1837
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLElement>;
1627
1838
 
1839
+ export declare const TKbd: DefineComponent<__VLS_Props_67, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_67> & Readonly<{}>, {
1840
+ size: keyof typeof SIZES_3;
1841
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLElement>;
1842
+
1628
1843
  export declare const TLargeTitle: __VLS_WithTemplateSlots_8<typeof __VLS_component_8, __VLS_TemplateResult_8["slots"]>;
1629
1844
 
1630
1845
  export declare const TLogo: DefineComponent<__VLS_Props_46, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_46> & Readonly<{}>, {
@@ -1701,6 +1916,17 @@ declare const TONES_4: {
1701
1916
  readonly faint: "var(--label-3)";
1702
1917
  };
1703
1918
 
1919
+ declare const TONES_5: {
1920
+ readonly inverse: {
1921
+ readonly bar: readonly ["var(--label)", "var(--bg)"];
1922
+ readonly pill: readonly ["var(--bg)", "var(--label)"];
1923
+ };
1924
+ readonly accent: {
1925
+ readonly bar: readonly ["var(--accent)", "var(--on-accent)"];
1926
+ readonly pill: readonly ["var(--on-accent)", "var(--accent)"];
1927
+ };
1928
+ };
1929
+
1704
1930
  export declare const TOrderButton: DefineComponent<__VLS_Props_53, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
1705
1931
  click: (e: MouseEvent) => any;
1706
1932
  }, string, PublicProps, Readonly<__VLS_Props_53> & Readonly<{
@@ -1709,6 +1935,22 @@ onClick?: ((e: MouseEvent) => any) | undefined;
1709
1935
  compact: boolean;
1710
1936
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
1711
1937
 
1938
+ export declare const TPager: DefineComponent<__VLS_Props_63, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
1939
+ "update:page": (page: number) => any;
1940
+ "update:pageSize": (size: number) => any;
1941
+ }, string, PublicProps, Readonly<__VLS_Props_63> & Readonly<{
1942
+ "onUpdate:page"?: ((page: number) => any) | undefined;
1943
+ "onUpdate:pageSize"?: ((size: number) => any) | undefined;
1944
+ }>, {
1945
+ last: boolean;
1946
+ compact: boolean;
1947
+ teleport: boolean;
1948
+ mobile: boolean;
1949
+ sizes: readonly number[];
1950
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {
1951
+ anchor: HTMLButtonElement;
1952
+ }, HTMLDivElement>;
1953
+
1712
1954
  export declare const TParallelMark: DefineComponent<__VLS_Props_57, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_57> & Readonly<{}>, {
1713
1955
  others: string[];
1714
1956
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLSpanElement>;
@@ -1818,6 +2060,19 @@ disabled: boolean;
1818
2060
 
1819
2061
  export declare const TSheet: __VLS_WithTemplateSlots_9<typeof __VLS_component_9, __VLS_TemplateResult_9["slots"]>;
1820
2062
 
2063
+ export declare const TSkeleton: DefineComponent<__VLS_Props_64, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_64> & Readonly<{}>, {
2064
+ width: string;
2065
+ height: number;
2066
+ shape: keyof typeof RADIUS;
2067
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLSpanElement>;
2068
+
2069
+ export declare const TSkeletonList: DefineComponent<__VLS_Props_65, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_65> & Readonly<{}>, {
2070
+ subtitle: boolean;
2071
+ leading: keyof typeof LEADING;
2072
+ trailing: boolean;
2073
+ rows: number;
2074
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
2075
+
1821
2076
  export declare const TStartHero: DefineComponent<__VLS_Props_40, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
1822
2077
  open: () => any;
1823
2078
  pick: (taskId: string) => any;
@@ -1897,12 +2152,14 @@ list: HTMLDivElement;
1897
2152
 
1898
2153
  export declare const TWorkspaceDrawer: DefineComponent<__VLS_Props_37, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
1899
2154
  help: () => any;
2155
+ action: (id: string) => any;
1900
2156
  "update:modelValue": (id: string) => any;
1901
2157
  close: () => any;
1902
2158
  create: () => any;
1903
2159
  account: () => any;
1904
2160
  }, string, PublicProps, Readonly<__VLS_Props_37> & Readonly<{
1905
2161
  onHelp?: (() => any) | undefined;
2162
+ onAction?: ((id: string) => any) | undefined;
1906
2163
  "onUpdate:modelValue"?: ((id: string) => any) | undefined;
1907
2164
  onClose?: (() => any) | undefined;
1908
2165
  onCreate?: (() => any) | undefined;
@@ -1910,29 +2167,36 @@ onAccount?: (() => any) | undefined;
1910
2167
  }>, {
1911
2168
  teleport: boolean;
1912
2169
  showAll: boolean;
2170
+ actions: readonly WorkspaceAction[];
1913
2171
  user: DrawerUser | null;
1914
2172
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
1915
2173
 
1916
2174
  export declare const TWorkspaceMenu: DefineComponent<__VLS_Props_36, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
2175
+ action: (id: string) => any;
1917
2176
  "update:modelValue": (id: string) => any;
1918
2177
  create: () => any;
1919
2178
  }, string, PublicProps, Readonly<__VLS_Props_36> & Readonly<{
2179
+ onAction?: ((id: string) => any) | undefined;
1920
2180
  "onUpdate:modelValue"?: ((id: string) => any) | undefined;
1921
2181
  onCreate?: (() => any) | undefined;
1922
2182
  }>, {
1923
2183
  showAll: boolean;
1924
2184
  embedded: boolean;
2185
+ actions: readonly WorkspaceAction[];
1925
2186
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
1926
2187
 
1927
2188
  export declare const TWorkspaceSwitcher: DefineComponent<__VLS_Props_35, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
2189
+ action: (id: string) => any;
1928
2190
  "update:modelValue": (id: string) => any;
1929
2191
  create: () => any;
1930
2192
  }, string, PublicProps, Readonly<__VLS_Props_35> & Readonly<{
2193
+ onAction?: ((id: string) => any) | undefined;
1931
2194
  "onUpdate:modelValue"?: ((id: string) => any) | undefined;
1932
2195
  onCreate?: (() => any) | undefined;
1933
2196
  }>, {
1934
2197
  teleport: boolean;
1935
2198
  showAll: boolean;
2199
+ actions: readonly WorkspaceAction[];
1936
2200
  }, {}, {}, {}, string, ComponentProvideOptions, false, {
1937
2201
  trigger: HTMLButtonElement;
1938
2202
  }, HTMLDivElement>;
@@ -1976,11 +2240,29 @@ export declare interface WaterfallSegment {
1976
2240
 
1977
2241
  export declare const WEEKDAYS: string[];
1978
2242
 
2243
+ export declare const WHEEL_TICK = "timebraid-tick";
2244
+
1979
2245
  export declare interface WheelOption {
1980
2246
  value: number;
1981
2247
  label: string;
1982
2248
  }
1983
2249
 
2250
+ export declare const WORKSPACE_ICONS: readonly WorkspaceGalleryIcon[];
2251
+
2252
+ export declare interface WorkspaceAction {
2253
+ id: string;
2254
+ label: string;
2255
+ icon: string;
2256
+ }
2257
+
2258
+ export declare interface WorkspaceGalleryIcon {
2259
+ id: string;
2260
+ label: string;
2261
+ svg: string;
2262
+ }
2263
+
2264
+ export declare const workspaceIconDataUrl: (icon: WorkspaceGalleryIcon) => string;
2265
+
1984
2266
  export declare interface WorkspaceOption {
1985
2267
  id: string;
1986
2268
  name: string;
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- @import"https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400..700&display=swap";:root{--font-display:var(--font-sans);--font-ui:var(--font-sans);--font-numeric:var(--font-mono)}:root{--font-sans:"Instrument Sans",-apple-system,BlinkMacSystemFont,"SF Pro Text",sans-serif;--font-mono:"JetBrains Mono",ui-monospace,"SF Mono",Menlo,monospace;--indigo-400:#6C77DE;--indigo-500:#4A57D2;--indigo-600:#3A44AF;--indigo-700:#2C3391;--chart-1:#0072B2;--chart-2:#E69F00;--chart-3:#009E73;--chart-4:#CC79A7;--chart-5:#56B4E9;--chart-6:#D55E00;--chart-7:#F0E442;--chart-8:#6B7085;--bg:#F2F3F8;--bg-elev:#FFFFFF;--bg-elev-2:#F7F8FC;--bg-sidebar:rgba(244,245,250,.86);--bg-bar:rgba(242,243,248,.82);--fill:rgba(20,22,40,.06);--fill-2:rgba(20,22,40,.1);--fill-3:rgba(20,22,40,.16);--sep:rgba(20,22,40,.1);--sep-strong:rgba(20,22,40,.18);--label:#0E1024;--label-2:#5C6178;--label-3:#8B90A5;--label-4:#B7BBCB;--on-accent:#FFFFFF;--accent:#4A57D2;--accent-hover:#3F4BC0;--accent-soft:rgba(74,87,210,.12);--accent-soft-2:rgba(74,87,210,.2);--running:#4A57D2;--running-soft:rgba(74,87,210,.1);--green:#1E9E6A;--green-soft:rgba(30,158,106,.12);--red:#D6453D;--red-soft:rgba(214,69,61,.1);--orange:#D97B0F;--r-cell:12px;--r-card:14px;--r-btn:10px;--r-pill:999px;--r-sheet:20px;--r-window:12px;--sh-card:0 1px 2px rgba(14,16,36,.04),0 0 0 1px rgba(14,16,36,.04);--sh-float:0 12px 32px -8px rgba(14,16,36,.22),0 2px 6px rgba(14,16,36,.08),0 0 0 1px rgba(14,16,36,.05);--sh-sheet:0 -8px 40px -8px rgba(14,16,36,.24);--sh-thumb:0 2px 6px rgba(0,0,0,.25);--sh-seg:0 1px 2px rgba(0,0,0,.14),0 3px 8px -2px rgba(0,0,0,.12),0 0 0 .5px var(--sep);--blur:saturate(180%) blur(22px);--scrim:rgba(10,11,20,.42);--dash:rgba(255,255,255,.7);--ease:cubic-bezier(.2,0,.2,1);--ease-out:cubic-bezier(.16,1,.3,1);--ease-sheet:cubic-bezier(.32,.72,0,1);--t-fast:.14s;--t-base:.22s;--t-sheet:.42s}[data-theme=dark]{--bg:#15161F;--bg-elev:#1F2030;--bg-elev-2:#282A3C;--bg-sidebar:rgba(24,25,36,.86);--bg-bar:rgba(21,22,31,.78);--fill:rgba(255,255,255,.07);--fill-2:rgba(255,255,255,.11);--fill-3:rgba(255,255,255,.17);--sep:rgba(255,255,255,.09);--sep-strong:rgba(255,255,255,.16);--label:#F3F4FA;--label-2:#A7ABC0;--label-3:#7D8199;--label-4:#575B70;--accent:#7A84E6;--accent-hover:#8C95EC;--accent-soft:rgba(122,132,230,.16);--accent-soft-2:rgba(122,132,230,.26);--running:#8A93EC;--running-soft:rgba(122,132,230,.14);--green:#3CC08A;--green-soft:rgba(60,192,138,.14);--red:#F06B62;--red-soft:rgba(240,107,98,.14);--orange:#F0A24B;--chart-8:#9A9FB4;--sh-card:0 1px 2px rgba(0,0,0,.2),0 0 0 1px rgba(255,255,255,.04);--sh-float:0 16px 40px -8px rgba(0,0,0,.6),0 2px 8px rgba(0,0,0,.3),0 0 0 1px rgba(255,255,255,.08);--sh-sheet:0 -8px 40px -8px rgba(0,0,0,.6);--scrim:rgba(0,0,0,.55)}:root{--text-display-1:64px;--leading-display-1:1.02;--tracking-display-1:-.03em;--text-display-2:48px;--leading-display-2:1.06;--tracking-display-2:-.025em;--text-large-title:30px;--text-large-title-phone:34px;--tracking-large-title:-.025em;--leading-large-title:1.1;--text-title:17px;--text-row:15px;--text-subtitle:12.5px;--text-section:12px;--tracking-section:.04em;--text-body:14px;--text-body-lg:18px;--leading-body-lg:1.6;--text-caption:12px;--text-footnote:11.5px;--text-timer-xl:44px;--text-timer-lg:28px;--text-timer-md:22px;--text-timer-sm:15px;--weight-regular:400;--weight-medium:500;--weight-semibold:600;--weight-bold:700}:root{--space-0:0px;--space-1:2px;--space-2:4px;--space-3:8px;--space-4:12px;--space-5:16px;--space-6:20px;--space-7:24px;--space-8:32px;--space-9:40px;--space-10:48px;--space-11:64px;--space-12:80px;--space-13:112px;--space-14:160px;--section-y:112px;--section-y-tight:72px;--container-max:1160px;--container-prose:660px;--gutter:24px;--sidebar-w:232px;--content-max:1040px;--content-max-narrow:760px;--gutter-phone:16px;--row-h:46px;--row-h-sub:56px;--row-h-dense:40px;--control-h-sm:30px;--control-h-md:36px;--control-h-lg:44px;--control-h-xl:50px;--pill-h:46px;--pill-h-compact:30px;--timer-bar-h:56px;--timer-bar-pad:72px;--inset-top:env(safe-area-inset-top,0px);--inset-bottom:env(safe-area-inset-bottom,0px);--tab-bar-inset-ios:max(10px,calc(var(--inset-bottom) - 12px));--tab-bar-h-ios:calc(42px + var(--tab-bar-inset-ios));--timer-bar-bottom-ios:calc(var(--tab-bar-h-ios) + 10px);--tab-bar-pad-ios:calc(var(--tab-bar-h-ios) + 16px);--nav-bar-h-android:80px;--nav-bar-pad-android:96px;--toggle-w:46px;--toggle-h:28px;--field-h:38px;--seg-h:36px;--seg-h-sm:30px;--icon-square:28px}*,*:before,*:after{box-sizing:border-box}html,body{margin:0}html{-webkit-text-size-adjust:100%}body{font-family:var(--font-sans);color:var(--label);background:var(--bg);-webkit-font-smoothing:antialiased;font-size:var(--text-body);line-height:1.45}button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer;-webkit-tap-highlight-color:transparent}input,select,textarea{font:inherit;color:inherit}a{color:var(--accent);text-decoration:none}a:hover{color:var(--accent-hover)}a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.num{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}.clamp-2{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;overflow-wrap:anywhere;line-height:1.3;min-width:0}.ellipsis{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::selection{background:var(--accent-soft-2)}@keyframes t-pulse{0%,to{opacity:1}50%{opacity:.35}}@keyframes t-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}@keyframes t-sheet{0%{transform:translateY(100%)}to{transform:none}}@keyframes t-drawer{0%{transform:translate(-100%)}to{transform:none}}@keyframes t-scrim{0%{opacity:0}to{opacity:1}}@keyframes t-pop{0%{opacity:0;transform:scale(.96) translateY(6px)}to{opacity:1;transform:none}}@keyframes t-island{0%{transform:scaleX(.6);opacity:.4}to{transform:none;opacity:1}}.view-in{animation:t-in var(--t-base) var(--ease-out) both}.press{transition:transform var(--t-fast) var(--ease),background var(--t-fast) var(--ease),opacity var(--t-fast) var(--ease)}.press:active{transform:scale(.98)}.row-press:active{background:var(--fill-2)!important}@media (prefers-reduced-motion:reduce){*{animation-duration:0ms!important;transition-duration:0ms!important}}.t-wheel-list[data-v-4bb937c1]{scrollbar-width:none}.t-wheel-list[data-v-4bb937c1]::-webkit-scrollbar{display:none}.t-wheel-list[data-v-4bb937c1]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:var(--r-btn)}.check:focus-within .box[data-v-8c783040]{outline:2px solid var(--accent);outline-offset:2px}.t-spinner[data-v-a41169e8]{animation:t-spinner-turn-a41169e8 .7s linear infinite}@keyframes t-spinner-turn-a41169e8{to{transform:rotate(360deg)}}
1
+ @import"https://fonts.googleapis.com/css2?family=Instrument+Sans:ital,wght@0,400..700;1,400..700&family=JetBrains+Mono:wght@400..700&display=swap";:root{--font-display:var(--font-sans);--font-ui:var(--font-sans);--font-numeric:var(--font-mono)}:root{--font-sans:"Instrument Sans",-apple-system,BlinkMacSystemFont,"SF Pro Text",sans-serif;--font-mono:"JetBrains Mono",ui-monospace,"SF Mono",Menlo,monospace;--indigo-400:#6C77DE;--indigo-500:#4A57D2;--indigo-600:#3A44AF;--indigo-700:#2C3391;--chart-1:#0072B2;--chart-2:#E69F00;--chart-3:#009E73;--chart-4:#CC79A7;--chart-5:#56B4E9;--chart-6:#D55E00;--chart-7:#F0E442;--chart-8:#6B7085;--bg:#F2F3F8;--bg-elev:#FFFFFF;--bg-elev-2:#F7F8FC;--bg-sidebar:rgba(244,245,250,.86);--bg-bar:rgba(242,243,248,.82);--fill:rgba(20,22,40,.06);--fill-2:rgba(20,22,40,.1);--fill-3:rgba(20,22,40,.16);--sep:rgba(20,22,40,.1);--sep-strong:rgba(20,22,40,.18);--label:#0E1024;--label-2:#5C6178;--label-3:#8B90A5;--label-4:#B7BBCB;--on-accent:#FFFFFF;--accent:#4A57D2;--accent-hover:#3F4BC0;--accent-soft:rgba(74,87,210,.12);--accent-soft-2:rgba(74,87,210,.2);--running:#4A57D2;--running-soft:rgba(74,87,210,.1);--green:#1E9E6A;--green-soft:rgba(30,158,106,.12);--red:#D6453D;--red-soft:rgba(214,69,61,.1);--orange:#D97B0F;--brand-field:#5D68CF;--brand-field-deep:#191E5E;--brand-ink:#141846;--r-cell:12px;--r-card:14px;--r-btn:10px;--r-pill:999px;--r-sheet:20px;--r-window:12px;--sh-card:0 1px 2px rgba(14,16,36,.04),0 0 0 1px rgba(14,16,36,.04);--sh-float:0 12px 32px -8px rgba(14,16,36,.22),0 2px 6px rgba(14,16,36,.08),0 0 0 1px rgba(14,16,36,.05);--sh-sheet:0 -8px 40px -8px rgba(14,16,36,.24);--sh-thumb:0 2px 6px rgba(0,0,0,.25);--sh-seg:0 1px 2px rgba(0,0,0,.14),0 3px 8px -2px rgba(0,0,0,.12),0 0 0 .5px var(--sep);--blur:saturate(180%) blur(22px);--scrim:rgba(10,11,20,.42);--dash:rgba(255,255,255,.7);--ease:cubic-bezier(.2,0,.2,1);--ease-out:cubic-bezier(.16,1,.3,1);--ease-sheet:cubic-bezier(.32,.72,0,1);--t-fast:.14s;--t-base:.22s;--t-sheet:.42s}[data-theme=dark]{--bg:#15161F;--bg-elev:#1F2030;--bg-elev-2:#282A3C;--bg-sidebar:rgba(24,25,36,.86);--bg-bar:rgba(21,22,31,.78);--fill:rgba(255,255,255,.07);--fill-2:rgba(255,255,255,.11);--fill-3:rgba(255,255,255,.17);--sep:rgba(255,255,255,.09);--sep-strong:rgba(255,255,255,.16);--label:#F3F4FA;--label-2:#A7ABC0;--label-3:#7D8199;--label-4:#575B70;--accent:#7A84E6;--accent-hover:#8C95EC;--accent-soft:rgba(122,132,230,.16);--accent-soft-2:rgba(122,132,230,.26);--running:#8A93EC;--running-soft:rgba(122,132,230,.14);--green:#3CC08A;--green-soft:rgba(60,192,138,.14);--red:#F06B62;--red-soft:rgba(240,107,98,.14);--orange:#F0A24B;--chart-8:#9A9FB4;--sh-card:0 1px 2px rgba(0,0,0,.2),0 0 0 1px rgba(255,255,255,.04);--sh-float:0 16px 40px -8px rgba(0,0,0,.6),0 2px 8px rgba(0,0,0,.3),0 0 0 1px rgba(255,255,255,.08);--sh-sheet:0 -8px 40px -8px rgba(0,0,0,.6);--scrim:rgba(0,0,0,.55)}:root{--text-display-1:64px;--leading-display-1:1.02;--tracking-display-1:-.03em;--text-display-2:48px;--leading-display-2:1.06;--tracking-display-2:-.025em;--text-large-title:30px;--text-large-title-phone:34px;--tracking-large-title:-.025em;--leading-large-title:1.1;--text-title:17px;--text-row:15px;--text-subtitle:12.5px;--text-section:12px;--tracking-section:.04em;--text-body:14px;--text-body-lg:18px;--leading-body-lg:1.6;--text-caption:12px;--text-footnote:11.5px;--text-timer-xl:44px;--text-timer-lg:28px;--text-timer-md:22px;--text-timer-sm:15px;--weight-regular:400;--weight-medium:500;--weight-semibold:600;--weight-bold:700}:root{--space-0:0px;--space-1:2px;--space-2:4px;--space-3:8px;--space-4:12px;--space-5:16px;--space-6:20px;--space-7:24px;--space-8:32px;--space-9:40px;--space-10:48px;--space-11:64px;--space-12:80px;--space-13:112px;--space-14:160px;--section-y:112px;--section-y-tight:72px;--container-max:1160px;--container-prose:660px;--gutter:24px;--sidebar-w:232px;--content-max:1040px;--content-max-narrow:760px;--gutter-phone:16px;--row-h:46px;--row-h-sub:56px;--row-h-dense:40px;--control-h-sm:30px;--control-h-md:36px;--control-h-lg:44px;--control-h-xl:50px;--pill-h:46px;--pill-h-compact:30px;--timer-bar-h:56px;--timer-bar-pad:72px;--inset-top:env(safe-area-inset-top,0px);--inset-bottom:env(safe-area-inset-bottom,0px);--tab-bar-inset-ios:max(10px,calc(var(--inset-bottom) - 12px));--tab-bar-h-ios:calc(42px + var(--tab-bar-inset-ios));--timer-bar-bottom-ios:calc(var(--tab-bar-h-ios) + 10px);--tab-bar-pad-ios:calc(var(--tab-bar-h-ios) + 16px);--nav-bar-h-android:80px;--nav-bar-pad-android:96px;--toggle-w:46px;--toggle-h:28px;--field-h:38px;--seg-h:36px;--seg-h-sm:30px;--icon-square:28px}*,*:before,*:after{box-sizing:border-box}html,body{margin:0}html{-webkit-text-size-adjust:100%}body{font-family:var(--font-sans);color:var(--label);background:var(--bg);-webkit-font-smoothing:antialiased;font-size:var(--text-body);line-height:1.45}button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer;-webkit-tap-highlight-color:transparent}input,select,textarea{font:inherit;color:inherit}a{color:var(--accent);text-decoration:none}a:hover{color:var(--accent-hover)}a:focus-visible,button:focus-visible,input:focus-visible,select:focus-visible,[tabindex]:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.num{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}.clamp-2{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2;overflow:hidden;overflow-wrap:anywhere;line-height:1.3;min-width:0}.ellipsis{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::selection{background:var(--accent-soft-2)}@keyframes t-pulse{0%,to{opacity:1}50%{opacity:.35}}@keyframes t-shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}.t-skeleton{background:linear-gradient(90deg,var(--fill) 25%,var(--fill-2) 50%,var(--fill) 75%);background-size:400% 100%;animation:t-shimmer 1.6s linear infinite}@media (prefers-reduced-motion:reduce){.t-skeleton{animation:none;background:var(--fill)}}@keyframes t-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}@keyframes t-sheet{0%{transform:translateY(100%)}to{transform:none}}@keyframes t-drawer{0%{transform:translate(-100%)}to{transform:none}}@keyframes t-scrim{0%{opacity:0}to{opacity:1}}@keyframes t-pop{0%{opacity:0;transform:scale(.96) translateY(6px)}to{opacity:1;transform:none}}@keyframes t-island{0%{transform:scaleX(.6);opacity:.4}to{transform:none;opacity:1}}@keyframes t-sweep{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes t-float{0%,to{translate:0 0}50%{translate:0 -6px}}@keyframes t-flash{0%,30%{background-color:var(--accent-soft);box-shadow:inset 0 0 0 1.5px var(--accent)}to{background-color:transparent;box-shadow:none}}.view-in{animation:t-in var(--t-base) var(--ease-out) both}.t-flash{animation:t-flash 2s var(--ease) 1 both}.press{transition:transform var(--t-fast) var(--ease),background var(--t-fast) var(--ease),opacity var(--t-fast) var(--ease)}.press:active{transform:scale(.98)}.row-press:active{background:var(--fill-2)!important}@media (prefers-reduced-motion:reduce){*{animation-duration:0ms!important;transition-duration:0ms!important}}.t-wheel-list[data-v-f89240c7]{scrollbar-width:none}.t-wheel-list[data-v-f89240c7]::-webkit-scrollbar{display:none}.t-wheel-list[data-v-f89240c7]:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:var(--r-btn)}.check:focus-within .box[data-v-8c783040]{outline:2px solid var(--accent);outline-offset:2px}.t-spinner[data-v-a41169e8]{animation:t-spinner-turn-a41169e8 .7s linear infinite}@keyframes t-spinner-turn-a41169e8{to{transform:rotate(360deg)}}[data-palette-item][data-v-088bc492]:hover:not([aria-selected=true]){background:var(--fill)}