@timebraid/vue 1.16.0 → 1.17.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,7 @@ 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
+ | `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
39
  | `TBar` | Animated value bar |
39
40
  | `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
41
  | `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,9 +50,9 @@ Import `@timebraid/tokens/styles.css` once in `main.ts` (or `@timebraid/vue/styl
49
50
  | `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
51
  | `TWsIcon` | Workspace glyph: a coloured initial square, or the app mark when `all` |
51
52
  | `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 |
53
+ | `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 |
54
+ | `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 |
55
+ | `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
56
  | `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 |
56
57
  | `TStrokes` | Oversized faded tally strokes behind sign-in and empty states |
57
58
  | `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` |
@@ -78,6 +79,9 @@ Import `@timebraid/tokens/styles.css` once in `main.ts` (or `@timebraid/vue/styl
78
79
  | `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
80
  | `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
81
  | `THighlight` | Text with every word of a query marked in `--accent-soft-2` |
82
+ | `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 |
83
+ | `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 |
84
+ | `TSkeletonList` | The skeleton of a list card: rows of a leading mark, two lines of differing length and a short right block |
81
85
 
82
86
  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`.
83
87
 
package/dist/index.d.ts CHANGED
@@ -57,6 +57,18 @@ multiple: boolean;
57
57
  addLabel: string;
58
58
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
59
59
 
60
+ declare const __VLS_component_16: DefineComponent<__VLS_Props_66, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
61
+ action: () => any;
62
+ }, string, PublicProps, Readonly<__VLS_Props_66> & Readonly<{
63
+ onAction?: (() => any) | undefined;
64
+ }>, {
65
+ text: string;
66
+ icon: string;
67
+ tone: keyof typeof TONES_5;
68
+ action: string;
69
+ compact: boolean;
70
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
71
+
60
72
  declare const __VLS_component_2: DefineComponent<__VLS_Props_2, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
61
73
  click: (event: MouseEvent | KeyboardEvent) => any;
62
74
  }, string, PublicProps, Readonly<__VLS_Props_2> & Readonly<{
@@ -378,6 +390,7 @@ declare type __VLS_Props_35 = {
378
390
  modelValue: string;
379
391
  showAll?: boolean;
380
392
  teleport?: boolean;
393
+ actions?: readonly WorkspaceAction[];
381
394
  };
382
395
 
383
396
  declare type __VLS_Props_36 = {
@@ -385,6 +398,7 @@ declare type __VLS_Props_36 = {
385
398
  modelValue: string;
386
399
  showAll?: boolean;
387
400
  embedded?: boolean;
401
+ actions?: readonly WorkspaceAction[];
388
402
  };
389
403
 
390
404
  declare type __VLS_Props_37 = {
@@ -394,6 +408,7 @@ declare type __VLS_Props_37 = {
394
408
  showAll?: boolean;
395
409
  teleport?: boolean;
396
410
  user?: DrawerUser | null;
411
+ actions?: readonly WorkspaceAction[];
397
412
  };
398
413
 
399
414
  declare type __VLS_Props_38 = {
@@ -619,6 +634,39 @@ declare type __VLS_Props_62 = {
619
634
  query?: string;
620
635
  };
621
636
 
637
+ declare type __VLS_Props_63 = {
638
+ page: number;
639
+ pageSize: number;
640
+ total: number;
641
+ sizes?: readonly number[];
642
+ compact?: boolean;
643
+ mobile?: boolean;
644
+ teleport?: boolean;
645
+ last?: boolean;
646
+ };
647
+
648
+ declare type __VLS_Props_64 = {
649
+ width?: string;
650
+ height?: number;
651
+ shape?: keyof typeof RADIUS;
652
+ };
653
+
654
+ declare type __VLS_Props_65 = {
655
+ rows?: number;
656
+ leading?: keyof typeof LEADING;
657
+ trailing?: boolean;
658
+ subtitle?: boolean;
659
+ };
660
+
661
+ declare type __VLS_Props_66 = {
662
+ title: string;
663
+ text?: string;
664
+ icon?: string;
665
+ action?: string;
666
+ tone?: keyof typeof TONES_5;
667
+ compact?: boolean;
668
+ };
669
+
622
670
  declare type __VLS_Props_7 = {
623
671
  modelValue: string;
624
672
  options: {
@@ -728,6 +776,15 @@ declare function __VLS_template_15(): {
728
776
  rootEl: HTMLDivElement;
729
777
  };
730
778
 
779
+ declare function __VLS_template_16(): {
780
+ attrs: Partial<{}>;
781
+ slots: {
782
+ default?(_: {}): any;
783
+ };
784
+ refs: {};
785
+ rootEl: HTMLDivElement;
786
+ };
787
+
731
788
  declare function __VLS_template_2(): {
732
789
  attrs: Partial<{}>;
733
790
  slots: {
@@ -826,6 +883,8 @@ declare type __VLS_TemplateResult_14 = ReturnType<typeof __VLS_template_14>;
826
883
 
827
884
  declare type __VLS_TemplateResult_15 = ReturnType<typeof __VLS_template_15>;
828
885
 
886
+ declare type __VLS_TemplateResult_16 = ReturnType<typeof __VLS_template_16>;
887
+
829
888
  declare type __VLS_TemplateResult_2 = ReturnType<typeof __VLS_template_2>;
830
889
 
831
890
  declare type __VLS_TemplateResult_3 = ReturnType<typeof __VLS_template_3>;
@@ -884,6 +943,12 @@ declare type __VLS_WithTemplateSlots_15<T, S> = T & {
884
943
  };
885
944
  };
886
945
 
946
+ declare type __VLS_WithTemplateSlots_16<T, S> = T & {
947
+ new (): {
948
+ $slots: S;
949
+ };
950
+ };
951
+
887
952
  declare type __VLS_WithTemplateSlots_2<T, S> = T & {
888
953
  new (): {
889
954
  $slots: S;
@@ -953,6 +1018,8 @@ export declare function clampOffset(x: number, y: number, z: number, stage: numb
953
1018
  y: number;
954
1019
  };
955
1020
 
1021
+ export declare const clampPage: (page: number, total: number, size: number) => number;
1022
+
956
1023
  export declare const clampZoom: (z: number) => number;
957
1024
 
958
1025
  export declare function clockToMinutes(clock: string): number | null;
@@ -977,6 +1044,8 @@ export declare interface CustomRange {
977
1044
  /** Where TIcon masks from when nothing overrides it. */
978
1045
  export declare const DEFAULT_ICON_BASE = "https://unpkg.com/lucide-static@0.545.0/icons/";
979
1046
 
1047
+ export declare const DEFAULT_PAGE_SIZE = 10;
1048
+
980
1049
  export declare const DIMENSION_KEYS: Readonly<Record<FilterDimension, 'workspaces' | 'projects' | 'tasks' | 'people'>>;
981
1050
 
982
1051
  export declare interface DrawerUser {
@@ -1088,6 +1157,25 @@ declare const KINDS: {
1088
1157
  };
1089
1158
  };
1090
1159
 
1160
+ declare const LEADING: {
1161
+ readonly none: null;
1162
+ readonly dot: {
1163
+ readonly width: "10px";
1164
+ readonly height: 10;
1165
+ readonly shape: "circle";
1166
+ };
1167
+ readonly avatar: {
1168
+ readonly width: "30px";
1169
+ readonly height: 30;
1170
+ readonly shape: "circle";
1171
+ };
1172
+ readonly square: {
1173
+ readonly width: "var(--icon-square)";
1174
+ readonly height: 30;
1175
+ readonly shape: "block";
1176
+ };
1177
+ };
1178
+
1091
1179
  export declare function longestTimer(timers: PillTimer[]): PillTimer | null;
1092
1180
 
1093
1181
  export declare const MASK_INSET = 6;
@@ -1133,6 +1221,32 @@ export declare function orderRange(a: string, b: string): {
1133
1221
 
1134
1222
  export declare const OUTPUT_SIZE = 512;
1135
1223
 
1224
+ export declare const PAGE_SIZES: readonly number[];
1225
+
1226
+ export declare const pageable: (total: number, sizes?: readonly number[]) => boolean;
1227
+
1228
+ export declare interface PageBounds {
1229
+ page: number;
1230
+ pages: number;
1231
+ from: number;
1232
+ to: number;
1233
+ }
1234
+
1235
+ export declare function pageBounds(page: number, total: number, size: number): PageBounds;
1236
+
1237
+ export declare const pageCount: (total: number, size: number) => number;
1238
+
1239
+ export declare const pageRangeLabel: ({ from, to }: Pick<PageBounds, "from" | "to">, total: number) => string;
1240
+
1241
+ export declare const pageSizeLabel: (size: number) => string;
1242
+
1243
+ export declare interface PageSlice<T> extends PageBounds {
1244
+ rows: T[];
1245
+ total: number;
1246
+ }
1247
+
1248
+ export declare function pageSlice<T>(items: readonly T[], page: number, size: number): PageSlice<T>;
1249
+
1136
1250
  export declare function parallelMinutes(spans: readonly TimelineSpan[]): number;
1137
1251
 
1138
1252
  export declare function parallelPartners(spans: readonly TimelineSpan[]): Map<string, string[]>;
@@ -1214,6 +1328,13 @@ export declare function presetRange(kind: RangePreset, today: string): {
1214
1328
  /** Okabe-Ito, the only palette permitted for projects and charts. */
1215
1329
  export declare const PROJECT_COLORS: string[];
1216
1330
 
1331
+ declare const RADIUS: {
1332
+ readonly text: "6px";
1333
+ readonly block: "var(--r-btn)";
1334
+ readonly circle: "50%";
1335
+ readonly pill: "var(--r-pill)";
1336
+ };
1337
+
1217
1338
  export declare const RANGE_PRESETS: {
1218
1339
  value: RangePreset;
1219
1340
  label: string;
@@ -1221,6 +1342,9 @@ export declare const RANGE_PRESETS: {
1221
1342
 
1222
1343
  export declare type RangePreset = 'today' | 'week' | 'last7' | 'month';
1223
1344
 
1345
+ /** Draws an SVG document onto a square canvas and hands back a PNG, the way the sheet saves an uploaded icon. */
1346
+ export declare function rasterizeSvg(svg: string, size?: number): Promise<Blob>;
1347
+
1224
1348
  export declare interface RecentTask {
1225
1349
  id: string;
1226
1350
  task: string;
@@ -1347,6 +1471,8 @@ max: number;
1347
1471
 
1348
1472
  export declare const TBadge: __VLS_WithTemplateSlots_7<typeof __VLS_component_7, __VLS_TemplateResult_7["slots"]>;
1349
1473
 
1474
+ export declare const TBanner: __VLS_WithTemplateSlots_16<typeof __VLS_component_16, __VLS_TemplateResult_16["slots"]>;
1475
+
1350
1476
  export declare const TBar: DefineComponent<__VLS_Props_20, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_20> & Readonly<{}>, {
1351
1477
  color: string;
1352
1478
  to: string | string[];
@@ -1701,6 +1827,17 @@ declare const TONES_4: {
1701
1827
  readonly faint: "var(--label-3)";
1702
1828
  };
1703
1829
 
1830
+ declare const TONES_5: {
1831
+ readonly inverse: {
1832
+ readonly bar: readonly ["var(--label)", "var(--bg)"];
1833
+ readonly pill: readonly ["var(--bg)", "var(--label)"];
1834
+ };
1835
+ readonly accent: {
1836
+ readonly bar: readonly ["var(--accent)", "var(--on-accent)"];
1837
+ readonly pill: readonly ["var(--on-accent)", "var(--accent)"];
1838
+ };
1839
+ };
1840
+
1704
1841
  export declare const TOrderButton: DefineComponent<__VLS_Props_53, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
1705
1842
  click: (e: MouseEvent) => any;
1706
1843
  }, string, PublicProps, Readonly<__VLS_Props_53> & Readonly<{
@@ -1709,6 +1846,22 @@ onClick?: ((e: MouseEvent) => any) | undefined;
1709
1846
  compact: boolean;
1710
1847
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
1711
1848
 
1849
+ export declare const TPager: DefineComponent<__VLS_Props_63, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
1850
+ "update:page": (page: number) => any;
1851
+ "update:pageSize": (size: number) => any;
1852
+ }, string, PublicProps, Readonly<__VLS_Props_63> & Readonly<{
1853
+ "onUpdate:page"?: ((page: number) => any) | undefined;
1854
+ "onUpdate:pageSize"?: ((size: number) => any) | undefined;
1855
+ }>, {
1856
+ last: boolean;
1857
+ compact: boolean;
1858
+ teleport: boolean;
1859
+ mobile: boolean;
1860
+ sizes: readonly number[];
1861
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {
1862
+ anchor: HTMLButtonElement;
1863
+ }, HTMLDivElement>;
1864
+
1712
1865
  export declare const TParallelMark: DefineComponent<__VLS_Props_57, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_57> & Readonly<{}>, {
1713
1866
  others: string[];
1714
1867
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLSpanElement>;
@@ -1818,6 +1971,19 @@ disabled: boolean;
1818
1971
 
1819
1972
  export declare const TSheet: __VLS_WithTemplateSlots_9<typeof __VLS_component_9, __VLS_TemplateResult_9["slots"]>;
1820
1973
 
1974
+ export declare const TSkeleton: DefineComponent<__VLS_Props_64, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_64> & Readonly<{}>, {
1975
+ width: string;
1976
+ height: number;
1977
+ shape: keyof typeof RADIUS;
1978
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLSpanElement>;
1979
+
1980
+ export declare const TSkeletonList: DefineComponent<__VLS_Props_65, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<__VLS_Props_65> & Readonly<{}>, {
1981
+ subtitle: boolean;
1982
+ leading: keyof typeof LEADING;
1983
+ trailing: boolean;
1984
+ rows: number;
1985
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
1986
+
1821
1987
  export declare const TStartHero: DefineComponent<__VLS_Props_40, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
1822
1988
  open: () => any;
1823
1989
  pick: (taskId: string) => any;
@@ -1897,12 +2063,14 @@ list: HTMLDivElement;
1897
2063
 
1898
2064
  export declare const TWorkspaceDrawer: DefineComponent<__VLS_Props_37, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
1899
2065
  help: () => any;
2066
+ action: (id: string) => any;
1900
2067
  "update:modelValue": (id: string) => any;
1901
2068
  close: () => any;
1902
2069
  create: () => any;
1903
2070
  account: () => any;
1904
2071
  }, string, PublicProps, Readonly<__VLS_Props_37> & Readonly<{
1905
2072
  onHelp?: (() => any) | undefined;
2073
+ onAction?: ((id: string) => any) | undefined;
1906
2074
  "onUpdate:modelValue"?: ((id: string) => any) | undefined;
1907
2075
  onClose?: (() => any) | undefined;
1908
2076
  onCreate?: (() => any) | undefined;
@@ -1910,29 +2078,36 @@ onAccount?: (() => any) | undefined;
1910
2078
  }>, {
1911
2079
  teleport: boolean;
1912
2080
  showAll: boolean;
2081
+ actions: readonly WorkspaceAction[];
1913
2082
  user: DrawerUser | null;
1914
2083
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
1915
2084
 
1916
2085
  export declare const TWorkspaceMenu: DefineComponent<__VLS_Props_36, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
2086
+ action: (id: string) => any;
1917
2087
  "update:modelValue": (id: string) => any;
1918
2088
  create: () => any;
1919
2089
  }, string, PublicProps, Readonly<__VLS_Props_36> & Readonly<{
2090
+ onAction?: ((id: string) => any) | undefined;
1920
2091
  "onUpdate:modelValue"?: ((id: string) => any) | undefined;
1921
2092
  onCreate?: (() => any) | undefined;
1922
2093
  }>, {
1923
2094
  showAll: boolean;
1924
2095
  embedded: boolean;
2096
+ actions: readonly WorkspaceAction[];
1925
2097
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, HTMLDivElement>;
1926
2098
 
1927
2099
  export declare const TWorkspaceSwitcher: DefineComponent<__VLS_Props_35, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {
2100
+ action: (id: string) => any;
1928
2101
  "update:modelValue": (id: string) => any;
1929
2102
  create: () => any;
1930
2103
  }, string, PublicProps, Readonly<__VLS_Props_35> & Readonly<{
2104
+ onAction?: ((id: string) => any) | undefined;
1931
2105
  "onUpdate:modelValue"?: ((id: string) => any) | undefined;
1932
2106
  onCreate?: (() => any) | undefined;
1933
2107
  }>, {
1934
2108
  teleport: boolean;
1935
2109
  showAll: boolean;
2110
+ actions: readonly WorkspaceAction[];
1936
2111
  }, {}, {}, {}, string, ComponentProvideOptions, false, {
1937
2112
  trigger: HTMLButtonElement;
1938
2113
  }, HTMLDivElement>;
@@ -1976,11 +2151,29 @@ export declare interface WaterfallSegment {
1976
2151
 
1977
2152
  export declare const WEEKDAYS: string[];
1978
2153
 
2154
+ export declare const WHEEL_TICK = "timebraid-tick";
2155
+
1979
2156
  export declare interface WheelOption {
1980
2157
  value: number;
1981
2158
  label: string;
1982
2159
  }
1983
2160
 
2161
+ export declare const WORKSPACE_ICONS: readonly WorkspaceGalleryIcon[];
2162
+
2163
+ export declare interface WorkspaceAction {
2164
+ id: string;
2165
+ label: string;
2166
+ icon: string;
2167
+ }
2168
+
2169
+ export declare interface WorkspaceGalleryIcon {
2170
+ id: string;
2171
+ label: string;
2172
+ svg: string;
2173
+ }
2174
+
2175
+ export declare const workspaceIconDataUrl: (icon: WorkspaceGalleryIcon) => string;
2176
+
1984
2177
  export declare interface WorkspaceOption {
1985
2178
  id: string;
1986
2179
  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;--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}}.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-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)}}