@parca/profile 0.16.381 → 0.16.383

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
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.16.383](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.382...@parca/profile@0.16.383) (2024-06-05)
7
+
8
+ **Note:** Version bump only for package @parca/profile
9
+
10
+ ## [0.16.382](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.381...@parca/profile@0.16.382) (2024-06-04)
11
+
12
+ **Note:** Version bump only for package @parca/profile
13
+
6
14
  ## [0.16.381](https://github.com/parca-dev/parca/compare/@parca/profile@0.16.380...@parca/profile@0.16.381) (2024-06-04)
7
15
 
8
16
  **Note:** Version bump only for package @parca/profile
@@ -5,6 +5,7 @@ import { type NavigateFunction } from '@parca/utilities';
5
5
  interface GraphTooltipArrowContentProps {
6
6
  table: Table<any>;
7
7
  profileType?: ProfileType;
8
+ unit?: string;
8
9
  total: bigint;
9
10
  totalUnfiltered: bigint;
10
11
  row: number | null;
@@ -12,5 +13,5 @@ interface GraphTooltipArrowContentProps {
12
13
  isFixed: boolean;
13
14
  navigateTo: NavigateFunction;
14
15
  }
15
- declare const GraphTooltipArrowContent: ({ table, profileType, total, totalUnfiltered, row, level, isFixed, navigateTo, }: GraphTooltipArrowContentProps) => React.JSX.Element;
16
+ declare const GraphTooltipArrowContent: ({ table, profileType, unit, total, totalUnfiltered, row, level, isFixed, navigateTo, }: GraphTooltipArrowContentProps) => React.JSX.Element;
16
17
  export default GraphTooltipArrowContent;
@@ -8,10 +8,11 @@ import { useGraphTooltipMetaInfo } from './useGraphTooltipMetaInfo';
8
8
  const NoData = () => {
9
9
  return _jsx("span", { className: "rounded bg-gray-200 px-2 dark:bg-gray-800", children: "Not available" });
10
10
  };
11
- const GraphTooltipArrowContent = ({ table, profileType, total, totalUnfiltered, row, level, isFixed, navigateTo, }) => {
11
+ const GraphTooltipArrowContent = ({ table, profileType, unit, total, totalUnfiltered, row, level, isFixed, navigateTo, }) => {
12
12
  const graphTooltipData = useGraphTooltip({
13
13
  table,
14
14
  profileType,
15
+ unit,
15
16
  total,
16
17
  totalUnfiltered,
17
18
  row,
@@ -8,6 +8,7 @@ interface Props {
8
8
  row: number | null;
9
9
  level: number;
10
10
  profileType?: ProfileType;
11
+ unit?: string;
11
12
  }
12
- export declare const DockedGraphTooltip: ({ table, total, totalUnfiltered, row, level, profileType, }: Props) => JSX.Element;
13
+ export declare const DockedGraphTooltip: ({ table, total, totalUnfiltered, row, level, profileType, unit, }: Props) => JSX.Element;
13
14
  export {};
@@ -25,7 +25,7 @@ const InfoSection = ({ title, value, minWidth = '', }) => {
25
25
  const NoData = () => {
26
26
  return _jsx("span", { className: "rounded bg-gray-200 px-2 dark:bg-gray-800", children: "Not available" });
27
27
  };
28
- export const DockedGraphTooltip = ({ table, total, totalUnfiltered, row, level, profileType, }) => {
28
+ export const DockedGraphTooltip = ({ table, total, totalUnfiltered, row, level, profileType, unit, }) => {
29
29
  let { width } = useWindowSize();
30
30
  const { profileExplorer, navigateTo } = useParcaContext();
31
31
  const { PaddingX } = profileExplorer ?? { PaddingX: 0 };
@@ -33,6 +33,7 @@ export const DockedGraphTooltip = ({ table, total, totalUnfiltered, row, level,
33
33
  const graphTooltipData = useGraphTooltip({
34
34
  table,
35
35
  profileType,
36
+ unit,
36
37
  total,
37
38
  totalUnfiltered,
38
39
  row,
@@ -3,6 +3,7 @@ import { ProfileType } from '@parca/parser';
3
3
  interface Props {
4
4
  table: Table<any>;
5
5
  profileType?: ProfileType;
6
+ unit?: string;
6
7
  total: bigint;
7
8
  totalUnfiltered: bigint;
8
9
  row: number | null;
@@ -19,5 +20,5 @@ interface GraphTooltipData {
19
20
  diff: bigint;
20
21
  row: number;
21
22
  }
22
- export declare const useGraphTooltip: ({ table, profileType, total, totalUnfiltered, row, level, }: Props) => GraphTooltipData | null;
23
+ export declare const useGraphTooltip: ({ table, profileType, unit, total, totalUnfiltered, row, level, }: Props) => GraphTooltipData | null;
23
24
  export {};
@@ -13,11 +13,12 @@
13
13
  import { divide, valueFormatter } from '@parca/utilities';
14
14
  import { FIELD_CUMULATIVE, FIELD_CUMULATIVE_PER_SECOND, FIELD_DIFF, FIELD_DIFF_PER_SECOND, FIELD_FLAT, FIELD_FLAT_PER_SECOND, FIELD_LOCATION_ADDRESS, } from '../../ProfileIcicleGraph/IcicleGraphArrow';
15
15
  import { getTextForCumulative, getTextForCumulativePerSecond, nodeLabel, } from '../../ProfileIcicleGraph/IcicleGraphArrow/utils';
16
- export const useGraphTooltip = ({ table, profileType, total, totalUnfiltered, row, level, }) => {
16
+ export const useGraphTooltip = ({ table, profileType, unit, total, totalUnfiltered, row, level, }) => {
17
17
  if (row === null || profileType === undefined) {
18
18
  return null;
19
19
  }
20
20
  const locationAddress = table.getChild(FIELD_LOCATION_ADDRESS)?.get(row) ?? 0n;
21
+ unit = unit ?? profileType.sampleUnit;
21
22
  const cumulative = table.getChild(FIELD_CUMULATIVE)?.get(row) !== null
22
23
  ? BigInt(table.getChild(FIELD_CUMULATIVE)?.get(row))
23
24
  : 0n;
@@ -49,7 +50,7 @@ export const useGraphTooltip = ({ table, profileType, total, totalUnfiltered, ro
49
50
  const prevValue = cumulative - diff;
50
51
  const diffRatio = diff !== 0n ? divide(diff, prevValue) : 0;
51
52
  const diffSign = diff > 0 ? '+' : '';
52
- const diffValueText = diffSign + valueFormatter(diff, profileType?.sampleUnit ?? '', 1);
53
+ const diffValueText = diffSign + valueFormatter(diff, unit, 1);
53
54
  const diffPercentageText = diffSign + (diffRatio * 100).toFixed(2) + '%';
54
55
  diffText = `${diffValueText} (${diffPercentageText})`;
55
56
  }
@@ -57,10 +58,10 @@ export const useGraphTooltip = ({ table, profileType, total, totalUnfiltered, ro
57
58
  return {
58
59
  name,
59
60
  locationAddress,
60
- cumulativeText: getTextForCumulative(cumulative, totalUnfiltered, total, profileType?.periodUnit ?? ''),
61
- cumulativePerSecondText: getTextForCumulativePerSecond(cumulativePerSecond, profileType?.periodUnit ?? 'CPU Cores'),
62
- flatText: getTextForCumulative(flat, totalUnfiltered, total, profileType.periodUnit ?? ''),
63
- flatPerSecondText: getTextForCumulativePerSecond(flatPerSecond, profileType?.periodUnit ?? 'CPU Cores'),
61
+ cumulativeText: getTextForCumulative(cumulative, totalUnfiltered, total, unit ?? ''),
62
+ cumulativePerSecondText: getTextForCumulativePerSecond(cumulativePerSecond, unit ?? 'CPU Cores'),
63
+ flatText: getTextForCumulative(flat, totalUnfiltered, total, unit ?? ''),
64
+ flatPerSecondText: getTextForCumulativePerSecond(flatPerSecond, unit ?? 'CPU Cores'),
64
65
  diffText,
65
66
  diff,
66
67
  row,
@@ -6,6 +6,7 @@ interface ContextMenuProps {
6
6
  menuId: string;
7
7
  table: Table<any>;
8
8
  profileType?: ProfileType;
9
+ unit?: string;
9
10
  total: bigint;
10
11
  totalUnfiltered: bigint;
11
12
  row: number;
@@ -17,5 +18,5 @@ interface ContextMenuProps {
17
18
  hideMenu: () => void;
18
19
  hideBinary: (binaryToRemove: string) => void;
19
20
  }
20
- declare const ContextMenu: ({ menuId, table, total, totalUnfiltered, row, level, navigateTo, trackVisibility, curPath, setCurPath, hideMenu, profileType, hideBinary, }: ContextMenuProps) => JSX.Element;
21
+ declare const ContextMenu: ({ menuId, table, total, totalUnfiltered, row, level, navigateTo, trackVisibility, curPath, setCurPath, hideMenu, profileType, unit, hideBinary, }: ContextMenuProps) => JSX.Element;
21
22
  export default ContextMenu;
@@ -20,13 +20,14 @@ import { getLastItem } from '@parca/utilities';
20
20
  import { useGraphTooltip } from '../../GraphTooltipArrow/useGraphTooltip';
21
21
  import { useGraphTooltipMetaInfo } from '../../GraphTooltipArrow/useGraphTooltipMetaInfo';
22
22
  import { hexifyAddress, truncateString } from '../../utils';
23
- const ContextMenu = ({ menuId, table, total, totalUnfiltered, row, level, navigateTo, trackVisibility, curPath, setCurPath, hideMenu, profileType, hideBinary, }) => {
23
+ const ContextMenu = ({ menuId, table, total, totalUnfiltered, row, level, navigateTo, trackVisibility, curPath, setCurPath, hideMenu, profileType, unit, hideBinary, }) => {
24
24
  const { isDarkMode } = useParcaContext();
25
25
  const { enableSourcesView } = useParcaContext();
26
26
  const [isGraphTooltipDocked, setIsDocked] = useUserPreference(USER_PREFERENCES.GRAPH_METAINFO_DOCKED.key);
27
27
  const contextMenuData = useGraphTooltip({
28
28
  table,
29
29
  profileType,
30
+ unit,
30
31
  total,
31
32
  totalUnfiltered,
32
33
  row,
@@ -180,6 +180,6 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({ arrow, total, f
180
180
  highlightSimilarStacksSetLevel,
181
181
  highlightSimilarStacksSetName,
182
182
  ]);
183
- return (_jsx(_Fragment, { children: _jsxs("div", { onMouseLeave: () => dispatch(setHoveringNode(undefined)), children: [_jsx(ContextMenu, { menuId: MENU_ID, table: table, row: hoveringRow ?? 0, level: hoveringLevel ?? 0, total: total, totalUnfiltered: total + filtered, profileType: profileType, navigateTo: navigateTo, trackVisibility: trackVisibility, curPath: curPath, setCurPath: setCurPath, hideMenu: hideAll, hideBinary: hideBinary }), dockedMetainfo ? (_jsx(DockedGraphTooltip, { table: table, row: hoveringRow, level: hoveringLevel ?? 0, total: total, totalUnfiltered: total + filtered, profileType: profileType })) : (!isContextMenuOpen && (_jsx(GraphTooltipArrow, { contextElement: svg.current, isContextMenuOpen: isContextMenuOpen, children: _jsx(GraphTooltipArrowContent, { table: table, row: hoveringRow, level: hoveringLevel ?? 0, isFixed: false, total: total, totalUnfiltered: total + filtered, profileType: profileType, navigateTo: navigateTo }) }))), root] }) }));
183
+ return (_jsx(_Fragment, { children: _jsxs("div", { onMouseLeave: () => dispatch(setHoveringNode(undefined)), children: [_jsx(ContextMenu, { menuId: MENU_ID, table: table, row: hoveringRow ?? 0, level: hoveringLevel ?? 0, total: total, totalUnfiltered: total + filtered, profileType: profileType, navigateTo: navigateTo, trackVisibility: trackVisibility, curPath: curPath, setCurPath: setCurPath, hideMenu: hideAll, hideBinary: hideBinary, unit: arrow.unit }), dockedMetainfo ? (_jsx(DockedGraphTooltip, { table: table, row: hoveringRow, level: hoveringLevel ?? 0, total: total, totalUnfiltered: total + filtered, profileType: profileType, unit: arrow.unit })) : (!isContextMenuOpen && (_jsx(GraphTooltipArrow, { contextElement: svg.current, isContextMenuOpen: isContextMenuOpen, children: _jsx(GraphTooltipArrowContent, { table: table, row: hoveringRow, level: hoveringLevel ?? 0, isFixed: false, total: total, totalUnfiltered: total + filtered, profileType: profileType, navigateTo: navigateTo, unit: arrow.unit }) }))), root] }) }));
184
184
  });
185
185
  export default IcicleGraphArrow;
@@ -134,14 +134,6 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
134
134
  setIsLoading(true);
135
135
  }
136
136
  }, [loadingState]);
137
- if (error != null) {
138
- onError?.(error);
139
- if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
140
- return _jsx(ErrorContent, { errorMessage: authenticationErrorMessage });
141
- }
142
- return _jsx(ErrorContent, { errorMessage: capitalizeOnlyFirstLetter(error.message) });
143
- }
144
- // eslint-disable-next-line react-hooks/rules-of-hooks
145
137
  const icicleGraph = useMemo(() => {
146
138
  if (isLoading) {
147
139
  return (_jsx("div", { className: "h-auto overflow-clip", children: _jsx(IcicleGraphSkeleton, { isHalfScreen: isHalfScreen, isDarkMode: isDarkMode }) }));
@@ -171,6 +163,13 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({ graph, arrow, to
171
163
  isDarkMode,
172
164
  mappingsList,
173
165
  ]);
166
+ if (error != null) {
167
+ onError?.(error);
168
+ if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
169
+ return _jsx(ErrorContent, { errorMessage: authenticationErrorMessage });
170
+ }
171
+ return _jsx(ErrorContent, { errorMessage: capitalizeOnlyFirstLetter(error.message) });
172
+ }
174
173
  if (isTrimmed) {
175
174
  console.info(`Trimmed ${trimmedFormatted} (${trimmedPercentage}%) too small values.`);
176
175
  }
@@ -21,6 +21,7 @@ export interface TopTableData {
21
21
  total?: bigint;
22
22
  filtered?: bigint;
23
23
  error?: any;
24
+ unit?: string;
24
25
  }
25
26
  interface CallgraphData {
26
27
  loading: boolean;
@@ -119,7 +119,7 @@ export const ProfileView = ({ total, filtered, flamegraphData, topTableData, cal
119
119
  dimensions?.width !== undefined ? (_jsx(Callgraph, { data: callgraphData.data, svgString: callgraphSVG, profileType: profileSource?.ProfileType(), width: isHalfScreen ? dimensions?.width / 2 : dimensions?.width })) : (_jsx(_Fragment, {}));
120
120
  }
121
121
  case 'table': {
122
- return topTableData != null ? (_jsx(Table, { total: total, filtered: filtered, loading: topTableData.loading, data: topTableData.arrow?.record, profileType: profileSource?.ProfileType(), navigateTo: navigateTo, setActionButtons: setActionButtons, currentSearchString: currentSearchString, isHalfScreen: isHalfScreen })) : (_jsx(_Fragment, {}));
122
+ return topTableData != null ? (_jsx(Table, { total: total, filtered: filtered, loading: topTableData.loading, data: topTableData.arrow?.record, unit: topTableData.unit, profileType: profileSource?.ProfileType(), navigateTo: navigateTo, setActionButtons: setActionButtons, currentSearchString: currentSearchString, isHalfScreen: isHalfScreen })) : (_jsx(_Fragment, {}));
123
123
  }
124
124
  case 'source': {
125
125
  return sourceData != null ? (_jsx(SourceView, { loading: sourceData.loading, data: sourceData.data, total: total, filtered: filtered, setActionButtons: setActionButtons })) : (_jsx(_Fragment, {}));
@@ -149,6 +149,9 @@ export const ProfileViewWithData = ({ queryClient, profileSource, navigateTo, })
149
149
  ? tableResponse.report.tableArrow
150
150
  : undefined,
151
151
  error: tableError,
152
+ unit: tableResponse?.report.oneofKind === 'tableArrow'
153
+ ? tableResponse.report.tableArrow.unit
154
+ : '',
152
155
  }, callgraphData: {
153
156
  loading: callgraphLoading,
154
157
  data: callgraphResponse?.report.oneofKind === 'callgraph'
@@ -35,6 +35,7 @@ interface TableProps {
35
35
  currentSearchString?: string;
36
36
  setActionButtons?: (buttons: React.JSX.Element) => void;
37
37
  isHalfScreen: boolean;
38
+ unit?: string;
38
39
  }
39
40
  export declare const Table: React.NamedExoticComponent<TableProps>;
40
41
  export declare const RowName: (mappingFileColumn: Vector | null, locationAddressColumn: Vector | null, functionNameColumn: Vector | null, row: number) => string;
@@ -84,7 +84,12 @@ const CustomRowRenderer = ({ row, usePointerCursor, onRowClick, onRowDoubleClick
84
84
  return (_jsx("tr", { className: cx(usePointerCursor === true ? 'cursor-pointer' : 'cursor-auto', 'relative', bgClassNames, {
85
85
  'hover:bg-[#62626212] dark:hover:bg-[#ffffff12] ': !isExpanded && !_isSubRow,
86
86
  'hover:bg-indigo-200 dark:hover:bg-indigo-500': isExpanded || _isSubRow,
87
- }), onClick: onRowClick != null ? () => onRowClick(row.original) : undefined, onDoubleClick: onRowDoubleClick != null ? () => onRowDoubleClick(row, rows) : undefined, style: enableHighlighting !== true || shouldHighlightRow === undefined
87
+ }), onClick: onRowClick != null ? () => onRowClick(row.original) : undefined, onDoubleClick: onRowDoubleClick != null
88
+ ? () => {
89
+ onRowDoubleClick(row, rows);
90
+ window.getSelection()?.removeAllRanges();
91
+ }
92
+ : undefined, style: enableHighlighting !== true || shouldHighlightRow === undefined
88
93
  ? undefined
89
94
  : { opacity: shouldHighlightRow(row.original) ? 1 : 0.5 }, children: row.getVisibleCells().map((cell, idx) => {
90
95
  return (_jsxs("td", { className: cx('p-1.5 align-top', {
@@ -92,6 +97,7 @@ const CustomRowRenderer = ({ row, usePointerCursor, onRowClick, onRowDoubleClick
92
97
  'text-right': cell.column.columnDef.meta?.align === 'right',
93
98
  /* @ts-expect-error */
94
99
  'text-left': cell.column.columnDef.meta?.align === 'left',
100
+ 'pl-5 whitespace-nowrap': idx === 0,
95
101
  }), children: [idx === 0 && isExpanded ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: `absolute top-0 left-0 bg-white dark:bg-indigo-500 px-1 uppercase -rotate-90 origin-top-left z-10 text-[10px] border-l border-y border-gray-200 dark:border-gray-700 text-left `, style: getCallerLabelWidthStyle(row.originalSubRows ?? []), children: ["Callers ", '->'] }), _jsxs("div", { className: `absolute left-[18px] bg-white dark:bg-indigo-500 px-1 uppercase -rotate-90 origin-bottom-left z-10 text-[10px] border-r border-y border-gray-200 dark:border-gray-700 `, style: getCalleeLabelWidthStyle(row.originalSubRows ?? []), children: ['<-', " Callees"] })] })) : null, flexRender(cell.column.columnDef.cell, cell.getContext())] }, cell.id));
96
102
  }) }, row.id));
97
103
  };
@@ -119,7 +125,7 @@ const getCalleeRows = (callees) => {
119
125
  }
120
126
  return [{ size: 3 - rows.length, message: '', isBottomSubRow: true }, ...rows];
121
127
  };
122
- export const Table = React.memo(function Table({ data, total, filtered, profileType, navigateTo, loading, currentSearchString, setActionButtons, isHalfScreen, }) {
128
+ export const Table = React.memo(function Table({ data, total, filtered, profileType, navigateTo, loading, currentSearchString, setActionButtons, isHalfScreen, unit, }) {
123
129
  const router = parseParams(window?.location.search);
124
130
  const [rawDashboardItems] = useURLState({ param: 'dashboard_items' });
125
131
  const [filterByFunctionInput] = useURLState({ param: 'filter_by_function' });
@@ -147,12 +153,13 @@ export const Table = React.memo(function Table({ data, total, filtered, profileT
147
153
  return `${percentageString(value, total)} / ${percentageString(value, filtered)}`;
148
154
  };
149
155
  const columnHelper = createColumnHelper();
156
+ unit = useMemo(() => unit ?? profileType?.sampleUnit ?? '', [unit, profileType?.sampleUnit]);
150
157
  const columns = useMemo(() => {
151
158
  return [
152
159
  columnHelper.accessor('flat', {
153
160
  id: 'flat',
154
161
  header: 'Flat',
155
- cell: info => valueFormatter(info.getValue(), profileType?.sampleUnit ?? '', 2),
162
+ cell: info => valueFormatter(info.getValue(), unit, 2),
156
163
  size: 80,
157
164
  meta: {
158
165
  align: 'right',
@@ -177,7 +184,7 @@ export const Table = React.memo(function Table({ data, total, filtered, profileT
177
184
  columnHelper.accessor('flatDiff', {
178
185
  id: 'flatDiff',
179
186
  header: 'Flat Diff',
180
- cell: info => addPlusSign(valueFormatter(info.getValue(), profileType?.sampleUnit ?? '', 2)),
187
+ cell: info => addPlusSign(valueFormatter(info.getValue(), unit, 2)),
181
188
  size: 120,
182
189
  meta: {
183
190
  align: 'right',
@@ -202,7 +209,7 @@ export const Table = React.memo(function Table({ data, total, filtered, profileT
202
209
  columnHelper.accessor('cumulative', {
203
210
  id: 'cumulative',
204
211
  header: 'Cumulative',
205
- cell: info => valueFormatter(info.getValue(), profileType?.sampleUnit ?? '', 2),
212
+ cell: info => valueFormatter(info.getValue(), unit, 2),
206
213
  size: 150,
207
214
  meta: {
208
215
  align: 'right',
@@ -227,7 +234,7 @@ export const Table = React.memo(function Table({ data, total, filtered, profileT
227
234
  columnHelper.accessor('cumulativeDiff', {
228
235
  id: 'cumulativeDiff',
229
236
  header: 'Cumulative Diff',
230
- cell: info => addPlusSign(valueFormatter(info.getValue(), profileType?.sampleUnit ?? '', 2)),
237
+ cell: info => addPlusSign(valueFormatter(info.getValue(), unit, 2)),
231
238
  size: 170,
232
239
  meta: {
233
240
  align: 'right',
@@ -271,7 +278,7 @@ export const Table = React.memo(function Table({ data, total, filtered, profileT
271
278
  }),
272
279
  ];
273
280
  // eslint-disable-next-line react-hooks/exhaustive-deps
274
- }, [profileType]);
281
+ }, [profileType, unit]);
275
282
  const [columnVisibility, setColumnVisibility] = useState(() => {
276
283
  return {
277
284
  flat: true,
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.-inset-2{bottom:-.5rem;left:-.5rem;right:-.5rem;top:-.5rem}.inset-y-0{bottom:0;top:0}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.top-0{top:0}.left-\[18px\]{left:18px}.bottom-0{bottom:0}.z-50{z-index:50}.z-10{z-index:10}.z-20{z-index:20}.m-auto{margin:auto}.m-2{margin:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.my-4{margin-bottom:1rem;margin-top:1rem}.mr-3{margin-right:.75rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.ml-2{margin-left:.5rem}.mb-2{margin-bottom:.5rem}.mb-0\.5{margin-bottom:.125rem}.mt-1\.5{margin-top:.375rem}.mb-0{margin-bottom:0}.mb-4{margin-bottom:1rem}.ml-3{margin-left:.75rem}.mr-6{margin-right:1.5rem}.mr-1{margin-right:.25rem}.mb-1{margin-bottom:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-fit{height:-moz-fit-content;height:fit-content}.h-10{height:2.5rem}.h-\[38px\]{height:38px}.h-auto{height:auto}.h-full{height:100%}.h-1{height:.25rem}.h-6{height:1.5rem}.h-4{height:1rem}.h-\[700px\]{height:700px}.h-\[80vh\]{height:80vh}.h-5{height:1.25rem}.max-h-\[400px\]{max-height:400px}.max-h-\[300px\]{max-height:300px}.min-h-52{min-height:13rem}.min-h-\[38px\]{min-height:38px}.min-h-48{min-height:12rem}.min-h-\[78px\]{min-height:78px}.min-h-96{min-height:24rem}.min-h-\[700px\]{min-height:700px}.w-full{width:100%}.w-auto{width:auto}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-\[500px\]{width:500px}.w-max{width:-moz-max-content;width:max-content}.w-40{width:10rem}.w-3{width:.75rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-9{width:2.25rem}.w-11{width:2.75rem}.w-\[52px\]{width:52px}.w-\[68px\]{width:68px}.w-\[76px\]{width:76px}.w-\[84px\]{width:84px}.w-\[92px\]{width:92px}.w-\[100px\]{width:100px}.w-\[108px\]{width:108px}.w-\[116px\]{width:116px}.w-4{width:1rem}.w-8{width:2rem}.w-44{width:11rem}.w-\[460px\]{width:460px}.w-1\/5{width:20%}.w-11\/12{width:91.666667%}.w-1\/12{width:8.333333%}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.min-w-\[400px\]{min-width:400px}.max-w-\[500px\]{max-width:500px}.max-w-\[300px\]{max-width:300px}.max-w-\[400px\]{max-width:400px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.flex-grow-0{flex-grow:0}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.origin-top-left{transform-origin:top left}.origin-bottom-left{transform-origin:bottom left}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.-rotate-90{--tw-rotate:-90deg}.-rotate-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-auto{cursor:auto}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-4{gap:1rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-clip{overflow:clip}.overflow-scroll{overflow:scroll}.overflow-x-hidden{overflow-x:hidden}.text-ellipsis{text-overflow:ellipsis}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-y{border-bottom-width:1px;border-top-width:1px}.border-r{border-right-width:1px}.border-l{border-left-width:1px}.border-t{border-top-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.border-r-gray-200{--tw-border-opacity:1;border-right-color:rgb(229 231 235/var(--tw-border-opacity))}.border-l-amber-900{--tw-border-opacity:1;border-left-color:rgb(120 53 15/var(--tw-border-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-yellow-200{--tw-bg-opacity:1;background-color:rgb(254 240 138/var(--tw-bg-opacity))}.bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}.bg-indigo-100{--tw-bg-opacity:1;background-color:rgb(224 231 255/var(--tw-bg-opacity))}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}.bg-indigo-50{--tw-bg-opacity:1;background-color:rgb(238 242 255/var(--tw-bg-opacity))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.bg-indigo-500{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.bg-opacity-90{--tw-bg-opacity:0.9}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.stroke-gray-300{stroke:#d1d5db}.stroke-white{stroke:#fff}.stroke-\[3\]{stroke-width:3}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1\.5{padding:.375rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-4{padding-bottom:1rem;padding-top:1rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.\!py-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.\!px-3{padding-left:.75rem!important;padding-right:.75rem!important}.px-3{padding-left:.75rem;padding-right:.75rem}.py-0{padding-bottom:0;padding-top:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-8{padding-left:2rem;padding-right:2rem}.pr-0{padding-right:0}.pt-2{padding-top:.5rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pb-4{padding-bottom:1rem}.pb-2{padding-bottom:.5rem}.pb-6{padding-bottom:1.5rem}.pb-\[10px\]{padding-bottom:10px}.pl-1{padding-left:.25rem}.pr-10{padding-right:2.5rem}.pr-2{padding-right:.5rem}.pr-\[1\.7rem\]{padding-right:1.7rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-\[10px\]{font-size:10px}.text-lg{font-size:1.125rem;line-height:1.75rem}.font-semibold{font-weight:600}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.leading-6{line-height:1.5rem}.leading-5{line-height:1.25rem}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-indigo-600{--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-90{opacity:.9}.opacity-50{opacity:.5}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\]{--tw-shadow:0 0 10px 2px rgba(0,0,0,.3);--tw-shadow-colored:0 0 10px 2px var(--tw-shadow-color)}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[stroke-dasharray\:6\2c 4\]{stroke-dasharray:6,4}.\[stroke-linecap\:round\]{stroke-linecap:round}.\[stroke-linejoin\:round\]{stroke-linejoin:round}.hover\:whitespace-normal:hover{white-space:normal}.hover\:bg-\[\#62626212\]:hover{background-color:#62626212}.hover\:bg-indigo-200:hover{--tw-bg-opacity:1;background-color:rgb(199 210 254/var(--tw-bg-opacity))}.focus\:border-indigo-500:focus{--tw-border-opacity:1;border-color:rgb(99 102 241/var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-1:focus,.focus\:ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-indigo-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(99 102 241/var(--tw-ring-opacity))}.focus\:ring-indigo-600:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(79 70 229/var(--tw-ring-opacity))}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}.group:hover .group-hover\:flex{display:flex}[class~=theme-dark] .dark\:border{border-width:1px}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-r-gray-700{--tw-border-opacity:1;border-right-color:rgb(55 65 81/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-500{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-indigo-500{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-opacity-80{--tw-bg-opacity:0.8}[class~=theme-dark] .dark\:stroke-gray-500{stroke:#6b7280}[class~=theme-dark] .dark\:stroke-gray-700{stroke:#374151}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}[class~=theme-dark] .dark\:ring-white{--tw-ring-opacity:1;--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity))}[class~=theme-dark] .dark\:ring-opacity-20{--tw-ring-opacity:0.2}[class~=theme-dark] .dark\:hover\:bg-\[\#ffffff12\]:hover{background-color:#ffffff12}[class~=theme-dark] .dark\:hover\:bg-indigo-500:hover{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}[class~=theme-dark] .hover\:dark\:text-gray-100:hover{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:block{display:block}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}.md\:justify-end{justify-content:flex-end}}@media (min-width:1024px){.lg\:flex{display:flex}}
1
+ /*! tailwindcss v3.2.4 | MIT License | https://tailwindcss.com*/*,:after,:before{border:0 solid #e5e7eb;box-sizing:border-box}:after,:before{--tw-content:""}html{-webkit-text-size-adjust:100%;font-feature-settings:normal;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4}body{line-height:inherit;margin:0}hr{border-top-width:1px;color:inherit;height:0}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{border-collapse:collapse;border-color:inherit;text-indent:0}button,input,optgroup,select,textarea{color:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{color:#9ca3af;opacity:1}input::placeholder,textarea::placeholder{color:#9ca3af;opacity:1}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{height:auto;max-width:100%}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.-inset-2{bottom:-.5rem;left:-.5rem;right:-.5rem;top:-.5rem}.inset-y-0{bottom:0;top:0}.left-\[25px\]{left:25px}.left-0{left:0}.top-\[-46px\]{top:-46px}.right-0{right:0}.top-0{top:0}.left-\[18px\]{left:18px}.bottom-0{bottom:0}.z-50{z-index:50}.z-10{z-index:10}.z-20{z-index:20}.m-auto{margin:auto}.m-2{margin:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mx-2{margin-left:.5rem;margin-right:.5rem}.my-2{margin-bottom:.5rem;margin-top:.5rem}.my-20{margin-bottom:5rem;margin-top:5rem}.my-6{margin-bottom:1.5rem;margin-top:1.5rem}.my-4{margin-bottom:1rem;margin-top:1rem}.mr-3{margin-right:.75rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.ml-2{margin-left:.5rem}.mb-2{margin-bottom:.5rem}.mb-0\.5{margin-bottom:.125rem}.mt-1\.5{margin-top:.375rem}.mb-0{margin-bottom:0}.mb-4{margin-bottom:1rem}.ml-3{margin-left:.75rem}.mr-6{margin-right:1.5rem}.mr-1{margin-right:.25rem}.mb-1{margin-bottom:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-8{margin-top:2rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-fit{height:-moz-fit-content;height:fit-content}.h-10{height:2.5rem}.h-\[38px\]{height:38px}.h-auto{height:auto}.h-full{height:100%}.h-1{height:.25rem}.h-6{height:1.5rem}.h-4{height:1rem}.h-\[700px\]{height:700px}.h-\[80vh\]{height:80vh}.h-5{height:1.25rem}.max-h-\[400px\]{max-height:400px}.max-h-\[300px\]{max-height:300px}.min-h-52{min-height:13rem}.min-h-\[38px\]{min-height:38px}.min-h-48{min-height:12rem}.min-h-\[78px\]{min-height:78px}.min-h-96{min-height:24rem}.min-h-\[700px\]{min-height:700px}.w-full{width:100%}.w-auto{width:auto}.w-1\/4{width:25%}.w-3\/4{width:75%}.w-\[500px\]{width:500px}.w-max{width:-moz-max-content;width:max-content}.w-40{width:10rem}.w-3{width:.75rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-9{width:2.25rem}.w-11{width:2.75rem}.w-\[52px\]{width:52px}.w-\[68px\]{width:68px}.w-\[76px\]{width:76px}.w-\[84px\]{width:84px}.w-\[92px\]{width:92px}.w-\[100px\]{width:100px}.w-\[108px\]{width:108px}.w-\[116px\]{width:116px}.w-4{width:1rem}.w-8{width:2rem}.w-44{width:11rem}.w-\[460px\]{width:460px}.w-1\/5{width:20%}.w-11\/12{width:91.666667%}.w-1\/12{width:8.333333%}.w-16{width:4rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-\[420px\]{width:420px}.min-w-\[300px\]{min-width:300px}.min-w-\[400px\]{min-width:400px}.max-w-\[500px\]{max-width:500px}.max-w-\[300px\]{max-width:300px}.max-w-\[400px\]{max-width:400px}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.flex-grow-0{flex-grow:0}.flex-grow{flex-grow:1}.table-auto{table-layout:auto}.table-fixed{table-layout:fixed}.origin-top-left{transform-origin:top left}.origin-bottom-left{transform-origin:bottom left}.translate-y-1{--tw-translate-y:0.25rem}.translate-y-0,.translate-y-1{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y:0px}.-rotate-90{--tw-rotate:-90deg}.-rotate-90,.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-auto{cursor:auto}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.content-start{align-content:flex-start}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-4{gap:1rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-bottom:calc(1.25rem*var(--tw-space-y-reverse));margin-top:calc(1.25rem*(1 - var(--tw-space-y-reverse)))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-clip{overflow:clip}.overflow-scroll{overflow:scroll}.overflow-x-hidden{overflow-x:hidden}.text-ellipsis{text-overflow:ellipsis}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-none{border-radius:0}.rounded-t-lg{border-top-left-radius:.5rem;border-top-right-radius:.5rem}.rounded-l{border-bottom-left-radius:.25rem;border-top-left-radius:.25rem}.rounded-r{border-bottom-right-radius:.25rem;border-top-right-radius:.25rem}.border{border-width:1px}.border-y{border-bottom-width:1px;border-top-width:1px}.border-r{border-right-width:1px}.border-l{border-left-width:1px}.border-t{border-top-width:1px}.border-r-0{border-right-width:0}.border-l-0{border-left-width:0}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-red-400{--tw-border-opacity:1;border-color:rgb(248 113 113/var(--tw-border-opacity))}.border-gray-200{--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.border-r-gray-200{--tw-border-opacity:1;border-right-color:rgb(229 231 235/var(--tw-border-opacity))}.border-l-amber-900{--tw-border-opacity:1;border-left-color:rgb(120 53 15/var(--tw-border-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-gray-200{--tw-bg-opacity:1;background-color:rgb(229 231 235/var(--tw-bg-opacity))}.bg-indigo-600{--tw-bg-opacity:1;background-color:rgb(79 70 229/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-red-100{--tw-bg-opacity:1;background-color:rgb(254 226 226/var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}.bg-yellow-200{--tw-bg-opacity:1;background-color:rgb(254 240 138/var(--tw-bg-opacity))}.bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}.bg-indigo-100{--tw-bg-opacity:1;background-color:rgb(224 231 255/var(--tw-bg-opacity))}.bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}.bg-indigo-50{--tw-bg-opacity:1;background-color:rgb(238 242 255/var(--tw-bg-opacity))}.bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}.bg-indigo-500{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}.bg-inherit{background-color:inherit}.bg-opacity-90{--tw-bg-opacity:0.9}.fill-transparent{fill:transparent}.fill-current{fill:currentColor}.stroke-gray-300{stroke:#d1d5db}.stroke-white{stroke:#fff}.stroke-\[3\]{stroke-width:3}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-10{padding:2.5rem}.p-4{padding:1rem}.p-1\.5{padding:.375rem}.p-1{padding:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-1{padding-bottom:.25rem;padding-top:.25rem}.py-2{padding-bottom:.5rem;padding-top:.5rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-4{padding-bottom:1rem;padding-top:1rem}.px-4{padding-left:1rem;padding-right:1rem}.py-3{padding-bottom:.75rem;padding-top:.75rem}.\!py-2{padding-bottom:.5rem!important;padding-top:.5rem!important}.\!px-3{padding-left:.75rem!important;padding-right:.75rem!important}.px-3{padding-left:.75rem;padding-right:.75rem}.py-0{padding-bottom:0;padding-top:0}.px-1{padding-left:.25rem;padding-right:.25rem}.px-8{padding-left:2rem;padding-right:2rem}.pr-0{padding-right:0}.pt-2{padding-top:.5rem}.pl-3{padding-left:.75rem}.pr-9{padding-right:2.25rem}.pb-4{padding-bottom:1rem}.pb-2{padding-bottom:.5rem}.pb-6{padding-bottom:1.5rem}.pb-\[10px\]{padding-bottom:10px}.pl-1{padding-left:.25rem}.pr-10{padding-right:2.5rem}.pr-2{padding-right:.5rem}.pl-5{padding-left:1.25rem}.pr-\[1\.7rem\]{padding-right:1.7rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.text-base{font-size:1rem;line-height:1.5rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-\[10px\]{font-size:10px}.text-lg{font-size:1.125rem;line-height:1.75rem}.font-semibold{font-weight:600}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.leading-6{line-height:1.5rem}.leading-5{line-height:1.25rem}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-black{--tw-text-opacity:1;color:rgb(0 0 0/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-indigo-600{--tw-text-opacity:1;color:rgb(79 70 229/var(--tw-text-opacity))}.text-gray-900{--tw-text-opacity:1;color:rgb(17 24 39/var(--tw-text-opacity))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity))}.\!text-indigo-600{--tw-text-opacity:1!important;color:rgb(79 70 229/var(--tw-text-opacity))!important}.opacity-100{opacity:1}.opacity-0{opacity:0}.opacity-90{opacity:.9}.opacity-50{opacity:.5}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\]{--tw-shadow:0 0 10px 2px rgba(0,0,0,.3);--tw-shadow-colored:0 0 10px 2px var(--tw-shadow-color)}.shadow-\[0_0_10px_2px_rgba\(0\2c 0\2c 0\2c 0\.3\)\],.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow-md{--tw-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -2px rgba(0,0,0,.1);--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color),0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-black{--tw-ring-opacity:1;--tw-ring-color:rgb(0 0 0/var(--tw-ring-opacity))}.ring-opacity-5{--tw-ring-opacity:0.05}.blur{--tw-blur:blur(8px)}.blur,.invert{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.invert{--tw-invert:invert(100%)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-duration:.15s;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-100{transition-duration:.1s}.duration-200{transition-duration:.2s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.\[stroke-dasharray\:6\2c 4\]{stroke-dasharray:6,4}.\[stroke-linecap\:round\]{stroke-linecap:round}.\[stroke-linejoin\:round\]{stroke-linejoin:round}.hover\:whitespace-normal:hover{white-space:normal}.hover\:bg-\[\#62626212\]:hover{background-color:#62626212}.hover\:bg-indigo-200:hover{--tw-bg-opacity:1;background-color:rgb(199 210 254/var(--tw-bg-opacity))}.focus\:border-indigo-500:focus{--tw-border-opacity:1;border-color:rgb(99 102 241/var(--tw-border-opacity))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-1:focus,.focus\:ring-2:focus{box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)}.focus\:ring-indigo-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(99 102 241/var(--tw-ring-opacity))}.focus\:ring-indigo-600:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(79 70 229/var(--tw-ring-opacity))}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px}.group:hover .group-hover\:flex{display:flex}[class~=theme-dark] .dark\:border{border-width:1px}[class~=theme-dark] .dark\:border-gray-500{--tw-border-opacity:1;border-color:rgb(107 114 128/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-gray-600{--tw-border-opacity:1;border-color:rgb(75 85 99/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity))}[class~=theme-dark] .dark\:border-r-gray-700{--tw-border-opacity:1;border-right-color:rgb(55 65 81/var(--tw-border-opacity))}[class~=theme-dark] .dark\:bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-700{--tw-bg-opacity:1;background-color:rgb(55 65 81/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-500{--tw-bg-opacity:1;background-color:rgb(107 114 128/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-yellow-700{--tw-bg-opacity:1;background-color:rgb(161 98 7/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-gray-600{--tw-bg-opacity:1;background-color:rgb(75 85 99/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-indigo-500{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-black{--tw-bg-opacity:1;background-color:rgb(0 0 0/var(--tw-bg-opacity))}[class~=theme-dark] .dark\:bg-opacity-80{--tw-bg-opacity:0.8}[class~=theme-dark] .dark\:stroke-gray-500{stroke:#6b7280}[class~=theme-dark] .dark\:stroke-gray-700{stroke:#374151}[class~=theme-dark] .dark\:text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-gray-50{--tw-text-opacity:1;color:rgb(249 250 251/var(--tw-text-opacity))}[class~=theme-dark] .dark\:text-indigo-500{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity))}[class~=theme-dark] .dark\:\!text-indigo-400{--tw-text-opacity:1!important;color:rgb(129 140 248/var(--tw-text-opacity))!important}[class~=theme-dark] .dark\:ring-white{--tw-ring-opacity:1;--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity))}[class~=theme-dark] .dark\:ring-opacity-20{--tw-ring-opacity:0.2}[class~=theme-dark] .dark\:hover\:bg-\[\#ffffff12\]:hover{background-color:#ffffff12}[class~=theme-dark] .dark\:hover\:bg-indigo-500:hover{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity))}[class~=theme-dark] .hover\:dark\:text-gray-100:hover{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}@media (min-width:640px){.sm\:inline{display:inline}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width:768px){.md\:block{display:block}.md\:flex-row{flex-direction:row}.md\:items-end{align-items:flex-end}.md\:justify-end{justify-content:flex-end}}@media (min-width:1024px){.lg\:flex{display:flex}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parca/profile",
3
- "version": "0.16.381",
3
+ "version": "0.16.383",
4
4
  "description": "Profile viewing libraries",
5
5
  "dependencies": {
6
6
  "@headlessui/react": "^1.7.19",
@@ -71,5 +71,5 @@
71
71
  "access": "public",
72
72
  "registry": "https://registry.npmjs.org/"
73
73
  },
74
- "gitHead": "b635461683728acd7afd5caf540c324f84f64590"
74
+ "gitHead": "c29c6d4d865438567a07f29652ed186e6916087d"
75
75
  }
@@ -27,6 +27,7 @@ import {useGraphTooltipMetaInfo} from './useGraphTooltipMetaInfo';
27
27
  interface GraphTooltipArrowContentProps {
28
28
  table: Table<any>;
29
29
  profileType?: ProfileType;
30
+ unit?: string;
30
31
  total: bigint;
31
32
  totalUnfiltered: bigint;
32
33
  row: number | null;
@@ -42,6 +43,7 @@ const NoData = (): React.JSX.Element => {
42
43
  const GraphTooltipArrowContent = ({
43
44
  table,
44
45
  profileType,
46
+ unit,
45
47
  total,
46
48
  totalUnfiltered,
47
49
  row,
@@ -52,6 +54,7 @@ const GraphTooltipArrowContent = ({
52
54
  const graphTooltipData = useGraphTooltip({
53
55
  table,
54
56
  profileType,
57
+ unit,
55
58
  total,
56
59
  totalUnfiltered,
57
60
  row,
@@ -31,6 +31,7 @@ interface Props {
31
31
  row: number | null;
32
32
  level: number;
33
33
  profileType?: ProfileType;
34
+ unit?: string;
34
35
  }
35
36
 
36
37
  const InfoSection = ({
@@ -61,6 +62,7 @@ export const DockedGraphTooltip = ({
61
62
  row,
62
63
  level,
63
64
  profileType,
65
+ unit,
64
66
  }: Props): JSX.Element => {
65
67
  let {width} = useWindowSize();
66
68
  const {profileExplorer, navigateTo} = useParcaContext();
@@ -70,6 +72,7 @@ export const DockedGraphTooltip = ({
70
72
  const graphTooltipData = useGraphTooltip({
71
73
  table,
72
74
  profileType,
75
+ unit,
73
76
  total,
74
77
  totalUnfiltered,
75
78
  row,
@@ -34,6 +34,7 @@ import {
34
34
  interface Props {
35
35
  table: Table<any>;
36
36
  profileType?: ProfileType;
37
+ unit?: string;
37
38
  total: bigint;
38
39
  totalUnfiltered: bigint;
39
40
  row: number | null;
@@ -55,6 +56,7 @@ interface GraphTooltipData {
55
56
  export const useGraphTooltip = ({
56
57
  table,
57
58
  profileType,
59
+ unit,
58
60
  total,
59
61
  totalUnfiltered,
60
62
  row,
@@ -65,6 +67,7 @@ export const useGraphTooltip = ({
65
67
  }
66
68
 
67
69
  const locationAddress: bigint = table.getChild(FIELD_LOCATION_ADDRESS)?.get(row) ?? 0n;
70
+ unit = unit ?? profileType.sampleUnit;
68
71
 
69
72
  const cumulative: bigint =
70
73
  table.getChild(FIELD_CUMULATIVE)?.get(row) !== null
@@ -103,7 +106,7 @@ export const useGraphTooltip = ({
103
106
  const prevValue = cumulative - diff;
104
107
  const diffRatio = diff !== 0n ? divide(diff, prevValue) : 0;
105
108
  const diffSign = diff > 0 ? '+' : '';
106
- const diffValueText = diffSign + valueFormatter(diff, profileType?.sampleUnit ?? '', 1);
109
+ const diffValueText = diffSign + valueFormatter(diff, unit, 1);
107
110
  const diffPercentageText = diffSign + (diffRatio * 100).toFixed(2) + '%';
108
111
  diffText = `${diffValueText} (${diffPercentageText})`;
109
112
  }
@@ -113,21 +116,13 @@ export const useGraphTooltip = ({
113
116
  return {
114
117
  name,
115
118
  locationAddress,
116
- cumulativeText: getTextForCumulative(
117
- cumulative,
118
- totalUnfiltered,
119
- total,
120
- profileType?.periodUnit ?? ''
121
- ),
119
+ cumulativeText: getTextForCumulative(cumulative, totalUnfiltered, total, unit ?? ''),
122
120
  cumulativePerSecondText: getTextForCumulativePerSecond(
123
121
  cumulativePerSecond,
124
- profileType?.periodUnit ?? 'CPU Cores'
125
- ),
126
- flatText: getTextForCumulative(flat, totalUnfiltered, total, profileType.periodUnit ?? ''),
127
- flatPerSecondText: getTextForCumulativePerSecond(
128
- flatPerSecond,
129
- profileType?.periodUnit ?? 'CPU Cores'
122
+ unit ?? 'CPU Cores'
130
123
  ),
124
+ flatText: getTextForCumulative(flat, totalUnfiltered, total, unit ?? ''),
125
+ flatPerSecondText: getTextForCumulativePerSecond(flatPerSecond, unit ?? 'CPU Cores'),
131
126
  diffText,
132
127
  diff,
133
128
  row,
@@ -29,6 +29,7 @@ interface ContextMenuProps {
29
29
  menuId: string;
30
30
  table: Table<any>;
31
31
  profileType?: ProfileType;
32
+ unit?: string;
32
33
  total: bigint;
33
34
  totalUnfiltered: bigint;
34
35
  row: number;
@@ -54,6 +55,7 @@ const ContextMenu = ({
54
55
  setCurPath,
55
56
  hideMenu,
56
57
  profileType,
58
+ unit,
57
59
  hideBinary,
58
60
  }: ContextMenuProps): JSX.Element => {
59
61
  const {isDarkMode} = useParcaContext();
@@ -64,6 +66,7 @@ const ContextMenu = ({
64
66
  const contextMenuData = useGraphTooltip({
65
67
  table,
66
68
  profileType,
69
+ unit,
67
70
  total,
68
71
  totalUnfiltered,
69
72
  row,
@@ -318,6 +318,7 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
318
318
  setCurPath={setCurPath}
319
319
  hideMenu={hideAll}
320
320
  hideBinary={hideBinary}
321
+ unit={arrow.unit}
321
322
  />
322
323
  {dockedMetainfo ? (
323
324
  <DockedGraphTooltip
@@ -327,6 +328,7 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
327
328
  total={total}
328
329
  totalUnfiltered={total + filtered}
329
330
  profileType={profileType}
331
+ unit={arrow.unit}
330
332
  />
331
333
  ) : (
332
334
  !isContextMenuOpen && (
@@ -340,6 +342,7 @@ export const IcicleGraphArrow = memo(function IcicleGraphArrow({
340
342
  totalUnfiltered={total + filtered}
341
343
  profileType={profileType}
342
344
  navigateTo={navigateTo as NavigateFunction}
345
+ unit={arrow.unit}
343
346
  />
344
347
  </GraphTooltipArrow>
345
348
  )
@@ -340,17 +340,6 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
340
340
  }
341
341
  }, [loadingState]);
342
342
 
343
- if (error != null) {
344
- onError?.(error);
345
-
346
- if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
347
- return <ErrorContent errorMessage={authenticationErrorMessage} />;
348
- }
349
-
350
- return <ErrorContent errorMessage={capitalizeOnlyFirstLetter(error.message)} />;
351
- }
352
-
353
- // eslint-disable-next-line react-hooks/rules-of-hooks
354
343
  const icicleGraph = useMemo(() => {
355
344
  if (isLoading) {
356
345
  return (
@@ -415,6 +404,16 @@ const ProfileIcicleGraph = function ProfileIcicleGraphNonMemo({
415
404
  mappingsList,
416
405
  ]);
417
406
 
407
+ if (error != null) {
408
+ onError?.(error);
409
+
410
+ if (authenticationErrorMessage !== undefined && error.code === 'UNAUTHENTICATED') {
411
+ return <ErrorContent errorMessage={authenticationErrorMessage} />;
412
+ }
413
+
414
+ return <ErrorContent errorMessage={capitalizeOnlyFirstLetter(error.message)} />;
415
+ }
416
+
418
417
  if (isTrimmed) {
419
418
  console.info(`Trimmed ${trimmedFormatted} (${trimmedPercentage}%) too small values.`);
420
419
  }
@@ -78,6 +78,7 @@ export interface TopTableData {
78
78
  total?: bigint;
79
79
  filtered?: bigint;
80
80
  error?: any;
81
+ unit?: string;
81
82
  }
82
83
 
83
84
  interface CallgraphData {
@@ -278,6 +279,7 @@ export const ProfileView = ({
278
279
  filtered={filtered}
279
280
  loading={topTableData.loading}
280
281
  data={topTableData.arrow?.record}
282
+ unit={topTableData.unit}
281
283
  profileType={profileSource?.ProfileType()}
282
284
  navigateTo={navigateTo}
283
285
  setActionButtons={setActionButtons}
@@ -214,6 +214,10 @@ export const ProfileViewWithData = ({
214
214
  ? tableResponse.report.tableArrow
215
215
  : undefined,
216
216
  error: tableError,
217
+ unit:
218
+ tableResponse?.report.oneofKind === 'tableArrow'
219
+ ? tableResponse.report.tableArrow.unit
220
+ : '',
217
221
  }}
218
222
  callgraphData={{
219
223
  loading: callgraphLoading,
@@ -99,6 +99,7 @@ interface TableProps {
99
99
  currentSearchString?: string;
100
100
  setActionButtons?: (buttons: React.JSX.Element) => void;
101
101
  isHalfScreen: boolean;
102
+ unit?: string;
102
103
  }
103
104
 
104
105
  const rowBgClassNames = (isExpanded: boolean, isSubRow: boolean): Record<string, boolean> => {
@@ -182,7 +183,14 @@ const CustomRowRenderer = ({
182
183
  }
183
184
  )}
184
185
  onClick={onRowClick != null ? () => onRowClick(row.original) : undefined}
185
- onDoubleClick={onRowDoubleClick != null ? () => onRowDoubleClick(row, rows) : undefined}
186
+ onDoubleClick={
187
+ onRowDoubleClick != null
188
+ ? () => {
189
+ onRowDoubleClick(row, rows);
190
+ window.getSelection()?.removeAllRanges();
191
+ }
192
+ : undefined
193
+ }
186
194
  style={
187
195
  enableHighlighting !== true || shouldHighlightRow === undefined
188
196
  ? undefined
@@ -198,6 +206,7 @@ const CustomRowRenderer = ({
198
206
  'text-right': cell.column.columnDef.meta?.align === 'right',
199
207
  /* @ts-expect-error */
200
208
  'text-left': cell.column.columnDef.meta?.align === 'left',
209
+ 'pl-5 whitespace-nowrap': idx === 0,
201
210
  })}
202
211
  >
203
212
  {idx === 0 && isExpanded ? (
@@ -264,6 +273,7 @@ export const Table = React.memo(function Table({
264
273
  currentSearchString,
265
274
  setActionButtons,
266
275
  isHalfScreen,
276
+ unit,
267
277
  }: TableProps): React.JSX.Element {
268
278
  const router = parseParams(window?.location.search);
269
279
  const [rawDashboardItems] = useURLState({param: 'dashboard_items'});
@@ -300,17 +310,14 @@ export const Table = React.memo(function Table({
300
310
 
301
311
  const columnHelper = createColumnHelper<Row>();
302
312
 
313
+ unit = useMemo(() => unit ?? profileType?.sampleUnit ?? '', [unit, profileType?.sampleUnit]);
314
+
303
315
  const columns = useMemo<Array<ColumnDef<Row>>>(() => {
304
316
  return [
305
317
  columnHelper.accessor('flat', {
306
318
  id: 'flat',
307
319
  header: 'Flat',
308
- cell: info =>
309
- valueFormatter(
310
- (info as CellContext<DataRow, bigint>).getValue(),
311
- profileType?.sampleUnit ?? '',
312
- 2
313
- ),
320
+ cell: info => valueFormatter((info as CellContext<DataRow, bigint>).getValue(), unit, 2),
314
321
  size: 80,
315
322
  meta: {
316
323
  align: 'right',
@@ -336,13 +343,7 @@ export const Table = React.memo(function Table({
336
343
  id: 'flatDiff',
337
344
  header: 'Flat Diff',
338
345
  cell: info =>
339
- addPlusSign(
340
- valueFormatter(
341
- (info as CellContext<DataRow, bigint>).getValue(),
342
- profileType?.sampleUnit ?? '',
343
- 2
344
- )
345
- ),
346
+ addPlusSign(valueFormatter((info as CellContext<DataRow, bigint>).getValue(), unit, 2)),
346
347
  size: 120,
347
348
  meta: {
348
349
  align: 'right',
@@ -367,12 +368,7 @@ export const Table = React.memo(function Table({
367
368
  columnHelper.accessor('cumulative', {
368
369
  id: 'cumulative',
369
370
  header: 'Cumulative',
370
- cell: info =>
371
- valueFormatter(
372
- (info as CellContext<DataRow, bigint>).getValue(),
373
- profileType?.sampleUnit ?? '',
374
- 2
375
- ),
371
+ cell: info => valueFormatter((info as CellContext<DataRow, bigint>).getValue(), unit, 2),
376
372
  size: 150,
377
373
  meta: {
378
374
  align: 'right',
@@ -398,13 +394,7 @@ export const Table = React.memo(function Table({
398
394
  id: 'cumulativeDiff',
399
395
  header: 'Cumulative Diff',
400
396
  cell: info =>
401
- addPlusSign(
402
- valueFormatter(
403
- (info as CellContext<DataRow, bigint>).getValue(),
404
- profileType?.sampleUnit ?? '',
405
- 2
406
- )
407
- ),
397
+ addPlusSign(valueFormatter((info as CellContext<DataRow, bigint>).getValue(), unit, 2)),
408
398
  size: 170,
409
399
  meta: {
410
400
  align: 'right',
@@ -448,7 +438,7 @@ export const Table = React.memo(function Table({
448
438
  }),
449
439
  ];
450
440
  // eslint-disable-next-line react-hooks/exhaustive-deps
451
- }, [profileType]);
441
+ }, [profileType, unit]);
452
442
 
453
443
  const [columnVisibility, setColumnVisibility] = useState(() => {
454
444
  return {