@schumann-dev/ui 0.12.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.
Files changed (48) hide show
  1. package/README.md +144 -0
  2. package/dist/atoms/Avatar/Avatar.d.ts +12 -0
  3. package/dist/atoms/Badge/Badge.d.ts +11 -0
  4. package/dist/atoms/Button/Button.d.ts +14 -0
  5. package/dist/atoms/Heading/Heading.d.ts +8 -0
  6. package/dist/atoms/Icon/Icon.d.ts +30 -0
  7. package/dist/atoms/IconButton/IconButton.d.ts +10 -0
  8. package/dist/atoms/Input/Input.d.ts +11 -0
  9. package/dist/atoms/Label/Label.d.ts +5 -0
  10. package/dist/atoms/ProgressBar/ProgressBar.d.ts +16 -0
  11. package/dist/atoms/Skeleton/Skeleton.d.ts +10 -0
  12. package/dist/atoms/Spinner/Spinner.d.ts +8 -0
  13. package/dist/atoms/Switch/Switch.d.ts +11 -0
  14. package/dist/atoms/Text/Text.d.ts +16 -0
  15. package/dist/chunks/Icon-xe35IPZg.js +141 -0
  16. package/dist/hooks/useControllableState.d.ts +8 -0
  17. package/dist/hooks/useFormField.d.ts +9 -0
  18. package/dist/icons/lucide.d.ts +1 -0
  19. package/dist/icons.js +16 -0
  20. package/dist/index.d.ts +72 -0
  21. package/dist/index.js +1814 -0
  22. package/dist/molecules/ColorPicker/ColorPicker.d.ts +19 -0
  23. package/dist/molecules/Combobox/Combobox.d.ts +18 -0
  24. package/dist/molecules/DateTimeInput/DateTimeInput.d.ts +10 -0
  25. package/dist/molecules/EmptyState/EmptyState.d.ts +14 -0
  26. package/dist/molecules/FormField/FormField.d.ts +16 -0
  27. package/dist/molecules/IconPicker/IconPicker.d.ts +17 -0
  28. package/dist/molecules/MoneyInput/MoneyInput.d.ts +12 -0
  29. package/dist/molecules/MonthPicker/MonthPicker.d.ts +20 -0
  30. package/dist/molecules/MultiSelect/MultiSelect.d.ts +21 -0
  31. package/dist/molecules/SegmentedControl/SegmentedControl.d.ts +19 -0
  32. package/dist/molecules/StatCard/StatCard.d.ts +18 -0
  33. package/dist/molecules/SwitchCard/SwitchCard.d.ts +11 -0
  34. package/dist/molecules/Tooltip/Tooltip.d.ts +17 -0
  35. package/dist/organisms/Card/Card.d.ts +18 -0
  36. package/dist/organisms/ConfirmModal/ConfirmModal.d.ts +19 -0
  37. package/dist/organisms/DataTable/DataTable.d.ts +41 -0
  38. package/dist/organisms/Menu/Menu.d.ts +24 -0
  39. package/dist/organisms/Modal/Modal.d.ts +30 -0
  40. package/dist/styles.css +1 -0
  41. package/dist/templates/AppShell/AppShell.d.ts +38 -0
  42. package/dist/templates/PageContainer/PageContainer.d.ts +7 -0
  43. package/dist/templates/PageHeader/PageHeader.d.ts +14 -0
  44. package/dist/utils/color.d.ts +10 -0
  45. package/dist/utils/cx.d.ts +3 -0
  46. package/dist/utils/dom.d.ts +19 -0
  47. package/dist/utils/text.d.ts +2 -0
  48. package/package.json +89 -0
