@scinverse/ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/dist/components/Badge/Badge.d.ts +16 -0
- package/dist/components/Badge/index.d.ts +1 -0
- package/dist/components/Button/Button.d.ts +19 -0
- package/dist/components/Button/index.d.ts +1 -0
- package/dist/components/Card/Card.d.ts +17 -0
- package/dist/components/Card/index.d.ts +1 -0
- package/dist/components/Checkbox/Checkbox.d.ts +15 -0
- package/dist/components/Checkbox/index.d.ts +1 -0
- package/dist/components/Dropdown/Dropdown.d.ts +46 -0
- package/dist/components/Dropdown/index.d.ts +1 -0
- package/dist/components/Filter/Filter.d.ts +22 -0
- package/dist/components/Filter/filterModel.d.ts +68 -0
- package/dist/components/Filter/index.d.ts +2 -0
- package/dist/components/Input/FieldCaption.d.ts +9 -0
- package/dist/components/Input/Input.d.ts +16 -0
- package/dist/components/Input/SearchBar.d.ts +15 -0
- package/dist/components/Input/TextArea.d.ts +13 -0
- package/dist/components/Input/index.d.ts +3 -0
- package/dist/components/Panel/Panel.d.ts +6 -0
- package/dist/components/Panel/index.d.ts +1 -0
- package/dist/components/RadioGroup/Radio.d.ts +13 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +19 -0
- package/dist/components/RadioGroup/RadioGroupContext.d.ts +11 -0
- package/dist/components/RadioGroup/index.d.ts +2 -0
- package/dist/components/Switcher/Switcher.d.ts +16 -0
- package/dist/components/Switcher/index.d.ts +1 -0
- package/dist/components/Tip/Tip.d.ts +21 -0
- package/dist/components/Tip/index.d.ts +1 -0
- package/dist/icons/SvgIcon.d.ts +38 -0
- package/dist/icons/branding.d.ts +20 -0
- package/dist/icons/buttonIcons.d.ts +32 -0
- package/dist/icons/createSvgIcon.d.ts +10 -0
- package/dist/icons/flagIcons.d.ts +20 -0
- package/dist/icons/index.d.ts +7 -0
- package/dist/icons/labels.d.ts +4 -0
- package/dist/icons/railIcons.d.ts +16 -0
- package/dist/index.cjs +200 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +1605 -0
- package/dist/index.js.map +1 -0
- package/dist/placeFixedMenu.d.ts +10 -0
- package/dist/styles.cjs +0 -0
- package/dist/styles.css +2 -0
- package/dist/styles.js +0 -0
- package/dist/svg/flags/de.svg +1 -0
- package/dist/svg/flags/en.svg +23 -0
- package/dist/svg/flags/es.svg +1 -0
- package/dist/svg/flags/fr.svg +1 -0
- package/dist/svg/flags/it.svg +1 -0
- package/dist/svg/flags/nl.svg +1 -0
- package/dist/svg/flags/pt.svg +1 -0
- package/dist/svg/flags/ru.svg +1 -0
- package/dist/svg/flags/zh.svg +15 -0
- package/dist/svg/marks/nc-icon.svg +9 -0
- package/dist/svg/marks/nc-scinverse-icon.svg +34 -0
- package/dist/svg/marks/ohs-icon.svg +3 -0
- package/dist/svg/marks/ohs-scinverse-icon.svg +37 -0
- package/dist/svg/marks/scinverse-avatar.svg +13 -0
- package/dist/svg/marks/scinverse-icon.svg +20 -0
- package/dist/svg/marks/scinverse-logo.svg +4 -0
- package/dist/svg/marks/ui-kit-icon.svg +6 -0
- package/dist/svg/marks/ui-kit-scinverse-icon.svg +34 -0
- package/dist/svg/set/arrow-drop-down.svg +3 -0
- package/dist/svg/set/arrow-drop-up.svg +3 -0
- package/dist/svg/set/bell.svg +4 -0
- package/dist/svg/set/check.svg +3 -0
- package/dist/svg/set/chevron-down.svg +3 -0
- package/dist/svg/set/close.svg +3 -0
- package/dist/svg/set/exchange.svg +6 -0
- package/dist/svg/set/eye-slash.svg +3 -0
- package/dist/svg/set/eye.svg +3 -0
- package/dist/svg/set/help.svg +5 -0
- package/dist/svg/set/integration.svg +5 -0
- package/dist/svg/set/loading.svg +11 -0
- package/dist/svg/set/logout.svg +5 -0
- package/dist/svg/set/messages.svg +4 -0
- package/dist/svg/set/moon.svg +6 -0
- package/dist/svg/set/news.svg +3 -0
- package/dist/svg/set/pencil.svg +4 -0
- package/dist/svg/set/plus.svg +3 -0
- package/dist/svg/set/power.svg +3 -0
- package/dist/svg/set/refresh.svg +3 -0
- package/dist/svg/set/search.svg +3 -0
- package/dist/svg/set/settings.svg +4 -0
- package/dist/svg/set/sun.svg +4 -0
- package/dist/svg/set/system.svg +5 -0
- package/dist/svg/set/user.svg +4 -0
- package/dist/theme/ThemeProvider.d.ts +15 -0
- package/package.json +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/theme/ThemeProvider.tsx","../src/icons/SvgIcon.tsx","../src/components/Button/Button.module.css","../src/components/Button/Button.tsx","../src/components/Panel/Panel.module.css","../src/components/Panel/Panel.tsx","../src/components/Card/Card.module.css","../src/components/Card/Card.tsx","../src/components/Badge/Badge.module.css","../src/components/Badge/Badge.tsx","../src/icons/createSvgIcon.tsx","../src/icons/buttonIcons.tsx","../src/components/Checkbox/Checkbox.module.css","../src/components/Checkbox/Checkbox.tsx","../src/components/Tip/Tip.module.css","../src/components/Tip/Tip.tsx","../src/components/RadioGroup/RadioGroupContext.ts","../src/components/RadioGroup/Radio.module.css","../src/components/RadioGroup/Radio.tsx","../src/components/RadioGroup/RadioGroup.module.css","../src/components/RadioGroup/RadioGroup.tsx","../src/components/Input/Input.module.css","../src/components/Input/FieldCaption.tsx","../src/components/Input/Input.tsx","../src/components/Input/SearchBar.module.css","../src/components/Input/SearchBar.tsx","../src/components/Input/TextArea.tsx","../src/components/Switcher/Switcher.module.css","../src/components/Switcher/Switcher.tsx","../src/placeFixedMenu.ts","../src/components/Dropdown/Dropdown.module.css","../src/components/Dropdown/Dropdown.tsx","../src/components/Filter/filterModel.ts","../src/components/Filter/Filter.module.css","../src/components/Filter/Filter.tsx","../src/icons/branding.tsx","../src/icons/flagIcons.tsx","../src/icons/railIcons.tsx","../src/icons/labels.tsx"],"sourcesContent":["import {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\n\nexport type Theme = 'dark' | 'light';\n\nconst THEME_KEY = 'scinverse-ui:theme';\n\ninterface ThemeContextValue {\n theme: Theme;\n setTheme: (theme: Theme) => void;\n toggleTheme: () => void;\n}\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\nfunction readStoredTheme(): Theme {\n try {\n const raw = localStorage.getItem(THEME_KEY);\n if (raw === 'light' || raw === 'dark') return raw;\n } catch {\n /* ignore */\n }\n return 'dark';\n}\n\nfunction applyTheme(theme: Theme, root: HTMLElement) {\n root.dataset.theme = theme;\n try {\n localStorage.setItem(THEME_KEY, theme);\n } catch {\n /* ignore */\n }\n}\n\nexport function ThemeProvider({\n children,\n defaultTheme,\n target = 'document',\n}: {\n children: ReactNode;\n defaultTheme?: Theme;\n /** Apply data-theme on documentElement (default) or a local wrapper. */\n target?: 'document' | 'local';\n}) {\n const [theme, setThemeState] = useState<Theme>(() => defaultTheme ?? readStoredTheme());\n\n const setTheme = useCallback(\n (next: Theme) => {\n setThemeState(next);\n if (target === 'document') applyTheme(next, document.documentElement);\n },\n [target],\n );\n\n const toggleTheme = useCallback(() => {\n setTheme(theme === 'dark' ? 'light' : 'dark');\n }, [setTheme, theme]);\n\n useEffect(() => {\n if (target === 'document') applyTheme(theme, document.documentElement);\n }, [theme, target]);\n\n const value = useMemo(\n () => ({ theme, setTheme, toggleTheme }),\n [theme, setTheme, toggleTheme],\n );\n\n if (target === 'local') {\n return (\n <ThemeContext.Provider value={value}>\n <div className=\"sci-root\" data-theme={theme}>\n {children}\n </div>\n </ThemeContext.Provider>\n );\n }\n\n return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;\n}\n\nexport function useTheme(): ThemeContextValue {\n const ctx = useContext(ThemeContext);\n if (!ctx) throw new Error('useTheme must be used within ThemeProvider');\n return ctx;\n}\n","import type { ElementType, ReactNode, SVGProps } from 'react';\n\n/** Token names only — raw CSS colors go through the `(string & {})` branch. */\nexport type IconColor =\n | 'inherit'\n | 'accent'\n | 'focus'\n | 'success'\n | 'warning'\n | 'error'\n | 'ink'\n | 'text'\n | 'text-secondary'\n | 'muted';\n\nexport type IconSizeToken = 'sm' | 'md' | 'lg';\n\nexport type SvgIconProps = {\n color?: IconColor | (string & {});\n /** Token or px. Omit = md (24). */\n size?: IconSizeToken | number;\n /**\n * Outline stroke thickness → `strokeWidth`.\n * Meaningful for stroke glyphs; ignored by filled marks that do not stroke.\n */\n weight?: number;\n /** Accessible name → `<title>` + role=\"img\". Without it: aria-hidden. */\n title?: string;\n /** Render as another element/component (SVGR mark, custom svg root). */\n component?: ElementType;\n /** Take viewBox from `component` instead of forcing the default. */\n inheritViewBox?: boolean;\n /** Default viewBox when not inheriting. */\n viewBox?: string;\n children?: ReactNode;\n} & Omit<SVGProps<SVGSVGElement>, 'color' | 'width' | 'height'>;\n\n/** Size tokens → px. Numbers pass through. */\nexport const ICON_SIZE_PX = {\n sm: 16,\n md: 24,\n lg: 32,\n} as const satisfies Record<IconSizeToken, number>;\n\n/**\n * Token → CSS color value.\n * `inherit` = no override (currentColor from parent).\n * Raw strings (`#hex`, `rgb()`, `var(...)`) are used as-is.\n */\nexport const ICON_COLOR_CSS: Record<Exclude<IconColor, 'inherit'>, string> = {\n accent: 'var(--sci-color-accent)',\n focus: 'var(--sci-color-border-focus)',\n success: 'var(--sci-color-success)',\n warning: 'var(--sci-color-warning)',\n error: 'var(--sci-color-error)',\n ink: 'var(--sci-color-ink)',\n text: 'var(--sci-color-text)',\n 'text-secondary': 'var(--sci-color-text-secondary)',\n muted: 'var(--sci-color-text-muted)',\n};\n\nconst DEFAULT_VIEWBOX = '0 0 24 24';\n\nexport function resolveIconSize(size?: IconSizeToken | number): number {\n if (typeof size === 'number') return size;\n return ICON_SIZE_PX[size ?? 'md'];\n}\n\nexport function resolveIconColor(color?: IconColor | (string & {})): string | undefined {\n if (!color || color === 'inherit') return undefined;\n if (Object.prototype.hasOwnProperty.call(ICON_COLOR_CSS, color)) {\n return ICON_COLOR_CSS[color as Exclude<IconColor, 'inherit'>];\n }\n return color;\n}\n\nexport function SvgIcon({\n color = 'inherit',\n size,\n weight,\n title,\n component: Component = 'svg',\n inheritViewBox = false,\n viewBox = DEFAULT_VIEWBOX,\n className,\n style,\n strokeWidth,\n children,\n ...rest\n}: SvgIconProps) {\n const px = resolveIconSize(size);\n const cssColor = resolveIconColor(color);\n const boxProps = inheritViewBox ? {} : { viewBox };\n\n return (\n <Component\n {...boxProps}\n width={px}\n height={px}\n strokeWidth={weight ?? strokeWidth}\n className={['sci-SvgIcon', className].filter(Boolean).join(' ')}\n style={{ color: cssColor, ...style }}\n aria-hidden={title ? undefined : true}\n role={title ? 'img' : undefined}\n {...rest}\n >\n {title ? <title>{title}</title> : null}\n {children}\n </Component>\n );\n}\n",".root {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--sci-spacing-sm);\n min-height: 32px;\n padding: 0.4rem 0.85rem;\n border: 1px solid transparent;\n border-radius: var(--sci-radius-sm);\n font-family: var(--sci-font-family);\n font-size: var(--sci-font-size-sm);\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;\n}\n\n.root:focus,\n.root:focus-visible {\n outline: none;\n}\n\n.root:disabled {\n opacity: 0.45;\n cursor: default;\n}\n\n.small {\n min-height: 28px;\n padding: 0.22rem 0.65rem;\n font-size: 0.8125rem;\n}\n\n.large {\n min-height: 40px;\n padding: 0.55rem 1.1rem;\n font-size: 1rem;\n}\n\n.primary {\n background: var(--sci-color-accent);\n border-color: var(--sci-color-accent);\n color: #fff;\n}\n\n.primary:hover:not(:disabled) {\n background: var(--sci-color-accent-hover);\n border-color: var(--sci-color-accent-hover);\n}\n\n.secondary {\n background: var(--sci-color-bg-input);\n border-color: var(--sci-color-border);\n color: var(--sci-color-text);\n}\n\n.secondary:hover:not(:disabled) {\n border-color: var(--sci-color-border-focus);\n background: var(--sci-color-bg-hover);\n}\n\n.ghost {\n background: transparent;\n border-color: var(--sci-color-border);\n color: var(--sci-color-text-secondary);\n}\n\n.ghost:hover:not(:disabled) {\n color: var(--sci-color-text);\n background: var(--sci-color-bg-hover);\n}\n\n/* Header / panel chrome — 30×30 icon control. */\n.panel {\n width: 30px;\n height: 30px;\n min-height: 30px;\n padding: 0;\n font-size: 15px;\n font-weight: 400;\n line-height: 1;\n background: var(--sci-color-bg-input);\n border-color: var(--sci-color-border);\n color: var(--sci-color-text-secondary);\n}\n\n.panel:hover:not(:disabled) {\n border-color: var(--sci-color-border-focus);\n background: var(--sci-color-bg-hover);\n color: var(--sci-color-text);\n}\n\n.panel.small {\n width: 26px;\n height: 26px;\n min-height: 26px;\n padding: 0;\n}\n\n.panel.large {\n width: 36px;\n height: 36px;\n min-height: 36px;\n padding: 0;\n}\n\n/* Token / raw color via --sci-button-color (same tokens as Icon). */\n.colored.primary {\n background: var(--sci-button-color);\n border-color: var(--sci-button-color);\n color: #fff;\n}\n\n.colored.primary:hover:not(:disabled) {\n background: color-mix(in srgb, var(--sci-button-color) 82%, #000);\n border-color: color-mix(in srgb, var(--sci-button-color) 82%, #000);\n}\n\n.colored.secondary {\n color: var(--sci-button-color);\n border-color: var(--sci-button-color);\n}\n\n.colored.secondary:hover:not(:disabled) {\n border-color: var(--sci-button-color);\n background: color-mix(in srgb, var(--sci-button-color) 12%, transparent);\n color: var(--sci-button-color);\n}\n\n.colored.ghost {\n color: var(--sci-button-color);\n}\n\n.colored.ghost:hover:not(:disabled) {\n color: var(--sci-button-color);\n background: color-mix(in srgb, var(--sci-button-color) 12%, transparent);\n}\n\n.colored.panel {\n color: var(--sci-button-color);\n}\n\n.colored.panel:hover:not(:disabled) {\n color: var(--sci-button-color);\n border-color: var(--sci-button-color);\n background: color-mix(in srgb, var(--sci-button-color) 12%, transparent);\n}\n\n/* Recording / view-toggle on — accent wash (OHS RecordingToggle). */\n.toggledAccent,\n.toggledAccent.primary,\n.toggledAccent.secondary,\n.toggledAccent.ghost,\n.toggledAccent.panel,\n.toggledAccent.colored {\n color: var(--sci-color-accent);\n border-color: color-mix(in srgb, var(--sci-color-accent) 55%, transparent);\n background: color-mix(in srgb, var(--sci-color-accent) 14%, transparent);\n}\n\n.toggledAccent:hover:not(:disabled),\n.toggledAccent.primary:hover:not(:disabled),\n.toggledAccent.secondary:hover:not(:disabled),\n.toggledAccent.ghost:hover:not(:disabled),\n.toggledAccent.panel:hover:not(:disabled),\n.toggledAccent.colored:hover:not(:disabled) {\n color: var(--sci-color-accent);\n border-color: color-mix(in srgb, var(--sci-color-accent) 55%, transparent);\n background: color-mix(in srgb, var(--sci-color-accent) 20%, transparent);\n}\n\n.toggledAccent svg {\n filter: drop-shadow(0 0 5px color-mix(in srgb, var(--sci-color-accent) 85%, transparent));\n}\n\n/* R5 on — accent border and ink, dark surface (ConnectionRetryPopover .btnOn). */\n.toggledDark,\n.toggledDark.primary,\n.toggledDark.secondary,\n.toggledDark.ghost,\n.toggledDark.panel,\n.toggledDark.colored {\n color: var(--sci-color-accent);\n border-color: var(--sci-color-accent);\n background: var(--sci-color-bg-input);\n}\n\n.toggledDark:hover:not(:disabled),\n.toggledDark:focus,\n.toggledDark:focus-visible,\n.toggledDark.primary:hover:not(:disabled),\n.toggledDark.secondary:hover:not(:disabled),\n.toggledDark.ghost:hover:not(:disabled),\n.toggledDark.panel:hover:not(:disabled),\n.toggledDark.colored:hover:not(:disabled) {\n color: var(--sci-color-accent);\n border-color: var(--sci-color-accent);\n background: var(--sci-color-bg-input);\n}\n","import type { ButtonHTMLAttributes, CSSProperties, ReactNode } from 'react';\nimport { resolveIconColor, type IconColor } from '../../icons/SvgIcon';\nimport styles from './Button.module.css';\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'panel';\nexport type ButtonSize = 'small' | 'medium' | 'large';\n/** Same token names as SvgIcon `color`. */\nexport type ButtonColor = IconColor;\n/** Pressed look: `true` / `accent` = recording wash; `dark` = R5 fill. */\nexport type ButtonToggled = boolean | 'accent' | 'dark';\n\nexport interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'color'> {\n variant?: ButtonVariant;\n /** Default medium — same footprint as Basic. */\n size?: ButtonSize;\n /** Palette token or raw CSS color. Omit = variant defaults. */\n color?: ButtonColor | (string & {});\n /** Pressed / on. `true` is the accent wash; `dark` is the R5 fill. */\n toggled?: ButtonToggled;\n children?: ReactNode;\n}\n\nfunction toggledOn(toggled: ButtonToggled | undefined): boolean {\n return toggled === true || toggled === 'accent' || toggled === 'dark';\n}\n\nexport function Button({\n variant = 'primary',\n size = 'medium',\n color,\n toggled,\n className,\n type = 'button',\n style,\n children,\n ...rest\n}: ButtonProps) {\n const variantClass =\n variant === 'secondary'\n ? styles.secondary\n : variant === 'ghost'\n ? styles.ghost\n : variant === 'panel'\n ? styles.panel\n : styles.primary;\n const sizeClass = size === 'small' ? styles.small : size === 'large' ? styles.large : null;\n const tint = resolveIconColor(color);\n const tinted = Boolean(tint);\n const pressed = toggledOn(toggled);\n const dark = toggled === 'dark';\n const mergedStyle = (\n tinted ? { ...style, ['--sci-button-color' as string]: tint } : style\n ) as CSSProperties | undefined;\n\n return (\n <button\n type={type}\n className={[\n styles.root,\n variantClass,\n sizeClass,\n tinted ? styles.colored : null,\n pressed ? (dark ? styles.toggledDark : styles.toggledAccent) : null,\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n style={mergedStyle}\n {...rest}\n aria-pressed={rest['aria-pressed'] ?? (toggled !== undefined ? pressed : undefined)}\n >\n {children}\n </button>\n );\n}\n",".root {\n background: var(--sci-color-bg-panel);\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-lg);\n padding: var(--sci-spacing-lg);\n}\n\n.title {\n margin: 0 0 var(--sci-spacing-md);\n color: var(--sci-color-accent);\n font-family: var(--sci-font-family-mono);\n font-size: 0.7rem;\n font-weight: 500;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport styles from './Panel.module.css';\n\nexport interface PanelProps extends HTMLAttributes<HTMLDivElement> {\n title?: string;\n children?: ReactNode;\n}\n\nexport function Panel({ title, children, className, ...rest }: PanelProps) {\n return (\n <div className={[styles.root, className].filter(Boolean).join(' ')} {...rest}>\n {title ? <h3 className={styles.title}>{title}</h3> : null}\n {children}\n </div>\n );\n}\n",".root {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n width: 100%;\n padding: 8px 10px;\n border: 1px solid transparent;\n border-radius: var(--sci-radius-sm);\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n\n.root:hover {\n background: var(--sci-color-bg-hover);\n}\n\n.selected {\n border-color: var(--sci-color-border-focus);\n background: var(--sci-color-bg-hover);\n}\n\n.info {\n display: flex;\n min-width: 0;\n flex-direction: column;\n}\n\n.name {\n font-weight: 600;\n color: var(--sci-color-text);\n}\n\n.kind {\n color: var(--sci-color-text-muted);\n font-size: 11px;\n}\n\n.end {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n}\n\n.dot {\n display: inline-block;\n flex-shrink: 0;\n width: 9px;\n height: 9px;\n border-radius: 50%;\n background: currentColor;\n box-shadow: 0 0 6px currentColor;\n}\n","import type { ButtonHTMLAttributes, ReactNode } from 'react';\nimport { ICON_COLOR_CSS, type IconColor } from '../../icons/SvgIcon';\nimport styles from './Card.module.css';\n\nexport interface CardProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'name'> {\n name: ReactNode;\n kind?: ReactNode;\n selected?: boolean;\n /** Status dot, soon badge, anything. */\n end?: ReactNode;\n}\n\nexport type CardDotTone = Extract<\n IconColor,\n 'accent' | 'success' | 'warning' | 'error' | 'muted'\n>;\n\nexport interface CardDotProps {\n tone?: CardDotTone;\n label?: string;\n}\n\n/** Selectable rail row: name, kind, trailing mark. */\nexport function Card({\n name,\n kind,\n selected = false,\n end,\n className,\n type = 'button',\n ...rest\n}: CardProps) {\n return (\n <button\n type={type}\n className={[styles.root, selected ? styles.selected : '', className].filter(Boolean).join(' ')}\n aria-current={selected ? 'true' : undefined}\n {...rest}\n >\n <span className={styles.info}>\n <span className={styles.name}>{name}</span>\n {kind != null ? <span className={styles.kind}>{kind}</span> : null}\n </span>\n {end != null ? <span className={styles.end}>{end}</span> : null}\n </button>\n );\n}\n\nexport function CardDot({ tone = 'muted', label }: CardDotProps) {\n return (\n <span\n className={styles.dot}\n style={{ color: ICON_COLOR_CSS[tone] }}\n aria-label={label}\n title={label}\n />\n );\n}\n",".root {\n display: inline-flex;\n align-items: center;\n box-sizing: border-box;\n font-family: var(--sci-font-family);\n font-weight: 600;\n letter-spacing: 0.04em;\n line-height: 1.2;\n text-transform: uppercase;\n color: var(--sci-color-text-muted);\n background: var(--sci-color-bg-input);\n white-space: nowrap;\n}\n\n.basic {\n border-radius: var(--sci-radius-sm);\n}\n\n.rounded {\n border-radius: var(--sci-radius-lg);\n}\n\n.small {\n padding: 2px 5px;\n font-size: 9px;\n}\n\n.medium {\n padding: 3px 6px;\n font-size: 10px;\n}\n\n.large {\n padding: 3px 8px;\n font-size: 12px;\n}\n\n.colored {\n color: var(--sci-badge-color);\n background: color-mix(in srgb, var(--sci-badge-color) 16%, var(--sci-color-bg-input));\n}\n","import type { HTMLAttributes, ReactNode } from 'react';\nimport { resolveIconColor, type IconColor } from '../../icons/SvgIcon';\nimport styles from './Badge.module.css';\n\nexport type BadgeSize = 'small' | 'medium' | 'large';\n/** Same token names as SvgIcon `color`. */\nexport type BadgeColor = IconColor;\nexport type BadgeRound = 'rounded' | 'basic' | number;\n\nexport interface BadgeProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'color'> {\n children: ReactNode;\n /** Default medium. */\n size?: BadgeSize;\n /** Palette token or raw CSS. Omit = muted. */\n color?: BadgeColor | (string & {});\n /** `basic` (default) — 4px. `rounded` — 12px. A number is px. */\n round?: BadgeRound;\n}\n\nexport function Badge({\n children,\n size = 'medium',\n color,\n round = 'basic',\n className,\n style,\n ...rest\n}: BadgeProps) {\n const sizeClass = size === 'small' ? styles.small : size === 'large' ? styles.large : styles.medium;\n const tint = resolveIconColor(color);\n const customRound = typeof round === 'number';\n const roundClass = customRound ? '' : round === 'rounded' ? styles.rounded : styles.basic;\n return (\n <span\n className={[styles.root, sizeClass, roundClass, tint ? styles.colored : '', className]\n .filter(Boolean)\n .join(' ')}\n style={{\n ...style,\n ...(tint ? { ['--sci-badge-color' as string]: tint } : {}),\n ...(customRound ? { borderRadius: round } : {}),\n }}\n {...rest}\n >\n {children}\n </span>\n );\n}\n","import type { ReactElement, ReactNode } from 'react';\nimport { SvgIcon, type SvgIconProps } from './SvgIcon';\n\nexport type CreateSvgIconOptions = {\n viewBox?: string;\n /** `stroke` = outline defaults (action glyphs). `fill` = filled path. */\n kind?: 'stroke' | 'fill';\n /** Default outline thickness for `kind: 'stroke'`. Maps to `strokeWidth`. Default 1.7. */\n weight?: number;\n};\n\nexport function createSvgIcon(\n path: ReactNode,\n displayName: string,\n options: CreateSvgIconOptions = {},\n): (props: SvgIconProps) => ReactElement {\n const { viewBox = '0 0 24 24', kind = 'stroke', weight = 1.7 } = options;\n\n function Component(props: SvgIconProps) {\n const kindDefaults =\n kind === 'stroke'\n ? {\n fill: 'none' as const,\n stroke: 'currentColor',\n weight,\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n }\n : { fill: 'currentColor' as const };\n\n return (\n <SvgIcon viewBox={viewBox} {...kindDefaults} {...props}>\n {path}\n </SvgIcon>\n );\n }\n\n Component.displayName = `${displayName}Icon`;\n return Component;\n}\n","import { createSvgIcon } from './createSvgIcon';\n\n/** 16-grid — at `sm` / 16px the bars sit on the pixel grid. Stroke is the kit default 1.7. */\nexport const PlusIcon = createSvgIcon(\n <path d=\"M8 3v10M3 8h10\" />,\n 'Plus',\n { viewBox: '0 0 16 16' },\n);\n\nexport const MinusIcon = createSvgIcon(\n <path d=\"M3 8h10\" />,\n 'Minus',\n { viewBox: '0 0 16 16' },\n);\n\n/** Recording start/stop — OHS power/standby (filled). */\nexport const PowerIcon = createSvgIcon(\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M7.25 7.25a.75.75 0 0 0 1.5 0V.75a.75.75 0 0 0-1.5 0zm4.04 5.157A5.5 5.5 0 1 1 5 3.39a.75.75 0 1 0-.818-1.257a7 7 0 1 0 7.635 0A.75.75 0 0 0 11 3.39a5.5 5.5 0 0 1 .291 9.017Z\"\n />,\n 'Power',\n { kind: 'fill', viewBox: '0 0 16 16' },\n);\n\nexport const CloseIcon = createSvgIcon(<path d=\"M6 6l12 12M18 6L6 18\" />, 'Close');\n\n/** Magnifier — FilterSearch / SearchBar (same path as OHS Console toolbar). */\nexport const SearchIcon = createSvgIcon(\n <path d=\"M7 2a5 5 0 1 1 0 10A5 5 0 0 1 7 2Zm3.5 8.5L14 14\" />,\n 'Search',\n { viewBox: '0 0 16 16', weight: 1.5 },\n);\n\n/** Login form password reveal — Font Awesome `fa-eye`. */\nexport const EyeIcon = createSvgIcon(\n <path d=\"M572.52 241.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400a144 144 0 1 1 144-144 143.93 143.93 0 0 1-144 144zm0-240a95.31 95.31 0 0 0-25.31 3.79 47.85 47.85 0 0 1-66.9 66.9A95.78 95.78 0 1 0 288 160z\" />,\n 'Eye',\n { kind: 'fill', viewBox: '0 0 576 512' },\n);\n\n/** Login form password hide — Font Awesome `fa-eye-slash`. */\nexport const EyeSlashIcon = createSvgIcon(\n <path d=\"M320 400c-75.85 0-137.25-58.71-142.9-133.11L72.2 185.82c-13.79 17.3-26.48 35.59-36.72 55.59a32.35 32.35 0 0 0 0 29.19C89.71 376.41 197.07 448 320 448c26.91 0 52.87-4 77.89-10.46L346 397.39a144.13 144.13 0 0 1-26 2.61zm313.82 58.1l-110.55-85.44a331.25 331.25 0 0 0 81.25-102.07 32.35 32.35 0 0 0 0-29.19C557.29 135.59 449.93 64 320 64a308.15 308.15 0 0 0-147.32 37.7L45.46 3.37A16 16 0 0 0 23 6.18L3.37 31.45A16 16 0 0 0 6.18 53.9l588.36 454.73a16 16 0 0 0 22.46-2.81l19.64-25.27a16 16 0 0 0-2.82-22.45zm-183.72-142l-39.3-30.38A94.75 94.75 0 0 0 416 256a94.76 94.76 0 0 0-121.31-92.21A47.65 47.65 0 0 1 304 192a46.64 46.64 0 0 1-1.54 10l-73.61-56.89A142.31 142.31 0 0 1 320 112a143.92 143.92 0 0 1 144 144c0 21.63-5.29 41.79-13.9 60.11z\" />,\n 'EyeSlash',\n { kind: 'fill', viewBox: '0 0 640 512' },\n);\n\nexport const CheckIcon = createSvgIcon(<path d=\"M5 12.5l4.2 4.2L19 7.5\" />, 'Check');\n\nexport const ChevronDownIcon = createSvgIcon(<path d=\"M6 9l6 6 6-6\" />, 'ChevronDown');\n\n/** Material arrow_drop_down — closed Dropdown caret. */\nexport const ArrowDropDownIcon = createSvgIcon(\n <path d=\"m7 10l5 5l5-5z\" />,\n 'ArrowDropDown',\n { kind: 'fill' },\n);\n\n/** Material arrow_drop_up — open Dropdown caret. */\nexport const ArrowDropUpIcon = createSvgIcon(\n <path d=\"m7 14l5-5l5 5z\" />,\n 'ArrowDropUp',\n { kind: 'fill' },\n);\n\n/** Theme toggle — light side (shown while dark is active). */\nexport const SunIcon = createSvgIcon(\n <>\n <circle cx=\"12\" cy=\"12\" r=\"3.5\" />\n <path d=\"M12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6l1.4 1.4M17 17l1.4 1.4M18.4 5.6L17 7M7 17l-1.4 1.4\" />\n </>,\n 'Sun',\n);\n\n/** Theme toggle — dark side (shown while light is active). */\nexport const MoonIcon = createSvgIcon(\n <g transform=\"translate(256 256) scale(0.875) translate(-256 -256)\">\n <path d=\"M268.279 496c-67.574 0-130.978-26.191-178.534-73.745S16 311.293 16 243.718A252.25 252.25 0 0 1 154.183 18.676a24.44 24.44 0 0 1 34.46 28.958a220.12 220.12 0 0 0 54.8 220.923A218.75 218.75 0 0 0 399.085 333.2a220.2 220.2 0 0 0 65.277-9.846a24.439 24.439 0 0 1 28.959 34.461A252.26 252.26 0 0 1 268.279 496M153.31 55.781A219.3 219.3 0 0 0 48 243.718C48 365.181 146.816 464 268.279 464a219.3 219.3 0 0 0 187.938-105.31a253 253 0 0 1-57.13 6.513a250.54 250.54 0 0 1-178.268-74.016a252.15 252.15 0 0 1-67.509-235.4Z\" />\n </g>,\n 'Moon',\n { kind: 'fill', viewBox: '0 0 512 512' },\n);\n\n/** Header / rail — sign out. */\nexport const LogoutIcon = createSvgIcon(\n <>\n <path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\" />\n <polyline points=\"16 17 21 12 16 7\" />\n <line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\" />\n </>,\n 'Logout',\n);\n\n/** Edit action — same pencil as the console context menu. */\nexport const PencilIcon = createSvgIcon(\n <>\n <path d=\"M12 20h9\" />\n <path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\" />\n </>,\n 'Pencil',\n);\n\n/** Header / rail — system settings gear. */\nexport const SettingsIcon = createSvgIcon(\n <>\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n <path d=\"M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z\" />\n </>,\n 'Settings',\n);\n\n/** Reload / refresh action — two circular arrows. */\nexport const RefreshIcon = createSvgIcon(\n <path d=\"M6.34 6.34c.73-.73 1.59-1.31 2.54-1.71c.99-.42 2.03-.63 3.11-.63V2c-1.35 0-2.66.26-3.89.79c-1.19.5-2.26 1.23-3.18 2.14c-.92.92-1.64 1.99-2.14 3.18c-.52 1.23-.79 2.54-.79 3.89s.26 2.66.79 3.89c.5 1.19 1.22 2.26 2.14 3.18c.17.17.35.32.52.48L2.99 22h6v-6l-2.13 2.13c-.18-.15-.36-.31-.52-.48a8.1 8.1 0 0 1-1.72-2.54c-.42-.99-.63-2.03-.63-3.11s.21-2.13.63-3.11c.4-.95.98-1.81 1.72-2.54Zm12.73-1.41c-.17-.17-.35-.32-.52-.48L21 2h-6v6l2.13-2.13c.18.15.36.31.52.48c.74.74 1.31 1.59 1.72 2.54c.42.99.63 2.03.63 3.11s-.21 2.13-.63 3.11c-.4.95-.98 1.81-1.72 2.54c-.73.73-1.59 1.31-2.54 1.71c-.99.42-2.03.63-3.11.63v2c1.35 0 2.66-.26 3.89-.79c1.19-.5 2.26-1.23 3.18-2.14c.92-.92 1.64-1.99 2.14-3.18c.52-1.23.79-2.54.79-3.89s-.26-2.66-.79-3.89a9.9 9.9 0 0 0-2.14-3.18Z\" />,\n 'Refresh',\n { kind: 'fill' },\n);\n\n/** Indeterminate loading — arc spinner (SMIL). */\nexport const LoadingIcon = createSvgIcon(\n <>\n <path strokeDasharray=\"19\" d=\"M12 2c5.52 0 10 4.48 10 10\">\n <animate fill=\"freeze\" attributeName=\"stroke-dashoffset\" dur=\"0.3s\" values=\"19;0\" />\n <animateTransform\n attributeName=\"transform\"\n dur=\"1.5s\"\n repeatCount=\"indefinite\"\n type=\"rotate\"\n values=\"0 12 12;360 12 12\"\n />\n </path>\n <path\n strokeDasharray=\"63\"\n d=\"M12 2c5.52 0 10 4.48 10 10c0 5.52-4.48 10-10 10c-5.52 0-10-4.48-10-10c0-5.52 4.48-10 10-10Z\"\n opacity={0.3}\n >\n <animate fill=\"freeze\" attributeName=\"stroke-dashoffset\" dur=\"1.2s\" values=\"63;0\" />\n </path>\n </>,\n 'Loading',\n { kind: 'stroke', weight: 2.15 },\n);\n",".root {\n --sci-checkbox-size: 16px;\n --sci-checkbox-mark: 100%;\n display: inline-flex;\n align-items: baseline;\n gap: var(--sci-spacing-sm);\n cursor: pointer;\n user-select: none;\n color: var(--sci-color-text);\n font-size: var(--sci-font-size-sm);\n line-height: 1;\n}\n\n.root:has(.input:disabled) {\n opacity: 0.45;\n cursor: default;\n}\n\n.small {\n --sci-checkbox-size: 14px;\n font-size: 0.8125rem;\n}\n\n.large {\n --sci-checkbox-size: 20px;\n font-size: 1rem;\n}\n\n.input {\n position: absolute;\n opacity: 0;\n width: 1px;\n height: 1px;\n pointer-events: none;\n}\n\n.box {\n position: relative;\n box-sizing: border-box;\n flex-shrink: 0;\n /* Absolute mark stays out of flow — baseline stays the box bottom. */\n width: var(--sci-checkbox-size);\n height: var(--sci-checkbox-size);\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-sm);\n background: var(--sci-color-bg-input);\n transition: border-color 0.12s ease, background 0.12s ease;\n}\n\n.input:focus-visible + .box {\n outline: 2px solid var(--sci-color-border-focus);\n outline-offset: 2px;\n}\n\n.input:checked + .box {\n background: var(--sci-color-accent);\n border-color: var(--sci-color-accent);\n}\n\n.mark {\n position: absolute;\n top: 50%;\n left: 50%;\n width: var(--sci-checkbox-mark) !important;\n height: var(--sci-checkbox-mark) !important;\n color: #fff;\n transform: translate(-50%, -50%);\n visibility: hidden;\n}\n\n.input:checked + .box .mark {\n visibility: visible;\n}\n\n.colored .input:checked + .box {\n background: var(--sci-checkbox-color);\n border-color: var(--sci-checkbox-color);\n}\n\n.label {\n line-height: 1;\n /* Baseline sits on the box bottom; lift so the ink matches the square. */\n translate: 0 -0.12em;\n}\n","import { useEffect, useRef, type CSSProperties, type InputHTMLAttributes, type ReactNode } from 'react';\nimport { CheckIcon } from '../../icons/buttonIcons';\nimport { resolveIconColor, type IconColor } from '../../icons/SvgIcon';\nimport styles from './Checkbox.module.css';\n\nexport type CheckboxSize = 'small' | 'medium' | 'large';\n/** Same token names as SvgIcon `color`. */\nexport type CheckboxColor = IconColor;\n\nexport interface CheckboxProps\n extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size' | 'color'> {\n label?: ReactNode;\n /** Default medium. */\n size?: CheckboxSize;\n /** Palette token or raw CSS color. Omit = accent when checked. */\n color?: CheckboxColor | (string & {});\n /** Visual mixed state. Set on the DOM node — not a native React attribute. */\n indeterminate?: boolean;\n}\n\nexport function Checkbox({\n label,\n size = 'medium',\n color,\n className,\n id,\n style,\n indeterminate = false,\n ...rest\n}: CheckboxProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const inputId = id ?? (typeof label === 'string' ? `sci-cb-${label}` : undefined);\n const sizeClass = size === 'small' ? styles.small : size === 'large' ? styles.large : null;\n const tint = resolveIconColor(color);\n const tinted = Boolean(tint);\n const mergedStyle = (\n tinted ? { ...style, ['--sci-checkbox-color' as string]: tint } : style\n ) as CSSProperties | undefined;\n\n useEffect(() => {\n if (inputRef.current) inputRef.current.indeterminate = indeterminate;\n }, [indeterminate]);\n\n return (\n <label\n className={[styles.root, sizeClass, tinted ? styles.colored : null, className]\n .filter(Boolean)\n .join(' ')}\n htmlFor={inputId}\n style={mergedStyle}\n >\n <input ref={inputRef} id={inputId} type=\"checkbox\" className={styles.input} {...rest} />\n <span className={styles.box} aria-hidden=\"true\">\n <CheckIcon className={styles.mark} weight={2.4} />\n </span>\n {label != null ? <span className={styles.label}>{label}</span> : null}\n </label>\n );\n}\n",".tip {\n position: fixed;\n z-index: 10000;\n max-width: 260px;\n /* Light: 1px less on top — light tips read visually higher. Dark: even padding below. */\n padding: 3px 8px 4px;\n border-radius: var(--sci-radius-sm, 4px);\n border: 1px solid var(--sci-color-text-secondary, var(--color-text-secondary, #adb5bd));\n background: var(--sci-color-bg, var(--color-bg, #f2f4fa));\n /* Light: primary text (approved). Dark: softer — see override below. */\n color: var(--sci-color-text, var(--color-text, #1c2433));\n font-size: 12px;\n font-family: var(--sci-font-family, var(--font-family, system-ui, sans-serif));\n line-height: 1.35;\n white-space: pre-wrap;\n box-shadow: var(--sci-shadow-md, 0 4px 14px rgba(0, 0, 0, 0.35));\n pointer-events: none;\n animation: sciTipIn 0.12s ease-out;\n}\n\n:global([data-theme='dark']) .tip {\n padding: 4px 8px;\n border-color: var(--sci-color-border, var(--color-border, #373a40));\n color: var(--sci-color-text-secondary, var(--color-text-secondary, #adb5bd));\n}\n\n.host {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n max-width: 100%;\n}\n\n.hostBlock {\n display: block;\n width: 100%;\n height: 100%;\n max-width: none;\n}\n\n.hostBlock > * {\n width: 100%;\n}\n\n@keyframes sciTipIn {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n","import {\n useCallback,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type CSSProperties,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport styles from './Tip.module.css';\n\ntype Side = 'bottom' | 'top';\n\nexport interface TipProps {\n /** Tooltip text. Empty / undefined — no tip. */\n content?: string;\n /** Preferred side (default bottom-center; flips near the edge). */\n side?: Side;\n /** Stretch host to 100% (grid cells / full-width buttons). */\n block?: boolean;\n /** Clamp position to this element (otherwise the viewport). */\n boundaryRef?: RefObject<HTMLElement | null>;\n className?: string;\n children: ReactNode;\n}\n\ninterface Pos {\n /** Left / top edges in CSS px (integers — avoids AA blur on borders). */\n left: number;\n top: number;\n side: Side;\n /** Anchor center X — used to re-clamp after measure. */\n centerX: number;\n /** Anchor top (or bottom for side bottom) used to recompute top after measure. */\n anchorY: number;\n gap: number;\n}\n\nconst VIEW_PAD = 8;\n\nfunction isDisabledControl(root: HTMLElement): boolean {\n if (root instanceof HTMLButtonElement && root.disabled) return true;\n if (root.getAttribute('aria-disabled') === 'true') return true;\n const control = root.querySelector('button, input, select, textarea');\n if (control instanceof HTMLButtonElement && control.disabled) return true;\n if (control?.getAttribute('aria-disabled') === 'true') return true;\n if (control instanceof HTMLInputElement && control.disabled) return true;\n return false;\n}\n\nfunction clampCenterX(centerX: number, tipWidth: number, bound: DOMRect): number {\n const half = tipWidth / 2;\n const min = bound.left + VIEW_PAD + half;\n const max = bound.right - VIEW_PAD - half;\n if (min > max) return (bound.left + bound.right) / 2;\n return Math.min(Math.max(centerX, min), max);\n}\n\nfunction leftEdgeFor(centerX: number, tipWidth: number, bound: DOMRect): number {\n return Math.round(clampCenterX(centerX, tipWidth, bound) - tipWidth / 2);\n}\n\n/** Top CSS edge (integer). For side `top`, pass measured tip height so we skip translateY blur. */\nfunction topEdgeFor(anchorTop: number, gap: number, side: Side, tipHeight = 0): number {\n if (side === 'bottom') return Math.round(anchorTop + gap);\n return Math.round(anchorTop - gap - tipHeight);\n}\n\nfunction viewportBound(): DOMRect {\n return {\n left: 0,\n right: window.innerWidth,\n top: 0,\n bottom: window.innerHeight,\n width: window.innerWidth,\n height: window.innerHeight,\n x: 0,\n y: 0,\n toJSON: () => ({}),\n } as DOMRect;\n}\n\n/**\n * Custom tooltip used by NC and OHS Console (portal → not clipped by overflow).\n * Same props as those copies (`delivery/spec.md` §4): hosts swap the import, not call sites.\n * Do not pair with native `title` — you would get a double tip.\n */\nexport function Tip({ content, side = 'bottom', block = false, boundaryRef, className, children }: TipProps) {\n const tipId = useId();\n const tipRef = useRef<HTMLSpanElement>(null);\n const [pos, setPos] = useState<Pos | null>(null);\n\n const hide = useCallback(() => setPos(null), []);\n\n const showFrom = useCallback(\n (el: HTMLElement) => {\n if (!content || isDisabledControl(el)) {\n return;\n }\n const rect = el.getBoundingClientRect();\n const gap = 8;\n const tipEstimate = 36;\n const bound = boundaryRef?.current?.getBoundingClientRect() ?? viewportBound();\n\n let nextSide = side;\n let anchorY = side === 'bottom' ? rect.bottom : rect.top;\n\n if (side === 'bottom' && bound.bottom - rect.bottom < tipEstimate) {\n nextSide = 'top';\n anchorY = rect.top;\n } else if (side === 'top' && rect.top - bound.top < tipEstimate) {\n nextSide = 'bottom';\n anchorY = rect.bottom;\n }\n\n const centerX = rect.left + rect.width / 2;\n const roughW = Math.min(260, Math.max(80, content.length * 7));\n\n setPos({\n left: leftEdgeFor(centerX, roughW, bound),\n // Estimate before measure; layout effect snaps with real tipHeight.\n top: topEdgeFor(anchorY, gap, nextSide, nextSide === 'top' ? tipEstimate : 0),\n side: nextSide,\n centerX,\n anchorY,\n gap,\n });\n },\n [boundaryRef, content, side],\n );\n\n useLayoutEffect(() => {\n if (!pos || !tipRef.current) return;\n const tipW = tipRef.current.offsetWidth;\n const tipH = tipRef.current.offsetHeight;\n const bound = boundaryRef?.current?.getBoundingClientRect() ?? viewportBound();\n const nextLeft = leftEdgeFor(pos.centerX, tipW, bound);\n const nextTop = topEdgeFor(pos.anchorY, pos.gap, pos.side, tipH);\n if (nextLeft !== pos.left || nextTop !== pos.top) {\n setPos((p) => (p ? { ...p, left: nextLeft, top: nextTop } : p));\n }\n }, [boundaryRef, pos]);\n\n if (!content) {\n return <>{children}</>;\n }\n\n return (\n <span\n className={[styles.host, block ? styles.hostBlock : '', className].filter(Boolean).join(' ')}\n aria-describedby={pos ? tipId : undefined}\n onMouseEnter={(e) => showFrom(e.currentTarget)}\n onMouseLeave={hide}\n onFocus={(e) => showFrom(e.currentTarget)}\n onBlur={hide}\n >\n {children}\n {pos &&\n createPortal(\n <span\n ref={tipRef}\n id={tipId}\n role=\"tooltip\"\n className={styles.tip}\n style={{ left: pos.left, top: pos.top } as CSSProperties}\n >\n {content}\n </span>,\n document.body,\n )}\n </span>\n );\n}\n","import { createContext, type ChangeEvent } from 'react';\nimport type { RadioColor, RadioSize } from './Radio';\n\nexport type RadioGroupContextValue = {\n name: string;\n value?: string;\n disabled?: boolean;\n size?: RadioSize;\n color?: RadioColor | (string & {});\n onSelect: (event: ChangeEvent<HTMLInputElement>) => void;\n};\n\nexport const RadioGroupContext = createContext<RadioGroupContextValue | null>(null);\n",".root {\n --sci-radio-size: 16px;\n --sci-radio-label-nudge: -3px;\n position: relative;\n display: inline-flex;\n align-items: baseline;\n gap: var(--sci-spacing-sm);\n cursor: pointer;\n user-select: none;\n color: var(--sci-color-text);\n font-size: var(--sci-font-size-sm);\n line-height: 1;\n}\n\n.root:has(.input:disabled) {\n opacity: 0.45;\n cursor: default;\n}\n\n.small {\n --sci-radio-size: 14px;\n --sci-radio-label-nudge: -2px;\n font-size: 0.8125rem;\n}\n\n.large {\n --sci-radio-size: 20px;\n --sci-radio-label-nudge: -5px;\n font-size: 1rem;\n}\n\n.input {\n position: absolute;\n opacity: 0;\n width: 1px;\n height: 1px;\n pointer-events: none;\n}\n\n.box {\n display: block;\n flex-shrink: 0;\n width: var(--sci-radio-size);\n height: var(--sci-radio-size);\n overflow: hidden;\n}\n\n.glyph {\n display: block;\n width: var(--sci-radio-size);\n height: var(--sci-radio-size);\n}\n\n.ring {\n fill: var(--sci-color-bg-input);\n stroke: var(--sci-color-border);\n stroke-width: 1.5;\n}\n\n.dot {\n fill: var(--sci-color-accent);\n opacity: 0;\n transition: opacity 0.12s ease;\n}\n\n.input:focus-visible + .box .ring {\n stroke: var(--sci-color-border-focus);\n}\n\n.input:checked + .box .ring {\n stroke: var(--sci-color-accent);\n}\n\n.input:checked + .box .dot {\n opacity: 1;\n}\n\n.colored .input:checked + .box .ring {\n stroke: var(--sci-radio-color);\n}\n\n.colored .dot {\n fill: var(--sci-radio-color);\n}\n\n.label {\n line-height: 1;\n translate: 0 var(--sci-radio-label-nudge);\n}\n","import type { CSSProperties, InputHTMLAttributes, ReactNode } from 'react';\nimport { useContext } from 'react';\nimport { resolveIconColor, type IconColor } from '../../icons/SvgIcon';\nimport { RadioGroupContext } from './RadioGroupContext';\nimport styles from './Radio.module.css';\n\nexport type RadioSize = 'small' | 'medium' | 'large';\n/** Same token names as SvgIcon `color`. */\nexport type RadioColor = IconColor;\n\nexport interface RadioProps\n extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size' | 'color'> {\n label?: ReactNode;\n /** Default medium. Group value wins if the radio omits size. */\n size?: RadioSize;\n /** Palette token or raw CSS color. Omit = accent when selected. */\n color?: RadioColor | (string & {});\n}\n\nexport function Radio({\n label,\n size: sizeProp,\n color: colorProp,\n className,\n id,\n style,\n name: nameProp,\n disabled: disabledProp,\n checked: checkedProp,\n value,\n onChange,\n ...rest\n}: RadioProps) {\n const group = useContext(RadioGroupContext);\n const size = sizeProp ?? group?.size ?? 'medium';\n const color = colorProp ?? group?.color;\n const disabled = disabledProp ?? group?.disabled;\n const name = group?.name ?? nameProp;\n const checked = group ? group.value === String(value ?? '') : checkedProp;\n const sizeClass = size === 'small' ? styles.small : size === 'large' ? styles.large : null;\n const tint = resolveIconColor(color);\n const tinted = Boolean(tint);\n const mergedStyle = (\n tinted ? { ...style, ['--sci-radio-color' as string]: tint } : style\n ) as CSSProperties | undefined;\n const inputId = id ?? (typeof label === 'string' ? `sci-radio-${name ?? 'x'}-${label}` : undefined);\n\n return (\n <label\n className={[styles.root, sizeClass, tinted ? styles.colored : null, className]\n .filter(Boolean)\n .join(' ')}\n htmlFor={inputId}\n style={mergedStyle}\n >\n <input\n id={inputId}\n type=\"radio\"\n className={styles.input}\n name={name}\n value={value}\n checked={checked}\n disabled={disabled}\n onChange={group ? group.onSelect : onChange}\n {...rest}\n />\n <span className={styles.box} aria-hidden=\"true\">\n <svg className={styles.glyph} viewBox=\"0 0 24 24\" focusable=\"false\">\n <circle className={styles.ring} cx=\"12\" cy=\"12\" r=\"10\" />\n <circle className={styles.dot} cx=\"12\" cy=\"12\" r=\"5.5\" />\n </svg>\n </span>\n {label != null ? <span className={styles.label}>{label}</span> : null}\n </label>\n );\n}\n",".root {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0.15rem;\n}\n\n.legend {\n color: var(--sci-color-text-secondary);\n font-size: var(--sci-font-size-sm);\n line-height: 1.3;\n}\n\n.optionsV,\n.optionsH {\n display: flex;\n gap: var(--sci-spacing-sm);\n}\n\n.optionsV {\n flex-direction: column;\n align-items: flex-start;\n}\n\n.optionsH {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--sci-spacing-md);\n}\n","import {\n useCallback,\n useId,\n useState,\n type ChangeEvent,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport type { RadioColor, RadioSize } from './Radio';\nimport { RadioGroupContext } from './RadioGroupContext';\nimport styles from './RadioGroup.module.css';\n\nexport type RadioGroupOrientation = 'vertical' | 'horizontal';\n\nexport interface RadioGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange' | 'color'> {\n /** Shared `name` for the radios. Auto-generated when omitted. */\n name?: string;\n value?: string;\n defaultValue?: string;\n onChange?: (event: ChangeEvent<HTMLInputElement>, value: string) => void;\n /** Default vertical. */\n orientation?: RadioGroupOrientation;\n disabled?: boolean;\n size?: RadioSize;\n color?: RadioColor | (string & {});\n /** Visible group title; also used as `aria-label` when that is omitted. */\n label?: ReactNode;\n children?: ReactNode;\n}\n\nexport function RadioGroup({\n name: nameProp,\n value: valueProp,\n defaultValue,\n onChange,\n orientation = 'vertical',\n disabled,\n size,\n color,\n label,\n className,\n children,\n 'aria-label': ariaLabel,\n ...rest\n}: RadioGroupProps) {\n const autoName = useId();\n const name = nameProp ?? autoName;\n const [uncontrolled, setUncontrolled] = useState(defaultValue);\n const value = valueProp !== undefined ? valueProp : uncontrolled;\n\n const onSelect = useCallback(\n (event: ChangeEvent<HTMLInputElement>) => {\n if (valueProp === undefined) setUncontrolled(event.target.value);\n onChange?.(event, event.target.value);\n },\n [onChange, valueProp],\n );\n\n return (\n <RadioGroupContext.Provider value={{ name, value, disabled, size, color, onSelect }}>\n <div\n role=\"radiogroup\"\n aria-orientation={orientation}\n aria-label={ariaLabel ?? (typeof label === 'string' ? label : undefined)}\n className={[styles.root, className].filter(Boolean).join(' ')}\n {...rest}\n >\n {label != null ? <div className={styles.legend}>{label}</div> : null}\n <div className={orientation === 'horizontal' ? styles.optionsH : styles.optionsV}>\n {children}\n </div>\n </div>\n </RadioGroupContext.Provider>\n );\n}\n",".labeled {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: 0.25rem;\n width: max-content;\n max-width: 100%;\n min-width: 0;\n}\n\n.labeled.fill {\n width: 100%;\n}\n\n.caption {\n font-size: 11px;\n line-height: 1.3;\n color: var(--sci-color-text-muted);\n}\n\n.field {\n display: block;\n width: auto;\n max-width: 100%;\n min-width: 0;\n box-sizing: border-box;\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-sm);\n background: var(--sci-color-bg-input);\n color: var(--sci-color-text);\n font: inherit;\n font-size: var(--sci-font-size-sm);\n}\n\n.field:focus,\n.field:focus-visible {\n outline: none;\n border-color: var(--sci-color-border-focus);\n}\n\n.invalid,\n.invalid:focus,\n.invalid:focus-visible {\n border-color: var(--sci-color-error);\n}\n\n.field:disabled {\n color: var(--sci-color-text-muted);\n user-select: none;\n -webkit-user-select: none;\n}\n\n.field:disabled::placeholder {\n color: var(--sci-color-text-muted);\n}\n\n.input {\n height: 32px;\n padding: 0 8px;\n}\n\n.fill.field,\n.fill .field {\n width: 100%;\n}\n\n.passwordWrap {\n position: relative;\n display: block;\n width: max-content;\n max-width: 100%;\n min-width: 0;\n}\n\n.passwordWrap.fill {\n width: 100%;\n}\n\n.passwordInput {\n padding-right: 28px;\n}\n\n.reveal {\n position: absolute;\n top: 50%;\n right: 4px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n border: none;\n border-radius: 0;\n background: transparent;\n color: var(--sci-color-text-muted);\n line-height: 1;\n cursor: pointer;\n transform: translateY(-50%);\n}\n\n.reveal:focus,\n.reveal:focus-visible {\n outline: none;\n}\n\n.reveal:hover:not(:disabled) {\n color: var(--sci-color-text);\n}\n\n.passwordWrap:has(.field:disabled) {\n user-select: none;\n -webkit-user-select: none;\n}\n\n.passwordWrap:has(.field:disabled) .reveal {\n opacity: 0.55;\n}\n\n.reveal:disabled {\n color: var(--sci-color-text-muted);\n}\n\n.textarea {\n min-height: 64px;\n padding: 6px 8px;\n resize: vertical;\n line-height: 1.4;\n}\n\n.mono {\n font-family: var(--sci-font-family-mono);\n}\n","import type { ReactNode } from 'react';\nimport styles from './Input.module.css';\n\n/** Caption above Input / TextArea / Dropdown. Bare control when `label` is omitted. */\nexport function FieldCaption({\n label,\n htmlFor,\n fullWidth = false,\n children,\n}: {\n label?: ReactNode;\n htmlFor?: string;\n /** Stretch to the parent. Default hugs the control. */\n fullWidth?: boolean;\n children: ReactNode;\n}) {\n if (label == null) return children;\n return (\n <label\n className={[styles.labeled, fullWidth ? styles.fill : ''].filter(Boolean).join(' ')}\n htmlFor={htmlFor}\n >\n <span className={styles.caption}>{label}</span>\n {children}\n </label>\n );\n}\n","import { useId, useState, type InputHTMLAttributes, type ReactNode } from 'react';\nimport { EyeIcon, EyeSlashIcon } from '../../icons/buttonIcons';\nimport { FieldCaption } from './FieldCaption';\nimport styles from './Input.module.css';\n\nexport interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {\n type?: 'text' | 'search' | 'email' | 'url' | 'password' | 'number';\n /** Caption above the field. Omit for a bare input. */\n label?: ReactNode;\n /** Stretch to the parent. Default hugs the content. */\n fullWidth?: boolean;\n /** Red border after a failed validation. */\n invalid?: boolean;\n /** Password reveal — shown. Default matches the login form. */\n showPasswordLabel?: string;\n /** Password reveal — hidden. */\n hidePasswordLabel?: string;\n}\n\n/** Single-line field. Same chrome as SearchBar / Dropdown — no system focus ring. */\nexport function Input({\n className,\n type = 'text',\n label,\n fullWidth = false,\n invalid = false,\n disabled,\n id,\n showPasswordLabel = 'Show password',\n hidePasswordLabel = 'Hide password',\n ...rest\n}: InputProps) {\n const [revealed, setRevealed] = useState(false);\n const generatedId = useId();\n const isPassword = type === 'password';\n const inputId = id ?? (label != null || isPassword ? generatedId : undefined);\n const inputType = isPassword && revealed ? 'text' : type;\n\n const field = (\n <input\n id={inputId}\n type={inputType}\n disabled={disabled}\n aria-invalid={invalid || undefined}\n className={[\n styles.field,\n styles.input,\n isPassword ? styles.passwordInput : '',\n fullWidth ? styles.fill : '',\n invalid ? styles.invalid : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n />\n );\n\n const control = !isPassword ? (\n field\n ) : (\n <div className={[styles.passwordWrap, fullWidth ? styles.fill : ''].filter(Boolean).join(' ')}>\n {field}\n <button\n type=\"button\"\n className={styles.reveal}\n aria-label={revealed ? hidePasswordLabel : showPasswordLabel}\n aria-controls={inputId}\n aria-pressed={revealed}\n disabled={disabled}\n onClick={() => setRevealed((open) => !open)}\n >\n {revealed ? <EyeSlashIcon size={14} /> : <EyeIcon size={14} />}\n </button>\n </div>\n );\n\n return (\n <FieldCaption label={label} htmlFor={inputId} fullWidth={fullWidth}>\n {control}\n </FieldCaption>\n );\n}\n",".wrap {\n position: relative;\n display: inline-flex;\n align-items: center;\n /* Flex parents stretch children on the cross axis — wrap must stay input-wide\n or `right: 4px` on clear lands at the far edge of the row. */\n width: max-content;\n max-width: 100%;\n align-self: flex-start;\n}\n\n.fill {\n display: flex;\n width: 100%;\n}\n\n.icon {\n position: absolute;\n left: 8px;\n color: var(--sci-color-text-muted);\n pointer-events: none;\n}\n\n.input {\n width: 200px;\n max-width: 240px;\n height: 32px;\n box-sizing: border-box;\n padding: 6px 10px 6px 28px;\n border-radius: var(--sci-radius-sm);\n border: 1px solid var(--sci-color-border);\n background: var(--sci-color-bg-input);\n color: var(--sci-color-text);\n font: inherit;\n font-size: var(--sci-font-size-sm);\n}\n\n.fill .input {\n width: 100%;\n max-width: none;\n flex: 1;\n min-width: 0;\n}\n\n.withClear {\n padding-right: 26px;\n}\n\n.input:focus,\n.input:focus-visible {\n outline: none;\n border-color: var(--sci-color-border-focus);\n}\n\n.wrap:has(.input:disabled) {\n user-select: none;\n -webkit-user-select: none;\n}\n\n.wrap:has(.input:disabled) .icon {\n opacity: 0.55;\n}\n\n.input:disabled {\n color: var(--sci-color-text-muted);\n user-select: none;\n -webkit-user-select: none;\n}\n\n.input:disabled::placeholder {\n color: var(--sci-color-text-muted);\n}\n\n.clear {\n position: absolute;\n right: 4px;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n border: none;\n border-radius: 0;\n background: transparent;\n color: var(--sci-color-text-muted);\n line-height: 1;\n cursor: pointer;\n}\n\n.clear:hover:not(:disabled) {\n color: var(--sci-color-text);\n background: transparent;\n}\n\n.clear:disabled {\n color: var(--sci-color-text-muted);\n}\n","import {\n useEffect,\n useRef,\n useState,\n type ChangeEvent,\n type InputHTMLAttributes,\n} from 'react';\nimport { CloseIcon, SearchIcon } from '../../icons/buttonIcons';\nimport styles from './SearchBar.module.css';\n\nexport interface SearchBarProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'> {\n /** Stretch to the parent. Default is the compact width. */\n fullWidth?: boolean;\n /**\n * Debounced value. First emit is skipped when it matches the starting value.\n */\n onSearch?: (query: string) => void;\n /** Delay before `onSearch`, in ms. Default 300. Use 500+ for a large catalog. */\n debounce?: number;\n /** aria-label on the clear control. */\n clearLabel?: string;\n}\n\nfunction useDebouncedValue(value: string, ms: number): string {\n const [debounced, setDebounced] = useState(value);\n useEffect(() => {\n if (ms <= 0) return;\n const id = window.setTimeout(() => setDebounced(value), ms);\n return () => window.clearTimeout(id);\n }, [value, ms]);\n // No delay means no state to hold: read through and skip the extra render.\n return ms <= 0 ? value : debounced;\n}\n\n/** Text query field: icon, optional clear, optional debounce. */\nexport function SearchBar({\n className,\n fullWidth = false,\n onSearch,\n debounce = 300,\n clearLabel = 'Clear search',\n value,\n defaultValue,\n onChange,\n disabled,\n ...rest\n}: SearchBarProps) {\n const controlled = value !== undefined;\n const [inner, setInner] = useState(() => String(defaultValue ?? ''));\n const text = controlled ? String(value ?? '') : inner;\n const debounced = useDebouncedValue(text, debounce);\n\n const onSearchRef = useRef(onSearch);\n // Declared before the emit effect below, so `current` is fresh by the time it fires.\n useEffect(() => {\n onSearchRef.current = onSearch;\n });\n const lastSent = useRef(String(defaultValue ?? value ?? ''));\n\n useEffect(() => {\n if (!onSearchRef.current) return;\n if (debounced === lastSent.current) return;\n lastSent.current = debounced;\n onSearchRef.current(debounced);\n }, [debounced]);\n\n const emitChange = (next: string, event?: ChangeEvent<HTMLInputElement>) => {\n if (!controlled) setInner(next);\n if (event) {\n onChange?.(event);\n return;\n }\n onChange?.({\n target: { value: next },\n currentTarget: { value: next },\n } as ChangeEvent<HTMLInputElement>);\n };\n\n const clear = () => {\n emitChange('');\n lastSent.current = '';\n onSearchRef.current?.('');\n };\n\n return (\n <div className={[styles.wrap, fullWidth ? styles.fill : '', className].filter(Boolean).join(' ')}>\n <SearchIcon className={styles.icon} size={14} />\n <input\n type=\"text\"\n className={[styles.input, text && !disabled ? styles.withClear : ''].filter(Boolean).join(' ')}\n value={text}\n disabled={disabled}\n onChange={(event) => {\n if (!controlled) setInner(event.target.value);\n onChange?.(event);\n }}\n {...rest}\n />\n {text && !disabled ? (\n <button\n type=\"button\"\n className={styles.clear}\n aria-label={clearLabel}\n onClick={clear}\n >\n <CloseIcon size={12} />\n </button>\n ) : null}\n </div>\n );\n}\n","import { useId, type ReactNode, type TextareaHTMLAttributes } from 'react';\nimport { FieldCaption } from './FieldCaption';\nimport styles from './Input.module.css';\n\nexport interface TextAreaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {\n /** Caption above the field. Omit for a bare textarea. */\n label?: ReactNode;\n /** Stretch to the parent. Default hugs the content. */\n fullWidth?: boolean;\n /** Monospace (glob, code). */\n mono?: boolean;\n /** Red border after a failed validation. */\n invalid?: boolean;\n}\n\n/** Multiline field. Same chrome as Input. */\nexport function TextArea({\n className,\n label,\n fullWidth = false,\n mono = false,\n invalid = false,\n id,\n ...rest\n}: TextAreaProps) {\n const generatedId = useId();\n const inputId = id ?? (label != null ? generatedId : undefined);\n\n return (\n <FieldCaption label={label} htmlFor={inputId} fullWidth={fullWidth}>\n <textarea\n id={inputId}\n aria-invalid={invalid || undefined}\n className={[\n styles.field,\n styles.textarea,\n fullWidth ? styles.fill : '',\n mono ? styles.mono : '',\n invalid ? styles.invalid : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n />\n </FieldCaption>\n );\n}\n",".wrap {\n display: inline-flex;\n align-items: center;\n gap: var(--sci-spacing-sm);\n}\n\n.track {\n position: relative;\n box-sizing: border-box;\n width: 52px;\n height: 28px;\n padding: 0;\n margin: 0;\n border: 1px solid var(--sci-color-border);\n border-radius: 999px;\n background: var(--sci-color-bg-input);\n line-height: 0;\n cursor: pointer;\n transition:\n background 0.18s ease,\n border-color 0.18s ease;\n}\n\n.track:focus,\n.track:focus-visible {\n outline: none;\n}\n\n.wrap:has(.track:disabled) {\n opacity: 0.45;\n user-select: none;\n -webkit-user-select: none;\n}\n\n.track:disabled {\n cursor: default;\n}\n\n.track:disabled .knob {\n animation: none;\n}\n\n.knob {\n position: absolute;\n top: 50%;\n left: 2px;\n display: flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n width: 22px;\n height: 22px;\n border-radius: 50%;\n background: #fff;\n color: var(--sci-color-text-muted);\n font-size: 13px;\n line-height: 1;\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);\n transform: translateY(-50%);\n transition:\n transform 0.18s ease,\n background 0.18s ease;\n}\n\n.off {\n background: var(--sci-color-bg-input);\n border-color: var(--sci-color-border);\n}\n\n.off .knob {\n background-color: var(--sci-color-text-muted);\n}\n\n.connecting {\n background: var(--sci-color-warning);\n border-color: var(--sci-color-warning);\n}\n\n.connecting .knob {\n transform: translate(13px, -50%);\n background-color: color-mix(in srgb, var(--sci-color-warning) 40%, white);\n animation: pulse 0.9s ease-in-out infinite;\n}\n\n.active {\n background: var(--sci-color-accent);\n border-color: var(--sci-color-accent);\n}\n\n.active .knob {\n transform: translate(24px, -50%);\n background-color: color-mix(in srgb, var(--sci-color-accent) 25%, white);\n}\n\n.waiting {\n background: var(--sci-color-success);\n border-color: var(--sci-color-success);\n}\n\n.waiting .knob {\n transform: translate(24px, -50%);\n background-color: color-mix(in srgb, var(--sci-color-success) 25%, white);\n}\n\n.degraded {\n background: var(--sci-color-warning);\n border-color: var(--sci-color-warning);\n}\n\n.degraded .knob {\n transform: translate(24px, -50%);\n background-color: color-mix(in srgb, var(--sci-color-warning) 35%, white);\n animation: pulse 0.9s ease-in-out infinite;\n}\n\n.unreachable {\n background: var(--sci-color-warning);\n border-color: var(--sci-color-warning);\n}\n\n.unreachable .knob {\n transform: translate(13px, -50%);\n background-color: color-mix(in srgb, var(--sci-color-warning) 40%, white);\n animation: pulse 0.9s ease-in-out infinite;\n}\n\n.error {\n background: var(--sci-color-error);\n border-color: var(--sci-color-error);\n}\n\n.error .knob {\n background-color: color-mix(in srgb, var(--sci-color-error) 40%, white);\n}\n\n.label {\n font-size: var(--sci-font-size-sm);\n color: var(--sci-color-text-secondary);\n}\n\n.small {\n flex-direction: column;\n gap: 2px;\n align-items: center;\n justify-content: center;\n}\n\n.small .label {\n font-size: 8px;\n line-height: 1;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n opacity: 0.8;\n}\n\n.small .track {\n width: 39px;\n height: 20px;\n}\n\n.small .knob {\n left: 2px;\n width: 16px;\n height: 16px;\n font-size: 9px;\n}\n\n.small .connecting .knob,\n.small .unreachable .knob {\n transform: translate(9px, -50%);\n}\n\n.small .active .knob,\n.small .waiting .knob,\n.small .degraded .knob {\n transform: translate(18px, -50%);\n}\n\n@keyframes pulse {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n","import type { ButtonHTMLAttributes, ReactNode } from 'react';\nimport styles from './Switcher.module.css';\n\nexport type SwitcherPhase =\n | 'off'\n | 'connecting'\n | 'active'\n | 'waiting'\n | 'degraded'\n | 'error'\n | 'unreachable';\n\n/** `medium` — Connection track. `small` — Auto. */\nexport type SwitcherSize = 'medium' | 'small';\n\nexport interface SwitcherProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onToggle'> {\n /** Track color and knob position. Default `off`. */\n phase?: SwitcherPhase;\n /** When `phase` is omitted: `true` → `active`, `false` → `off`. */\n checked?: boolean;\n label?: ReactNode;\n /** Default medium (Connection). Small is Auto. */\n size?: SwitcherSize;\n onToggle?: () => void;\n}\n\nfunction resolvePhase(phase: SwitcherPhase | undefined, checked: boolean | undefined): SwitcherPhase {\n if (phase) return phase;\n if (checked) return 'active';\n return 'off';\n}\n\n/** Colored track switch — Connection (medium) and Auto (small). */\nexport function Switcher({\n phase: phaseProp,\n checked,\n label,\n size = 'medium',\n disabled,\n onToggle,\n className,\n ...rest\n}: SwitcherProps) {\n const phase = resolvePhase(phaseProp, checked);\n const on = phase === 'active' || phase === 'waiting' || phase === 'degraded';\n const busy = phase === 'connecting' || phase === 'unreachable';\n const locked = disabled || phase === 'unreachable';\n\n return (\n <div\n className={[styles.wrap, size === 'small' ? styles.small : '', className].filter(Boolean).join(' ')}\n >\n {label != null ? <span className={styles.label}>{label}</span> : null}\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={on || busy}\n aria-busy={busy || undefined}\n disabled={disabled}\n className={[styles.track, styles[phase]].join(' ')}\n {...rest}\n onClick={() => {\n if (locked) return;\n onToggle?.();\n }}\n >\n <span className={styles.knob}>{on || busy ? '' : '×'}</span>\n </button>\n </div>\n );\n}\n","/** Viewport-fixed menu at a pointer, flipped above when it would overflow. */\nexport function placeFixedPoint(\n x: number,\n y: number,\n menu: HTMLElement | null,\n): { top: number; left: number } {\n return placeFixedMenu(new DOMRect(x, y, 0, 0), menu, 0);\n}\n\n/** Viewport-fixed menu under `anchor`, flipped above when it would overflow. */\nexport function placeFixedMenu(\n anchor: DOMRect,\n menu: HTMLElement | null,\n gap: number,\n): { top: number; left: number } {\n const pad = 8;\n const vh = window.innerHeight;\n const vw = window.innerWidth;\n const menuH = menu?.offsetHeight ?? 0;\n const menuW = menu?.offsetWidth ?? 0;\n\n let top = anchor.bottom + gap;\n const spaceBelow = vh - pad - top;\n const spaceAbove = anchor.top - gap - pad;\n if (menuH > 0 && spaceBelow < menuH && spaceAbove > spaceBelow) {\n top = Math.max(pad, anchor.top - gap - menuH);\n } else if (menuH > 0 && top + menuH > vh - pad) {\n top = Math.max(pad, vh - pad - menuH);\n }\n\n let left = anchor.left;\n if (menuW > 0 && left + menuW > vw - pad) {\n left = Math.max(pad, vw - pad - menuW);\n }\n return { top, left };\n}\n",".root {\n position: relative;\n display: block;\n width: max-content;\n max-width: 100%;\n min-width: 0;\n}\n\n.root.fill {\n width: 100%;\n}\n\n.trigger {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n width: max-content;\n max-width: 100%;\n height: 32px;\n padding: 0 4px 0 12px;\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-sm);\n background: var(--sci-color-bg-input);\n color: var(--sci-color-text);\n font: inherit;\n font-size: var(--sci-font-size-sm);\n text-align: left;\n cursor: pointer;\n}\n\n.fill .trigger {\n width: 100%;\n}\n\n.trigger:hover:not(:disabled) {\n background: color-mix(in srgb, var(--sci-color-text) 4%, var(--sci-color-bg-input));\n}\n\n.trigger:focus,\n.trigger:focus-visible {\n outline: none;\n border-color: var(--sci-color-border-focus);\n}\n\n.triggerOpen {\n border-color: var(--sci-color-border-focus);\n}\n\n.root:has(.trigger:disabled) {\n opacity: 0.45;\n user-select: none;\n -webkit-user-select: none;\n}\n\n.trigger:disabled {\n color: var(--sci-color-text-muted);\n cursor: default;\n}\n\n.value {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.caret {\n flex-shrink: 0;\n color: var(--sci-color-text-muted);\n}\n\n.menu {\n z-index: 60;\n box-sizing: border-box;\n margin: 0;\n padding: 4px 0;\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-sm);\n background: var(--sci-color-bg-panel);\n color: var(--sci-color-text);\n list-style: none;\n max-height: min(280px, 50vh);\n overflow: auto;\n box-shadow:\n 0 5px 5px -3px rgba(0, 0, 0, 0.2),\n 0 8px 10px 1px rgba(0, 0, 0, 0.14),\n 0 3px 14px 2px rgba(0, 0, 0, 0.12);\n opacity: 0;\n transform: translateY(-6px);\n transform-origin: top center;\n transition:\n opacity 0.16s ease,\n transform 0.16s ease;\n pointer-events: none;\n}\n\n.menuOpen {\n opacity: 1;\n transform: translateY(0);\n pointer-events: auto;\n}\n\n.option {\n display: block;\n width: 100%;\n padding: 7px 12px;\n border: none;\n border-radius: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-size: var(--sci-font-size-sm);\n text-align: left;\n cursor: pointer;\n}\n\n.option:hover,\n.optionActive {\n background: var(--sci-color-bg-hover);\n}\n\n.optionSelected {\n background: color-mix(in srgb, var(--sci-color-accent) 22%, transparent);\n}\n\n.optionSelected:hover,\n.optionSelected.optionActive {\n background: color-mix(in srgb, var(--sci-color-accent) 30%, transparent);\n}\n\n.option:focus,\n.option:focus-visible {\n outline: none;\n}\n\n/* Header language control — PlatformHeader .iconBtn / .localeMenu */\n.iconRoot {\n width: max-content;\n}\n\n.iconTrigger {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n padding: 0;\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-sm);\n background: var(--sci-color-bg-input);\n color: var(--sci-color-text-secondary);\n font-size: 15px;\n line-height: 1;\n cursor: pointer;\n transition:\n border-color 0.12s ease,\n background 0.12s ease,\n color 0.12s ease;\n}\n\n.iconTrigger:hover:not(:disabled) {\n border-color: var(--sci-color-border-focus);\n background: var(--sci-color-bg-hover);\n color: var(--sci-color-text);\n}\n\n.iconTrigger:disabled {\n opacity: 0.45;\n cursor: default;\n}\n\n.iconTrigger:focus,\n.iconTrigger:focus-visible {\n outline: none;\n}\n\n.flagIcon {\n display: block;\n flex-shrink: 0;\n line-height: 0;\n shape-rendering: geometricPrecision;\n}\n\n.iconMenu {\n z-index: 60;\n box-sizing: border-box;\n margin: 0;\n padding: var(--sci-spacing-xs);\n list-style: none;\n min-width: 11.5rem;\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-md);\n background: var(--sci-color-bg-panel);\n box-shadow: var(--sci-shadow-md);\n}\n\n.iconOption {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n text-align: left;\n padding: 0.45rem 0.65rem;\n border: 0;\n border-radius: var(--sci-radius-sm);\n background: transparent;\n color: var(--sci-color-text-secondary);\n font-family: inherit;\n font-size: var(--sci-font-size-sm);\n cursor: pointer;\n}\n\n.iconOption:hover,\n.iconOptionActive:not(.iconOptionSelected) {\n background: var(--sci-color-bg-hover);\n color: var(--sci-color-text);\n}\n\n.iconOptionSelected {\n color: var(--sci-color-accent);\n background: color-mix(in srgb, var(--sci-color-accent) 12%, transparent);\n}\n\n.iconLabel {\n line-height: 1.25;\n color: inherit;\n}\n\n.iconOption:focus,\n.iconOption:focus-visible {\n outline: none;\n}\n\n/* Filter [+] — FilterChips .iconBtn / .popover */\n.selectorTrigger {\n color: var(--sci-color-accent);\n}\n\n.selectorTrigger:hover:not(:disabled) {\n color: var(--sci-color-accent);\n}\n\n.selectorTriggerOpen {\n border-color: var(--sci-color-accent);\n background: color-mix(in srgb, var(--sci-color-accent) 16%, transparent);\n}\n\n.selectorMenu {\n z-index: 60;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n min-width: 200px;\n max-height: 60vh;\n overflow-y: auto;\n margin: 0;\n padding: var(--sci-spacing-xs);\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-md);\n background: var(--sci-color-bg-panel);\n box-shadow: var(--sci-shadow-md);\n}\n\n.selectorList {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n.selectorOption {\n width: 100%;\n box-sizing: border-box;\n padding: 7px 10px;\n border-radius: var(--sci-radius-sm);\n white-space: nowrap;\n}\n\n.selectorOption:hover,\n.selectorOptionActive {\n background: var(--sci-color-bg-hover);\n}\n\n.selectorFooter {\n display: flex;\n justify-content: flex-end;\n margin-top: 4px;\n padding: 4px 4px 2px;\n border-top: 1px solid var(--sci-color-border);\n}\n\n.selectorOk {\n height: 26px;\n padding: 0 12px;\n border-radius: var(--sci-radius-sm);\n border: 1px solid var(--sci-color-accent);\n background: var(--sci-color-accent);\n color: #fff;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n}\n\n.selectorOk:hover {\n background: color-mix(in srgb, var(--sci-color-accent) 85%, #000);\n border-color: color-mix(in srgb, var(--sci-color-accent) 85%, #000);\n}\n\n/* Right-click menu — console connection / integration card */\n.contextBackdrop {\n position: fixed;\n inset: 0;\n z-index: 59;\n}\n\n.contextMenu {\n z-index: 60;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 168px;\n margin: 0;\n padding: 4px;\n list-style: none;\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-sm);\n background: var(--sci-color-bg-panel);\n box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);\n}\n\n.contextOption {\n display: flex;\n align-items: center;\n gap: 8px;\n width: 100%;\n padding: 7px 10px;\n border: none;\n border-radius: var(--sci-radius-sm);\n background: transparent;\n color: var(--sci-color-text);\n font: inherit;\n font-size: var(--sci-font-size-sm);\n text-align: left;\n cursor: pointer;\n}\n\n.contextOption:hover,\n.contextOptionActive {\n background: var(--sci-color-bg-hover);\n}\n\n.contextIcon {\n display: inline-flex;\n width: 16px;\n height: 16px;\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n color: var(--sci-color-text-muted);\n}\n\n.contextDanger:hover,\n.contextDanger.contextOptionActive {\n color: var(--sci-color-error);\n}\n\n.contextDanger:hover .contextIcon,\n.contextDanger.contextOptionActive .contextIcon {\n color: var(--sci-color-error);\n}\n\n.contextOption:focus,\n.contextOption:focus-visible {\n outline: none;\n}\n","import {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type KeyboardEvent as ReactKeyboardEvent,\n type ReactNode,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport { ArrowDropDownIcon, ArrowDropUpIcon, PlusIcon } from '../../icons/buttonIcons';\nimport { placeFixedMenu, placeFixedPoint } from '../../placeFixedMenu';\nimport { Checkbox } from '../Checkbox/Checkbox';\nimport { FieldCaption } from '../Input/FieldCaption';\nimport { Tip } from '../Tip/Tip';\nimport styles from './Dropdown.module.css';\n\nconst CLOSE_MS = 160;\n\nexport type DropdownVariant = 'field' | 'icon' | 'selector' | 'context';\n\nexport interface DropdownOption<T extends string = string> {\n value: T;\n label: string;\n /** Glyph in the icon / context variants. */\n icon?: ReactNode;\n /** Context row — error color on hover. */\n danger?: boolean;\n}\n\nexport interface DropdownProps<T extends string = string> {\n options: readonly DropdownOption<T>[];\n value?: T;\n defaultValue?: T;\n onChange?: (value: T) => void;\n /**\n * `field` — form select (Input chrome).\n * `icon` — header language control: 30×30 panel button + flag menu.\n * `selector` — filter [+] : multi-select, kit Checkbox, OK.\n * `context` — portal at `anchor`. Host opens it from `onContextMenu`.\n */\n variant?: DropdownVariant;\n /** Checked keys (`selector`). */\n selected?: readonly T[];\n defaultSelected?: readonly T[];\n onSelectedChange?: (selected: T[]) => void;\n /** Caption above the field. Omit for a bare trigger. */\n label?: ReactNode;\n /** Stretch to the parent. Default hugs the selected label. */\n fullWidth?: boolean;\n /** Fixed width (px if number). Omit for content width. */\n width?: number | string;\n disabled?: boolean;\n className?: string;\n id?: string;\n 'aria-label'?: string;\n /** Pointer (`variant=\"context\"`). `null` / omit — closed. */\n anchor?: { x: number; y: number } | null;\n /** Backdrop, Escape, pick (`variant=\"context\"`). */\n onClose?: () => void;\n}\n\n/** Form select, header language icon, filter [+], or a right-click menu. */\nexport function Dropdown<T extends string = string>({\n options,\n value,\n defaultValue,\n onChange,\n variant = 'field',\n selected,\n defaultSelected,\n onSelectedChange,\n label,\n fullWidth = false,\n width,\n disabled = false,\n className,\n id,\n 'aria-label': ariaLabel,\n anchor,\n onClose,\n}: DropdownProps<T>) {\n const generatedId = useId();\n const inputId = id ?? generatedId;\n const listId = `${inputId}-list`;\n const controlled = value !== undefined;\n const [inner, setInner] = useState<T>(\n () => (defaultValue ?? options[0]?.value ?? ('' as T)),\n );\n const current = controlled ? value : inner;\n\n const rootRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLElement>(null);\n const closeTimer = useRef<number | null>(null);\n\n const [present, setPresent] = useState(false);\n const [open, setOpen] = useState(false);\n const [activeIdx, setActiveIdx] = useState(-1);\n const [menuBox, setMenuBox] = useState<{ top: number; left: number; width: number } | null>(\n null,\n );\n\n const isIcon = variant === 'icon';\n const isSelector = variant === 'selector';\n const isContext = variant === 'context';\n const isFlyout = isIcon || isSelector;\n const pointRef = useRef<{ x: number; y: number } | null>(null);\n const currentOpt = options.find((opt) => opt.value === current) ?? options[0];\n const selectedIdx = Math.max(\n 0,\n options.findIndex((opt) => opt.value === current),\n );\n const selectedCtrl = selected !== undefined;\n const [innerSelected, setInnerSelected] = useState<T[]>(() => [...(defaultSelected ?? [])]);\n const picked = new Set(selectedCtrl ? selected : innerSelected);\n\n const placeMenu = (menu?: HTMLElement | null) => {\n const node = menu === undefined ? menuRef.current : menu;\n if (isContext) {\n const p = pointRef.current;\n if (!p) return;\n const pos = placeFixedPoint(p.x, p.y, node);\n setMenuBox((cur) => {\n const next = { ...pos, width: 0 };\n if (cur && cur.top === next.top && cur.left === next.left && cur.width === next.width) {\n return cur;\n }\n return next;\n });\n return;\n }\n const el = triggerRef.current;\n if (!el) return;\n const r = el.getBoundingClientRect();\n const pos = placeFixedMenu(r, node, isIcon ? 6 : 4);\n setMenuBox((cur) => {\n const next = { ...pos, width: r.width };\n if (cur && cur.top === next.top && cur.left === next.left && cur.width === next.width) {\n return cur;\n }\n return next;\n });\n };\n\n const menuCallbackRef = (node: HTMLElement | null) => {\n menuRef.current = node;\n if (node) placeMenu(node);\n };\n\n const openMenu = () => {\n if (disabled) return;\n if (closeTimer.current != null) {\n window.clearTimeout(closeTimer.current);\n closeTimer.current = null;\n }\n placeMenu();\n setPresent(true);\n setActiveIdx(isContext ? 0 : selectedIdx);\n if (isFlyout) {\n setOpen(true);\n return;\n }\n requestAnimationFrame(() => setOpen(true));\n };\n\n const closeMenu = () => {\n if (isContext) {\n onClose?.();\n return;\n }\n setOpen(false);\n if (isFlyout) {\n setPresent(false);\n setMenuBox(null);\n return;\n }\n if (closeTimer.current != null) window.clearTimeout(closeTimer.current);\n closeTimer.current = window.setTimeout(() => {\n setPresent(false);\n setMenuBox(null);\n closeTimer.current = null;\n }, CLOSE_MS);\n };\n\n // TODO: `variant=\"context\"` mirrors the `anchor` prop into open/present/position state so the\n // CLOSE_MS exit animation can outlive the prop. Deriving it instead means lifting that timer\n // out of the component — tracked separately; suppressed here rather than half-refactored.\n /* eslint-disable react-hooks/set-state-in-effect */\n useLayoutEffect(() => {\n if (!isContext) return;\n if (anchor) {\n pointRef.current = { x: anchor.x, y: anchor.y };\n if (closeTimer.current != null) {\n window.clearTimeout(closeTimer.current);\n closeTimer.current = null;\n }\n setActiveIdx(0);\n setPresent(true);\n setOpen(true);\n placeMenu();\n return;\n }\n setOpen(false);\n setPresent(false);\n setMenuBox(null);\n pointRef.current = null;\n }, [isContext, anchor]);\n /* eslint-enable react-hooks/set-state-in-effect */\n\n useLayoutEffect(() => {\n if (!present || isContext) return;\n placeMenu();\n }, [present, isIcon, isSelector]);\n\n useEffect(() => {\n if (!present) return;\n const onDoc = (e: MouseEvent) => {\n const t = e.target as Node;\n if (rootRef.current?.contains(t)) return;\n if (menuRef.current?.contains(t)) return;\n closeMenu();\n };\n const onReposition = () => placeMenu();\n document.addEventListener('mousedown', onDoc);\n window.addEventListener('resize', onReposition);\n window.addEventListener('scroll', onReposition, true);\n return () => {\n document.removeEventListener('mousedown', onDoc);\n window.removeEventListener('resize', onReposition);\n window.removeEventListener('scroll', onReposition, true);\n };\n }, [present]);\n\n useEffect(\n () => () => {\n if (closeTimer.current != null) window.clearTimeout(closeTimer.current);\n },\n [],\n );\n\n const pick = (next: T) => {\n if (!isContext && !controlled) setInner(next);\n onChange?.(next);\n closeMenu();\n if (!isContext) triggerRef.current?.focus();\n };\n\n const toggle = (key: T) => {\n const cur = [...(selected ?? innerSelected)];\n const next = picked.has(key) ? cur.filter((v) => v !== key) : [...cur, key];\n if (!selectedCtrl) setInnerSelected(next);\n onSelectedChange?.(next);\n };\n\n const onTriggerKey = (e: ReactKeyboardEvent<HTMLButtonElement>) => {\n if (disabled) return;\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n if (!open) {\n openMenu();\n return;\n }\n if (e.key === 'Enter' || e.key === ' ') {\n const opt = options[activeIdx];\n if (!opt) return;\n if (isSelector) toggle(opt.value);\n else pick(opt.value);\n } else {\n setActiveIdx((i) => Math.min(options.length - 1, (i < 0 ? selectedIdx : i) + 1));\n }\n } else if (e.key === 'Escape' && present) {\n e.preventDefault();\n closeMenu();\n } else if (open && e.key === 'ArrowUp') {\n e.preventDefault();\n setActiveIdx((i) => Math.max(0, (i < 0 ? selectedIdx : i) - 1));\n }\n };\n\n useEffect(() => {\n if (!open) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n closeMenu();\n return;\n }\n if (!isContext) return;\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setActiveIdx((i) => Math.min(options.length - 1, (i < 0 ? 0 : i) + 1));\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n setActiveIdx((i) => Math.max(0, (i < 0 ? 0 : i) - 1));\n } else if (e.key === 'Enter') {\n e.preventDefault();\n const opt = options[activeIdx];\n if (opt) pick(opt.value);\n }\n };\n document.addEventListener('keydown', onKey, true);\n return () => document.removeEventListener('keydown', onKey, true);\n }, [open, isContext, activeIdx, options]);\n\n const optionRows = options.map((opt, i) => {\n const isOn = isSelector ? picked.has(opt.value) : !isContext && opt.value === current;\n const isActive = i === activeIdx;\n const optId = `${listId}-opt-${i}`;\n if (isSelector) {\n return (\n <li\n key={opt.value === '' ? `__empty-${i}` : opt.value}\n role=\"option\"\n aria-selected={isOn}\n onMouseEnter={() => setActiveIdx(i)}\n >\n <Checkbox\n id={optId}\n checked={isOn}\n label={opt.label}\n className={[styles.selectorOption, isActive ? styles.selectorOptionActive : '']\n .filter(Boolean)\n .join(' ')}\n onChange={() => toggle(opt.value)}\n />\n </li>\n );\n }\n if (isContext) {\n return (\n <li key={opt.value === '' ? `__empty-${i}` : opt.value} role=\"presentation\">\n <button\n type=\"button\"\n id={optId}\n role=\"menuitem\"\n className={[\n styles.contextOption,\n opt.danger ? styles.contextDanger : '',\n isActive ? styles.contextOptionActive : '',\n ]\n .filter(Boolean)\n .join(' ')}\n onMouseEnter={() => setActiveIdx(i)}\n onClick={() => pick(opt.value)}\n >\n {opt.icon ? <span className={styles.contextIcon}>{opt.icon}</span> : null}\n {opt.label}\n </button>\n </li>\n );\n }\n return (\n <li key={opt.value === '' ? `__empty-${i}` : opt.value} role=\"presentation\">\n <button\n type=\"button\"\n id={optId}\n role=\"option\"\n aria-selected={isOn}\n className={[\n isIcon ? styles.iconOption : styles.option,\n isOn ? (isIcon ? styles.iconOptionSelected : styles.optionSelected) : '',\n isActive ? (isIcon ? styles.iconOptionActive : styles.optionActive) : '',\n ]\n .filter(Boolean)\n .join(' ')}\n onMouseEnter={() => setActiveIdx(i)}\n onClick={() => pick(opt.value)}\n >\n {isIcon ? (\n <>\n {opt.icon ? <span className={styles.flagIcon}>{opt.icon}</span> : null}\n <span className={styles.iconLabel}>{opt.label}</span>\n </>\n ) : (\n opt.label\n )}\n </button>\n </li>\n );\n });\n\n const trigger = (\n <button\n ref={triggerRef}\n type=\"button\"\n id={inputId}\n className={\n isSelector\n ? [\n styles.iconTrigger,\n styles.selectorTrigger,\n open ? styles.selectorTriggerOpen : '',\n ]\n .filter(Boolean)\n .join(' ')\n : isIcon\n ? styles.iconTrigger\n : [styles.trigger, open ? styles.triggerOpen : ''].filter(Boolean).join(' ')\n }\n disabled={disabled}\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-controls={present ? listId : undefined}\n aria-label={ariaLabel}\n onClick={() => (open ? closeMenu() : openMenu())}\n onKeyDown={onTriggerKey}\n >\n {isSelector ? (\n <PlusIcon size={16} />\n ) : isIcon ? (\n currentOpt?.icon ? <span className={styles.flagIcon}>{currentOpt.icon}</span> : null\n ) : (\n <>\n <span className={styles.value}>{currentOpt?.label ?? ''}</span>\n {open ? (\n <ArrowDropUpIcon className={styles.caret} size={18} />\n ) : (\n <ArrowDropDownIcon className={styles.caret} size={18} />\n )}\n </>\n )}\n </button>\n );\n\n const listProps = {\n id: listId,\n role: (isContext ? 'menu' : 'listbox') as 'menu' | 'listbox',\n 'aria-activedescendant': activeIdx >= 0 ? `${listId}-opt-${activeIdx}` : undefined,\n };\n\n const menu =\n present &&\n menuBox &&\n createPortal(\n isSelector ? (\n <div\n ref={menuCallbackRef}\n className={styles.selectorMenu}\n style={{ position: 'fixed', top: menuBox.top, left: menuBox.left }}\n >\n <ul className={styles.selectorList} {...listProps}>\n {optionRows}\n </ul>\n <div className={styles.selectorFooter}>\n <button type=\"button\" className={styles.selectorOk} onClick={closeMenu}>\n OK\n </button>\n </div>\n </div>\n ) : (\n <ul\n ref={menuCallbackRef}\n className={\n isContext\n ? styles.contextMenu\n : isIcon\n ? styles.iconMenu\n : [styles.menu, open ? styles.menuOpen : ''].filter(Boolean).join(' ')\n }\n style={\n isContext || isIcon\n ? { position: 'fixed', top: menuBox.top, left: menuBox.left }\n : {\n position: 'fixed',\n top: menuBox.top,\n left: menuBox.left,\n minWidth: menuBox.width,\n width: fullWidth || width != null ? menuBox.width : 'max-content',\n }\n }\n {...listProps}\n >\n {optionRows}\n </ul>\n ),\n document.body,\n );\n\n const tip = isSelector ? ariaLabel : isIcon ? currentOpt?.label : undefined;\n\n const backdrop =\n isContext &&\n present &&\n createPortal(\n <div\n // Pointer-only dismiss surface; keyboard users close with Escape, so keep it\n // out of the accessibility tree instead of giving it a role and tab stop.\n role=\"presentation\"\n className={styles.contextBackdrop}\n onClick={closeMenu}\n onContextMenu={(e) => {\n e.preventDefault();\n closeMenu();\n }}\n />,\n document.body,\n );\n\n if (isContext) {\n if (!anchor) return null;\n return (\n <>\n {backdrop}\n {menu}\n </>\n );\n }\n\n return (\n <FieldCaption label={label} htmlFor={inputId} fullWidth={!isFlyout && fullWidth}>\n <div\n ref={rootRef}\n className={[\n styles.root,\n isFlyout ? styles.iconRoot : '',\n !isFlyout && (fullWidth || width != null) ? styles.fill : '',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n style={\n isFlyout || width == null\n ? undefined\n : { width: typeof width === 'number' ? `${width}px` : width }\n }\n >\n {tip ? <Tip content={tip}>{trigger}</Tip> : trigger}\n {menu}\n </div>\n </FieldCaption>\n );\n}\n","import type { ReactNode } from 'react';\n\n/** Option in a chip popover. */\nexport interface FilterOption {\n id: string;\n label: string;\n /** Extra count on the right (selected instruments, members). */\n count?: number;\n disabled?: boolean;\n /** Tip — why disabled, etc. */\n title?: string;\n /** Leading glyph. */\n icon?: ReactNode;\n}\n\n/** Radio group under the options. */\nexport interface FilterRadioGroup {\n label: string;\n options: FilterOption[];\n selected: string;\n onChange: (id: string) => void;\n}\n\n/**\n * One chip. The bar does not know about stores or hosts — bind through this spec.\n */\nexport interface FilterSpec {\n key: string;\n name: string;\n /** `single` — radio, closes on pick. `multi` — checkboxes. */\n mode: 'single' | 'multi';\n options: FilterOption[];\n /** Selected ids. Empty id `''` is neutral (no chip value). */\n selected: string[];\n onChange: (selected: string[]) => void;\n /** Multi: master «All» + divider. */\n masterAll?: boolean;\n applyScope?: FilterRadioGroup;\n /**\n * × removes the chip immediately.\n * Empty `options` and no `content` — tag chip, no popover.\n */\n removeOnly?: boolean;\n /** Always shown; × only resets. */\n pinned?: boolean;\n /** Override chip value text. */\n summary?: string;\n /** When set, first × uses this instead of «no summary». */\n atDefault?: boolean;\n onReset?: () => void;\n /** Custom popover body. */\n content?: ReactNode;\n footerActions?: { label: string; onClick: () => void }[];\n optionActions?: Record<string, { label: string; title?: string; onClick: () => void }>;\n}\n\n/** Row in the [+] menu. */\nexport interface FilterMenuItem {\n key: string;\n name: string;\n}\n\nexport function isTagChip(spec: FilterSpec): boolean {\n return Boolean(spec.removeOnly && spec.options.length === 0 && spec.content == null);\n}\n\nexport function summarize(spec: FilterSpec): string | undefined {\n if (spec.summary !== undefined) {\n return spec.summary === '' ? undefined : spec.summary;\n }\n const labels = spec.selected\n .filter((id) => id !== '')\n .map((id) => spec.options.find((o) => o.id === id)?.label ?? id);\n const scope = spec.applyScope;\n if (scope && scope.selected !== scope.options[0]?.id) {\n const scopeLabel = scope.options.find((o) => o.id === scope.selected)?.label;\n if (scopeLabel) labels.push(scopeLabel);\n }\n return labels.length > 0 ? labels.join(', ') : undefined;\n}\n\nexport function isSpecAtDefault(spec: FilterSpec): boolean {\n if (spec.atDefault !== undefined) return spec.atDefault;\n return summarize(spec) === undefined;\n}\n\nexport function resetSpec(spec: FilterSpec): void {\n if (spec.onReset) {\n spec.onReset();\n return;\n }\n spec.onChange([]);\n if (spec.applyScope) {\n const first = spec.applyScope.options[0]?.id;\n if (first !== undefined && spec.applyScope.selected !== first) {\n spec.applyScope.onChange(first);\n }\n }\n}\n",".root {\n display: flex;\n align-items: center;\n gap: var(--sci-spacing-sm);\n flex-wrap: wrap;\n}\n\n.chipWrap {\n position: relative;\n display: inline-flex;\n}\n\n.chip {\n display: inline-flex;\n align-items: center;\n height: 30px;\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-sm);\n background: var(--sci-color-bg-input);\n color: var(--sci-color-text);\n overflow: hidden;\n}\n\n.chipActive {\n border-color: var(--sci-color-accent);\n background: color-mix(in srgb, var(--sci-color-accent) 16%, transparent);\n}\n\n.chipBody {\n display: inline-flex;\n align-items: center;\n align-self: stretch;\n gap: 4px;\n padding: 0 8px 0 10px;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-size: var(--sci-font-size-sm);\n font-weight: 600;\n white-space: nowrap;\n cursor: pointer;\n}\n\n.chipBody:hover {\n background: var(--sci-color-bg-hover);\n}\n\n.chipBodyStatic {\n cursor: default;\n}\n\n.chipBodyStatic:hover {\n background: transparent;\n}\n\n.chipName {\n color: inherit;\n}\n\n.chipValue {\n color: var(--sci-color-text-secondary);\n font-weight: 400;\n max-width: 220px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.caret {\n flex-shrink: 0;\n color: var(--sci-color-text-secondary);\n}\n\n.chipCloseHost {\n align-self: stretch;\n align-items: stretch;\n}\n\n.chipClose {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n height: 100%;\n padding: 0 8px;\n border: 0;\n background: transparent;\n color: var(--sci-color-text-muted);\n cursor: pointer;\n}\n\n.chipClose:hover {\n background: var(--sci-color-bg-hover);\n color: var(--sci-color-text);\n}\n\n.iconBtn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 30px;\n height: 30px;\n padding: 0;\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-sm);\n background: var(--sci-color-bg-input);\n color: var(--sci-color-accent);\n cursor: pointer;\n}\n\n.iconBtn:hover:not(:disabled) {\n border-color: var(--sci-color-border-focus);\n background: var(--sci-color-bg-hover);\n}\n\n.iconBtn:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n.popover {\n z-index: 60;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n min-width: 200px;\n max-height: 60vh;\n overflow-y: auto;\n margin: 0;\n padding: var(--sci-spacing-xs);\n border: 1px solid var(--sci-color-border);\n border-radius: var(--sci-radius-md);\n background: var(--sci-color-bg-panel);\n box-shadow: var(--sci-shadow-md);\n}\n\n.row {\n width: 100%;\n box-sizing: border-box;\n padding: 7px 10px;\n border-radius: var(--sci-radius-sm);\n white-space: nowrap;\n}\n\n.row:hover {\n background: var(--sci-color-bg-hover);\n}\n\n.rowAll {\n font-weight: 600;\n}\n\n.optionRow {\n display: flex;\n align-items: center;\n gap: 4px;\n width: 100%;\n}\n\n.optionRow .row {\n flex: 1;\n min-width: 0;\n}\n\n.optionLabel {\n display: inline-flex;\n align-items: baseline;\n gap: 0.4em;\n min-width: 0;\n}\n\n.optionText {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.count {\n margin-left: auto;\n padding-left: 10px;\n color: var(--sci-color-text-muted);\n font-variant-numeric: tabular-nums;\n}\n\n.divider {\n height: 1px;\n margin: 2px 6px;\n background: var(--sci-color-border);\n}\n\n.optionAction {\n flex: none;\n width: 22px;\n height: 22px;\n padding: 0;\n border: 0;\n border-radius: var(--sci-radius-sm);\n background: transparent;\n color: var(--sci-color-text-muted);\n cursor: pointer;\n}\n\n.optionAction:hover {\n color: var(--sci-color-accent);\n background: color-mix(in srgb, var(--sci-color-accent) 14%, transparent);\n}\n\n.applyScope {\n display: flex;\n flex-direction: column;\n margin-top: var(--sci-spacing-xs);\n padding-top: var(--sci-spacing-xs);\n border-top: 1px solid var(--sci-color-border);\n}\n\n.scopeLabel {\n padding: 4px 10px 2px;\n color: var(--sci-color-text-muted);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n}\n\n.footer {\n display: flex;\n justify-content: flex-end;\n margin-top: 4px;\n padding: 4px 4px 2px;\n border-top: 1px solid var(--sci-color-border);\n}\n\n.footerOk {\n height: 26px;\n padding: 0 12px;\n border-radius: var(--sci-radius-sm);\n border: 1px solid var(--sci-color-accent);\n background: var(--sci-color-accent);\n color: #fff;\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n}\n\n.footerOk:hover {\n background: color-mix(in srgb, var(--sci-color-accent) 85%, #000);\n border-color: color-mix(in srgb, var(--sci-color-accent) 85%, #000);\n}\n\n.empty {\n padding: 7px 10px;\n color: var(--sci-color-text-muted);\n font-size: var(--sci-font-size-sm);\n}\n","import { useEffect, useLayoutEffect, useRef, useState, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n ArrowDropDownIcon,\n ArrowDropUpIcon,\n CloseIcon,\n SettingsIcon,\n} from '../../icons/buttonIcons';\nimport { Checkbox } from '../Checkbox/Checkbox';\nimport { Dropdown } from '../Dropdown/Dropdown';\nimport { Radio } from '../RadioGroup/Radio';\nimport { RadioGroup } from '../RadioGroup/RadioGroup';\nimport { Tip } from '../Tip/Tip';\nimport { placeFixedMenu } from '../../placeFixedMenu';\nimport {\n isSpecAtDefault,\n isTagChip,\n resetSpec,\n summarize,\n type FilterMenuItem,\n type FilterSpec,\n} from './filterModel';\nimport styles from './Filter.module.css';\n\nexport type { FilterMenuItem, FilterOption, FilterRadioGroup, FilterSpec } from './filterModel';\n\nexport interface FilterProps {\n available: readonly FilterMenuItem[];\n /** Keys added via [+], in add order. */\n active: readonly string[];\n specs: Record<string, FilterSpec>;\n /** Always-visible chips. Not cleared by [×]. */\n pinned?: readonly string[];\n onAdd: (key: string) => void;\n onRemove: (key: string) => void;\n onClear: () => void;\n addLabel?: string;\n clearLabel?: string;\n className?: string;\n}\n\n/**\n * Dynamic filter bar: [+] chips [×].\n * First × on a chip resets to default; second × removes it.\n * [×] drops every chip added through [+].\n */\nexport function Filter({\n available,\n active,\n specs,\n pinned = [],\n onAdd,\n onRemove,\n onClear,\n addLabel = 'Add filter',\n clearLabel = 'Clear filters',\n className,\n}: FilterProps) {\n const [openKey, setOpenKey] = useState<string | null>(null);\n const wrapRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const [menuBox, setMenuBox] = useState<{ top: number; left: number } | null>(null);\n\n const placeMenu = (menu?: HTMLElement | null) => {\n const el = wrapRef.current;\n const node = menu === undefined ? menuRef.current : menu;\n if (!el) return;\n const next = placeFixedMenu(el.getBoundingClientRect(), node, 4);\n setMenuBox((cur) => (cur && cur.top === next.top && cur.left === next.left ? cur : next));\n };\n\n const menuCallbackRef = (node: HTMLDivElement | null) => {\n menuRef.current = node;\n if (node) placeMenu(node);\n };\n\n // The popover only renders under `openKey`, so a stale box is never visible: on reopen\n // `menuCallbackRef` repositions it with real dimensions before paint.\n useLayoutEffect(() => {\n if (openKey) placeMenu();\n }, [openKey]);\n\n useEffect(() => {\n if (!openKey) return;\n const onDoc = (e: MouseEvent) => {\n const t = e.target as Node;\n if (wrapRef.current?.contains(t)) return;\n if (menuRef.current?.contains(t)) return;\n setOpenKey(null);\n };\n const onReposition = () => placeMenu();\n document.addEventListener('mousedown', onDoc);\n window.addEventListener('resize', onReposition);\n window.addEventListener('scroll', onReposition, true);\n return () => {\n document.removeEventListener('mousedown', onDoc);\n window.removeEventListener('resize', onReposition);\n window.removeEventListener('scroll', onReposition, true);\n };\n }, [openKey]);\n\n const toggleChip = (key: string) => setOpenKey((cur) => (cur === key ? null : key));\n\n const handleClose = (spec: FilterSpec) => {\n if (spec.removeOnly) {\n if (!spec.pinned) onRemove(spec.key);\n setOpenKey(null);\n return;\n }\n if (!isSpecAtDefault(spec)) {\n resetSpec(spec);\n return;\n }\n if (spec.pinned) return;\n onRemove(spec.key);\n setOpenKey(null);\n };\n\n const chips = [...pinned, ...active.filter((k) => !pinned.includes(k))];\n\n const addOptions = available.map((item) => ({ value: item.key, label: item.name }));\n\n return (\n <div className={[styles.root, className].filter(Boolean).join(' ')}>\n <Dropdown\n variant=\"selector\"\n options={addOptions}\n selected={[...active]}\n onSelectedChange={(next) => {\n for (const key of next) if (!active.includes(key)) onAdd(key);\n for (const key of active) if (!next.includes(key)) onRemove(key);\n }}\n aria-label={addLabel}\n />\n\n {chips.map((key) => {\n const spec = specs[key];\n if (!spec) return null;\n const value = summarize(spec);\n const tagOnly = isTagChip(spec);\n const isOpen = openKey === key;\n const atDefault = isSpecAtDefault(spec);\n const on = Boolean(value) || isOpen || tagOnly;\n const closeTip = spec.pinned\n ? 'Reset filter'\n : spec.removeOnly || tagOnly || atDefault\n ? 'Remove filter'\n : 'Reset filter';\n return (\n <div\n key={key}\n className={styles.chipWrap}\n ref={isOpen ? wrapRef : undefined}\n >\n <div className={[styles.chip, on ? styles.chipActive : ''].filter(Boolean).join(' ')}>\n {tagOnly ? (\n <span className={[styles.chipBody, styles.chipBodyStatic].join(' ')}>\n <span className={styles.chipName}>{spec.name}</span>\n </span>\n ) : (\n <button\n type=\"button\"\n className={styles.chipBody}\n aria-expanded={isOpen}\n onClick={() => toggleChip(key)}\n >\n <span className={styles.chipName}>{spec.name}</span>\n {value ? <span className={styles.chipValue}>: {value}</span> : null}\n {isOpen ? (\n <ArrowDropUpIcon className={styles.caret} size={16} />\n ) : (\n <ArrowDropDownIcon className={styles.caret} size={16} />\n )}\n </button>\n )}\n <Tip content={closeTip} className={styles.chipCloseHost}>\n <button\n type=\"button\"\n className={styles.chipClose}\n aria-label={`${closeTip} «${spec.name}»`}\n onClick={() => handleClose(spec)}\n >\n <CloseIcon size={12} />\n </button>\n </Tip>\n </div>\n </div>\n );\n })}\n\n <Tip content={clearLabel}>\n <button\n type=\"button\"\n className={styles.iconBtn}\n disabled={active.length === 0}\n aria-label={clearLabel}\n onClick={() => {\n onClear();\n setOpenKey(null);\n }}\n >\n <CloseIcon size={16} />\n </button>\n </Tip>\n\n {openKey &&\n menuBox &&\n specs[openKey] &&\n !isTagChip(specs[openKey]) &&\n createPortal(\n <div\n ref={menuCallbackRef}\n className={styles.popover}\n style={{ position: 'fixed', top: menuBox.top, left: menuBox.left }}\n >\n <ChipPopover spec={specs[openKey]} onClose={() => setOpenKey(null)} />\n </div>,\n document.body,\n )}\n </div>\n );\n}\n\nfunction ChipPopover({ spec, onClose }: { spec: FilterSpec; onClose: () => void }) {\n return (\n <>\n {spec.content != null ? (\n spec.content\n ) : spec.mode === 'single' ? (\n <SingleOptions spec={spec} onPick={onClose} />\n ) : (\n <MultiOptions spec={spec} />\n )}\n {spec.applyScope ? <ApplyScope group={spec.applyScope} /> : null}\n {spec.footerActions && spec.footerActions.length > 0 ? (\n <div className={styles.footer}>\n {spec.footerActions.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n className={styles.footerOk}\n onClick={() => {\n onClose();\n action.onClick();\n }}\n >\n {action.label}\n </button>\n ))}\n </div>\n ) : null}\n </>\n );\n}\n\nfunction optionLabel(o: FilterSpec['options'][number]): ReactNode {\n return (\n <span className={styles.optionLabel}>\n {o.icon}\n <span className={styles.optionText}>{o.label}</span>\n {o.count !== undefined ? <span className={styles.count}>{o.count}</span> : null}\n </span>\n );\n}\n\nfunction SingleOptions({ spec, onPick }: { spec: FilterSpec; onPick: () => void }) {\n const current = spec.selected[0] ?? '';\n return (\n <RadioGroup\n value={current}\n onChange={(_, id) => {\n spec.onChange([id]);\n onPick();\n }}\n >\n {spec.options.map((o) => (\n <Tip key={o.id} content={o.title} block>\n <Radio\n value={o.id}\n label={optionLabel(o)}\n disabled={o.disabled}\n className={styles.row}\n />\n </Tip>\n ))}\n </RadioGroup>\n );\n}\n\nfunction MultiOptions({ spec }: { spec: FilterSpec }) {\n const selected = new Set(spec.selected);\n const enabledIds = spec.options.filter((o) => !o.disabled).map((o) => o.id);\n const allChecked = enabledIds.length > 0 && enabledIds.every((id) => selected.has(id));\n const someChecked = enabledIds.some((id) => selected.has(id)) && !allChecked;\n\n return (\n <>\n {spec.masterAll ? (\n <>\n <Checkbox\n checked={allChecked}\n indeterminate={someChecked}\n label=\"All\"\n className={[styles.row, styles.rowAll].join(' ')}\n onChange={() => {\n if (allChecked) {\n spec.onChange(spec.selected.filter((id) => !enabledIds.includes(id)));\n } else {\n const next = new Set(spec.selected);\n for (const id of enabledIds) next.add(id);\n spec.onChange([...next]);\n }\n }}\n />\n <div className={styles.divider} aria-hidden=\"true\" />\n </>\n ) : null}\n {spec.options.map((o) => {\n const action = spec.optionActions?.[o.id];\n return (\n <Tip key={o.id} content={o.title} block>\n <div className={styles.optionRow}>\n <Checkbox\n checked={selected.has(o.id)}\n disabled={o.disabled}\n label={optionLabel(o)}\n className={styles.row}\n onChange={(e) => {\n const next = new Set(selected);\n if (e.target.checked) next.add(o.id);\n else next.delete(o.id);\n spec.onChange([...next]);\n }}\n />\n {action ? (\n <Tip content={action.title ?? action.label}>\n <button\n type=\"button\"\n className={styles.optionAction}\n aria-label={action.label}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n action.onClick();\n }}\n >\n <SettingsIcon size={12} />\n </button>\n </Tip>\n ) : null}\n </div>\n </Tip>\n );\n })}\n </>\n );\n}\n\nfunction ApplyScope({ group }: { group: NonNullable<FilterSpec['applyScope']> }) {\n return (\n <div className={styles.applyScope}>\n <div className={styles.scopeLabel}>{group.label}</div>\n <RadioGroup value={group.selected} onChange={(_, id) => group.onChange(id)}>\n {group.options.map((o) => (\n <Radio key={o.id} value={o.id} label={o.label} className={styles.row} />\n ))}\n </RadioGroup>\n </div>\n );\n}\n","import { useId, useMemo } from 'react';\nimport avatarSvg from './marks/scinverse-avatar.svg?raw';\nimport iconSvg from './marks/scinverse-icon.svg?raw';\nimport logoSvg from './marks/scinverse-logo.svg?raw';\nimport ncSvg from './marks/nc-icon.svg?raw';\nimport ncConnectionSvg from './marks/nc-scinverse-icon.svg?raw';\nimport ohsSvg from './marks/ohs-icon.svg?raw';\nimport ohsConnectionSvg from './marks/ohs-scinverse-icon.svg?raw';\nimport uiKitSvg from './marks/ui-kit-icon.svg?raw';\nimport uiKitConnectionSvg from './marks/ui-kit-scinverse-icon.svg?raw';\nimport { SvgIcon, type SvgIconProps } from './SvgIcon';\n\nexport type BrandMarkProps = Omit<SvgIconProps, 'component' | 'inheritViewBox' | 'children'>;\n\nfunction prefixIds(svg: string, prefix: string): string {\n return svg\n .replace(/id=\"([^\"]+)\"/g, `id=\"${prefix}-$1\"`)\n .replace(/url\\(#([^)]+)\\)/g, `url(#${prefix}-$1)`);\n}\n\nfunction paintCurrentColor(svg: string): string {\n return svg.replace(/(fill|stroke)=\"#000(?:000)?\"/gi, '$1=\"currentColor\"');\n}\n\nfunction markParts(source: string): { viewBox: string; inner: string } {\n const viewBox = source.match(/viewBox=\"([^\"]+)\"/)?.[1] ?? '0 0 64 64';\n const inner = source.replace(/^[\\s\\S]*?<svg[^>]*>/, '').replace(/<\\/svg>\\s*$/, '');\n return { viewBox, inner };\n}\n\n/** Canonical brand SVG. Ink is currentColor; clip and mask ids are unique per instance. */\nfunction BrandMark({ source, title, ...rest }: BrandMarkProps & { source: string }) {\n const prefix = useId().replace(/[^a-zA-Z0-9]/g, '');\n const { viewBox, inner } = useMemo(() => {\n const painted = paintCurrentColor(prefixIds(source, prefix));\n return markParts(painted);\n }, [source, prefix]);\n\n return (\n <SvgIcon viewBox={viewBox} fill=\"currentColor\" title={title} {...rest}>\n <g dangerouslySetInnerHTML={{ __html: inner }} />\n </SvgIcon>\n );\n}\n\n/** Geometric globe. Favicon, tab, small chrome. */\nexport function ScinverseIcon(props: BrandMarkProps) {\n return <BrandMark source={iconSvg} {...props} />;\n}\n\n/** Spatial globe. Header, README, lockup. */\nexport function ScinverseLogo(props: BrandMarkProps) {\n return <BrandMark source={logoSvg} {...props} />;\n}\n\n/** Detailed globe. Org avatar, profile, large circles. No outer ring. */\nexport function ScinverseAvatar(props: BrandMarkProps) {\n return <BrandMark source={avatarSvg} {...props} />;\n}\n\n/** OHS on the Scinverse globe — product lockup in headers. */\nexport function ConnectionOhsIcon(props: BrandMarkProps) {\n return <BrandMark source={ohsConnectionSvg} {...props} />;\n}\n\n/** NC on the Scinverse globe — product lockup in headers. */\nexport function ConnectionNcIcon(props: BrandMarkProps) {\n return <BrandMark source={ncConnectionSvg} {...props} />;\n}\n\n/** UI kit on the Scinverse globe — product lockup in headers. */\nexport function ConnectionUiKitIcon(props: BrandMarkProps) {\n return <BrandMark source={uiKitConnectionSvg} {...props} />;\n}\n\n/** OHS — ring with segment cuts and a bar chart. */\nexport function ServiceOhsIcon(props: BrandMarkProps) {\n return <BrandMark source={ohsSvg} {...props} />;\n}\n\n/** NC — bell in a ring. */\nexport function ServiceNcIcon(props: BrandMarkProps) {\n return <BrandMark source={ncSvg} {...props} />;\n}\n\n/** UI kit — palette. */\nexport function ServiceUiKitIcon(props: BrandMarkProps) {\n return <BrandMark source={uiKitSvg} {...props} />;\n}\n","import { useId, useMemo } from 'react';\nimport deSvg from './flags/de.svg?raw';\nimport enSvg from './flags/en.svg?raw';\nimport esSvg from './flags/es.svg?raw';\nimport frSvg from './flags/fr.svg?raw';\nimport itSvg from './flags/it.svg?raw';\nimport nlSvg from './flags/nl.svg?raw';\nimport ptSvg from './flags/pt.svg?raw';\nimport ruSvg from './flags/ru.svg?raw';\nimport zhSvg from './flags/zh.svg?raw';\nimport { SvgIcon, type SvgIconProps } from './SvgIcon';\n\nexport type FlagIconProps = Omit<SvgIconProps, 'component' | 'inheritViewBox' | 'children'>;\n\nfunction prefixIds(svg: string, prefix: string): string {\n return svg\n .replace(/id=\"([^\"]+)\"/g, `id=\"${prefix}-$1\"`)\n .replace(/url\\(#([^)]+)\\)/g, `url(#${prefix}-$1)`);\n}\n\nfunction markParts(source: string): { viewBox: string; inner: string } {\n const viewBox = source.match(/viewBox=\"([^\"]+)\"/)?.[1] ?? '0 0 512 512';\n const inner = source.replace(/^[\\s\\S]*?<svg[^>]*>/, '').replace(/<\\/svg>\\s*$/, '');\n return { viewBox, inner };\n}\n\n/**\n * Circular Language Icons (country glyphs for locale).\n * Multicolor — keep native fills; mask ids are unique per instance.\n */\nfunction FlagIcon({ source, title, ...rest }: FlagIconProps & { source: string }) {\n const prefix = useId().replace(/[^a-zA-Z0-9]/g, '');\n const { viewBox, inner } = useMemo(() => markParts(prefixIds(source, prefix)), [source, prefix]);\n\n return (\n <SvgIcon viewBox={viewBox} title={title} {...rest}>\n <g dangerouslySetInnerHTML={{ __html: inner }} />\n </SvgIcon>\n );\n}\n\n/** English — circle-flags:gb */\nexport function FlagEnIcon(props: FlagIconProps) {\n return <FlagIcon source={enSvg} {...props} />;\n}\n\n/** French — circle-flags:fr */\nexport function FlagFrIcon(props: FlagIconProps) {\n return <FlagIcon source={frSvg} {...props} />;\n}\n\n/** Russian — circle-flags:ru */\nexport function FlagRuIcon(props: FlagIconProps) {\n return <FlagIcon source={ruSvg} {...props} />;\n}\n\n/** German — circle-flags:de */\nexport function FlagDeIcon(props: FlagIconProps) {\n return <FlagIcon source={deSvg} {...props} />;\n}\n\n/** Italian — circle-flags:it */\nexport function FlagItIcon(props: FlagIconProps) {\n return <FlagIcon source={itSvg} {...props} />;\n}\n\n/** Spanish — circle-flags:es */\nexport function FlagEsIcon(props: FlagIconProps) {\n return <FlagIcon source={esSvg} {...props} />;\n}\n\n/** Portuguese — circle-flags:pt */\nexport function FlagPtIcon(props: FlagIconProps) {\n return <FlagIcon source={ptSvg} {...props} />;\n}\n\n/** Dutch — circle-flags:nl */\nexport function FlagNlIcon(props: FlagIconProps) {\n return <FlagIcon source={nlSvg} {...props} />;\n}\n\n/** Chinese */\nexport function FlagZhIcon(props: FlagIconProps) {\n return <FlagIcon source={zhSvg} {...props} />;\n}\n","import { createSvgIcon } from './createSvgIcon';\n\n/** Venue / exchange — building with columns. */\nexport const ExchangeIcon = createSvgIcon(\n <>\n <path d=\"M3 9.5 12 4l9 5.5\" />\n <path d=\"M4 9.5h16\" />\n <path d=\"M6 9.5v8M10 9.5v8M14 9.5v8M18 9.5v8\" />\n <path d=\"M3.5 20.5h17\" />\n </>,\n 'Exchange',\n);\n\n/** Plug — external integration. */\nexport const IntegrationIcon = createSvgIcon(\n <>\n <path d=\"M9 3v5M15 3v5\" />\n <path d=\"M6 8h12v3a6 6 0 0 1-12 0z\" />\n <path d=\"M12 17v4\" />\n </>,\n 'Integration',\n);\n\n/** Broadcast waves — news. */\nexport const NewsIcon = createSvgIcon(\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M5.472 6L2 12l3.472 6H7.5l-3.472-6L7.5 6zM12 13.5a1.5 1.5 0 1 0 0-3a1.5 1.5 0 0 0 0 3M22 12l-3.472-6H16.5l3.472 6l-3.472 6h2.028zM8.315 8L6 12l2.315 4h2.028l-2.315-4l2.314-4zm10.028 4l-2.315-4H14l2.315 4L14 16h2.028z\"\n />,\n 'News',\n { kind: 'fill' },\n);\n\n/** Stacked hosts — system / infrastructure. */\nexport const SystemIcon = createSvgIcon(\n <>\n <rect x=\"3.5\" y=\"4\" width=\"17\" height=\"7\" rx=\"1.5\" />\n <rect x=\"3.5\" y=\"13\" width=\"17\" height=\"7\" rx=\"1.5\" />\n <path d=\"M7 7.5h.01M7 16.5h.01\" />\n </>,\n 'System',\n);\n\n/** Envelope — messages / incident log. */\nexport const MessagesIcon = createSvgIcon(\n <>\n <rect x=\"3\" y=\"5.5\" width=\"18\" height=\"13\" rx=\"2\" />\n <path d=\"m4 7 8 5.5L20 7\" />\n </>,\n 'Messages',\n);\n\n/** Question in a circle — help. */\nexport const HelpIcon = createSvgIcon(\n <>\n <circle cx=\"12\" cy=\"12\" r=\"9\" />\n <path d=\"M9.2 9.3a2.8 2.8 0 0 1 5.4 1c0 1.9-2.6 2.2-2.6 3.7\" />\n <path d=\"M12 17.3h.01\" />\n </>,\n 'Help',\n);\n\n/** Bell — notifications. */\nexport const BellIcon = createSvgIcon(\n <>\n <path d=\"M18 8.5a6 6 0 0 0-12 0c0 6.5-2.5 8.5-2.5 8.5h17S18 15 18 8.5\" />\n <path d=\"M13.7 20.5a2 2 0 0 1-3.4 0\" />\n </>,\n 'Bell',\n);\n\n/** User avatar. */\nexport const UserIcon = createSvgIcon(\n <>\n <path d=\"M19 20.5v-1.8a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v1.8\" />\n <circle cx=\"12\" cy=\"7.5\" r=\"3.8\" />\n </>,\n 'User',\n);\n","import { createSvgIcon } from './createSvgIcon';\n\nexport const InfoLabelIcon = createSvgIcon(\n <>\n <circle cx=\"12\" cy=\"12\" r=\"8.5\" />\n <path d=\"M12 11v5M12 8h.01\" />\n </>,\n 'InfoLabel',\n);\n\nexport const OkLabelIcon = createSvgIcon(\n <>\n <circle cx=\"12\" cy=\"12\" r=\"8.5\" />\n <path d=\"M8.2 12.3l2.6 2.6 5-5.2\" />\n </>,\n 'OkLabel',\n);\n\nexport const WarnLabelIcon = createSvgIcon(\n <>\n <path d=\"M12 4.2l8.2 14.6H3.8L12 4.2z\" />\n <path d=\"M12 10v4M12 16.6h.01\" />\n </>,\n 'WarnLabel',\n);\n\nexport const ErrorLabelIcon = createSvgIcon(\n <>\n <circle cx=\"12\" cy=\"12\" r=\"8.5\" />\n <path d=\"M9 9l6 6M15 9l-6 6\" />\n </>,\n 'ErrorLabel',\n);\n"],"mappings":"gJAYA,IAAM,EAAY,qBAQZ,GAAA,EAAe,EAAA,cAAA,CAAwC,IAAI,EAEjE,SAAS,GAAyB,CAChC,GAAI,CACF,IAAM,EAAM,aAAa,QAAQ,CAAS,EAC1C,GAAI,IAAQ,SAAW,IAAQ,OAAQ,OAAO,CAChD,MAAQ,CAER,CACA,MAAO,MACT,CAEA,SAAS,EAAW,EAAc,EAAmB,CACnD,EAAK,QAAQ,MAAQ,EACrB,GAAI,CACF,aAAa,QAAQ,EAAW,CAAK,CACvC,MAAQ,CAER,CACF,CAEA,SAAgB,EAAc,CAC5B,WACA,eACA,SAAS,YAMR,CACD,GAAM,CAAC,EAAO,IAAA,EAAiB,EAAA,SAAA,KAAsB,GAAgB,EAAgB,CAAC,EAEhF,GAAA,EAAW,EAAA,YAAA,CACd,GAAgB,CACf,EAAc,CAAI,EACd,IAAW,YAAY,EAAW,EAAM,SAAS,eAAe,CACtE,EACA,CAAC,CAAM,CACT,EAEM,GAAA,EAAc,EAAA,YAAA,KAAkB,CACpC,EAAS,IAAU,OAAS,QAAU,MAAM,CAC9C,EAAG,CAAC,EAAU,CAAK,CAAC,GAEpB,EAAA,EAAA,UAAA,KAAgB,CACV,IAAW,YAAY,EAAW,EAAO,SAAS,eAAe,CACvE,EAAG,CAAC,EAAO,CAAM,CAAC,EAElB,IAAM,GAAA,EAAQ,EAAA,QAAA,MACL,CAAE,QAAO,WAAU,aAAY,GACtC,CAAC,EAAO,EAAU,CAAW,CAC/B,EAYA,OAVI,IAAW,SAEX,EAAA,EAAA,IAAA,CAAC,EAAa,SAAd,CAA8B,QAC5B,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,WAAW,aAAY,EACnC,UACE,CAAA,CACgB,CAAA,GAIpB,EAAA,EAAA,IAAA,CAAC,EAAa,SAAd,CAA8B,QAAQ,UAAgC,CAAA,CAC/E,CAEA,SAAgB,GAA8B,CAC5C,IAAM,GAAA,EAAM,EAAA,WAAA,CAAW,CAAY,EACnC,GAAI,CAAC,EAAK,MAAU,MAAM,4CAA4C,EACtE,OAAO,CACT,CCrDA,IAAa,EAAe,CAC1B,GAAI,GACJ,GAAI,GACJ,GAAI,EACN,EAOa,EAAgE,CAC3E,OAAQ,0BACR,MAAO,gCACP,QAAS,2BACT,QAAS,2BACT,MAAO,yBACP,IAAK,uBACL,KAAM,wBACN,iBAAkB,kCAClB,MAAO,6BACT,EAEM,EAAkB,YAExB,SAAgB,EAAgB,EAAuC,CAErE,OADI,OAAO,GAAS,SAAiB,EAC9B,EAAa,GAAQ,KAC9B,CAEA,SAAgB,EAAiB,EAAuD,CAClF,GAAC,GAAS,IAAU,UAIxB,OAHI,OAAO,UAAU,eAAe,KAAK,EAAgB,CAAK,EACrD,EAAe,GAEjB,CACT,CAEA,SAAgB,EAAQ,CACtB,QAAQ,UACR,OACA,SACA,QACA,UAAW,EAAY,MACvB,iBAAiB,GACjB,UAAU,EACV,YACA,QACA,cACA,WACA,GAAG,GACY,CACf,IAAM,EAAK,EAAgB,CAAI,EACzB,EAAW,EAAiB,CAAK,EAGvC,OACE,EAAA,EAAA,KAAA,CAAC,EAAD,CACE,GAJa,EAAiB,CAAC,EAAI,CAAE,SAAQ,EAK7C,MAAO,EACP,OAAQ,EACR,YAAa,GAAU,EACvB,UAAW,CAAC,cAAe,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAC9D,MAAO,CAAE,MAAO,EAAU,GAAG,CAAM,EACnC,cAAa,IAAQ,IAAA,GACrB,KAAM,EAAQ,MAAQ,IAAA,GACtB,GAAI,EATN,SAAA,CAWG,GAAQ,EAAA,EAAA,IAAA,CAAC,QAAD,CAAA,SAAQ,CAAa,CAAA,EAAI,KACjC,CACQ,GAEf,qSExFA,SAAS,EAAU,EAA6C,CAC9D,OAAO,IAAY,IAAQ,IAAY,UAAY,IAAY,MACjE,CAEA,SAAgB,EAAO,CACrB,UAAU,UACV,OAAO,SACP,QACA,UACA,YACA,OAAO,SACP,QACA,WACA,GAAG,GACW,CACd,IAAM,EACJ,IAAY,YACR,EAAO,UACP,IAAY,QACV,EAAO,MACP,IAAY,QACV,EAAO,MACP,EAAO,QACX,EAAY,IAAS,QAAU,EAAO,MAAQ,IAAS,QAAU,EAAO,MAAQ,KAChF,EAAO,EAAiB,CAAK,EAC7B,EAAS,EAAQ,EACjB,EAAU,EAAU,CAAO,EAC3B,EAAO,IAAY,OACnB,EACJ,EAAS,CAAE,GAAG,EAAQ,qBAAiC,CAAK,EAAI,EAGlE,OACE,EAAA,EAAA,IAAA,CAAC,SAAD,CACQ,OACN,UAAW,CACT,EAAO,KACP,EACA,EACA,EAAS,EAAO,QAAU,KAC1B,EAAW,EAAO,EAAO,YAAc,EAAO,cAAiB,KAC/D,CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,MAAO,EACP,GAAI,EACJ,eAAc,EAAK,kBAAoB,IAAY,IAAA,GAAsB,IAAA,GAAV,GAE9D,UACK,CAAA,CAEZ,qDElEA,SAAgB,EAAM,CAAE,QAAO,WAAU,YAAW,GAAG,GAAoB,CACzE,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,CAAC,EAAO,KAAM,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAAG,GAAI,EAAxE,SAAA,CACG,GAAQ,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAW,EAAO,MAAQ,SAAA,CAAU,CAAA,EAAI,KACpD,CACE,GAET,sKEQA,SAAgB,EAAK,CACnB,OACA,OACA,WAAW,GACX,MACA,YACA,OAAO,SACP,GAAG,GACS,CACZ,OACE,EAAA,EAAA,KAAA,CAAC,SAAD,CACQ,OACN,UAAW,CAAC,EAAO,KAAM,EAAW,EAAO,SAAW,GAAI,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAC7F,eAAc,EAAW,OAAS,IAAA,GAClC,GAAI,EAJN,SAAA,EAME,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAO,KAAxB,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,KAAO,SAAA,CAAW,CAAA,EACzC,GAAQ,KAAqD,MAA9C,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,KAAO,SAAA,CAAW,CAAA,CACtD,CACL,CAAA,EAAA,GAAO,KAAmD,MAA5C,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,IAAM,SAAA,CAAU,CAAA,CACjD,GAEZ,CAEA,SAAgB,EAAQ,CAAE,OAAO,QAAS,SAAuB,CAC/D,OACE,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,UAAW,EAAO,IAClB,MAAO,CAAE,MAAO,EAAe,EAAM,EACrC,aAAY,EACZ,MAAO,CACR,CAAA,CAEL,wLEtCA,SAAgB,GAAM,CACpB,WACA,OAAO,SACP,QACA,QAAQ,QACR,YACA,QACA,GAAG,GACU,CACb,IAAM,EAAY,IAAS,QAAU,EAAO,MAAQ,IAAS,QAAU,EAAO,MAAQ,EAAO,OACvF,EAAO,EAAiB,CAAK,EAC7B,EAAc,OAAO,GAAU,SAC/B,EAAa,EAAc,GAAK,IAAU,UAAY,EAAO,QAAU,EAAO,MACpF,OACE,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,UAAW,CAAC,EAAO,KAAM,EAAW,EAAY,EAAO,EAAO,QAAU,GAAI,CAAS,CAAC,CACnF,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,MAAO,CACL,GAAG,EACH,GAAI,EAAO,CAAG,oBAAgC,CAAK,EAAI,CAAC,EACxD,GAAI,EAAc,CAAE,aAAc,CAAM,EAAI,CAAC,CAC/C,EACA,GAAI,EAEH,UACG,CAAA,CAEV,CCpCA,SAAgB,EACd,EACA,EACA,EAAgC,CAAC,EACM,CACvC,GAAM,CAAE,UAAU,YAAa,OAAO,SAAU,SAAS,KAAQ,EAEjE,SAAS,EAAU,EAAqB,CAYtC,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAkB,UAAS,GAX3B,IAAS,SACL,CACE,KAAM,OACN,OAAQ,eACR,SACA,cAAe,QACf,eAAgB,OAClB,EACA,CAAE,KAAM,cAAwB,EAGS,GAAI,EAC9C,SAAA,CACM,CAAA,CAEb,CAGA,MADA,GAAU,YAAc,GAAG,EAAY,MAChC,CACT,CCpCA,IAAa,GAAW,GACtB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,gBAAkB,CAAA,EAC1B,OACA,CAAE,QAAS,WAAY,CACzB,EAEa,GAAY,GACvB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,SAAW,CAAA,EACnB,QACA,CAAE,QAAS,WAAY,CACzB,EAGa,GAAY,GACvB,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,SAAS,UACT,SAAS,UACT,EAAE,gLACH,CAAA,EACD,QACA,CAAE,KAAM,OAAQ,QAAS,WAAY,CACvC,EAEa,EAAY,GAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,sBAAwB,CAAA,EAAG,OAAO,EAGpE,EAAa,GACxB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,kDAAoD,CAAA,EAC5D,SACA,CAAE,QAAS,YAAa,OAAQ,GAAI,CACtC,EAGa,EAAU,GACrB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,4UAA8U,CAAA,EACtV,MACA,CAAE,KAAM,OAAQ,QAAS,aAAc,CACzC,EAGa,EAAe,GAC1B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,iuBAAmuB,CAAA,EAC3uB,WACA,CAAE,KAAM,OAAQ,QAAS,aAAc,CACzC,EAEa,EAAY,GAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,wBAA0B,CAAA,EAAG,OAAO,EAEtE,EAAkB,GAAc,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,cAAgB,CAAA,EAAG,aAAa,EAGxE,GAAoB,GAC/B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,gBAAkB,CAAA,EAC1B,gBACA,CAAE,KAAM,MAAO,CACjB,EAGa,GAAkB,GAC7B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,gBAAkB,CAAA,EAC1B,cACA,CAAE,KAAM,MAAO,CACjB,EAGa,EAAU,GACrB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,GAAG,KAAK,GAAG,KAAK,EAAE,KAAO,CAAA,GACjC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,0FAA4F,CAAA,CACpG,CAAA,CAAA,EACF,KACF,EAGa,EAAW,GACtB,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,uDACX,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,ggBAAkgB,CAAA,CACzgB,CAAA,EACH,OACA,CAAE,KAAM,OAAQ,QAAS,aAAc,CACzC,EAGa,EAAa,GACxB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,yCAA2C,CAAA,GACnD,EAAA,EAAA,IAAA,CAAC,WAAD,CAAU,OAAO,kBAAoB,CAAA,GACrC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAM,CAAA,CACtC,CAAA,CAAA,EACF,QACF,EAGa,EAAa,GACxB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,UAAY,CAAA,GACpB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,8CAAgD,CAAA,CACxD,CAAA,CAAA,EACF,QACF,EAGa,EAAe,GAC1B,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,GAAG,KAAK,GAAG,KAAK,EAAE,GAAK,CAAA,GAC/B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,gnBAAknB,CAAA,CAC1nB,CAAA,CAAA,EACF,UACF,EAGa,EAAc,GACzB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,qvBAAuvB,CAAA,EAC/vB,UACA,CAAE,KAAM,MAAO,CACjB,EAGa,EAAc,GACzB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,gBAAgB,KAAK,EAAE,6BAA7B,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,UAAD,CAAS,KAAK,SAAS,cAAc,oBAAoB,IAAI,OAAO,OAAO,MAAQ,CAAA,GACnF,EAAA,EAAA,IAAA,CAAC,mBAAD,CACE,cAAc,YACd,IAAI,OACJ,YAAY,aACZ,KAAK,SACL,OAAO,mBACR,CAAA,CACG,CACN,CAAA,GAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,gBAAgB,KAChB,EAAE,8FACF,QAAS,GAET,UAAA,EAAA,EAAA,IAAA,CAAC,UAAD,CAAS,KAAK,SAAS,cAAc,oBAAoB,IAAI,OAAO,OAAO,MAAQ,CAAA,CAC/E,CAAA,CACN,CAAA,CAAA,EACF,UACA,CAAE,KAAM,SAAU,OAAQ,IAAK,CACjC,iME3HA,SAAgB,GAAS,CACvB,QACA,OAAO,SACP,QACA,YACA,KACA,QACA,gBAAgB,GAChB,GAAG,GACa,CAChB,IAAM,GAAA,EAAW,EAAA,OAAA,CAAyB,IAAI,EACxC,EAAU,IAAO,OAAO,GAAU,SAAW,UAAU,IAAU,IAAA,IACjE,EAAY,IAAS,QAAU,EAAO,MAAQ,IAAS,QAAU,EAAO,MAAQ,KAChF,EAAO,EAAiB,CAAK,EAC7B,EAAS,EAAQ,EACjB,EACJ,EAAS,CAAE,GAAG,EAAQ,uBAAmC,CAAK,EAAI,EAOpE,OAJA,EAAA,EAAA,UAAA,KAAgB,CACV,EAAS,UAAS,EAAS,QAAQ,cAAgB,EACzD,EAAG,CAAC,CAAa,CAAC,GAGhB,EAAA,EAAA,KAAA,CAAC,QAAD,CACE,UAAW,CAAC,EAAO,KAAM,EAAW,EAAS,EAAO,QAAU,KAAM,CAAS,CAAC,CAC3E,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,QAAS,EACT,MAAO,EALT,SAAA,EAOE,EAAA,EAAA,IAAA,CAAC,QAAD,CAAO,IAAK,EAAU,GAAI,EAAS,KAAK,WAAW,UAAW,EAAO,MAAO,GAAI,CAAO,CAAA,GACvF,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,IAAK,cAAY,OACvC,UAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,UAAW,EAAO,KAAM,OAAQ,GAAM,CAAA,CAC7C,CAAA,EACL,GAAS,KAAuD,MAAhD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,CAAY,CAAA,CACxD,GAEX,+GElBM,EAAW,EAEjB,SAAS,EAAkB,EAA4B,CAErD,GADI,aAAgB,mBAAqB,EAAK,UAC1C,EAAK,aAAa,eAAe,IAAM,OAAQ,MAAO,GAC1D,IAAM,EAAU,EAAK,cAAc,iCAAiC,EAIpE,MADA,GAFI,aAAmB,mBAAqB,EAAQ,UAChD,GAAS,aAAa,eAAe,IAAM,QAC3C,aAAmB,kBAAoB,EAAQ,SAErD,CAEA,SAAS,GAAa,EAAiB,EAAkB,EAAwB,CAC/E,IAAM,EAAO,EAAW,EAClB,EAAM,EAAM,KAAO,EAAW,EAC9B,EAAM,EAAM,MAAQ,EAAW,EAErC,OADI,EAAM,GAAa,EAAM,KAAO,EAAM,OAAS,EAC5C,KAAK,IAAI,KAAK,IAAI,EAAS,CAAG,EAAG,CAAG,CAC7C,CAEA,SAAS,GAAY,EAAiB,EAAkB,EAAwB,CAC9E,OAAO,KAAK,MAAM,GAAa,EAAS,EAAU,CAAK,EAAI,EAAW,CAAC,CACzE,CAGA,SAAS,GAAW,EAAmB,EAAa,EAAY,EAAY,EAAW,CAErF,OAD8B,KAAK,MAA/B,IAAS,SAA4B,EAAY,EACnC,EAAY,EAAM,CADoB,CAE1D,CAEA,SAAS,IAAyB,CAChC,MAAO,CACL,KAAM,EACN,MAAO,OAAO,WACd,IAAK,EACL,OAAQ,OAAO,YACf,MAAO,OAAO,WACd,OAAQ,OAAO,YACf,EAAG,EACH,EAAG,EACH,YAAe,CAAC,EAClB,CACF,CAOA,SAAgB,EAAI,CAAE,UAAS,OAAO,SAAU,QAAQ,GAAO,cAAa,YAAW,YAAsB,CAC3G,IAAM,GAAA,EAAQ,EAAA,MAAA,CAAM,EACd,GAAA,EAAS,EAAA,OAAA,CAAwB,IAAI,EACrC,CAAC,EAAK,IAAA,EAAU,EAAA,SAAA,CAAqB,IAAI,EAEzC,GAAA,EAAO,EAAA,YAAA,KAAkB,EAAO,IAAI,EAAG,CAAC,CAAC,EAEzC,GAAA,EAAW,EAAA,YAAA,CACd,GAAoB,CACnB,GAAI,CAAC,GAAW,EAAkB,CAAE,EAClC,OAEF,IAAM,EAAO,EAAG,sBAAsB,EAGhC,EAAQ,GAAa,SAAS,sBAAsB,GAAK,GAAc,EAEzE,EAAW,EACX,EAAU,IAAS,SAAW,EAAK,OAAS,EAAK,IAEjD,IAAS,UAAY,EAAM,OAAS,EAAK,OAAS,IACpD,EAAW,MACX,EAAU,EAAK,KACN,IAAS,OAAS,EAAK,IAAM,EAAM,IAAM,KAClD,EAAW,SACX,EAAU,EAAK,QAGjB,IAAM,EAAU,EAAK,KAAO,EAAK,MAAQ,EACnC,EAAS,KAAK,IAAI,IAAK,KAAK,IAAI,GAAI,EAAQ,OAAS,CAAC,CAAC,EAE7D,EAAO,CACL,KAAM,GAAY,EAAS,EAAQ,CAAK,EAExC,IAAK,GAAW,EAAS,EAAK,EAAU,IAAa,MAAQ,GAAc,CAAC,EAC5E,KAAM,EACN,UACA,UACA,KACF,CAAC,CACH,EACA,CAAC,EAAa,EAAS,CAAI,CAC7B,EAkBA,OAhBA,EAAA,EAAA,gBAAA,KAAsB,CACpB,GAAI,CAAC,GAAO,CAAC,EAAO,QAAS,OAC7B,IAAM,EAAO,EAAO,QAAQ,YACtB,EAAO,EAAO,QAAQ,aACtB,EAAQ,GAAa,SAAS,sBAAsB,GAAK,GAAc,EACvE,EAAW,GAAY,EAAI,QAAS,EAAM,CAAK,EAC/C,EAAU,GAAW,EAAI,QAAS,EAAI,IAAK,EAAI,KAAM,CAAI,GAC3D,IAAa,EAAI,MAAQ,IAAY,EAAI,MAC3C,EAAQ,GAAO,GAAI,CAAE,GAAG,EAAG,KAAM,EAAU,IAAK,CAAQ,CAAM,CAElE,EAAG,CAAC,EAAa,CAAG,CAAC,EAEhB,GAKH,EAAA,EAAA,KAAA,CAAC,OAAD,CACE,UAAW,CAAC,EAAO,KAAM,EAAQ,EAAO,UAAY,GAAI,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAC3F,mBAAkB,EAAM,EAAQ,IAAA,GAChC,aAAe,GAAM,EAAS,EAAE,aAAa,EAC7C,aAAc,EACd,QAAU,GAAM,EAAS,EAAE,aAAa,EACxC,OAAQ,EANV,SAAA,CAQG,EACA,IAAA,EACC,EAAA,aAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,IAAK,EACL,GAAI,EACJ,KAAK,UACL,UAAW,EAAO,IAClB,MAAO,CAAE,KAAM,EAAI,KAAM,IAAK,EAAI,GAAI,EAErC,SAAA,CACG,CAAA,EACN,SAAS,IACX,CACE,KA1BC,EAAA,EAAA,IAAA,CAAA,EAAA,SAAA,CAAG,UAAW,CAAA,CA4BzB,CClKA,IAAa,IAAA,EAAoB,EAAA,cAAA,CAA6C,IAAI,6OEOlF,SAAgB,EAAM,CACpB,QACA,KAAM,EACN,MAAO,EACP,YACA,KACA,QACA,KAAM,EACN,SAAU,EACV,QAAS,EACT,QACA,WACA,GAAG,GACU,CACb,IAAM,GAAA,EAAQ,EAAA,WAAA,CAAW,EAAiB,EACpC,EAAO,GAAY,GAAO,MAAQ,SAClC,EAAQ,GAAa,GAAO,MAC5B,EAAW,GAAgB,GAAO,SAClC,EAAO,GAAO,MAAQ,EACtB,EAAU,EAAQ,EAAM,QAAU,OAAO,GAAS,EAAE,EAAI,EACxD,EAAY,IAAS,QAAU,EAAO,MAAQ,IAAS,QAAU,EAAO,MAAQ,KAChF,EAAO,EAAiB,CAAK,EAC7B,EAAS,EAAQ,EACjB,GACJ,EAAS,CAAE,GAAG,EAAQ,oBAAgC,CAAK,EAAI,EAE3D,EAAU,IAAO,OAAO,GAAU,SAAW,aAAa,GAAQ,IAAI,GAAG,IAAU,IAAA,IAEzF,OACE,EAAA,EAAA,KAAA,CAAC,QAAD,CACE,UAAW,CAAC,EAAO,KAAM,EAAW,EAAS,EAAO,QAAU,KAAM,CAAS,CAAC,CAC3E,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,QAAS,EACT,MAAO,GALT,SAAA,EAOE,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,GAAI,EACJ,KAAK,QACL,UAAW,EAAO,MACZ,OACC,QACE,UACC,WACV,SAAU,EAAQ,EAAM,SAAW,EACnC,GAAI,CACL,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,IAAK,cAAY,OACvC,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAO,MAAO,QAAQ,YAAY,UAAU,QAA5D,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,UAAW,EAAO,KAAM,GAAG,KAAK,GAAG,KAAK,EAAE,IAAM,CAAA,GACxD,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,UAAW,EAAO,IAAK,GAAG,KAAK,GAAG,KAAK,EAAE,KAAO,CAAA,CACrD,GACD,CAAA,EACL,GAAS,KAAuD,MAAhD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,CAAY,CAAA,CACxD,GAEX,mHE7CA,SAAgB,EAAW,CACzB,KAAM,EACN,MAAO,EACP,eACA,WACA,cAAc,WACd,WACA,OACA,QACA,QACA,YACA,WACA,aAAc,EACd,GAAG,GACe,CAClB,IAAM,GAAA,EAAW,EAAA,MAAA,CAAM,EACjB,EAAO,GAAY,EACnB,CAAC,EAAc,IAAA,EAAmB,EAAA,SAAA,CAAS,CAAY,EACvD,EAAQ,IAAc,IAAA,GAAwB,EAAZ,EAElC,GAAA,EAAW,EAAA,YAAA,CACd,GAAyC,CACpC,IAAc,IAAA,IAAW,EAAgB,EAAM,OAAO,KAAK,EAC/D,IAAW,EAAO,EAAM,OAAO,KAAK,CACtC,EACA,CAAC,EAAU,CAAS,CACtB,EAEA,OACE,EAAA,EAAA,IAAA,CAAC,GAAkB,SAAnB,CAA4B,MAAO,CAAE,OAAM,QAAO,WAAU,OAAM,QAAO,UAAS,EAChF,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,KAAK,aACL,mBAAkB,EAClB,aAAY,IAAc,OAAO,GAAU,SAAW,EAAQ,IAAA,IAC9D,UAAW,CAAC,EAAO,KAAM,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAC5D,GAAI,EALN,SAAA,CAOG,GAAS,KAAsD,MAA/C,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,OAAS,SAAA,CAAW,CAAA,GAC5D,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,IAAgB,aAAe,EAAO,SAAW,EAAO,SACrE,UACE,CAAA,CACF,GACqB,CAAA,CAEhC,gUEtEA,SAAgB,GAAa,CAC3B,QACA,UACA,YAAY,GACZ,YAOC,CAED,OADI,GAAS,KAAa,GAExB,EAAA,EAAA,KAAA,CAAC,QAAD,CACE,UAAW,CAAC,EAAO,QAAS,EAAY,EAAO,KAAO,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EACzE,UAFX,SAAA,EAIE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,QAAU,SAAA,CAAY,CAAA,EAC7C,CACI,GAEX,CCNA,SAAgB,GAAM,CACpB,YACA,OAAO,OACP,QACA,YAAY,GACZ,UAAU,GACV,WACA,KACA,oBAAoB,gBACpB,oBAAoB,gBACpB,GAAG,GACU,CACb,GAAM,CAAC,EAAU,IAAA,EAAe,EAAA,SAAA,CAAS,EAAK,EACxC,GAAA,EAAc,EAAA,MAAA,CAAM,EACpB,EAAa,IAAS,WACtB,EAAU,IAAO,GAAS,MAAQ,EAAa,EAAc,IAAA,IAG7D,GACJ,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,GAAI,EACJ,KALc,GAAc,EAAW,OAAS,EAMtC,WACV,eAAc,GAAW,IAAA,GACzB,UAAW,CACT,EAAO,MACP,EAAO,MACP,EAAa,EAAO,cAAgB,GACpC,EAAY,EAAO,KAAO,GAC1B,EAAU,EAAO,QAAU,GAC3B,CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,GAAI,CACL,CAAA,EAGG,EAAW,GAGf,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,CAAC,EAAO,aAAc,EAAY,EAAO,KAAO,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAA5F,SAAA,CACG,GACD,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAO,OAClB,aAAY,EAAW,EAAoB,EAC3C,gBAAe,EACf,eAAc,EACJ,WACV,YAAe,EAAa,GAAS,CAAC,CAAI,EAEzC,SAAA,GAAW,EAAA,EAAA,IAAA,CAAC,EAAD,CAAc,KAAM,EAAK,CAAA,GAAI,EAAA,EAAA,IAAA,CAAC,EAAD,CAAS,KAAM,EAAK,CAAA,CACvD,CAAA,CACL,IAfL,EAkBF,OACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAqB,QAAO,QAAS,EAAoB,YACtD,SAAA,CACW,CAAA,CAElB,0JE3DA,SAAS,GAAkB,EAAe,EAAoB,CAC5D,GAAM,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAS,CAAK,EAOhD,OANA,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,GAAM,EAAG,OACb,IAAM,EAAK,OAAO,eAAiB,EAAa,CAAK,EAAG,CAAE,EAC1D,UAAa,OAAO,aAAa,CAAE,CACrC,EAAG,CAAC,EAAO,CAAE,CAAC,EAEP,GAAM,EAAI,EAAQ,CAC3B,CAGA,SAAgB,GAAU,CACxB,YACA,YAAY,GACZ,WACA,WAAW,IACX,aAAa,eACb,QACA,eACA,WACA,WACA,GAAG,GACc,CACjB,IAAM,EAAa,IAAU,IAAA,GACvB,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,KAAe,OAAO,GAAgB,EAAE,CAAC,EAC7D,EAAO,EAAa,OAAO,GAAS,EAAE,EAAI,EAC1C,EAAY,GAAkB,EAAM,CAAQ,EAE5C,GAAA,EAAc,EAAA,OAAA,CAAO,CAAQ,GAEnC,EAAA,EAAA,UAAA,KAAgB,CACd,EAAY,QAAU,CACxB,CAAC,EACD,IAAM,GAAA,EAAW,EAAA,OAAA,CAAO,OAAO,GAAgB,GAAS,EAAE,CAAC,GAE3D,EAAA,EAAA,UAAA,KAAgB,CACT,EAAY,SACb,IAAc,EAAS,UAC3B,EAAS,QAAU,EACnB,EAAY,QAAQ,CAAS,EAC/B,EAAG,CAAC,CAAS,CAAC,EAEd,IAAM,GAAc,EAAc,IAA0C,CAE1E,GADK,GAAY,EAAS,CAAI,EAC1B,EAAO,CACT,IAAW,CAAK,EAChB,MACF,CACA,IAAW,CACT,OAAQ,CAAE,MAAO,CAAK,EACtB,cAAe,CAAE,MAAO,CAAK,CAC/B,CAAkC,CACpC,EAEM,MAAc,CAClB,EAAW,EAAE,EACb,EAAS,QAAU,GACnB,EAAY,UAAU,EAAE,CAC1B,EAEA,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,CAAC,EAAO,KAAM,EAAY,EAAO,KAAO,GAAI,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAA/F,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAY,UAAW,EAAO,KAAM,KAAM,EAAK,CAAA,GAC/C,EAAA,EAAA,IAAA,CAAC,QAAD,CACE,KAAK,OACL,UAAW,CAAC,EAAO,MAAO,GAAQ,CAAC,EAAW,EAAO,UAAY,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAC7F,MAAO,EACG,WACV,SAAW,GAAU,CACd,GAAY,EAAS,EAAM,OAAO,KAAK,EAC5C,IAAW,CAAK,CAClB,EACA,GAAI,CACL,CAAA,EACA,GAAQ,CAAC,GACR,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAO,MAClB,aAAY,EACZ,QAAS,EAET,UAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,KAAM,EAAK,CAAA,CAChB,CAAA,EACN,IACD,GAET,CC9FA,SAAgB,GAAS,CACvB,YACA,QACA,YAAY,GACZ,OAAO,GACP,UAAU,GACV,KACA,GAAG,GACa,CAChB,IAAM,GAAA,EAAc,EAAA,MAAA,CAAM,EACpB,EAAU,IAAO,GAAS,KAAqB,IAAA,GAAd,GAEvC,OACE,EAAA,EAAA,IAAA,CAAC,GAAD,CAAqB,QAAO,QAAS,EAAoB,YACvD,UAAA,EAAA,EAAA,IAAA,CAAC,WAAD,CACE,GAAI,EACJ,eAAc,GAAW,IAAA,GACzB,UAAW,CACT,EAAO,MACP,EAAO,SACP,EAAY,EAAO,KAAO,GAC1B,EAAO,EAAO,KAAO,GACrB,EAAU,EAAO,QAAU,GAC3B,CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,GAAI,CACL,CAAA,CACW,CAAA,CAElB,6VErBA,SAAS,GAAa,EAAkC,EAA6C,CAGnG,OAFI,IACA,EAAgB,SACb,MACT,CAGA,SAAgB,GAAS,CACvB,MAAO,EACP,UACA,QACA,OAAO,SACP,WACA,WACA,YACA,GAAG,GACa,CAChB,IAAM,EAAQ,GAAa,EAAW,CAAO,EACvC,EAAK,IAAU,UAAY,IAAU,WAAa,IAAU,WAC5D,EAAO,IAAU,cAAgB,IAAU,cAC3C,EAAS,GAAY,IAAU,cAErC,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,UAAW,CAAC,EAAO,KAAM,IAAS,QAAU,EAAO,MAAQ,GAAI,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EADpG,SAAA,CAGG,GAAS,KAAuD,MAAhD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,CAAY,CAAA,GAC7D,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,KAAK,SACL,eAAc,GAAM,EACpB,YAAW,GAAQ,IAAA,GACT,WACV,UAAW,CAAC,EAAO,MAAO,EAAO,EAAM,CAAC,CAAC,KAAK,GAAG,EACjD,GAAI,EACJ,YAAe,CACT,GACJ,IAAW,CACb,EAEA,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,KAAO,SAAA,GAAM,EAAO,GAAK,GAAU,CAAA,CACrD,CAAA,CACL,GAET,CCrEA,SAAgB,GACd,EACA,EACA,EAC+B,CAC/B,OAAO,GAAe,IAAI,QAAQ,EAAG,EAAG,EAAG,CAAC,EAAG,EAAM,CAAC,CACxD,CAGA,SAAgB,GACd,EACA,EACA,EAC+B,CAC/B,IACM,EAAK,OAAO,YACZ,EAAK,OAAO,WACZ,EAAQ,GAAM,cAAgB,EAC9B,EAAQ,GAAM,aAAe,EAE/B,EAAM,EAAO,OAAS,EACpB,EAAa,EAAK,EAAM,EACxB,EAAa,EAAO,IAAM,EAAM,EAClC,EAAQ,GAAK,EAAa,GAAS,EAAa,EAClD,EAAM,KAAK,IAAI,EAAK,EAAO,IAAM,EAAM,CAAK,EACnC,EAAQ,GAAK,EAAM,EAAQ,EAAK,IACzC,EAAM,KAAK,IAAI,EAAK,EAAK,EAAM,CAAK,GAGtC,IAAI,EAAO,EAAO,KAIlB,OAHI,EAAQ,GAAK,EAAO,EAAQ,EAAK,IACnC,EAAO,KAAK,IAAI,EAAK,EAAK,EAAM,CAAK,GAEhC,CAAE,MAAK,MAAK,CACrB,0sCElBM,GAAW,IA8CjB,SAAgB,GAAoC,CAClD,UACA,QACA,eACA,WACA,UAAU,QACV,WACA,kBACA,mBACA,QACA,YAAY,GACZ,QACA,WAAW,GACX,YACA,KACA,aAAc,EACd,SACA,WACmB,CACnB,IAAM,GAAA,EAAc,EAAA,MAAA,CAAM,EACpB,EAAU,GAAM,EAChB,EAAS,GAAG,EAAQ,OACpB,EAAa,IAAU,IAAA,GACvB,CAAC,GAAO,IAAA,EAAY,EAAA,SAAA,KACjB,GAAgB,EAAQ,EAAE,EAAE,OAAU,EAC/C,EACM,GAAU,EAAa,EAAQ,GAE/B,IAAA,EAAU,EAAA,OAAA,CAAuB,IAAI,EACrC,GAAA,EAAa,EAAA,OAAA,CAA0B,IAAI,EAC3C,GAAA,EAAU,EAAA,OAAA,CAAoB,IAAI,EAClC,GAAA,EAAa,EAAA,OAAA,CAAsB,IAAI,EAEvC,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAS,EAAK,EACtC,CAAC,EAAM,IAAA,EAAW,EAAA,SAAA,CAAS,EAAK,EAChC,CAAC,EAAW,IAAA,EAAgB,EAAA,SAAA,CAAS,EAAE,EACvC,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAC5B,IACF,EAEM,EAAS,IAAY,OACrB,EAAa,IAAY,WACzB,EAAY,IAAY,UACxB,EAAW,GAAU,EACrB,GAAA,EAAW,EAAA,OAAA,CAAwC,IAAI,EACvD,EAAa,EAAQ,KAAM,GAAQ,EAAI,QAAU,EAAO,GAAK,EAAQ,GACrE,GAAc,KAAK,IACvB,EACA,EAAQ,UAAW,GAAQ,EAAI,QAAU,EAAO,CAClD,EACM,GAAe,IAAa,IAAA,GAC5B,CAAC,GAAe,KAAA,EAAoB,EAAA,SAAA,KAAoB,CAAC,GAAI,GAAmB,CAAC,CAAE,CAAC,EACpF,GAAS,IAAI,IAAI,GAAe,EAAW,EAAa,EAExD,EAAa,GAA8B,CAC/C,IAAM,EAAO,IAAS,IAAA,GAAY,EAAQ,QAAU,EACpD,GAAI,EAAW,CACb,IAAM,EAAI,EAAS,QACnB,GAAI,CAAC,EAAG,OACR,IAAM,EAAM,GAAgB,EAAE,EAAG,EAAE,EAAG,CAAI,EAC1C,EAAY,GAAQ,CAClB,IAAM,EAAO,CAAE,GAAG,EAAK,MAAO,CAAE,EAIhC,OAHI,GAAO,EAAI,MAAQ,EAAK,KAAO,EAAI,OAAS,EAAK,MAAQ,EAAI,QAAU,EAAK,MACvE,EAEF,CACT,CAAC,EACD,MACF,CACA,IAAM,EAAK,EAAW,QACtB,GAAI,CAAC,EAAI,OACT,IAAM,EAAI,EAAG,sBAAsB,EAC7B,EAAM,GAAe,EAAG,EAAM,EAAS,EAAI,CAAC,EAClD,EAAY,GAAQ,CAClB,IAAM,EAAO,CAAE,GAAG,EAAK,MAAO,EAAE,KAAM,EAItC,OAHI,GAAO,EAAI,MAAQ,EAAK,KAAO,EAAI,OAAS,EAAK,MAAQ,EAAI,QAAU,EAAK,MACvE,EAEF,CACT,CAAC,CACH,EAEM,EAAmB,GAA6B,CACpD,EAAQ,QAAU,EACd,GAAM,EAAU,CAAI,CAC1B,EAEM,MAAiB,CACjB,MAQJ,IAPI,EAAW,SAAW,OACxB,OAAO,aAAa,EAAW,OAAO,EACtC,EAAW,QAAU,MAEvB,EAAU,EACV,EAAW,EAAI,EACf,EAAa,EAAY,EAAI,EAAW,EACpC,EAAU,CACZ,EAAQ,EAAI,EACZ,MACF,CACA,0BAA4B,EAAQ,EAAI,CAAC,CADzC,CAEF,EAEM,MAAkB,CACtB,GAAI,EAAW,CACb,IAAU,EACV,MACF,CAEA,GADA,EAAQ,EAAK,EACT,EAAU,CACZ,EAAW,EAAK,EAChB,EAAW,IAAI,EACf,MACF,CACI,EAAW,SAAW,MAAM,OAAO,aAAa,EAAW,OAAO,EACtE,EAAW,QAAU,OAAO,eAAiB,CAC3C,EAAW,EAAK,EAChB,EAAW,IAAI,EACf,EAAW,QAAU,IACvB,EAAG,EAAQ,CACb,GAMA,EAAA,EAAA,gBAAA,KAAsB,CACf,KACL,IAAI,EAAQ,CACV,EAAS,QAAU,CAAE,EAAG,EAAO,EAAG,EAAG,EAAO,CAAE,EAC1C,EAAW,SAAW,OACxB,OAAO,aAAa,EAAW,OAAO,EACtC,EAAW,QAAU,MAEvB,EAAa,CAAC,EACd,EAAW,EAAI,EACf,EAAQ,EAAI,EACZ,EAAU,EACV,MACF,CACA,EAAQ,EAAK,EACb,EAAW,EAAK,EAChB,EAAW,IAAI,EACf,EAAS,QAAU,IAJnB,CAKF,EAAG,CAAC,EAAW,CAAM,CAAC,GAGtB,EAAA,EAAA,gBAAA,KAAsB,CACf,GAAW,IAChB,EAAU,CACZ,EAAG,CAAC,EAAS,EAAQ,CAAU,CAAC,GAEhC,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EAAS,OACd,IAAM,EAAS,GAAkB,CAC/B,IAAM,EAAI,EAAE,OACR,GAAQ,SAAS,SAAS,CAAC,GAC3B,EAAQ,SAAS,SAAS,CAAC,GAC/B,EAAU,CACZ,EACM,MAAqB,EAAU,EAIrC,OAHA,SAAS,iBAAiB,YAAa,CAAK,EAC5C,OAAO,iBAAiB,SAAU,CAAY,EAC9C,OAAO,iBAAiB,SAAU,EAAc,EAAI,MACvC,CACX,SAAS,oBAAoB,YAAa,CAAK,EAC/C,OAAO,oBAAoB,SAAU,CAAY,EACjD,OAAO,oBAAoB,SAAU,EAAc,EAAI,CACzD,CACF,EAAG,CAAC,CAAO,CAAC,GAEZ,EAAA,EAAA,UAAA,SACc,CACN,EAAW,SAAW,MAAM,OAAO,aAAa,EAAW,OAAO,CACxE,EACA,CAAC,CACH,EAEA,IAAM,EAAQ,GAAY,CACpB,CAAC,GAAa,CAAC,GAAY,EAAS,CAAI,EAC5C,IAAW,CAAI,EACf,EAAU,EACL,GAAW,EAAW,SAAS,MAAM,CAC5C,EAEM,GAAU,GAAW,CACzB,IAAM,EAAM,CAAC,GAAI,GAAY,EAAc,EACrC,EAAO,GAAO,IAAI,CAAG,EAAI,EAAI,OAAQ,GAAM,IAAM,CAAG,EAAI,CAAC,GAAG,EAAK,CAAG,EACrE,IAAc,GAAiB,CAAI,EACxC,IAAmB,CAAI,CACzB,EAEM,EAAgB,GAA6C,CAC7D,MACJ,IAAI,EAAE,MAAQ,aAAe,EAAE,MAAQ,SAAW,EAAE,MAAQ,IAAK,CAE/D,GADA,EAAE,eAAe,EACb,CAAC,EAAM,CACT,EAAS,EACT,MACF,CACA,GAAI,EAAE,MAAQ,SAAW,EAAE,MAAQ,IAAK,CACtC,IAAM,EAAM,EAAQ,GACpB,GAAI,CAAC,EAAK,OACN,EAAY,GAAO,EAAI,KAAK,EAC3B,EAAK,EAAI,KAAK,CACrB,MACE,EAAc,GAAM,KAAK,IAAI,EAAQ,OAAS,GAAI,EAAI,EAAI,GAAc,GAAK,CAAC,CAAC,CAEnF,MAAW,EAAE,MAAQ,UAAY,GAC/B,EAAE,eAAe,EACjB,EAAU,GACD,GAAQ,EAAE,MAAQ,YAC3B,EAAE,eAAe,EACjB,EAAc,GAAM,KAAK,IAAI,GAAI,EAAI,EAAI,GAAc,GAAK,CAAC,CAAC,EAChE,CACF,GAEA,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EAAM,OACX,IAAM,EAAS,GAAqB,CAClC,GAAI,EAAE,MAAQ,SAAU,CACtB,EAAE,eAAe,EACjB,EAAE,gBAAgB,EAClB,EAAU,EACV,MACF,CACK,KACL,IAAI,EAAE,MAAQ,YACZ,EAAE,eAAe,EACjB,EAAc,GAAM,KAAK,IAAI,EAAQ,OAAS,GAAI,EAAI,EAAI,EAAI,GAAK,CAAC,CAAC,OAChE,GAAI,EAAE,MAAQ,UACnB,EAAE,eAAe,EACjB,EAAc,GAAM,KAAK,IAAI,GAAI,EAAI,EAAI,EAAI,GAAK,CAAC,CAAC,OAC/C,GAAI,EAAE,MAAQ,QAAS,CAC5B,EAAE,eAAe,EACjB,IAAM,EAAM,EAAQ,GAChB,GAAK,EAAK,EAAI,KAAK,CACzB,EACF,EAEA,OADA,SAAS,iBAAiB,UAAW,EAAO,EAAI,MACnC,SAAS,oBAAoB,UAAW,EAAO,EAAI,CAClE,EAAG,CAAC,EAAM,EAAW,EAAW,CAAO,CAAC,EAExC,IAAM,GAAa,EAAQ,KAAK,EAAK,IAAM,CACzC,IAAM,EAAO,EAAa,GAAO,IAAI,EAAI,KAAK,EAAI,CAAC,GAAa,EAAI,QAAU,GACxE,EAAW,IAAM,EACjB,EAAQ,GAAG,EAAO,OAAO,IA4C/B,OA3CI,GAEA,EAAA,EAAA,IAAA,CAAC,KAAD,CAEE,KAAK,SACL,gBAAe,EACf,iBAAoB,EAAa,CAAC,EAElC,UAAA,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,GAAI,EACJ,QAAS,EACT,MAAO,EAAI,MACX,UAAW,CAAC,EAAO,eAAgB,EAAW,EAAO,qBAAuB,EAAE,CAAC,CAC5E,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,aAAgB,GAAO,EAAI,KAAK,CACjC,CAAA,CACC,EAdG,EAAI,QAAU,GAAK,WAAW,IAAM,EAAI,KAc3C,EAGJ,GAEA,EAAA,EAAA,IAAA,CAAC,KAAD,CAAwD,KAAK,eAC3D,UAAA,EAAA,EAAA,KAAA,CAAC,SAAD,CACE,KAAK,SACL,GAAI,EACJ,KAAK,WACL,UAAW,CACT,EAAO,cACP,EAAI,OAAS,EAAO,cAAgB,GACpC,EAAW,EAAO,oBAAsB,EAC1C,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,iBAAoB,EAAa,CAAC,EAClC,YAAe,EAAK,EAAI,KAAK,EAZ/B,SAAA,CAcG,EAAI,MAAO,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,YAAc,SAAA,EAAI,IAAW,CAAA,EAAI,KACpE,EAAI,KACC,GACN,EAlBK,EAAI,QAAU,GAAK,WAAW,IAAM,EAAI,KAkB7C,GAIN,EAAA,EAAA,IAAA,CAAC,KAAD,CAAwD,KAAK,eAC3D,UAAA,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,GAAI,EACJ,KAAK,SACL,gBAAe,EACf,UAAW,CACT,EAAS,EAAO,WAAa,EAAO,OACpC,EAAQ,EAAS,EAAO,mBAAqB,EAAO,eAAkB,GACtE,EAAY,EAAS,EAAO,iBAAmB,EAAO,aAAgB,EACxE,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,iBAAoB,EAAa,CAAC,EAClC,YAAe,EAAK,EAAI,KAAK,EAE5B,SAAA,GACC,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CACG,EAAI,MAAO,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,SAAW,SAAA,EAAI,IAAW,CAAA,EAAI,MAClE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,UAAY,SAAA,EAAI,KAAY,CAAA,CACpD,CAAA,CAAA,EAEF,EAAI,KAEA,CAAA,CACN,EAzBK,EAAI,QAAU,GAAK,WAAW,IAAM,EAAI,KAyB7C,CAER,CAAC,EAEK,IACJ,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,IAAK,EACL,KAAK,SACL,GAAI,EACJ,UACE,EACI,CACE,EAAO,YACP,EAAO,gBACP,EAAO,EAAO,oBAAsB,EACtC,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,EACE,EAAO,YACP,CAAC,EAAO,QAAS,EAAO,EAAO,YAAc,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAEvE,WACV,gBAAc,UACd,gBAAe,EACf,gBAAe,EAAU,EAAS,IAAA,GAClC,aAAY,EACZ,YAAgB,EAAO,EAAU,EAAI,EAAS,EAC9C,UAAW,EAEV,SAAA,GACC,EAAA,EAAA,IAAA,CAAC,GAAD,CAAU,KAAM,EAAK,CAAA,EACnB,EACF,GAAY,MAAO,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,SAAW,SAAA,EAAW,IAAW,CAAA,EAAI,MAEhF,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,GAAY,OAAS,EAAS,CAAA,EAC7D,GACC,EAAA,EAAA,IAAA,CAAC,GAAD,CAAiB,UAAW,EAAO,MAAO,KAAM,EAAK,CAAA,GAErD,EAAA,EAAA,IAAA,CAAC,GAAD,CAAmB,UAAW,EAAO,MAAO,KAAM,EAAK,CAAA,CAEzD,CAAA,CAAA,CAEE,CAAA,EAGJ,GAAY,CAChB,GAAI,EACJ,KAAO,EAAY,OAAS,UAC5B,wBAAyB,GAAa,EAAI,GAAG,EAAO,OAAO,IAAc,IAAA,EAC3E,EAEM,EACJ,GACA,IAAA,EACA,EAAA,aAAA,CACE,GACE,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,IAAK,EACL,UAAW,EAAO,aAClB,MAAO,CAAE,SAAU,QAAS,IAAK,EAAQ,IAAK,KAAM,EAAQ,IAAK,EAHnE,SAAA,EAKE,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAW,EAAO,aAAc,GAAI,GACrC,SAAA,EACC,CAAA,GACJ,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,eACrB,UAAA,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,KAAK,SAAS,UAAW,EAAO,WAAY,QAAS,EAAW,SAAA,IAEhE,CAAA,CACL,CAAA,CACF,CAEL,CAAA,GAAA,EAAA,EAAA,IAAA,CAAC,KAAD,CACE,IAAK,EACL,UACE,EACI,EAAO,YACP,EACE,EAAO,SACP,CAAC,EAAO,KAAM,EAAO,EAAO,SAAW,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAE3E,MACE,GAAa,EACT,CAAE,SAAU,QAAS,IAAK,EAAQ,IAAK,KAAM,EAAQ,IAAK,EAC1D,CACE,SAAU,QACV,IAAK,EAAQ,IACb,KAAM,EAAQ,KACd,SAAU,EAAQ,MAClB,MAAO,GAAa,GAAS,KAAO,EAAQ,MAAQ,aACtD,EAEN,GAAI,GAEH,SAAA,EACC,CAAA,EAEN,SAAS,IACX,EAEI,GAAM,EAAa,EAAY,EAAS,GAAY,MAAQ,IAAA,GAE5D,GACJ,GACA,IAAA,EACA,EAAA,aAAA,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAGE,KAAK,eACL,UAAW,EAAO,gBAClB,QAAS,EACT,cAAgB,GAAM,CACpB,EAAE,eAAe,EACjB,EAAU,CACZ,CACD,CAAA,EACD,SAAS,IACX,EAYF,OAVI,EACG,GAEH,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CACG,GACA,CACD,CAAA,CAAA,EALgB,MAUpB,EAAA,EAAA,IAAA,CAAC,GAAD,CAAqB,QAAO,QAAS,EAAS,UAAW,CAAC,GAAY,EACpE,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,IAAK,GACL,UAAW,CACT,EAAO,KACP,EAAW,EAAO,SAAW,GAC7B,CAAC,IAAa,GAAa,GAAS,MAAQ,EAAO,KAAO,GAC1D,CACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,EACX,MACE,GAAY,GAAS,KACjB,IAAA,GACA,CAAE,MAAO,OAAO,GAAU,SAAW,GAAG,EAAM,IAAM,CAAM,EAblE,SAAA,CAgBG,IAAM,EAAA,EAAA,IAAA,CAAC,EAAD,CAAK,QAAS,GAAM,SAAA,EAAa,CAAA,EAAI,GAC3C,CACE,GACO,CAAA,CAElB,CCvdA,SAAgB,GAAU,EAA2B,CACnD,MAAO,GAAQ,EAAK,YAAc,EAAK,QAAQ,SAAW,GAAK,EAAK,SAAW,KACjF,CAEA,SAAgB,GAAU,EAAsC,CAC9D,GAAI,EAAK,UAAY,IAAA,GACnB,OAAO,EAAK,UAAY,GAAK,IAAA,GAAY,EAAK,QAEhD,IAAM,EAAS,EAAK,SACjB,OAAQ,GAAO,IAAO,EAAE,CAAC,CACzB,IAAK,GAAO,EAAK,QAAQ,KAAM,GAAM,EAAE,KAAO,CAAE,CAAC,EAAE,OAAS,CAAE,EAC3D,EAAQ,EAAK,WACnB,GAAI,GAAS,EAAM,WAAa,EAAM,QAAQ,EAAE,EAAE,GAAI,CACpD,IAAM,EAAa,EAAM,QAAQ,KAAM,GAAM,EAAE,KAAO,EAAM,QAAQ,CAAC,EAAE,MACnE,GAAY,EAAO,KAAK,CAAU,CACxC,CACA,OAAO,EAAO,OAAS,EAAI,EAAO,KAAK,IAAI,EAAI,IAAA,EACjD,CAEA,SAAgB,GAAgB,EAA2B,CAEzD,OADI,EAAK,YAAc,IAAA,GAChB,GAAU,CAAI,IAAM,IAAA,GADc,EAAK,SAEhD,CAEA,SAAgB,GAAU,EAAwB,CAChD,GAAI,EAAK,QAAS,CAChB,EAAK,QAAQ,EACb,MACF,CAEA,GADA,EAAK,SAAS,CAAC,CAAC,EACZ,EAAK,WAAY,CACnB,IAAM,EAAQ,EAAK,WAAW,QAAQ,EAAE,EAAE,GACtC,IAAU,IAAA,IAAa,EAAK,WAAW,WAAa,GACtD,EAAK,WAAW,SAAS,CAAK,CAElC,CACF,gyBEpDA,SAAgB,GAAO,CACrB,YACA,SACA,QACA,SAAS,CAAC,EACV,QACA,WACA,UACA,WAAW,aACX,aAAa,gBACb,aACc,CACd,GAAM,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAAwB,IAAI,EACpD,GAAA,EAAU,EAAA,OAAA,CAAuB,IAAI,EACrC,GAAA,EAAU,EAAA,OAAA,CAAuB,IAAI,EACrC,CAAC,EAAS,IAAA,EAAc,EAAA,SAAA,CAA+C,IAAI,EAE3E,EAAa,GAA8B,CAC/C,IAAM,EAAK,EAAQ,QACb,EAAO,IAAS,IAAA,GAAY,EAAQ,QAAU,EACpD,GAAI,CAAC,EAAI,OACT,IAAM,EAAO,GAAe,EAAG,sBAAsB,EAAG,EAAM,CAAC,EAC/D,EAAY,GAAS,GAAO,EAAI,MAAQ,EAAK,KAAO,EAAI,OAAS,EAAK,KAAO,EAAM,CAAK,CAC1F,EAEM,EAAmB,GAAgC,CACvD,EAAQ,QAAU,EACd,GAAM,EAAU,CAAI,CAC1B,GAIA,EAAA,EAAA,gBAAA,KAAsB,CAChB,GAAS,EAAU,CACzB,EAAG,CAAC,CAAO,CAAC,GAEZ,EAAA,EAAA,UAAA,KAAgB,CACd,GAAI,CAAC,EAAS,OACd,IAAM,EAAS,GAAkB,CAC/B,IAAM,EAAI,EAAE,OACR,EAAQ,SAAS,SAAS,CAAC,GAC3B,EAAQ,SAAS,SAAS,CAAC,GAC/B,EAAW,IAAI,CACjB,EACM,MAAqB,EAAU,EAIrC,OAHA,SAAS,iBAAiB,YAAa,CAAK,EAC5C,OAAO,iBAAiB,SAAU,CAAY,EAC9C,OAAO,iBAAiB,SAAU,EAAc,EAAI,MACvC,CACX,SAAS,oBAAoB,YAAa,CAAK,EAC/C,OAAO,oBAAoB,SAAU,CAAY,EACjD,OAAO,oBAAoB,SAAU,EAAc,EAAI,CACzD,CACF,EAAG,CAAC,CAAO,CAAC,EAEZ,IAAM,EAAc,GAAgB,EAAY,GAAS,IAAQ,EAAM,KAAO,CAAI,EAE5E,EAAe,GAAqB,CACxC,GAAI,EAAK,WAAY,CACd,EAAK,QAAQ,EAAS,EAAK,GAAG,EACnC,EAAW,IAAI,EACf,MACF,CACA,GAAI,CAAC,GAAgB,CAAI,EAAG,CAC1B,GAAU,CAAI,EACd,MACF,CACI,EAAK,SACT,EAAS,EAAK,GAAG,EACjB,EAAW,IAAI,EACjB,EAEM,EAAQ,CAAC,GAAG,EAAQ,GAAG,EAAO,OAAQ,GAAM,CAAC,EAAO,SAAS,CAAC,CAAC,CAAC,EAEhE,GAAa,EAAU,IAAK,IAAU,CAAE,MAAO,EAAK,IAAK,MAAO,EAAK,IAAK,EAAE,EAElF,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,CAAC,EAAO,KAAM,CAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAAjE,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAQ,WACR,QAAS,GACT,SAAU,CAAC,GAAG,CAAM,EACpB,iBAAmB,GAAS,CAC1B,IAAK,IAAM,KAAO,EAAW,EAAO,SAAS,CAAG,GAAG,EAAM,CAAG,EAC5D,IAAK,IAAM,KAAO,EAAa,EAAK,SAAS,CAAG,GAAG,EAAS,CAAG,CACjE,EACA,aAAY,CACb,CAAA,EAEA,EAAM,IAAK,GAAQ,CAClB,IAAM,EAAO,EAAM,GACnB,GAAI,CAAC,EAAM,OAAO,KAClB,IAAM,EAAQ,GAAU,CAAI,EACtB,EAAU,GAAU,CAAI,EACxB,EAAS,IAAY,EACrB,EAAY,GAAgB,CAAI,EAChC,EAAK,EAAQ,GAAU,GAAU,EACjC,EAAW,EAAK,OAClB,eACA,EAAK,YAAc,GAAW,EAC5B,gBACA,eACN,OACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAEE,UAAW,EAAO,SAClB,IAAK,EAAS,EAAU,IAAA,GAExB,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,CAAC,EAAO,KAAM,EAAK,EAAO,WAAa,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG,EAAnF,SAAA,CACG,GACC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,CAAC,EAAO,SAAU,EAAO,cAAc,CAAC,CAAC,KAAK,GAAG,EAChE,UAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,SAAW,SAAA,EAAK,IAAW,CAAA,CAC/C,CAAA,GAEN,EAAA,EAAA,KAAA,CAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAO,SAClB,gBAAe,EACf,YAAe,EAAW,CAAG,EAJ/B,SAAA,EAME,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,SAAW,SAAA,EAAK,IAAW,CAAA,EAClD,GAAQ,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAO,UAAxB,SAAA,CAAmC,KAAG,CAAY,CAAI,CAAA,EAAA,KAC9D,GACC,EAAA,EAAA,IAAA,CAAC,GAAD,CAAiB,UAAW,EAAO,MAAO,KAAM,EAAK,CAAA,GAErD,EAAA,EAAA,IAAA,CAAC,GAAD,CAAmB,UAAW,EAAO,MAAO,KAAM,EAAK,CAAA,CAEnD,CAEV,CAAA,GAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CAAK,QAAS,EAAU,UAAW,EAAO,cACxC,UAAA,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAO,UAClB,aAAY,GAAG,EAAS,IAAI,EAAK,KAAK,GACtC,YAAe,EAAY,CAAI,EAE/B,UAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,KAAM,EAAK,CAAA,CAChB,CAAA,CACL,CAAA,CACF,GACF,EApCE,CAoCF,CAET,CAAC,GAED,EAAA,EAAA,IAAA,CAAC,EAAD,CAAK,QAAS,EACZ,UAAA,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAO,QAClB,SAAU,EAAO,SAAW,EAC5B,aAAY,EACZ,YAAe,CACb,EAAQ,EACR,EAAW,IAAI,CACjB,EAEA,UAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,KAAM,EAAK,CAAA,CAChB,CAAA,CACL,CAAA,EAEJ,GACC,GACA,EAAM,IACN,CAAC,GAAU,EAAM,EAAQ,IAAA,EACzB,EAAA,aAAA,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,IAAK,EACL,UAAW,EAAO,QAClB,MAAO,CAAE,SAAU,QAAS,IAAK,EAAQ,IAAK,KAAM,EAAQ,IAAK,EAEjE,UAAA,EAAA,EAAA,IAAA,CAAC,GAAD,CAAa,KAAM,EAAM,GAAU,YAAe,EAAW,IAAI,CAAI,CAAA,CAClE,CAAA,EACL,SAAS,IACX,CACC,GAET,CAEA,SAAS,GAAY,CAAE,OAAM,WAAsD,CACjF,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CACG,EAAK,SAAW,KAEb,EAAK,OAAS,UAChB,EAAA,EAAA,IAAA,CAAC,GAAD,CAAqB,OAAM,OAAQ,CAAU,CAAA,GAE7C,EAAA,EAAA,IAAA,CAAC,GAAD,CAAoB,MAAO,CAAA,EAJ3B,EAAK,QAMN,EAAK,YAAa,EAAA,EAAA,IAAA,CAAC,GAAD,CAAY,MAAO,EAAK,UAAa,CAAA,EAAI,KAC3D,EAAK,eAAiB,EAAK,cAAc,OAAS,GACjD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,OACpB,SAAA,EAAK,cAAc,IAAK,IACvB,EAAA,EAAA,IAAA,CAAC,SAAD,CAEE,KAAK,SACL,UAAW,EAAO,SAClB,YAAe,CACb,EAAQ,EACR,EAAO,QAAQ,CACjB,EAEC,SAAA,EAAO,KACF,EATD,EAAO,KASN,CACT,CACE,CAAA,EACH,IACJ,CAAA,CAAA,CAEN,CAEA,SAAS,GAAY,EAA6C,CAChE,OACE,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAO,YAAxB,SAAA,CACG,EAAE,MACH,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,WAAa,SAAA,EAAE,KAAY,CAAA,EAClD,EAAE,QAAU,IAAA,GAA8D,MAAlD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAO,MAAQ,SAAA,EAAE,KAAY,CAAA,CACnE,GAEV,CAEA,SAAS,GAAc,CAAE,OAAM,UAAoD,CACjF,IAAM,EAAU,EAAK,SAAS,IAAM,GACpC,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EACP,UAAW,EAAG,IAAO,CACnB,EAAK,SAAS,CAAC,CAAE,CAAC,EAClB,EAAO,CACT,EAEC,SAAA,EAAK,QAAQ,IAAK,IACjB,EAAA,EAAA,IAAA,CAAC,EAAD,CAAgB,QAAS,EAAE,MAAO,MAAA,GAChC,UAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CACE,MAAO,EAAE,GACT,MAAO,GAAY,CAAC,EACpB,SAAU,EAAE,SACZ,UAAW,EAAO,GACnB,CAAA,CACE,EAPK,EAAE,EAOP,CACN,CACS,CAAA,CAEhB,CAEA,SAAS,GAAa,CAAE,QAA8B,CACpD,IAAM,EAAW,IAAI,IAAI,EAAK,QAAQ,EAChC,EAAa,EAAK,QAAQ,OAAQ,GAAM,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAK,GAAM,EAAE,EAAE,EACpE,EAAa,EAAW,OAAS,GAAK,EAAW,MAAO,GAAO,EAAS,IAAI,CAAE,CAAC,EAC/E,EAAc,EAAW,KAAM,GAAO,EAAS,IAAI,CAAE,CAAC,GAAK,CAAC,EAElE,OACE,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,CACG,EAAK,WACJ,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAS,EACT,cAAe,EACf,MAAM,MACN,UAAW,CAAC,EAAO,IAAK,EAAO,MAAM,CAAC,CAAC,KAAK,GAAG,EAC/C,aAAgB,CACd,GAAI,EACF,EAAK,SAAS,EAAK,SAAS,OAAQ,GAAO,CAAC,EAAW,SAAS,CAAE,CAAC,CAAC,MAC/D,CACL,IAAM,EAAO,IAAI,IAAI,EAAK,QAAQ,EAClC,IAAK,IAAM,KAAM,EAAY,EAAK,IAAI,CAAE,EACxC,EAAK,SAAS,CAAC,GAAG,CAAI,CAAC,CACzB,CACF,CACD,CAAA,GACD,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,QAAS,cAAY,MAAQ,CAAA,CACpD,CAAA,CAAA,EACA,KACH,EAAK,QAAQ,IAAK,GAAM,CACvB,IAAM,EAAS,EAAK,gBAAgB,EAAE,IACtC,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAgB,QAAS,EAAE,MAAO,MAAA,GAChC,UAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAO,UAAvB,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,GAAD,CACE,QAAS,EAAS,IAAI,EAAE,EAAE,EAC1B,SAAU,EAAE,SACZ,MAAO,GAAY,CAAC,EACpB,UAAW,EAAO,IAClB,SAAW,GAAM,CACf,IAAM,EAAO,IAAI,IAAI,CAAQ,EACzB,EAAE,OAAO,QAAS,EAAK,IAAI,EAAE,EAAE,EAC9B,EAAK,OAAO,EAAE,EAAE,EACrB,EAAK,SAAS,CAAC,GAAG,CAAI,CAAC,CACzB,CACD,CAAA,EACA,GACC,EAAA,EAAA,IAAA,CAAC,EAAD,CAAK,QAAS,EAAO,OAAS,EAAO,MACnC,UAAA,EAAA,EAAA,IAAA,CAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAO,aAClB,aAAY,EAAO,MACnB,QAAU,GAAM,CACd,EAAE,eAAe,EACjB,EAAE,gBAAgB,EAClB,EAAO,QAAQ,CACjB,EAEA,UAAA,EAAA,EAAA,IAAA,CAAC,EAAD,CAAc,KAAM,EAAK,CAAA,CACnB,CAAA,CACL,CAAA,EACH,IACD,GACF,EA/BK,EAAE,EA+BP,CAET,CAAC,CACD,CAAA,CAAA,CAEN,CAEA,SAAS,GAAW,CAAE,SAA2D,CAC/E,OACE,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAO,WAAvB,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAO,WAAa,SAAA,EAAM,KAAW,CAAA,GACrD,EAAA,EAAA,IAAA,CAAC,EAAD,CAAY,MAAO,EAAM,SAAU,UAAW,EAAG,IAAO,EAAM,SAAS,CAAE,EACtE,SAAA,EAAM,QAAQ,IAAK,IAClB,EAAA,EAAA,IAAA,CAAC,EAAD,CAAkB,MAAO,EAAE,GAAI,MAAO,EAAE,MAAO,UAAW,EAAO,GAAM,EAA3D,EAAE,EAAyD,CACxE,CACS,CAAA,CACT,GAET;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECnWA,SAAS,GAAU,EAAa,EAAwB,CACtD,OAAO,EACJ,QAAQ,gBAAiB,OAAO,EAAO,KAAK,CAAC,CAC7C,QAAQ,mBAAoB,QAAQ,EAAO,KAAK,CACrD,CAEA,SAAS,GAAkB,EAAqB,CAC9C,OAAO,EAAI,QAAQ,iCAAkC,mBAAmB,CAC1E,CAEA,SAAS,GAAU,EAAoD,CAGrE,MAAO,CAAE,QAFO,EAAO,MAAM,mBAAmB,CAAC,GAAG,IAAM,YAExC,MADJ,EAAO,QAAQ,sBAAuB,EAAE,CAAC,CAAC,QAAQ,cAAe,EAC7D,CAAM,CAC1B,CAGA,SAAS,EAAU,CAAE,SAAQ,QAAO,GAAG,GAA6C,CAClF,IAAM,GAAA,EAAS,EAAA,MAAA,CAAM,CAAC,CAAC,QAAQ,gBAAiB,EAAE,EAC5C,CAAE,UAAS,UAAA,EAAU,EAAA,QAAA,KAElB,GADS,GAAkB,GAAU,EAAQ,CAAM,CACzC,CAAO,EACvB,CAAC,EAAQ,CAAM,CAAC,EAEnB,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAkB,UAAS,KAAK,eAAsB,QAAO,GAAI,EAC/D,UAAA,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,wBAAyB,CAAE,OAAQ,CAAM,CAAI,CAAA,CACzC,CAAA,CAEb,CAGA,SAAgB,GAAc,EAAuB,CACnD,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,OAAQ,GAAS,GAAI,CAAQ,CAAA,CACjD,CAGA,SAAgB,GAAc,EAAuB,CACnD,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,OAAQ,GAAS,GAAI,CAAQ,CAAA,CACjD,CAGA,SAAgB,GAAgB,EAAuB,CACrD,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,OAAQ,GAAW,GAAI,CAAQ,CAAA,CACnD,CAGA,SAAgB,GAAkB,EAAuB,CACvD,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,OAAQ,GAAkB,GAAI,CAAQ,CAAA,CAC1D,CAGA,SAAgB,GAAiB,EAAuB,CACtD,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,OAAQ,GAAiB,GAAI,CAAQ,CAAA,CACzD,CAGA,SAAgB,GAAoB,EAAuB,CACzD,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,OAAQ,GAAoB,GAAI,CAAQ,CAAA,CAC5D,CAGA,SAAgB,GAAe,EAAuB,CACpD,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,OAAQ,GAAQ,GAAI,CAAQ,CAAA,CAChD,CAGA,SAAgB,GAAc,EAAuB,CACnD,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC/C,CAGA,SAAgB,GAAiB,EAAuB,CACtD,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAW,OAAQ,GAAU,GAAI,CAAQ,CAAA,CAClD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EC1EA,SAAS,GAAU,EAAa,EAAwB,CACtD,OAAO,EACJ,QAAQ,gBAAiB,OAAO,EAAO,KAAK,CAAC,CAC7C,QAAQ,mBAAoB,QAAQ,EAAO,KAAK,CACrD,CAEA,SAAS,GAAU,EAAoD,CAGrE,MAAO,CAAE,QAFO,EAAO,MAAM,mBAAmB,CAAC,GAAG,IAAM,cAExC,MADJ,EAAO,QAAQ,sBAAuB,EAAE,CAAC,CAAC,QAAQ,cAAe,EAC7D,CAAM,CAC1B,CAMA,SAAS,EAAS,CAAE,SAAQ,QAAO,GAAG,GAA4C,CAChF,IAAM,GAAA,EAAS,EAAA,MAAA,CAAM,CAAC,CAAC,QAAQ,gBAAiB,EAAE,EAC5C,CAAE,UAAS,UAAA,EAAU,EAAA,QAAA,KAAc,GAAU,GAAU,EAAQ,CAAM,CAAC,EAAG,CAAC,EAAQ,CAAM,CAAC,EAE/F,OACE,EAAA,EAAA,IAAA,CAAC,EAAD,CAAkB,UAAgB,QAAO,GAAI,EAC3C,UAAA,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,wBAAyB,CAAE,OAAQ,CAAM,CAAI,CAAA,CACzC,CAAA,CAEb,CAGA,SAAgB,GAAW,EAAsB,CAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC9C,CAGA,SAAgB,GAAW,EAAsB,CAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC9C,CAGA,SAAgB,GAAW,EAAsB,CAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC9C,CAGA,SAAgB,GAAW,EAAsB,CAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC9C,CAGA,SAAgB,GAAW,EAAsB,CAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC9C,CAGA,SAAgB,GAAW,EAAsB,CAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC9C,CAGA,SAAgB,GAAW,EAAsB,CAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC9C,CAGA,SAAgB,GAAW,EAAsB,CAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC9C,CAGA,SAAgB,GAAW,EAAsB,CAC/C,OAAO,EAAA,EAAA,IAAA,CAAC,EAAD,CAAU,OAAQ,GAAO,GAAI,CAAQ,CAAA,CAC9C,CCjFA,IAAa,GAAe,GAC1B,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,mBAAqB,CAAA,GAC7B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,WAAa,CAAA,GACrB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,qCAAuC,CAAA,GAC/C,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,cAAgB,CAAA,CACxB,CAAA,CAAA,EACF,UACF,EAGa,GAAkB,GAC7B,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,eAAiB,CAAA,GACzB,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,2BAA6B,CAAA,GACrC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,UAAY,CAAA,CACpB,CAAA,CAAA,EACF,aACF,EAGa,GAAW,GACtB,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,SAAS,UACT,SAAS,UACT,EAAE,0NACH,CAAA,EACD,OACA,CAAE,KAAM,MAAO,CACjB,EAGa,GAAa,GACxB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,MAAM,EAAE,IAAI,MAAM,KAAK,OAAO,IAAI,GAAG,KAAO,CAAA,GACpD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,MAAM,EAAE,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG,KAAO,CAAA,GACrD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,uBAAyB,CAAA,CACjC,CAAA,CAAA,EACF,QACF,EAGa,GAAe,GAC1B,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,IAAI,EAAE,MAAM,MAAM,KAAK,OAAO,KAAK,GAAG,GAAK,CAAA,GACnD,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,iBAAmB,CAAA,CAC3B,CAAA,CAAA,EACF,UACF,EAGa,GAAW,GACtB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,GAAG,KAAK,GAAG,KAAK,EAAE,GAAK,CAAA,GAC/B,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,oDAAsD,CAAA,GAC9D,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,cAAgB,CAAA,CACxB,CAAA,CAAA,EACF,MACF,EAGa,GAAW,GACtB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,8DAAgE,CAAA,GACxE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,4BAA8B,CAAA,CACtC,CAAA,CAAA,EACF,MACF,EAGa,GAAW,GACtB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,iDAAmD,CAAA,GAC3D,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,GAAG,KAAK,GAAG,MAAM,EAAE,KAAO,CAAA,CAClC,CAAA,CAAA,EACF,MACF,EC7Ea,GAAgB,GAC3B,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,GAAG,KAAK,GAAG,KAAK,EAAE,KAAO,CAAA,GACjC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,mBAAqB,CAAA,CAC7B,CAAA,CAAA,EACF,WACF,EAEa,GAAc,GACzB,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,GAAG,KAAK,GAAG,KAAK,EAAE,KAAO,CAAA,GACjC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,yBAA2B,CAAA,CACnC,CAAA,CAAA,EACF,SACF,EAEa,GAAgB,GAC3B,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,8BAAgC,CAAA,GACxC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,sBAAwB,CAAA,CAChC,CAAA,CAAA,EACF,WACF,EAEa,GAAiB,GAC5B,EAAA,EAAA,KAAA,CAAA,EAAA,SAAA,CAAA,SAAA,EACE,EAAA,EAAA,IAAA,CAAC,SAAD,CAAQ,GAAG,KAAK,GAAG,KAAK,EAAE,KAAO,CAAA,GACjC,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,EAAE,oBAAsB,CAAA,CAC9B,CAAA,CAAA,EACF,YACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API. Styles are opt-in: consumers import `@scinverse/ui/styles.css` once
|
|
3
|
+
* at the app root, so MF remotes sharing a host page never load tokens twice.
|
|
4
|
+
*/
|
|
5
|
+
export { ThemeProvider, useTheme, type Theme } from './theme/ThemeProvider';
|
|
6
|
+
export { Button, type ButtonColor, type ButtonProps, type ButtonSize, type ButtonToggled, type ButtonVariant, } from './components/Button';
|
|
7
|
+
export { Panel, type PanelProps } from './components/Panel';
|
|
8
|
+
export { Card, CardDot, type CardDotProps, type CardDotTone, type CardProps, } from './components/Card';
|
|
9
|
+
export { Badge, type BadgeColor, type BadgeProps, type BadgeRound, type BadgeSize, } from './components/Badge';
|
|
10
|
+
export { Checkbox, type CheckboxColor, type CheckboxProps, type CheckboxSize, } from './components/Checkbox';
|
|
11
|
+
export { Tip, type TipProps } from './components/Tip';
|
|
12
|
+
export { Radio, RadioGroup, type RadioColor, type RadioGroupOrientation, type RadioGroupProps, type RadioProps, type RadioSize, } from './components/RadioGroup';
|
|
13
|
+
export { Input, SearchBar, TextArea, type InputProps, type SearchBarProps, type TextAreaProps, } from './components/Input';
|
|
14
|
+
export { Switcher, type SwitcherPhase, type SwitcherProps, type SwitcherSize, } from './components/Switcher';
|
|
15
|
+
export { Dropdown, type DropdownOption, type DropdownProps, type DropdownVariant, } from './components/Dropdown';
|
|
16
|
+
export { Filter, type FilterMenuItem, type FilterOption, type FilterProps, type FilterRadioGroup, type FilterSpec, } from './components/Filter';
|
|
17
|
+
export { SvgIcon, createSvgIcon, resolveIconColor, resolveIconSize, ICON_COLOR_CSS, ICON_SIZE_PX, type SvgIconProps, type IconColor, type IconSizeToken, type CreateSvgIconOptions, type BrandMarkProps, type FlagIconProps, ScinverseIcon, ScinverseLogo, ScinverseAvatar, ConnectionOhsIcon, ConnectionNcIcon, ConnectionUiKitIcon, ServiceOhsIcon, ServiceNcIcon, ServiceUiKitIcon, FlagEnIcon, FlagFrIcon, FlagRuIcon, FlagDeIcon, FlagItIcon, FlagEsIcon, FlagPtIcon, FlagNlIcon, FlagZhIcon, PlusIcon, MinusIcon, PowerIcon, CloseIcon, SearchIcon, EyeIcon, EyeSlashIcon, CheckIcon, ChevronDownIcon, ArrowDropDownIcon, ArrowDropUpIcon, SunIcon, MoonIcon, LogoutIcon, PencilIcon, SettingsIcon, RefreshIcon, LoadingIcon, ExchangeIcon, SystemIcon, IntegrationIcon, NewsIcon, MessagesIcon, HelpIcon, BellIcon, UserIcon, InfoLabelIcon, OkLabelIcon, WarnLabelIcon, ErrorLabelIcon, } from './icons';
|