@@ -0,0 +1,19 @@
1
+ /** Paleta padrão de sugestões (sobrescreva via prop `swatches`). */
2
+ export declare const DEFAULT_SWATCHES: string[];
3
+ export interface ColorPickerProps {
4
+ value: string;
5
+ onChange: (hex: string) => void;
6
+ /** Sugestões em formato de bolinha, antes do botão "cor personalizada". */
7
+ swatches?: string[];
8
+ /** Painel aberto por padrão (não-controlado). */
9
+ defaultOpen?: boolean;
10
+ open?: boolean;
11
+ onOpenChange?: (open: boolean) => void;
12
+ /** Mostra a linha de preview + campo hex/rgb dentro do painel. Default: true. */
13
+ showInput?: boolean;
14
+ customLabel?: string;
15
+ className?: string;
16
+ }
17
+ /** Seletor de cor: swatches + botão de cor personalizada que expande um painel
18
+ * inline com canvas HSV arrastável, hue slider e campo dual hex/rgb. */
19
+ export declare function ColorPicker({ value, onChange, swatches, defaultOpen, open: openProp, onOpenChange, showInput, customLabel, className, }: ColorPickerProps): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ComboboxOption {
3
+ value: string;
4
+ label: string;
5
+ /** Visual à esquerda da opção (ícone, logo, dot de cor…) — fornecido pelo app. */
6
+ leading?: ReactNode;
7
+ }
8
+ export interface ComboboxProps {
9
+ value: string;
10
+ onChange: (value: string) => void;
11
+ options: ComboboxOption[];
12
+ placeholder?: string;
13
+ emptyText?: string;
14
+ disabled?: boolean;
15
+ className?: string;
16
+ }
17
+ /** Single-select pesquisável (combobox com dropdown), navegável por teclado. */
18
+ export declare function Combobox({ value, onChange, options, placeholder, emptyText, disabled, className, }: ComboboxProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ export interface DateTimeInputProps {
2
+ /** ISO local 'YYYY-MM-DDTHH:mm' (ou ''). */
3
+ value: string;
4
+ onChange: (isoValue: string) => void;
5
+ placeholder?: string;
6
+ disabled?: boolean;
7
+ }
8
+ /** Campo de data/hora com máscara de digitação dd/mm/aaaa hh:mm.
9
+ * Emite onChange apenas quando a data digitada é válida e completa. */
10
+ export declare function DateTimeInput({ value, onChange, placeholder, disabled, }: DateTimeInputProps): import("react").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ export interface EmptyStateProps {
3
+ /** Ícone/ilustração no topo (opcional). */
4
+ icon?: ReactNode;
5
+ title: ReactNode;
6
+ description?: ReactNode;
7
+ /** Ações abaixo do texto (ex.: botão "Adicionar"). */
8
+ actions?: ReactNode;
9
+ /** Borda tracejada — para dropzones / áreas "adicione o primeiro item". */
10
+ dashed?: boolean;
11
+ className?: string;
12
+ }
13
+ /** Estado vazio centralizado: ícone + título + descrição + ações. */
14
+ export declare function EmptyState({ icon, title, description, actions, dashed, className }: EmptyStateProps): import("react").JSX.Element;
@@ -0,0 +1,16 @@
1
+ import { ReactNode } from 'react';
2
+ export interface FormFieldProps {
3
+ label?: ReactNode;
4
+ hint?: ReactNode;
5
+ /** When set, the field renders in the error state and shows this message. */
6
+ error?: ReactNode;
7
+ required?: boolean;
8
+ /** Explicit id for the control; auto-generated otherwise. */
9
+ id?: string;
10
+ className?: string;
11
+ children: ReactNode;
12
+ }
13
+ /** Wraps a control with a label, hint/error text and the ARIA wiring
14
+ * (`id`, `aria-invalid`, `aria-describedby`) any Schumann.ui control reads
15
+ * automatically via context. */
16
+ export declare function FormField({ label, hint, error, required, id, className, children, }: FormFieldProps): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ /** Subconjunto padrão de ícones para escolha (sobrescreva via prop `icons` —
2
+ * com `import '@schumann/ui/icons'` + `getIconNames()` vira o set Lucide inteiro). */
3
+ export declare const DEFAULT_PICKER_ICONS: string[];
4
+ export interface IconPickerProps {
5
+ value: string;
6
+ onChange: (name: string) => void;
7
+ /** Cor de destaque do ícone selecionado. */
8
+ color: string;
9
+ icons?: string[];
10
+ /** Busca por nome. Padrão: automática quando há mais de 40 ícones. */
11
+ searchable?: boolean;
12
+ searchPlaceholder?: string;
13
+ emptyText?: string;
14
+ className?: string;
15
+ }
16
+ /** Grade de ícones selecionáveis, com busca embutida para sets grandes. */
17
+ export declare function IconPicker({ value, onChange, color, icons, searchable, searchPlaceholder, emptyText, className, }: IconPickerProps): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ export interface MoneyInputProps {
2
+ /** Valor decimal como string ('' ou '123.45'). */
3
+ value: string;
4
+ onChange: (value: string) => void;
5
+ /** Prefixo de moeda exibido dentro do campo. */
6
+ currency?: string;
7
+ placeholder?: string;
8
+ disabled?: boolean;
9
+ invalid?: boolean;
10
+ }
11
+ /** Campo monetário com máscara "digit-shift" (digita centavos, o valor desloca). */
12
+ export declare function MoneyInput({ value, onChange, currency, placeholder, disabled, invalid, }: MoneyInputProps): import("react").JSX.Element;
@@ -0,0 +1,20 @@
1
+ export interface MonthPickerValue {
2
+ year: number;
3
+ /** 1–12 */
4
+ month: number;
5
+ }
6
+ export interface MonthPickerProps {
7
+ value: MonthPickerValue;
8
+ onChange: (value: MonthPickerValue) => void;
9
+ /** 12 nomes completos — default pt-BR. O grid usa as 3 primeiras letras ("Jan"). */
10
+ monthLabels?: string[];
11
+ /** Formato do label da pill — default "Mês Ano" (ex.: Julho 2026). */
12
+ formatLabel?: (value: MonthPickerValue) => string;
13
+ prevLabel?: string;
14
+ nextLabel?: string;
15
+ className?: string;
16
+ }
17
+ /** Pill `[📅 Mês Ano | ‹ ›]` com painel 4×3 dos 12 meses e navegação de ano
18
+ * (visual do handoff MonthPicker.html do Schumann design).
19
+ * Selecionado: brand sólido. Mês atual: texto na cor brand. */
20
+ export declare function MonthPicker({ value, onChange, monthLabels, formatLabel, prevLabel, nextLabel, className, }: MonthPickerProps): import("react").JSX.Element;
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from 'react';
2
+ export interface MultiSelectOption {
3
+ value: string;
4
+ label: string;
5
+ sublabel?: string;
6
+ sublabelColor?: string;
7
+ color?: string;
8
+ icon?: ReactNode;
9
+ }
10
+ export interface MultiSelectProps {
11
+ options: MultiSelectOption[];
12
+ selected: string[];
13
+ onChange: (next: string[]) => void;
14
+ placeholder?: string;
15
+ emptyText?: string;
16
+ noResultsText?: string;
17
+ className?: string;
18
+ }
19
+ /** Multi-select pesquisável com chips removíveis. O dropdown usa position:fixed
20
+ * para escapar de containers com overflow (ex.: modais com scroll). */
21
+ export declare function MultiSelect({ options, selected, onChange, placeholder, emptyText, noResultsText, className, }: MultiSelectProps): import("react").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { ReactNode } from 'react';
2
+ export interface SegmentedOption {
3
+ value: string;
4
+ label: ReactNode;
5
+ /** Linha secundária — usada na variante `card`. */
6
+ sublabel?: ReactNode;
7
+ color?: string;
8
+ }
9
+ export interface SegmentedControlProps {
10
+ options: SegmentedOption[];
11
+ value: string;
12
+ onChange: (value: string) => void;
13
+ /** `pill`: linha compacta com dot colorido. `card`: cartões empilhados com sublabel.
14
+ * `tab`: barra de abas (ativo com fill sólido brand, sem dot). */
15
+ variant?: 'pill' | 'card' | 'tab';
16
+ className?: string;
17
+ }
18
+ /** Grupo de opções mutuamente exclusivas (toggle buttons coloridos). */
19
+ export declare function SegmentedControl({ options, value, onChange, variant, className, }: SegmentedControlProps): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import { ReactNode } from 'react';
2
+ export interface StatCardProps {
3
+ /** Rótulo pequeno em maiúsculas. */
4
+ label: ReactNode;
5
+ /** Valor principal (renderizado em fonte mono, tabular). */
6
+ value: ReactNode;
7
+ /** Linha secundária opcional abaixo do valor. */
8
+ sublabel?: ReactNode;
9
+ /** Ícone/adorno à esquerda do label. */
10
+ icon?: ReactNode;
11
+ /** Cor de acento — pinta ícone, label e valor. Default: herda text-primary. */
12
+ accent?: string;
13
+ interactive?: boolean;
14
+ onClick?: () => void;
15
+ className?: string;
16
+ }
17
+ /** Card de métrica: ícone + label + valor mono grande + sublabel. */
18
+ export declare function StatCard({ label, value, sublabel, icon, accent, interactive, onClick, className, }: StatCardProps): import("react").JSX.Element;
@@ -0,0 +1,11 @@
1
+ import { ReactNode } from 'react';
2
+ export interface SwitchCardProps {
3
+ title: ReactNode;
4
+ description?: ReactNode;
5
+ checked: boolean;
6
+ onCheckedChange: (checked: boolean) => void;
7
+ disabled?: boolean;
8
+ className?: string;
9
+ }
10
+ /** Linha de configuração clicável: título + descrição + Switch. */
11
+ export declare function SwitchCard({ title, description, checked, onCheckedChange, disabled, className, }: SwitchCardProps): import("react").JSX.Element;
@@ -0,0 +1,17 @@
1
+ import { ReactNode } from 'react';
2
+ import * as RadixTooltip from '@radix-ui/react-tooltip';
3
+ export interface TooltipProps {
4
+ /** Conteúdo do tooltip. */
5
+ content: ReactNode;
6
+ children: ReactNode;
7
+ side?: 'top' | 'right' | 'bottom' | 'left';
8
+ align?: 'start' | 'center' | 'end';
9
+ /** Atraso até aparecer (ms). Default 200. */
10
+ delayDuration?: number;
11
+ className?: string;
12
+ }
13
+ /** Tooltip acessível (Radix): aparece no hover e no foco por teclado,
14
+ * com ARIA e posicionamento colidido corretos. Envolva o gatilho. */
15
+ export declare function Tooltip({ content, children, side, align, delayDuration, className, }: TooltipProps): import("react").JSX.Element;
16
+ /** Provider — envolva a aplicação uma vez para compartilhar o timing entre tooltips. */
17
+ export declare const TooltipProvider: import('react').FC<RadixTooltip.TooltipProviderProps>;
@@ -0,0 +1,18 @@
1
+ import { HTMLAttributes } from 'react';
2
+ export interface CardProps extends HTMLAttributes<HTMLDivElement> {
3
+ /** Adds a hover lift affordance (use for clickable cards). */
4
+ interactive?: boolean;
5
+ }
6
+ declare function CardRoot({ interactive, className, ...rest }: CardProps): import("react").JSX.Element;
7
+ declare function CardHeader({ className, ...rest }: HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
8
+ declare function CardTitle({ children, className, ...rest }: HTMLAttributes<HTMLHeadingElement>): import("react").JSX.Element;
9
+ declare function CardContent({ className, ...rest }: HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
10
+ declare function CardFooter({ className, ...rest }: HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
11
+ /** Compound card: `<Card><Card.Header><Card.Title/></Card.Header>…</Card>`. */
12
+ export declare const Card: typeof CardRoot & {
13
+ Header: typeof CardHeader;
14
+ Title: typeof CardTitle;
15
+ Content: typeof CardContent;
16
+ Footer: typeof CardFooter;
17
+ };
18
+ export {};
@@ -0,0 +1,19 @@
1
+ import { ReactNode } from 'react';
2
+ import { ButtonVariant } from '../../atoms/Button/Button';
3
+ export interface ConfirmModalProps {
4
+ open: boolean;
5
+ onOpenChange: (open: boolean) => void;
6
+ title: ReactNode;
7
+ message: ReactNode;
8
+ confirmLabel?: string;
9
+ cancelLabel?: string;
10
+ busyLabel?: string;
11
+ confirmVariant?: ButtonVariant;
12
+ icon?: ReactNode;
13
+ /** Pode lançar/rejeitar: o erro é exibido no modal e ele permanece aberto. */
14
+ onConfirm: () => void | Promise<void>;
15
+ /** Converte o erro lançado em mensagem amigável (mapa de erros fica no app). */
16
+ formatError?: (error: unknown) => ReactNode;
17
+ }
18
+ /** Diálogo de confirmação com estado de espera e exibição de erro embutidos. */
19
+ export declare function ConfirmModal({ open, onOpenChange, title, message, confirmLabel, cancelLabel, busyLabel, confirmVariant, icon, onConfirm, formatError, }: ConfirmModalProps): import("react").JSX.Element;
@@ -0,0 +1,41 @@
1
+ import { ReactNode } from 'react';
2
+ export interface DataTableColumn<T> {
3
+ key: string;
4
+ header: string;
5
+ align?: 'left' | 'right';
6
+ width?: number;
7
+ sortable?: boolean;
8
+ sortValue?: (row: T) => string | number | null;
9
+ searchValue?: (row: T) => string;
10
+ render?: (row: T) => ReactNode;
11
+ }
12
+ export interface DataTableLabels {
13
+ pageSizePrefix: string;
14
+ pageSizeItem: (n: number) => string;
15
+ pageSizeSuffix: string;
16
+ selected: (n: number) => string;
17
+ range: (from: number, to: number, total: number) => string;
18
+ }
19
+ export interface DataTableProps<T> {
20
+ columns: DataTableColumn<T>[];
21
+ data: T[];
22
+ keyField?: keyof T;
23
+ searchable?: boolean;
24
+ searchPlaceholder?: string;
25
+ selectable?: boolean;
26
+ initialSelectedIds?: T[keyof T][];
27
+ pageSize?: number;
28
+ pageSizeOptions?: number[] | null;
29
+ onRowClick?: (row: T) => void;
30
+ toolbarTitle?: string;
31
+ toolbarActions?: ReactNode;
32
+ bulkActions?: (selected: Set<T[keyof T]>, clear: () => void) => ReactNode;
33
+ emptyMessage?: string;
34
+ loadingMessage?: string;
35
+ loading?: boolean;
36
+ labels?: Partial<DataTableLabels>;
37
+ className?: string;
38
+ }
39
+ /** Tabela genérica com busca, ordenação, seleção, paginação e ações em lote.
40
+ * Todo o conteúdo das células vem das `columns` (render/props) do app. */
41
+ export declare function DataTable<T>({ columns, data, keyField, searchable, searchPlaceholder, selectable, initialSelectedIds, pageSize: pageSizeProp, pageSizeOptions, onRowClick, toolbarTitle, toolbarActions, bulkActions, emptyMessage, loadingMessage, loading, labels: labelsProp, className, }: DataTableProps<T>): import("react").JSX.Element;
@@ -0,0 +1,24 @@
1
+ import { ReactNode } from 'react';
2
+ export interface MenuItem {
3
+ label?: ReactNode;
4
+ /** Nome do ícone do registro da lib ou um ReactNode custom. */
5
+ icon?: string | ReactNode;
6
+ danger?: boolean;
7
+ onClick?: () => void;
8
+ /** Separador — ignora as demais props. */
9
+ sep?: boolean;
10
+ }
11
+ export interface MenuProps {
12
+ /** Posição fixa na tela (ex.: rect do botão kebab). */
13
+ x: number;
14
+ y: number;
15
+ items: MenuItem[];
16
+ onClose: () => void;
17
+ /** `end` (padrão): o menu abre alinhado à direita do ponto (translateX(-100%)). */
18
+ align?: 'start' | 'end';
19
+ className?: string;
20
+ }
21
+ /** Menu de contexto/kebab ancorado numa posição fixa da tela.
22
+ * Fecha sozinho após clicar num item, com Escape ou clicando fora.
23
+ * Navegável por teclado (setas + Enter). */
24
+ export declare function Menu({ x, y, items, onClose, align, className }: MenuProps): import("react").JSX.Element;
@@ -0,0 +1,30 @@
1
+ import { HTMLAttributes, ReactNode } from 'react';
2
+ import * as Dialog from '@radix-ui/react-dialog';
3
+ export interface ModalProps {
4
+ open?: boolean;
5
+ defaultOpen?: boolean;
6
+ onOpenChange?: (open: boolean) => void;
7
+ children: ReactNode;
8
+ }
9
+ /** Accessible modal dialog built on Radix (focus trap, ESC, scroll lock,
10
+ * aria-modal and labelling handled for you). Controlled or uncontrolled. */
11
+ declare function ModalRoot({ open, defaultOpen, onOpenChange, children }: ModalProps): import("react").JSX.Element;
12
+ export interface ModalContentProps {
13
+ /** Required for accessibility — becomes the dialog's aria-label/title. */
14
+ title: ReactNode;
15
+ description?: ReactNode;
16
+ maxWidth?: number;
17
+ /** Hide the built-in close (×) button. */
18
+ hideClose?: boolean;
19
+ className?: string;
20
+ children?: ReactNode;
21
+ }
22
+ declare function ModalContent({ title, description, maxWidth, hideClose, className, children, }: ModalContentProps): import("react").JSX.Element;
23
+ declare function ModalFooter({ className, ...rest }: HTMLAttributes<HTMLDivElement>): import("react").JSX.Element;
24
+ export declare const Modal: typeof ModalRoot & {
25
+ Trigger: import('react').ForwardRefExoticComponent<Dialog.DialogTriggerProps & import('react').RefAttributes<HTMLButtonElement>>;
26
+ Close: import('react').ForwardRefExoticComponent<Dialog.DialogCloseProps & import('react').RefAttributes<HTMLButtonElement>>;
27
+ Content: typeof ModalContent;
28
+ Footer: typeof ModalFooter;
29
+ };
30
+ export {};
@@ -0,0 +1 @@
1
+ .sui-icon{fill:none;stroke-linecap:round;stroke-linejoin:round;flex-shrink:0}.sui-icon-img{display:block;flex-shrink:0;object-fit:cover}.sui-iconbox{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.sui-spinner{display:inline-block;width:var(--sui-spinner-size, 16px);height:var(--sui-spinner-size, 16px);border:2px solid currentColor;border-right-color:transparent;border-radius:var(--radius-full);animation:sui-spin .6s linear infinite;flex-shrink:0}@keyframes sui-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion: reduce){.sui-spinner{animation-duration:1.5s}}.sui-btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--space-2);border:1px solid transparent;border-radius:var(--radius-md);font-family:var(--font-sans);font-weight:var(--weight-semibold);line-height:1;white-space:nowrap;cursor:pointer;transition:background var(--transition-base),border-color var(--transition-base),color var(--transition-base),opacity var(--transition-base);position:relative}.sui-btn--full{width:100%}.sui-btn:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-btn:disabled{cursor:not-allowed;opacity:.55}.sui-btn__icon{display:inline-flex;flex-shrink:0}.sui-btn[data-size=sm]{height:32px;padding:0 var(--space-3);font-size:var(--text-xs)}.sui-btn[data-size=md]{height:40px;padding:0 var(--space-4);font-size:var(--text-sm)}.sui-btn[data-size=lg]{height:48px;padding:0 var(--space-5);font-size:var(--text-base)}.sui-btn[data-variant=primary]{background:var(--interactive-primary);border-color:var(--interactive-primary);color:var(--interactive-primary-text)}.sui-btn[data-variant=primary]:not(:disabled):hover{background:var(--interactive-primary-hover);border-color:var(--interactive-primary-hover)}.sui-btn[data-variant=secondary]{background:var(--surface-raised);border-color:var(--interactive-outline-border);color:var(--text-primary)}.sui-btn[data-variant=secondary]:not(:disabled):hover{background:var(--interactive-outline-hover)}.sui-btn[data-variant=success]{background:var(--color-green-400);border-color:var(--color-green-400);color:#fff}.sui-btn[data-variant=success]:not(:disabled):hover{filter:brightness(1.08)}.sui-btn[data-variant=danger]{background:var(--color-rose-600);border-color:var(--color-rose-600);color:#fff}.sui-btn[data-variant=danger]:not(:disabled):hover{filter:brightness(1.08)}.sui-btn[data-variant=ghost]{background:transparent;border-color:transparent;color:var(--text-secondary)}.sui-btn[data-variant=ghost]:not(:disabled):hover{background:var(--interactive-outline-hover);color:var(--text-primary)}.sui-iconbtn{display:inline-flex;align-items:center;justify-content:center;border:1px solid transparent;background:transparent;color:var(--text-primary);cursor:pointer;flex-shrink:0;transition:background var(--transition-base),color var(--transition-base)}.sui-iconbtn:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-iconbtn:disabled{cursor:not-allowed;opacity:.5}.sui-iconbtn[data-size=sm]{width:28px;height:28px}.sui-iconbtn[data-size=md]{width:34px;height:34px}.sui-iconbtn[data-size=lg]{width:40px;height:40px}.sui-iconbtn[data-shape=square]{border-radius:var(--radius-lg)}.sui-iconbtn[data-shape=circle]{border-radius:var(--radius-full)}.sui-iconbtn[data-variant=ghost]:not(:disabled):hover{background:var(--interactive-outline-hover)}.sui-iconbtn[data-variant=outline]{border-color:var(--surface-border);background:var(--surface-inset)}.sui-iconbtn[data-variant=outline]:not(:disabled):hover{background:var(--interactive-outline-hover)}.sui-iconbtn[data-variant=primary]{background:var(--interactive-primary);color:var(--interactive-primary-text)}.sui-iconbtn[data-variant=primary]:not(:disabled):hover{background:var(--interactive-primary-hover)}.sui-input{display:flex;align-items:center;width:100%;background:var(--surface-raised);border:1px solid var(--surface-border);border-radius:var(--radius-lg);color:var(--text-primary);transition:border-color var(--transition-base),box-shadow var(--transition-base)}.sui-input:focus-within{border-color:var(--interactive-primary);box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-input[data-invalid]{border-color:var(--color-rose-400)}.sui-input[data-invalid]:focus-within{box-shadow:0 0 0 3px var(--status-error-bd)}.sui-input[data-disabled]{opacity:.6;cursor:not-allowed}.sui-input__control{flex:1;min-width:0;width:100%;border:none;outline:none;background:transparent;color:inherit;font-family:var(--font-sans)}.sui-input__control::placeholder{color:var(--text-muted)}.sui-input__control:disabled{cursor:not-allowed}.sui-input__addon{display:inline-flex;align-items:center;color:var(--text-secondary);flex-shrink:0}.sui-input[data-size=sm]{min-height:36px;padding:0 var(--space-3);font-size:var(--text-xs)}.sui-input[data-size=md]{min-height:44px;padding:0 var(--space-3);font-size:var(--text-sm)}.sui-input[data-size=lg]{min-height:48px;padding:0 var(--space-4);font-size:var(--text-base)}.sui-input__control{padding:var(--space-2-5) var(--space-1)}.sui-input__addon--left{padding-right:var(--space-2)}.sui-input__addon--right{padding-left:var(--space-2)}.sui-text{font-family:var(--font-sans);margin:0}.sui-text--mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums}.sui-text--truncate{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sui-text[data-size=xs]{font-size:var(--text-xs);line-height:1.4}.sui-text[data-size=sm]{font-size:var(--text-sm);line-height:1.45}.sui-text[data-size=base]{font-size:var(--text-base);line-height:1.5}.sui-text[data-size=lg]{font-size:var(--text-lg);line-height:1.5}.sui-text[data-size=xl]{font-size:var(--text-xl);line-height:1.5}.sui-text[data-weight=regular]{font-weight:var(--weight-regular)}.sui-text[data-weight=medium]{font-weight:var(--weight-medium)}.sui-text[data-weight=semibold]{font-weight:var(--weight-semibold)}.sui-text[data-weight=bold]{font-weight:var(--weight-bold)}.sui-text[data-tone=primary]{color:var(--text-primary)}.sui-text[data-tone=secondary]{color:var(--text-secondary)}.sui-text[data-tone=muted]{color:var(--text-muted)}.sui-text[data-tone=brand]{color:var(--text-brand)}.sui-text[data-tone=success]{color:var(--text-success)}.sui-text[data-tone=error]{color:var(--text-error)}.sui-text[data-tone=warning]{color:var(--text-warning)}.sui-text[data-align=start]{text-align:left}.sui-text[data-align=center]{text-align:center}.sui-text[data-align=end]{text-align:right}.sui-heading{font-family:var(--font-sans);color:var(--text-primary);margin:0;letter-spacing:var(--tracking-tight)}.sui-heading[data-level="1"]{font-size:var(--text-title-md);font-weight:var(--weight-extrabold);line-height:1.15}.sui-heading[data-level="2"]{font-size:var(--text-title-sm);font-weight:var(--weight-bold);line-height:1.2}.sui-heading[data-level="3"]{font-size:var(--text-xl);font-weight:var(--weight-bold);line-height:1.3}.sui-heading[data-level="4"]{font-size:var(--text-lg);font-weight:var(--weight-semibold);line-height:1.35}.sui-label{display:inline-flex;align-items:center;gap:var(--space-1);font-family:var(--font-sans);font-size:var(--text-xs);font-weight:var(--weight-semibold);color:var(--text-primary)}.sui-label__required{color:var(--text-error)}.sui-badge{display:inline-flex;align-items:center;gap:var(--space-1-5);border:1px solid transparent;border-radius:var(--radius-full);font-family:var(--font-sans);font-weight:var(--weight-bold);white-space:nowrap;line-height:1}.sui-badge__dot{width:6px;height:6px;border-radius:var(--radius-full);background:currentColor;flex-shrink:0}.sui-badge__icon{display:inline-flex;flex-shrink:0}.sui-badge[data-size=sm]{padding:2px var(--space-2);font-size:11px}.sui-badge[data-size=md]{padding:3px var(--space-2-5);font-size:var(--text-xs)}.sui-badge[data-status=neutral]{background:var(--status-neutral-bg);color:var(--status-neutral-fg);border-color:var(--surface-border)}.sui-badge[data-status=brand]{background:#5961f729;color:var(--text-brand);border-color:#5961f74d}.sui-badge[data-status=success]{background:var(--status-success-bg);color:var(--status-success-fg);border-color:var(--status-success-bd)}.sui-badge[data-status=error]{background:var(--status-error-bg);color:var(--status-error-fg);border-color:var(--status-error-bd)}.sui-badge[data-status=warning]{background:var(--status-warning-bg);color:var(--status-warning-fg);border-color:var(--status-warning-bd)}.sui-badge[data-status=info]{background:var(--status-info-bg);color:var(--status-info-fg);border-color:var(--status-info-bd)}.sui-avatar{display:flex;align-items:center;justify-content:center;border-radius:var(--radius-full);overflow:hidden;flex-shrink:0;background:var(--color-brand-500);color:#fff;font-weight:var(--weight-bold);-webkit-user-select:none;user-select:none}.sui-avatar img{width:100%;height:100%;object-fit:cover}.sui-switch{position:relative;display:inline-block;width:44px;height:24px;border-radius:var(--radius-full);background:var(--surface-raised);border:1px solid var(--surface-border);transition:background var(--transition-base);flex-shrink:0;cursor:pointer;padding:0}.sui-switch[data-checked]{background:var(--color-brand-500);border-color:var(--color-brand-500)}.sui-switch:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-switch:disabled{opacity:.5;cursor:not-allowed}.sui-switch__thumb{position:absolute;top:1px;left:1px;width:20px;height:20px;border-radius:var(--radius-full);background:var(--text-muted);transition:left var(--transition-base),background var(--transition-base)}.sui-switch[data-checked] .sui-switch__thumb{left:21px;background:#fff}.sui-skeleton{display:block;background:linear-gradient(90deg,#ffffff0a 25%,#ffffff17 37%,#ffffff0a 63%);background-size:900px 100%;animation:sui-shimmer 1.5s infinite}:root[data-theme=light] .sui-skeleton{background:linear-gradient(90deg,#0000000d 25%,#0000001a 37%,#0000000d 63%);background-size:900px 100%}@keyframes sui-shimmer{0%{background-position:-450px 0}to{background-position:450px 0}}@media (prefers-reduced-motion: reduce){.sui-skeleton{animation:none}}.sui-progressbar{width:100%;border-radius:var(--radius-full);background:var(--surface-inset);overflow:hidden}.sui-progressbar__fill{height:100%;border-radius:inherit;transition:width .3s ease}@media (prefers-reduced-motion: reduce){.sui-progressbar__fill{transition:none}}.sui-formfield{display:flex;flex-direction:column;gap:var(--space-1-5);width:100%}.sui-combobox{position:relative;width:100%}.sui-combobox__trigger{width:100%;min-height:44px;padding:var(--space-2-5) var(--space-8) var(--space-2-5) var(--space-3);border-radius:var(--radius-lg);border:1px solid var(--surface-border);background:var(--surface-raised);color:var(--text-primary);font-size:var(--text-sm);display:flex;align-items:center;gap:var(--space-2);cursor:text;position:relative;transition:border-color var(--transition-base),box-shadow var(--transition-base)}.sui-combobox__trigger:focus-visible,.sui-combobox__trigger:focus-within{outline:none;border-color:var(--interactive-primary);box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-combobox__trigger[data-disabled]{opacity:.72;cursor:not-allowed}.sui-combobox__trigger[data-invalid]{border-color:var(--color-rose-400)}.sui-combobox__leading{display:inline-flex;flex-shrink:0}.sui-combobox__value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sui-combobox__value--empty{color:var(--text-secondary)}.sui-combobox__search{flex:1;min-width:0;border:none;outline:none;background:transparent;color:var(--text-primary);font-size:var(--text-sm);font-family:var(--font-sans);padding:0}.sui-combobox__chev{position:absolute;right:var(--space-3);top:50%;transform:translateY(-50%);pointer-events:none;color:var(--text-secondary);display:inline-flex}.sui-combobox__backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:calc(var(--z-dropdown) - 1)}.sui-combobox__list{position:absolute;top:calc(100% + 6px);left:0;right:0;z-index:var(--z-dropdown);max-height:230px;overflow-y:auto;background:var(--surface-overlay);border:1px solid var(--surface-border);border-radius:var(--radius-xl);box-shadow:var(--shadow-lg);padding:var(--space-1-5);display:flex;flex-direction:column;gap:2px}.sui-combobox__empty{padding:var(--space-2-5);font-size:var(--text-xs);color:var(--text-secondary);text-align:center}.sui-combobox__option{display:flex;align-items:center;gap:var(--space-2-5);width:100%;padding:var(--space-2) var(--space-2);border-radius:var(--radius-lg);border:none;cursor:pointer;font-size:var(--text-sm);font-weight:var(--weight-semibold);font-family:var(--font-sans);background:transparent;color:var(--text-primary);text-align:left}.sui-combobox__option[data-selected]{background:#5961f724}.sui-combobox__option[data-highlight]{box-shadow:inset 0 0 0 1px var(--color-brand-500)}.sui-combobox__option[data-highlight]:not([data-selected]){background:var(--interactive-outline-hover)}.sui-combobox__option-label{flex:1;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sui-multiselect{position:relative;width:100%}.sui-multiselect__trigger{width:100%;min-height:44px;padding:7px var(--space-3);border-radius:var(--radius-lg);border:1px solid var(--surface-border);background:var(--surface-raised);color:var(--text-primary);display:flex;align-items:center;gap:var(--space-2);cursor:text;transition:border-color var(--transition-base),box-shadow var(--transition-base)}.sui-multiselect__trigger:focus-visible,.sui-multiselect__trigger:focus-within{outline:none;border-color:var(--interactive-primary);box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-multiselect__trigger[data-invalid]{border-color:var(--color-rose-400)}.sui-multiselect__chips{flex:1;min-width:0;display:flex;flex-wrap:wrap;gap:var(--space-1-5);align-items:center;min-height:24px}.sui-multiselect__chip{display:inline-flex;align-items:center;gap:var(--space-1-5);padding:3px var(--space-2);border-radius:7px;font-size:.76rem;font-weight:var(--weight-semibold)}.sui-multiselect__chip-x{background:none;border:none;color:inherit;cursor:pointer;font-size:.95rem;line-height:1;padding:0;opacity:.75}.sui-multiselect__dot{width:7px;height:7px;border-radius:var(--radius-full);flex-shrink:0}.sui-multiselect__dot--lg{width:9px;height:9px}.sui-multiselect__search{flex:1 0 60px;min-width:60px;border:none;outline:none;background:transparent;color:var(--text-primary);font-size:var(--text-sm);font-family:var(--font-sans);padding:0}.sui-multiselect__chev{color:var(--text-secondary);flex-shrink:0;display:inline-flex}.sui-multiselect__backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:calc(var(--z-dropdown) - 1)}.sui-multiselect__list{position:fixed;z-index:var(--z-dropdown);max-height:320px;overflow-y:auto;background:var(--surface-overlay);border:1px solid var(--surface-border);border-radius:var(--radius-xl);box-shadow:var(--shadow-lg);padding:var(--space-1-5);display:flex;flex-direction:column;gap:2px}.sui-multiselect__empty{padding:var(--space-2-5);font-size:var(--text-xs);color:var(--text-secondary);text-align:center}.sui-multiselect__option{display:flex;align-items:center;gap:var(--space-2-5);width:100%;padding:var(--space-2) var(--space-2);border-radius:var(--radius-lg);border:none;cursor:pointer;font-size:var(--text-sm);font-weight:var(--weight-semibold);font-family:var(--font-sans);background:transparent;color:var(--text-primary);text-align:left}.sui-multiselect__option[data-checked]{background:#5961f724}.sui-multiselect__option[data-highlight]{box-shadow:inset 0 0 0 1px var(--color-brand-500)}.sui-multiselect__option[data-highlight]:not([data-checked]){background:var(--interactive-outline-hover)}.sui-multiselect__check{width:18px;height:18px;border-radius:5px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--surface-border);background:transparent}.sui-multiselect__option-text{flex:1;min-width:0;overflow:hidden}.sui-multiselect__option-label{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sui-multiselect__option-sub{display:block;font-size:.72rem;font-weight:var(--weight-semibold);color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sui-segmented{display:flex;gap:var(--space-1)}.sui-segmented[data-variant=pill]{padding:var(--space-1);min-height:44px;box-sizing:border-box;border-radius:var(--radius-xl);border:1px solid var(--surface-border);background:var(--surface-raised)}.sui-segmented[data-variant=card]{gap:var(--space-2)}.sui-segmented[data-variant=tab]{display:inline-flex;gap:2px;padding:2px;border-radius:var(--radius-lg);border:1px solid var(--surface-border);background:var(--status-neutral-bg)}.sui-segmented__option{flex:1 1 0;min-width:0;display:inline-flex;align-items:center;justify-content:center;gap:7px;border:none;cursor:pointer;white-space:nowrap;font-family:var(--font-sans);font-size:.8rem;font-weight:var(--weight-semibold);color:var(--text-secondary);background:transparent;transition:background var(--transition-fast),color var(--transition-fast)}.sui-segmented__option:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-segmented[data-variant=pill] .sui-segmented__option{padding:7px var(--space-2-5);border-radius:7px}.sui-segmented[data-variant=card] .sui-segmented__option{flex-direction:column;gap:2px;padding:var(--space-2-5) var(--space-1-5);border-radius:var(--radius-xl);border:1px solid var(--surface-border);background:var(--surface-inset);text-align:center}.sui-segmented[data-variant=card] .sui-segmented__option[data-on]{color:var(--text-primary)}.sui-segmented[data-variant=tab] .sui-segmented__option{flex:0 0 auto;padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);font-size:.82rem}.sui-segmented[data-variant=tab] .sui-segmented__option[data-on]{background:var(--interactive-primary);color:var(--interactive-primary-text)}.sui-segmented[data-variant=tab] .sui-segmented__option:not([data-on]):hover{color:var(--text-primary)}.sui-segmented__dot{width:7px;height:7px;border-radius:var(--radius-full);flex-shrink:0}.sui-segmented__label{overflow:hidden;text-overflow:ellipsis}.sui-segmented__sublabel{font-size:.7rem;font-weight:var(--weight-bold);color:var(--text-muted)}.sui-switchcard{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3-5);padding:var(--space-3-5) var(--space-4);border-radius:var(--radius-xl);border:1px solid var(--surface-border);background:var(--surface-inset);cursor:pointer}.sui-switchcard[data-disabled]{opacity:.6;cursor:not-allowed}.sui-switchcard__text{flex:1;min-width:0}.sui-switchcard__title{font-size:.9rem;font-weight:var(--weight-semibold);color:var(--text-primary)}.sui-switchcard__desc{font-size:.76rem;color:var(--text-secondary);line-height:1.5;margin-top:3px}.sui-moneyinput .sui-input__control{font-family:var(--font-mono);font-variant-numeric:tabular-nums}.sui-moneyinput__currency{font-size:.82rem;font-family:var(--font-mono)}.sui-monthpicker{position:relative;display:inline-block}.sui-monthpicker__bar{display:inline-flex;align-items:center;gap:var(--space-1);background:var(--surface-raised);border:1px solid var(--surface-border);border-radius:var(--radius-full);padding:6px 6px 6px 8px}.sui-monthpicker__label{display:flex;align-items:center;gap:var(--space-2);background:transparent;border:none;padding:6px 8px;border-radius:var(--radius-full);color:var(--text-primary);font-family:var(--font-sans);font-size:var(--text-sm);font-weight:var(--weight-semibold);white-space:nowrap;cursor:pointer;transition:background var(--transition-fast)}.sui-monthpicker__label:hover{background:var(--surface-overlay)}.sui-monthpicker__label:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-monthpicker__label-text{position:relative;display:inline-block;padding:0 2px;font-variant-numeric:tabular-nums}.sui-monthpicker__label-ghost{visibility:hidden;display:block}.sui-monthpicker__label-value{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;align-items:center;justify-content:center;white-space:nowrap}.sui-monthpicker__divider{width:1px;height:18px;background:var(--surface-border);flex-shrink:0}.sui-monthpicker__step{display:flex;align-items:center;justify-content:center;width:28px;height:28px;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-secondary);cursor:pointer;flex-shrink:0;transition:background var(--transition-fast),color var(--transition-fast)}.sui-monthpicker__step:hover{background:var(--surface-overlay);color:var(--text-primary)}.sui-monthpicker__step:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-monthpicker__backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:calc(var(--z-dropdown) - 1)}.sui-monthpicker__panel{position:absolute;top:calc(100% + 8px);left:0;z-index:var(--z-dropdown);width:272px;padding:var(--space-5);background:var(--surface-overlay);border:1px solid var(--surface-border);border-radius:var(--radius-2xl);box-shadow:var(--shadow-lg);animation:sui-monthpicker-pop .14s ease}@keyframes sui-monthpicker-pop{0%{opacity:0;transform:translateY(-4px) scale(.98)}to{opacity:1;transform:none}}@media (prefers-reduced-motion: reduce){.sui-monthpicker__panel{animation:none}}.sui-monthpicker__yearbar{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-4)}.sui-monthpicker__step--year{width:30px;height:30px}.sui-monthpicker__step--year:hover{background:var(--surface-raised)}.sui-monthpicker__year{font-family:var(--font-mono);font-size:var(--text-lg);font-weight:var(--weight-extrabold);letter-spacing:var(--tracking-tight);color:var(--text-primary);font-variant-numeric:tabular-nums}.sui-monthpicker__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-2)}.sui-monthpicker__month{height:44px;display:flex;align-items:center;justify-content:center;border:none;border-radius:var(--radius-lg);background:transparent;color:var(--text-secondary);font-family:var(--font-sans);font-size:var(--text-sm);font-weight:var(--weight-medium);cursor:pointer;transition:background .15s ease,color .15s ease}.sui-monthpicker__month:hover{background:var(--surface-raised)}.sui-monthpicker__month:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-monthpicker__month[data-current]{color:var(--text-brand)}.sui-monthpicker__month[data-selected]{background:var(--interactive-primary);color:#fff;font-weight:var(--weight-bold)}.sui-monthpicker__month[data-selected]:hover{background:var(--interactive-primary-hover)}.sui-colorpicker{display:flex;flex-direction:column;gap:var(--space-3);width:100%}.sui-colorpicker__swatches{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3)}.sui-colorpicker__swatch{width:34px;height:34px;border-radius:var(--radius-full);padding:0;cursor:pointer;border:none;flex-shrink:0;display:flex;align-items:center;justify-content:center;transition:box-shadow .15s ease,transform .15s ease}.sui-colorpicker__swatch:hover{transform:scale(1.1)}.sui-colorpicker__swatch:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)!important}.sui-colorpicker__wheel{width:34px;height:34px;border-radius:var(--radius-full);padding:0;cursor:pointer;border:none;flex-shrink:0;display:flex;align-items:center;justify-content:center;background:conic-gradient(from 0deg,#f7547a,#f59e0b,#facc15,#15b887,#38bdf8,#3b5cf5,#8b5cf6,#ec4899,#f7547a);transition:box-shadow .15s ease,transform .15s ease}.sui-colorpicker__wheel:hover{transform:scale(1.1)}.sui-colorpicker__wheel:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)!important}.sui-colorpicker__wheel-center{width:22px;height:22px;border-radius:var(--radius-full);display:flex;align-items:center;justify-content:center;transition:background .15s ease}.sui-colorpicker__panel{background:var(--surface-raised);border:1px solid var(--surface-border);border-radius:var(--radius-lg);padding:var(--space-4);display:flex;flex-direction:column;gap:var(--space-4)}.sui-colorpicker__sv{position:relative;width:100%;height:168px;border-radius:10px;cursor:crosshair;touch-action:none;box-shadow:inset 0 0 0 1px #ffffff14}.sui-colorpicker__hue{position:relative;width:100%;height:12px;border-radius:var(--radius-full);cursor:pointer;touch-action:none;background:linear-gradient(to right,red,#ff0 17%,#0f0 33%,#0ff,#00f 67%,#f0f 83%,red);box-shadow:inset 0 0 0 1px #ffffff1a}.sui-colorpicker__knob{position:absolute;width:20px;height:20px;margin:-10px 0 0 -10px;border-radius:var(--radius-full);border:3px solid #fff;box-shadow:0 2px 6px #00000080,0 0 0 1px #0000004d;pointer-events:none}.sui-colorpicker__inputrow{display:flex;align-items:center;gap:var(--space-3)}.sui-colorpicker__preview{width:44px;height:44px;border-radius:var(--radius-lg);flex-shrink:0;transition:box-shadow .2s ease}.sui-colorpicker__field{flex:1;min-width:0;display:flex;align-items:center;background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--radius-md);padding:0 var(--space-3);height:40px;transition:border-color var(--transition-base)}.sui-colorpicker__field:focus-within{border-color:var(--interactive-primary)}.sui-colorpicker__prefix{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--text-muted);-webkit-user-select:none;user-select:none}.sui-colorpicker__hexinput{flex:1;min-width:0;border:none;outline:none;background:transparent;color:var(--text-primary);font-size:var(--text-sm);font-family:var(--font-mono);padding:0 0 0 2px;letter-spacing:.02em}.sui-colorpicker__rgbfields{flex:1;display:flex;align-items:center;justify-content:space-between}.sui-colorpicker__rgbfield-wrap{display:flex;align-items:center;gap:var(--space-1)}.sui-colorpicker__rgbinput{width:34px;border:none;outline:none;background:transparent;color:var(--text-primary);font-size:var(--text-sm);font-family:var(--font-mono);text-align:center;padding:0}.sui-colorpicker__rgbsep{color:var(--text-muted);font-family:var(--font-mono);font-size:var(--text-sm);-webkit-user-select:none;user-select:none}.sui-colorpicker__modetoggle{display:flex;align-items:center;gap:2px;background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--radius-md);padding:3px;height:40px;box-sizing:border-box;flex-shrink:0}.sui-colorpicker__modetab{border:none;cursor:pointer;font-family:var(--font-mono);font-size:10px;font-weight:var(--weight-bold);letter-spacing:.08em;padding:0 10px;height:100%;border-radius:calc(var(--radius-md) - 3px);background:transparent;color:var(--text-muted);transition:background .15s ease,color .15s ease}.sui-colorpicker__modetab[data-active]{background:var(--surface-overlay);color:var(--text-primary)}.sui-colorpicker__modetab:focus-visible{outline:none;box-shadow:0 0 0 2px var(--interactive-focus-ring)}.sui-iconpicker{display:flex;flex-direction:column;gap:var(--space-2-5)}.sui-iconpicker__search{width:100%;min-height:38px;padding:var(--space-2) var(--space-3);border-radius:var(--radius-lg);border:1px solid var(--surface-border);background:var(--surface-raised);color:var(--text-primary);font-family:var(--font-sans);font-size:var(--text-sm);outline:none;transition:border-color var(--transition-base),box-shadow var(--transition-base)}.sui-iconpicker__search:focus-visible{border-color:var(--interactive-primary);box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-iconpicker__search::placeholder{color:var(--text-muted)}.sui-iconpicker__grid{display:flex;flex-wrap:wrap;gap:var(--space-2)}.sui-iconpicker__grid[data-scroll]{max-height:320px;overflow-y:auto;padding-right:var(--space-1)}.sui-iconpicker__empty{width:100%;padding:var(--space-4);text-align:center;font-size:var(--text-xs);color:var(--text-secondary)}.sui-iconpicker__cell{width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border-radius:var(--radius-2xl);cursor:pointer;flex-shrink:0;background:var(--surface-inset);border:1px solid var(--surface-border);transition:background var(--transition-fast);padding:0}.sui-iconpicker__cell:hover:not([data-on]){background:var(--interactive-outline-hover)}.sui-iconpicker__cell:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-statcard{background:var(--surface-inset);border:1px solid var(--surface-divider);border-radius:var(--radius-xl);padding:var(--space-3-5) var(--space-4)}.sui-statcard--interactive{cursor:pointer;transition:transform var(--transition-fast),border-color var(--transition-fast)}.sui-statcard--interactive:hover{transform:translateY(-1px);border-color:var(--surface-border)}.sui-statcard--interactive:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-statcard__head{display:flex;align-items:center;gap:7px;margin-bottom:9px;color:var(--sui-stat-accent, var(--text-secondary))}.sui-statcard__icon{display:inline-flex;flex-shrink:0}.sui-statcard__label{font-size:.72rem;font-weight:var(--weight-bold);text-transform:uppercase;letter-spacing:.07em}.sui-statcard__value{font-family:var(--font-mono);font-size:1.4rem;font-weight:var(--weight-bold);letter-spacing:-.02em;font-variant-numeric:tabular-nums;line-height:1;margin-bottom:5px;color:var(--sui-stat-accent, var(--text-primary))}.sui-statcard__sub{font-size:.74rem;color:var(--text-secondary)}.sui-emptystate{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:var(--space-2);padding:var(--space-10) var(--space-5)}.sui-emptystate--dashed{border:1.5px dashed var(--surface-border);border-radius:var(--radius-xl);background:var(--surface-inset)}.sui-emptystate__icon{display:inline-flex;color:var(--text-muted);margin-bottom:var(--space-1)}.sui-emptystate__title{font-size:var(--text-sm);font-weight:var(--weight-semibold);color:var(--text-primary)}.sui-emptystate__desc{font-size:var(--text-xs);color:var(--text-secondary);line-height:1.5;max-width:340px}.sui-emptystate__actions{display:flex;align-items:center;gap:var(--space-2);margin-top:var(--space-3)}.sui-tooltip{max-width:260px;padding:var(--space-2) var(--space-2-5);background:var(--surface-overlay);border:1px solid var(--surface-border);border-radius:var(--radius-md);box-shadow:var(--shadow-lg);color:var(--text-primary);font-family:var(--font-sans);font-size:var(--text-xs);line-height:1.4;z-index:var(--z-toast);animation:sui-tooltip-in .12s ease}.sui-tooltip__arrow{fill:var(--surface-overlay)}@keyframes sui-tooltip-in{0%{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}@media (prefers-reduced-motion: reduce){.sui-tooltip{animation:none}}.sui-card{background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--radius-card);box-shadow:var(--shadow-md);overflow:hidden}.sui-card--interactive{cursor:pointer;transition:transform var(--transition-fast),border-color var(--transition-fast)}.sui-card--interactive:hover{transform:translateY(-1px);border-color:var(--interactive-outline-border)}.sui-card__header{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-5) var(--space-6);border-bottom:1px solid var(--surface-divider)}.sui-card__title{margin:0}.sui-card__content{padding:var(--space-6)}.sui-card__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-4) var(--space-6);border-top:1px solid var(--surface-divider)}.sui-modal__overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:var(--z-overlay);animation:sui-modal-fade .15s ease}.sui-modal__content{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:calc(100vw - var(--space-8));max-height:92vh;overflow-y:auto;background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--radius-card);box-shadow:var(--shadow-xl);z-index:var(--z-modal);animation:sui-modal-pop .16s ease}.sui-modal__content:focus{outline:none}.sui-modal__header{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-3);padding:var(--space-5) var(--space-6) var(--space-4);border-bottom:1px solid var(--surface-divider)}.sui-modal__title{margin:0;font-family:var(--font-sans);font-size:var(--text-lg);font-weight:var(--weight-bold);color:var(--text-primary)}.sui-modal__desc{margin:var(--space-1) 0 0;font-size:var(--text-sm);color:var(--text-secondary)}.sui-modal__close{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;border-radius:var(--radius-lg);background:transparent;color:var(--text-secondary);cursor:pointer;flex-shrink:0;transition:background var(--transition-base),color var(--transition-base)}.sui-modal__close:hover{background:var(--interactive-outline-hover);color:var(--text-primary)}.sui-modal__close:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-modal__body{padding:var(--space-6)}.sui-modal__footer{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-4) var(--space-6);border-top:1px solid var(--surface-divider)}@keyframes sui-modal-fade{0%{opacity:0}to{opacity:1}}@keyframes sui-modal-pop{0%{opacity:0;transform:translate(-50%,-48%) scale(.98)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}@media (prefers-reduced-motion: reduce){.sui-modal__overlay,.sui-modal__content{animation:none}}.sui-confirm__overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000b3;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:var(--z-overlay)}.sui-confirm{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:calc(100vw - var(--space-8));max-width:400px;background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--radius-card);box-shadow:var(--shadow-xl);padding:var(--space-6);z-index:var(--z-modal)}.sui-confirm:focus{outline:none}.sui-confirm__head{display:flex;align-items:flex-start;gap:var(--space-3-5)}.sui-confirm__title{margin:0 0 5px;font-size:1.1rem;font-weight:var(--weight-bold);color:var(--text-primary);font-family:var(--font-sans)}.sui-confirm__message{margin:0;font-size:.86rem;color:var(--text-secondary);line-height:1.5}.sui-confirm__error{margin-top:var(--space-3-5);font-size:var(--text-xs);color:var(--status-error-fg);background:var(--status-error-bg);border:1px solid var(--status-error-bd);border-radius:var(--radius-lg);padding:9px var(--space-3)}.sui-confirm__actions{display:flex;gap:var(--space-2-5);margin-top:var(--space-5)}.sui-menu__backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:calc(var(--z-dropdown) - 1)}.sui-menu{position:fixed;z-index:var(--z-dropdown);min-width:210px;max-height:60vh;overflow-y:auto;padding:var(--space-1-5);background:var(--surface-overlay);border:1px solid var(--surface-border);border-radius:var(--radius-xl);box-shadow:var(--shadow-xl);display:flex;flex-direction:column;gap:2px}.sui-menu__sep{height:1px;background:var(--surface-divider);margin:5px 0}.sui-menu__item{display:flex;align-items:center;gap:var(--space-2-5);width:100%;padding:9px 13px;background:transparent;border:none;border-radius:var(--radius-lg);text-align:left;font-size:var(--text-sm);font-weight:var(--weight-medium);font-family:var(--font-sans);cursor:pointer;color:var(--text-primary)}.sui-menu__item:hover,.sui-menu__item:focus-visible{background:var(--interactive-outline-hover)}.sui-menu__item[data-danger]{color:var(--status-error-fg)}.sui-menu__item[data-danger]:hover,.sui-menu__item[data-danger]:focus-visible{background:var(--status-error-bg)}.sui-menu__item:focus-visible{outline:none;box-shadow:inset 0 0 0 1px var(--color-brand-500)}.sui-datatable{background:var(--surface-card);border:1px solid var(--surface-border);border-radius:var(--radius-card);overflow:hidden;font-family:var(--font-sans)}.sui-datatable__toolbar{display:flex;align-items:center;gap:var(--space-3);flex-wrap:wrap;padding:var(--space-3-5) var(--space-4);border-bottom:1px solid var(--surface-divider)}.sui-datatable__title{margin:0 4px 0 0;font-size:var(--text-base);font-weight:var(--weight-semibold);color:var(--text-primary)}.sui-datatable__pagesize{display:flex;align-items:center;gap:var(--space-2);font-size:13px;color:var(--text-secondary)}.sui-datatable__pagesize-btn{display:inline-flex;align-items:center;gap:var(--space-1-5);background:var(--surface-inset);color:var(--text-primary);border:1px solid var(--surface-border);border-radius:var(--radius-md);padding:6px 8px 6px 11px;font-size:13px;font-family:var(--font-sans);font-weight:var(--weight-semibold);cursor:pointer}.sui-datatable__search{display:flex;align-items:center;gap:var(--space-2);height:34px;padding:0 var(--space-3);border-radius:var(--radius-full);border:1px solid var(--surface-border);background:var(--surface-inset);min-width:180px;flex:0 1 240px;transition:border-color var(--transition-base),box-shadow var(--transition-base)}.sui-datatable__search:focus-within{border-color:var(--interactive-primary);box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-datatable__search input{border:none;background:transparent;outline:none;color:var(--text-primary);font-family:var(--font-sans);font-size:13px;width:100%}.sui-datatable__actions{margin-left:auto;display:flex;gap:var(--space-2);align-items:center}.sui-datatable__bulkbar{display:flex;align-items:center;gap:var(--space-3);padding:9px var(--space-4);background:var(--status-info-bg);border-bottom:1px solid var(--surface-divider)}.sui-datatable__bulkcount{font-size:13px;font-weight:var(--weight-semibold);color:var(--text-primary)}.sui-datatable__bulkactions{margin-left:auto;display:flex;gap:var(--space-2)}.sui-datatable__scroll{overflow-x:auto}.sui-datatable table{width:100%;border-collapse:collapse}.sui-datatable thead{border-bottom:1px solid var(--surface-divider)}.sui-datatable__th{text-align:left;padding:11px var(--space-4);font-size:var(--text-xs);font-weight:var(--weight-semibold);letter-spacing:.04em;text-transform:uppercase;color:var(--text-secondary);white-space:nowrap;-webkit-user-select:none;user-select:none}.sui-datatable__th[data-align=right]{text-align:right}.sui-datatable__th[data-sortable]{cursor:pointer}.sui-datatable__th--check{width:40px}.sui-datatable__th-inner{display:inline-flex;align-items:center;gap:var(--space-1)}.sui-datatable__sort{font-size:9px;color:var(--text-muted);opacity:.5}.sui-datatable__sort[data-active]{color:var(--text-brand);opacity:1}.sui-datatable__row{border-bottom:1px solid var(--surface-divider);transition:background var(--transition-fast)}.sui-datatable__row[data-clickable]{cursor:pointer}.sui-datatable__row:hover{background:#ffffff06}.sui-datatable__row[data-selected]{background:#5961f71a}.sui-datatable__row[data-selected]:hover{background:#5961f729}:root[data-theme=light] .sui-datatable__row:hover{background:#00000005}.sui-datatable__td{padding:var(--space-2) var(--space-4);font-size:var(--text-sm);color:var(--text-primary);white-space:nowrap}.sui-datatable__td[data-align=right]{text-align:right}.sui-datatable input[type=checkbox]{accent-color:var(--color-brand-500);cursor:pointer}.sui-datatable__empty{padding:var(--space-12) var(--space-4);text-align:center;color:var(--text-muted);font-size:13px}.sui-datatable__footer{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:11px var(--space-4);border-top:1px solid var(--surface-divider)}.sui-datatable__range{font-size:var(--text-xs);color:var(--text-secondary)}.sui-datatable__pager{display:flex;align-items:center;gap:var(--space-1-5)}.sui-datatable__pager button{width:28px;height:28px;border-radius:var(--radius-md);border:1px solid var(--surface-border);background:transparent;color:var(--text-primary);cursor:pointer}.sui-datatable__pager button:disabled{cursor:not-allowed;opacity:.4}.sui-datatable__pageinfo{font-size:var(--text-xs);color:var(--text-secondary);padding:0 var(--space-1-5);font-variant-numeric:tabular-nums}.sui-page{width:100%;max-width:var(--sui-page-max, 1280px);margin:0 auto;padding:var(--space-6) var(--space-8) var(--space-16)}@media (max-width: 640px){.sui-page{padding:var(--space-5) var(--space-4) var(--space-12)}}.sui-appshell{display:grid;grid-template-columns:220px 1fr;grid-template-rows:56px 1fr;grid-template-areas:"topbar topbar" "sidebar content";width:100%;height:100vh;overflow:hidden;background:var(--surface-bg)}.sui-appshell[data-collapsed]{grid-template-columns:66px 1fr}.sui-appshell[data-mobile]{grid-template-columns:1fr;grid-template-areas:"topbar" "content"}.sui-appshell__topbar{grid-area:topbar;display:flex;align-items:center;gap:var(--space-3);height:56px;padding:0 var(--space-3-5);background:var(--surface-topbar);border-bottom:1px solid var(--surface-border);z-index:30;position:relative}.sui-appshell__topbar-start{display:flex;align-items:center;gap:var(--space-3);flex:1;min-width:0}.sui-appshell__logo{display:flex;align-items:center;-webkit-user-select:none;user-select:none}.sui-appshell__topbar-center{display:flex;align-items:center;gap:var(--space-2-5);flex-shrink:0}.sui-appshell__topbar-end{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2-5);flex:1;min-width:0}.sui-appshell__sidebar{grid-area:sidebar;display:flex;flex-direction:column;overflow:hidden;background:var(--surface-sidebar);border-right:1px solid var(--surface-border);padding:var(--space-4) var(--space-3)}.sui-appshell[data-mobile] .sui-appshell__sidebar{position:fixed;left:0;top:56px;bottom:0;width:250px;z-index:25;transform:translate(-102%);transition:transform var(--transition-base)}.sui-appshell[data-mobile] .sui-appshell__sidebar[data-open]{transform:none;box-shadow:var(--shadow-xl)}.sui-appshell__search{display:flex;align-items:center;gap:var(--space-2);height:36px;padding:0 var(--space-2-5);margin-bottom:var(--space-3-5);border:1px solid var(--surface-border);border-radius:10px;background:var(--surface-inset);flex-shrink:0;transition:border-color var(--transition-base),box-shadow var(--transition-base)}.sui-appshell__search:focus-within{border-color:var(--interactive-primary);box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-appshell__search input{flex:1;min-width:0;border:none;outline:none;background:transparent;color:var(--text-primary);font-family:var(--font-sans);font-size:13px}.sui-appshell__search input::placeholder{color:var(--text-muted)}.sui-appshell__nav{flex:1;overflow-y:auto;overflow-x:hidden}.sui-appshell__navgroup{margin-bottom:var(--space-4)}.sui-appshell__navlabel{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--text-secondary);margin:0 0 var(--space-1-5) 9px;font-weight:var(--weight-bold);white-space:nowrap}.sui-appshell__navitem{display:flex;align-items:center;gap:11px;justify-content:flex-start;padding:var(--space-2) 11px;width:100%;border-radius:9px;cursor:pointer;color:var(--text-secondary);text-align:left;font-size:13.5px;font-weight:var(--weight-medium);font-family:var(--font-sans);border:none;background:transparent;white-space:nowrap;margin-bottom:2px;transition:background var(--transition-fast),color var(--transition-fast)}.sui-appshell__navitem[data-icon-only]{gap:0;justify-content:center;padding:9px 0}.sui-appshell__navitem:hover:not([data-active]){background:var(--interactive-outline-hover);color:var(--text-primary)}.sui-appshell__navitem[data-active]{color:var(--text-primary);font-weight:var(--weight-semibold);background:#5961f724}.sui-appshell__navitem:focus-visible{outline:none;box-shadow:0 0 0 3px var(--interactive-focus-ring)}.sui-appshell__navicon{display:inline-flex;flex-shrink:0}.sui-appshell__sidebar-footer{border-top:1px solid var(--surface-divider);padding-top:var(--space-2-5);margin-top:var(--space-1-5)}.sui-appshell__content{grid-area:content;overflow-y:auto}.sui-appshell__scrim{position:fixed;top:56px;right:0;bottom:0;left:0;background:#0000008c;z-index:20}.sui-pageheader{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--space-4);flex-wrap:wrap;margin-bottom:var(--space-5)}.sui-pageheader__text{min-width:0}.sui-pageheader__eyebrow{display:block;font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--text-secondary);font-weight:var(--weight-bold);margin-bottom:var(--space-1-5)}.sui-pageheader__title{font-size:2rem;font-weight:var(--weight-extrabold);letter-spacing:-.03em;line-height:1;margin:0;color:var(--text-primary)}.sui-pageheader__desc{margin:var(--space-2) 0 0;font-size:var(--text-sm);color:var(--text-secondary);line-height:1.5}.sui-pageheader__actions{display:flex;align-items:center;gap:var(--space-2-5);flex-shrink:0}:root{--color-brand-25: #f4f5ff;--color-brand-50: #eceefe;--color-brand-100: #dcdffe;--color-brand-200: #bcc0fc;--color-brand-300: #969cfa;--color-brand-400: #7c82f9;--color-brand-500: #5961f7;--color-brand-600: #4850e0;--color-brand-700: #3a41c4;--color-brand-800: #2f35a0;--color-brand-900: #2a3080;--color-brand-950: #191c4d;--color-green-25: #f0fdf9;--color-green-50: #dcfcef;--color-green-100: #b9f7de;--color-green-200: #85edc6;--color-green-300: #4fdcab;--color-green-400: #15803d;--color-green-500: #166534;--color-green-600: #14532d;--color-green-700: #0f3d21;--color-green-800: #0b2d18;--color-green-900: #06210f;--color-rose-25: #fff5f7;--color-rose-50: #ffe9ee;--color-rose-100: #ffd3dc;--color-rose-200: #feacbd;--color-rose-300: #fc7f99;--color-rose-400: #e11d48;--color-rose-500: #c81e1e;--color-rose-600: #b91c1c;--color-rose-700: #991b1b;--color-rose-800: #7f1d1d;--color-rose-900: #661010;--color-warning-50: #fffaeb;--color-warning-100: #fef0c7;--color-warning-300: #fec84b;--color-warning-400: #fdb022;--color-warning-500: #f59e0b;--color-warning-600: #d97706;--color-warning-700: #b45309;--color-info-50: #ecf9ff;--color-info-100: #d5f1ff;--color-info-300: #7ad4fb;--color-info-400: #38bdf8;--color-info-500: #0ea5e9;--color-info-600: #0284c7;--color-info-700: #0369a1;--color-gray-25: #fbfbfb;--color-gray-50: #f6f6f7;--color-gray-100: #ececee;--color-gray-200: #d5d6da;--color-gray-300: #b1b3ba;--color-gray-400: #8a8d96;--color-gray-500: #676a73;--color-gray-600: #4b4d55;--color-gray-700: #33353b;--color-gray-800: #232323;--color-gray-900: #1c1c1c;--color-gray-950: #161616;--space-0: 0px;--space-0-5: 2px;--space-1: 4px;--space-1-5: 6px;--space-2: 8px;--space-2-5: 10px;--space-3: 12px;--space-3-5: 14px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-7: 28px;--space-8: 32px;--space-10: 40px;--space-12: 48px;--space-16: 64px;--radius-sm: 4px;--radius-md: 6px;--radius-lg: 8px;--radius-xl: 12px;--radius-2xl: 16px;--radius-card: 18px;--radius-full: 9999px;--font-sans: "Roboto", system-ui, -apple-system, sans-serif;--font-mono: "JetBrains Mono", "Fira Code", "Cascadia Code", "Consolas", monospace;--text-title-lg: 48px;--text-title-md: 36px;--text-title-sm: 30px;--text-xl: 20px;--text-lg: 18px;--text-base: 16px;--text-sm: 14px;--text-xs: 12px;--weight-regular: 400;--weight-medium: 500;--weight-semibold: 600;--weight-bold: 700;--weight-extrabold: 800;--tracking-tight: -.02em;--tracking-wide: .02em;--tracking-widest: .1em;--z-overlay: 1100;--z-modal: 1200;--z-dropdown: 1250;--z-toast: 1300;--transition-fast: .12s ease;--transition-base: .2s ease-in-out}:root,:root[data-theme=dark]{--surface-bg: #181818;--surface-sidebar: #161616;--surface-topbar: #1f1f1f;--surface-card: #1c1c1c;--surface-raised: #232323;--surface-overlay: #262626;--surface-inset: rgba(255, 255, 255, .04);--surface-border: rgba(255, 255, 255, .1);--surface-divider: rgba(255, 255, 255, .06);--text-primary: rgba(255, 255, 255, .87);--text-secondary: rgba(255, 255, 255, .55);--text-muted: rgba(255, 255, 255, .4);--text-inverse: #181818;--text-brand: #7c82f9;--text-success: #4fdcab;--text-error: #fca5a5;--text-warning: #f59e0b;--text-info: #38bdf8;--interactive-primary: #5961f7;--interactive-primary-hover: #4850e0;--interactive-primary-text: #ffffff;--interactive-outline-border: rgba(255, 255, 255, .14);--interactive-outline-hover: rgba(255, 255, 255, .06);--interactive-focus-ring: rgba(89, 97, 247, .35);--status-success-bg: rgba(10, 114, 2, .16);--status-success-fg: #4fdcab;--status-success-bd: rgba(10, 114, 2, .3);--status-error-bg: rgba(247, 84, 122, .16);--status-error-fg: #fca5a5;--status-error-bd: rgba(247, 84, 122, .28);--status-warning-bg: rgba(245, 158, 11, .16);--status-warning-fg: #fcd34d;--status-warning-bd: rgba(250, 204, 21, .28);--status-info-bg: rgba(37, 99, 235, .18);--status-info-fg: #9fc1ff;--status-info-bd: rgba(96, 165, 250, .36);--status-neutral-bg: rgba(255, 255, 255, .06);--status-neutral-fg: rgba(255, 255, 255, .55);--shadow-sm: 0px 1px 3px 0px rgba(0, 0, 0, .25), 0px 1px 2px 0px rgba(0, 0, 0, .15);--shadow-md: 0px 4px 8px -2px rgba(0, 0, 0, .3), 0px 2px 4px -2px rgba(0, 0, 0, .2);--shadow-lg: 0px 12px 16px -4px rgba(0, 0, 0, .35), 0px 4px 6px -2px rgba(0, 0, 0, .15);--shadow-xl: 0px 20px 24px -4px rgba(0, 0, 0, .4), 0px 8px 8px -4px rgba(0, 0, 0, .2);--scrollbar-thumb: rgba(255, 255, 255, .12);--scrollbar-thumb-hover: rgba(255, 255, 255, .2)}:root[data-theme=light]{--surface-bg: #f6f6f7;--surface-sidebar: #ffffff;--surface-topbar: #ffffff;--surface-card: #ffffff;--surface-raised: #ffffff;--surface-overlay: #ffffff;--surface-inset: rgba(0, 0, 0, .03);--surface-border: rgba(0, 0, 0, .12);--surface-divider: rgba(0, 0, 0, .08);--text-primary: rgba(20, 20, 22, .92);--text-secondary: rgba(20, 20, 22, .6);--text-muted: rgba(20, 20, 22, .42);--text-inverse: #ffffff;--text-brand: #4850e0;--text-success: #166534;--text-error: #b91c1c;--text-warning: #b45309;--text-info: #0369a1;--interactive-primary: #5961f7;--interactive-primary-hover: #4850e0;--interactive-primary-text: #ffffff;--interactive-outline-border: rgba(0, 0, 0, .14);--interactive-outline-hover: rgba(0, 0, 0, .04);--interactive-focus-ring: rgba(89, 97, 247, .3);--status-success-bg: rgba(22, 101, 52, .12);--status-success-fg: #166534;--status-success-bd: rgba(22, 101, 52, .24);--status-error-bg: rgba(185, 28, 28, .1);--status-error-fg: #b91c1c;--status-error-bd: rgba(185, 28, 28, .24);--status-warning-bg: rgba(245, 158, 11, .14);--status-warning-fg: #b45309;--status-warning-bd: rgba(245, 158, 11, .3);--status-info-bg: rgba(14, 165, 233, .12);--status-info-fg: #0369a1;--status-info-bd: rgba(14, 165, 233, .3);--status-neutral-bg: rgba(0, 0, 0, .05);--status-neutral-fg: rgba(20, 20, 22, .6);--shadow-sm: 0px 1px 3px 0px rgba(0, 0, 0, .08), 0px 1px 2px 0px rgba(0, 0, 0, .06);--shadow-md: 0px 4px 8px -2px rgba(0, 0, 0, .1), 0px 2px 4px -2px rgba(0, 0, 0, .06);--shadow-lg: 0px 12px 16px -4px rgba(0, 0, 0, .12), 0px 4px 6px -2px rgba(0, 0, 0, .06);--shadow-xl: 0px 20px 24px -4px rgba(0, 0, 0, .14), 0px 8px 8px -4px rgba(0, 0, 0, .08);--scrollbar-thumb: rgba(0, 0, 0, .2);--scrollbar-thumb-hover: rgba(0, 0, 0, .32)}*,*:before,*:after{box-sizing:border-box}.sui-root,[data-sui-theme]{font-family:var(--font-sans);color:var(--text-primary)}button,input,select,textarea{font-family:inherit;font-size:100%}*{scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) transparent}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:var(--radius-full)}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}
@@ -0,0 +1,38 @@
1
+ import { ReactNode } from 'react';
2
+ export interface AppShellNavItem {
3
+ key: string;
4
+ label: ReactNode;
5
+ icon?: ReactNode;
6
+ active?: boolean;
7
+ onSelect?: () => void;
8
+ }
9
+ export interface AppShellNavGroup {
10
+ label?: ReactNode;
11
+ items: AppShellNavItem[];
12
+ }
13
+ export interface AppShellProps {
14
+ /** Grupos de navegação da sidebar — dados e callbacks vêm do app (sem router). */
15
+ nav: AppShellNavGroup[];
16
+ /** Logo/branding no topbar, ao lado do hambúrguer. */
17
+ logo?: ReactNode;
18
+ /** Slot central do topbar (busca, month-picker…). */
19
+ topbarCenter?: ReactNode;
20
+ /** Slot direito do topbar (ações, avatar…). */
21
+ topbarEnd?: ReactNode;
22
+ /** Rodapé da sidebar (ex.: botão sair). */
23
+ sidebarFooter?: ReactNode;
24
+ /** Campo de busca no topo da sidebar que filtra os itens de nav pelo label. */
25
+ searchable?: boolean;
26
+ searchPlaceholder?: string;
27
+ collapsed?: boolean;
28
+ defaultCollapsed?: boolean;
29
+ onCollapsedChange?: (collapsed: boolean) => void;
30
+ /** Abaixo desta largura a sidebar vira drawer. */
31
+ mobileBreakpoint?: number;
32
+ menuButtonLabel?: string;
33
+ children: ReactNode;
34
+ className?: string;
35
+ }
36
+ /** Layout de aplicação: topbar + sidebar retrátil + área de conteúdo.
37
+ * Apenas estrutura — navegação, dados e ações são fornecidos pelo app. */
38
+ export declare function AppShell({ nav, logo, topbarCenter, topbarEnd, sidebarFooter, searchable, searchPlaceholder, collapsed, defaultCollapsed, onCollapsedChange, mobileBreakpoint, menuButtonLabel, children, className, }: AppShellProps): import("react").JSX.Element;
@@ -0,0 +1,7 @@
1
+ import { HTMLAttributes } from 'react';
2
+ export interface PageContainerProps extends HTMLAttributes<HTMLDivElement> {
3
+ /** Max content width in px. Defaults to 1280. */
4
+ maxWidth?: number;
5
+ }
6
+ /** Centered, padded page wrapper. Layout only — no navigation or business chrome. */
7
+ export declare function PageContainer({ maxWidth, className, style, ...rest }: PageContainerProps): import("react").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ export interface PageHeaderProps {
3
+ /** Linha superior pequena em maiúsculas (categoria/seção). */
4
+ eyebrow?: ReactNode;
5
+ title: ReactNode;
6
+ /** Descrição opcional abaixo do título. */
7
+ description?: ReactNode;
8
+ /** Slot de ações à direita (botões, view toggles…). */
9
+ actions?: ReactNode;
10
+ className?: string;
11
+ }
12
+ /** Cabeçalho de página: eyebrow + título grande + ações à direita.
13
+ * Layout puro — o conteúdo (textos, botões) vem do app. */
14
+ export declare function PageHeader({ eyebrow, title, description, actions, className }: PageHeaderProps): import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ /** hex color + alpha → rgba() string */
2
+ export declare function hexA(hex: string, a: number): string;
3
+ export declare function hexToRgb(hex: string): [number, number, number];
4
+ export declare function rgbToHex(r: number, g: number, b: number): string;
5
+ export declare function rgbToHsv(r: number, g: number, b: number): {
6
+ h: number;
7
+ s: number;
8
+ v: number;
9
+ };
10
+ export declare function hsvToRgb(h: number, s: number, v: number): [number, number, number];
@@ -0,0 +1,3 @@
1
+ export type ClassValue = string | number | false | null | undefined;
2
+ /** Join truthy class names. Tiny local helper — no `clsx` dependency needed. */
3
+ export declare function cx(...values: ClassValue[]): string;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Um ancestral com `transform`, `filter`, `perspective`, `contain` ou `will-change`
3
+ * vira o *containing block* de descendentes `position: fixed` — o fixed deixa de ser
4
+ * relativo à viewport e passa a ser relativo a esse ancestral.
5
+ *
6
+ * Não é teórico: o Storybook aplica `transform` no wrapper de zoom das páginas de
7
+ * Docs (mesmo com matriz identidade), o que deslocava dropdowns posicionados por
8
+ * `getBoundingClientRect()` — que devolve coordenadas de viewport.
9
+ */
10
+ export declare function getFixedContainingBlock(el: HTMLElement | null): HTMLElement | null;
11
+ /**
12
+ * Offset a subtrair de coordenadas de viewport (`getBoundingClientRect`) para
13
+ * posicionar corretamente um elemento `position: fixed` que esteja dentro de um
14
+ * containing block. Zero quando o fixed é realmente relativo à viewport.
15
+ */
16
+ export declare function getFixedOffset(el: HTMLElement | null): {
17
+ top: number;
18
+ left: number;
19
+ };
@@ -0,0 +1,2 @@
1
+ /** Accent-insensitive lowercase, for client-side search/filtering. */
2
+ export declare function normalizeSearch(s: string): string;