diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92564e01e2..589063afe2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -529,6 +529,9 @@ jobs: - name: Check repository hygiene run: pnpm run check:repo-hygiene + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Validate interactive capability contract run: pnpm run capabilities:check && pnpm run capabilities:test && pnpm run website:test && pnpm run website:build @@ -538,9 +541,6 @@ jobs: - name: Check core boundaries run: pnpm run check:core-boundaries - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Setup Bun for package resource preflight if: needs.build-impact.outputs.frontend_required != 'false' uses: oven-sh/setup-bun@v2 diff --git a/BitFun-Installer/README.md b/BitFun-Installer/README.md index ffcf6cbb54..dc2754f016 100644 --- a/BitFun-Installer/README.md +++ b/BitFun-Installer/README.md @@ -77,9 +77,9 @@ BitFun-Installer/ │ ├── hooks/ │ │ └── useInstaller.ts # Core installer state machine │ ├── styles/ -│ │ ├── global.css # Base styles -│ │ ├── variables.css # Design tokens +│ │ ├── global.css # Base styles consuming canonical tokens │ │ └── animations.css # Keyframe animations +│ ├── theme/ # Canonical theme projection + installer presets │ ├── types/ │ │ └── installer.ts # TypeScript types │ ├── App.tsx @@ -202,7 +202,9 @@ src-tauri/target/release-fast/bitfun-installer.exe ### Changing the UI Theme -Edit [variables.css](src/styles/variables.css). Colors, spacing, and animations are controlled by CSS custom properties. +Shared light/dark values come from `@bitfun/theme-bitfun`. Installer-only named presets live in +[installerThemesData.ts](src/theme/installerThemesData.ts), and components consume only canonical +`--bf-*` variables projected by [installerThemeRuntime.ts](src/theme/installerThemeRuntime.ts). ### Adding Install Steps diff --git a/BitFun-Installer/index.html b/BitFun-Installer/index.html index 7c3f33ad41..65424725a0 100644 --- a/BitFun-Installer/index.html +++ b/BitFun-Installer/index.html @@ -3,19 +3,11 @@ + Install BitFun - + diff --git a/BitFun-Installer/package.json b/BitFun-Installer/package.json index ae90699962..7e211540a6 100644 --- a/BitFun-Installer/package.json +++ b/BitFun-Installer/package.json @@ -24,6 +24,7 @@ "type-check": "tsc --noEmit" }, "dependencies": { + "@bitfun/theme-bitfun": "workspace:^", "@tauri-apps/api": "^2.10.1", "@tauri-apps/plugin-dialog": "^2.6.0", "i18next": "^25.8.0", diff --git a/BitFun-Installer/src/App.tsx b/BitFun-Installer/src/App.tsx index a6bcfa5c93..6d4bd1614f 100644 --- a/BitFun-Installer/src/App.tsx +++ b/BitFun-Installer/src/App.tsx @@ -136,7 +136,7 @@ function App() { {!isFullscreen && (
diff --git a/BitFun-Installer/src/components/InstallErrorPanel.tsx b/BitFun-Installer/src/components/InstallErrorPanel.tsx index c9f8bcd8fe..34c2b5b436 100644 --- a/BitFun-Installer/src/components/InstallErrorPanel.tsx +++ b/BitFun-Installer/src/components/InstallErrorPanel.tsx @@ -23,9 +23,9 @@ export function InstallErrorPanel({ message, variant = 'options' }: InstallError marginTop: 10, padding: '10px 12px', borderRadius: 10, - border: '1px solid color-mix(in srgb, var(--border-base) 70%, transparent)', - background: 'color-mix(in srgb, var(--element-bg-subtle) 80%, transparent)', - color: 'var(--color-text-secondary)', + border: '1px solid color-mix(in srgb, var(--bf-color-border-default) 70%, transparent)', + background: 'color-mix(in srgb, var(--bf-color-surface-subtle) 80%, transparent)', + color: 'var(--bf-color-content-secondary)', fontSize: 11, lineHeight: 1.55, textAlign: variant === 'bare' ? 'center' : 'left', @@ -40,7 +40,7 @@ export function InstallErrorPanel({ message, variant = 'options' }: InstallError <>
diff --git a/BitFun-Installer/src/pages/LanguageSelect.tsx b/BitFun-Installer/src/pages/LanguageSelect.tsx index 675aea3f2e..9c3e34403e 100644 --- a/BitFun-Installer/src/pages/LanguageSelect.tsx +++ b/BitFun-Installer/src/pages/LanguageSelect.tsx @@ -29,11 +29,11 @@ export function LanguageSelect({ onSelect }: LanguageSelectProps) { display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', position: 'relative', overflow: 'hidden', - background: 'var(--color-bg-primary)', + background: 'var(--bf-color-surface-canvas)', }}>
@@ -44,13 +44,13 @@ export function LanguageSelect({ onSelect }: LanguageSelectProps) { BitFun

BitFun

@@ -68,7 +68,7 @@ export function LanguageSelect({ onSelect }: LanguageSelectProps) { padding: '0 24px', textAlign: 'center', fontSize: 11, - color: 'var(--color-text-muted)', + color: 'var(--bf-color-content-muted)', opacity: 0.6, letterSpacing: '0.5px', }}> @@ -107,36 +107,36 @@ export function LanguageSelect({ onSelect }: LanguageSelectProps) { display: 'flex', alignItems: 'center', gap: 12, padding: '14px 16px', width: '100%', background: isSelected - ? 'color-mix(in srgb, var(--color-accent-500) 8%, transparent)' - : 'var(--element-bg-subtle)', + ? 'color-mix(in srgb, var(--bf-color-accent-default) 8%, transparent)' + : 'var(--bf-color-surface-subtle)', border: 'none', - borderRadius: 'var(--size-radius-sm)', + borderRadius: 'var(--bf-radius-sm)', cursor: 'pointer', textAlign: 'left', transition: 'all 0.25s ease', outline: 'none', - fontFamily: 'var(--font-sans)', + fontFamily: 'var(--bf-font-family-sans)', boxShadow: 'none', }} onMouseEnter={(e) => { if (!isSelected) { - e.currentTarget.style.background = 'var(--element-bg-soft)'; + e.currentTarget.style.background = 'var(--bf-color-action-neutral-surface)'; } }} onMouseLeave={(e) => { if (!isSelected) { - e.currentTarget.style.background = 'var(--element-bg-subtle)'; + e.currentTarget.style.background = 'var(--bf-color-surface-subtle)'; } }} >
{lang.nativeName}
{lang.label}
diff --git a/BitFun-Installer/src/pages/Options.tsx b/BitFun-Installer/src/pages/Options.tsx index 36674bc253..d99151efd6 100644 --- a/BitFun-Installer/src/pages/Options.tsx +++ b/BitFun-Installer/src/pages/Options.tsx @@ -79,7 +79,7 @@ export function Options({
-
+
{t('options.subtitle')}
{existingInstall?.detected ? ( @@ -88,11 +88,11 @@ export function Options({ marginBottom: 16, padding: '12px 14px', borderRadius: 10, - border: '1px solid color-mix(in srgb, var(--color-accent-500) 45%, transparent)', - background: 'color-mix(in srgb, var(--color-accent-500) 8%, transparent)', + border: '1px solid color-mix(in srgb, var(--bf-color-accent-default) 45%, transparent)', + background: 'color-mix(in srgb, var(--bf-color-accent-default) 8%, transparent)', fontSize: 12, lineHeight: 1.55, - color: 'var(--color-text-primary)', + color: 'var(--bf-color-content-primary)', }} >
{t('options.existingInstallTitle')}
@@ -107,7 +107,7 @@ export function Options({
) : null} {!existingInstall.mainBinaryPresent ? ( -
+
{t('options.existingInstallBinaryMissing')}
) : null} @@ -173,7 +173,7 @@ export function Options({ gap: 16, marginTop: 8, fontSize: 11, - color: 'var(--color-text-muted)', + color: 'var(--bf-color-content-muted)', opacity: 0.7, flexWrap: 'wrap', }} @@ -184,7 +184,7 @@ export function Options({ {diskSpace.available < Number.MAX_SAFE_INTEGER ? formatBytes(diskSpace.available) : '-'} {!diskSpace.sufficient && ( - {t('options.insufficientSpace')} + {t('options.insufficientSpace')} )}
)} diff --git a/BitFun-Installer/src/pages/Progress.tsx b/BitFun-Installer/src/pages/Progress.tsx index 9d6e341180..556999a27c 100644 --- a/BitFun-Installer/src/pages/Progress.tsx +++ b/BitFun-Installer/src/pages/Progress.tsx @@ -44,10 +44,10 @@ export function ProgressPage({ > {!error ? ( <> -

+

{t('progress.title')}

-

+

{stepLabel}

@@ -59,7 +59,7 @@ export function ProgressPage({ gap: 8, marginTop: 8, fontSize: 11, - color: 'var(--color-text-muted)', + color: 'var(--bf-color-content-muted)', opacity: 0.7, flexWrap: 'wrap', }} @@ -76,7 +76,7 @@ export function ProgressPage({ height="18" viewBox="0 0 24 24" fill="none" - stroke="var(--color-error)" + stroke="var(--bf-color-status-danger-content)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" @@ -84,7 +84,7 @@ export function ProgressPage({ > -

{t('progress.failed')}

+

{t('progress.failed')}

)} diff --git a/BitFun-Installer/src/pages/ThemeSetup.tsx b/BitFun-Installer/src/pages/ThemeSetup.tsx index 1cd209eda0..4d6cfc907b 100644 --- a/BitFun-Installer/src/pages/ThemeSetup.tsx +++ b/BitFun-Installer/src/pages/ThemeSetup.tsx @@ -30,8 +30,8 @@ export function ThemeSetup({ options, setOptions, onLaunch, onClose }: ThemeSetu borderRadius: 12, padding: 8, background: active - ? 'color-mix(in srgb, var(--color-accent-500) 8%, transparent)' - : 'var(--element-bg-subtle)', + ? 'color-mix(in srgb, var(--bf-color-accent-default) 8%, transparent)' + : 'var(--bf-color-surface-subtle)', border: 'none', cursor: 'pointer', transition: 'background 0.2s ease', @@ -74,7 +74,7 @@ export function ThemeSetup({ options, setOptions, onLaunch, onClose }: ThemeSetu

{t('themeSetup.subtitle')} @@ -98,7 +98,7 @@ export function ThemeSetup({ options, setOptions, onLaunch, onClose }: ThemeSetu

-
+
{t('themeSetup.followSystem')}
@@ -115,7 +115,7 @@ export function ThemeSetup({ options, setOptions, onLaunch, onClose }: ThemeSetu
-
+
{t(`themeSetup.themeNames.${theme.id}`, { defaultValue: theme.name })}
@@ -132,7 +132,7 @@ export function ThemeSetup({ options, setOptions, onLaunch, onClose }: ThemeSetu {finishError && (
): TonePreset { return { - subtle: alpha(rgb, alphas[0]), - base: alpha(rgb, alphas[1]), + text: { + primary: themeValue(theme, 'color.content.primary'), + secondary: themeValue(theme, 'color.content.secondary'), + muted: themeValue(theme, 'color.content.muted'), + }, + semantic: { + success: themeValue(theme, 'color.status.success.content'), + warning: themeValue(theme, 'color.status.warning.content'), + error: themeValue(theme, 'color.status.danger.content'), + }, + border: { + subtle: themeValue(theme, 'color.border.subtle'), + base: themeValue(theme, 'color.border.default'), + }, + element: { + subtle: themeValue(theme, 'color.surface.subtle'), + soft: themeValue(theme, 'color.action.neutral.surface'), + medium: themeValue(theme, 'color.action.neutral.surfacePressed'), + }, }; } -function createElementRamp(rgb: string): ElementColors { +const DARK_TONE = createTone('dark'); +const LIGHT_TONE = createTone('light'); + +function createBuiltinInstallerTheme( + id: Extract, + name: string, + type: Extract, +): InstallerTheme { + const tone = type === 'light' ? LIGHT_TONE : DARK_TONE; return { - subtle: alpha(rgb, '0.06'), - soft: alpha(rgb, '0.12'), - medium: alpha(rgb, '0.18'), + id, + name, + type, + colors: { + background: { + primary: themeValue(type, 'color.surface.canvas'), + secondary: themeValue(type, 'color.surface.panel'), + }, + text: { ...tone.text }, + accent: themeValue(type, 'color.accent.default'), + semantic: { ...tone.semantic }, + border: { ...tone.border }, + element: { ...tone.element }, + }, }; } -const DARK_TONE: TonePreset = { - text: { primary: '#e8e8e8', secondary: '#b0b0b0', muted: '#858585' }, - semantic: { - success: '#34d399', - warning: '#f59e0b', - error: '#ef4444', - }, - border: createBorderRamp('255, 255, 255', ['0.12', '0.18']), - element: createElementRamp('255, 255, 255'), -}; - -const LIGHT_TONE: TonePreset = { - text: { primary: '#1e293b', secondary: '#3d4f66', muted: '#64748b' }, - semantic: { - success: '#5b9a6f', - warning: '#c08c42', - error: '#c26565', - }, - border: createBorderRamp('100, 116, 139', ['0.15', '0.22']), - element: createElementRamp('71, 102, 143'), -}; - function createInstallerTheme(seed: ThemeSeed): InstallerTheme { const tone = seed.type === 'light' ? LIGHT_TONE : DARK_TONE; @@ -135,23 +149,8 @@ function createInstallerTheme(seed: ThemeSeed): InstallerTheme { } export const THEMES: InstallerTheme[] = [ - createInstallerTheme({ - id: 'bitfun-dark', - name: 'Dark', - type: 'dark', - background: { - primary: DARK_CARD_BACKGROUND, - secondary: DARK_CARD_SURFACE, - }, - accent: DEFAULT_BLUE, - }), - createInstallerTheme({ - id: 'bitfun-light', - name: 'Light', - type: 'light', - background: { primary: '#f7f8fa', secondary: '#ffffff' }, - accent: '#5a7bb2', - }), + createBuiltinInstallerTheme('bitfun-dark', 'Dark', 'dark'), + createBuiltinInstallerTheme('bitfun-light', 'Light', 'light'), createInstallerTheme({ id: 'bitfun-midnight', name: 'Midnight', diff --git a/MiniApp/Demo/git-graph/source/style.css b/MiniApp/Demo/git-graph/source/style.css index 611feace90..623fe7d462 100644 --- a/MiniApp/Demo/git-graph/source/style.css +++ b/MiniApp/Demo/git-graph/source/style.css @@ -1,32 +1,32 @@ /* styles/tokens.css */ /* Git Graph MiniApp — theme tokens (host --bitfun-* when running in BitFun) */ :root { - --bg: var(--bitfun-bg, #0d1117); - --bg-surface: var(--bitfun-bg-secondary, #161b22); - --bg-hover: var(--bitfun-element-hover, #1c2333); - --bg-active: var(--bitfun-element-bg, #1f2a3d); - --border: var(--bitfun-border, #30363d); - --border-light: var(--bitfun-border-subtle, #21262d); - --text: var(--bitfun-text, #e6edf3); - --text-sec: var(--bitfun-text-secondary, #8b949e); - --text-dim: var(--bitfun-text-muted, #484f58); - --accent: var(--bitfun-accent, #58a6ff); - --accent-dim: var(--bitfun-accent-hover, #1f6feb); - --green: var(--bitfun-success, #3fb950); - --red: var(--bitfun-error, #f85149); - --orange: var(--bitfun-warning, #d29922); - --purple: var(--bitfun-info, #bc8cff); - --branch-1: var(--bitfun-accent, #58a6ff); - --branch-2: var(--bitfun-success, #3fb950); - --branch-3: var(--bitfun-info, #bc8cff); - --branch-4: var(--bitfun-warning, #f0883e); + --bg: var(--bitfun-bg); + --bg-surface: var(--bitfun-bg-secondary); + --bg-hover: var(--bitfun-element-hover); + --bg-active: var(--bitfun-element-bg); + --border: var(--bitfun-border); + --border-light: var(--bitfun-border-subtle); + --text: var(--bitfun-text); + --text-sec: var(--bitfun-text-secondary); + --text-dim: var(--bitfun-text-muted); + --accent: var(--bitfun-accent); + --accent-dim: var(--bitfun-accent-hover); + --green: var(--bitfun-success); + --red: var(--bitfun-error); + --orange: var(--bitfun-warning); + --purple: var(--bitfun-accent-secondary); + --branch-1: var(--bitfun-accent); + --branch-2: var(--bitfun-success); + --branch-3: var(--bitfun-accent-secondary); + --branch-4: var(--bitfun-warning); --branch-5: #f778ba; --branch-6: #79c0ff; --branch-7: #56d364; - --radius: var(--bitfun-radius, 6px); - --radius-lg: var(--bitfun-radius-lg, 10px); - --graph-node-stroke: var(--bitfun-bg, #0d1117); - --graph-uncommitted: var(--text-dim, #808080); + --radius: var(--bitfun-radius); + --radius-lg: var(--bitfun-radius-lg); + --graph-node-stroke: var(--bitfun-bg); + --graph-uncommitted: var(--text-dim); --graph-lane-width: 18px; --graph-row-height: 28px; } @@ -34,7 +34,7 @@ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } body { - font-family: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif); + font-family: var(--bitfun-font-sans); font-size: 13px; color: var(--text); background: var(--bg); @@ -70,7 +70,7 @@ body { text-overflow: ellipsis; white-space: nowrap; max-width: 280px; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); } .toolbar__branch-filter { position: relative; } .toolbar__branch-filter .chevron { margin-left: 4px; opacity: .8; } @@ -85,7 +85,7 @@ body { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 8px 24px rgba(0,0,0,.25); + box-shadow: var(--bitfun-shadow-overlay); z-index: 200; padding: 4px 0; } @@ -121,8 +121,8 @@ body { } .btn--primary { background: var(--accent-dim); - color: #fff; - border-color: rgba(88,166,255,.4); + color: var(--bitfun-text-on-accent); + border-color: color-mix(in srgb, var(--accent) 40%, transparent); } .btn--primary:hover { background: var(--accent); } .btn--primary:active { background: var(--accent-dim); } @@ -177,19 +177,19 @@ body { line-height: 1.4; } .badge--branch { - background: rgba(88,166,255,.15); + background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); - border: 1px solid rgba(88,166,255,.25); + border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent); } .badge--status { - background: rgba(63,185,80,.12); + background: color-mix(in srgb, var(--green) 12%, transparent); color: var(--green); - border: 1px solid rgba(63,185,80,.2); + border: 1px solid color-mix(in srgb, var(--green) 20%, transparent); } .badge--status.has-changes { - background: rgba(210,153,34,.12); + background: color-mix(in srgb, var(--orange) 12%, transparent); color: var(--orange); - border-color: rgba(210,153,34,.2); + border-color: color-mix(in srgb, var(--orange) 20%, transparent); } /* ── Empty state ─────────────────── */ @@ -260,7 +260,7 @@ body { } .commit-row:hover { background: var(--bg-hover); } .commit-row.selected { background: var(--bg-active); } -.commit-row.find-highlight { background: rgba(88,166,255,.15); } +.commit-row.find-highlight { background: color-mix(in srgb, var(--accent) 15%, transparent); } .commit-row.compare-selected { box-shadow: inset 0 0 0 2px var(--accent); } .commit-row.commit-row--stash .graph-node--stash-outer { fill: none; @@ -289,7 +289,7 @@ body { } .commit-row__hash { flex-shrink: 0; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-family: var(--bitfun-font-mono); font-size: 11px; color: var(--accent); width: 56px; @@ -318,19 +318,19 @@ body { white-space: nowrap; } .ref-tag--head { - background: rgba(88,166,255,.18); + background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); } .ref-tag--branch { - background: rgba(63,185,80,.14); + background: color-mix(in srgb, var(--green) 14%, transparent); color: var(--green); } .ref-tag--tag { - background: rgba(210,153,34,.14); + background: color-mix(in srgb, var(--orange) 14%, transparent); color: var(--orange); } .ref-tag--remote { - background: rgba(188,140,255,.14); + background: color-mix(in srgb, var(--purple) 14%, transparent); color: var(--purple); } @@ -350,7 +350,7 @@ body { font-size: 11px; color: var(--text-dim); text-align: right; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-family: var(--bitfun-font-mono); } /* styles/graph.css */ @@ -392,7 +392,7 @@ body { display: flex; flex-direction: column; overflow: hidden; - box-shadow: -4px 0 12px rgba(0,0,0,.08); + box-shadow: var(--bitfun-shadow-card); } .detail-panel-resizer { width: 6px; @@ -485,7 +485,7 @@ body { flex-shrink: 0; } .detail-code-preview__filename { - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 12px; color: var(--text); overflow: hidden; @@ -513,7 +513,7 @@ body { .detail-code-preview__error { color: var(--red); } .detail-code-preview__diff { margin: 0; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 11px; line-height: 1.6; white-space: pre; @@ -522,8 +522,8 @@ body { color: var(--text); } .detail-code-preview__diff .diff-line { display: block; } -.detail-code-preview__diff .diff-line.diff-add { color: var(--green); background: rgba(63,185,80,.08); } -.detail-code-preview__diff .diff-line.diff-del { color: var(--red); background: rgba(248,81,73,.08); } +.detail-code-preview__diff .diff-line.diff-add { color: var(--green); background: color-mix(in srgb, var(--green) 8%, transparent); } +.detail-code-preview__diff .diff-line.diff-del { color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); } .detail-code-preview__diff .diff-line.diff-hunk { color: var(--text-dim); } .detail-section { @@ -541,7 +541,7 @@ body { margin-bottom: 8px; } .detail-hash { - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 12px; color: var(--accent); word-break: break-all; @@ -588,7 +588,7 @@ body { background: var(--bg); border-radius: var(--radius); border: 1px solid var(--border-light); - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 11px; line-height: 1.5; white-space: pre-wrap; @@ -597,8 +597,8 @@ body { overflow: auto; } .diff-line { display: block; } -.diff-line.diff-add { color: var(--green); background: rgba(63,185,80,.08); } -.diff-line.diff-del { color: var(--red); background: rgba(248,81,73,.08); } +.diff-line.diff-add { color: var(--green); background: color-mix(in srgb, var(--green) 8%, transparent); } +.diff-line.diff-del { color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); } .diff-line.diff-hunk { color: var(--text-dim); } .detail-file__name { flex: 1; @@ -606,7 +606,7 @@ body { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); color: var(--text-sec); } .detail-file__stat { display: flex; gap: 6px; flex-shrink: 0; font-size: 11px; } @@ -651,7 +651,7 @@ body { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 4px 16px rgba(0,0,0,.2); + box-shadow: var(--bitfun-shadow-overlay); } .find-widget__input { width: 220px; @@ -680,7 +680,7 @@ body { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 8px 24px rgba(0,0,0,.3); + box-shadow: var(--bitfun-shadow-overlay); font-size: 12px; } .context-menu[aria-hidden="true"] { display: none; } @@ -722,7 +722,7 @@ body { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0,0,0,.35); + box-shadow: var(--bitfun-shadow-overlay); } .modal-dialog__header { display: flex; diff --git a/MiniApp/Demo/git-graph/source/styles/detail-panel.css b/MiniApp/Demo/git-graph/source/styles/detail-panel.css index 818d96290a..13e37e4edc 100644 --- a/MiniApp/Demo/git-graph/source/styles/detail-panel.css +++ b/MiniApp/Demo/git-graph/source/styles/detail-panel.css @@ -11,7 +11,7 @@ display: flex; flex-direction: column; overflow: hidden; - box-shadow: -4px 0 12px rgba(0,0,0,.08); + box-shadow: var(--bitfun-shadow-card); } .detail-panel-resizer { width: 6px; @@ -104,7 +104,7 @@ flex-shrink: 0; } .detail-code-preview__filename { - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 12px; color: var(--text); overflow: hidden; @@ -132,7 +132,7 @@ .detail-code-preview__error { color: var(--red); } .detail-code-preview__diff { margin: 0; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 11px; line-height: 1.6; white-space: pre; @@ -141,8 +141,8 @@ color: var(--text); } .detail-code-preview__diff .diff-line { display: block; } -.detail-code-preview__diff .diff-line.diff-add { color: var(--green); background: rgba(63,185,80,.08); } -.detail-code-preview__diff .diff-line.diff-del { color: var(--red); background: rgba(248,81,73,.08); } +.detail-code-preview__diff .diff-line.diff-add { color: var(--green); background: color-mix(in srgb, var(--green) 8%, transparent); } +.detail-code-preview__diff .diff-line.diff-del { color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); } .detail-code-preview__diff .diff-line.diff-hunk { color: var(--text-dim); } .detail-section { @@ -160,7 +160,7 @@ margin-bottom: 8px; } .detail-hash { - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 12px; color: var(--accent); word-break: break-all; @@ -207,7 +207,7 @@ background: var(--bg); border-radius: var(--radius); border: 1px solid var(--border-light); - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 11px; line-height: 1.5; white-space: pre-wrap; @@ -216,8 +216,8 @@ overflow: auto; } .diff-line { display: block; } -.diff-line.diff-add { color: var(--green); background: rgba(63,185,80,.08); } -.diff-line.diff-del { color: var(--red); background: rgba(248,81,73,.08); } +.diff-line.diff-add { color: var(--green); background: color-mix(in srgb, var(--green) 8%, transparent); } +.diff-line.diff-del { color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); } .diff-line.diff-hunk { color: var(--text-dim); } .detail-file__name { flex: 1; @@ -225,7 +225,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); color: var(--text-sec); } .detail-file__stat { display: flex; gap: 6px; flex-shrink: 0; font-size: 11px; } diff --git a/MiniApp/Demo/git-graph/source/styles/layout.css b/MiniApp/Demo/git-graph/source/styles/layout.css index 866044d095..491ae7c98e 100644 --- a/MiniApp/Demo/git-graph/source/styles/layout.css +++ b/MiniApp/Demo/git-graph/source/styles/layout.css @@ -23,7 +23,7 @@ text-overflow: ellipsis; white-space: nowrap; max-width: 280px; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); } .toolbar__branch-filter { position: relative; } .toolbar__branch-filter .chevron { margin-left: 4px; opacity: .8; } @@ -38,7 +38,7 @@ background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 8px 24px rgba(0,0,0,.25); + box-shadow: var(--bitfun-shadow-overlay); z-index: 200; padding: 4px 0; } @@ -74,8 +74,8 @@ } .btn--primary { background: var(--accent-dim); - color: #fff; - border-color: rgba(88,166,255,.4); + color: var(--bitfun-text-on-accent); + border-color: color-mix(in srgb, var(--accent) 40%, transparent); } .btn--primary:hover { background: var(--accent); } .btn--primary:active { background: var(--accent-dim); } @@ -130,19 +130,19 @@ line-height: 1.4; } .badge--branch { - background: rgba(88,166,255,.15); + background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); - border: 1px solid rgba(88,166,255,.25); + border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent); } .badge--status { - background: rgba(63,185,80,.12); + background: color-mix(in srgb, var(--green) 12%, transparent); color: var(--green); - border: 1px solid rgba(63,185,80,.2); + border: 1px solid color-mix(in srgb, var(--green) 20%, transparent); } .badge--status.has-changes { - background: rgba(210,153,34,.12); + background: color-mix(in srgb, var(--orange) 12%, transparent); color: var(--orange); - border-color: rgba(210,153,34,.2); + border-color: color-mix(in srgb, var(--orange) 20%, transparent); } /* ── Empty state ─────────────────── */ @@ -213,7 +213,7 @@ } .commit-row:hover { background: var(--bg-hover); } .commit-row.selected { background: var(--bg-active); } -.commit-row.find-highlight { background: rgba(88,166,255,.15); } +.commit-row.find-highlight { background: color-mix(in srgb, var(--accent) 15%, transparent); } .commit-row.compare-selected { box-shadow: inset 0 0 0 2px var(--accent); } .commit-row.commit-row--stash .graph-node--stash-outer { fill: none; @@ -242,7 +242,7 @@ } .commit-row__hash { flex-shrink: 0; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-family: var(--bitfun-font-mono); font-size: 11px; color: var(--accent); width: 56px; @@ -271,19 +271,19 @@ white-space: nowrap; } .ref-tag--head { - background: rgba(88,166,255,.18); + background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); } .ref-tag--branch { - background: rgba(63,185,80,.14); + background: color-mix(in srgb, var(--green) 14%, transparent); color: var(--green); } .ref-tag--tag { - background: rgba(210,153,34,.14); + background: color-mix(in srgb, var(--orange) 14%, transparent); color: var(--orange); } .ref-tag--remote { - background: rgba(188,140,255,.14); + background: color-mix(in srgb, var(--purple) 14%, transparent); color: var(--purple); } @@ -303,5 +303,5 @@ font-size: 11px; color: var(--text-dim); text-align: right; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-family: var(--bitfun-font-mono); } diff --git a/MiniApp/Demo/git-graph/source/styles/overlay.css b/MiniApp/Demo/git-graph/source/styles/overlay.css index 20694046e2..b4960d1674 100644 --- a/MiniApp/Demo/git-graph/source/styles/overlay.css +++ b/MiniApp/Demo/git-graph/source/styles/overlay.css @@ -35,7 +35,7 @@ background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 4px 16px rgba(0,0,0,.2); + box-shadow: var(--bitfun-shadow-overlay); } .find-widget__input { width: 220px; @@ -64,7 +64,7 @@ background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 8px 24px rgba(0,0,0,.3); + box-shadow: var(--bitfun-shadow-overlay); font-size: 12px; } .context-menu[aria-hidden="true"] { display: none; } @@ -106,7 +106,7 @@ background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0,0,0,.35); + box-shadow: var(--bitfun-shadow-overlay); } .modal-dialog__header { display: flex; diff --git a/MiniApp/Demo/git-graph/source/styles/tokens.css b/MiniApp/Demo/git-graph/source/styles/tokens.css index 0f1649176e..6f00ce692b 100644 --- a/MiniApp/Demo/git-graph/source/styles/tokens.css +++ b/MiniApp/Demo/git-graph/source/styles/tokens.css @@ -1,31 +1,31 @@ /* Git Graph MiniApp — theme tokens (host --bitfun-* when running in BitFun) */ :root { - --bg: var(--bitfun-bg, #0d1117); - --bg-surface: var(--bitfun-bg-secondary, #161b22); - --bg-hover: var(--bitfun-element-hover, #1c2333); - --bg-active: var(--bitfun-element-bg, #1f2a3d); - --border: var(--bitfun-border, #30363d); - --border-light: var(--bitfun-border-subtle, #21262d); - --text: var(--bitfun-text, #e6edf3); - --text-sec: var(--bitfun-text-secondary, #8b949e); - --text-dim: var(--bitfun-text-muted, #484f58); - --accent: var(--bitfun-accent, #58a6ff); - --accent-dim: var(--bitfun-accent-hover, #1f6feb); - --green: var(--bitfun-success, #3fb950); - --red: var(--bitfun-error, #f85149); - --orange: var(--bitfun-warning, #d29922); - --purple: var(--bitfun-info, #bc8cff); - --branch-1: var(--bitfun-accent, #58a6ff); - --branch-2: var(--bitfun-success, #3fb950); - --branch-3: var(--bitfun-info, #bc8cff); - --branch-4: var(--bitfun-warning, #f0883e); + --bg: var(--bitfun-bg); + --bg-surface: var(--bitfun-bg-secondary); + --bg-hover: var(--bitfun-element-hover); + --bg-active: var(--bitfun-element-bg); + --border: var(--bitfun-border); + --border-light: var(--bitfun-border-subtle); + --text: var(--bitfun-text); + --text-sec: var(--bitfun-text-secondary); + --text-dim: var(--bitfun-text-muted); + --accent: var(--bitfun-accent); + --accent-dim: var(--bitfun-accent-hover); + --green: var(--bitfun-success); + --red: var(--bitfun-error); + --orange: var(--bitfun-warning); + --purple: var(--bitfun-accent-secondary); + --branch-1: var(--bitfun-accent); + --branch-2: var(--bitfun-success); + --branch-3: var(--bitfun-accent-secondary); + --branch-4: var(--bitfun-warning); --branch-5: #f778ba; --branch-6: #79c0ff; --branch-7: #56d364; - --radius: var(--bitfun-radius, 6px); - --radius-lg: var(--bitfun-radius-lg, 10px); - --graph-node-stroke: var(--bitfun-bg, #0d1117); - --graph-uncommitted: var(--text-dim, #808080); + --radius: var(--bitfun-radius); + --radius-lg: var(--bitfun-radius-lg); + --graph-node-stroke: var(--bitfun-bg); + --graph-uncommitted: var(--text-dim); --graph-lane-width: 18px; --graph-row-height: 28px; } @@ -33,7 +33,7 @@ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } body { - font-family: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif); + font-family: var(--bitfun-font-sans); font-size: 13px; color: var(--text); background: var(--bg); diff --git a/MiniApp/Demo/git-graph/source/ui.js b/MiniApp/Demo/git-graph/source/ui.js index cf7c1802b5..86718662a9 100644 --- a/MiniApp/Demo/git-graph/source/ui.js +++ b/MiniApp/Demo/git-graph/source/ui.js @@ -122,27 +122,34 @@ const root = document.documentElement; function getComputed(name) { - return getComputedStyle(root).getPropertyValue(name).trim() || null; + return getComputedStyle(root).getPropertyValue(name).trim(); + } + + function requireComputed(name) { + const value = getComputed(name); + if (!value) { + throw new Error('Git Graph requires the MiniApp appearance contract variable ' + name + '.'); + } + return value; } /** Returns array of 7 branch/lane colors from CSS variables (appearance-aware). */ window.__GG.getGraphColors = function () { const colors = []; for (let i = 1; i <= 7; i++) { - const v = getComputed('--branch-' + i); - colors.push(v || '#58a6ff'); + colors.push(requireComputed('--branch-' + i)); } return colors; }; /** Node stroke color (contrast with background). */ window.__GG.getNodeStroke = function () { - return getComputed('--graph-node-stroke') || getComputed('--bitfun-bg') || getComputed('--bg') || '#0d1117'; + return requireComputed('--graph-node-stroke'); }; /** Uncommitted / WIP line and node color. */ window.__GG.getUncommittedColor = function () { - return getComputed('--graph-uncommitted') || getComputed('--text-dim') || '#808080'; + return requireComputed('--graph-uncommitted'); }; })(); diff --git a/MiniApp/Demo/git-graph/source/ui/appearance.js b/MiniApp/Demo/git-graph/source/ui/appearance.js index 239ee2e055..b6d9a05f49 100644 --- a/MiniApp/Demo/git-graph/source/ui/appearance.js +++ b/MiniApp/Demo/git-graph/source/ui/appearance.js @@ -6,26 +6,33 @@ const root = document.documentElement; function getComputed(name) { - return getComputedStyle(root).getPropertyValue(name).trim() || null; + return getComputedStyle(root).getPropertyValue(name).trim(); + } + + function requireComputed(name) { + const value = getComputed(name); + if (!value) { + throw new Error('Git Graph requires the MiniApp appearance contract variable ' + name + '.'); + } + return value; } /** Returns array of 7 branch/lane colors from CSS variables (appearance-aware). */ window.__GG.getGraphColors = function () { const colors = []; for (let i = 1; i <= 7; i++) { - const v = getComputed('--branch-' + i); - colors.push(v || '#58a6ff'); + colors.push(requireComputed('--branch-' + i)); } return colors; }; /** Node stroke color (contrast with background). */ window.__GG.getNodeStroke = function () { - return getComputed('--graph-node-stroke') || getComputed('--bitfun-bg') || getComputed('--bg') || '#0d1117'; + return requireComputed('--graph-node-stroke'); }; /** Uncommitted / WIP line and node color. */ window.__GG.getUncommittedColor = function () { - return getComputed('--graph-uncommitted') || getComputed('--text-dim') || '#808080'; + return requireComputed('--graph-uncommitted'); }; })(); diff --git a/MiniApp/Demo/icon-design-system/source/style.css b/MiniApp/Demo/icon-design-system/source/style.css index b6d3bf2408..b9023ad997 100644 --- a/MiniApp/Demo/icon-design-system/source/style.css +++ b/MiniApp/Demo/icon-design-system/source/style.css @@ -1,36 +1,35 @@ /* ── Theme token aliases ────────────────────────────────────────────────────── */ /* Map --bitfun-* host variables to local names so every rule auto-adapts. */ :root { - --bg: var(--bitfun-bg, #121214); - --bg2: var(--bitfun-bg-secondary, #18181a); - --bg3: var(--bitfun-bg-tertiary, #0e0e10); - --bg-el: var(--bitfun-element-bg, #27272a); - --bg-hover: var(--bitfun-element-hover, #3f3f46); - --text: var(--bitfun-text, #e8e8e8); - --text2: var(--bitfun-text-secondary, #b0b0b0); - --text3: var(--bitfun-text-muted, #858585); - --accent: var(--bitfun-accent, #60a5fa); - --accent2: var(--bitfun-accent-hover, #3b82f6); - --success: var(--bitfun-success, #34d399); - --warning: var(--bitfun-warning, #f59e0b); - --danger: var(--bitfun-error, #ef4444); - --info: var(--bitfun-info, #60a5fa); - --border: var(--bitfun-border, #2e2e32); - --border2: var(--bitfun-border-subtle, #27272a); - --radius: var(--bitfun-radius, 6px); - --radius-lg: var(--bitfun-radius-lg, 10px); - --font: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif); - --font-mono: var(--bitfun-font-mono, ui-monospace, monospace); - --scrollbar: var(--bitfun-scrollbar-thumb, rgba(128,128,128,0.25)); + --bg: var(--bitfun-bg); + --bg2: var(--bitfun-bg-secondary); + --bg3: var(--bitfun-bg-tertiary); + --bg-el: var(--bitfun-element-bg); + --bg-hover: var(--bitfun-element-hover); + --text: var(--bitfun-text); + --text2: var(--bitfun-text-secondary); + --text3: var(--bitfun-text-muted); + --accent: var(--bitfun-accent); + --accent2: var(--bitfun-accent-hover); + --success: var(--bitfun-success); + --warning: var(--bitfun-warning); + --danger: var(--bitfun-error); + --info: var(--bitfun-info); + --border: var(--bitfun-border); + --border2: var(--bitfun-border-subtle); + --radius: var(--bitfun-radius); + --radius-lg: var(--bitfun-radius-lg); + --font: var(--bitfun-font-sans); + --font-mono: var(--bitfun-font-mono); + --scrollbar: var(--bitfun-scrollbar-thumb); /* Derived semantic tokens */ - --on-accent: #fff; /* text on accent-coloured surface */ - --on-danger: #fff; /* text on danger-coloured surface */ - --on-success: #fff; /* text on success-coloured surface */ + --on-accent: var(--bitfun-text-on-accent); + --on-danger: var(--bitfun-text-on-accent); + --on-success: var(--bitfun-text-on-accent); } -/* In light theme the on-accent/danger text must be white only if the accent is - dark enough; hosts should override via --bitfun-on-accent if needed. */ +/* On-accent and danger text use the registered --bitfun-text-on-accent projection. */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } diff --git a/design-system/apps/design-lab/src/App.tsx b/design-system/apps/design-lab/src/App.tsx index 00d11a5445..7a914d637f 100644 --- a/design-system/apps/design-lab/src/App.tsx +++ b/design-system/apps/design-lab/src/App.tsx @@ -383,10 +383,12 @@ export function App() { || Boolean(activeComponent && activeComponent.category !== "flow-chat"); return ( -
-
+ ); } diff --git a/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.tsx b/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.tsx index e9999508c5..237aab7d44 100644 --- a/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.tsx +++ b/design-system/apps/design-lab/src/preview/FlowChatPreviewRegistry.tsx @@ -324,7 +324,7 @@ function FrameworkPreview({ actions={actions} content={( - curl -s -o /dev/null -w "HTTP %{http_code}" https://openbitfun.com + {'curl -s -o /dev/null -w "HTTP %{http_code}" https://openbitfun.com'} )} extra={( diff --git a/design-system/apps/design-lab/src/styles.css b/design-system/apps/design-lab/src/styles.css index b8822b88a2..505e6b9cff 100644 --- a/design-system/apps/design-lab/src/styles.css +++ b/design-system/apps/design-lab/src/styles.css @@ -1,7 +1,4 @@ :root { - font-family: var(--bf-font-family-sans); - color: #181818; - background: #ffffff; font-synthesis: none; text-rendering: optimizeLegibility; } @@ -41,47 +38,12 @@ body, } .lab-shell { - --lab-bg: #ffffff; - --lab-surface: #ffffff; - --lab-surface-subtle: #f7f7f7; - --lab-surface-hover: #f2f2f2; - --lab-surface-selected: #ededed; - --lab-border: #e6e6e6; - --lab-border-strong: #d8d8d8; - --lab-text: #171717; - --lab-text-secondary: #5f6168; - --lab-text-muted: #85878d; - --lab-inverse: #ffffff; - --lab-inverse-bg: #171717; - --lab-danger: #a7352d; - --lab-shadow: 0 16px 42px rgb(0 0 0 / 0.08); - --lab-shadow-soft: 0 8px 28px rgb(0 0 0 / 0.05); - display: grid; grid-template-columns: 270px minmax(0, 1fr); min-height: 100vh; - color: var(--lab-text); - background: var(--lab-bg); -} - -.lab-shell[data-lab-scheme="dark"] { - --lab-bg: #111111; - --lab-surface: #181818; - --lab-surface-subtle: #202020; - --lab-surface-hover: #282828; - --lab-surface-selected: #303030; - --lab-border: #303030; - --lab-border-strong: #404040; - --lab-text: #f4f4f4; - --lab-text-secondary: #bcbcbc; - --lab-text-muted: #888888; - --lab-inverse: #171717; - --lab-inverse-bg: #f1f1ee; - --lab-danger: #ff958b; - --lab-shadow: 0 18px 48px rgb(0 0 0 / 0.34); - --lab-shadow-soft: 0 10px 32px rgb(0 0 0 / 0.22); - - color-scheme: dark; + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-canvas); + font-family: var(--bf-font-family-sans); } .lab-sidebar { @@ -92,8 +54,8 @@ body, grid-template-rows: auto minmax(0, 1fr) auto; height: 100vh; overflow: hidden; - border-right: 1px solid var(--lab-border); - background: var(--lab-surface); + border-right: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-panel); } .lab-sidebar-backdrop { @@ -107,7 +69,7 @@ body, gap: 11px; min-height: 74px; padding: 14px 18px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .lab-brand__mark { @@ -115,9 +77,9 @@ body, width: 34px; height: 34px; place-items: center; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 10px; - background: var(--lab-surface-subtle); + background: var(--bf-color-surface-tertiary); } .lab-brand > span:nth-child(2) { @@ -137,7 +99,7 @@ body, .lab-brand small { overflow: hidden; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-micro); text-overflow: ellipsis; white-space: nowrap; @@ -165,7 +127,7 @@ body, .lab-nav-label, .page-kicker { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-micro); font-weight: var(--bf-font-weight-semibold); letter-spacing: var(--bf-letter-spacing-caps); @@ -190,7 +152,7 @@ body, min-height: 38px; padding: 7px 10px; border-radius: 8px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); text-decoration: none; transition: color 120ms ease, background-color 120ms ease; @@ -198,18 +160,18 @@ body, .lab-navigation > a:hover, .lab-component-links a:hover { - color: var(--lab-text); - background: var(--lab-surface-hover); + color: var(--bf-color-content-primary); + background: var(--bf-color-action-quiet-hover); } .lab-navigation a[aria-current="page"] { - color: var(--lab-text); - background: var(--lab-surface-selected); + color: var(--bf-color-content-primary); + background: var(--bf-color-action-quiet-pressed); font-weight: var(--bf-font-weight-semibold); } .lab-navigation a small { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-2xs); font-weight: var(--bf-font-weight-medium); text-transform: capitalize; @@ -233,10 +195,10 @@ body, gap: 12px; margin: 12px; padding: 10px 12px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 9px; - color: var(--lab-text-secondary); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-micro); text-transform: capitalize; } @@ -254,8 +216,8 @@ body, gap: 10px; min-height: 74px; padding: 14px 28px; - border-bottom: 1px solid var(--lab-border); - background: var(--lab-surface); + border-bottom: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-panel); } .topbar-menu-button, @@ -265,7 +227,7 @@ body, place-items: center; padding: 0; border: 1px solid transparent; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); background: transparent; cursor: pointer; } @@ -283,9 +245,9 @@ body, .topbar-menu-button:hover, .topbar-icon-button:hover { - color: var(--lab-text); - border-color: var(--lab-border); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-primary); + border-color: var(--bf-color-border-subtle); + background: var(--bf-color-surface-tertiary); } .lab-search { @@ -297,16 +259,16 @@ body, min-width: 260px; height: 42px; padding: 0 10px 0 14px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 999px; - color: var(--lab-text-muted); - background: var(--lab-surface); + color: var(--bf-color-content-muted); + background: var(--bf-color-surface-panel); transition: border-color 120ms ease, box-shadow 120ms ease; } .lab-search:focus-within { - border-color: var(--lab-text-muted); - box-shadow: 0 0 0 3px color-mix(in srgb, var(--lab-text) 8%, transparent); + border-color: var(--bf-color-content-muted); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--bf-color-content-primary) 8%, transparent); } .lab-search input { @@ -315,13 +277,13 @@ body, padding: 0 10px; border: 0; outline: 0; - color: var(--lab-text); + color: var(--bf-color-content-primary); background: transparent; font-size: var(--bf-font-size-xs); } .lab-search input::placeholder { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); } .lab-search input::-webkit-search-cancel-button { @@ -330,10 +292,10 @@ body, .lab-search kbd { padding: 3px 6px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 6px; - color: var(--lab-text-muted); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-muted); + background: var(--bf-color-surface-tertiary); font-family:var(--bf-font-family-sans); font-size: var(--bf-font-size-2xs); } @@ -347,10 +309,10 @@ body, max-height: min(480px, calc(100vh - 110px)); overflow: auto; padding: 7px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 12px; - background: var(--lab-surface); - box-shadow: var(--lab-shadow); + background: var(--bf-color-surface-panel); + box-shadow: var(--bf-shadow-overlay); } .lab-search-results button { @@ -370,7 +332,7 @@ body, .lab-search-results button:hover, .lab-search-results button:focus-visible { outline: 0; - background: var(--lab-surface-hover); + background: var(--bf-color-action-quiet-hover); } .lab-search-results button > span:first-child { @@ -378,10 +340,10 @@ body, width: 30px; height: 30px; place-items: center; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; - color: var(--lab-text-secondary); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-tertiary); } .lab-search-results button > span:last-child { @@ -390,13 +352,13 @@ body, } .lab-search-results strong { - color: var(--lab-text); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-xs); } .lab-search-results small, .lab-search-results p { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-micro); } @@ -414,14 +376,14 @@ body, } .topbar-links a { - color: var(--lab-text); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-semibold); text-decoration: none; } .topbar-links a:hover { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); } .lab-language-control { @@ -434,15 +396,15 @@ body, padding: 0 9px; border: 1px solid transparent; border-radius: 9px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); background: transparent; } .lab-language-control:hover, .lab-language-control:focus-within { - border-color: var(--lab-border); - color: var(--lab-text); - background: var(--lab-surface-subtle); + border-color: var(--bf-color-border-subtle); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-tertiary); } .lab-language-control select { @@ -471,10 +433,10 @@ body, gap: 13px; width: 280px; padding: 16px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 12px; - background: var(--lab-surface); - box-shadow: var(--lab-shadow); + background: var(--bf-color-surface-panel); + box-shadow: var(--bf-shadow-overlay); } .lab-settings-panel__heading { @@ -483,7 +445,7 @@ body, justify-content: space-between; gap: 12px; padding-bottom: 12px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .lab-settings-panel__heading > div { @@ -497,7 +459,7 @@ body, .lab-settings-panel__heading span, .lab-settings-panel label > span { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-micro); } @@ -522,10 +484,10 @@ body, .token-tools select { min-height: 36px; padding: 6px 30px 6px 10px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 8px; - color: var(--lab-text); - background: var(--lab-surface); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-meta); } @@ -535,9 +497,9 @@ body, justify-content: space-between; min-height: 36px; padding: 7px 10px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; - background: var(--lab-surface-subtle); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-meta); cursor: pointer; } @@ -548,7 +510,7 @@ body, height: 20px; place-items: center; border-radius: 999px; - background: var(--lab-surface-selected); + background: var(--bf-color-action-quiet-pressed); font-size: var(--bf-font-size-2xs); } @@ -600,7 +562,7 @@ body, .page-heading p { max-width: 680px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-relaxed); } @@ -613,10 +575,10 @@ body, gap: 8px; min-height: 38px; padding: 8px 14px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 999px; - color: var(--lab-text); - background: var(--lab-surface); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-semibold); cursor: pointer; @@ -624,20 +586,20 @@ body, .lab-button:hover, .token-action-row button:hover:not(:disabled) { - background: var(--lab-surface-hover); + background: var(--bf-color-action-quiet-hover); } .lab-button--primary, .token-action-row .token-save-button { - border-color: var(--lab-inverse-bg); - color: var(--lab-inverse); - background: var(--lab-inverse-bg); + border-color: var(--bf-color-action-primary-background); + color: var(--bf-color-content-inverse); + background: var(--bf-color-action-primary-background); } .lab-button--primary:hover, .token-action-row .token-save-button:hover:not(:disabled) { opacity: 0.88; - background: var(--lab-inverse-bg); + background: var(--bf-color-action-primary-background); } .lab-button:focus-visible, @@ -652,7 +614,7 @@ body, .token-category-tabs button:focus-visible, .token-table__row:focus-visible, .copy-value-row:focus-visible { - outline: 2px solid var(--lab-text); + outline: 2px solid var(--bf-color-content-primary); outline-offset: 2px; } @@ -678,10 +640,10 @@ body, .page-version { padding: 5px 10px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 999px; - color: var(--lab-text-secondary); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-micro); font-weight: var(--bf-font-weight-semibold); } @@ -698,7 +660,7 @@ body, .overview-copy p { max-width: 580px; margin: 0; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xl); line-height: var(--bf-line-height-relaxed); } @@ -738,14 +700,14 @@ body, width: 42px; height: 42px; place-items: center; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 999px; - color: var(--lab-text); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-tertiary); } .component-card__category { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-2xs); letter-spacing: var(--bf-letter-spacing-widest); text-transform: uppercase; @@ -758,8 +720,8 @@ body, gap: 24px; margin-top: 56px; padding-top: 22px; - border-top: 1px solid var(--lab-border); - color: var(--lab-text-muted); + border-top: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-micro); } @@ -768,9 +730,9 @@ body, display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 26px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 11px; - background: var(--lab-surface-subtle); + background: var(--bf-color-surface-tertiary); } .component-summary-strip > span { @@ -779,8 +741,8 @@ body, gap: 6px; min-height: 58px; padding: 12px 16px; - border-right: 1px solid var(--lab-border); - color: var(--lab-text-secondary); + border-right: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-micro); } @@ -789,7 +751,7 @@ body, } .component-summary-strip strong { - color: var(--lab-text); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-lg); } @@ -816,7 +778,7 @@ body, .component-library-section-heading h2 { margin: 0; - color: var(--lab-text); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-3xl); letter-spacing: var(--bf-letter-spacing-tight); } @@ -824,7 +786,7 @@ body, .component-library-section-heading p { max-width: 720px; margin: 0; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-base); } @@ -968,9 +930,9 @@ body, gap: 48px; margin-top: 34px; padding: 28px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 12px; - background: var(--lab-surface-subtle); + background: var(--bf-color-surface-tertiary); } .primitive-note > div { @@ -979,7 +941,7 @@ body, } .primitive-note p { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); line-height: var(--bf-line-height-spacious); } @@ -992,14 +954,14 @@ body, margin-bottom: 24px; padding: 0; border: 0; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); background: transparent; font-size: var(--bf-font-size-micro); cursor: pointer; } .breadcrumb-back:hover { - color: var(--lab-text); + color: var(--bf-color-content-primary); } .component-detail-content { @@ -1012,15 +974,15 @@ body, display: grid; grid-template-columns: 220px minmax(0, 1fr); overflow: hidden; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 12px; - background: var(--lab-surface); - box-shadow: var(--lab-shadow-soft); + background: var(--bf-color-surface-panel); + box-shadow: var(--bf-shadow-menu); } .component-config-panel { - border-right: 1px solid var(--lab-border); - background: var(--lab-surface-subtle); + border-right: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-tertiary); } .preview-choice-group { @@ -1029,7 +991,7 @@ body, margin: 0; padding: 17px; border: 0; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .preview-choice-group:last-child { @@ -1038,7 +1000,7 @@ body, .preview-choice-group legend { padding: 0; - color: var(--lab-text); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-micro); font-weight: var(--bf-font-weight-semibold); } @@ -1052,19 +1014,19 @@ body, .preview-choice-group button { min-height: 29px; padding: 5px 9px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 7px; - color: var(--lab-text-secondary); - background: var(--lab-surface); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-2xs); text-transform: capitalize; cursor: pointer; } .preview-choice-group button[data-active] { - border-color: var(--lab-inverse-bg); - color: var(--lab-inverse); - background: var(--lab-inverse-bg); + border-color: var(--bf-color-action-primary-background); + color: var(--bf-color-content-inverse); + background: var(--bf-color-action-primary-background); } .component-preview-column { @@ -1135,8 +1097,8 @@ input.lab-force-focus { .component-code-panel { overflow: hidden; - border-top: 1px solid var(--lab-border); - background: var(--lab-surface-subtle); + border-top: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-tertiary); } .component-code-panel__header { @@ -1146,7 +1108,7 @@ input.lab-force-focus { gap: 12px; min-height: 38px; padding: 7px 12px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); font-size: var(--bf-font-size-2xs); font-weight: var(--bf-font-weight-semibold); } @@ -1156,9 +1118,9 @@ input.lab-force-focus { align-items: center; gap: 6px; padding: 4px 7px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 6px; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-2xs); cursor: pointer; } @@ -1168,7 +1130,7 @@ input.lab-force-focus { margin: 0; overflow: auto; padding: 16px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-micro); line-height: var(--bf-line-height-relaxed); @@ -1183,9 +1145,9 @@ input.lab-force-focus { .component-guidance-grid > section, .component-reference-panel { padding: 20px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 11px; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); } .component-guidance-grid > section { @@ -1213,14 +1175,14 @@ input.lab-force-focus { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-micro); line-height: var(--bf-line-height-comfortable); } .component-guidance-grid li svg { margin-top: 1px; - color: var(--lab-text); + color: var(--bf-color-content-primary); } .reference-panel__heading { @@ -1238,7 +1200,7 @@ input.lab-force-focus { .reference-panel__heading > span, .text-action { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-2xs); } @@ -1246,7 +1208,7 @@ input.lab-force-focus { justify-self: start; padding: 0; border: 0; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); background: transparent; text-decoration: underline; text-underline-offset: 3px; @@ -1256,7 +1218,7 @@ input.lab-force-focus { .props-table { min-width: 0; overflow: auto; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; } @@ -1264,7 +1226,7 @@ input.lab-force-focus { display: grid; grid-template-columns: minmax(100px, 0.7fr) minmax(240px, 1.5fr) minmax(100px, 0.7fr); min-width: 540px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .props-table__row:last-child { @@ -1273,8 +1235,8 @@ input.lab-force-focus { .props-table__row > * { padding: 10px 12px; - border-right: 1px solid var(--lab-border); - color: var(--lab-text-secondary); + border-right: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-2xs); } @@ -1283,11 +1245,11 @@ input.lab-force-focus { } .props-table__row--header { - background: var(--lab-surface-subtle); + background: var(--bf-color-surface-tertiary); } .props-table__row--header > * { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-family:var(--bf-font-family-sans); font-weight: var(--bf-font-weight-semibold); text-transform: uppercase; @@ -1303,10 +1265,10 @@ input.lab-force-focus { .token-chip-list code, .token-owner-list span { padding: 5px 7px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 6px; - color: var(--lab-text-secondary); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-2xs); } @@ -1322,10 +1284,10 @@ input.lab-force-focus { .reference-color-palette { margin-bottom: 26px; overflow: hidden; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 12px; - background: var(--lab-surface); - box-shadow: var(--lab-shadow-soft); + background: var(--bf-color-surface-panel); + box-shadow: var(--bf-shadow-menu); } .reference-color-palette__heading { @@ -1334,7 +1296,7 @@ input.lab-force-focus { justify-content: space-between; gap: 24px; padding: 18px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .reference-color-palette__heading > div:first-child { @@ -1350,7 +1312,7 @@ input.lab-force-focus { .reference-color-palette__heading p, .reference-color-palette__contract { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-micro); line-height: var(--bf-line-height-comfortable); } @@ -1363,10 +1325,10 @@ input.lab-force-focus { .reference-color-palette__summary span { padding: 5px 7px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 999px; - color: var(--lab-text-muted); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-muted); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-3xs); white-space: nowrap; } @@ -1380,7 +1342,7 @@ input.lab-force-focus { grid-template-columns: 112px minmax(0, 1fr); min-width: 0; padding: 14px 16px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .reference-color-scale > header { @@ -1396,7 +1358,7 @@ input.lab-force-focus { } .reference-color-scale > header span { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-3xs); } @@ -1406,7 +1368,7 @@ input.lab-force-focus { grid-auto-flow: column; min-width: 0; overflow-x: auto; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; } @@ -1415,8 +1377,8 @@ input.lab-force-focus { grid-template-rows: 38px auto auto; min-width: 58px; padding-bottom: 6px; - border-right: 1px solid var(--lab-border); - background: var(--lab-surface); + border-right: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-panel); } .reference-color-step:last-child { @@ -1426,7 +1388,7 @@ input.lab-force-focus { .reference-color-step__swatch { display: block; width: 100%; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .reference-color-step strong, @@ -1439,20 +1401,20 @@ input.lab-force-focus { .reference-color-step strong { margin-top: 6px; - color: var(--lab-text); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-3xs); font-weight: var(--bf-font-weight-semibold); } .reference-color-step code { margin-top: 2px; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-4xs); } .reference-color-palette__contract { padding: 10px 16px; - background: var(--lab-surface-subtle); + background: var(--bf-color-surface-tertiary); } .token-page-actions { @@ -1465,7 +1427,7 @@ input.lab-force-focus { display: flex; align-items: center; gap: 7px; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-2xs); } @@ -1473,16 +1435,16 @@ input.lab-force-focus { width: 7px; height: 7px; border-radius: 999px; - background: var(--lab-text-muted); + background: var(--bf-color-content-muted); } .token-source-status > span:first-child[data-ready] { - background: var(--lab-text); + background: var(--bf-color-content-primary); } .token-save-error, .token-error { - color: var(--lab-danger); + color: var(--bf-color-status-danger-content); font-size: var(--bf-font-size-2xs); } @@ -1507,7 +1469,7 @@ input.lab-force-focus { .token-edit-count { margin-right: 4px; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-2xs); } @@ -1517,7 +1479,7 @@ input.lab-force-focus { overflow-x: auto; margin-bottom: 0; padding: 0 10px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .token-category-tabs button { @@ -1525,15 +1487,15 @@ input.lab-force-focus { padding: 11px 9px 10px; border: 0; border-bottom: 2px solid transparent; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); background: transparent; font-size: var(--bf-font-size-micro); cursor: pointer; } .token-category-tabs button[data-active] { - border-bottom-color: var(--lab-text); - color: var(--lab-text); + border-bottom-color: var(--bf-color-content-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-semibold); } @@ -1542,18 +1504,18 @@ input.lab-force-focus { grid-template-columns: minmax(0, 1fr) 344px; min-height: 650px; margin-top: 0; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-top: 0; border-radius: 0 0 12px 12px; - background: var(--lab-surface); - box-shadow: var(--lab-shadow-soft); + background: var(--bf-color-surface-panel); + box-shadow: var(--bf-shadow-menu); } .token-catalog-panel { display: grid; grid-template-rows: auto minmax(0, 1fr); min-width: 0; - border-right: 1px solid var(--lab-border); + border-right: 1px solid var(--bf-color-border-subtle); } .token-tools { @@ -1561,7 +1523,7 @@ input.lab-force-focus { grid-template-columns: minmax(220px, 1fr) minmax(130px, 0.45fr) minmax(150px, 0.55fr); gap: 8px; padding: 14px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .token-search-field { @@ -1570,10 +1532,10 @@ input.lab-force-focus { align-items: center; min-height: 36px; padding: 0 10px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 8px; - color: var(--lab-text-muted); - background: var(--lab-surface); + color: var(--bf-color-content-muted); + background: var(--bf-color-surface-panel); } .token-search-field input { @@ -1582,7 +1544,7 @@ input.lab-force-focus { padding: 0 8px; border: 0; outline: 0; - color: var(--lab-text); + color: var(--bf-color-content-primary); background: transparent; font-size: var(--bf-font-size-micro); } @@ -1603,9 +1565,9 @@ input.lab-force-focus { .token-table__header { min-height: 40px; padding: 0 14px; - border-bottom: 1px solid var(--lab-border); - color: var(--lab-text-muted); - background: var(--lab-surface-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-muted); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-2xs); font-weight: var(--bf-font-weight-semibold); } @@ -1621,20 +1583,20 @@ input.lab-force-focus { min-height: 58px; padding: 0 14px; border: 0; - border-bottom: 1px solid var(--lab-border); - color: var(--lab-text); - background: var(--lab-surface); + border-bottom: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-panel); text-align: left; cursor: pointer; } .token-table__row:hover { - background: var(--lab-surface-hover); + background: var(--bf-color-action-quiet-hover); } .token-table__row[data-active] { - background: var(--lab-surface-selected); - box-shadow: inset 2px 0 var(--lab-text); + background: var(--bf-color-action-quiet-pressed); + box-shadow: inset 2px 0 var(--bf-color-content-primary); } .token-table__row[data-edited]::after { @@ -1644,7 +1606,7 @@ input.lab-force-focus { width: 6px; height: 6px; border-radius: 999px; - background: var(--lab-text); + background: var(--bf-color-content-primary); content: ""; } @@ -1671,7 +1633,7 @@ input.lab-force-focus { .token-table__row code { overflow: hidden; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-2xs); text-overflow: ellipsis; @@ -1679,15 +1641,15 @@ input.lab-force-focus { } .token-table__row > span:last-child { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-2xs); } .token-table__row > span:last-child i { padding: 2px 5px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 999px; - color: var(--lab-text); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-3xs); font-style: normal; } @@ -1696,7 +1658,7 @@ input.lab-force-focus { flex: 0 0 auto; width: 24px; height: 24px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 6px; } @@ -1707,8 +1669,8 @@ input.lab-force-focus { gap: 16px; min-height: 42px; padding: 8px 14px; - color: var(--lab-text-muted); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-muted); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-2xs); text-transform: capitalize; } @@ -1718,7 +1680,7 @@ input.lab-force-focus { min-height: 220px; place-items: center; padding: 24px; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-micro); text-align: center; } @@ -1732,13 +1694,13 @@ input.lab-force-focus { min-width: 0; max-height: calc(100vh - 112px); overflow: auto; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); } .token-inspector__heading, .token-inspector__section { padding: 18px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .token-inspector__heading { @@ -1765,10 +1727,10 @@ input.lab-force-focus { align-items: center; gap: 4px; padding: 4px 6px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 999px; - color: var(--lab-text-secondary); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-3xs); } @@ -1791,12 +1753,12 @@ input.lab-force-focus { } .token-inspector__label-row span { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-3xs); } .token-inspector p { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-micro); line-height: var(--bf-line-height-relaxed); } @@ -1811,25 +1773,25 @@ input.lab-force-focus { width: 38px; height: 38px; padding: 3px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 8px; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); } .token-value-input { min-width: 0; height: 38px; padding: 6px 9px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 8px; - color: var(--lab-text); - background: var(--lab-surface); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-panel); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-micro); } .token-value-input[aria-invalid="true"] { - border-color: var(--lab-danger); + border-color: var(--bf-color-status-danger-content); } .token-error { @@ -1844,10 +1806,10 @@ input.lab-force-focus { min-width: 0; min-height: 38px; padding: 7px 9px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; - color: var(--lab-text-secondary); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-tertiary); cursor: pointer; } @@ -1863,7 +1825,7 @@ input.lab-force-focus { align-items: center; justify-content: space-between; gap: 14px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-2xs); text-transform: capitalize; } @@ -1873,7 +1835,7 @@ input.lab-force-focus { min-height: 260px; place-items: center; padding: 32px; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-micro); line-height: var(--bf-line-height-relaxed); text-align: center; @@ -1882,9 +1844,9 @@ input.lab-force-focus { .token-system-preview { margin-top: 26px; overflow: hidden; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 12px; - box-shadow: var(--lab-shadow-soft); + box-shadow: var(--bf-shadow-menu); } .token-preview-theme-host { @@ -2140,7 +2102,7 @@ input.lab-force-focus { position: static; grid-template-columns: repeat(2, minmax(0, 1fr)); max-height: none; - border-top: 1px solid var(--lab-border); + border-top: 1px solid var(--bf-color-border-subtle); } .token-inspector__heading { @@ -2148,7 +2110,7 @@ input.lab-force-focus { } .token-inspector__section { - border-right: 1px solid var(--lab-border); + border-right: 1px solid var(--bf-color-border-subtle); } .token-inspector__meta { @@ -2179,7 +2141,7 @@ input.lab-force-focus { inset: 0; display: block; border: 0; - background: rgb(0 0 0 / 0.34); + background: var(--bf-color-overlay-scrim); opacity: 0; pointer-events: none; transition: opacity 180ms ease; @@ -2220,11 +2182,11 @@ input.lab-force-focus { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-right: 0; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .preview-choice-group { - border-right: 1px solid var(--lab-border); + border-right: 1px solid var(--bf-color-border-subtle); border-bottom: 0; } @@ -2321,7 +2283,7 @@ input.lab-force-focus { .component-summary-strip > span { border-right: 0; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .component-summary-strip > span:last-child { @@ -2338,7 +2300,7 @@ input.lab-force-focus { .preview-choice-group { border-right: 0; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .preview-choice-group:last-child { @@ -2505,7 +2467,7 @@ input.lab-force-focus { min-height: 42px; margin: 14px 20px 24px; padding: 8px 11px; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-meta); } @@ -2515,7 +2477,7 @@ input.lab-force-focus { gap: 6px; padding: 0; border: 0; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); background: transparent; font-size: var(--bf-font-size-micro); text-transform: capitalize; @@ -2589,7 +2551,7 @@ input.lab-force-focus { .guide-hero > p { max-width: 720px; margin: 0; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-lg); line-height: var(--bf-line-height-spacious); } @@ -2597,9 +2559,9 @@ input.lab-force-focus { .guide-step-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 12px; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); } .guide-step-grid article { @@ -2609,7 +2571,7 @@ input.lab-force-focus { gap: 10px; min-height: 250px; padding: 28px; - border-right: 1px solid var(--lab-border); + border-right: 1px solid var(--bf-color-border-subtle); } .guide-step-grid article:last-child { @@ -2620,7 +2582,7 @@ input.lab-force-focus { position: absolute; top: 24px; right: 24px; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-micro); } @@ -2631,9 +2593,9 @@ input.lab-force-focus { width: 40px; height: 40px; place-items: center; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 10px; - background: var(--lab-surface-subtle); + background: var(--bf-color-surface-tertiary); } .guide-step-grid h2 { @@ -2647,7 +2609,7 @@ input.lab-force-focus { .guide-next-panel p, .resource-boundary-panel p { margin: 0; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); line-height: var(--bf-line-height-spacious); } @@ -2658,9 +2620,9 @@ input.lab-force-focus { gap: 48px; align-items: center; padding: 34px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 12px; - background: var(--lab-surface-subtle); + background: var(--bf-color-surface-tertiary); } .guide-contract-copy { @@ -2687,17 +2649,17 @@ input.lab-force-focus { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); line-height: var(--bf-line-height-comfortable); } .guide-code-card { overflow: hidden; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 10px; - background: var(--lab-surface); - box-shadow: var(--lab-shadow-soft); + background: var(--bf-color-surface-panel); + box-shadow: var(--bf-shadow-menu); } .guide-code-card > div { @@ -2706,8 +2668,8 @@ input.lab-force-focus { gap: 7px; min-height: 40px; padding: 8px 13px; - border-bottom: 1px solid var(--lab-border); - color: var(--lab-text-secondary); + border-bottom: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-micro); } @@ -2715,7 +2677,7 @@ input.lab-force-focus { margin: 0; overflow: auto; padding: 20px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-meta); line-height: var(--bf-line-height-loose); @@ -2728,7 +2690,7 @@ input.lab-force-focus { justify-content: space-between; gap: 30px; padding: 28px 0; - border-top: 1px solid var(--lab-border); + border-top: 1px solid var(--bf-color-border-subtle); } .guide-next-panel > div, @@ -2750,7 +2712,7 @@ input.lab-force-focus { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 28px; - border-block: 1px solid var(--lab-border); + border-block: 1px solid var(--bf-color-border-subtle); } .resource-fact-strip span { @@ -2759,8 +2721,8 @@ input.lab-force-focus { gap: 8px; min-height: 74px; padding: 18px 24px; - border-right: 1px solid var(--lab-border); - color: var(--lab-text-secondary); + border-right: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); } @@ -2769,7 +2731,7 @@ input.lab-force-focus { } .resource-fact-strip strong { - color: var(--lab-text); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-4xl); letter-spacing: var(--bf-letter-spacing-tight); } @@ -2787,16 +2749,16 @@ input.lab-force-focus { gap: 14px; min-height: 112px; padding: 20px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 11px; - color: var(--lab-text); - background: var(--lab-surface); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-panel); text-decoration: none; } .resource-grid a:hover { - border-color: var(--lab-border-strong); - background: var(--lab-surface-subtle); + border-color: var(--bf-color-border-default); + background: var(--bf-color-surface-tertiary); } .resource-grid a > span:nth-child(2) { @@ -2809,7 +2771,7 @@ input.lab-force-focus { } .resource-grid small { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); line-height: var(--bf-line-height-comfortable); } @@ -2845,7 +2807,7 @@ input.lab-force-focus { gap: clamp(28px, 4vw, 64px); align-items: start; padding-block-start: 30px; - border-block-start: 1px solid var(--lab-border); + border-block-start: 1px solid var(--bf-color-border-subtle); } .pattern-section__heading { @@ -2855,7 +2817,7 @@ input.lab-force-focus { } .pattern-section__heading > span { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-micro); } @@ -2878,7 +2840,7 @@ input.lab-force-focus { .pattern-section__heading p, .pattern-navigation-copy p { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); line-height: var(--bf-line-height-relaxed); } @@ -2906,7 +2868,7 @@ input.lab-force-focus { overflow: hidden; border: 1px solid var(--bf-color-border-subtle); border-radius: var(--bf-radius-lg); - background: var(--bf-color-surface-base); + background: var(--bf-color-surface-panel); } .pattern-navigation-stage > [data-bf-component="navigation-panel"] { @@ -3136,7 +3098,7 @@ input.lab-force-focus { align-items: center; gap: 7px; margin-bottom: 14px; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); } @@ -3150,7 +3112,7 @@ input.lab-force-focus { .component-breadcrumb button:hover, .component-breadcrumb span { - color: var(--lab-text); + color: var(--bf-color-content-primary); } .component-detail-heading { @@ -3181,7 +3143,7 @@ input.lab-force-focus { .component-detail-heading p { max-width: 680px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-base); line-height: var(--bf-line-height-comfortable); } @@ -3194,10 +3156,10 @@ input.lab-force-focus { .component-meta-row span { padding: 4px 7px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 6px; - color: var(--lab-text-secondary); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-2xs); text-transform: capitalize; } @@ -3219,7 +3181,7 @@ input.lab-force-focus { gap: 16px; min-height: 52px; padding: 9px 12px 9px 18px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .component-workbench__toolbar > span, @@ -3243,15 +3205,15 @@ input.lab-force-focus { gap: 6px; min-height: 31px; padding: 6px 9px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 7px; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-2xs); cursor: pointer; } .component-workbench__toolbar button:hover { - background: var(--lab-surface-hover); + background: var(--bf-color-action-quiet-hover); } .component-workbench__body { @@ -3260,8 +3222,8 @@ input.lab-force-focus { } .component-config-panel { - border-right: 1px solid var(--lab-border); - background: var(--lab-surface); + border-right: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-panel); } .preview-choice-group { @@ -3343,11 +3305,11 @@ input.lab-force-focus { display: grid; grid-template-columns: minmax(72px, 0.7fr) minmax(130px, 1.5fr) minmax(70px, 0.7fr); min-width: 310px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .compact-props-table > div:first-child { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-3xs); text-transform: uppercase; } @@ -3361,7 +3323,7 @@ input.lab-force-focus { min-width: 0; overflow-wrap: anywhere; padding: 7px 5px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-3xs); } @@ -3398,7 +3360,7 @@ input.lab-force-focus { .guide-step-grid article { min-height: 210px; border-right: 0; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .guide-step-grid article:last-child { @@ -3417,7 +3379,7 @@ input.lab-force-focus { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); border-right: 0; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } } @@ -3449,7 +3411,7 @@ input.lab-force-focus { .resource-fact-strip span { min-height: 60px; border-right: 0; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .resource-fact-strip span:last-child { @@ -3533,9 +3495,9 @@ input.lab-force-focus { .component-code-panel--standalone, .component-inspector { overflow: hidden; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 10px; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); } .component-panel-heading { @@ -3545,7 +3507,7 @@ input.lab-force-focus { gap: 20px; min-height: 72px; padding: 14px 22px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .component-panel-heading h2 { @@ -3556,7 +3518,7 @@ input.lab-force-focus { .component-panel-heading > span, .component-code-heading span { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-micro); text-transform: capitalize; } @@ -3565,7 +3527,7 @@ input.lab-force-focus { min-width: 0; overflow: auto; color: var(--bf-color-content-primary); - background: var(--lab-surface); + background: var(--bf-color-surface-panel); } .component-modal-preview-stage { @@ -3638,8 +3600,8 @@ input.lab-force-focus { } .component-card-media-visual svg { - inline-size: var(--bf-icon-size-lg); - block-size: var(--bf-icon-size-lg); + inline-size: var(--bf-control-icon-size-lg); + block-size: var(--bf-control-icon-size-lg); } .component-card-command-grid { @@ -3989,7 +3951,7 @@ input.lab-force-focus { border: var(--bf-border-width-default) solid var(--bf-color-border-subtle); border-radius: var(--bf-radius-md); color: var(--bf-color-content-primary); - background: var(--bf-color-surface-default); + background: var(--bf-color-surface-panel); } .component-icon-catalog__item code { @@ -4205,8 +4167,8 @@ input.lab-force-focus { } .component-code-panel--standalone { - border-top: 1px solid var(--lab-border); - background: var(--lab-surface); + border-top: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-panel); } .component-code-heading > div { @@ -4221,24 +4183,24 @@ input.lab-force-focus { gap: 6px; min-height: 34px; padding: 6px 10px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 7px; - color: var(--lab-text); - background: var(--lab-surface); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-2xs); cursor: pointer; } .component-code-heading button:hover { - background: var(--lab-surface-hover); + background: var(--bf-color-action-quiet-hover); } .component-code-panel--standalone pre { min-height: 320px; padding: 22px; border: 0; - color: var(--lab-text-secondary); - background: var(--lab-surface); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-xs); line-height: var(--bf-line-height-loose); } @@ -4257,8 +4219,8 @@ input.lab-force-focus { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); padding: 0 14px; - border-bottom: 1px solid var(--lab-border); - background: var(--lab-surface); + border-bottom: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-panel); } .component-inspector-tabs button { @@ -4266,14 +4228,14 @@ input.lab-force-focus { min-height: 68px; padding: 10px 8px; border: 0; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); background: transparent; font-size: var(--bf-font-size-xs); cursor: pointer; } .component-inspector-tabs button[aria-selected="true"] { - color: var(--lab-text); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-semibold); } @@ -4283,7 +4245,7 @@ input.lab-force-focus { left: 50%; width: 52px; height: 2px; - background: var(--lab-text); + background: var(--bf-color-content-primary); content: ""; transform: translateX(-50%); } @@ -4291,7 +4253,7 @@ input.lab-force-focus { .component-inspector-tabs button:focus-visible, .component-inspector-action:focus-visible, .component-code-heading button:focus-visible { - outline: 2px solid var(--lab-text); + outline: 2px solid var(--bf-color-content-primary); outline-offset: -2px; } @@ -4303,7 +4265,7 @@ input.lab-force-focus { display: grid; gap: 14px; padding: 20px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .component-inspector-content > section:last-child { @@ -4326,7 +4288,7 @@ input.lab-force-focus { grid-template-columns: minmax(82px, 0.7fr) minmax(0, 1.3fr); align-items: center; gap: 12px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); } @@ -4336,12 +4298,12 @@ input.lab-force-focus { align-items: center; gap: 12px; min-height: 38px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); } .component-inspector-toggle [data-bf-component="switch"] { - --bf-color-control-switch-track-checked: var(--lab-inverse-bg); + --bf-color-control-switch-track-checked: var(--bf-color-action-primary-background); justify-self: end; } @@ -4350,10 +4312,10 @@ input.lab-force-focus { min-width: 0; height: 38px; padding: 6px 30px 6px 10px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; - color: var(--lab-text); - background: var(--lab-surface); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-xs); cursor: pointer; } @@ -4383,7 +4345,7 @@ input.lab-force-focus { .component-inspector-props { display: grid; - border-block: 1px solid var(--lab-border); + border-block: 1px solid var(--bf-color-border-subtle); } .component-inspector-props > div { @@ -4392,7 +4354,7 @@ input.lab-force-focus { gap: 8px; align-items: start; padding: 9px 10px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .component-inspector-props > div:last-child { @@ -4404,22 +4366,22 @@ input.lab-force-focus { .component-inspector-props small { min-width: 0; overflow-wrap: anywhere; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-3xs); } .component-inspector-props code { - color: var(--lab-text); + color: var(--bf-color-content-primary); } .component-inspector-props small { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); } .component-inspector-facts { display: grid; margin: 0; - border-block: 1px solid var(--lab-border); + border-block: 1px solid var(--bf-color-border-subtle); } .component-inspector-facts > div { @@ -4428,7 +4390,7 @@ input.lab-force-focus { justify-content: space-between; gap: 16px; min-height: 42px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .component-inspector-facts > div:last-child { @@ -4438,12 +4400,12 @@ input.lab-force-focus { .component-inspector-facts dt, .component-inspector-facts dd { margin: 0; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-micro); } .component-inspector-facts dd { - color: var(--lab-text); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-semibold); text-transform: capitalize; } @@ -4458,10 +4420,10 @@ input.lab-force-focus { .component-inspector-chip-list span, .component-inspector-token-list code { padding: 5px 7px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 6px; - color: var(--lab-text-secondary); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-tertiary); font-size: var(--bf-font-size-3xs); } @@ -4477,17 +4439,17 @@ input.lab-force-focus { .component-inspector-action { min-height: 36px; padding: 7px 10px; - border: 1px solid var(--lab-border-strong); + border: 1px solid var(--bf-color-border-default); border-radius: 8px; - color: var(--lab-text); - background: var(--lab-surface); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-micro); font-weight: var(--bf-font-weight-semibold); cursor: pointer; } .component-inspector-action:hover { - background: var(--lab-surface-hover); + background: var(--bf-color-action-quiet-hover); } @media (max-width: 1280px) { @@ -4557,12 +4519,12 @@ input.lab-force-focus { align-items: center; gap: 9px; margin-bottom: 20px; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); } .colors-breadcrumb strong { - color: var(--lab-text); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-semibold); } @@ -4593,7 +4555,7 @@ input.lab-force-focus { } .colors-heading-copy p { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-base); line-height: var(--bf-line-height-comfortable); } @@ -4610,7 +4572,7 @@ input.lab-force-focus { display: flex; align-items: center; gap: 9px; - color: var(--lab-text); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-semibold); white-space: nowrap; @@ -4620,7 +4582,7 @@ input.lab-force-focus { .colors-filter-field { position: relative; display: block; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); } .colors-select-field select, @@ -4629,11 +4591,11 @@ input.lab-force-focus { height: 40px; appearance: none; padding: 0 35px 0 12px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; outline: 0; - color: var(--lab-text); - background: var(--lab-surface); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-xs); cursor: pointer; } @@ -4663,14 +4625,8 @@ input.lab-force-focus { .colors-select-field select:focus-visible, .colors-filter-field select:focus-visible, .colors-search-field:focus-within { - border-color: var(--lab-border-strong); - box-shadow: 0 0 0 3px rgb(0 0 0 / 0.055); -} - -.lab-shell[data-lab-scheme="dark"] .colors-select-field select:focus-visible, -.lab-shell[data-lab-scheme="dark"] .colors-filter-field select:focus-visible, -.lab-shell[data-lab-scheme="dark"] .colors-search-field:focus-within { - box-shadow: 0 0 0 3px rgb(255 255 255 / 0.08); + border-color: var(--bf-color-border-default); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--bf-color-focus-ring) 18%, transparent); } .colors-section-tabs { @@ -4678,7 +4634,7 @@ input.lab-force-focus { gap: 28px; overflow-x: auto; margin-top: 29px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .colors-section-tabs button { @@ -4686,21 +4642,21 @@ input.lab-force-focus { padding: 14px 1px 13px; border: 0; border-bottom: 2px solid transparent; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); background: transparent; font-size: var(--bf-font-size-sm); cursor: pointer; } .colors-section-tabs button[data-active] { - border-bottom-color: var(--lab-text); - color: var(--lab-text); + border-bottom-color: var(--bf-color-content-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-semibold); } .colors-section-tabs button:focus-visible, .colors-expand-button:focus-visible { - outline: 2px solid var(--lab-text); + outline: 2px solid var(--bf-color-content-primary); outline-offset: -2px; } @@ -4708,9 +4664,9 @@ input.lab-force-focus { scroll-margin-top: 92px; margin-top: 16px; overflow: hidden; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 11px; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); } .colors-card-heading { @@ -4720,7 +4676,7 @@ input.lab-force-focus { justify-content: space-between; gap: 24px; padding: 12px 16px 12px 22px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); } .colors-card-heading h2 { @@ -4736,7 +4692,7 @@ input.lab-force-focus { .colors-card-heading p { max-width: 760px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); line-height: var(--bf-line-height-comfortable); } @@ -4754,10 +4710,10 @@ input.lab-force-focus { width: 248px; height: 40px; padding: 0 12px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; - color: var(--lab-text-muted); - background: var(--lab-surface); + color: var(--bf-color-content-muted); + background: var(--bf-color-surface-panel); } .colors-search-field input { @@ -4766,13 +4722,13 @@ input.lab-force-focus { padding: 0 9px; border: 0; outline: 0; - color: var(--lab-text); + color: var(--bf-color-content-primary); background: transparent; font-size: var(--bf-font-size-xs); } .colors-search-field input::placeholder { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); } .colors-filter-field select { @@ -4813,8 +4769,8 @@ input.lab-force-focus { min-width: 0; height: 48px; padding: 9px 16px; - border-right: 1px solid var(--lab-border); - border-bottom: 1px solid var(--lab-border); + border-right: 1px solid var(--bf-color-border-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); text-align: left; } @@ -4824,8 +4780,8 @@ input.lab-force-focus { .semantic-color-table thead th { height: 46px; - color: var(--lab-text-secondary); - background: var(--lab-surface); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-semibold); white-space: nowrap; @@ -4833,7 +4789,7 @@ input.lab-force-focus { .semantic-color-table tbody th[scope="rowgroup"] { vertical-align: middle; - background: var(--lab-surface); + background: var(--bf-color-surface-panel); } .semantic-color-table tbody th[scope="row"] { @@ -4841,7 +4797,7 @@ input.lab-force-focus { } .semantic-color-table tbody td:last-child { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); line-height: var(--bf-line-height-base); } @@ -4849,7 +4805,7 @@ input.lab-force-focus { .semantic-color-table code, .colors-mapping-table code { overflow-wrap: anywhere; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-micro); font-weight: var(--bf-font-weight-medium); @@ -4875,45 +4831,45 @@ input.lab-force-focus { } .semantic-color-group small { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-regular); } .semantic-color-group--surface > i { - background: #dbeafe; + background: var(--bf-color-surface-panel); } .semantic-color-group--content > i { - background: #b6efd4; + background: var(--bf-color-content-primary); } .semantic-color-group--action > i { - background: #93c5fd; + background: var(--bf-color-action-primary-background); } .semantic-color-group--accent > i { - background: #bfdbfe; + background: var(--bf-color-accent-default); } .semantic-color-group--border > i { - background: #c9c9cc; + background: var(--bf-color-border-default); } .semantic-color-group--field > i { - background: #ededee; + background: var(--bf-color-field-background); } .semantic-color-group--control > i { - background: #83e2b8; + background: var(--bf-color-control-switch-track-checked); } .semantic-color-group--focus > i { - background: #60a5fa; + background: var(--bf-color-focus-ring); } .semantic-color-group--status > i { - background: #ffdc89; + background: var(--bf-color-status-warning-content); } .semantic-color-value { @@ -4927,9 +4883,9 @@ input.lab-force-focus { flex: 0 0 auto; width: 19px; height: 19px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 3px; - box-shadow: inset 0 0 0 0.5px rgb(0 0 0 / 0.035); + box-shadow: var(--bf-shadow-inner-highlight); } .semantic-color-value code { @@ -4940,7 +4896,7 @@ input.lab-force-focus { .semantic-color-table__empty td { height: 96px; - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); text-align: center; } @@ -4954,15 +4910,15 @@ input.lab-force-focus { gap: 9px; padding: 10px 22px; border: 0; - color: var(--lab-text-secondary); - background: var(--lab-surface); + color: var(--bf-color-content-secondary); + background: var(--bf-color-surface-panel); font-size: var(--bf-font-size-meta); cursor: pointer; } .colors-expand-button:hover { - color: var(--lab-text); - background: var(--lab-surface-subtle); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-tertiary); } .colors-expand-button svg { @@ -4983,7 +4939,7 @@ input.lab-force-focus { display: flex; align-items: center; gap: 10px; - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); } @@ -5013,19 +4969,19 @@ input.lab-force-focus { } .colors-scale-step strong { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-medium); } .colors-scale-step > span { display: block; - border: 1px solid rgb(0 0 0 / 0.035); + border: 1px solid var(--bf-color-border-subtle); border-radius: 6px; } .colors-scale-step code { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-micro); } @@ -5044,7 +5000,7 @@ input.lab-force-focus { gap: 14px; min-width: 0; padding: 13px; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; } @@ -5058,7 +5014,7 @@ input.lab-force-focus { } .colors-palette-row small { - color: var(--lab-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-2xs); } @@ -5068,7 +5024,7 @@ input.lab-force-focus { grid-auto-flow: column; height: 38px; overflow: hidden; - border: 1px solid var(--lab-border); + border: 1px solid var(--bf-color-border-subtle); border-radius: 6px; } @@ -5088,7 +5044,7 @@ input.lab-force-focus { .colors-mapping-table td { height: 46px; padding: 9px 18px; - border-bottom: 1px solid var(--lab-border); + border-bottom: 1px solid var(--bf-color-border-subtle); text-align: left; } @@ -5101,7 +5057,7 @@ input.lab-force-focus { } .colors-mapping-table thead th { - color: var(--lab-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-semibold); } diff --git a/design-system/apps/design-lab/src/token-editor/TokenWorkbench.tsx b/design-system/apps/design-lab/src/token-editor/TokenWorkbench.tsx index 266523f2c3..4f71553197 100644 --- a/design-system/apps/design-lab/src/token-editor/TokenWorkbench.tsx +++ b/design-system/apps/design-lab/src/token-editor/TokenWorkbench.tsx @@ -1,4 +1,5 @@ import { useEffect, useMemo, useState, type ReactNode } from "react"; +import { themes } from "@bitfun/theme-bitfun"; import { Check, Clipboard, @@ -142,7 +143,9 @@ function TokenValueControl({ className="token-color-picker" onChange={(event) => onChange(event.target.value)} type="color" - value={/^#[0-9a-f]{6}$/i.test(value) ? value : "#000000"} + value={/^#[0-9a-f]{6}$/i.test(value) + ? value + : String(themes.light["color.content.onLight"])} /> )} = 4.5, ); for (const status of ["info", "success", "warning", "danger"]) { - // The existing BitFun light Appearance warning pair is 4.38:1. Keep - // that single migration baseline exact instead of silently restyling - // the product; all other default and high-contrast pairs remain 4.5:1. - const minimumContrast = mode === "light" && status === "warning" ? 4.38 : 4.5; + const minimumContrast = 4.5; assert.ok( contrastRatio( variant[`color.status.${status}.surface`].value, diff --git a/design-system/packages/ui/src/components/Icon/assets/arrow-left.svg b/design-system/packages/ui/src/components/Icon/assets/arrow-left.svg index d4b37e1a6d..f0935e0ec7 100644 --- a/design-system/packages/ui/src/components/Icon/assets/arrow-left.svg +++ b/design-system/packages/ui/src/components/Icon/assets/arrow-left.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/arrow-right.svg b/design-system/packages/ui/src/components/Icon/assets/arrow-right.svg index 39b5c0bdd9..ddb167ef4c 100644 --- a/design-system/packages/ui/src/components/Icon/assets/arrow-right.svg +++ b/design-system/packages/ui/src/components/Icon/assets/arrow-right.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/arrow-up.svg b/design-system/packages/ui/src/components/Icon/assets/arrow-up.svg index ceaad590a3..1575dee313 100644 --- a/design-system/packages/ui/src/components/Icon/assets/arrow-up.svg +++ b/design-system/packages/ui/src/components/Icon/assets/arrow-up.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/arrow-upright.svg b/design-system/packages/ui/src/components/Icon/assets/arrow-upright.svg index a496346fc2..231f9f3c06 100644 --- a/design-system/packages/ui/src/components/Icon/assets/arrow-upright.svg +++ b/design-system/packages/ui/src/components/Icon/assets/arrow-upright.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/bell.svg b/design-system/packages/ui/src/components/Icon/assets/bell.svg index 1c2c2a7120..1c9a024434 100644 --- a/design-system/packages/ui/src/components/Icon/assets/bell.svg +++ b/design-system/packages/ui/src/components/Icon/assets/bell.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/browser.svg b/design-system/packages/ui/src/components/Icon/assets/browser.svg index 66d925a8e2..119c22548f 100644 --- a/design-system/packages/ui/src/components/Icon/assets/browser.svg +++ b/design-system/packages/ui/src/components/Icon/assets/browser.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/check-circle.svg b/design-system/packages/ui/src/components/Icon/assets/check-circle.svg index 79988a8aa9..c0c3345975 100644 --- a/design-system/packages/ui/src/components/Icon/assets/check-circle.svg +++ b/design-system/packages/ui/src/components/Icon/assets/check-circle.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/check-fill.svg b/design-system/packages/ui/src/components/Icon/assets/check-fill.svg index 50590d37f2..430a033b5e 100644 --- a/design-system/packages/ui/src/components/Icon/assets/check-fill.svg +++ b/design-system/packages/ui/src/components/Icon/assets/check-fill.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/check-line.svg b/design-system/packages/ui/src/components/Icon/assets/check-line.svg index 8fb135d15a..ecd239e9ac 100644 --- a/design-system/packages/ui/src/components/Icon/assets/check-line.svg +++ b/design-system/packages/ui/src/components/Icon/assets/check-line.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/chevron-down.svg b/design-system/packages/ui/src/components/Icon/assets/chevron-down.svg index 4dec14ccd3..23f3b909f6 100644 --- a/design-system/packages/ui/src/components/Icon/assets/chevron-down.svg +++ b/design-system/packages/ui/src/components/Icon/assets/chevron-down.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/chevron-right.svg b/design-system/packages/ui/src/components/Icon/assets/chevron-right.svg index de41eebaf3..e060378577 100644 --- a/design-system/packages/ui/src/components/Icon/assets/chevron-right.svg +++ b/design-system/packages/ui/src/components/Icon/assets/chevron-right.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/chevron-up.svg b/design-system/packages/ui/src/components/Icon/assets/chevron-up.svg index 4eac2397ee..078b2012d6 100644 --- a/design-system/packages/ui/src/components/Icon/assets/chevron-up.svg +++ b/design-system/packages/ui/src/components/Icon/assets/chevron-up.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/circle.svg b/design-system/packages/ui/src/components/Icon/assets/circle.svg index 0b643f55ba..0ee57499ad 100644 --- a/design-system/packages/ui/src/components/Icon/assets/circle.svg +++ b/design-system/packages/ui/src/components/Icon/assets/circle.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/clock.svg b/design-system/packages/ui/src/components/Icon/assets/clock.svg index c5e6f35ac0..34702f9def 100644 --- a/design-system/packages/ui/src/components/Icon/assets/clock.svg +++ b/design-system/packages/ui/src/components/Icon/assets/clock.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/command-mac.svg b/design-system/packages/ui/src/components/Icon/assets/command-mac.svg index 24e6bbb609..474211bef9 100644 --- a/design-system/packages/ui/src/components/Icon/assets/command-mac.svg +++ b/design-system/packages/ui/src/components/Icon/assets/command-mac.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/commit.svg b/design-system/packages/ui/src/components/Icon/assets/commit.svg index c0a04e8d3e..c65645f886 100644 --- a/design-system/packages/ui/src/components/Icon/assets/commit.svg +++ b/design-system/packages/ui/src/components/Icon/assets/commit.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/device-mac.svg b/design-system/packages/ui/src/components/Icon/assets/device-mac.svg index 7e6515e1f9..f323955e80 100644 --- a/design-system/packages/ui/src/components/Icon/assets/device-mac.svg +++ b/design-system/packages/ui/src/components/Icon/assets/device-mac.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/download.svg b/design-system/packages/ui/src/components/Icon/assets/download.svg index 95a245ae82..e5d5f1f738 100644 --- a/design-system/packages/ui/src/components/Icon/assets/download.svg +++ b/design-system/packages/ui/src/components/Icon/assets/download.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/duplicate.svg b/design-system/packages/ui/src/components/Icon/assets/duplicate.svg index 31b02cda09..ad7d0ba184 100644 --- a/design-system/packages/ui/src/components/Icon/assets/duplicate.svg +++ b/design-system/packages/ui/src/components/Icon/assets/duplicate.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/edit.svg b/design-system/packages/ui/src/components/Icon/assets/edit.svg index df46b32357..6c0b24a84a 100644 --- a/design-system/packages/ui/src/components/Icon/assets/edit.svg +++ b/design-system/packages/ui/src/components/Icon/assets/edit.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/extension.svg b/design-system/packages/ui/src/components/Icon/assets/extension.svg index 06fda65a37..dfed7ed920 100644 --- a/design-system/packages/ui/src/components/Icon/assets/extension.svg +++ b/design-system/packages/ui/src/components/Icon/assets/extension.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/eye.svg b/design-system/packages/ui/src/components/Icon/assets/eye.svg index adcaddb9ef..5598bf22b8 100644 --- a/design-system/packages/ui/src/components/Icon/assets/eye.svg +++ b/design-system/packages/ui/src/components/Icon/assets/eye.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/files.svg b/design-system/packages/ui/src/components/Icon/assets/files.svg index 6c98ca1607..a57f9a3847 100644 --- a/design-system/packages/ui/src/components/Icon/assets/files.svg +++ b/design-system/packages/ui/src/components/Icon/assets/files.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/filter.svg b/design-system/packages/ui/src/components/Icon/assets/filter.svg index 3cd4a748f2..00e7f06537 100644 --- a/design-system/packages/ui/src/components/Icon/assets/filter.svg +++ b/design-system/packages/ui/src/components/Icon/assets/filter.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/floating-window.svg b/design-system/packages/ui/src/components/Icon/assets/floating-window.svg index c51b9059f8..8c5609a267 100644 --- a/design-system/packages/ui/src/components/Icon/assets/floating-window.svg +++ b/design-system/packages/ui/src/components/Icon/assets/floating-window.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/folder.svg b/design-system/packages/ui/src/components/Icon/assets/folder.svg index a3eb294dd0..b559c1ac78 100644 --- a/design-system/packages/ui/src/components/Icon/assets/folder.svg +++ b/design-system/packages/ui/src/components/Icon/assets/folder.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/gear.svg b/design-system/packages/ui/src/components/Icon/assets/gear.svg index 69e74b9b00..65399288ae 100644 --- a/design-system/packages/ui/src/components/Icon/assets/gear.svg +++ b/design-system/packages/ui/src/components/Icon/assets/gear.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/git.svg b/design-system/packages/ui/src/components/Icon/assets/git.svg index 495f588bb4..a6784f8732 100644 --- a/design-system/packages/ui/src/components/Icon/assets/git.svg +++ b/design-system/packages/ui/src/components/Icon/assets/git.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/image.svg b/design-system/packages/ui/src/components/Icon/assets/image.svg index 0e16a96c90..6fd2495f0e 100644 --- a/design-system/packages/ui/src/components/Icon/assets/image.svg +++ b/design-system/packages/ui/src/components/Icon/assets/image.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/info.svg b/design-system/packages/ui/src/components/Icon/assets/info.svg index 2c583c972b..d0e463dd00 100644 --- a/design-system/packages/ui/src/components/Icon/assets/info.svg +++ b/design-system/packages/ui/src/components/Icon/assets/info.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/level.svg b/design-system/packages/ui/src/components/Icon/assets/level.svg index efb2867766..02cf96ba40 100644 --- a/design-system/packages/ui/src/components/Icon/assets/level.svg +++ b/design-system/packages/ui/src/components/Icon/assets/level.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/link.svg b/design-system/packages/ui/src/components/Icon/assets/link.svg index 6b429bed9f..0bfaa0eb27 100644 --- a/design-system/packages/ui/src/components/Icon/assets/link.svg +++ b/design-system/packages/ui/src/components/Icon/assets/link.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/mic.svg b/design-system/packages/ui/src/components/Icon/assets/mic.svg index 87184eaab5..4586baf8f1 100644 --- a/design-system/packages/ui/src/components/Icon/assets/mic.svg +++ b/design-system/packages/ui/src/components/Icon/assets/mic.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/mini-app.svg b/design-system/packages/ui/src/components/Icon/assets/mini-app.svg index a053675bec..5ae2a4b97b 100644 --- a/design-system/packages/ui/src/components/Icon/assets/mini-app.svg +++ b/design-system/packages/ui/src/components/Icon/assets/mini-app.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/more.svg b/design-system/packages/ui/src/components/Icon/assets/more.svg index 63af5adc10..f8fd292ea3 100644 --- a/design-system/packages/ui/src/components/Icon/assets/more.svg +++ b/design-system/packages/ui/src/components/Icon/assets/more.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/palette.svg b/design-system/packages/ui/src/components/Icon/assets/palette.svg index 7439b99b1f..42dbf5f17c 100644 --- a/design-system/packages/ui/src/components/Icon/assets/palette.svg +++ b/design-system/packages/ui/src/components/Icon/assets/palette.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/pin.svg b/design-system/packages/ui/src/components/Icon/assets/pin.svg index 98224fec3b..2a2c59de89 100644 --- a/design-system/packages/ui/src/components/Icon/assets/pin.svg +++ b/design-system/packages/ui/src/components/Icon/assets/pin.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/plus.svg b/design-system/packages/ui/src/components/Icon/assets/plus.svg index 43da3ee9f6..7e510c114d 100644 --- a/design-system/packages/ui/src/components/Icon/assets/plus.svg +++ b/design-system/packages/ui/src/components/Icon/assets/plus.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/progress-25.svg b/design-system/packages/ui/src/components/Icon/assets/progress-25.svg index adaaa6b470..deff56f81e 100644 --- a/design-system/packages/ui/src/components/Icon/assets/progress-25.svg +++ b/design-system/packages/ui/src/components/Icon/assets/progress-25.svg @@ -1,6 +1,6 @@ - - + + diff --git a/design-system/packages/ui/src/components/Icon/assets/refresh.svg b/design-system/packages/ui/src/components/Icon/assets/refresh.svg index a42ac053f4..8f22029228 100644 --- a/design-system/packages/ui/src/components/Icon/assets/refresh.svg +++ b/design-system/packages/ui/src/components/Icon/assets/refresh.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/search.svg b/design-system/packages/ui/src/components/Icon/assets/search.svg index 1ff7e056dc..b97f56b236 100644 --- a/design-system/packages/ui/src/components/Icon/assets/search.svg +++ b/design-system/packages/ui/src/components/Icon/assets/search.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/session.svg b/design-system/packages/ui/src/components/Icon/assets/session.svg index 8cdde77459..6d73330e4d 100644 --- a/design-system/packages/ui/src/components/Icon/assets/session.svg +++ b/design-system/packages/ui/src/components/Icon/assets/session.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/settings.svg b/design-system/packages/ui/src/components/Icon/assets/settings.svg index 63cd895351..9fa37ab47e 100644 --- a/design-system/packages/ui/src/components/Icon/assets/settings.svg +++ b/design-system/packages/ui/src/components/Icon/assets/settings.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/show-session.svg b/design-system/packages/ui/src/components/Icon/assets/show-session.svg index 71df9157a9..3dc58b4003 100644 --- a/design-system/packages/ui/src/components/Icon/assets/show-session.svg +++ b/design-system/packages/ui/src/components/Icon/assets/show-session.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/side-chat.svg b/design-system/packages/ui/src/components/Icon/assets/side-chat.svg index 08f8ed3e44..85e79159bf 100644 --- a/design-system/packages/ui/src/components/Icon/assets/side-chat.svg +++ b/design-system/packages/ui/src/components/Icon/assets/side-chat.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/sidebar-left.svg b/design-system/packages/ui/src/components/Icon/assets/sidebar-left.svg index 67e3619fd1..a70bb22060 100644 --- a/design-system/packages/ui/src/components/Icon/assets/sidebar-left.svg +++ b/design-system/packages/ui/src/components/Icon/assets/sidebar-left.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/sidebar-right.svg b/design-system/packages/ui/src/components/Icon/assets/sidebar-right.svg index 8019454813..b7b97ad077 100644 --- a/design-system/packages/ui/src/components/Icon/assets/sidebar-right.svg +++ b/design-system/packages/ui/src/components/Icon/assets/sidebar-right.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/spark.svg b/design-system/packages/ui/src/components/Icon/assets/spark.svg index 8ac023b519..daed6c8cec 100644 --- a/design-system/packages/ui/src/components/Icon/assets/spark.svg +++ b/design-system/packages/ui/src/components/Icon/assets/spark.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/star.svg b/design-system/packages/ui/src/components/Icon/assets/star.svg index dac3fc6e97..be38a6e18d 100644 --- a/design-system/packages/ui/src/components/Icon/assets/star.svg +++ b/design-system/packages/ui/src/components/Icon/assets/star.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/store.svg b/design-system/packages/ui/src/components/Icon/assets/store.svg index 3f06ed29f1..e5b5172403 100644 --- a/design-system/packages/ui/src/components/Icon/assets/store.svg +++ b/design-system/packages/ui/src/components/Icon/assets/store.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/terminal.svg b/design-system/packages/ui/src/components/Icon/assets/terminal.svg index 391c9d4fd0..0443452c77 100644 --- a/design-system/packages/ui/src/components/Icon/assets/terminal.svg +++ b/design-system/packages/ui/src/components/Icon/assets/terminal.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/thinking.svg b/design-system/packages/ui/src/components/Icon/assets/thinking.svg index 46c0c60c8b..47dc58054b 100644 --- a/design-system/packages/ui/src/components/Icon/assets/thinking.svg +++ b/design-system/packages/ui/src/components/Icon/assets/thinking.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/turn.svg b/design-system/packages/ui/src/components/Icon/assets/turn.svg index 9387237fe4..afb8145b3d 100644 --- a/design-system/packages/ui/src/components/Icon/assets/turn.svg +++ b/design-system/packages/ui/src/components/Icon/assets/turn.svg @@ -1,3 +1,3 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/upload.svg b/design-system/packages/ui/src/components/Icon/assets/upload.svg index db786995ef..d166840788 100644 --- a/design-system/packages/ui/src/components/Icon/assets/upload.svg +++ b/design-system/packages/ui/src/components/Icon/assets/upload.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/user.svg b/design-system/packages/ui/src/components/Icon/assets/user.svg index f673efe31c..8e2001c4b2 100644 --- a/design-system/packages/ui/src/components/Icon/assets/user.svg +++ b/design-system/packages/ui/src/components/Icon/assets/user.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/Icon/assets/xmark.svg b/design-system/packages/ui/src/components/Icon/assets/xmark.svg index b87b7bc232..d8c5f2592d 100644 --- a/design-system/packages/ui/src/components/Icon/assets/xmark.svg +++ b/design-system/packages/ui/src/components/Icon/assets/xmark.svg @@ -1,5 +1,5 @@ - + diff --git a/design-system/packages/ui/src/components/KeyHint/KeyHint.module.css b/design-system/packages/ui/src/components/KeyHint/KeyHint.module.css index 739c0c6cec..927a2a7507 100644 --- a/design-system/packages/ui/src/components/KeyHint/KeyHint.module.css +++ b/design-system/packages/ui/src/components/KeyHint/KeyHint.module.css @@ -10,9 +10,9 @@ padding-block: calc(var(--bf-space-1) / 2); padding-inline: var(--bf-space-1); border: 0; - border-radius: var(--bf-radius-xs, calc(var(--bf-radius-sm) - 2px)); + border-radius: var(--bf-radius-xs); color: var(--bf-color-content-muted); - background: var(--bf-color-key-hint-background, var(--bf-color-action-neutral-surface)); + background: var(--bf-color-key-hint-background); font-family:var(--bf-font-family-sans); font-size: var(--bf-font-size-micro); font-weight: var(--bf-font-weight-regular); diff --git a/design-system/packages/ui/src/flow-chat/tool-cards/FlowChatToolCard.module.css b/design-system/packages/ui/src/flow-chat/tool-cards/FlowChatToolCard.module.css index b494e9d7ec..5342b634a7 100644 --- a/design-system/packages/ui/src/flow-chat/tool-cards/FlowChatToolCard.module.css +++ b/design-system/packages/ui/src/flow-chat/tool-cards/FlowChatToolCard.module.css @@ -2,7 +2,7 @@ .prominentRoot, .ambientRoot { --_tool-card-action-size: var(--bf-space-6); - --_icon-size: var(--bf-font-size-xl); + --_flow-chat-tool-card-icon-size: var(--bf-font-size-xl); --_tool-card-transition: var(--bf-motion-duration-fast) var(--bf-motion-easing-standard); box-sizing: border-box; @@ -261,8 +261,8 @@ .iconMarks { position: relative; display: inline-flex; - inline-size: var(--_icon-size); - block-size: var(--_icon-size); + inline-size: var(--_flow-chat-tool-card-icon-size); + block-size: var(--_flow-chat-tool-card-icon-size); align-items: center; justify-content: center; } diff --git a/design-system/packages/ui/src/primitives/Stack/Stack.tsx b/design-system/packages/ui/src/primitives/Stack/Stack.tsx index 41dbf0032c..e6bb5d7003 100644 --- a/design-system/packages/ui/src/primitives/Stack/Stack.tsx +++ b/design-system/packages/ui/src/primitives/Stack/Stack.tsx @@ -4,6 +4,19 @@ import styles from "./Stack.module.css"; type StackGap = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "8" | "10" | "12"; +const stackGapVariables = { + "0": "var(--bf-space-0)", + "1": "var(--bf-space-1)", + "2": "var(--bf-space-2)", + "3": "var(--bf-space-3)", + "4": "var(--bf-space-4)", + "5": "var(--bf-space-5)", + "6": "var(--bf-space-6)", + "8": "var(--bf-space-8)", + "10": "var(--bf-space-10)", + "12": "var(--bf-space-12)", +} as const satisfies Record; + export interface StackProps extends HTMLAttributes { align?: "start" | "center" | "end" | "stretch"; direction?: "horizontal" | "vertical"; @@ -24,7 +37,7 @@ export function Stack({ }: StackProps) { const stackStyle = { ...style, - "--_stack-gap": `var(--bf-space-${gap})`, + "--_stack-gap": stackGapVariables[gap], } as CSSProperties; return ( diff --git a/design-system/packages/ui/tests/icon.test.mjs b/design-system/packages/ui/tests/icon.test.mjs index 215b964095..544338d654 100644 --- a/design-system/packages/ui/tests/icon.test.mjs +++ b/design-system/packages/ui/tests/icon.test.mjs @@ -1,7 +1,7 @@ import assert from "node:assert/strict"; import { createElement } from "react"; import { renderToStaticMarkup } from "react-dom/server"; -import { readFile } from "node:fs/promises"; +import { readFile, readdir } from "node:fs/promises"; import test from "node:test"; import { Icon, iconNames } from "../dist/index.js"; @@ -50,3 +50,19 @@ test("Icon styles consume only public geometry and semantic color tokens", async assert.match(styles, /--bf-color-status-success-content/); assert.match(styles, /mask-size:contain/); }); + +test("Icon mask assets are color-agnostic", async () => { + const assetDirectory = new URL("../src/components/Icon/assets/", import.meta.url); + const assetNames = (await readdir(assetDirectory)).filter((name) => name.endsWith(".svg")); + + assert.equal(assetNames.length, iconNames.length); + for (const assetName of assetNames) { + const source = await readFile(new URL(assetName, assetDirectory), "utf8"); + assert.match(source, /(?:fill|stroke)="currentColor"/i, `${assetName} must use currentColor`); + assert.doesNotMatch( + source, + /\b(?:fill|stroke)="(?:black|white|#[0-9a-f]{3,8}|rgba?\()/i, + `${assetName} must not own a color`, + ); + } +}); diff --git a/docs/architecture/theme-token-optimization.md b/docs/architecture/theme-token-optimization.md index d24adce6af..987a73128e 100644 --- a/docs/architecture/theme-token-optimization.md +++ b/docs/architecture/theme-token-optimization.md @@ -1,181 +1,308 @@ # 主题与颜色 Token 治理 -本文定义 BitFun 各界面的主题所有权、Token 分层、生成边界和防回退规则。它只保留长期有效的架构约束, -不记录审计数量、迁移批次或阶段历史。当前事实以以下可执行契约及其输出为准: +本文定义 BitFun 全部前端的颜色所有权、运行时投影和防回退契约。目标不是在旧变量之上再包一层, +而是让设计系统成为普通 UI 颜色的唯一公共来源:组件只消费 canonical `--bf-*`,产品层只选择、 +组合和投影这些 Token,不再维护第二套别名体系。 +当前事实以以下可执行契约及其输出为准: + +- `design-system/packages/design-tokens` +- `design-system/packages/theme-bitfun` +- `src/web-ui/src/infrastructure/appearance/appearanceTokenContract.ts` - `scripts/theme-color-governance-baseline*.json` - `scripts/theme-color-near-pair-decisions.json` - `scripts/theme-css-var-contract.mjs` - `scripts/theme-visual-governance-contract.json` -- `scripts/audit-theme-colors.mjs` 与 `scripts/audit-cli-theme-colors.mjs` +- `scripts/frontend-color-surface-registry.json` +- `scripts/audit-frontend-colors.mjs` +- `scripts/audit-theme-colors.mjs` -文档与可执行契约冲突时,先核对代码和审计脚本;不得通过修改文档掩盖实际回退。 +文档与代码或审计结果冲突时,应修复 owner、消费方或契约;不得通过提高 baseline、扩充宽泛 allowlist +或恢复旧变量来掩盖回退。 -## 范围 +## 一条正向依赖链 -本治理覆盖: +| 层级 | 唯一职责 | 不拥有的内容 | +|---|---|---| +| `@bitfun/design-tokens` | 主题无关的命名、系统尺度和基础 Token 契约 | BitFun 具体 light/dark 值、产品状态、route 或运行时选择 | +| `@bitfun/theme-bitfun` | BitFun 的 reference/semantic 主题值、canonical CSS 变量映射和 `default.css` | Web UI Appearance 包、产品 store、组件内部状态 | +| `@bitfun/ui` | 消费 semantic/system Token 的公共组件 anatomy、行为和无障碍契约 | 具体主题值、Appearance schema、旧 Web UI 变量 | +| Web UI Appearance | 选择和组合主题,生成 schema v2 包,并投影 canonical root/scoped Token 与显式 product domain/component Token | 公共 Token 的第二套命名、兼容双写、组件私有 palette | +| 产品前端 | 选择主题、设置设计系统 root 属性并消费 canonical Token | 复制 `theme-bitfun` palette、随组件新增 raw color | -- `design-system` 的共享系统 Token、BitFun 默认语义主题和独立组件消费契约。 -- `src/web-ui` 的 Appearance 包、CSS 变量投影、组件样式和专用渲染色板。 -- `src/mobile-web` 的移动端主题与运行时变量。 -- `BitFun-Installer/src` 的安装器主题、首屏静态变量和流程组件。 -- `src/apps/cli` 的 TUI preset、终端颜色映射和降级行为。 -- Desktop 首屏 bootstrap、生成式 UI 主题提示等由主题源生成的只读产物。 -- BitFun GUI 插件的语义色投影,以及 OpenCode TUI 主题的独立兼容边界。 +正向依赖固定为: -本治理不要求不同产品形态共享完整主题 schema,也不把 Monaco、终端 ANSI、Mermaid、语法高亮、diff、 -语言标识或数据可视化色板强行合并为普通应用 Token。 +```mermaid +flowchart LR + System["@bitfun/design-tokens
命名与系统尺度"] --> Theme["@bitfun/theme-bitfun
默认语义值"] + System --> UI["@bitfun/ui"] + Theme --> UI + Theme --> Appearance["Web UI Appearance v2
产品主题组合"] + Appearance --> Runtime["theme-tokens adapter"] + Runtime --> Root["canonical root --bf-*"] + Runtime --> Scope["canonical scoped --bf-*"] + Theme --> Surfaces["Web surfaces / Desktop bootstrap / MiniApp projection"] + Mobile["Native mobile contract"] --> Native["HarmonyOS / Android / iOS"] +``` -## 所有权与依赖方向 +这里没有 compatibility projection。共享设计系统包不能反向依赖 Web UI Appearance;组件、生成产物、 +Desktop bootstrap 和产品前端也不能反向定义公共主题值。 -| 范围 | 权威 owner | 消费或产物路径 | 约束 | -|---|---|---|---| -| 共享设计系统 Token | `design-system/packages/design-tokens` 与 `design-system/packages/theme-bitfun` | `@bitfun/ui`、Design Lab、Web UI 的 canonical CSS 变量 | 前者拥有主题无关名称和系统尺度,后者拥有可替换的 BitFun 默认语义值;不得依赖产品 route、store、locale、Tauri 或专用渲染域 | -| Web UI Appearance | `src/web-ui/src/infrastructure/appearance` | 运行时 CSS、组件/Scene 契约与 renderer adapter | 拥有包 schema、运行时选择、导入导出、历史包兼容、产品/component Token 和专用域投影;默认 light/dark 共享值从 `@bitfun/theme-bitfun` 取得,Rust 不复制 | -| Desktop 首屏 | Web UI builtin Appearance 与 `scripts/generate-startup-appearance-bootstrap.mjs` | `src/apps/desktop/src/generated/startup_appearance_bootstrap.json` | 只保存 JS 加载前必要字段;生成产物不能反向定义 Appearance | -| 生成式 UI 提示 | Web UI builtin Appearance 与 `scripts/generate-startup-appearance-bootstrap.mjs` | `src/crates/assembly/core/src/agentic/tools/implementations/generated/appearance_prompt_snapshots.json` | 只读生成产物;Rust 不手写第二套内置 palette | -| Mobile Web | `src/mobile-web/src/theme` | Mobile 运行时变量与组件 | 不从 Desktop 或 Web UI 运行时偷读内部变量 | -| Installer | `BitFun-Installer/src/theme` | `BitFun-Installer/src/styles/variables.css` 与流程组件 | Rust 壳不复制完整 palette | -| CLI/TUI | `src/apps/cli/themes/presets` 与 `src/apps/cli/src/ui/theme.rs` | 终端样式 | 拥有 preset、ANSI/monochrome 降级;不实现 Web `ThemeConfig` | -| BitFun GUI 插件 | Web UI Appearance owner | `src/web-ui/src/infrastructure/appearance/adapters/PluginAppearanceProjection.ts` | 只投影约定的语义色,不暴露包或内部变量全集 | -| OpenCode TUI 主题 | CLI/TUI 兼容适配器 | OpenCode 主题来源与终端投影 | 保留来源顺序、稳定字段、引用和 light/dark 变体;不由 GUI 七色投影替代 | -| 专用渲染域 | 对应 editor、terminal、syntax、diff、Mermaid 等模块 | 各自 namespace | 不得泄漏为普通组件随手可用的色板 | +## Canonical Token 分层 -依赖方向固定为: +正向代码只使用以下四类 Token: -```mermaid -flowchart LR - System["@bitfun/design-tokens
共享名称与系统尺度"] --> Theme["@bitfun/theme-bitfun
BitFun 默认语义值"] - System --> Components["@bitfun/ui"] - Theme --> Source["Web UI builtin Appearance
产品与专用域组合"] - Source --> Runtime["AppearanceRuntime"] - Source --> Generator["Appearance 生成器"] - Generator --> Bootstrap["Desktop 首屏 bootstrap"] - Generator --> Prompt["生成式 UI 提示快照"] - Runtime --> Canonical["canonical --bf-* 投影"] - Runtime --> Compatibility["兼容 --bf-appearance-token-*"] - Runtime --> Projection["GUI 插件语义色投影"] +1. **System / semantic**:`--bf-color-*`、`--bf-shadow-*`、`--bf-effect-*`、`--bf-opacity-*` + 等由设计系统发布的公共变量,是普通 UI 的默认消费层。 +2. **Component**:`--bf-component-*`。仅用于跨消费方稳定存在、又无法由 semantic Token 准确表达的 + 组件差异;必须在 `appearanceTokenContract.ts` 中登记。 +3. **Product domain**:`--bf-domain-*`。用于 Git lane、语言身份、syntax、inspector、工具类别等明确的 + 专用语义;不得当作普通 UI 的备用色板。 +4. **Renderer payload**:Monaco、xterm、Mermaid、BitFun Canvas 等第三方或专用渲染器的显式配置。 + 它们有各自格式,不进入普通组件 CSS。 + +Primitive/reference 色值只存在于主题 authoring、明确的主题 preset 或专用 renderer owner 中。普通组件 +不得直接消费 reference ramp,也不得自行定义“看起来差不多”的局部颜色。 + +新增颜色按以下顺序判断: + +1. 语义相同,直接复用现有 semantic Token。 +2. 数值相近且相邻状态仍可区分,合并到已有 Token,并更新 near-pair 决策。 +3. 存在独立、稳定、可说明的组件语义,在最窄 owner 中新增 `--bf-component-*`。 +4. 属于产品或渲染专用域,进入 `--bf-domain-*` 或 renderer payload。 +5. 只有主题本身需要新的基础色时,才修改 `@bitfun/theme-bitfun` 的 authoring source。 + +数值接近不是唯一判断标准;相邻背景/边框、文本层级、状态色、diff、syntax 和数据系列必须结合同时 +出现时的区分度审查。反过来,也不能以“可能有视觉差异”为理由给每个组件建立近似私有颜色。 + +## 普通 UI 的硬约束 + +普通应用组件和页面必须满足: + +- 颜色、阴影和 blur 只从 canonical Token 取得;允许用 `color-mix()`、gradient 等 CSS 运算组合 Token。 +- 不写 hex、rgb、hsl、命名色等 raw color;静态资产元数据和明确主题/renderer owner 除外。 +- 不使用 `var(--token, fallback)` 隐藏缺失 Token。 +- 不引用未定义、未登记或跨 root 偷借的变量。 +- 不定义 `--color-*`、`--lab-*` 或 `--bf-appearance-token-*` 等局部/历史公共前缀。 +- SVG 图标优先使用 `currentColor`,由外层 semantic Token 控制状态。 +- Component-private 非颜色变量可使用包约定的 `--_` 前缀,但不能借此建立私有颜色系统。 + +静态 favicon、manifest、SVG metadata 等不参与组件主题切换的值只能计入 `assetMetadata`。它们不能迁回 +`appUi` allowlist,也不能被组件引用。 + +## Web UI Appearance schema v2 + +Web UI Appearance 的当前 schema 固定为 v2。颜色入口是 `theme-tokens` renderer: + +```ts +{ + "theme-tokens": { + version: 1, + settings: { + tokens: { "--bf-color-*": "...", "--bf-component-*": "...", "--bf-domain-*": "..." }, + scopes: { + chrome: { "--bf-color-*": "..." } + } + } + } +} ``` -共享设计系统包不能反向依赖 Appearance;生成产物、Rust bootstrap、插件投影和消费组件也不能反向定义 -Appearance。Desktop 和 Web UI 只持久化并解析 `appearance.selection`。旧 `theme`、`themes` 和 Skin 数据 -不兼容、不迁移。 +其边界如下: -## Token 分层 +- `tokens` 只能包含 `appearanceTokenContract.ts` 登记的 root Token。 +- `scopes.chrome` 只能重绑定设计系统已有的 canonical theme Token,并应用到 + `[data-bf-theme-scope="chrome"]`;scope 内不发明另一套 chrome 名称。 +- `ThemeTokenAppearanceAdapter` 在切换时移除上一包写入的 root/scoped Token,再写入新包;不双写任何 + 历史名称。 +- Token 名和 Token 值都经过 allowlist 与安全校验;未登记名称、嵌套 `var()`、URL 或可注入片段直接失败。 +- builtin Appearance 从 `@bitfun/theme-bitfun` 的完整主题值开始,只覆盖产品 theme/preset 真正不同的 + canonical 值,再补充受治理的 component/domain Token。 +- Widget、Desktop 首屏 bootstrap 和生成式 UI 提示只消费同一 canonical 源生成的 allowlist 产物, + 不能反向成为主题 owner。 -Token 只按职责分四层: +`CssTokenAppearanceAdapter`、`appearanceTokenProjection`、`css-tokens` renderer 和 +`--bf-appearance-token-*` 运行时变量均已退休。不得为第三方包、旧组件或测试重新引入这些接口。 -1. **Primitive**:颜色原料和必要 alpha ramp,不表达业务含义。 -2. **Semantic**:背景、文本、边框、交互、状态和产品意图,是普通组件的默认消费层。 -3. **Component**:仅在稳定组件契约无法由 semantic token 清楚表达时增加。 -4. **Exception domain**:editor、terminal、syntax、diff、Mermaid、语言标识和其他专用色板。 +### v1 读取不是兼容运行时 -兼容别名不是第五层。它只服务已确认的迁移调用方,必须声明 canonical 目标、owner 和移除条件;新代码不得继续 -读取历史别名。 +升级兼容只存在于包读取入口: -应用结构层可以使用 `--bf-appearance-token-chrome-*` 这一窄化的 component token 家族,表达导航、标签栏和 -工作台外壳相对于内容面的稳定反相关系。它由 Web UI builtin Appearance 投影拥有,只能在结构层 scope 内重绑定 -普通 semantic token;未声明独立 chrome palette 的内置或导入外观沿用所属 light/dark 基础外观的内容色,不能让 -组件按 Appearance ID 硬编码颜色特例。 +1. Parser 识别持久化的 schema v1 包。 +2. `migrateAppearancePackage` 将已知 `css-tokens` 字段和旧名称单向映射为 v2 `theme-tokens` root/scoped + canonical Token。 +3. 旧 `css-tokens` renderer 被删除,后续校验、运行时和导出只接收 v2。 +4. 已安装的旧包在加载后重新保存为 v2,之后不再依赖旧名称。 -共享设置页可以使用 `--bf-appearance-token-config-page-*` 这一窄化的 component token 家族,分别表达 section -块面、section 边界、行分隔线与 hover 填充。它只由 `ConfigPageLayout` 消费,默认映射回普通 element/border -semantic token;仅当某个 Appearance 需要让“信息块面”和“表单控件边界”采用不同层级时才覆写,不能扩散成 -通用卡片色板或按 Appearance ID 编写 CSS 特例。 +因此,旧名称只允许出现在迁移映射、upgrade fixture 和“不得出现”的负向断言中。它们不是可供新代码 +消费的 alias,也不会在 DOM 中生成。未知旧字段不得被猜测或静默投影;应保留原数据并给出明确的不支持状态。 -新增颜色按以下顺序判断: +## 全前端 Surface 注册表 -1. 语义相同:复用现有 Token。 -2. 色值近似且相邻状态不会失去区分:合并并更新审计决策。 -3. 存在独立、稳定且可说明的用户语义:在最窄 owner 中新增 semantic 或 component token。 -4. 属于专用渲染域:进入对应 exception namespace,不扩张普通应用色板。 +`scripts/frontend-color-surface-registry.json` 是前端颜色治理范围的唯一清单。每个可交付或可运行的前端必须 +登记稳定 `id`、源码 root、颜色 owner 和审计引擎;新增目录不能依赖维护者再给 `package.json` 手写一段命令。 +当前注册表覆盖: -不得仅因数值接近就合并颜色。相邻背景/边框、文本层级、成功/警告/错误、diff、语法和数据系列必须结合实际 -同时出现的状态复核。反过来,也不能用“可能有视觉差异”作为每个组件新增近似色的理由。 +- Web UI、`@bitfun/ui`、Design Lab、Website、Mini App Market、Skin Market、Mobile Web 和 Installer。 +- Desktop JavaScript 启动前页面、Native Mobile 比较预览、CLI/TUI。 +- HarmonyOS、Android、iOS 三端原生源码。 +- 全部 builtin/Demo MiniApp 及其内置 Skill reference mirror。 +- `@bitfun/design-tokens` 与 `@bitfun/theme-bitfun` 的 authoring owner。 -## CSS 变量与运行时边界 +`scripts/audit-frontend-colors.mjs` 只从该注册表编排检查:普通 Web surface 复用 CSS/Token 审计,CLI 复用终端 +主题审计,Native Mobile 与 MiniApp 使用各自的源码契约检查。MiniApp discovery 会从三个登记的父目录查找 +所有带 `meta.json` 的应用;发现未登记应用、登记路径消失或 reference mirror 不再 byte-equal 都直接失败。 -- 新设计系统组件只消费包生成的 canonical `--bf-*` 变量。`--bf-appearance-token-*` 仍是现有 Appearance - 包和产品代码的兼容输入,不是新公共组件 API。 -- `CssTokenAppearanceAdapter` 在同一次原子应用中写入历史变量,并通过显式 allowlist 把共享部分投影到 - canonical 变量。投影表由产品基础设施拥有,不能移入 `@bitfun/ui` 或让独立包识别 Appearance schema。 -- 普通组件优先消费运行时 CSS 变量;不得用 SCSS 编译期颜色复制动态主题语义。 -- `tokens.scss` 可以保留尺寸、字体、动效、root Token 和少量兼容 mixin,不应成为第二套产品颜色源。 -- 动态 CSS 变量族必须在 `theme-css-var-contract.mjs` 登记 owner、前缀和消费范围。 -- fallback 只允许存在于明确的启动、第三方或兼容边界;普通组件不得用 fallback 隐藏缺失 Token。 -- 未解析变量、未登记 key、跨 root 借用和运行时/静态定义漂移必须由审计失败暴露。 -- iframe、MiniApp 或生成式 UI 只接收显式 allowlist 的主题 payload,不接收 Web UI 内部变量全集。 -- 导入 Appearance 由 Web UI 加载和校验。Rust 首屏无法解析导入包时使用系统默认启动色,JS 启动后再原子应用完整包。 +注册表不是兼容表。surface 被下线时删除条目,owner 被迁移时原子更新唯一条目;不得同时登记新旧 root、双写 +变量或用另一个命令继续扫描退休实现。 -## 防回退契约 +## 各前端 surface 的 owner -主题 baseline 是 no-growth ratchet,不是普通快照。审计失败时,默认修复方式是复用 Token、删除游离 key、收敛 -近似色、修复 owner 或补最小契约,不能直接提高 baseline、扩充 allowlist、放宽测试或关闭检查。 +### Design Lab、Website、Market -baseline 只允许两类变更: +Design Lab、Website、Mini App Market 与 Skin Market 直接加载 `@bitfun/theme-bitfun/default.css`,通过 +`data-bf-design-system-root`、`data-color-scheme`、`data-contrast` 和 `data-density` 选择已发布主题。 +它们可以拥有布局和产品交互,但不得再维护本地 light/dark palette。 -- 实际债务下降时同步下调。 -- 确有新的用户语义且无法复用时,在独立治理变更中说明 owner、消费方、相邻状态、无障碍影响、回退方式和复审结论。 +### Mobile Web / Remote Control -治理不预设脱离代码检查的固定 Token 数量。预算由审计维度、现有 baseline 和真实消费关系共同约束;没有 checker -保护的任意数字会快速失真,不应成为架构承诺。 +Mobile Web 直接消费 `@bitfun/theme-bitfun`。`ThemeProvider` 与首屏 bootstrap 只负责选择 light/dark、 +写设计系统 root 属性和同步浏览器 `theme-color`;已退休的本地 preset/ramp 不得恢复。Relay 中的 Mobile +静态包必须由这一源码重新构建,不能保留旧 Vite 产物作为隐式第二套主题实现。 -以下做法视为治理回退: +### Desktop bootstrap 与 Native Mobile 预览 -- 为通过 CI 上调 baseline 或 fixture 期望。 -- 把普通组件路径加入专用域 allowlist。 -- 新增与现有 Token 等价的字面量或 fallback。 -- 在 Rust、CLI 或安装器中复制 Web UI 的完整主题模型。 -- 用生成文件或产品定制配置绕过主题 owner。 +Desktop 的更新确认页和启动页只消费 `src/apps/desktop/src/generated/bootstrap_theme.css` 发布的 canonical +`--bf-*`,不得内联另一套启动色。该 CSS 和两个 Appearance manifest 一起由 +`generate-startup-appearance-bootstrap.mjs` 从正式主题/Appearance 源生成;统一颜色审计执行 `--check`, +生成物漂移直接失败。 + +Native Mobile 预览的工具 chrome 消费 canonical `--bf-*`;设备画布消费 `--mobile-*` 这一受登记的 scoped +动态变量族,其值只来自生成的 mobile contract data。二者不互相 alias。预览不得直接解释 ARGB 字符串为 Web +颜色,必须在投影边界显式转换;generated data 不作为普通 UI 源码重复计数,但必须通过生成物漂移检查。 + +### HarmonyOS / Android / iOS + +原生移动端不加载 Web CSS,也不复制 `@bitfun/theme-bitfun`。它们的唯一跨平台视觉事实 owner 是 +`src/apps/mobile/design-system/tokens/mobile-tokens.json`: + +- 颜色名称按语义登记,例如 content、surface、status、scrim、media control 和 shadow;不得使用 `green`、 + `red`、`white` 之类数值或外观名称充当公共 API。 +- `mobile-ui-design-system.mjs` 从同一 contract 生成 ArkTS/Kotlin/Swift 常量与预览数据;组件契约引用不存在的 + token 或任一生成物漂移都会失败。 +- 三端非 generated 源码不得出现 `Color.White` / `.black` / `.clear`、颜色构造器、hex 字符串或同类平台 + raw color。system bar 等平台桥接读取生成的 light/dark pair,不在 entrypoint 重建 palette。 +- Android vector、iOS asset catalog 与 HarmonyOS template media 是可 tint 的平台资产 owner,不是普通 UI + 颜色来源;渲染时仍必须由 semantic token 控制。 + +### Installer -## 产品定制与扩展 +Installer 首屏和普通流程组件加载设计系统默认主题并只消费 canonical Token。主题选择器保留六个明确的 +自定义安装器 preset;这些 preset 的身份色是唯一允许的 installer raw-color owner,并由 Installer 专属 +baseline 约束。运行时只把选中 preset 投影到 canonical `--bf-color-*` 子集。 -产品定制只引用宿主已注册的 Appearance ID,或对应边界明确允许的少量语义色;不得携带任意 CSS、完整 -Appearance 包、renderer 配置、动态代码或源码替换。详细边界见 -[`product-customization-blueprint.md`](product-customization-blueprint.md)。 +Installer 不再拥有 `src/styles/variables.css`,也不得让页面直接读取 preset 对象或建立页面级变量。新增 +preset 必须同时说明用户可见差异、相邻状态对比、所需 canonical 投影和 baseline 变化,不能借新增 preset +扩大普通 UI 的 raw-color 预算。 -GUI、Mobile、Installer 和 CLI/TUI 可以选择不同主题集合,但共享规则而不是共享全部数据结构: +### MiniApp 公共投影 -- 身份与品牌配置选择已注册 ID。 -- 每个 surface 的 owner 校验该 ID 和能力范围。 -- 未支持的组合在构建期或入口启动时失败,不静默回默认造成品牌错配。 -- OpenCode TUI 主题保持独立格式;BitFun GUI 插件七色投影不构成 OpenCode 兼容承诺。 +MiniApp 不能读取 Web UI 内部变量全集。公开边界只有 `src/shared/miniapp-appearance/contract.json` 中登记的 +`--bitfun-*`,每一项都投影自 `@bitfun/design-tokens` 或 `@bitfun/theme-bitfun` 的真实 canonical 变量。 +Web UI payload、Rust 首帧 style 和 MiniApp 源码共同遵守以下约束: -## 变更流程 +- 使用未登记的 `--bitfun-*`、在应用内重新定义宿主变量、或写 `var(--bitfun-*, fallback)` 均直接失败。 +- `default_appearance_style.html` 由公共 contract 生成,不是第三个 palette owner。 +- Demo/builtin 与内置 Skill 中的 reference mirror 必须 byte-equal;修改正式样例时同时更新 mirror,不保留旧版。 +- 普通 MiniApp chrome 的 raw color 为零。专用色不进入通用 baseline,只能登记到下表的最窄 owner;owner + 条目没有真实 occurrence 时也会因 stale 而失败。 -1. 确认变更所属 surface、主题 owner、用户语义和相邻视觉状态。 -2. 优先复用现有 semantic token;新增 Token 时选择最窄层级和 namespace。 -3. 共享名称或默认 BitFun 值更新对应 design-system owner;运行时、导入兼容或产品/专用域更新 Web UI - Appearance owner、校验器、compiler、投影和真实消费方。 -4. 仅在 JS 加载前确有需要时重新生成 Desktop bootstrap;生成式 UI 提示按同一 Appearance 源更新。 -5. 涉及动态变量、别名、专用域或跨 root 时,同步更新对应可执行 contract。 -6. 运行自动检查,并对受影响 surface、light/dark/system、交互状态和无障碍对比做 focused review。 +| MiniApp | 允许的专用 owner | 边界 | +|---|---|---| +| Coding Selfie | `data-viz` | `LANG_COLORS` 语言数据系列块 | +| Git Graph | `data-viz` | branch lane 5–7 的三个分类色;其余 lane 使用宿主语义 | +| Gomoku | `game-renderer` | 黑白棋子填充与对比描边变量 | +| Daily Divination | `bespoke-theme` | 塔罗场景本身的完整插画 light/dark 主题 | +| PPT Live | `slide-renderer` | 幻灯片内容、导出器和 renderer fixture;编辑器 chrome 仍为零 raw color | +| Regex Playground / Icon Design System | 无 | 全部视觉消费宿主投影 | -主题变更至少运行: +### 专用 renderer 和资产 + +Monaco、xterm/ANSI、Mermaid、syntax、diff、语言标识、调试 overlay、Canvas 和数据系列有独立的格式或 +稳定语义。它们必须留在对应 renderer/domain owner 中,并通过明确 payload 或 `--bf-domain-*` 消费;不得 +泄漏成普通组件可随手调用的 palette。 + +### 显式排除不是 allowlist + +Monaco 拷贝产物、Relay static、E2E fixture、诊断报表 HTML、PPT 内容 renderer、native template icons 和 +generated outputs 不属于普通应用 UI 扫描。每个边界都必须在 surface registry 中用现存路径、唯一 owner、 +artifact kind 和具体理由登记;路径消失或只写模糊理由会使 registry contract test 失败。 + +这些条目不会允许同名颜色进入其他目录,也不能用 glob 把普通组件一起隐藏。PPT、native asset 等专用 owner +仍由各自的 renderer、生成器或平台 tint 契约验证;“不计入普通 UI raw color”不等于“不受治理”。 + +## 防回退契约 + +主题 baseline 是 no-growth ratchet,不是可随实现调整的快照。以下指标对普通 UI 均应保持为零: + +- raw color occurrences / unique colors +- fallback occurrences / unique tokens +- unresolved required variables +- compatibility alias usage +- unregistered dynamic families +- indistinguishable near pairs +- non-canonical Widget payload fields + +审计失败时,默认修复方式是复用 Token、删除游离 key、收敛近似色、修复 owner 或补最小 component/domain +契约。以下做法均视为治理回退: + +- 为通过 CI 上调 baseline 或 fixture 期望。 +- 把普通组件路径加入 renderer/asset exception allowlist。 +- 新增与现有 Token 等价的字面量、fallback 或 alias。 +- 在 Mobile、Installer、Website、Market、Rust 或生成产物中复制公共 palette。 +- 同时写 canonical 与旧变量,或保留两个 adapter 让调用方任选。 +- 用生成文件、产品定制或静态 Vite 产物绕过当前主题 owner。 + +baseline 只允许两类变更:实际债务下降时同步下调;或确有新的稳定语义时,在独立治理变更中给出 owner、 +真实消费方、相邻状态、无障碍影响和复审结论。 + +## 变更与验证 + +颜色变更应按 owner 完成,而不是逐页面补丁: + +1. 确认 surface、用户语义、相邻状态和唯一 owner。 +2. 优先复用现有 semantic Token;确需新增时选择最窄 component/domain/renderer 边界。 +3. 更新 authoring source、运行时 contract 和真实消费方;删除被替代的旧 API、文件和变量。 +4. 若影响首屏、Widget 或静态包,从 canonical 源重新生成/构建产物。 +5. 运行最窄 owner 测试,再运行跨 surface 颜色审计。 + +核心自动门禁为: ```bash +pnpm run theme:color-audit:test +pnpm run theme:color-audit:all +pnpm run theme:color-audit:miniapps +pnpm run theme:color-audit:native-mobile +pnpm run theme:visual-contract +pnpm run appearance:contract-audit +pnpm run design-system:check pnpm run check:web -pnpm run generate-startup-appearance-bootstrap ``` -`check:web` 聚合执行类型检查、Appearance contract、主题颜色审计及其 contract tests,以及主题视觉治理契约, -与 CI 针对 Web UI 的 Appearance 门禁保持一致。 - -若 Appearance 源影响生成产物,先运行 `pnpm run generate-startup-appearance-bootstrap`,再确认只有预期的只读产物发生变化。 -跨 surface 视觉变化还应按 `theme-visual-governance-contract.json` 的覆盖项完成 focused review;自动审计不等于视觉 -或对比度已经通过。 +另外还应执行被改动 surface 的 type-check/test/build。自动审计、source 检查和 build 只能证明契约与产物 +一致,不能替代真实渲染的视觉与对比度审查;设计验收应在 Design Lab 或真实产品中人工完成,不能把浏览器 +自动化截图或 Mock 当作最终视觉证据。 -## 当前判定 +## 完成判据 -普通应用组件的 raw color、等价字面量、fallback 和近似色债务由审计脚本与 baseline 持续守护;本文不复制某次 -扫描数量。专用渲染 palette、兼容别名和各产品形态的独立主题仍然存在,它们只有在缺少 owner、越过作用域或 -重新进入普通组件时才构成债务。 +颜色体系只有在以下条件同时满足时才算完成: -主题治理完成的判据不是“色值最少”,而是: +- 普通 UI 的每个颜色都能追溯到一个 canonical semantic/component Token。 +- 每个专用色值都能追溯到一个 theme preset、domain、renderer 或 asset metadata owner。 +- Web UI 运行时只投影 schema v2 `theme-tokens`,DOM 中没有历史变量。 +- Mobile、Website、Market、Installer 和 Design Lab 不复制公共 palette。 +- v1 只在读取时迁移,正向源码、样式、产物与导出中不存在旧名称。 +- baseline 默认只下降,新增语义必须有真实消费方和明确审查证据。 -- 每个普通组件颜色都能追溯到稳定语义 Token。 -- 每个专用色板都有清楚 owner 和边界。 -- 每层主题事实只有一个权威 owner:共享名称与默认值属于 design-system,运行时选择与产品/专用域组合属于 - Appearance;生成物不反向定义契约。 -- 新主题和产品定制不需要复制 Rust/React/TUI 实现。 -- 审计 baseline 默认只下降;确需合理增长时,必须经独立评审且有真实消费方。 +完成目标不是“色值数量最少”,而是每个颜色只有一个权威 owner、每个消费方只依赖稳定语义、每次回退都能 +被自动门禁准确阻断。 diff --git a/package.json b/package.json index 48ecc49c26..86e7b28a27 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "generate-version": "node scripts/generate-version.cjs --build-env production", "generate-version:dev": "node scripts/generate-version.cjs --build-env development", "generate-startup-appearance-bootstrap": "node scripts/generate-startup-appearance-bootstrap.mjs", + "miniapp:appearance:generate": "node scripts/generate-miniapp-appearance-contract.mjs", + "miniapp:appearance:check": "node scripts/generate-miniapp-appearance-contract.mjs --check", "generate-all": "pnpm run generate-version && pnpm run generate-startup-appearance-bootstrap", "postinstall": "pnpm run copy-assets", "dev": "node scripts/dev.cjs web", @@ -39,12 +41,21 @@ "iconography:check": "node scripts/iconography/generate.mjs --check", "typography:audit": "node scripts/audit-typography-tokens.mjs", "typography:audit:test": "node --test scripts/audit-typography-tokens.test.mjs", - "theme:color-audit": "node scripts/audit-theme-colors.mjs", - "theme:color-audit:mobile": "node scripts/audit-theme-colors.mjs --root src/mobile-web/src --baseline scripts/theme-color-governance-baseline.mobile-web.json", - "theme:color-audit:installer": "node scripts/audit-theme-colors.mjs --root BitFun-Installer/src --baseline scripts/theme-color-governance-baseline.installer.json", - "theme:color-audit:cli": "node scripts/audit-cli-theme-colors.mjs", - "theme:color-audit:all": "pnpm run theme:color-audit && pnpm run theme:color-audit:mobile && pnpm run theme:color-audit:installer && pnpm run theme:color-audit:cli", - "theme:color-audit:test": "node --test scripts/audit-theme-colors.test.mjs scripts/audit-cli-theme-colors.test.mjs", + "theme:color-audit": "node scripts/audit-frontend-colors.mjs --surface web-ui", + "theme:color-audit:design-lab": "node scripts/audit-frontend-colors.mjs --surface design-lab", + "theme:color-audit:design-system-ui": "node scripts/audit-frontend-colors.mjs --surface design-system-ui", + "theme:color-audit:miniapp-market": "node scripts/audit-frontend-colors.mjs --surface miniapp-market", + "theme:color-audit:skin-market": "node scripts/audit-frontend-colors.mjs --surface skin-market", + "theme:color-audit:website": "node scripts/audit-frontend-colors.mjs --surface website", + "theme:color-audit:mobile": "node scripts/audit-frontend-colors.mjs --surface mobile-web", + "theme:color-audit:installer": "node scripts/audit-frontend-colors.mjs --surface installer", + "theme:color-audit:cli": "node scripts/audit-frontend-colors.mjs --surface cli", + "theme:color-audit:desktop-bootstrap": "node scripts/audit-frontend-colors.mjs --surface desktop-bootstrap", + "theme:color-audit:mobile-preview": "node scripts/audit-frontend-colors.mjs --surface mobile-design-preview", + "theme:color-audit:native-mobile": "node scripts/audit-frontend-colors.mjs --kind native-mobile", + "theme:color-audit:miniapps": "node scripts/audit-frontend-colors.mjs --kind miniapp", + "theme:color-audit:all": "node scripts/audit-frontend-colors.mjs", + "theme:color-audit:test": "node --test scripts/audit-theme-colors.test.mjs scripts/audit-cli-theme-colors.test.mjs scripts/audit-frontend-colors.test.mjs", "motion:audit": "node scripts/audit-web-motion.mjs", "theme:visual-contract": "node scripts/validate-theme-visual-contract.mjs", "appearance:contract-audit": "node scripts/audit-appearance-contracts.mjs", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3ccb0d8ea1..f89834c77f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,6 +56,9 @@ importers: BitFun-Installer: dependencies: + '@bitfun/theme-bitfun': + specifier: workspace:^ + version: link:../design-system/packages/theme-bitfun '@tauri-apps/api': specifier: ^2.10.1 version: 2.10.1 @@ -207,6 +210,9 @@ importers: src/miniapp-market-web: dependencies: + '@bitfun/theme-bitfun': + specifier: workspace:^ + version: link:../../design-system/packages/theme-bitfun '@phosphor-icons/react': specifier: ^2.1.10 version: 2.1.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -241,6 +247,9 @@ importers: src/mobile-web: dependencies: + '@bitfun/theme-bitfun': + specifier: workspace:^ + version: link:../../design-system/packages/theme-bitfun '@noble/ciphers': specifier: ^2.1.1 version: 2.1.1 @@ -293,6 +302,9 @@ importers: src/skin-market-web: dependencies: + '@bitfun/theme-bitfun': + specifier: workspace:^ + version: link:../../design-system/packages/theme-bitfun '@phosphor-icons/react': specifier: ^2.1.10 version: 2.1.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -587,6 +599,15 @@ importers: specifier: ^3.0.3 version: 3.0.3(@wdio/types@8.41.0) + website: + dependencies: + '@bitfun/design-tokens': + specifier: workspace:^ + version: link:../design-system/packages/design-tokens + '@bitfun/theme-bitfun': + specifier: workspace:^ + version: link:../design-system/packages/theme-bitfun + packages: '@antfu/install-pkg@1.1.0': diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d1afbbbf0a..8b640e2b03 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -9,6 +9,7 @@ packages: - "src/miniapp-market-web" - "src/skin-market-web" - "BitFun-Installer" + - "website" - "tests/e2e" patchedDependencies: diff --git a/scripts/audit-appearance-contracts.mjs b/scripts/audit-appearance-contracts.mjs index f3c4914831..072b286e7c 100644 --- a/scripts/audit-appearance-contracts.mjs +++ b/scripts/audit-appearance-contracts.mjs @@ -764,9 +764,9 @@ for (const [file, source] of adapterFiles) { } } -const cssTokenAdapterSource = fs.readFileSync(path.join(sourceRoot, 'infrastructure', 'appearance', 'adapters', 'CssTokenAppearanceAdapter.ts'), 'utf8'); -if (!cssTokenAdapterSource.includes('APPEARANCE_CSS_TOKEN_NAMES') || cssTokenAdapterSource.includes("startsWith(ALLOWED_TOKEN_PREFIX)")) { - failures.push('CssTokenAppearanceAdapter must validate against the closed host token registry'); +const themeTokenAdapterSource = fs.readFileSync(path.join(sourceRoot, 'infrastructure', 'appearance', 'adapters', 'ThemeTokenAppearanceAdapter.ts'), 'utf8'); +if (!themeTokenAdapterSource.includes('APPEARANCE_ROOT_TOKEN_NAMES') || themeTokenAdapterSource.includes("startsWith(ALLOWED_TOKEN_PREFIX)")) { + failures.push('ThemeTokenAppearanceAdapter must validate against the closed canonical token registry'); } const widgetAdapterSource = fs.readFileSync(path.join(sourceRoot, 'infrastructure', 'appearance', 'adapters', 'WidgetAppearanceAdapter.ts'), 'utf8'); if (!widgetAdapterSource.includes('WIDGET_APPEARANCE_VARIABLE_NAMES')) { @@ -803,7 +803,7 @@ for (const [file, source] of productionSources) { if (/\bThemeService\b|\bthemeService\b|\buseTheme\b|\buseThemeStore\b|ThemeAppearanceBridge/.test(source)) { failures.push(`${relative(file)}: legacy Theme runtime reference is forbidden`); } - if (/data-theme(?:-type)?|data-bf-theme|bitfun\/request-theme|themeChange|onThemeChange/.test(source)) { + if (/data-theme(?:-type)?|data-bf-theme(?!-scope(?=$|[="'\]\s]))|bitfun\/request-theme|themeChange|onThemeChange/.test(source)) { failures.push(`${relative(file)}: legacy Theme DOM or bridge contract is forbidden`); } if (/--(?:color|border|element|git-color|scrollbar|shadow|blur|size|opacity|motion|easing|font|line-height|btn|flowchat|scene)-/.test(source)) { diff --git a/scripts/audit-frontend-colors.mjs b/scripts/audit-frontend-colors.mjs new file mode 100644 index 0000000000..971d895a18 --- /dev/null +++ b/scripts/audit-frontend-colors.mjs @@ -0,0 +1,845 @@ +#!/usr/bin/env node + +import { spawnSync } from 'node:child_process'; +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import { fileURLToPath } from 'node:url'; + +const SCRIPT_PATH = fileURLToPath(import.meta.url); +const REPOSITORY_ROOT = path.resolve(path.dirname(SCRIPT_PATH), '..'); +const DEFAULT_REGISTRY_PATH = path.join(REPOSITORY_ROOT, 'scripts/frontend-color-surface-registry.json'); +const THEME_AUDITOR_PATH = path.join(REPOSITORY_ROOT, 'scripts/audit-theme-colors.mjs'); +const CLI_AUDITOR_PATH = path.join(REPOSITORY_ROOT, 'scripts/audit-cli-theme-colors.mjs'); +const MINIAPP_SOURCE_EXTENSIONS = new Set(['.css', '.html', '.js', '.jsx', '.mjs', '.scss', '.svg', '.ts', '.tsx']); +const SPECIALIZED_COLOR_OWNER_KINDS = new Set(['bespoke-theme', 'data-viz', 'game-renderer', 'slide-renderer']); +const SURFACE_KINDS = new Set(['canonical-web', 'contract-owner', 'miniapp', 'native-mobile', 'terminal']); +const AUDIT_ENGINES = new Set(['cli', 'miniapp', 'native', 'theme']); +const CANONICAL_ZERO_METRICS = [ + 'colorScopes.appUi.occurrences', + 'colorScopes.appUi.uniqueColors', + 'colorScopes.token.occurrences', + 'colorScopes.exception.occurrences', + 'fallbackOccurrences', + 'fallbackUniqueTokens', + 'fallbackContracts.uncontractedUnique', + 'compatibilityAliases.usedUnique', + 'compatibilityAliases.occurrences', + 'compatibilityAliases.familyUsedUnique', + 'compatibilityAliases.familyOccurrences', + 'compatibilityAliases.missingCanonicalUnique', + 'surfaceTokenRenames.activeUnique', + 'surfaceTokenRenames.activeOccurrences', + 'surfaceTokenRenames.missingCanonicalUnique', + 'tokenAliasLiterals.occurrences', + 'tokenAliasLiterals.uniqueColors', + 'cssVarDefinitions.unresolvedUnique', + 'cssVarDefinitions.unresolvedRequiredUnique', + 'cssVarDefinitions.fallbackOnlyUnique', + 'cssVarDefinitions.nonContractCrossFileUnique', + 'cssVarDefinitions.nonContractDynamicInputUnique', + 'cssVarDefinitions.nonContractCssPrivateUnique', + 'cssVarDefinitions.unregisteredDynamicFamilyUnique', + 'cssVarDefinitions.dynamicFamilyUnexportedUnique', + 'cssVarDefinitions.staleRegisteredDynamicFamilyUnique', + 'nearPairs.indistinguishableTotal', + 'nearPairs.nearTotal' +]; +const HEX_COLOR_PATTERN = /(? value?.[key], object); +} + +function pathIsWithinRoot(repositoryRoot, candidate) { + const relative = path.relative(repositoryRoot, candidate); + return relative !== '' && !relative.startsWith(`..${path.sep}`) && relative !== '..' && !path.isAbsolute(relative); +} + +function resolveRegistryPath(repositoryRoot, relativePath, label, failures, { allowFile = true, allowDirectory = true } = {}) { + if (typeof relativePath !== 'string' || relativePath.trim() === '' || path.isAbsolute(relativePath)) { + failures.push(`${label} must be a non-empty repository-relative path.`); + return null; + } + const resolved = path.resolve(repositoryRoot, relativePath); + if (!pathIsWithinRoot(repositoryRoot, resolved)) { + failures.push(`${label} escapes the repository root: ${relativePath}`); + return null; + } + if (!fs.existsSync(resolved)) { + failures.push(`${label} does not exist: ${relativePath}`); + return null; + } + const stat = fs.statSync(resolved); + if ((!allowFile && stat.isFile()) || (!allowDirectory && stat.isDirectory())) { + failures.push(`${label} has the wrong path kind: ${relativePath}`); + } + return resolved; +} + +export function validateRegistry(registry, { repositoryRoot = REPOSITORY_ROOT } = {}) { + const failures = []; + if (!registry || registry.version !== 1) { + return ['frontend color surface registry must use version 1.']; + } + if (!registry.contracts || typeof registry.contracts !== 'object') { + failures.push('registry.contracts must be an object.'); + } else { + for (const [name, contractPath] of Object.entries(registry.contracts)) { + resolveRegistryPath(repositoryRoot, contractPath, `contracts.${name}`, failures, { allowDirectory: false }); + } + } + if (!Array.isArray(registry.surfaces) || registry.surfaces.length === 0) { + failures.push('registry.surfaces must be a non-empty array.'); + return failures; + } + + const surfaceIds = new Set(); + for (const [index, surface] of registry.surfaces.entries()) { + const label = `surfaces[${index}]`; + if (!/^[a-z0-9-]+$/.test(surface?.id ?? '')) failures.push(`${label}.id must be kebab-case.`); + if (surfaceIds.has(surface?.id)) failures.push(`${label}.id duplicates ${surface.id}.`); + surfaceIds.add(surface?.id); + if (typeof surface?.label !== 'string' || surface.label.trim() === '') failures.push(`${label}.label is required.`); + if (!SURFACE_KINDS.has(surface?.kind)) failures.push(`${label}.kind is invalid: ${String(surface?.kind)}`); + if (typeof surface?.owner !== 'string' || surface.owner.trim() === '') failures.push(`${label}.owner is required.`); + + const roots = surface?.roots ?? (surface?.root ? [surface.root] : []); + if (!Array.isArray(roots) || roots.length === 0) failures.push(`${label} must declare root or roots.`); + for (const [rootIndex, root] of roots.entries()) { + resolveRegistryPath(repositoryRoot, root, `${label}.roots[${rootIndex}]`, failures, { allowFile: false }); + } + + if (surface.kind === 'contract-owner') { + if (surface.audit !== undefined) failures.push(`${label} contract owners must not declare an audit engine.`); + continue; + } + if (!surface.audit || !AUDIT_ENGINES.has(surface.audit.engine)) { + failures.push(`${label}.audit.engine is required and must be registered.`); + continue; + } + const expectedEngine = surface.kind === 'terminal' + ? 'cli' + : surface.kind === 'native-mobile' + ? 'native' + : surface.kind === 'miniapp' + ? 'miniapp' + : 'theme'; + if (surface.audit.engine !== expectedEngine) { + failures.push(`${label}.audit.engine must be ${expectedEngine} for ${surface.kind}.`); + } + if (surface.audit.baseline) { + resolveRegistryPath(repositoryRoot, surface.audit.baseline, `${label}.audit.baseline`, failures, { allowDirectory: false }); + } + for (const [excludeIndex, excludePath] of (surface.audit.excludePaths ?? []).entries()) { + resolveRegistryPath( + repositoryRoot, + path.join(surface.root, excludePath), + `${label}.audit.excludePaths[${excludeIndex}]`, + failures + ); + } + for (const [excludeIndex, excludeFile] of (surface.audit.excludeFiles ?? []).entries()) { + resolveRegistryPath( + repositoryRoot, + path.join(surface.root, excludeFile), + `${label}.audit.excludeFiles[${excludeIndex}]`, + failures, + { allowDirectory: false } + ); + } + for (const [ownerIndex, owner] of (surface.audit.rawColorOwners ?? []).entries()) { + const ownerLabel = `${label}.audit.rawColorOwners[${ownerIndex}]`; + if (!SPECIALIZED_COLOR_OWNER_KINDS.has(owner?.kind)) failures.push(`${ownerLabel}.kind is invalid.`); + if (typeof owner?.reason !== 'string' || owner.reason.trim().length < 24) failures.push(`${ownerLabel}.reason must explain the narrow owner.`); + const ownerFiles = [owner.file, ...(owner.files ?? []), ...(owner.pathPrefixes ?? [])].filter(Boolean); + if (ownerFiles.length === 0) failures.push(`${ownerLabel} must declare file, files, or pathPrefixes.`); + for (const [fileIndex, ownerFile] of ownerFiles.entries()) { + resolveRegistryPath( + repositoryRoot, + path.join(surface.root, ownerFile), + `${ownerLabel}.paths[${fileIndex}]`, + failures + ); + } + if ((owner.startMarker && !owner.endMarker) || (!owner.startMarker && owner.endMarker)) { + failures.push(`${ownerLabel} must declare both startMarker and endMarker.`); + } + if (owner.linePattern) { + try { + new RegExp(owner.linePattern); + } catch (error) { + failures.push(`${ownerLabel}.linePattern is invalid: ${error instanceof Error ? error.message : String(error)}`); + } + } + } + for (const [bundleIndex, bundle] of (surface.audit.generatedBundles ?? []).entries()) { + const bundleLabel = `${label}.audit.generatedBundles[${bundleIndex}]`; + resolveRegistryPath(repositoryRoot, path.join(surface.root, bundle.output), `${bundleLabel}.output`, failures, { allowDirectory: false }); + if (!Array.isArray(bundle.inputs) || bundle.inputs.length === 0) failures.push(`${bundleLabel}.inputs must be non-empty.`); + for (const [inputIndex, input] of (bundle.inputs ?? []).entries()) { + resolveRegistryPath(repositoryRoot, path.join(surface.root, input), `${bundleLabel}.inputs[${inputIndex}]`, failures, { allowDirectory: false }); + } + } + } + + const mirrorPaths = new Set(); + for (const [index, mirror] of (registry.mirrors ?? []).entries()) { + const label = `mirrors[${index}]`; + const surface = registry.surfaces.find(candidate => candidate.id === mirror?.surfaceId); + if (!surface || surface.kind !== 'miniapp') failures.push(`${label}.surfaceId must name a MiniApp surface.`); + if (mirrorPaths.has(mirror?.path)) failures.push(`${label}.path duplicates ${mirror.path}.`); + mirrorPaths.add(mirror?.path); + resolveRegistryPath(repositoryRoot, mirror?.path, `${label}.path`, failures, { allowFile: false }); + } + + const discoveryParents = registry.discovery?.miniappParents; + if (!Array.isArray(discoveryParents) || discoveryParents.length === 0) { + failures.push('registry.discovery.miniappParents must be non-empty.'); + } else { + for (const [index, parent] of discoveryParents.entries()) { + resolveRegistryPath(repositoryRoot, parent, `discovery.miniappParents[${index}]`, failures, { allowFile: false }); + } + } + + const generatedCheckIds = new Set(); + for (const [index, check] of (registry.generatedChecks ?? []).entries()) { + const label = `generatedChecks[${index}]`; + if (!/^[a-z0-9-]+$/.test(check?.id ?? '')) failures.push(`${label}.id must be kebab-case.`); + if (generatedCheckIds.has(check?.id)) failures.push(`${label}.id duplicates ${check.id}.`); + generatedCheckIds.add(check?.id); + if (!Array.isArray(check?.command) || check.command.length < 2 || check.command.some(part => typeof part !== 'string' || part === '')) { + failures.push(`${label}.command must be a non-empty string array.`); + } + for (const surfaceId of check?.surfaceIds ?? []) { + if (!surfaceIds.has(surfaceId)) failures.push(`${label}.surfaceIds references unknown surface ${surfaceId}.`); + } + for (const kind of check?.surfaceKinds ?? []) { + if (!SURFACE_KINDS.has(kind)) failures.push(`${label}.surfaceKinds references unknown kind ${kind}.`); + } + } + + const exclusionIds = new Set(); + for (const [index, exclusion] of (registry.exclusions ?? []).entries()) { + const label = `exclusions[${index}]`; + if (!/^[a-z0-9-]+$/.test(exclusion?.id ?? '')) failures.push(`${label}.id must be kebab-case.`); + if (exclusionIds.has(exclusion?.id)) failures.push(`${label}.id duplicates ${exclusion.id}.`); + exclusionIds.add(exclusion?.id); + resolveRegistryPath(repositoryRoot, exclusion?.path, `${label}.path`, failures); + if (typeof exclusion?.kind !== 'string' || exclusion.kind.trim() === '') failures.push(`${label}.kind is required.`); + if (typeof exclusion?.owner !== 'string' || exclusion.owner.trim() === '') failures.push(`${label}.owner is required.`); + if (typeof exclusion?.reason !== 'string' || exclusion.reason.trim().length < 24) failures.push(`${label}.reason must explain the boundary.`); + } + return failures; +} + +function walkFiles(root, { extensions, excludePaths = [], excludeFiles = [] } = {}) { + const files = []; + const normalizedExcludePaths = excludePaths.map(normalizeRelativePath); + const normalizedExcludeFiles = new Set(excludeFiles.map(normalizeRelativePath)); + const stack = [root]; + while (stack.length > 0) { + const current = stack.pop(); + for (const entry of fs.readdirSync(current, { withFileTypes: true })) { + const fullPath = path.join(current, entry.name); + const relativePath = normalizePath(path.relative(root, fullPath)); + const excluded = normalizedExcludeFiles.has(relativePath) || normalizedExcludePaths.some(prefix => ( + relativePath === prefix || relativePath.startsWith(`${prefix}/`) + )); + if (excluded) continue; + if (entry.isDirectory()) { + if (entry.name === 'node_modules' || entry.name === '.git') continue; + stack.push(fullPath); + } else if (entry.isFile() && (!extensions || extensions.has(path.extname(entry.name).toLowerCase()))) { + files.push(fullPath); + } + } + } + return files.sort((left, right) => left.localeCompare(right)); +} + +function addFinding(findings, seen, { file, content, index, value, type }) { + const key = `${file}:${index}:${type}:${value.toLowerCase()}`; + if (seen.has(key)) return; + seen.add(key); + const line = content.slice(0, index).split(/\r?\n/).length; + const lineText = content.split(/\r?\n/)[line - 1] ?? ''; + findings.push({ file, index, line, lineText, type, value }); +} + +function collectRawColorFindings(relativePath, content) { + const findings = []; + const seen = new Set(); + for (const pattern of [HEX_COLOR_PATTERN, FUNCTION_COLOR_PATTERN]) { + pattern.lastIndex = 0; + for (const match of content.matchAll(pattern)) { + addFinding(findings, seen, { + file: relativePath, + content, + index: match.index, + value: match[0], + type: match[0].startsWith('#') ? 'hex' : 'color-function' + }); + } + } + + const extension = path.extname(relativePath).toLowerCase(); + if (['.css', '.html', '.scss', '.svg'].includes(extension)) { + CSS_DECLARATION_PATTERN.lastIndex = 0; + for (const declaration of content.matchAll(CSS_DECLARATION_PATTERN)) { + const value = declaration[1].replace(/url\((?:\"[^\"]*\"|'[^']*'|[^)]*)\)/gi, ' '); + CSS_NAMED_COLOR_PATTERN.lastIndex = 0; + for (const match of value.matchAll(CSS_NAMED_COLOR_PATTERN)) { + addFinding(findings, seen, { + file: relativePath, + content, + index: declaration.index + declaration[0].indexOf(declaration[1]) + match.index + match[0].lastIndexOf(match[1]), + value: match[1], + type: 'named-color' + }); + } + } + CSS_COLOR_ATTRIBUTE_PATTERN.lastIndex = 0; + for (const match of content.matchAll(CSS_COLOR_ATTRIBUTE_PATTERN)) { + addFinding(findings, seen, { + file: relativePath, + content, + index: match.index + match[0].lastIndexOf(match[1]), + value: match[1], + type: 'named-color' + }); + } + } else { + SCRIPT_COLOR_VALUE_PATTERN.lastIndex = 0; + for (const match of content.matchAll(SCRIPT_COLOR_VALUE_PATTERN)) { + addFinding(findings, seen, { + file: relativePath, + content, + index: match.index + match[0].lastIndexOf(match[1]), + value: match[1], + type: 'named-color' + }); + } + } + return findings.sort((left, right) => left.index - right.index); +} + +function ownerMatchesFinding(owner, finding, content) { + const ownerPaths = [owner.file, ...(owner.files ?? []), ...(owner.pathPrefixes ?? [])] + .filter(Boolean) + .map(normalizeRelativePath); + const pathMatches = ownerPaths.some(ownerPath => ( + finding.file === ownerPath || finding.file.startsWith(`${ownerPath}/`) + )); + if (!pathMatches) return false; + if (owner.startMarker) { + const start = content.indexOf(owner.startMarker); + const end = start < 0 ? -1 : content.indexOf(owner.endMarker, start + owner.startMarker.length); + if (start < 0 || end < 0 || finding.index < start || finding.index > end + owner.endMarker.length) return false; + } + if (owner.linePattern && !new RegExp(owner.linePattern).test(finding.lineText)) return false; + return true; +} + +function checkGeneratedBundles(surface, repositoryRoot) { + const failures = []; + for (const bundle of surface.audit.generatedBundles ?? []) { + const outputRelative = normalizeRelativePath(bundle.output); + const outputDirectory = path.posix.dirname(outputRelative); + const expected = bundle.inputs.map((input) => { + const normalizedInput = normalizeRelativePath(input); + const label = path.posix.relative(outputDirectory, normalizedInput); + const content = fs.readFileSync(path.join(repositoryRoot, surface.root, normalizedInput), 'utf8'); + return `/* ${label} */\n${content}\n`; + }).join(''); + const actual = fs.readFileSync(path.join(repositoryRoot, surface.root, outputRelative), 'utf8'); + if (actual !== expected) { + failures.push(`${surface.id} generated bundle ${bundle.output} is stale; run its source/build.js.`); + } + } + return failures; +} + +export function auditMiniappSurface(surface, contract, { repositoryRoot = REPOSITORY_ROOT } = {}) { + const root = path.join(repositoryRoot, surface.root); + const files = walkFiles(root, { + extensions: MINIAPP_SOURCE_EXTENSIONS, + excludePaths: surface.audit.excludePaths ?? [], + excludeFiles: surface.audit.excludeFiles ?? [] + }); + const allowedHostVariables = new Set(contract.variables.map(variable => variable.name)); + const rawOwnerMatches = new Map((surface.audit.rawColorOwners ?? []).map((owner, index) => [index, 0])); + const failures = []; + const rawFindings = []; + const hostVariables = new Set(); + let hostVariableOccurrences = 0; + + for (const file of files) { + const relativePath = normalizePath(path.relative(root, file)); + const content = fs.readFileSync(file, 'utf8'); + for (const finding of collectRawColorFindings(relativePath, content)) { + const ownerIndex = (surface.audit.rawColorOwners ?? []).findIndex(owner => ownerMatchesFinding(owner, finding, content)); + if (ownerIndex < 0) { + rawFindings.push(finding); + failures.push(`${surface.id}:${finding.file}:${finding.line} has unowned ${finding.type} ${finding.value}.`); + } else { + rawOwnerMatches.set(ownerIndex, (rawOwnerMatches.get(ownerIndex) ?? 0) + 1); + } + } + + HOST_VARIABLE_PATTERN.lastIndex = 0; + for (const match of content.matchAll(HOST_VARIABLE_PATTERN)) { + hostVariables.add(match[0]); + hostVariableOccurrences += 1; + if (!allowedHostVariables.has(match[0])) { + const line = content.slice(0, match.index).split(/\r?\n/).length; + failures.push(`${surface.id}:${relativePath}:${line} uses unregistered MiniApp appearance variable ${match[0]}.`); + } + } + HOST_VARIABLE_FALLBACK_PATTERN.lastIndex = 0; + for (const match of content.matchAll(HOST_VARIABLE_FALLBACK_PATTERN)) { + const line = content.slice(0, match.index).split(/\r?\n/).length; + failures.push(`${surface.id}:${relativePath}:${line} adds a fallback to public host variable ${match[1]}.`); + } + HOST_VARIABLE_DEFINITION_PATTERN.lastIndex = 0; + for (const match of content.matchAll(HOST_VARIABLE_DEFINITION_PATTERN)) { + const line = content.slice(0, match.index).split(/\r?\n/).length; + failures.push(`${surface.id}:${relativePath}:${line} redefines host-owned MiniApp variable ${match[1]}.`); + } + } + + for (const [ownerIndex, count] of rawOwnerMatches) { + if (count === 0) { + const owner = surface.audit.rawColorOwners[ownerIndex]; + failures.push(`${surface.id} specialized owner ${owner.kind} is stale; remove or narrow the registry entry.`); + } + } + failures.push(...checkGeneratedBundles(surface, repositoryRoot)); + return { + surfaceId: surface.id, + engine: 'miniapp', + filesScanned: files.length, + hostVariableOccurrences, + hostVariables: Array.from(hostVariables).sort(), + unownedRawColors: rawFindings, + specializedOwners: (surface.audit.rawColorOwners ?? []).map((owner, index) => ({ + kind: owner.kind, + occurrences: rawOwnerMatches.get(index) ?? 0 + })), + failures + }; +} + +const NATIVE_PATTERNS = { + android: [ + { type: 'named-native-color', pattern: /\bColor\.(?:Black|White|Red|Green|Blue|Yellow|Gray|Magenta|Cyan|Transparent)\b/g }, + { type: 'native-color-constructor', pattern: /\bColor\s*\(\s*0x[0-9a-fA-F_]+\s*\)/g }, + { type: 'native-color-function', pattern: /\b(?:android\.graphics\.)?Color\.(?:argb|rgb|parseColor)\s*\(/g }, + { type: 'hex-string', pattern: /['\"]#[0-9a-fA-F]{3,8}\b/g } + ], + ios: [ + { type: 'named-native-color', pattern: /(? ( + `${surface.id}:${finding.file}:${finding.line} has raw native color ${finding.value}.` + )); + if (files.length === 0) failures.push(`${surface.id} scanned no native source files.`); + return { + surfaceId: surface.id, + engine: 'native', + platform: surface.audit.platform, + filesScanned: files.length, + rawColorOccurrences: findings.length, + findings, + failures + }; +} + +function listTreeFiles(root) { + return walkFiles(root).map(file => normalizePath(path.relative(root, file))); +} + +export function compareMirrorTrees(sourceRoot, mirrorRoot) { + const sourceFiles = listTreeFiles(sourceRoot); + const mirrorFiles = listTreeFiles(mirrorRoot); + const sourceSet = new Set(sourceFiles); + const mirrorSet = new Set(mirrorFiles); + const failures = []; + for (const file of sourceFiles) { + if (!mirrorSet.has(file)) { + failures.push(`mirror is missing ${file}`); + continue; + } + const source = fs.readFileSync(path.join(sourceRoot, file)); + const mirror = fs.readFileSync(path.join(mirrorRoot, file)); + if (!source.equals(mirror)) failures.push(`mirror differs at ${file}`); + } + for (const file of mirrorFiles) { + if (!sourceSet.has(file)) failures.push(`mirror has extra file ${file}`); + } + return failures; +} + +export function discoverMiniappRoots(registry, { repositoryRoot = REPOSITORY_ROOT } = {}) { + const discovered = []; + for (const parentPath of registry.discovery.miniappParents) { + const parent = path.join(repositoryRoot, parentPath); + for (const entry of fs.readdirSync(parent, { withFileTypes: true })) { + if (!entry.isDirectory()) continue; + const appRoot = path.join(parent, entry.name); + if (fs.existsSync(path.join(appRoot, 'meta.json'))) { + discovered.push(normalizePath(path.relative(repositoryRoot, appRoot))); + } + } + } + return discovered.sort(); +} + +function auditMiniappDiscovery(registry, repositoryRoot) { + const registered = new Set([ + ...registry.surfaces.filter(surface => surface.kind === 'miniapp').map(surface => normalizeRelativePath(surface.root)), + ...(registry.mirrors ?? []).map(mirror => normalizeRelativePath(mirror.path)) + ]); + const discovered = discoverMiniappRoots(registry, { repositoryRoot }); + const discoveredSet = new Set(discovered); + const failures = []; + for (const root of discovered) { + if (!registered.has(root)) failures.push(`Unregistered MiniApp discovered at ${root}.`); + } + for (const root of registered) { + if (!discoveredSet.has(root)) failures.push(`Registered MiniApp path is not discoverable: ${root}.`); + } + return { discovered, registered: Array.from(registered).sort(), failures }; +} + +function runSubprocess(command, args, repositoryRoot) { + return spawnSync(command, args, { + cwd: repositoryRoot, + encoding: 'utf8', + env: process.env, + maxBuffer: 64 * 1024 * 1024 + }); +} + +function parseJsonOutput(result, label) { + if (!result.stdout?.trim()) { + return { report: null, failures: [`${label} returned no JSON output. ${result.stderr?.trim() ?? ''}`.trim()] }; + } + try { + return { report: JSON.parse(result.stdout), failures: [] }; + } catch (error) { + return { + report: null, + failures: [`${label} returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`] + }; + } +} + +function auditThemeSurface(surface, repositoryRoot) { + const args = [THEME_AUDITOR_PATH, '--root', surface.root, '--json', '--top', '0']; + if (surface.audit.baseline) args.push('--baseline', surface.audit.baseline); + else args.push('--no-baseline'); + for (const packageName of surface.audit.packageContracts ?? []) args.push('--package-contract', packageName); + for (const excludePath of surface.audit.excludePaths ?? []) args.push('--exclude', excludePath); + const result = runSubprocess(process.execPath, args, repositoryRoot); + const parsed = parseJsonOutput(result, `${surface.id} theme audit`); + const failures = [...parsed.failures]; + if (result.status !== 0) { + failures.push(`${surface.id} theme audit failed: ${result.stderr?.trim() || `exit ${result.status}`}`); + } + if (parsed.report?.filesScanned === 0) failures.push(`${surface.id} theme audit scanned no files.`); + if (surface.audit.policy === 'canonical-ui-zero' && parsed.report) { + for (const metric of CANONICAL_ZERO_METRICS) { + const actual = getPathValue(parsed.report, metric); + if (typeof actual !== 'number') failures.push(`${surface.id} canonical policy references missing metric ${metric}.`); + else if (actual !== 0) failures.push(`${surface.id} ${metric} must be 0, found ${actual}.`); + } + } + return { surfaceId: surface.id, engine: 'theme', report: parsed.report, failures }; +} + +function auditCliSurface(surface, repositoryRoot) { + const args = [CLI_AUDITOR_PATH, '--root', surface.root, '--json']; + if (surface.audit.baseline) args.push('--baseline', surface.audit.baseline); + else args.push('--no-baseline'); + const result = runSubprocess(process.execPath, args, repositoryRoot); + const parsed = parseJsonOutput(result, `${surface.id} CLI audit`); + const failures = [...parsed.failures]; + if (result.status !== 0) failures.push(`${surface.id} CLI audit failed: ${result.stderr?.trim() || `exit ${result.status}`}`); + return { surfaceId: surface.id, engine: 'cli', report: parsed.report, failures }; +} + +function generatedCheckApplies(check, selectedSurfaces) { + const selectedIds = new Set(selectedSurfaces.map(surface => surface.id)); + const selectedKinds = new Set(selectedSurfaces.map(surface => surface.kind)); + return (check.surfaceIds ?? []).some(id => selectedIds.has(id)) + || (check.surfaceKinds ?? []).some(kind => selectedKinds.has(kind)); +} + +function runGeneratedCheck(check, repositoryRoot) { + const [executable, ...args] = check.command; + const command = executable === 'node' ? process.execPath : executable; + const result = runSubprocess(command, args, repositoryRoot); + return { + id: check.id, + status: result.status, + output: [result.stdout, result.stderr].filter(Boolean).join('\n').trim(), + failures: result.status === 0 + ? [] + : [`Generated artifact check ${check.id} failed: ${[result.stdout, result.stderr].filter(Boolean).join('\n').trim()}`] + }; +} + +export function loadRegistry(registryPath = DEFAULT_REGISTRY_PATH) { + return JSON.parse(fs.readFileSync(registryPath, 'utf8')); +} + +export function runFrontendColorAudit({ + registry, + repositoryRoot = REPOSITORY_ROOT, + surfaceIds = [], + surfaceKinds = [], + runGeneratedChecks = true +}) { + const failures = validateRegistry(registry, { repositoryRoot }); + const requestedIds = new Set(surfaceIds); + const requestedKinds = new Set(surfaceKinds); + const hasFilter = requestedIds.size > 0 || requestedKinds.size > 0; + for (const id of requestedIds) { + if (!registry.surfaces.some(surface => surface.id === id)) failures.push(`Unknown frontend color surface: ${id}.`); + } + for (const kind of requestedKinds) { + if (!SURFACE_KINDS.has(kind)) failures.push(`Unknown frontend color surface kind: ${kind}.`); + } + if (failures.length > 0) { + return { registryVersion: registry.version, surfaces: [], discovery: null, mirrors: [], generatedChecks: [], failures }; + } + + const selectedSurfaces = registry.surfaces.filter(surface => ( + !hasFilter || requestedIds.has(surface.id) || requestedKinds.has(surface.kind) + )); + const miniappContract = JSON.parse(fs.readFileSync(path.join(repositoryRoot, registry.contracts.miniappAppearance), 'utf8')); + const surfaceReports = []; + for (const surface of selectedSurfaces) { + let report; + if (surface.kind === 'contract-owner') { + report = { surfaceId: surface.id, engine: 'contract-owner', roots: surface.roots, failures: [] }; + } else if (surface.audit.engine === 'theme') { + report = auditThemeSurface(surface, repositoryRoot); + } else if (surface.audit.engine === 'cli') { + report = auditCliSurface(surface, repositoryRoot); + } else if (surface.audit.engine === 'native') { + report = auditNativeSurface(surface, { repositoryRoot }); + } else { + report = auditMiniappSurface(surface, miniappContract, { repositoryRoot }); + } + surfaceReports.push(report); + failures.push(...report.failures); + } + + const selectedMiniapps = selectedSurfaces.filter(surface => surface.kind === 'miniapp'); + const shouldAuditAllMiniappDiscovery = !hasFilter || requestedKinds.has('miniapp'); + const discovery = shouldAuditAllMiniappDiscovery ? auditMiniappDiscovery(registry, repositoryRoot) : null; + if (discovery) failures.push(...discovery.failures); + + const selectedMiniappIds = new Set(selectedMiniapps.map(surface => surface.id)); + const mirrorReports = (registry.mirrors ?? []) + .filter(mirror => !hasFilter || selectedMiniappIds.has(mirror.surfaceId) || requestedKinds.has('miniapp')) + .map((mirror) => { + const surface = registry.surfaces.find(candidate => candidate.id === mirror.surfaceId); + const mirrorFailures = compareMirrorTrees( + path.join(repositoryRoot, surface.root), + path.join(repositoryRoot, mirror.path) + ).map(failure => `${mirror.surfaceId} reference ${mirror.path}: ${failure}.`); + failures.push(...mirrorFailures); + return { surfaceId: mirror.surfaceId, path: mirror.path, failures: mirrorFailures }; + }); + + const generatedReports = runGeneratedChecks + ? (registry.generatedChecks ?? []) + .filter(check => generatedCheckApplies(check, selectedSurfaces)) + .map((check) => { + const report = runGeneratedCheck(check, repositoryRoot); + failures.push(...report.failures); + return report; + }) + : []; + return { + registryVersion: registry.version, + selectedSurfaceIds: selectedSurfaces.map(surface => surface.id), + surfaces: surfaceReports, + discovery, + mirrors: mirrorReports, + generatedChecks: generatedReports, + failures + }; +} + +function parseArgs(argv) { + const options = { + registryPath: DEFAULT_REGISTRY_PATH, + surfaceIds: [], + surfaceKinds: [], + json: false, + list: false, + runGeneratedChecks: true + }; + for (let index = 0; index < argv.length; index += 1) { + const arg = argv[index]; + if (arg === '--registry') options.registryPath = path.resolve(argv[++index] ?? ''); + else if (arg.startsWith('--registry=')) options.registryPath = path.resolve(arg.slice('--registry='.length)); + else if (arg === '--surface') options.surfaceIds.push(argv[++index] ?? ''); + else if (arg.startsWith('--surface=')) options.surfaceIds.push(arg.slice('--surface='.length)); + else if (arg === '--kind') options.surfaceKinds.push(argv[++index] ?? ''); + else if (arg.startsWith('--kind=')) options.surfaceKinds.push(arg.slice('--kind='.length)); + else if (arg === '--json') options.json = true; + else if (arg === '--list') options.list = true; + else if (arg === '--skip-generated-checks') options.runGeneratedChecks = false; + else if (arg === '--help' || arg === '-h') { + console.log('Usage: node scripts/audit-frontend-colors.mjs [--surface ] [--kind ] [--json] [--list]'); + process.exit(0); + } else throw new Error(`Unknown argument: ${arg}`); + } + return options; +} + +function formatSurfaceSummary(surfaceReport) { + if (surfaceReport.engine === 'theme') { + const report = surfaceReport.report; + return `${report?.filesScanned ?? 0} files, app raw=${report?.colorScopes?.appUi?.occurrences ?? '?'}, fallbacks=${report?.fallbackOccurrences ?? '?'}`; + } + if (surfaceReport.engine === 'cli') { + return `${surfaceReport.report?.presetFiles ?? 0} presets, runtime colors=${surfaceReport.report?.runtimePresetUniqueColors ?? '?'}`; + } + if (surfaceReport.engine === 'native') { + return `${surfaceReport.filesScanned} files, raw=${surfaceReport.rawColorOccurrences}`; + } + if (surfaceReport.engine === 'miniapp') { + const specialized = surfaceReport.specializedOwners.map(owner => `${owner.kind}:${owner.occurrences}`).join(', ') || 'none'; + return `${surfaceReport.filesScanned} files, host vars=${surfaceReport.hostVariableOccurrences}, specialized=${specialized}`; + } + return `${surfaceReport.roots.length} owner roots`; +} + +function main() { + const options = parseArgs(process.argv.slice(2)); + const registry = loadRegistry(options.registryPath); + if (options.list) { + for (const surface of registry.surfaces) console.log(`${surface.id}\t${surface.kind}\t${surface.label}`); + return; + } + const report = runFrontendColorAudit({ + registry, + repositoryRoot: REPOSITORY_ROOT, + surfaceIds: options.surfaceIds, + surfaceKinds: options.surfaceKinds, + runGeneratedChecks: options.runGeneratedChecks + }); + if (options.json) { + console.log(JSON.stringify(report, null, 2)); + } else { + for (const surfaceReport of report.surfaces) { + const mark = surfaceReport.failures.length === 0 ? 'ok' : 'failed'; + console.log(`[frontend-colors] ${mark} ${surfaceReport.surfaceId}: ${formatSurfaceSummary(surfaceReport)}`); + } + if (report.discovery) { + console.log(`[frontend-colors] ${report.discovery.failures.length === 0 ? 'ok' : 'failed'} MiniApp discovery: ${report.discovery.discovered.length} registered roots`); + } + for (const mirror of report.mirrors) { + console.log(`[frontend-colors] ${mirror.failures.length === 0 ? 'ok' : 'failed'} mirror ${mirror.surfaceId}`); + } + for (const check of report.generatedChecks) { + console.log(`[frontend-colors] ${check.failures.length === 0 ? 'ok' : 'failed'} generated ${check.id}`); + } + if (report.failures.length > 0) { + console.error('\nFrontend color governance failures:'); + for (const failure of report.failures) console.error(`- ${failure}`); + } else { + console.log(`[frontend-colors] all ${report.selectedSurfaceIds.length} selected surfaces passed.`); + } + } + if (report.failures.length > 0) process.exitCode = 1; +} + +if (process.argv[1] && path.resolve(process.argv[1]) === SCRIPT_PATH) { + main(); +} diff --git a/scripts/audit-frontend-colors.test.mjs b/scripts/audit-frontend-colors.test.mjs new file mode 100644 index 0000000000..096acec427 --- /dev/null +++ b/scripts/audit-frontend-colors.test.mjs @@ -0,0 +1,97 @@ +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; +import test from 'node:test'; + +import { + auditMiniappSurface, + auditNativeSurface, + compareMirrorTrees, + discoverMiniappRoots, + loadRegistry, + validateRegistry, +} from './audit-frontend-colors.mjs'; + +const repositoryRoot = process.cwd(); + +function writeText(filePath, content) { + fs.mkdirSync(path.dirname(filePath), { recursive: true }); + fs.writeFileSync(filePath, content, 'utf8'); +} + +test('frontend color surface registry covers every discovered MiniApp and names valid owners', () => { + const registry = loadRegistry(); + assert.deepEqual(validateRegistry(registry, { repositoryRoot }), []); + + const registered = new Set([ + ...registry.surfaces.filter(surface => surface.kind === 'miniapp').map(surface => surface.root), + ...registry.mirrors.map(mirror => mirror.path), + ]); + assert.deepEqual(discoverMiniappRoots(registry, { repositoryRoot }), Array.from(registered).sort()); + assert.ok(registry.exclusions.every(exclusion => exclusion.owner && exclusion.reason.length >= 24)); +}); + +test('MiniApp audit accepts a narrow data-viz owner and rejects ordinary raw colors or host fallbacks', (t) => { + const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'bitfun-miniapp-colors-')); + t.after(() => fs.rmSync(fixtureRoot, { recursive: true, force: true })); + writeText(path.join(fixtureRoot, 'app/ui.js'), "const SERIES = ['#ff00ff'];\n"); + writeText(path.join(fixtureRoot, 'app/style.css'), '.app { color: #ffffff; background: var(--bitfun-bg, #000000); }\n'); + const surface = { + id: 'fixture-miniapp', + root: 'app', + audit: { + engine: 'miniapp', + rawColorOwners: [{ + kind: 'data-viz', + file: 'ui.js', + startMarker: 'const SERIES = [', + endMarker: '];', + reason: 'Fixture categorical renderer palette owner.', + }], + }, + }; + const contract = { + variables: [{ name: '--bitfun-bg' }], + }; + + const report = auditMiniappSurface(surface, contract, { repositoryRoot: fixtureRoot }); + assert.equal(report.specializedOwners[0].occurrences, 1); + assert.match(report.failures.join('\n'), /unowned hex #ffffff/); + assert.match(report.failures.join('\n'), /fallback to public host variable --bitfun-bg/); +}); + +test('native source audit rejects raw platform colors while ignoring generated projections', (t) => { + const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'bitfun-native-colors-')); + t.after(() => fs.rmSync(fixtureRoot, { recursive: true, force: true })); + writeText(path.join(fixtureRoot, 'android/ui/Screen.kt'), 'val color = Color.White\n'); + writeText(path.join(fixtureRoot, 'android/generated/Tokens.kt'), 'val color = Color.Black\n'); + const surface = { + id: 'fixture-android', + root: 'android', + audit: { + engine: 'native', + platform: 'android', + extensions: ['.kt'], + excludePaths: ['generated'], + }, + }; + + const report = auditNativeSurface(surface, { repositoryRoot: fixtureRoot }); + assert.equal(report.filesScanned, 1); + assert.equal(report.rawColorOccurrences, 1); + assert.match(report.failures[0], /Color\.White/); +}); + +test('MiniApp reference mirrors are byte-exact, including file inventory', (t) => { + const fixtureRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'bitfun-miniapp-mirror-')); + t.after(() => fs.rmSync(fixtureRoot, { recursive: true, force: true })); + const source = path.join(fixtureRoot, 'source'); + const mirror = path.join(fixtureRoot, 'mirror'); + writeText(path.join(source, 'style.css'), '.app {}\n'); + writeText(path.join(mirror, 'style.css'), '.app {}\n'); + assert.deepEqual(compareMirrorTrees(source, mirror), []); + + writeText(path.join(mirror, 'style.css'), '.app { display: block; }\n'); + assert.deepEqual(compareMirrorTrees(source, mirror), ['mirror differs at style.css']); +}); diff --git a/scripts/audit-theme-colors.mjs b/scripts/audit-theme-colors.mjs index e94f71a391..b2676441be 100644 --- a/scripts/audit-theme-colors.mjs +++ b/scripts/audit-theme-colors.mjs @@ -17,6 +17,7 @@ import { EXCEPTION_PATH_PARTS, FALLBACK_VAR_CONTRACTS, PACKAGE_CSS_VAR_DEFINITION_CONTRACTS, + PACKAGE_CSS_VAR_IMPORT_CONTRACTS, REGISTERED_DYNAMIC_VAR_PREFIXES, RUNTIME_CONTRACT_VAR_DEFINITION_PATH_PARTS, STATIC_CONTRACT_VAR_DEFINITION_PATH_PARTS, @@ -30,6 +31,68 @@ import { writeReportJson } from './theme-color-audit-utils.mjs'; const COLOR_PATTERN = /#[0-9a-fA-F]{3,8}\b|rgba?\(\s*[-+]?\d*\.?\d+\s*,\s*[-+]?\d*\.?\d+\s*,\s*[-+]?\d*\.?\d+(?:\s*,\s*(?:[-+]?\d*\.?\d+|var\([^)]+\)))?\s*\)|hsla?\(\s*[-+]?\d*\.?\d+(?:deg|rad|turn)?\s*,\s*[-+]?\d*\.?\d+%\s*,\s*[-+]?\d*\.?\d+%(?:\s*,\s*(?:[-+]?\d*\.?\d+|var\([^)]+\)))?\s*\)/g; +const CSS_NAMED_COLORS = new Set(` + aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue + blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson + cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkgrey darkkhaki darkmagenta + darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray + darkslategrey darkturquoise darkviolet deeppink deepskyblue dimgray dimgrey dodgerblue firebrick + floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow grey + honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon + lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightgrey lightpink + lightsalmon lightseagreen lightskyblue lightslategray lightslategrey lightsteelblue lightyellow lime + limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen + mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose + moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen + paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple rebeccapurple red + rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue + slategray slategrey snow springgreen steelblue tan teal thistle tomato turquoise violet wheat white + whitesmoke yellow yellowgreen +`.trim().split(/\s+/)); +const CSS_NAMED_COLOR_PATTERN = new RegExp( + `(?:^|[^\\w-])(${Array.from(CSS_NAMED_COLORS).sort((a, b) => b.length - a.length).join('|')})(?![\\w-])`, + 'gi', +); +const COMMON_NAMED_COLOR_RGB = new Map([ + ['black', [0, 0, 0]], + ['silver', [192, 192, 192]], + ['gray', [128, 128, 128]], + ['grey', [128, 128, 128]], + ['white', [255, 255, 255]], + ['maroon', [128, 0, 0]], + ['red', [255, 0, 0]], + ['purple', [128, 0, 128]], + ['fuchsia', [255, 0, 255]], + ['magenta', [255, 0, 255]], + ['green', [0, 128, 0]], + ['lime', [0, 255, 0]], + ['olive', [128, 128, 0]], + ['yellow', [255, 255, 0]], + ['navy', [0, 0, 128]], + ['blue', [0, 0, 255]], + ['teal', [0, 128, 128]], + ['aqua', [0, 255, 255]], + ['cyan', [0, 255, 255]], + ['orange', [255, 165, 0]], + ['rebeccapurple', [102, 51, 153]], +]); +const STYLE_SOURCE_EXTENSIONS = new Set(['.css', '.less', '.sass', '.scss']); +const MARKUP_SOURCE_EXTENSIONS = new Set(['.html', '.svg']); +const CSS_DECLARATION_PATTERN = + /(?:^|[;{])\s*((?:--|\$)?[a-zA-Z_][a-zA-Z0-9_-]*)\s*:\s*([^;{}]+)/gm; +const CSS_COLOR_ATTRIBUTE_PATTERN = new RegExp( + `(?:^|[^\\w-])(?:color|fill|stroke|stop-color|flood-color|lighting-color)\\s*=\\s*['"](${Array.from(CSS_NAMED_COLORS).join('|')})['"]`, + 'gi', +); +const SCRIPT_COLOR_VALUE_PATTERN = new RegExp( + `(?:^|[,{;\\s])(?:color|backgroundColor|borderColor|outlineColor|caretColor|textDecorationColor|fill|stroke)\\s*:\\s*['"\\x60](${Array.from(CSS_NAMED_COLORS).join('|')})['"\\x60]`, + 'gi', +); +const RGB_CHANNEL_SOURCE = '(?:25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]?\\d)'; +const RAW_RGB_CHANNEL_DEFINITION_PATTERN = new RegExp( + `(?:^|[;{])\\s*(?:--|\\$)[a-zA-Z_][a-zA-Z0-9_-]*\\s*:\\s*(${RGB_CHANNEL_SOURCE}\\s*,\\s*${RGB_CHANNEL_SOURCE}\\s*,\\s*${RGB_CHANNEL_SOURCE})\\s*(?=;|})`, + 'gm', +); const TOKEN_ALIAS_DEFINITION_PATTERN = /(?:^|[;{\s])(\$[a-zA-Z0-9_-]+|--[a-zA-Z0-9_-]+)\s*:\s*(#[0-9a-fA-F]{3,8}\b|rgba?\(\s*[-+]?\d*\.?\d+\s*,\s*[-+]?\d*\.?\d+\s*,\s*[-+]?\d*\.?\d+(?:\s*,\s*(?:[-+]?\d*\.?\d+|var\([^)]+\)))?\s*\)|hsla?\(\s*[-+]?\d*\.?\d+(?:deg|rad|turn)?\s*,\s*[-+]?\d*\.?\d+%\s*,\s*[-+]?\d*\.?\d+%(?:\s*,\s*(?:[-+]?\d*\.?\d+|var\([^)]+\)))?\s*\))/gm; const CSS_VAR_USAGE_PATTERN = /var\(\s*(--[a-zA-Z0-9_-]+)/g; @@ -80,6 +143,8 @@ function parseArgs(argv) { reportJson: null, baselinePath: undefined, noBaseline: false, + packageContracts: [], + excludePaths: [], top: 15, budget: 120, }; @@ -110,6 +175,30 @@ function parseArgs(argv) { } } else if (arg === '--no-baseline') { options.noBaseline = true; + } else if (arg === '--package-contract') { + const packageName = argv[++index]; + if (!packageName) { + throw new Error('--package-contract requires a package name'); + } + options.packageContracts.push(packageName); + } else if (arg.startsWith('--package-contract=')) { + const packageName = arg.slice('--package-contract='.length); + if (!packageName) { + throw new Error('--package-contract requires a package name'); + } + options.packageContracts.push(packageName); + } else if (arg === '--exclude') { + const excludePath = argv[++index]; + if (!excludePath) { + throw new Error('--exclude requires a root-relative path'); + } + options.excludePaths.push(excludePath); + } else if (arg.startsWith('--exclude=')) { + const excludePath = arg.slice('--exclude='.length); + if (!excludePath) { + throw new Error('--exclude requires a root-relative path'); + } + options.excludePaths.push(excludePath); } else if (arg === '--root') { options.root = argv[++index] ?? DEFAULT_ROOT; } else if (arg === '--top') { @@ -136,6 +225,9 @@ Options: --budget Unique app color budget for the summary. Default: 120 --baseline Enforce a theme color governance baseline. --no-baseline Disable baseline enforcement. + --package-contract + Treat a declared design-system package as an external CSS variable owner. + --exclude Exclude an explicit root-relative file or directory. Repeatable. --json Print machine-readable JSON instead of text. --report-json Write the machine-readable report to a file. `); @@ -170,6 +262,20 @@ function normalizePath(filePath) { return filePath.split(path.sep).join('/'); } +function normalizeRootRelativePath(filePath) { + return normalizePath(path.normalize(filePath)) + .replace(/^\.\//, '') + .replace(/\/$/, ''); +} + +function isExplicitlyExcluded(rootRelativePath, excludePaths) { + const normalizedPath = normalizeRootRelativePath(rootRelativePath); + return excludePaths.some((excludePath) => { + const normalizedExclude = normalizeRootRelativePath(excludePath); + return normalizedPath === normalizedExclude || normalizedPath.startsWith(`${normalizedExclude}/`); + }); +} + function isAuditTestFile(relativePath) { return ( /(^|\/)__tests__\//.test(relativePath) @@ -181,6 +287,7 @@ function isGeneratedBuildArtifact(rootRelativePath) { return ( rootRelativePath === 'generated/version.ts' || rootRelativePath === 'generated/version-injection.html' + || rootRelativePath.startsWith('public/monaco-editor/') ); } @@ -214,14 +321,22 @@ function isGeneratedWidgetAppearancePayloadFile(relativePath) { function collectGeneratedWidgetPayloadVarNames(content) { const namesBlock = /export const WIDGET_APPEARANCE_VARIABLE_NAMES = \[([\s\S]*?)\] as const;/.exec(content)?.[1]; - if (!namesBlock) { - throw new Error('Unable to parse WIDGET_APPEARANCE_VARIABLE_NAMES; refusing to audit a partial payload contract.'); + if (namesBlock) { + const names = collectMatches(namesBlock, CSS_VAR_LITERAL_PATTERN).map(match => match[1]); + if (names.length === 0) { + throw new Error('WIDGET_APPEARANCE_VARIABLE_NAMES must not be empty.'); + } + return names; } - const names = collectMatches(namesBlock, CSS_VAR_LITERAL_PATTERN).map(match => match[1]); - if (names.length === 0) { - throw new Error('WIDGET_APPEARANCE_VARIABLE_NAMES must not be empty.'); + + if (/Object\.values\(themeCssVariables\)/.test(content)) { + const themeContract = PACKAGE_CSS_VAR_DEFINITION_CONTRACTS.find( + contract => contract.packageName === '@bitfun/theme-bitfun', + ); + if (themeContract?.variables.length) return [...themeContract.variables]; } - return names; + + throw new Error('Unable to parse WIDGET_APPEARANCE_VARIABLE_NAMES or resolve it from the canonical theme contract.'); } function pathMatchesPart(relativePath, pathPart) { @@ -229,6 +344,7 @@ function pathMatchesPart(relativePath, pathPart) { const normalizedPart = pathPart.toLowerCase(); return ( normalizedPath === normalizedPart + || normalizedPath.endsWith(`/${normalizedPart}`) || normalizedPath.startsWith(`${normalizedPart}/`) || normalizedPath.startsWith(`${normalizedPart}.`) || normalizedPath.includes(`/${normalizedPart}/`) @@ -238,7 +354,8 @@ function pathMatchesPart(relativePath, pathPart) { function getColorDomain(relativePath) { const rule = COLOR_DOMAIN_RULES.find(entry => ( - entry.pathParts.some(part => pathMatchesPart(relativePath, part)) + (!entry.extensions || entry.extensions.includes(path.extname(relativePath).toLowerCase())) + && entry.pathParts.some(part => pathMatchesPart(relativePath, part)) )); return rule?.key ?? 'appUi'; } @@ -258,6 +375,65 @@ function collectMatches(content, pattern) { return Array.from(content.matchAll(pattern)); } +function collectNamedColorValues(content, relativePath) { + const colors = []; + const extension = path.extname(relativePath).toLowerCase(); + + if (STYLE_SOURCE_EXTENSIONS.has(extension)) { + for (const declaration of collectMatches(content, CSS_DECLARATION_PATTERN)) { + if (declaration[1].toLowerCase() === 'content') continue; + const valueWithoutUrls = declaration[2].replace(/url\((?:"[^"]*"|'[^']*'|[^)]*)\)/gi, ' '); + for (const match of collectMatches(valueWithoutUrls, CSS_NAMED_COLOR_PATTERN)) { + colors.push(match[1].toLowerCase()); + } + } + } + + if (STYLE_SOURCE_EXTENSIONS.has(extension) || MARKUP_SOURCE_EXTENSIONS.has(extension)) { + for (const match of collectMatches(content, CSS_COLOR_ATTRIBUTE_PATTERN)) { + colors.push(match[1].toLowerCase()); + } + } + + if (!STYLE_SOURCE_EXTENSIONS.has(extension) && !MARKUP_SOURCE_EXTENSIONS.has(extension)) { + for (const match of collectMatches(content, SCRIPT_COLOR_VALUE_PATTERN)) { + colors.push(match[1].toLowerCase()); + } + } + + return colors; +} + +function collectRawRgbChannelValues(content) { + return collectMatches(content, RAW_RGB_CHANNEL_DEFINITION_PATTERN).map((match) => { + const channels = match[1].split(',').map(channel => Number(channel.trim())); + return `rgb(${channels.join(', ')})`; + }); +} + +function collectColorValues(content, relativePath) { + return [ + ...collectMatches(content, COLOR_PATTERN).map(match => match[0]), + ...collectNamedColorValues(content, relativePath), + ...collectRawRgbChannelValues(content), + ]; +} + +function collectImportedPackageNames(files, cwd) { + const packageNames = new Set(); + for (const file of files) { + const relativePath = normalizePath(path.relative(cwd, file)); + const content = createAuditContent(fs.readFileSync(file, 'utf8'), relativePath); + for (const contract of PACKAGE_CSS_VAR_IMPORT_CONTRACTS) { + if (!content.includes(contract.specifier)) continue; + for (const packageName of contract.packageNames) { + packageNames.add(packageName); + } + } + } + return packageNames; +} + function contractOwnerMatchesRoot(contract, rootRelativePath) { return String(contract.owner ?? '') .split(';') @@ -442,13 +618,19 @@ function stripCommentsForAudit(content, { stripLineComments = true } = {}) { } function createAuditContent(content, relativePath) { - return stripCommentsForAudit(content, { + const withoutComments = stripCommentsForAudit(content, { stripLineComments: !relativePath.endsWith('.css'), }); + return withoutComments.replace(/&#(?:x[0-9a-f]+|\d+);/gi, match => ' '.repeat(match.length)); } function parseColor(color) { const trimmed = color.trim().toLowerCase(); + const named = COMMON_NAMED_COLOR_RGB.get(trimmed); + if (named) { + return { r: named[0], g: named[1], b: named[2], a: 1 }; + } + const hex = /^#([0-9a-f]{3,8})$/.exec(trimmed); if (hex) { const raw = hex[1]; @@ -782,12 +964,25 @@ function audit(options) { !isAuditTestFile(entry.relativePath) && isGeneratedBuildArtifact(entry.rootRelativePath) )); + const ignoredExplicitFiles = fileEntries.filter(entry => ( + !isAuditTestFile(entry.relativePath) + && !isGeneratedBuildArtifact(entry.rootRelativePath) + && isExplicitlyExcluded(entry.rootRelativePath, options.excludePaths) + )); const auditedFiles = fileEntries .filter(entry => ( !isAuditTestFile(entry.relativePath) && !isGeneratedBuildArtifact(entry.rootRelativePath) + && !isExplicitlyExcluded(entry.rootRelativePath, options.excludePaths) )) .map(entry => entry.file); + const importedPackageNames = collectImportedPackageNames(auditedFiles, cwd); + for (const packageName of options.packageContracts) { + if (!PACKAGE_CSS_VAR_DEFINITION_CONTRACTS.some(contract => contract.packageName === packageName)) { + throw new Error(`Unknown package CSS variable contract: ${packageName}`); + } + importedPackageNames.add(packageName); + } const tokenAliasDefinitionsByColorKey = collectTokenAliasDefinitions(auditedFiles, cwd); const colorCounts = new Map(); @@ -829,7 +1024,7 @@ function audit(options) { const tokenFile = isTokenFile(relativePath); const exceptionFile = isExceptionFile(relativePath); const colorDomain = getColorDomain(relativePath); - const colors = collectMatches(content, COLOR_PATTERN).map(match => match[0]); + const colors = collectColorValues(content, relativePath); if (colors.length > 0) { fileColorCounts.set(relativePath, colors.length); @@ -934,14 +1129,13 @@ function audit(options) { } } - if (checksFullThemeSourceRoot) { - for (const contract of PACKAGE_CSS_VAR_DEFINITION_CONTRACTS) { - for (const name of contract.variables) { - incrementMap(varDefinitionCounts, name); - addToSetMap(varDefinitionKinds, name, 'package-contract'); - addToSetMap(varDefinitionFiles, name, contract.owner); - contractVarDefinitions.add(name); - } + for (const contract of PACKAGE_CSS_VAR_DEFINITION_CONTRACTS) { + if (!importedPackageNames.has(contract.packageName)) continue; + for (const name of contract.variables) { + incrementMap(varDefinitionCounts, name); + addToSetMap(varDefinitionKinds, name, 'package-contract'); + addToSetMap(varDefinitionFiles, name, contract.owner); + contractVarDefinitions.add(name); } } @@ -1043,6 +1237,7 @@ function audit(options) { .filter(([name]) => ( runtimeContractVarDefinitions.has(name) && !staticContractVarDefinitions.has(name) + && !getDefinitionKinds(name).includes('package-contract') && !fallbackTokenCounts.has(name) )) .map(([key, count]) => ({ @@ -1205,6 +1400,7 @@ function audit(options) { definitionKind: getExplicitDefinitionKind(key), files: Array.from(generatedWidgetPayloadVarFiles.get(key) ?? []).sort().slice(0, 5), })); + const hasGeneratedWidgetPayloadContract = generatedWidgetPayloadVars.length > 0; const generatedWidgetPayloadCompatibilityAliases = generatedWidgetPayloadVars .map(entry => { const contract = resolveCompatibilityAliasContract(entry.key); @@ -1266,6 +1462,21 @@ function audit(options) { .filter(entry => !entry.definitionKind) .sort((a, b) => a.key.localeCompare(b.key)); const generatedWidgetPayloadVarNames = new Set(generatedWidgetPayloadVars.map(entry => entry.key)); + const canonicalThemeVariableNames = new Set( + PACKAGE_CSS_VAR_DEFINITION_CONTRACTS.find( + contract => contract.packageName === '@bitfun/theme-bitfun', + )?.variables ?? [], + ); + const generatedWidgetPayloadMissingCanonicalThemeVars = hasGeneratedWidgetPayloadContract + ? [...canonicalThemeVariableNames] + .filter(name => !generatedWidgetPayloadVarNames.has(name)) + .sort() + : []; + const generatedWidgetPayloadNonCanonicalVars = hasGeneratedWidgetPayloadContract + ? [...generatedWidgetPayloadVarNames] + .filter(name => !canonicalThemeVariableNames.has(name)) + .sort() + : []; const generatedWidgetPayloadMissingCompatibilityCanonicals = [ ...generatedWidgetPayloadCompatibilityAliases, ...generatedWidgetPayloadCompatibilityFamilies, @@ -1360,8 +1571,14 @@ function audit(options) { filesScanned: auditedFiles.length, ignoredTestFiles: ignoredTestFiles.length, ignoredGeneratedFiles: ignoredGeneratedFiles.length, + ignoredExplicitFiles: ignoredExplicitFiles.length, + explicitExclusions: options.excludePaths.map(normalizeRootRelativePath).sort(), filesWithColors: fileColorCounts.size, colorOccurrences, + packageCssContracts: { + importedPackages: [...importedPackageNames].sort(), + importedPackageUnique: importedPackageNames.size, + }, uniqueColors: colorCounts.size, colorScopes: { appUi: { @@ -1418,8 +1635,11 @@ function audit(options) { families: compatibilityAliasFamilyEntries, }, generatedWidgetPayload: { + present: hasGeneratedWidgetPayloadContract, varUnique: generatedWidgetPayloadVars.length, occurrences: generatedWidgetPayloadVars.reduce((total, entry) => total + entry.count, 0), + missingCanonicalThemeUnique: generatedWidgetPayloadMissingCanonicalThemeVars.length, + nonCanonicalUnique: generatedWidgetPayloadNonCanonicalVars.length, undefinedUnique: generatedWidgetPayloadUndefinedVars.length, compatibilityAliasUnique: generatedWidgetPayloadCompatibilityAliases.length, compatibilityAliasOccurrences: generatedWidgetPayloadCompatibilityAliases.reduce( @@ -1442,6 +1662,8 @@ function audit(options) { topCompatibilityFamilies: generatedWidgetPayloadCompatibilityFamilies.slice(0, options.top), externalOnlyCompatibility: generatedWidgetPayloadExternalOnlyCompatibility.slice(0, REPORT_ROW_LIMIT), undefinedVars: generatedWidgetPayloadUndefinedVars.slice(0, REPORT_ROW_LIMIT), + missingCanonicalThemeVars: generatedWidgetPayloadMissingCanonicalThemeVars.slice(0, REPORT_ROW_LIMIT), + nonCanonicalVars: generatedWidgetPayloadNonCanonicalVars.slice(0, REPORT_ROW_LIMIT), missingCompatibilityCanonicals: generatedWidgetPayloadMissingCompatibilityCanonicals.slice(0, REPORT_ROW_LIMIT), unexportedCompatibilityCanonicals: generatedWidgetPayloadUnexportedCompatibilityCanonicals.slice( 0, @@ -1524,6 +1746,7 @@ function printText(report) { console.log(`Files scanned: ${report.filesScanned}`); console.log(`Ignored test files: ${report.ignoredTestFiles}`); console.log(`Ignored generated files: ${report.ignoredGeneratedFiles}`); + console.log(`Ignored explicitly excluded files: ${report.ignoredExplicitFiles}`); console.log(`Files with colors: ${report.filesWithColors}`); console.log(`Color occurrences: ${report.colorOccurrences}`); console.log(`Unique colors: ${report.uniqueColors}`); @@ -1547,6 +1770,8 @@ function printText(report) { ); console.log( `Generated widget payload: vars=${report.generatedWidgetPayload.varUnique}, ` + + `missingCanonicalTheme=${report.generatedWidgetPayload.missingCanonicalThemeUnique}, ` + + `nonCanonical=${report.generatedWidgetPayload.nonCanonicalUnique}, ` + `undefined=${report.generatedWidgetPayload.undefinedUnique}, ` + `compatAliases=${report.generatedWidgetPayload.compatibilityAliasUnique}, ` + `compatAliasFamilies=${report.generatedWidgetPayload.compatibilityAliasFamilyUnique}, ` + diff --git a/scripts/audit-theme-colors.test.mjs b/scripts/audit-theme-colors.test.mjs index f988791977..4e27a81f7b 100644 --- a/scripts/audit-theme-colors.test.mjs +++ b/scripts/audit-theme-colors.test.mjs @@ -20,11 +20,12 @@ import { const root = process.cwd(); const SOURCE_OWNER_ROOTS = [ 'BitFun-Installer/src', + 'src/apps/mobile/design-system/preview', 'src/mobile-web/src', - 'src/web-ui/src', + 'src/web-ui', ]; const NEAR_PAIR_DECISION_AUDIT_ROOTS = [ - { root: 'src/web-ui/src', args: ['--json', '--no-baseline', '--top', '0'] }, + { root: 'src/web-ui', args: ['--json', '--no-baseline', '--top', '0'] }, { root: 'src/mobile-web/src', args: ['--root', 'src/mobile-web/src', '--json', '--no-baseline', '--top', '0'] }, { root: 'BitFun-Installer/src', args: ['--root', 'BitFun-Installer/src', '--json', '--no-baseline', '--top', '0'] }, ]; @@ -114,6 +115,10 @@ test('theme CSS var contract registry is explicit and non-overlapping', () => { assert.equal(typeof rule.label, 'string'); assert.ok(rule.label.trim(), `${rule.key} must have a label`); assert.ok(Array.isArray(rule.pathParts) && rule.pathParts.length > 0, `${rule.key} must have path parts`); + if (rule.extensions !== undefined) { + assert.ok(Array.isArray(rule.extensions) && rule.extensions.length > 0, `${rule.key} extensions must be non-empty`); + assert.ok(rule.extensions.every(extension => /^\.[a-z0-9]+$/.test(extension)), `${rule.key} extensions must be normalized`); + } } const dynamicPrefixes = new Set(DYNAMIC_VAR_FAMILY_CONTRACTS.map(contract => contract.prefix)); @@ -163,7 +168,7 @@ test('theme CSS var contract registry is explicit and non-overlapping', () => { 'every specialized color domain must have an owner contract', ); for (const contract of COLOR_DOMAIN_CONTRACTS) { - assert.ok(contract.owner.includes('src/web-ui/src/'), `${contract.key} must name a source owner`); + assert.ok(contractOwnerHasKnownSource(contract.owner), `${contract.key} must name a source owner`); assert.ok(contract.reason.trim().length >= 30, `${contract.key} must explain why the domain exists`); assert.ok(contract.mergePolicy.trim().length >= 30, `${contract.key} must define a merge policy`); } @@ -321,6 +326,7 @@ test('repository specialized near color pairs have explicit decisions', () => { test('generated widget iframe has no compatibility alias module or contracts', () => { assert.equal(TOKEN_COMPATIBILITY_ALIAS_CONTRACTS.length, 0); assert.equal(TOKEN_COMPATIBILITY_ALIAS_FAMILY_CONTRACTS.length, 0); + assert.equal(SURFACE_TOKEN_RENAME_CONTRACTS.length, 0); assert.equal( fs.existsSync(path.join(root, 'src/web-ui/src/tools/generative-widget/appearancePayloadCompatibility.ts')), false, @@ -336,7 +342,7 @@ test('theme color audit emits scoped machine-readable reports', (t) => { '}', '', ].join('\n'), - 'infrastructure/appearance/adapters/CssTokenAppearanceAdapter.ts': [ + 'infrastructure/appearance/adapters/ThemeTokenAppearanceAdapter.ts': [ "document.documentElement.style.setProperty('--runtime-only', '#333333');", '', ].join('\n'), @@ -418,12 +424,14 @@ test('theme color audit reports static contract token external consumption', (t) ); }); -test('theme color audit reports deprecated surface-local token names', (t) => { +test('theme color audit resolves canonical variables from imported package CSS contracts', (t) => { const { dir, sourceRoot } = createFixture({ - 'tools/editor/meditor/components/TiptapEditor.scss': [ - '.m-editor-tiptap {', - ' --m-editor-highlight-rgb: var(--private-markdown-editor-highlight-rgb);', - ' background: rgba(var(--m-editor-highlight-rgb), 0.15);', + 'main.tsx': "import '@bitfun/theme-bitfun/default.css';\n", + 'app/App.scss': [ + '.app {', + ' color: var(--bf-color-content-primary);', + ' background: var(--bf-color-surface-canvas);', + ' padding: var(--bf-space-1);', '}', '', ].join('\n'), @@ -434,14 +442,29 @@ test('theme color audit reports deprecated surface-local token names', (t) => { assert.equal(result.status, 0, result.stderr || result.stdout); const report = JSON.parse(result.stdout); - assert.equal(report.surfaceTokenRenames.activeUnique, 1); - assert.equal(report.surfaceTokenRenames.activeOccurrences, 2); - assert.deepEqual( - report.surfaceTokenRenames.active.map(row => [row.key, row.canonical, row.definitionCount, row.usageCount]), - [ - ['--m-editor-highlight-rgb', '--private-markdown-editor-highlight-rgb', 1, 1], - ], - ); + assert.deepEqual(report.packageCssContracts.importedPackages, [ + '@bitfun/design-tokens', + '@bitfun/theme-bitfun', + ]); + assert.equal(report.cssVarDefinitions.unresolvedUnique, 0); + assert.equal(report.cssVarDefinitions.unresolvedRequiredUnique, 0); +}); + +test('theme color audit does not require a widget payload on surfaces without that contract', (t) => { + const { dir, sourceRoot } = createFixture({ + 'main.tsx': "import '@bitfun/theme-bitfun/default.css';\n", + 'app/App.scss': '.app { color: var(--bf-color-content-primary); }\n', + }); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + + const result = runAudit(['--root', sourceRoot, '--json', '--no-baseline']); + assert.equal(result.status, 0, result.stderr || result.stdout); + + const report = JSON.parse(result.stdout); + assert.equal(report.generatedWidgetPayload.present, false); + assert.equal(report.generatedWidgetPayload.missingCanonicalThemeUnique, 0); + assert.equal(report.generatedWidgetPayload.nonCanonicalUnique, 0); + assert.equal(report.generatedWidgetPayload.undefinedUnique, 0); }); test('theme color audit counts only the generated widget variable contract', (t) => { @@ -594,6 +617,95 @@ test('theme color audit ignores comment-only color-like text', (t) => { assert.equal(report.colorDomainScopes.appUi.uniqueColors, 1); }); +test('theme color audit counts named CSS colors and raw RGB channel variables without selector or comment noise', (t) => { + const { dir, sourceRoot } = createFixture({ + 'app/App.scss': [ + '/* white and black are documentation here, not values. */', + '.app[data-tone="red"] {', + ' --private-brand-rgb: 12, 34, 56;', + ' color: white;', + ' box-shadow: 0 0 0 1px black;', + '}', + '.app::before { content: "blue"; }', + '.search {', + ' mask: url("data:image/svg+xml;utf8,");', + '}', + '', + ].join('\n'), + 'app/style.ts': "export const style = { color: 'blue' };\n", + }); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + + const result = runAudit(['--root', sourceRoot, '--json', '--no-baseline']); + assert.equal(result.status, 0, result.stderr || result.stdout); + + const report = JSON.parse(result.stdout); + assert.equal(report.colorOccurrences, 5); + assert.equal(report.uniqueColors, 5); + assert.deepEqual( + new Set(report.topColors.map(entry => entry.key)), + new Set(['rgb(12, 34, 56)', 'white', 'black', 'red', 'blue']), + ); + assert.equal(report.colorDomainScopes.appUi.occurrences, 5); +}); + +test('theme color audit ignores numeric character references in SVG metadata', (t) => { + const { dir, sourceRoot } = createFixture({ + 'app/assets/icon.svg': [ + '', + ' ', + '', + '', + ].join('\n'), + }); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + + const result = runAudit(['--root', sourceRoot, '--json', '--no-baseline']); + assert.equal(result.status, 0, result.stderr || result.stdout); + + const report = JSON.parse(result.stdout); + assert.equal(report.colorOccurrences, 0); + assert.equal(report.colorDomainScopes.assetMetadata.occurrences, 0); +}); + +test('theme color audit does not exempt executable styles merely because their path contains assets', (t) => { + const { dir, sourceRoot } = createFixture({ + 'app/assets/embedded-app/style.css': '.panel { color: #123456; }\n', + 'app/assets/brand.svg': '\n', + }); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + + const result = runAudit(['--root', sourceRoot, '--json', '--no-baseline']); + assert.equal(result.status, 0, result.stderr || result.stdout); + + const report = JSON.parse(result.stdout); + assert.equal(report.colorDomainScopes.appUi.occurrences, 1); + assert.equal(report.colorDomainScopes.assetMetadata.occurrences, 1); +}); + +test('theme color audit can resolve peer-owned public package variables explicitly', (t) => { + const { dir, sourceRoot } = createFixture({ + 'components/Button.css': '.button { color: var(--bf-color-content-primary); padding: var(--bf-space-2); }\n', + }); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + + const result = runAudit([ + '--root', sourceRoot, + '--package-contract', '@bitfun/design-tokens', + '--package-contract', '@bitfun/theme-bitfun', + '--json', + '--no-baseline', + ]); + assert.equal(result.status, 0, result.stderr || result.stdout); + + const report = JSON.parse(result.stdout); + assert.equal(report.cssVarDefinitions.unresolvedUnique, 0); + assert.deepEqual( + report.packageCssContracts.importedPackages, + ['@bitfun/design-tokens', '@bitfun/theme-bitfun'], + ); +}); + test('theme color audit keeps template literal and expression color values', (t) => { const { dir, sourceRoot } = createFixture({ 'app/App.tsx': [ @@ -641,7 +753,7 @@ test('theme color audit counts full CSS var governance debt before row truncatio (_, index) => `.loose-${index} { color: var(--loose-${index}); }`, ); const { dir, sourceRoot } = createFixture({ - 'infrastructure/appearance/adapters/CssTokenAppearanceAdapter.ts': `${runtimeDefinitions.join('\n')}\n`, + 'infrastructure/appearance/adapters/ThemeTokenAppearanceAdapter.ts': `${runtimeDefinitions.join('\n')}\n`, 'app/App.scss': `${missingRules.join('\n')}\n${fallbackRules.join('\n')}\n${runtimeRules.join('\n')}\n`, 'app/LooseVar.tsx': [ 'export function LooseVar() {', @@ -854,7 +966,7 @@ test('theme color audit fails when fallback tokens lack a boundary contract', (t test('theme color audit requires dynamic CSS var families to be registered', (t) => { const { dir, sourceRoot } = createFixture({ - 'infrastructure/appearance/adapters/CssTokenAppearanceAdapter.ts': [ + 'infrastructure/appearance/adapters/ThemeTokenAppearanceAdapter.ts': [ "for (const [key, value] of Object.entries(theme.extra)) {", " document.documentElement.style.setProperty(`--unregistered-${key}`, value);", '}', @@ -881,7 +993,7 @@ test('theme color audit requires dynamic CSS var families to be registered', (t) test('theme color audit accepts registered dynamic CSS var families', (t) => { const { dir, sourceRoot } = createFixture({ - 'infrastructure/appearance/adapters/CssTokenAppearanceAdapter.ts': [ + 'infrastructure/appearance/adapters/ThemeTokenAppearanceAdapter.ts': [ "for (const [key, value] of Object.entries(fontSizeTokens)) {", " document.documentElement.style.setProperty(`--bf-font-size-${key}`, value);", '}', @@ -909,7 +1021,7 @@ test('theme color audit requires exact exports for dynamic-family CSS var usages '}', '', ].join('\n'), - 'infrastructure/appearance/adapters/CssTokenAppearanceAdapter.ts': [ + 'infrastructure/appearance/adapters/ThemeTokenAppearanceAdapter.ts': [ "for (const [key, value] of Object.entries(theme.colors.purple)) {", " document.documentElement.style.setProperty(`--bf-appearance-token-color-purple-${key}`, value);", '}', @@ -1020,3 +1132,25 @@ test('theme color audit fails stale non-contract var allowlist entries', (t) => /nonContractDynamicInputs allowlist entry --removed-var is stale/, ); }); + +test('theme color audit excludes only explicitly named root-relative paths', (t) => { + const { dir, sourceRoot } = createFixture({ + 'app/App.scss': '.app { color: var(--bf-color-content-primary); }\n', + 'generated/palette.css': '.generated { color: #ff00ff; }\n', + }); + t.after(() => fs.rmSync(dir, { recursive: true, force: true })); + + const result = runAudit([ + '--root', sourceRoot, + '--exclude', 'generated', + '--package-contract', '@bitfun/theme-bitfun', + '--json', + '--no-baseline', + ]); + assert.equal(result.status, 0, result.stderr || result.stdout); + const report = JSON.parse(result.stdout); + assert.equal(report.filesScanned, 1); + assert.equal(report.ignoredExplicitFiles, 1); + assert.deepEqual(report.explicitExclusions, ['generated']); + assert.equal(report.colorScopes.appUi.occurrences, 0); +}); diff --git a/scripts/frontend-color-surface-registry.json b/scripts/frontend-color-surface-registry.json new file mode 100644 index 0000000000..04ac73f09d --- /dev/null +++ b/scripts/frontend-color-surface-registry.json @@ -0,0 +1,481 @@ +{ + "version": 1, + "description": "Authoritative registry for every BitFun frontend color surface, its canonical token owner, narrowly scoped specialized palette owners, and non-product artifacts excluded from ordinary UI governance.", + "contracts": { + "webSystem": "design-system/packages/design-tokens/src/system.tokens.json", + "webTheme": "design-system/packages/theme-bitfun/src/light.tokens.json", + "miniappAppearance": "src/shared/miniapp-appearance/contract.json", + "nativeMobile": "src/apps/mobile/design-system/tokens/mobile-tokens.json" + }, + "discovery": { + "miniappParents": [ + "MiniApp/Demo", + "src/crates/contracts/product-domains/src/miniapp/builtin/assets", + "src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples" + ] + }, + "surfaces": [ + { + "id": "design-system-token-owner", + "label": "Design system token authoring", + "kind": "contract-owner", + "owner": "@bitfun/design-tokens and @bitfun/theme-bitfun", + "roots": [ + "design-system/packages/design-tokens/src", + "design-system/packages/theme-bitfun/src" + ] + }, + { + "id": "web-ui", + "label": "Web UI", + "kind": "canonical-web", + "owner": "@bitfun/theme-bitfun plus Web UI Appearance theme-tokens", + "root": "src/web-ui", + "audit": { + "engine": "theme", + "baseline": "scripts/theme-color-governance-baseline.json" + } + }, + { + "id": "design-system-ui", + "label": "Public design-system UI package", + "kind": "canonical-web", + "owner": "@bitfun/ui consuming peer-owned canonical tokens", + "root": "design-system/packages/ui", + "audit": { + "engine": "theme", + "baseline": "scripts/theme-color-governance-baseline.design-system-ui.json", + "packageContracts": ["@bitfun/design-tokens", "@bitfun/theme-bitfun"] + } + }, + { + "id": "design-lab", + "label": "Design Lab", + "kind": "canonical-web", + "owner": "@bitfun/theme-bitfun", + "root": "design-system/apps/design-lab", + "audit": { + "engine": "theme", + "baseline": "scripts/theme-color-governance-baseline.design-lab.json" + } + }, + { + "id": "miniapp-market", + "label": "Mini App Market", + "kind": "canonical-web", + "owner": "@bitfun/theme-bitfun", + "root": "src/miniapp-market-web", + "audit": { + "engine": "theme", + "baseline": "scripts/theme-color-governance-baseline.miniapp-market.json" + } + }, + { + "id": "skin-market", + "label": "Skin Market", + "kind": "canonical-web", + "owner": "@bitfun/theme-bitfun", + "root": "src/skin-market-web", + "audit": { + "engine": "theme", + "baseline": "scripts/theme-color-governance-baseline.skin-market.json" + } + }, + { + "id": "website", + "label": "Public website", + "kind": "canonical-web", + "owner": "@bitfun/theme-bitfun", + "root": "website", + "audit": { + "engine": "theme", + "baseline": "scripts/theme-color-governance-baseline.website.json" + } + }, + { + "id": "mobile-web", + "label": "Mobile Web and Remote Control", + "kind": "canonical-web", + "owner": "@bitfun/theme-bitfun", + "root": "src/mobile-web", + "audit": { + "engine": "theme", + "baseline": "scripts/theme-color-governance-baseline.mobile-web.json" + } + }, + { + "id": "installer", + "label": "BitFun Installer", + "kind": "canonical-web", + "owner": "@bitfun/theme-bitfun with the installer preset owner", + "root": "BitFun-Installer", + "audit": { + "engine": "theme", + "baseline": "scripts/theme-color-governance-baseline.installer.json" + } + }, + { + "id": "desktop-bootstrap", + "label": "Desktop pre-JavaScript bootstrap pages", + "kind": "canonical-web", + "owner": "generated @bitfun/theme-bitfun bootstrap projection", + "root": "src/apps/desktop/bootstrap-ui", + "audit": { + "engine": "theme", + "policy": "canonical-ui-zero", + "packageContracts": ["@bitfun/design-tokens", "@bitfun/theme-bitfun"] + } + }, + { + "id": "mobile-design-preview", + "label": "Native mobile comparison preview", + "kind": "canonical-web", + "owner": "canonical web tokens for chrome and generated native mobile tokens for device content", + "root": "src/apps/mobile/design-system/preview", + "audit": { + "engine": "theme", + "policy": "canonical-ui-zero", + "packageContracts": ["@bitfun/design-tokens", "@bitfun/theme-bitfun"], + "excludePaths": ["generated"] + } + }, + { + "id": "cli", + "label": "CLI and TUI", + "kind": "terminal", + "owner": "src/apps/cli/themes/presets and the terminal theme adapter", + "root": "src/apps/cli", + "audit": { + "engine": "cli", + "baseline": "scripts/theme-color-governance-baseline.cli.json" + } + }, + { + "id": "native-android", + "label": "Native Android", + "kind": "native-mobile", + "owner": "src/apps/mobile/design-system/tokens/mobile-tokens.json", + "root": "src/apps/mobile/android/app/src/main/kotlin", + "audit": { + "engine": "native", + "platform": "android", + "extensions": [".kt"], + "excludePaths": [ + "com/bitfun/mobile/app/ui/theme/generated", + "com/bitfun/mobile/app/ui/preview/generated" + ] + } + }, + { + "id": "native-ios", + "label": "Native iOS", + "kind": "native-mobile", + "owner": "src/apps/mobile/design-system/tokens/mobile-tokens.json", + "root": "src/apps/mobile/ios/BitFun", + "audit": { + "engine": "native", + "platform": "ios", + "extensions": [".swift"], + "excludeFiles": [ + "Features/DesignSystem/GeneratedMobileDesignTokens.swift", + "Features/DesignSystem/GeneratedMobilePreviewScenarios.swift" + ] + } + }, + { + "id": "native-harmonyos", + "label": "Native HarmonyOS", + "kind": "native-mobile", + "owner": "src/apps/mobile/design-system/tokens/mobile-tokens.json", + "root": "src/apps/mobile/harmonyos/entry/src/main/ets", + "audit": { + "engine": "native", + "platform": "harmonyos", + "extensions": [".ets"], + "excludePaths": ["generated"] + } + }, + { + "id": "miniapp-coding-selfie", + "label": "Coding Selfie MiniApp", + "kind": "miniapp", + "owner": "MiniApp public appearance contract", + "root": "src/crates/contracts/product-domains/src/miniapp/builtin/assets/coding-selfie", + "audit": { + "engine": "miniapp", + "rawColorOwners": [ + { + "kind": "data-viz", + "file": "ui.js", + "startMarker": "const LANG_COLORS = [", + "endMarker": "];", + "reason": "Categorical language-series colors must remain distinguishable and are renderer data, not application chrome." + } + ] + } + }, + { + "id": "miniapp-divination", + "label": "Daily Divination MiniApp", + "kind": "miniapp", + "owner": "self-contained bespoke theme", + "root": "src/crates/contracts/product-domains/src/miniapp/builtin/assets/divination", + "audit": { + "engine": "miniapp", + "rawColorOwners": [ + { + "kind": "bespoke-theme", + "pathPrefixes": ["style.css", "ui.js"], + "reason": "The tarot scene is an intentionally self-contained illustrated light/dark theme whose palette is the product content." + } + ] + } + }, + { + "id": "miniapp-gomoku", + "label": "Gomoku MiniApp", + "kind": "miniapp", + "owner": "MiniApp public appearance contract", + "root": "src/crates/contracts/product-domains/src/miniapp/builtin/assets/gomoku", + "audit": { + "engine": "miniapp", + "rawColorOwners": [ + { + "kind": "game-renderer", + "file": "style.css", + "linePattern": "^\\s*--g-stone-(?:black|white)(?:-stroke)?\\s*:", + "reason": "Stone fills and contrast rims are game-renderer content and must not become reusable UI tokens." + } + ] + } + }, + { + "id": "miniapp-ppt-live", + "label": "PPT Live MiniApp", + "kind": "miniapp", + "owner": "MiniApp public appearance contract for editor chrome and slide-renderer ownership for authored content", + "root": "src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live", + "audit": { + "engine": "miniapp", + "excludePaths": ["dist"], + "rawColorOwners": [ + { + "kind": "slide-renderer", + "pathPrefixes": ["src", "test"], + "reason": "Slide markup, export fixtures, and presentation authoring palettes are user-content renderer data rather than MiniApp editor chrome." + } + ] + } + }, + { + "id": "miniapp-regex-playground", + "label": "Regex Playground MiniApp", + "kind": "miniapp", + "owner": "MiniApp public appearance contract", + "root": "src/crates/contracts/product-domains/src/miniapp/builtin/assets/regex-playground", + "audit": { + "engine": "miniapp" + } + }, + { + "id": "miniapp-git-graph", + "label": "Git Graph MiniApp", + "kind": "miniapp", + "owner": "MiniApp public appearance contract", + "root": "MiniApp/Demo/git-graph", + "audit": { + "engine": "miniapp", + "rawColorOwners": [ + { + "kind": "data-viz", + "files": ["source/styles/tokens.css", "source/style.css"], + "linePattern": "^\\s*--branch-[5-7]\\s*:", + "reason": "The final three branch-lane colors extend the host semantic set for categorical graph separation." + } + ], + "generatedBundles": [ + { + "output": "source/ui.js", + "inputs": [ + "source/ui/state.js", + "source/ui/appearance.js", + "source/ui/graph/layout.js", + "source/ui/graph/renderRowSvg.js", + "source/ui/services/gitClient.js", + "source/ui/components/contextMenu.js", + "source/ui/components/modal.js", + "source/ui/components/findWidget.js", + "source/ui/panels/remotePanel.js", + "source/ui/panels/detailPanel.js", + "source/ui/main.js", + "source/ui/bootstrap.js" + ] + }, + { + "output": "source/style.css", + "inputs": [ + "source/styles/tokens.css", + "source/styles/layout.css", + "source/styles/graph.css", + "source/styles/detail-panel.css", + "source/styles/overlay.css" + ] + } + ] + } + }, + { + "id": "miniapp-icon-design-system", + "label": "Icon Design System MiniApp", + "kind": "miniapp", + "owner": "MiniApp public appearance contract", + "root": "MiniApp/Demo/icon-design-system", + "audit": { + "engine": "miniapp" + } + } + ], + "mirrors": [ + { + "surfaceId": "miniapp-git-graph", + "path": "src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph" + }, + { + "surfaceId": "miniapp-icon-design-system", + "path": "src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-icon-design-system" + }, + { + "surfaceId": "miniapp-coding-selfie", + "path": "src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-coding-selfie" + }, + { + "surfaceId": "miniapp-divination", + "path": "src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-daily-divination" + }, + { + "surfaceId": "miniapp-gomoku", + "path": "src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-gomoku" + }, + { + "surfaceId": "miniapp-regex-playground", + "path": "src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-regex-playground" + } + ], + "generatedChecks": [ + { + "id": "desktop-appearance-projection", + "surfaceIds": ["web-ui", "desktop-bootstrap"], + "command": ["node", "scripts/generate-startup-appearance-bootstrap.mjs", "--check"] + }, + { + "id": "miniapp-appearance-projection", + "surfaceKinds": ["miniapp"], + "command": ["node", "scripts/generate-miniapp-appearance-contract.mjs", "--check"] + }, + { + "id": "native-mobile-token-projection", + "surfaceKinds": ["native-mobile"], + "surfaceIds": ["mobile-design-preview"], + "command": ["node", "scripts/mobile-ui-design-system.mjs", "--check"] + }, + { + "id": "native-mobile-preview-assets", + "surfaceKinds": ["native-mobile"], + "surfaceIds": ["mobile-design-preview"], + "command": ["node", "scripts/mobile-ui-preview.mjs", "--check"] + } + ], + "exclusions": [ + { + "id": "monaco-generated", + "path": "src/web-ui/public/monaco-editor", + "kind": "generated-third-party", + "owner": "Monaco package copy step", + "reason": "Vendored editor output is verified by the Monaco asset check and is not BitFun application UI source." + }, + { + "id": "relay-static", + "path": "src/apps/relay-server/static", + "kind": "static-operational-surface", + "owner": "Relay server", + "reason": "Self-contained relay operational pages do not load the product design-system runtime and are governed by their owning server surface." + }, + { + "id": "e2e-fixtures", + "path": "tests/e2e/fixtures", + "kind": "test-fixture", + "owner": "E2E tests", + "reason": "Fixture colors describe test input and are never shipped as product UI." + }, + { + "id": "diagnostic-report-html", + "path": "scripts/request-trace-tools/usage-dashboard.html", + "kind": "diagnostic-artifact", + "owner": "Request trace tooling", + "reason": "The standalone diagnostic report is not a product frontend and has an independent operational lifecycle." + }, + { + "id": "ppt-content-source", + "path": "src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/src", + "kind": "slide-renderer", + "owner": "PPT Live slide renderer", + "reason": "Presentation content and export palettes are renderer payloads, not editor chrome." + }, + { + "id": "ppt-content-tests", + "path": "src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/test", + "kind": "slide-renderer", + "owner": "PPT Live slide renderer tests", + "reason": "Expected slide markup colors test renderer fidelity rather than application chrome." + }, + { + "id": "ppt-generated-bundle", + "path": "src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/dist", + "kind": "generated-output", + "owner": "PPT Live build-bitfun.mjs", + "reason": "Bundled JavaScript is generated from the registered PPT source owner." + }, + { + "id": "android-template-icons", + "path": "src/apps/mobile/android/app/src/main/res/drawable", + "kind": "native-template-asset", + "owner": "Android resource layer", + "reason": "Monochrome vector templates are tinted by native semantic tokens at render time." + }, + { + "id": "ios-template-icons", + "path": "src/apps/mobile/ios/BitFun/Resources.xcassets", + "kind": "native-template-asset", + "owner": "iOS asset catalog", + "reason": "Template images and app metadata are tinted or consumed by the platform asset layer." + }, + { + "id": "harmony-template-media", + "path": "src/apps/mobile/harmonyos/entry/src/main/resources/base/media", + "kind": "native-template-asset", + "owner": "HarmonyOS resource layer", + "reason": "Template media is tinted by semantic ResourceColor values in the native UI." + }, + { + "id": "mobile-preview-generated", + "path": "src/apps/mobile/design-system/preview/generated", + "kind": "generated-output", + "owner": "scripts/mobile-ui-design-system.mjs", + "reason": "Preview data is generated from the native mobile token contract and checked for drift." + }, + { + "id": "desktop-bootstrap-generated", + "path": "src/apps/desktop/src/generated", + "kind": "generated-output", + "owner": "scripts/generate-startup-appearance-bootstrap.mjs", + "reason": "Desktop first-paint theme CSS and manifests are generated from canonical Appearance and theme sources." + }, + { + "id": "miniapp-appearance-generated", + "path": "src/crates/contracts/product-domains/src/miniapp/generated", + "kind": "generated-output", + "owner": "scripts/generate-miniapp-appearance-contract.mjs", + "reason": "MiniApp first-paint variables are generated from the public projection contract." + } + ] +} diff --git a/scripts/generate-miniapp-appearance-contract.mjs b/scripts/generate-miniapp-appearance-contract.mjs new file mode 100644 index 0000000000..6a2f3a397d --- /dev/null +++ b/scripts/generate-miniapp-appearance-contract.mjs @@ -0,0 +1,110 @@ +#!/usr/bin/env node + +import fs from 'node:fs'; +import path from 'node:path'; +import process from 'node:process'; +import { fileURLToPath, pathToFileURL } from 'node:url'; + +const repositoryRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const contractPath = path.join(repositoryRoot, 'src/shared/miniapp-appearance/contract.json'); +const outputPath = path.join( + repositoryRoot, + 'src/crates/contracts/product-domains/src/miniapp/generated/default_appearance_style.html', +); +const themeEntryPath = path.join(repositoryRoot, 'design-system/packages/theme-bitfun/dist/index.js'); +const systemEntryPath = path.join(repositoryRoot, 'design-system/packages/design-tokens/dist/index.js'); +const checkOnly = process.argv.includes('--check'); + +const contract = JSON.parse(fs.readFileSync(contractPath, 'utf8')); +const [{ themes, themeCssVariables }, { cssVariables: systemCssVariables, tokens: systemTokens }] = await Promise.all([ + import(pathToFileURL(themeEntryPath).href), + import(pathToFileURL(systemEntryPath).href), +]); + +const themeNamesByCssVariable = invertUnique(themeCssVariables, 'theme'); +const systemNamesByCssVariable = invertUnique(systemCssVariables, 'system'); +validateContract(contract); +const systemDeclarations = renderDeclarations('system'); +const darkDeclarations = renderDeclarations('theme', 'dark'); +const lightDeclarations = renderDeclarations('theme', 'light'); +const generated = [ + '', + '', +].join('\n'); + +const current = fs.existsSync(outputPath) ? normalize(fs.readFileSync(outputPath, 'utf8')) : null; +if (checkOnly) { + if (current !== normalize(generated)) { + console.error('[miniapp-appearance] Generated first-paint projection is stale. Run `pnpm run miniapp:appearance:generate`.'); + process.exit(1); + } + console.log('[miniapp-appearance] Contract and generated first-paint projection are in sync.'); +} else { + fs.mkdirSync(path.dirname(outputPath), { recursive: true }); + fs.writeFileSync(outputPath, generated, 'utf8'); + console.log(`[miniapp-appearance] Wrote ${relative(outputPath)}.`); +} + +function validateContract(value) { + if (value?.version !== 1 || !Array.isArray(value.variables) || value.variables.length === 0) { + throw new Error('Unsupported or empty MiniApp appearance contract.'); + } + const names = new Set(); + for (const variable of value.variables) { + if (!/^--bitfun-[a-z0-9-]+$/.test(variable.name ?? '')) { + throw new Error(`Invalid MiniApp appearance variable: ${String(variable.name)}.`); + } + if (names.has(variable.name)) throw new Error(`Duplicate MiniApp appearance variable: ${variable.name}.`); + names.add(variable.name); + if (!['theme', 'system'].includes(variable.kind)) { + throw new Error(`Invalid MiniApp appearance variable kind for ${variable.name}.`); + } + const owners = variable.kind === 'theme' ? themeNamesByCssVariable : systemNamesByCssVariable; + if (!owners.has(variable.source)) { + throw new Error(`${variable.name} references unknown canonical ${variable.kind} variable ${variable.source}.`); + } + } +} + +function invertUnique(values, label) { + const result = new Map(); + for (const [name, cssVariable] of Object.entries(values)) { + if (result.has(cssVariable)) throw new Error(`Duplicate canonical ${label} CSS variable ${cssVariable}.`); + result.set(cssVariable, name); + } + return result; +} + +function renderDeclarations(kind, mode) { + return contract.variables + .filter(variable => variable.kind === kind) + .map(variable => { + const canonicalName = (kind === 'theme' ? themeNamesByCssVariable : systemNamesByCssVariable).get(variable.source); + const value = kind === 'theme' ? themes[mode][canonicalName] : systemTokens[canonicalName]; + if (!['string', 'number'].includes(typeof value)) { + throw new Error(`Canonical value for ${variable.source} cannot be serialized into CSS.`); + } + return ` ${variable.name}: ${String(value)};`; + }) + .join('\n'); +} + +function normalize(value) { + return String(value).replace(/\r\n?/g, '\n'); +} + +function relative(value) { + return path.relative(repositoryRoot, value).split(path.sep).join('/'); +} diff --git a/scripts/generate-startup-appearance-bootstrap.mjs b/scripts/generate-startup-appearance-bootstrap.mjs index a9f89fb2f5..8d2c904bfd 100644 --- a/scripts/generate-startup-appearance-bootstrap.mjs +++ b/scripts/generate-startup-appearance-bootstrap.mjs @@ -1,6 +1,6 @@ import fs from 'node:fs'; import path from 'node:path'; -import { fileURLToPath } from 'node:url'; +import { fileURLToPath, pathToFileURL } from 'node:url'; import { createServer } from 'vite'; @@ -16,12 +16,42 @@ const appearancePromptSnapshotOutputPath = path.join( repoRoot, 'src/crates/assembly/core/src/agentic/tools/implementations/generated/appearance_prompt_snapshots.json', ); +const desktopBootstrapThemeOutputPath = path.join( + repoRoot, + 'src/apps/desktop/src/generated/bootstrap_theme.css', +); +const themePackageEntryPath = path.join( + repoRoot, + 'design-system/packages/theme-bitfun/dist/index.js', +); const checkOnly = process.argv.includes('--check'); function normalizeGeneratedText(content) { return String(content).replace(/\r\n?/g, '\n'); } +function createDesktopBootstrapThemeCss(themeValues, cssVariables) { + const declarations = Object.entries(themeValues) + .map(([name, value]) => { + const cssVariable = cssVariables[name]; + if (!cssVariable) { + throw new Error(`Missing CSS variable mapping for bootstrap theme token ${name}.`); + } + return ` ${cssVariable}: ${String(value)};`; + }) + .join('\n'); + + return [ + '/* Generated by scripts/generate-startup-appearance-bootstrap.mjs. Do not edit. */', + '@layer bf.tokens.theme {', + ' :where([data-bf-design-system-root][data-color-scheme="dark"]) {', + declarations, + ' }', + '}', + '', + ].join('\n'); +} + const server = await createServer({ root: webUiRoot, logLevel: 'error', @@ -38,10 +68,12 @@ try { { builtinAppearancePalettes }, { createStartupAppearanceBootstrapManifest }, { createAppearancePromptSnapshotManifest }, + { themes, themeCssVariables }, ] = await Promise.all([ server.ssrLoadModule('/src/infrastructure/appearance/builtins/palettes.ts'), server.ssrLoadModule('/src/infrastructure/appearance/builtins/startupAppearanceBootstrap.ts'), server.ssrLoadModule('/src/infrastructure/appearance/builtins/appearancePromptSnapshots.ts'), + import(pathToFileURL(themePackageEntryPath).href), ]); const generatedFiles = [ @@ -55,6 +87,11 @@ try { outputPath: appearancePromptSnapshotOutputPath, content: `${JSON.stringify(createAppearancePromptSnapshotManifest(builtinAppearancePalettes), null, 2)}\n`, }, + { + label: 'Desktop bootstrap theme projection', + outputPath: desktopBootstrapThemeOutputPath, + content: createDesktopBootstrapThemeCss(themes.dark, themeCssVariables), + }, ]; for (const generatedFile of generatedFiles) { diff --git a/scripts/mobile-ui-design-system.mjs b/scripts/mobile-ui-design-system.mjs index 5b05fe974e..2f0504138c 100644 --- a/scripts/mobile-ui-design-system.mjs +++ b/scripts/mobile-ui-design-system.mjs @@ -102,6 +102,20 @@ function validateContract(tokenContract, componentContract, scenarioContract) { for (const [name, value] of Object.entries(tokenContract.geometry ?? {})) { if (!Number.isFinite(value) || value <= 0) throw new Error(`Invalid geometry token ${name}.`); } + const availableTokenNames = new Set([ + ...Object.keys(tokenContract.colors ?? {}), + ...Object.keys(tokenContract.typography ?? {}), + ...Object.keys(tokenContract.geometry ?? {}), + ...Object.keys(tokenContract.breakpoints ?? {}), + ...Object.keys(tokenContract.motion ?? {}), + ]); + for (const [componentName, component] of Object.entries(componentContract.components ?? {})) { + for (const tokenName of component.tokens ?? []) { + if (!availableTokenNames.has(tokenName)) { + throw new Error(`Component ${componentName} references unknown mobile token ${tokenName}.`); + } + } + } const ids = new Set(); for (const scenario of scenarioContract.scenarios ?? []) { if (!scenario.id || ids.has(scenario.id)) throw new Error(`Invalid or duplicate preview scenario id: ${scenario.id}.`); @@ -118,13 +132,16 @@ function renderHarmonyColors(colors, appearance) { } function renderHarmonyTokens(contract) { + const colors = Object.entries(contract.colors) + .map(([name, pair]) => ` static readonly ${camel(name)}: MobileColorPair = new MobileColorPair(${quoted(pair.light)}, ${quoted(pair.dark)});`) + .join('\n'); const typography = Object.entries(contract.typography) .map(([name, token]) => ` static readonly ${camel(name)}: MobileTypographyToken = new MobileTypographyToken(${token.size}, ${token.lineHeight}, ${token.weight});`) .join('\n'); const geometry = renderNumberProperties(contract.geometry, ' static readonly'); const breakpoints = renderNumberProperties(contract.breakpoints, ' static readonly'); const motion = renderNumberProperties(contract.motion, ' static readonly'); - return `// Generated by scripts/mobile-ui-design-system.mjs. Do not edit.\n\nexport class MobileTypographyToken {\n readonly size: number;\n readonly lineHeight: number;\n readonly weight: number;\n\n constructor(size: number, lineHeight: number, weight: number) {\n this.size = size;\n this.lineHeight = lineHeight;\n this.weight = weight;\n }\n}\n\nexport class MobileDesignTypography {\n${typography}\n}\n\nexport class MobileDesignGeometry {\n${geometry}\n}\n\nexport class MobileDesignBreakpoints {\n${breakpoints}\n}\n\nexport class MobileDesignMotion {\n${motion}\n}\n`; + return `// Generated by scripts/mobile-ui-design-system.mjs. Do not edit.\n\nexport class MobileColorPair {\n readonly light: string;\n readonly dark: string;\n\n constructor(light: string, dark: string) {\n this.light = light;\n this.dark = dark;\n }\n}\n\nexport class MobileDesignColors {\n${colors}\n}\n\nexport class MobileTypographyToken {\n readonly size: number;\n readonly lineHeight: number;\n readonly weight: number;\n\n constructor(size: number, lineHeight: number, weight: number) {\n this.size = size;\n this.lineHeight = lineHeight;\n this.weight = weight;\n }\n}\n\nexport class MobileDesignTypography {\n${typography}\n}\n\nexport class MobileDesignGeometry {\n${geometry}\n}\n\nexport class MobileDesignBreakpoints {\n${breakpoints}\n}\n\nexport class MobileDesignMotion {\n${motion}\n}\n`; } function renderHarmonyScenarios(contract) { diff --git a/scripts/mobile-ui-preview.mjs b/scripts/mobile-ui-preview.mjs index feb89ce259..78e8a0a3c0 100644 --- a/scripts/mobile-ui-preview.mjs +++ b/scripts/mobile-ui-preview.mjs @@ -2,13 +2,17 @@ import { createReadStream, existsSync, readFileSync } from 'node:fs'; import { createServer } from 'node:http'; -import { extname, join, normalize, resolve } from 'node:path'; +import { extname, join, normalize, resolve, sep } from 'node:path'; import { fileURLToPath } from 'node:url'; import { dirname } from 'node:path'; import { spawn } from 'node:child_process'; const ROOT = resolve(dirname(fileURLToPath(import.meta.url)), '..'); const PREVIEW_ROOT = join(ROOT, 'src', 'apps', 'mobile', 'design-system', 'preview'); +const SHARED_ASSETS = new Map([ + ['/design-system-tokens.css', join(ROOT, 'design-system', 'packages', 'design-tokens', 'dist', 'tokens.css')], + ['/design-system-theme.css', join(ROOT, 'design-system', 'packages', 'theme-bitfun', 'dist', 'themes.css')], +]); const requiredFiles = ['index.html', 'preview.css', 'preview.js', 'generated/mobile-design-data.js']; for (const file of requiredFiles) { @@ -18,6 +22,12 @@ for (const file of requiredFiles) { process.exit(1); } } +for (const [requestPath, assetPath] of SHARED_ASSETS) { + if (!existsSync(assetPath) || readFileSync(assetPath, 'utf8').trim().length === 0) { + console.error(`[mobile-ui-preview] Missing canonical design-system asset for ${requestPath}.`); + process.exit(1); + } +} if (process.argv.includes('--check')) { console.log('[mobile-ui-preview] Preview assets are present.'); @@ -30,9 +40,16 @@ const host = '127.0.0.1'; const url = `http://${host}:${port}`; const server = createServer((request, response) => { const requestPath = decodeURIComponent((request.url ?? '/').split('?')[0]); + const sharedAsset = SHARED_ASSETS.get(requestPath); + if (sharedAsset) { + response.setHeader('X-BitFun-Mobile-Preview', '1'); + response.setHeader('Content-Type', contentType(extname(sharedAsset))); + createReadStream(sharedAsset).pipe(response); + return; + } const relativePath = requestPath === '/' ? 'index.html' : requestPath.replace(/^\/+/, ''); const path = normalize(join(PREVIEW_ROOT, relativePath)); - if (!path.startsWith(`${PREVIEW_ROOT}/`) && path !== join(PREVIEW_ROOT, 'index.html')) { + if (!path.startsWith(`${PREVIEW_ROOT}${sep}`) && path !== join(PREVIEW_ROOT, 'index.html')) { response.writeHead(403).end('Forbidden'); return; } diff --git a/scripts/theme-color-governance-baseline.design-lab.json b/scripts/theme-color-governance-baseline.design-lab.json new file mode 100644 index 0000000000..9e639c6202 --- /dev/null +++ b/scripts/theme-color-governance-baseline.design-lab.json @@ -0,0 +1,47 @@ +{ + "version": 1, + "description": "Design Lab canonical color governance baseline. Ordinary UI colors, compatibility aliases, fallbacks, and unresolved variables stay at zero.", + "budgets": { + "fallbackOccurrences": { "max": 0 }, + "fallbackUniqueTokens": { "max": 0 }, + "fallbackContracts.uncontractedUnique": { "max": 0 }, + "fallbackContracts.staleRegisteredUnique": { "max": 0 }, + "compatibilityAliases.usedUnique": { "max": 0 }, + "compatibilityAliases.occurrences": { "max": 0 }, + "compatibilityAliases.familyUsedUnique": { "max": 0 }, + "compatibilityAliases.familyOccurrences": { "max": 0 }, + "compatibilityAliases.missingCanonicalUnique": { "max": 0 }, + "surfaceTokenRenames.activeUnique": { "max": 0 }, + "surfaceTokenRenames.activeOccurrences": { "max": 0 }, + "surfaceTokenRenames.missingCanonicalUnique": { "max": 0 }, + "colorDomainContracts.missingRegisteredUnique": { "max": 0 }, + "colorDomainContracts.staleRegisteredUnique": { "max": 0 }, + "colorDomainContracts.activeUncontractedUnique": { "max": 0 }, + "colorScopes.appUi.occurrences": { "max": 0 }, + "colorScopes.appUi.uniqueColors": { "max": 0 }, + "cssVarDefinitions.unresolvedUnique": { "max": 0 }, + "cssVarDefinitions.unresolvedRequiredUnique": { "max": 0 }, + "cssVarDefinitions.fallbackOnlyUnique": { "max": 0 }, + "cssVarDefinitions.runtimeOnlyRequiredContractUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCrossFileUnique": { "max": 0 }, + "cssVarDefinitions.nonContractDynamicInputUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCssPrivateUnique": { "max": 0 }, + "cssVarDefinitions.unregisteredDynamicFamilyUnique": { "max": 0 }, + "cssVarDefinitions.dynamicFamilyUnexportedUnique": { "max": 0 }, + "cssVarDefinitions.staleRegisteredDynamicFamilyUnique": { "max": 0 }, + "tokenAliasLiterals.occurrences": { "max": 0 }, + "tokenAliasLiterals.uniqueColors": { "max": 0 }, + "nearPairs.indistinguishableTotal": { "max": 0 }, + "nearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.nearTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.nearTotal": { "max": 0 }, + "colorDomainScopes.appUi.occurrences": { "max": 0 }, + "colorDomainScopes.appUi.uniqueColors": { "max": 0 }, + "colorDomainScopes.assetMetadata.occurrences": { "max": 0 }, + "colorDomainScopes.assetMetadata.uniqueColors": { "max": 0 } + } +} diff --git a/scripts/theme-color-governance-baseline.design-system-ui.json b/scripts/theme-color-governance-baseline.design-system-ui.json new file mode 100644 index 0000000000..ac9e57bffe --- /dev/null +++ b/scripts/theme-color-governance-baseline.design-system-ui.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "description": "Public @bitfun/ui color governance baseline. Component CSS and mask assets consume only canonical peer-owned variables and remain free of literals and fallbacks.", + "budgets": { + "fallbackOccurrences": { "max": 0 }, + "fallbackUniqueTokens": { "max": 0 }, + "colorScopes.appUi.occurrences": { "max": 0 }, + "colorScopes.appUi.uniqueColors": { "max": 0 }, + "colorDomainScopes.assetMetadata.occurrences": { "max": 0 }, + "colorDomainScopes.assetMetadata.uniqueColors": { "max": 0 }, + "cssVarDefinitions.unresolvedUnique": { "max": 0 }, + "cssVarDefinitions.unresolvedRequiredUnique": { "max": 0 }, + "cssVarDefinitions.fallbackOnlyUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCrossFileUnique": { "max": 0 }, + "cssVarDefinitions.nonContractDynamicInputUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCssPrivateUnique": { "max": 0 }, + "tokenAliasLiterals.occurrences": { "max": 0 }, + "tokenAliasLiterals.uniqueColors": { "max": 0 }, + "nearPairs.indistinguishableTotal": { "max": 0 }, + "nearPairs.nearTotal": { "max": 0 } + } +} diff --git a/scripts/theme-color-governance-baseline.installer.json b/scripts/theme-color-governance-baseline.installer.json index a8bf9f8c5e..b69327963d 100644 --- a/scripts/theme-color-governance-baseline.installer.json +++ b/scripts/theme-color-governance-baseline.installer.json @@ -1,117 +1,53 @@ { "version": 1, - "description": "Baseline for installer theme color governance. Lower values when debt is removed; do not raise without a documented review reason.", + "description": "Installer canonical color governance baseline. Ordinary UI consumes canonical variables while explicit installable theme presets remain the only palette owner.", "budgets": { - "fallbackOccurrences": { - "max": 0 - }, - "fallbackUniqueTokens": { - "max": 0 - }, - "fallbackContracts.uncontractedUnique": { - "max": 0 - }, - "compatibilityAliases.usedUnique": { - "max": 0 - }, - "compatibilityAliases.occurrences": { - "max": 0 - }, - "compatibilityAliases.familyUsedUnique": { - "max": 0 - }, - "compatibilityAliases.familyOccurrences": { - "max": 0 - }, - "compatibilityAliases.missingCanonicalUnique": { - "max": 0 - }, - "surfaceTokenRenames.activeUnique": { - "max": 0 - }, - "surfaceTokenRenames.activeOccurrences": { - "max": 0 - }, - "surfaceTokenRenames.missingCanonicalUnique": { - "max": 0 - }, - "colorDomainContracts.missingRegisteredUnique": { - "max": 0 - }, - "colorDomainContracts.staleRegisteredUnique": { - "max": 0 - }, - "colorDomainContracts.activeUncontractedUnique": { - "max": 0 - }, - "colorScopes.appUi.occurrences": { - "max": 0 - }, - "colorScopes.appUi.uniqueColors": { - "max": 0 - }, - "cssVarDefinitions.unresolvedRequiredUnique": { - "max": 0 - }, - "cssVarDefinitions.fallbackOnlyUnique": { - "max": 0 - }, - "cssVarDefinitions.nonContractCrossFileUnique": { - "max": 0 - }, - "cssVarDefinitions.nonContractDynamicInputUnique": { - "max": 0 - }, - "cssVarDefinitions.nonContractCssPrivateUnique": { - "max": 0 - }, - "cssVarDefinitions.unregisteredDynamicFamilyUnique": { - "max": 0 - }, - "tokenAliasLiterals.occurrences": { - "max": 0 - }, - "nearPairs.indistinguishableTotal": { - "max": 0 - }, - "nearPairs.nearTotal": { - "max": 0 - }, - "colorDomainNearPairs.themePreset.indistinguishableTotal": { - "max": 0 - }, - "colorDomainNearPairs.themePreset.nearTotal": { - "max": 3 - }, - "colorDomainNearPairs.tokenContract.indistinguishableTotal": { - "max": 0 - }, - "colorDomainNearPairs.tokenContract.nearTotal": { - "max": 0 - }, - "colorDomainNearPairs.appUi.indistinguishableTotal": { - "max": 0 - }, - "colorDomainNearPairs.appUi.nearTotal": { - "max": 0 - }, - "colorDomainScopes.themePreset.occurrences": { - "max": 47 - }, - "colorDomainScopes.themePreset.uniqueColors": { - "max": 46 - }, - "colorDomainScopes.tokenContract.occurrences": { - "max": 14 - }, - "colorDomainScopes.tokenContract.uniqueColors": { - "max": 12 - }, - "colorDomainScopes.appUi.occurrences": { - "max": 0 - }, - "colorDomainScopes.appUi.uniqueColors": { - "max": 0 - } + "fallbackOccurrences": { "max": 0 }, + "fallbackUniqueTokens": { "max": 0 }, + "fallbackContracts.uncontractedUnique": { "max": 0 }, + "fallbackContracts.staleRegisteredUnique": { "max": 0 }, + "compatibilityAliases.usedUnique": { "max": 0 }, + "compatibilityAliases.occurrences": { "max": 0 }, + "compatibilityAliases.familyUsedUnique": { "max": 0 }, + "compatibilityAliases.familyOccurrences": { "max": 0 }, + "compatibilityAliases.missingCanonicalUnique": { "max": 0 }, + "surfaceTokenRenames.activeUnique": { "max": 0 }, + "surfaceTokenRenames.activeOccurrences": { "max": 0 }, + "surfaceTokenRenames.missingCanonicalUnique": { "max": 0 }, + "colorDomainContracts.missingRegisteredUnique": { "max": 0 }, + "colorDomainContracts.staleRegisteredUnique": { "max": 0 }, + "colorDomainContracts.activeUncontractedUnique": { "max": 0 }, + "colorScopes.appUi.occurrences": { "max": 0 }, + "colorScopes.appUi.uniqueColors": { "max": 0 }, + "cssVarDefinitions.unresolvedUnique": { "max": 0 }, + "cssVarDefinitions.unresolvedRequiredUnique": { "max": 0 }, + "cssVarDefinitions.fallbackOnlyUnique": { "max": 0 }, + "cssVarDefinitions.runtimeOnlyRequiredContractUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCrossFileUnique": { "max": 0 }, + "cssVarDefinitions.nonContractDynamicInputUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCssPrivateUnique": { "max": 0 }, + "cssVarDefinitions.unregisteredDynamicFamilyUnique": { "max": 0 }, + "cssVarDefinitions.dynamicFamilyUnexportedUnique": { "max": 0 }, + "cssVarDefinitions.staleRegisteredDynamicFamilyUnique": { "max": 0 }, + "tokenAliasLiterals.occurrences": { "max": 0 }, + "tokenAliasLiterals.uniqueColors": { "max": 0 }, + "nearPairs.indistinguishableTotal": { "max": 0 }, + "nearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.nearTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.nearTotal": { "max": 0 }, + "colorDomainScopes.appUi.occurrences": { "max": 0 }, + "colorDomainScopes.appUi.uniqueColors": { "max": 0 }, + "colorDomainNearPairs.themePreset.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.themePreset.nearTotal": { "max": 0 }, + "colorDomainScopes.themePreset.occurrences": { "max": 29 }, + "colorDomainScopes.themePreset.uniqueColors": { "max": 29 }, + "colorDomainScopes.tokenContract.occurrences": { "max": 0 }, + "colorDomainScopes.tokenContract.uniqueColors": { "max": 0 }, + "colorDomainScopes.assetMetadata.occurrences": { "max": 0 }, + "colorDomainScopes.assetMetadata.uniqueColors": { "max": 0 } } } diff --git a/scripts/theme-color-governance-baseline.json b/scripts/theme-color-governance-baseline.json index 42b56789b2..767fb27fac 100644 --- a/scripts/theme-color-governance-baseline.json +++ b/scripts/theme-color-governance-baseline.json @@ -42,7 +42,7 @@ "max": 0 }, "surfaceTokenRenames.registeredUnique": { - "max": 2 + "max": 0 }, "surfaceTokenRenames.activeUnique": { "max": 0 @@ -53,11 +53,11 @@ "surfaceTokenRenames.missingCanonicalUnique": { "max": 0 }, - "generatedWidgetPayload.varUnique": { - "max": 54 + "generatedWidgetPayload.missingCanonicalThemeUnique": { + "max": 0 }, - "generatedWidgetPayload.occurrences": { - "max": 54 + "generatedWidgetPayload.nonCanonicalUnique": { + "max": 0 }, "generatedWidgetPayload.undefinedUnique": { "max": 0 @@ -87,7 +87,7 @@ "max": 0 }, "colorDomainContracts.registeredUnique": { - "max": 14 + "max": 15 }, "colorDomainContracts.missingRegisteredUnique": { "max": 0 @@ -105,10 +105,10 @@ "max": 0 }, "colorScopes.token.occurrences": { - "max": 13 + "max": 0 }, "colorScopes.token.uniqueColors": { - "max": 10 + "max": 0 }, "colorScopes.exception.uniqueColors": { "max": 0 @@ -171,7 +171,7 @@ "max": 0 }, "colorDomainNearPairs.nearTotal": { - "max": 6 + "max": 5 }, "colorDomainNearPairs.themePreset.indistinguishableTotal": { "max": 0 @@ -251,6 +251,12 @@ "colorDomainNearPairs.appUi.nearTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.indistinguishableTotal": { + "max": 0 + }, + "colorDomainNearPairs.assetMetadata.nearTotal": { + "max": 0 + }, "colorDomainScopes.themePreset.occurrences": { "max": 130 }, @@ -261,10 +267,10 @@ "max": 0 }, "colorDomainScopes.tokenContract.occurrences": { - "max": 13 + "max": 0 }, "colorDomainScopes.tokenContract.uniqueColors": { - "max": 10 + "max": 0 }, "colorDomainScopes.generatedWidget.occurrences": { "max": 0 @@ -305,6 +311,9 @@ "colorDomainScopes.appUi.uniqueColors": { "max": 0 }, + "colorDomainScopes.assetMetadata.uniqueColors": { + "max": 7 + }, "colorDomainScopes.mermaid.occurrences": { "max": 0 }, @@ -315,7 +324,7 @@ "max": 0 }, "colorDomainNearPairs.appearanceProjection.nearTotal": { - "max": 3 + "max": 2 }, "colorDomainNearPairs.appearanceDomain.indistinguishableTotal": { "max": 0 @@ -324,10 +333,10 @@ "max": 0 }, "colorDomainScopes.appearanceProjection.occurrences": { - "max": 124 + "max": 93 }, "colorDomainScopes.appearanceProjection.uniqueColors": { - "max": 81 + "max": 61 }, "colorDomainScopes.appearanceDomain.occurrences": { "max": 0 diff --git a/scripts/theme-color-governance-baseline.miniapp-market.json b/scripts/theme-color-governance-baseline.miniapp-market.json new file mode 100644 index 0000000000..f106c7012d --- /dev/null +++ b/scripts/theme-color-governance-baseline.miniapp-market.json @@ -0,0 +1,47 @@ +{ + "version": 1, + "description": "Mini App Market canonical color governance baseline. Ordinary UI colors, compatibility aliases, fallbacks, and unresolved variables stay at zero.", + "budgets": { + "fallbackOccurrences": { "max": 0 }, + "fallbackUniqueTokens": { "max": 0 }, + "fallbackContracts.uncontractedUnique": { "max": 0 }, + "fallbackContracts.staleRegisteredUnique": { "max": 0 }, + "compatibilityAliases.usedUnique": { "max": 0 }, + "compatibilityAliases.occurrences": { "max": 0 }, + "compatibilityAliases.familyUsedUnique": { "max": 0 }, + "compatibilityAliases.familyOccurrences": { "max": 0 }, + "compatibilityAliases.missingCanonicalUnique": { "max": 0 }, + "surfaceTokenRenames.activeUnique": { "max": 0 }, + "surfaceTokenRenames.activeOccurrences": { "max": 0 }, + "surfaceTokenRenames.missingCanonicalUnique": { "max": 0 }, + "colorDomainContracts.missingRegisteredUnique": { "max": 0 }, + "colorDomainContracts.staleRegisteredUnique": { "max": 0 }, + "colorDomainContracts.activeUncontractedUnique": { "max": 0 }, + "colorScopes.appUi.occurrences": { "max": 0 }, + "colorScopes.appUi.uniqueColors": { "max": 0 }, + "cssVarDefinitions.unresolvedUnique": { "max": 0 }, + "cssVarDefinitions.unresolvedRequiredUnique": { "max": 0 }, + "cssVarDefinitions.fallbackOnlyUnique": { "max": 0 }, + "cssVarDefinitions.runtimeOnlyRequiredContractUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCrossFileUnique": { "max": 0 }, + "cssVarDefinitions.nonContractDynamicInputUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCssPrivateUnique": { "max": 0 }, + "cssVarDefinitions.unregisteredDynamicFamilyUnique": { "max": 0 }, + "cssVarDefinitions.dynamicFamilyUnexportedUnique": { "max": 0 }, + "cssVarDefinitions.staleRegisteredDynamicFamilyUnique": { "max": 0 }, + "tokenAliasLiterals.occurrences": { "max": 0 }, + "tokenAliasLiterals.uniqueColors": { "max": 0 }, + "nearPairs.indistinguishableTotal": { "max": 0 }, + "nearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.nearTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.nearTotal": { "max": 0 }, + "colorDomainScopes.appUi.occurrences": { "max": 0 }, + "colorDomainScopes.appUi.uniqueColors": { "max": 0 }, + "colorDomainScopes.assetMetadata.occurrences": { "max": 7 }, + "colorDomainScopes.assetMetadata.uniqueColors": { "max": 5 } + } +} diff --git a/scripts/theme-color-governance-baseline.mobile-web.json b/scripts/theme-color-governance-baseline.mobile-web.json index 7ae6e45364..091a07aada 100644 --- a/scripts/theme-color-governance-baseline.mobile-web.json +++ b/scripts/theme-color-governance-baseline.mobile-web.json @@ -1,105 +1,51 @@ { "version": 1, - "description": "Baseline for Mobile Web theme color governance. Lower values when debt is removed; do not raise without a documented review reason.", + "description": "Mobile Web canonical color governance baseline. The former local light/dark palettes and numbered accent ramps are retired.", "budgets": { - "fallbackOccurrences": { - "max": 0 - }, - "fallbackUniqueTokens": { - "max": 0 - }, - "fallbackContracts.uncontractedUnique": { - "max": 0 - }, - "compatibilityAliases.usedUnique": { - "max": 0 - }, - "compatibilityAliases.occurrences": { - "max": 0 - }, - "compatibilityAliases.familyUsedUnique": { - "max": 0 - }, - "compatibilityAliases.familyOccurrences": { - "max": 0 - }, - "compatibilityAliases.missingCanonicalUnique": { - "max": 0 - }, - "surfaceTokenRenames.activeUnique": { - "max": 0 - }, - "surfaceTokenRenames.activeOccurrences": { - "max": 0 - }, - "surfaceTokenRenames.missingCanonicalUnique": { - "max": 0 - }, - "colorDomainContracts.missingRegisteredUnique": { - "max": 0 - }, - "colorDomainContracts.staleRegisteredUnique": { - "max": 0 - }, - "colorDomainContracts.activeUncontractedUnique": { - "max": 0 - }, - "colorScopes.appUi.occurrences": { - "max": 0 - }, - "colorScopes.appUi.uniqueColors": { - "max": 0 - }, - "cssVarDefinitions.unresolvedRequiredUnique": { - "max": 0 - }, - "cssVarDefinitions.fallbackOnlyUnique": { - "max": 0 - }, - "cssVarDefinitions.nonContractCrossFileUnique": { - "max": 0 - }, - "cssVarDefinitions.nonContractDynamicInputUnique": { - "max": 0 - }, - "cssVarDefinitions.nonContractCssPrivateUnique": { - "max": 0 - }, - "cssVarDefinitions.unregisteredDynamicFamilyUnique": { - "max": 0 - }, - "tokenAliasLiterals.occurrences": { - "max": 0 - }, - "nearPairs.indistinguishableTotal": { - "max": 0 - }, - "nearPairs.nearTotal": { - "max": 0 - }, - "colorDomainNearPairs.themePreset.indistinguishableTotal": { - "max": 0 - }, - "colorDomainNearPairs.themePreset.nearTotal": { - "max": 0 - }, - "colorDomainNearPairs.appUi.indistinguishableTotal": { - "max": 0 - }, - "colorDomainNearPairs.appUi.nearTotal": { - "max": 0 - }, - "colorDomainScopes.themePreset.occurrences": { - "max": 33 - }, - "colorDomainScopes.themePreset.uniqueColors": { - "max": 29 - }, - "colorDomainScopes.appUi.occurrences": { - "max": 0 - }, - "colorDomainScopes.appUi.uniqueColors": { - "max": 0 - } + "fallbackOccurrences": { "max": 0 }, + "fallbackUniqueTokens": { "max": 0 }, + "fallbackContracts.uncontractedUnique": { "max": 0 }, + "fallbackContracts.staleRegisteredUnique": { "max": 0 }, + "compatibilityAliases.usedUnique": { "max": 0 }, + "compatibilityAliases.occurrences": { "max": 0 }, + "compatibilityAliases.familyUsedUnique": { "max": 0 }, + "compatibilityAliases.familyOccurrences": { "max": 0 }, + "compatibilityAliases.missingCanonicalUnique": { "max": 0 }, + "surfaceTokenRenames.activeUnique": { "max": 0 }, + "surfaceTokenRenames.activeOccurrences": { "max": 0 }, + "surfaceTokenRenames.missingCanonicalUnique": { "max": 0 }, + "colorDomainContracts.missingRegisteredUnique": { "max": 0 }, + "colorDomainContracts.staleRegisteredUnique": { "max": 0 }, + "colorDomainContracts.activeUncontractedUnique": { "max": 0 }, + "colorScopes.appUi.occurrences": { "max": 0 }, + "colorScopes.appUi.uniqueColors": { "max": 0 }, + "cssVarDefinitions.unresolvedUnique": { "max": 0 }, + "cssVarDefinitions.unresolvedRequiredUnique": { "max": 0 }, + "cssVarDefinitions.fallbackOnlyUnique": { "max": 0 }, + "cssVarDefinitions.runtimeOnlyRequiredContractUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCrossFileUnique": { "max": 0 }, + "cssVarDefinitions.nonContractDynamicInputUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCssPrivateUnique": { "max": 0 }, + "cssVarDefinitions.unregisteredDynamicFamilyUnique": { "max": 0 }, + "cssVarDefinitions.dynamicFamilyUnexportedUnique": { "max": 0 }, + "cssVarDefinitions.staleRegisteredDynamicFamilyUnique": { "max": 0 }, + "tokenAliasLiterals.occurrences": { "max": 0 }, + "tokenAliasLiterals.uniqueColors": { "max": 0 }, + "nearPairs.indistinguishableTotal": { "max": 0 }, + "nearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.nearTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.nearTotal": { "max": 0 }, + "colorDomainScopes.appUi.occurrences": { "max": 0 }, + "colorDomainScopes.appUi.uniqueColors": { "max": 0 }, + "colorDomainNearPairs.themePreset.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.themePreset.nearTotal": { "max": 0 }, + "colorDomainScopes.themePreset.occurrences": { "max": 0 }, + "colorDomainScopes.themePreset.uniqueColors": { "max": 0 }, + "colorDomainScopes.assetMetadata.occurrences": { "max": 4 }, + "colorDomainScopes.assetMetadata.uniqueColors": { "max": 1 } } } diff --git a/scripts/theme-color-governance-baseline.skin-market.json b/scripts/theme-color-governance-baseline.skin-market.json new file mode 100644 index 0000000000..78f5e52d25 --- /dev/null +++ b/scripts/theme-color-governance-baseline.skin-market.json @@ -0,0 +1,47 @@ +{ + "version": 1, + "description": "Skin Market canonical color governance baseline. Ordinary UI colors, compatibility aliases, fallbacks, and unresolved variables stay at zero.", + "budgets": { + "fallbackOccurrences": { "max": 0 }, + "fallbackUniqueTokens": { "max": 0 }, + "fallbackContracts.uncontractedUnique": { "max": 0 }, + "fallbackContracts.staleRegisteredUnique": { "max": 0 }, + "compatibilityAliases.usedUnique": { "max": 0 }, + "compatibilityAliases.occurrences": { "max": 0 }, + "compatibilityAliases.familyUsedUnique": { "max": 0 }, + "compatibilityAliases.familyOccurrences": { "max": 0 }, + "compatibilityAliases.missingCanonicalUnique": { "max": 0 }, + "surfaceTokenRenames.activeUnique": { "max": 0 }, + "surfaceTokenRenames.activeOccurrences": { "max": 0 }, + "surfaceTokenRenames.missingCanonicalUnique": { "max": 0 }, + "colorDomainContracts.missingRegisteredUnique": { "max": 0 }, + "colorDomainContracts.staleRegisteredUnique": { "max": 0 }, + "colorDomainContracts.activeUncontractedUnique": { "max": 0 }, + "colorScopes.appUi.occurrences": { "max": 0 }, + "colorScopes.appUi.uniqueColors": { "max": 0 }, + "cssVarDefinitions.unresolvedUnique": { "max": 0 }, + "cssVarDefinitions.unresolvedRequiredUnique": { "max": 0 }, + "cssVarDefinitions.fallbackOnlyUnique": { "max": 0 }, + "cssVarDefinitions.runtimeOnlyRequiredContractUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCrossFileUnique": { "max": 0 }, + "cssVarDefinitions.nonContractDynamicInputUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCssPrivateUnique": { "max": 0 }, + "cssVarDefinitions.unregisteredDynamicFamilyUnique": { "max": 0 }, + "cssVarDefinitions.dynamicFamilyUnexportedUnique": { "max": 0 }, + "cssVarDefinitions.staleRegisteredDynamicFamilyUnique": { "max": 0 }, + "tokenAliasLiterals.occurrences": { "max": 0 }, + "tokenAliasLiterals.uniqueColors": { "max": 0 }, + "nearPairs.indistinguishableTotal": { "max": 0 }, + "nearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.nearTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.nearTotal": { "max": 0 }, + "colorDomainScopes.appUi.occurrences": { "max": 0 }, + "colorDomainScopes.appUi.uniqueColors": { "max": 0 }, + "colorDomainScopes.assetMetadata.occurrences": { "max": 6 }, + "colorDomainScopes.assetMetadata.uniqueColors": { "max": 5 } + } +} diff --git a/scripts/theme-color-governance-baseline.website.json b/scripts/theme-color-governance-baseline.website.json new file mode 100644 index 0000000000..e43a81e383 --- /dev/null +++ b/scripts/theme-color-governance-baseline.website.json @@ -0,0 +1,47 @@ +{ + "version": 1, + "description": "Website canonical color governance baseline. Ordinary UI colors, compatibility aliases, fallbacks, and unresolved variables stay at zero.", + "budgets": { + "fallbackOccurrences": { "max": 0 }, + "fallbackUniqueTokens": { "max": 0 }, + "fallbackContracts.uncontractedUnique": { "max": 0 }, + "fallbackContracts.staleRegisteredUnique": { "max": 0 }, + "compatibilityAliases.usedUnique": { "max": 0 }, + "compatibilityAliases.occurrences": { "max": 0 }, + "compatibilityAliases.familyUsedUnique": { "max": 0 }, + "compatibilityAliases.familyOccurrences": { "max": 0 }, + "compatibilityAliases.missingCanonicalUnique": { "max": 0 }, + "surfaceTokenRenames.activeUnique": { "max": 0 }, + "surfaceTokenRenames.activeOccurrences": { "max": 0 }, + "surfaceTokenRenames.missingCanonicalUnique": { "max": 0 }, + "colorDomainContracts.missingRegisteredUnique": { "max": 0 }, + "colorDomainContracts.staleRegisteredUnique": { "max": 0 }, + "colorDomainContracts.activeUncontractedUnique": { "max": 0 }, + "colorScopes.appUi.occurrences": { "max": 0 }, + "colorScopes.appUi.uniqueColors": { "max": 0 }, + "cssVarDefinitions.unresolvedUnique": { "max": 0 }, + "cssVarDefinitions.unresolvedRequiredUnique": { "max": 0 }, + "cssVarDefinitions.fallbackOnlyUnique": { "max": 0 }, + "cssVarDefinitions.runtimeOnlyRequiredContractUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCrossFileUnique": { "max": 0 }, + "cssVarDefinitions.nonContractDynamicInputUnique": { "max": 0 }, + "cssVarDefinitions.nonContractCssPrivateUnique": { "max": 0 }, + "cssVarDefinitions.unregisteredDynamicFamilyUnique": { "max": 0 }, + "cssVarDefinitions.dynamicFamilyUnexportedUnique": { "max": 0 }, + "cssVarDefinitions.staleRegisteredDynamicFamilyUnique": { "max": 0 }, + "tokenAliasLiterals.occurrences": { "max": 0 }, + "tokenAliasLiterals.uniqueColors": { "max": 0 }, + "nearPairs.indistinguishableTotal": { "max": 0 }, + "nearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.nearTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.appUi.nearTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.indistinguishableTotal": { "max": 0 }, + "colorDomainNearPairs.assetMetadata.nearTotal": { "max": 0 }, + "colorDomainScopes.appUi.occurrences": { "max": 0 }, + "colorDomainScopes.appUi.uniqueColors": { "max": 0 }, + "colorDomainScopes.assetMetadata.occurrences": { "max": 0 }, + "colorDomainScopes.assetMetadata.uniqueColors": { "max": 0 } + } +} diff --git a/scripts/theme-color-near-pair-decisions.json b/scripts/theme-color-near-pair-decisions.json index 73c7876fd9..3549ad2e75 100644 --- a/scripts/theme-color-near-pair-decisions.json +++ b/scripts/theme-color-near-pair-decisions.json @@ -3,7 +3,7 @@ "description": "Explicit decisions for specialized theme near-color pairs. Keep this file in sync with scripts/audit-theme-colors.mjs output; lower the audit baseline when a pair is merged.", "decisions": [ { - "root": "src/web-ui/src", + "root": "src/web-ui", "domain": "themePreset", "key": "#1a1b26 <-> #1c1c1f", "decision": "keep", @@ -12,7 +12,7 @@ "reevaluateWhen": "Only after a visual review proves Tokyo Night no longer needs a distinct primary background identity." }, { - "root": "src/web-ui/src", + "root": "src/web-ui", "domain": "themePreset", "key": "#1c1c1f <-> #212019", "decision": "keep", @@ -21,7 +21,7 @@ "reevaluateWhen": "Only if China Night gets a separate editor lineHighlight token or visual review proves the current-line cue remains visible." }, { - "root": "src/web-ui/src", + "root": "src/web-ui", "domain": "themePreset", "key": "#2b2d30 <-> #313335", "decision": "keep", @@ -30,7 +30,7 @@ "reevaluateWhen": "Only after a Midnight surface-ramp redesign removes the adjacent role split." }, { - "root": "src/web-ui/src", + "root": "src/web-ui", "domain": "appearanceProjection", "key": "#0451a5 <-> #0550ae", "decision": "keep", @@ -39,49 +39,13 @@ "reevaluateWhen": "Reevaluate only when terminal ANSI and workbench link roles share a reviewed palette contract." }, { - "root": "src/web-ui/src", - "domain": "appearanceProjection", - "key": "rgba(0, 0, 0, 0.12) <-> rgba(0, 0, 0, 0.15)", - "decision": "keep", - "owner": "src/web-ui/src/infrastructure/appearance/builtins/buildBuiltinAppearance.ts", - "reason": "The black overlay ladder separates subtle and stronger elevation states in light Appearance packages; both stops are intentional adjacent-state values.", - "reevaluateWhen": "Reevaluate when the light Appearance overlay ladder is redesigned with focused surface-state screenshots." - }, - { - "root": "src/web-ui/src", + "root": "src/web-ui", "domain": "appearanceProjection", "key": "rgba(255, 255, 255, 0.12) <-> rgba(255, 255, 255, 0.15)", "decision": "keep", "owner": "src/web-ui/src/infrastructure/appearance/builtins/buildBuiltinAppearance.ts", "reason": "The white overlay ladder separates subtle and stronger elevation states in dark Appearance packages; both stops are intentional adjacent-state values.", "reevaluateWhen": "Reevaluate when the dark Appearance overlay ladder is redesigned with focused surface-state screenshots." - }, - { - "root": "BitFun-Installer/src", - "domain": "themePreset", - "key": "#0e0e10 <-> #121214", - "decision": "keep", - "owner": "BitFun-Installer/src/theme/installerThemesData.ts", - "reason": "ThemeSetup renders dark theme cards side by side with primary and secondary preview backgrounds. Cyber needs its own darker primary preview seed so the named theme is not distinguishable only by label and accent.", - "reevaluateWhen": "Only if installer theme selection adds a separate identity swatch or screenshots prove the primary preview no longer carries theme identity." - }, - { - "root": "BitFun-Installer/src", - "domain": "themePreset", - "key": "#1a1b26 <-> #1a1c1e", - "decision": "keep", - "owner": "BitFun-Installer/src/theme/installerThemesData.ts", - "reason": "Tokyo Night appears as an adjacent installer preview card, and its primary background should preserve the Tokyo base hue while the shared installer card surface stays neutral.", - "reevaluateWhen": "Only after installer preview cards are redesigned to use a dedicated non-background theme identity affordance." - }, - { - "root": "BitFun-Installer/src", - "domain": "themePreset", - "key": "#121214 <-> #1a1814", - "decision": "keep", - "owner": "BitFun-Installer/src/theme/installerThemesData.ts", - "reason": "Ink Night uses a warmer dark primary background in adjacent installer preview cards. Collapsing it into the canonical dark seed makes multiple dark choices visually flatter before the app is installed.", - "reevaluateWhen": "Only if visual review shows installer dark theme cards no longer rely on primary background identity." } ] } diff --git a/scripts/theme-css-var-contract.mjs b/scripts/theme-css-var-contract.mjs index 08b384a592..5a470d092f 100644 --- a/scripts/theme-css-var-contract.mjs +++ b/scripts/theme-css-var-contract.mjs @@ -41,16 +41,41 @@ export const PACKAGE_CSS_VAR_DEFINITION_CONTRACTS = Object.freeze([ }), ]); -export const DEFAULT_ROOT = 'src/web-ui/src'; +export const PACKAGE_CSS_VAR_IMPORT_CONTRACTS = Object.freeze([ + Object.freeze({ + specifier: '@bitfun/design-tokens/tokens.css', + packageNames: Object.freeze(['@bitfun/design-tokens']), + }), + Object.freeze({ + specifier: '@bitfun/theme-bitfun/default.css', + packageNames: Object.freeze(['@bitfun/design-tokens', '@bitfun/theme-bitfun']), + }), + Object.freeze({ + specifier: '@bitfun/theme-bitfun/themes.css', + packageNames: Object.freeze(['@bitfun/theme-bitfun']), + }), +]); + +export const DEFAULT_ROOT = 'src/web-ui'; export const DEFAULT_BASELINE_PATH = 'scripts/theme-color-governance-baseline.json'; -export const COLOR_EXTENSIONS = new Set(['.css', '.scss', '.sass', '.ts', '.tsx', '.js', '.jsx']); +export const COLOR_EXTENSIONS = new Set([ + '.css', + '.html', + '.js', + '.jsx', + '.mjs', + '.sass', + '.scss', + '.svg', + '.ts', + '.tsx', + '.webmanifest', +]); export const TOKEN_PATH_PARTS = [ - 'BitFun-Installer/src/styles/variables.css', 'BitFun-Installer/src/theme', 'component-library/styles', - 'theme/presets', ]; export const TOKEN_ALIAS_SOURCE_PATH_PARTS = [ @@ -58,18 +83,17 @@ export const TOKEN_ALIAS_SOURCE_PATH_PARTS = [ ]; export const CONTRACT_VAR_DEFINITION_PATH_PARTS = [ - 'BitFun-Installer/src/styles/variables.css', 'BitFun-Installer/src/theme/installerThemeRuntime.ts', 'component-library/styles', 'infrastructure/appearance', - 'src/mobile-web/src/theme/presets', + 'src/mobile-web/src/styles/global.scss', 'tools/bitfun-canvas/runtime/styles', 'tools/generative-widget/appearancePayload.ts', ]; export const STATIC_CONTRACT_VAR_DEFINITION_PATH_PARTS = [ - 'BitFun-Installer/src/styles/variables.css', 'component-library/styles', + 'src/mobile-web/src/styles/global.scss', ]; export const RUNTIME_CONTRACT_VAR_DEFINITION_PATH_PARTS = [ @@ -86,6 +110,12 @@ export const EXCEPTION_PATH_PARTS = [ ]; export const COLOR_DOMAIN_RULES = [ + { + key: 'assetMetadata', + label: 'Static asset and install metadata', + pathParts: ['assets', 'public/favicon', 'site.webmanifest', 'src/assets'], + extensions: ['.svg', '.webmanifest'], + }, { key: 'appearanceProjection', label: 'Appearance projections', @@ -104,7 +134,7 @@ export const COLOR_DOMAIN_RULES = [ { key: 'tokenContract', label: 'Token contracts', - pathParts: ['BitFun-Installer/src/styles/variables.css', 'component-library/styles'], + pathParts: ['component-library/styles'], }, { key: 'generatedWidget', @@ -175,6 +205,12 @@ export const COLOR_DOMAIN_LABELS = Object.fromEntries([ ]); export const COLOR_DOMAIN_CONTRACTS = [ + { + key: 'assetMetadata', + owner: 'src/web-ui/src/app/components/NavPanel/assets; src/web-ui/public/assets; src/mobile-web/src/assets; src/miniapp-market-web/public; src/skin-market-web/public', + reason: 'Favicons, install metadata, and self-contained vector assets cannot consume runtime CSS variables and therefore own their serialized colors at the asset boundary.', + mergePolicy: 'Keep only identity or platform metadata colors here; any rendered application UI color must move to a canonical theme token.', + }, { key: 'appearanceProjection', owner: 'src/web-ui/src/infrastructure/appearance/builtins/buildBuiltinAppearance.ts', @@ -183,15 +219,15 @@ export const COLOR_DOMAIN_CONTRACTS = [ }, { key: 'themePreset', - owner: 'src/web-ui/src/infrastructure/appearance/builtins', + owner: 'src/web-ui/src/infrastructure/appearance/builtins; BitFun-Installer/src/theme', reason: 'Builtin appearances own primitive palette mapping and must keep per-appearance personality instead of being folded into shared app tokens.', mergePolicy: 'Only merge exact duplicate primitive values after confirming the theme still exposes distinct semantic roles.', }, { key: 'themeRuntime', - owner: 'src/web-ui/src/infrastructure/appearance/adapters/CssTokenAppearanceAdapter.ts', - reason: 'AppearanceRuntime applies the registered CSS token projection for static CSS, web preview, and embedded surface payloads.', - mergePolicy: 'Keep the runtime projection canonical and reject reintroduction of compatibility aliases or surface-local token owners.', + owner: 'src/web-ui/src/infrastructure/appearance/adapters/ThemeTokenAppearanceAdapter.ts', + reason: 'AppearanceRuntime applies the registered canonical theme, product-domain, and component token payloads.', + mergePolicy: 'Keep runtime payloads canonical and reject compatibility aliases or surface-local token owners.', }, { key: 'tokenContract', @@ -267,20 +303,7 @@ export const TOKEN_COMPATIBILITY_ALIAS_FAMILY_CONTRACTS = []; export const FALLBACK_VAR_CONTRACTS = []; -export const SURFACE_TOKEN_RENAME_CONTRACTS = [ - { - key: '--m-editor-highlight-rgb', - canonical: '--private-markdown-editor-highlight-rgb', - owner: 'src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss', - reason: 'Markdown editor highlight color should use the component-private markdown-editor helper instead of the abbreviated meditor local key.', - }, - { - key: '--m-editor-highlight-border-rgb', - canonical: '--private-markdown-editor-highlight-border-rgb', - owner: 'src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss', - reason: 'Markdown editor highlight border color should use the component-private markdown-editor helper instead of the abbreviated meditor local key.', - }, -]; +export const SURFACE_TOKEN_RENAME_CONTRACTS = []; export const DYNAMIC_VAR_FAMILY_CONTRACTS = [ { @@ -293,26 +316,16 @@ export const DYNAMIC_VAR_FAMILY_CONTRACTS = [ owner: 'src/web-ui/src/tools/bitfun-canvas/runtime/canvasRuntimeInstaller.ts; src/web-ui/src/tools/bitfun-canvas/runtime/styles/canvas-runtime.scss', reason: 'BitFun Canvas iframe runtime receives host Appearance values through a scoped CSS variable family that must stay isolated from app root tokens.', }, - { - prefix: '--color-accent-', - owner: 'src/mobile-web/src/theme/presets', - reason: 'Mobile presets export the active accent palette scale by numeric stop.', - }, - { - prefix: '--color-purple-', - owner: 'src/mobile-web/src/theme/presets', - reason: 'Mobile presets export the secondary accent palette by numeric stop.', - }, - { - prefix: '--color-pink-', - owner: 'src/mobile-web/src/theme/presets', - reason: 'Mobile presets export assistant-mode identity accents by numeric stop for session and picker states.', - }, { prefix: '--bf-font-size-', owner: 'src/web-ui/src/infrastructure/font-preference/core/FontPreferenceService.ts', reason: 'Font preference runtime overrides the canonical design-system font-size primitives so every semantic role follows one global scale.', }, + { + prefix: '--mobile-', + owner: 'src/apps/mobile/design-system/preview/preview.js; src/apps/mobile/design-system/preview/preview.css', + reason: 'The native comparison preview projects the validated mobile token contract into a scoped device canvas without exposing those values as canonical web theme tokens.', + }, ]; export const REGISTERED_DYNAMIC_VAR_PREFIXES = new Set( diff --git a/scripts/theme-visual-governance-contract.json b/scripts/theme-visual-governance-contract.json index 4f51d97b1a..97ea309a9e 100644 --- a/scripts/theme-visual-governance-contract.json +++ b/scripts/theme-visual-governance-contract.json @@ -9,7 +9,7 @@ "formFactors": ["desktop", "narrow"], "themes": ["dark", "light", "system", "bitfun-monochrome"], "states": ["default", "hover", "focus", "selected", "disabled"], - "tokenFamilies": ["--bf-appearance-token-color-bg-*", "--bf-appearance-token-color-text-*", "--bf-appearance-token-chrome-*", "--bf-appearance-token-element-bg-*", "--bf-appearance-token-border-*", "--bitfun-nav-*"], + "tokenFamilies": ["--bf-color-surface-*", "--bf-color-content-*", "--bf-color-border-*", "--bf-color-action-*", "--bf-component-scene-*", "--bitfun-nav-*"], "evidence": [ { "type": "theme-color-audit", @@ -22,7 +22,7 @@ } ], "risks": [ - "Web UI visual values must remain owned by the active Appearance projection.", + "Web UI visual values must resolve through canonical design-system tokens projected by the active Appearance.", "System theme resolution must not assume desktop-only media query behavior." ] }, @@ -33,7 +33,7 @@ "formFactors": ["desktop", "narrow"], "themes": ["dark", "light", "system", "bitfun-monochrome"], "states": ["default", "streaming", "hover", "focus", "selected", "error", "empty"], - "tokenFamilies": ["--bf-appearance-token-flowchat-*", "--bf-appearance-token-tool-card-*", "--bf-appearance-token-color-bg-scene", "--bf-appearance-token-color-text-*", "--bf-appearance-token-color-accent-*"], + "tokenFamilies": ["--bf-color-surface-*", "--bf-color-content-*", "--bf-color-accent-*", "--bf-color-action-*", "--bf-color-status-*", "--bf-domain-tool-*"], "evidence": [ { "type": "theme-color-audit", @@ -47,7 +47,7 @@ ], "risks": [ "Streaming and virtualized items can hide token regressions until historical turns are rendered.", - "Flow Chat has many visual states; every shared token family must remain in the Appearance contract." + "Flow Chat has many visual states; shared colors must stay in the canonical theme contract and tool identity colors in the registered domain contract." ] }, { @@ -57,7 +57,7 @@ "formFactors": ["desktop", "narrow"], "themes": ["dark", "light", "system"], "states": ["default", "expanded", "collapsed", "hover", "focus", "success", "warning", "error"], - "tokenFamilies": ["--bf-appearance-token-tool-card-*", "--bf-appearance-token-color-success*", "--bf-appearance-token-color-warning*", "--bf-appearance-token-color-error*"], + "tokenFamilies": ["--bf-color-surface-*", "--bf-color-border-*", "--bf-color-status-*", "--bf-color-action-*", "--bf-domain-tool-*"], "evidence": [ { "type": "theme-color-audit", @@ -81,7 +81,7 @@ "formFactors": ["desktop", "narrow"], "themes": ["dark", "light", "system"], "states": ["default", "focus", "selection", "search", "added", "deleted", "changed", "conflict"], - "tokenFamilies": ["Monaco palette", "--diff-editor-*", "--bf-appearance-token-git-color-*", "--bf-appearance-token-color-text-*"], + "tokenFamilies": ["Monaco palette", "--bf-domain-git-*", "--bf-color-content-*", "--bf-color-surface-*", "--bf-color-status-*"], "evidence": [ { "type": "theme-color-audit", @@ -105,7 +105,7 @@ "formFactors": ["desktop", "narrow"], "themes": ["dark", "light", "system"], "states": ["default", "focus", "selection", "ansi-normal", "ansi-bright", "error"], - "tokenFamilies": ["terminal ANSI palette", "--bf-appearance-token-color-text-*", "--bf-appearance-token-border-*"], + "tokenFamilies": ["terminal ANSI palette", "--bf-color-content-*", "--bf-color-surface-*", "--bf-color-border-*", "--bf-color-status-*"], "evidence": [ { "type": "theme-color-audit", @@ -129,7 +129,7 @@ "formFactors": ["desktop", "narrow"], "themes": ["dark", "light", "system"], "states": ["default", "code", "table", "link", "diagram", "error"], - "tokenFamilies": ["--markdown-*", "--markdown-primary-color", "Mermaid palette", "Prism palette"], + "tokenFamilies": ["--bf-color-content-*", "--bf-color-surface-*", "--bf-domain-mermaid-*", "--bf-domain-prism-*", "Mermaid renderer palette"], "evidence": [ { "type": "theme-color-audit", @@ -142,7 +142,7 @@ } ], "risks": [ - "--markdown-primary-color is the embedded-content accent override and must remain distinct from generic app primary aliases.", + "Embedded Markdown uses canonical content and surface roles while Mermaid and Prism retain registered renderer-domain roles.", "Mermaid graph roles do not map directly to app status colors." ] }, @@ -153,7 +153,7 @@ "formFactors": ["iframe", "desktop", "narrow"], "themes": ["dark", "light", "system"], "states": ["fallback-before-host-payload", "host-payload", "loading", "error"], - "tokenFamilies": ["--bf-appearance-token-color-*", "--bf-appearance-token-border-*", "--bf-appearance-token-element-bg-*", "--bf-appearance-token-size-radius-*", "--bf-appearance-token-size-gap-*"], + "tokenFamilies": ["--bf-color-*", "--bf-shadow-*", "--bf-effect-*", "--bf-opacity-*", "--bf-radius-*", "--bf-space-*"], "evidence": [ { "type": "boundary-render-review", @@ -162,7 +162,7 @@ { "type": "theme-color-audit", "command": "pnpm run theme:color-audit", - "requirement": "Generated widget fallback colors must be derived from a builtin Appearance package." + "requirement": "Generated widget values must come from the canonical theme package contract and the selected builtin Appearance projection." } ], "risks": [ @@ -177,7 +177,7 @@ "formFactors": ["desktop", "narrow"], "themes": ["dark", "light", "system", "bitfun-monochrome"], "states": ["default", "selected", "hover", "focus", "imported-appearance", "system-appearance"], - "tokenFamilies": ["--bf-appearance-token-color-accent-*", "--bf-appearance-token-color-bg-*", "--bf-appearance-token-color-text-*", "--bf-appearance-token-border-*", "--bf-appearance-token-element-bg-*", "--bf-appearance-token-config-page-*"], + "tokenFamilies": ["--bf-color-*", "--bf-shadow-*", "--bf-effect-*", "--bf-opacity-*", "--bf-component-config-page-*", "--bf-domain-*"], "evidence": [ { "type": "theme-color-audit", @@ -191,17 +191,17 @@ ], "risks": [ "Theme selection can resolve differently under system mode.", - "Custom theme previews can expose missing runtime aliases before ordinary components do." + "Imported v2 theme-token packages must validate against the canonical root and scoped token registries before preview or activation." ] }, { "key": "mobile-web-shell", - "owner": "src/mobile-web; src/web-ui/src/component-library/styles", + "owner": "src/mobile-web/src/theme; src/mobile-web/src/styles", "platforms": ["mobile-web"], "formFactors": ["mobile", "narrow"], "themes": ["dark", "light", "system"], "states": ["default", "loading", "error", "navigation"], - "tokenFamilies": ["shared web tokens", "--bf-appearance-token-color-bg-*", "--bf-appearance-token-color-text-*", "--bf-appearance-token-border-*"], + "tokenFamilies": ["@bitfun/theme-bitfun", "--bf-color-surface-*", "--bf-color-content-*", "--bf-color-border-*", "--bf-color-action-*", "--bf-color-status-*"], "evidence": [ { "type": "mobile-build-review", @@ -221,7 +221,7 @@ "formFactors": ["desktop", "narrow"], "themes": ["dark", "light", "system", "bitfun-dark", "bitfun-light", "bitfun-midnight", "bitfun-china-style", "bitfun-china-night", "bitfun-cyber", "bitfun-slate", "bitfun-tokyo-night"], "states": ["theme-setup", "language", "options", "loading", "progress", "error", "completed", "hover", "focus"], - "tokenFamilies": ["--bf-appearance-token-color-bg-*", "--bf-appearance-token-color-text-*", "--bf-appearance-token-element-bg-*", "--bf-appearance-token-border-*", "--bf-appearance-token-color-accent-*", "--bf-appearance-token-color-success", "--bf-appearance-token-color-warning", "--bf-appearance-token-color-error"], + "tokenFamilies": ["@bitfun/theme-bitfun", "--bf-color-surface-*", "--bf-color-content-*", "--bf-color-border-*", "--bf-color-action-*", "--bf-color-accent-*", "--bf-color-status-*"], "evidence": [ { "type": "theme-color-audit", diff --git a/src/apps/desktop/bootstrap-ui/frontend-update-confirm.html b/src/apps/desktop/bootstrap-ui/frontend-update-confirm.html index 224cc131b1..14bc2a22b4 100644 --- a/src/apps/desktop/bootstrap-ui/frontend-update-confirm.html +++ b/src/apps/desktop/bootstrap-ui/frontend-update-confirm.html @@ -1,25 +1,26 @@ - + Review frontend update + diff --git a/src/apps/desktop/bootstrap-ui/index.html b/src/apps/desktop/bootstrap-ui/index.html index 362dffc6d1..da483c8335 100644 --- a/src/apps/desktop/bootstrap-ui/index.html +++ b/src/apps/desktop/bootstrap-ui/index.html @@ -1,15 +1,16 @@ - + BitFun recovery + diff --git a/src/apps/desktop/src/appearance.rs b/src/apps/desktop/src/appearance.rs index 21cf5aaf47..7adf374fab 100644 --- a/src/apps/desktop/src/appearance.rs +++ b/src/apps/desktop/src/appearance.rs @@ -392,14 +392,20 @@ impl AppearanceConfig { root.setAttribute('data-bf-appearance', '{id}'); root.setAttribute('data-bf-appearance-mode', '{appearance_mode}'); + root.setAttribute('data-bf-design-system-root', ''); + root.setAttribute('data-color-scheme', '{appearance_mode}'); + root.setAttribute('data-contrast', 'standard'); + root.setAttribute('data-density', 'compact'); - root.style.setProperty('--bf-appearance-token-color-bg-primary', '{bg_primary}'); - root.style.setProperty('--bf-appearance-token-color-bg-secondary', '{bg_secondary}'); - root.style.setProperty('--bf-appearance-token-color-bg-tertiary', '{bg_primary}'); - root.style.setProperty('--bf-appearance-token-color-bg-workbench', '{bg_primary}'); - root.style.setProperty('--bf-appearance-token-color-bg-scene', '{bg_scene}'); - root.style.setProperty('--bf-appearance-token-color-text-primary', '{text_primary}'); - root.style.setProperty('--bf-appearance-token-color-accent-500', '{accent_color}'); + root.style.setProperty('--bf-color-surface-canvas', '{bg_primary}'); + root.style.setProperty('--bf-color-surface-panel', '{bg_secondary}'); + root.style.setProperty('--bf-color-surface-tertiary', '{bg_primary}'); + root.style.setProperty('--bf-color-surface-workbench', '{bg_primary}'); + root.style.setProperty('--bf-color-surface-scene', '{bg_scene}'); + root.style.setProperty('--bf-color-surface-chrome', '{bg_primary}'); + root.style.setProperty('--bf-color-content-primary', '{text_primary}'); + root.style.setProperty('--bf-color-content-muted', '{text_muted}'); + root.style.setProperty('--bf-color-accent-default', '{accent_color}'); root.style.backgroundColor = '{bg_primary}'; if (document.body) {{ @@ -428,6 +434,7 @@ impl AppearanceConfig { bg_secondary = self.bg_secondary, bg_scene = self.bg_scene, text_primary = self.text_primary, + text_muted = self.text_muted, accent_color = self.accent_color, startup_trace_id_json = startup_trace_id_json, perf_trace_enabled = perf_trace_enabled, @@ -479,10 +486,14 @@ mod startup_appearance_tests { assert!(script.contains("__BITFUN_BOOTSTRAP_APPEARANCE_SELECTION__")); assert!(script.contains("data-bf-appearance")); assert!(script.contains("data-bf-appearance-mode")); - assert!(script.contains("--bf-appearance-token-color-bg-primary")); - assert!(script.contains("--bf-appearance-token-color-bg-scene")); - assert!(script.contains("--bf-appearance-token-color-text-primary")); - assert!(script.contains("--bf-appearance-token-color-accent-500")); + assert!(script.contains("data-bf-design-system-root")); + assert!(script.contains("data-color-scheme")); + assert!(script.contains("--bf-color-surface-canvas")); + assert!(script.contains("--bf-color-surface-scene")); + assert!(script.contains("--bf-color-content-primary")); + assert!(script.contains("--bf-color-content-muted")); + assert!(script.contains("--bf-color-accent-default")); + assert!(!script.contains("--bf-appearance-token-")); let retired_bootstrap_global = ["__BITFUN_BOOTSTRAP", "THEME"].join("_"); let retired_background_token = ["--", "color-bg-"].concat(); let retired_text_token = ["--", "color-text-"].concat(); diff --git a/src/apps/desktop/src/frontend_workbench.rs b/src/apps/desktop/src/frontend_workbench.rs index 98a937dfa8..190a9b79c0 100644 --- a/src/apps/desktop/src/frontend_workbench.rs +++ b/src/apps/desktop/src/frontend_workbench.rs @@ -24,6 +24,7 @@ const TRANSACTION_WAIT_GRACE: Duration = Duration::from_secs(3); const STATE_SCHEMA_VERSION: u32 = 2; const RECOVERY_HTML: &[u8] = include_bytes!("../bootstrap-ui/index.html"); const CONFIRMATION_HTML: &[u8] = include_bytes!("../bootstrap-ui/frontend-update-confirm.html"); +const BOOTSTRAP_THEME_CSS: &[u8] = include_bytes!("generated/bootstrap_theme.css"); #[derive(Debug, Clone, Default, Serialize, Deserialize)] #[serde(default, rename_all = "camelCase")] @@ -755,6 +756,17 @@ impl FrontendWorkbenchManager { request: tauri::http::Request>, ) -> tauri::http::Response> { let request_path = request.uri().path(); + if request_path == "/bootstrap-theme.css" { + return tauri::http::Response::builder() + .status(tauri::http::StatusCode::OK) + .header( + tauri::http::header::CONTENT_TYPE, + "text/css; charset=utf-8", + ) + .header(tauri::http::header::CACHE_CONTROL, "no-store, max-age=0") + .body(BOOTSTRAP_THEME_CSS.to_vec()) + .unwrap_or_else(|_| tauri::http::Response::new(Vec::new())); + } if request_path == "/frontend-update-confirm.html" { return tauri::http::Response::builder() .status(tauri::http::StatusCode::OK) @@ -1769,4 +1781,26 @@ mod tests { assert!(body.contains("confirm_frontend_update")); assert!(body.contains("rollback_frontend_update")); } + + #[test] + fn protocol_serves_the_generated_bootstrap_theme_without_an_active_revision() { + let temp = tempfile::tempdir().expect("tempdir"); + let manager = FrontendWorkbenchManager::new(temp.path()); + let request = tauri::http::Request::builder() + .uri("bitfun-ui://localhost/bootstrap-theme.css") + .body(Vec::new()) + .expect("request"); + + let response = manager.protocol_response(request); + let body = String::from_utf8_lossy(response.body()); + + assert_eq!(response.status(), tauri::http::StatusCode::OK); + assert_eq!( + response.headers().get(tauri::http::header::CONTENT_TYPE), + Some(&tauri::http::HeaderValue::from_static("text/css; charset=utf-8")) + ); + assert!(body.contains("--bf-color-surface-canvas")); + assert!(body.contains("--bf-color-status-danger-content")); + assert!(!body.contains("--bf-appearance-token-")); + } } diff --git a/src/apps/desktop/src/generated/bootstrap_theme.css b/src/apps/desktop/src/generated/bootstrap_theme.css new file mode 100644 index 0000000000..f8787d804d --- /dev/null +++ b/src/apps/desktop/src/generated/bootstrap_theme.css @@ -0,0 +1,105 @@ +/* Generated by scripts/generate-startup-appearance-bootstrap.mjs. Do not edit. */ +@layer bf.tokens.theme { + :where([data-bf-design-system-root][data-color-scheme="dark"]) { + --bf-color-accent-border: color-mix(in srgb, #60a5fa 40%, transparent); + --bf-color-accent-border-subtle: color-mix(in srgb, #60a5fa 25%, transparent); + --bf-color-accent-default: #60a5fa; + --bf-color-accent-disabled: rgba(96, 165, 250, 0.30); + --bf-color-accent-hover: #3b82f6; + --bf-color-accent-secondary: #8b5cf6; + --bf-color-accent-secondary-border: color-mix(in srgb, #8b5cf6 25%, transparent); + --bf-color-accent-secondary-hover: #7c6b99; + --bf-color-accent-secondary-surface: color-mix(in srgb, #8b5cf6 9%, transparent); + --bf-color-accent-secondary-surface-strong: color-mix(in srgb, #8b5cf6 15%, transparent); + --bf-color-accent-surface: color-mix(in srgb, #60a5fa 9%, transparent); + --bf-color-accent-surface-strong: color-mix(in srgb, #60a5fa 15%, transparent); + --bf-color-accent-surface-subtle: color-mix(in srgb, #60a5fa 5%, transparent); + --bf-color-action-neutral-border: rgba(255, 255, 255, 0.18); + --bf-color-action-neutral-content: #b0b0b0; + --bf-color-action-neutral-content-disabled: #555555; + --bf-color-action-neutral-fill-border: rgba(255, 255, 255, 0.1); + --bf-color-action-neutral-surface: rgba(255, 255, 255, 0.1); + --bf-color-action-neutral-surface-hover: rgba(255, 255, 255, 0.12); + --bf-color-action-neutral-surface-pressed: rgba(255, 255, 255, 0.15); + --bf-color-action-primary-background: rgba(255, 255, 255, 0.16); + --bf-color-action-primary-content: #f3f3f5; + --bf-color-action-primary-hover: rgba(255, 255, 255, 0.24); + --bf-color-action-primary-pressed: rgba(255, 255, 255, 0.2); + --bf-color-action-quiet-content: #b0b0b0; + --bf-color-action-quiet-hover: rgba(255, 255, 255, 0.06); + --bf-color-action-quiet-pressed: rgba(255, 255, 255, 0.1); + --bf-color-action-secondary-background: rgba(255, 255, 255, 0.06); + --bf-color-action-secondary-content: #e8e8e8; + --bf-color-action-secondary-hover: rgba(255, 255, 255, 0.1); + --bf-color-action-secondary-pressed: rgba(255, 255, 255, 0.12); + --bf-color-border-default: rgba(255, 255, 255, 0.18); + --bf-color-border-strong: rgba(255, 255, 255, 0.3); + --bf-color-border-subtle: rgba(255, 255, 255, 0.12); + --bf-color-content-disabled: #555555; + --bf-color-content-inverse: #0e0e10; + --bf-color-content-muted: #858585; + --bf-color-content-on-dark: #ffffff; + --bf-color-content-on-light: #000000; + --bf-color-content-primary: #e8e8e8; + --bf-color-content-secondary: #b0b0b0; + --bf-color-control-switch-thumb: #ffffff; + --bf-color-control-switch-track: #555555; + --bf-color-control-switch-track-checked: #34c78c; + --bf-color-field-background: #1c1c1f; + --bf-color-field-background-hover: rgba(255, 255, 255, 0.06); + --bf-color-field-border: rgba(255, 255, 255, 0.18); + --bf-color-field-border-focus: #60a5fa; + --bf-color-field-border-hover: rgba(255, 255, 255, 0.24); + --bf-color-focus-ring: #60a5fa; + --bf-color-identity-assistant-border: color-mix(in srgb, #ec4899 15%, transparent); + --bf-color-identity-assistant-content: #ec4899; + --bf-color-identity-assistant-content-hover: #f472b6; + --bf-color-identity-assistant-surface: color-mix(in srgb, #ec4899 9%, transparent); + --bf-color-identity-assistant-surface-subtle: color-mix(in srgb, #ec4899 5%, transparent); + --bf-color-key-hint-background: rgba(255, 255, 255, 0.1); + --bf-color-link-default: #60a5fa; + --bf-color-link-hover: #93c5fd; + --bf-color-overlay-scrim: rgba(0, 0, 0, 0.56); + --bf-color-scrollbar-thumb: rgba(255, 255, 255, 0.12); + --bf-color-scrollbar-thumb-hover: rgba(255, 255, 255, 0.15); + --bf-color-status-danger-border: rgba(239, 68, 68, 0.3); + --bf-color-status-danger-content: #ef4444; + --bf-color-status-danger-surface: rgba(239, 68, 68, 0.1); + --bf-color-status-info-border: rgba(255, 255, 255, 0.24); + --bf-color-status-info-content: #a1a1aa; + --bf-color-status-info-surface: rgba(255, 255, 255, 0.08); + --bf-color-status-success-border: rgba(52, 211, 153, 0.3); + --bf-color-status-success-content: #34d399; + --bf-color-status-success-surface: rgba(52, 211, 153, 0.1); + --bf-color-status-warning-border: rgba(245, 158, 11, 0.3); + --bf-color-status-warning-content: #f59e0b; + --bf-color-status-warning-surface: rgba(245, 158, 11, 0.1); + --bf-color-surface-canvas: #0e0e10; + --bf-color-surface-chrome: #0e0e10; + --bf-color-surface-panel: #1c1c1f; + --bf-color-surface-raised: #1c1c1f; + --bf-color-surface-scene: #1c1c1f; + --bf-color-surface-subtle: rgba(255, 255, 255, 0.06); + --bf-color-surface-tertiary: #0e0e10; + --bf-color-surface-workbench: #0e0e10; + --bf-effect-blur-base: blur(8px) saturate(1.1); + --bf-effect-blur-medium: blur(12px) saturate(1.2); + --bf-effect-blur-subtle: blur(4px) saturate(1.05); + --bf-opacity-disabled: 0.6; + --bf-opacity-focus: 0.9; + --bf-opacity-hover: 0.8; + --bf-opacity-muted: 0.8; + --bf-shadow-accent-glow: 0 12px 32px color-mix(in srgb, #3b82f6 25%, transparent), 0 6px 16px color-mix(in srgb, #60a5fa 18%, transparent), 0 3px 8px rgba(0, 0, 0, 0.12); + --bf-shadow-base: 0 4px 8px rgba(0, 0, 0, 0.7); + --bf-shadow-composer: 0 2px 6px rgba(0, 0, 0, 0.32); + --bf-shadow-inner-highlight: inset 0 1px 0 rgba(255, 255, 255, 0.08); + --bf-shadow-inner-highlight-hover: inset 0 1px 0 rgba(255, 255, 255, 0.24); + --bf-shadow-lg: 0 8px 16px rgba(0, 0, 0, 0.6); + --bf-shadow-menu: 0 4px 10px rgba(0, 0, 0, 0.48); + --bf-shadow-overlay: 0 4px 20px rgba(0, 0, 0, 0.48); + --bf-shadow-raised: 0 2px 4px rgba(0, 0, 0, 0.8); + --bf-shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.8); + --bf-shadow-xl: 0 12px 24px rgba(0, 0, 0, 0.5); + --bf-shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.9); + } +} diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/account/AccountScreen.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/account/AccountScreen.kt index 6a6370e67d..d6bbbc5b8c 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/account/AccountScreen.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/account/AccountScreen.kt @@ -37,7 +37,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -57,6 +56,7 @@ import com.bitfun.mobile.app.viewmodel.AccountViewModel import com.bitfun.mobile.core.feature.account.AccountFailureReason import com.bitfun.mobile.core.feature.account.AccountIntent import com.bitfun.mobile.core.feature.account.AccountUiState +import com.bitfun.mobile.app.ui.theme.bitFunColors private val AccountCardShape = RoundedCornerShape(24.dp) @@ -177,8 +177,8 @@ private fun AccountInput( focusedContainerColor = MaterialTheme.colorScheme.surface, unfocusedContainerColor = MaterialTheme.colorScheme.surface, disabledContainerColor = MaterialTheme.colorScheme.surface, - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, + focusedIndicatorColor = bitFunColors.transparent, + unfocusedIndicatorColor = bitFunColors.transparent, cursorColor = MaterialTheme.colorScheme.onSurface, focusedTextColor = MaterialTheme.colorScheme.onSurface, unfocusedTextColor = MaterialTheme.colorScheme.onSurface, @@ -222,7 +222,7 @@ private fun AccountProfilePage( Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { Text(stringResource(R.string.account_bitfun_account), fontSize = 17.sp, fontWeight = FontWeight.Bold) Spacer(Modifier.weight(1f)) - Text(stringResource(R.string.remote_settings_account_signed_in), fontSize = 14.sp, color = com.bitfun.mobile.app.ui.theme.bitFunColors.success) + Text(stringResource(R.string.remote_settings_account_signed_in), fontSize = 14.sp, color = com.bitfun.mobile.app.ui.theme.bitFunColors.statusSuccess) } Text(stringResource(R.string.account_signed_in_body, state.username), fontSize = 14.sp, lineHeight = 20.sp, color = MaterialTheme.colorScheme.onSurfaceVariant) } @@ -254,7 +254,7 @@ private fun AccountProfilePage( }, ), fontSize = 13.sp, - color = if (device.online) com.bitfun.mobile.app.ui.theme.bitFunColors.success else MaterialTheme.colorScheme.onSurfaceVariant, + color = if (device.online) com.bitfun.mobile.app.ui.theme.bitFunColors.statusSuccess else MaterialTheme.colorScheme.onSurfaceVariant, ) } if (reconnectable) Surface(color = MaterialTheme.colorScheme.surfaceVariant, shape = RoundedCornerShape(14.dp)) { diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/BitFunHeaderActionMenu.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/BitFunHeaderActionMenu.kt index 8e88510d46..3edbd75fde 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/BitFunHeaderActionMenu.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/BitFunHeaderActionMenu.kt @@ -49,6 +49,7 @@ import androidx.compose.ui.window.PopupProperties import com.bitfun.mobile.app.ui.theme.BitFunEaseOut import com.bitfun.mobile.app.ui.theme.MotionQuickMillis import com.bitfun.mobile.app.ui.theme.generated.MobileDesignGeometry +import com.bitfun.mobile.app.ui.theme.bitFunColors internal const val HEADER_ACTION_MENU_TEST_TAG: String = "header-action-menu" @@ -197,7 +198,7 @@ private fun HeaderActionRow(action: BitFunHeaderAction, onDismiss: () -> Unit) { .clip(RoundedCornerShape(10.dp)) .background( if (action.selected) MaterialTheme.colorScheme.surfaceVariant - else androidx.compose.ui.graphics.Color.Transparent, + else bitFunColors.transparent, ) .clickable(enabled = action.enabled) { action.onClick() diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/ChatStatusBar.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/ChatStatusBar.kt index 64d552e666..bb15002439 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/ChatStatusBar.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/ChatStatusBar.kt @@ -55,7 +55,7 @@ internal fun ChatStatusBar( val stopLabel = stringResource(R.string.message_stop) val statusLabel = if (detail != title) "$title · $detail" else title val statusColor = when (ConnectionStatusPresenter.tone(phase)) { - ConnectionTone.OK -> bitFunColors.success + ConnectionTone.OK -> bitFunColors.statusSuccess ConnectionTone.BUSY -> MaterialTheme.colorScheme.onSurfaceVariant ConnectionTone.ERROR -> MaterialTheme.colorScheme.error ConnectionTone.MUTED -> MaterialTheme.colorScheme.onSurfaceVariant diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/ComposerBar.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/ComposerBar.kt index 26a8376279..8e879e039a 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/ComposerBar.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/ComposerBar.kt @@ -50,7 +50,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.onFocusChanged -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.layout.ContentScale @@ -72,6 +71,7 @@ import com.bitfun.mobile.app.R import com.bitfun.mobile.app.ui.theme.BitFunEaseOut import com.bitfun.mobile.app.ui.theme.MotionQuickMillis import com.bitfun.mobile.app.ui.theme.MotionStructureMillis +import com.bitfun.mobile.app.ui.theme.bitFunColors import com.bitfun.mobile.app.ui.theme.generated.MobileDesignBreakpoints import com.bitfun.mobile.app.ui.theme.generated.MobileDesignGeometry import com.bitfun.mobile.core.feature.connection.ConnectionPhase @@ -602,7 +602,7 @@ private fun ModelSelectorContent( ) .background( if (option.selected) MaterialTheme.colorScheme.surfaceVariant - else Color.Transparent, + else bitFunColors.transparent, ) .clickable { onSelect(option.id) } .semantics { @@ -688,7 +688,7 @@ private fun PrimaryActionButton( modifier = Modifier .size(ActionSize) .clip(CircleShape) - .background(if (action == ComposerPrimaryAction.STOP) colors.error else Color.Transparent) + .background(if (action == ComposerPrimaryAction.STOP) colors.error else bitFunColors.transparent) .clickable(enabled = enabled) { when (action) { ComposerPrimaryAction.STOP -> onStop() @@ -775,9 +775,8 @@ private fun AttachmentStrip( ) } } - // The badge carries its own scrim rather than borrowing the - // theme's: it sits on whatever the photo happens to be, and a - // pale photo would swallow a surface-coloured control. + // Media controls sit over arbitrary photo content, so their + // scrim is a dedicated mobile design token. val removeLabel = stringResource(R.string.message_remove_image) Box( contentAlignment = Alignment.Center, @@ -785,20 +784,17 @@ private fun AttachmentStrip( .align(Alignment.TopEnd) .size(32.dp) .clip(CircleShape) - .background(BadgeScrim) + .background(bitFunColors.mediaScrim) .clickable(role = Role.Button, enabled = enabled) { onRemove(image.id) } .semantics { contentDescription = removeLabel }, ) { Text( "×", style = MaterialTheme.typography.labelMedium, - color = Color.White, + color = MaterialTheme.colorScheme.onPrimary, ) } } } } } - -/** `#AA222222` from the other client — a scrim, so it is not a theme role. */ -private val BadgeScrim = Color(0xAA222222) diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/tool/ToolStatusList.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/tool/ToolStatusList.kt index e28cb54b24..d13f2855f8 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/tool/ToolStatusList.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/chat/tool/ToolStatusList.kt @@ -23,7 +23,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -37,6 +36,7 @@ import com.bitfun.mobile.core.feature.session.ToolOperation import com.bitfun.mobile.core.feature.session.ToolPhase import com.bitfun.mobile.core.feature.session.ToolRow import com.bitfun.mobile.core.feature.session.collapseToolRows +import com.bitfun.mobile.app.ui.theme.bitFunColors /** Anything the desktop must be told about a rejection needs a reason; this is ours. */ private const val REJECT_REASON = "Rejected from the Android client" @@ -193,13 +193,13 @@ internal fun ToolStatusRow( color = if (emphasized) { MaterialTheme.colorScheme.surfaceVariant } else { - Color.Transparent + bitFunColors.transparent }, shape = RoundedCornerShape(if (emphasized) 14.dp else 8.dp), ) .border( width = if (emphasized) 1.dp else 0.dp, - color = if (emphasized) MaterialTheme.colorScheme.outlineVariant else Color.Transparent, + color = if (emphasized) MaterialTheme.colorScheme.outlineVariant else bitFunColors.transparent, shape = RoundedCornerShape(if (emphasized) 14.dp else 8.dp), ) .padding( diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/common/AdaptiveModalSurface.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/common/AdaptiveModalSurface.kt index 9da8e461a9..f4a510430a 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/common/AdaptiveModalSurface.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/common/AdaptiveModalSurface.kt @@ -58,7 +58,7 @@ internal fun AdaptiveModalSurface( Box( modifier = Modifier .fillMaxSize() - .background(bitFunColors.modalScrim) + .background(MaterialTheme.colorScheme.scrim) .clickable(onClick = onDismissRequest) .safeDrawingPadding() .imePadding(), diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/ConnectAccountDeviceScreen.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/ConnectAccountDeviceScreen.kt index b1793135a0..9d113a8849 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/ConnectAccountDeviceScreen.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/ConnectAccountDeviceScreen.kt @@ -260,7 +260,7 @@ private fun DeviceListCard( ), fontSize = 13.sp, color = if (device.online) { - bitFunColors.success + bitFunColors.statusSuccess } else { MaterialTheme.colorScheme.onSurfaceVariant }, diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/ConnectView.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/ConnectView.kt index 9e74e45599..d4cd8122ea 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/ConnectView.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/ConnectView.kt @@ -343,7 +343,7 @@ private fun ManualPairing( val consumeTouches = remember { MutableInteractionSource() } Box( modifier = modifier - .background(bitFunColors.modalScrim) + .background(MaterialTheme.colorScheme.scrim) .clickable(enabled = !connecting, onClick = onBack), contentAlignment = Alignment.Center, ) { @@ -525,7 +525,7 @@ private fun CameraFrame() { modifier = Modifier .size(282.dp) .clip(RoundedCornerShape(40.dp)) - .background(Color.Black.copy(alpha = 0.10f)), + .background(bitFunColors.shadowMedium), ) { ScanCorner(accent, Alignment.TopStart, true, true) ScanCorner(accent, Alignment.TopEnd, false, true) diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/RemoteSessionListView.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/RemoteSessionListView.kt index a6c5e5cea2..e23c5b9e2e 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/RemoteSessionListView.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/remote/RemoteSessionListView.kt @@ -39,7 +39,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.geometry.Rect import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned @@ -73,6 +72,7 @@ import com.bitfun.mobile.core.feature.session.SessionWorkspaceContext import com.bitfun.mobile.core.feature.workspace.RemoteWorkspaceIntent import com.bitfun.mobile.core.feature.workspace.RemoteWorkspaceUiState import kotlinx.coroutines.delay +import com.bitfun.mobile.app.ui.theme.bitFunColors internal const val SESSION_LIST_TEST_TAG: String = "session-list" internal const val SESSION_PROJECTS_TEST_TAG: String = "session-projects" @@ -786,7 +786,7 @@ private fun SessionRow( .heightIn(min = if (metadata.isEmpty()) 46.dp else 56.dp) .clip(RoundedCornerShape(10.dp)) .background( - if (selected) MaterialTheme.colorScheme.secondaryContainer else Color.Transparent, + if (selected) MaterialTheme.colorScheme.secondaryContainer else bitFunColors.transparent, ) .onGloballyPositioned { coordinates -> anchorBounds = coordinates.boundsInWindow().toIntRect() diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/settings/ModelServiceScreen.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/settings/ModelServiceScreen.kt index 09d6034782..5d271d7bb8 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/settings/ModelServiceScreen.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/settings/ModelServiceScreen.kt @@ -421,7 +421,7 @@ private fun AccountModelSelection( .clip(RoundedCornerShape(9.dp)) .background( if (model.id == activeModelId) MaterialTheme.colorScheme.surfaceVariant - else Color.Transparent, + else bitFunColors.transparent, ) .clickable { onSelect(model.id) } .padding(horizontal = 10.dp), @@ -791,7 +791,7 @@ private fun LocalModelEditor( Text( stringResource(R.string.model_service_test_success), style = MaterialTheme.typography.bodySmall, - color = bitFunColors.success, + color = bitFunColors.statusSuccess, ) } } @@ -849,9 +849,9 @@ private fun SoftTextField( focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant, disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant, - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, + focusedIndicatorColor = bitFunColors.transparent, + unfocusedIndicatorColor = bitFunColors.transparent, + disabledIndicatorColor = bitFunColors.transparent, ), modifier = modifier.fillMaxWidth().defaultMinSize(minHeight = 48.dp), ) diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/AppSidebar.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/AppSidebar.kt index 5c08b4cb75..da99575b77 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/AppSidebar.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/AppSidebar.kt @@ -24,7 +24,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.IntRect import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.painterResource diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarChrome.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarChrome.kt index 2d3c7899ce..ee541496f8 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarChrome.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarChrome.kt @@ -66,7 +66,7 @@ internal fun ConnectionDot(phase: ConnectionPhase) { // BUSY is the one addition, because a dot that only ever goes green or grey // cannot say "connecting" while it is still trying. val color: Color = when (tone) { - ConnectionTone.OK -> bitFunColors.success + ConnectionTone.OK -> bitFunColors.statusSuccess ConnectionTone.BUSY -> MaterialTheme.colorScheme.tertiary ConnectionTone.ERROR -> MaterialTheme.colorScheme.error ConnectionTone.MUTED -> MaterialTheme.colorScheme.onSurfaceVariant diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarRemoteWorkspaceSection.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarRemoteWorkspaceSection.kt index ea65f2138d..ec15e7401d 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarRemoteWorkspaceSection.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarRemoteWorkspaceSection.kt @@ -30,7 +30,6 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Rect -import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.testTag @@ -53,6 +52,7 @@ import com.bitfun.mobile.core.feature.shell.RemoteSidebarSessionRow import com.bitfun.mobile.core.feature.shell.RemoteSidebarWorkspaceRow import com.bitfun.mobile.core.feature.session.RemoteSessionUiState import com.bitfun.mobile.core.feature.workspace.RemoteWorkspaceUiState +import com.bitfun.mobile.app.ui.theme.bitFunColors private const val SESSIONS_PER_WORKSPACE = 3 private const val WORKSPACES_PER_BATCH = 3 @@ -629,7 +629,7 @@ private fun RemoteSessionRow( .fillMaxWidth() .height(44.dp) .clip(RoundedCornerShape(10.dp)) - .background(if (selected) MaterialTheme.colorScheme.surfaceVariant else Color.Transparent) + .background(if (selected) MaterialTheme.colorScheme.surfaceVariant else bitFunColors.transparent) .onGloballyPositioned { coordinates -> anchorBounds = coordinates.boundsInWindow().toIntRect() } diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarSessionList.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarSessionList.kt index 64d4af54e9..ccaca14a1d 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarSessionList.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/shell/sidebar/SidebarSessionList.kt @@ -26,7 +26,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.geometry.Rect import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned @@ -45,6 +44,7 @@ import androidx.compose.ui.unit.sp import com.bitfun.mobile.app.R import com.bitfun.mobile.core.feature.shell.SidebarSections import com.bitfun.mobile.core.feature.shell.SidebarSessionRow +import com.bitfun.mobile.app.ui.theme.bitFunColors internal const val SIDEBAR_PINNED_TEST_TAG: String = "app-sidebar-pinned" internal const val SIDEBAR_ARCHIVED_TEST_TAG: String = "app-sidebar-archived" @@ -186,7 +186,7 @@ private fun SessionRow( .fillMaxWidth() .height(44.dp) .clip(RoundedCornerShape(10.dp)) - .background(if (selected) MaterialTheme.colorScheme.surfaceVariant else Color.Transparent) + .background(if (selected) MaterialTheme.colorScheme.surfaceVariant else bitFunColors.transparent) .onGloballyPositioned { coordinates -> anchorBounds = coordinates.boundsInWindow().toIntRect() } @@ -252,7 +252,7 @@ private fun ArchivedDisclosureRow(count: Int, expanded: Boolean, onToggle: () -> .padding(top = 8.dp) .height(46.dp) .clip(RoundedCornerShape(10.dp)) - .background(if (expanded) MaterialTheme.colorScheme.surfaceVariant else Color.Transparent) + .background(if (expanded) MaterialTheme.colorScheme.surfaceVariant else bitFunColors.transparent) .clickable(role = Role.Button, onClick = onToggle) .semantics(mergeDescendants = true) { contentDescription = archivedLabel diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/theme/Theme.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/theme/Theme.kt index 1012bb44ed..644f5ef927 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/theme/Theme.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/theme/Theme.kt @@ -30,21 +30,21 @@ private val LightTokens = MobileDesignColors.Light private val DarkTokens = MobileDesignColors.Dark private val InkLight = LightTokens.Ink private val InkDark = DarkTokens.Ink -private val White = LightTokens.PrimaryActionText +private val ContentOnAction = LightTokens.ContentOnAction private val LightScheme = lightColorScheme( primary = LightTokens.PrimaryAction, - onPrimary = White, // primary_action_text + onPrimary = ContentOnAction, primaryContainer = LightTokens.Soft, onPrimaryContainer = InkLight, secondary = LightTokens.Accent, - onSecondary = White, + onSecondary = ContentOnAction, secondaryContainer = LightTokens.Soft, onSecondaryContainer = InkLight, // file_link: the one saturated hue in the palette. Material has no link // role, so it lands on tertiary — which is also the "busy" connection dot. tertiary = LightTokens.FileLink, - onTertiary = White, + onTertiary = ContentOnAction, background = LightTokens.PageBg, onBackground = InkLight, surface = LightTokens.Card, @@ -72,21 +72,22 @@ private val LightScheme = lightColorScheme( inversePrimary = LightTokens.Line, outline = LightTokens.Subtle, outlineVariant = LightTokens.Line, - error = LightTokens.Red, - onError = White, + error = LightTokens.StatusDanger, + onError = ContentOnAction, // The HarmonyOS palette has no error container; rather than invent a hue, // a failure card is the same soft surface with the error colour on it. errorContainer = LightTokens.Soft, - onErrorContainer = LightTokens.Red, + onErrorContainer = LightTokens.StatusDanger, + scrim = LightTokens.Scrim, ) private val DarkScheme = darkColorScheme( primary = DarkTokens.PrimaryAction, - onPrimary = White, + onPrimary = ContentOnAction, primaryContainer = DarkTokens.Soft, onPrimaryContainer = InkDark, secondary = DarkTokens.Accent, - onSecondary = White, + onSecondary = ContentOnAction, secondaryContainer = DarkTokens.Soft, onSecondaryContainer = InkDark, tertiary = DarkTokens.FileLink, @@ -110,10 +111,11 @@ private val DarkScheme = darkColorScheme( inversePrimary = DarkTokens.Line, outline = DarkTokens.Subtle, outlineVariant = DarkTokens.Line, - error = DarkTokens.Red, - onError = White, + error = DarkTokens.StatusDanger, + onError = ContentOnAction, errorContainer = DarkTokens.Soft, - onErrorContainer = DarkTokens.Red, + onErrorContainer = DarkTokens.StatusDanger, + scrim = DarkTokens.Scrim, ) /** @@ -123,8 +125,17 @@ private val DarkScheme = darkColorScheme( * because primary here is near-black ink and a black dot reads as "off". */ internal data class BitFunColors( - val success: Color, - val modalScrim: Color, + val transparent: Color, + val statusSuccess: Color, + val shellScrim: Color, + val mediaBackground: Color, + val mediaScrim: Color, + val mediaControlBackground: Color, + val toastBackground: Color, + val shadowSubtle: Color, + val shadowMedium: Color, + val shadowStrong: Color, + val floatingBorder: Color, val heroBackground: Color, val heroSurface: Color, val heroAccent: Color, @@ -154,8 +165,17 @@ internal data class CodeSyntaxColors( ) private val LightExtras = BitFunColors( - success = LightTokens.Green, - modalScrim = LightTokens.ModalScrim, + transparent = LightTokens.Transparent, + statusSuccess = LightTokens.StatusSuccess, + shellScrim = LightTokens.ShellScrim, + mediaBackground = LightTokens.MediaBackground, + mediaScrim = LightTokens.MediaScrim, + mediaControlBackground = LightTokens.MediaControlBackground, + toastBackground = LightTokens.ToastBackground, + shadowSubtle = LightTokens.ShadowSubtle, + shadowMedium = LightTokens.ShadowMedium, + shadowStrong = LightTokens.ShadowStrong, + floatingBorder = LightTokens.FloatingBorder, heroBackground = LightTokens.ConnectHeroBg, heroSurface = LightTokens.ConnectHeroSurface, heroAccent = LightTokens.ConnectHeroAccent, @@ -175,8 +195,17 @@ private val LightExtras = BitFunColors( ) private val DarkExtras = BitFunColors( - success = DarkTokens.Green, - modalScrim = DarkTokens.ModalScrim, + transparent = DarkTokens.Transparent, + statusSuccess = DarkTokens.StatusSuccess, + shellScrim = DarkTokens.ShellScrim, + mediaBackground = DarkTokens.MediaBackground, + mediaScrim = DarkTokens.MediaScrim, + mediaControlBackground = DarkTokens.MediaControlBackground, + toastBackground = DarkTokens.ToastBackground, + shadowSubtle = DarkTokens.ShadowSubtle, + shadowMedium = DarkTokens.ShadowMedium, + shadowStrong = DarkTokens.ShadowStrong, + floatingBorder = DarkTokens.FloatingBorder, heroBackground = DarkTokens.ConnectHeroBg, heroSurface = DarkTokens.ConnectHeroSurface, heroAccent = DarkTokens.ConnectHeroAccent, diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/theme/generated/MobileDesignTokens.kt b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/theme/generated/MobileDesignTokens.kt index a6460f8f59..f3ae76fe96 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/theme/generated/MobileDesignTokens.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/bitfun/mobile/app/ui/theme/generated/MobileDesignTokens.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.unit.sp internal object MobileDesignColors { object Light { val StartWindowBackground = Color(0xFFFFFFFF) + val Transparent = Color(0x00000000) val PageBg = Color(0xFFFFFFFF) val PageBgFade = Color(0x00FFFFFF) val Ink = Color(0xFF171717) @@ -20,17 +21,27 @@ internal object MobileDesignColors { val Accent = Color(0xFF111111) val FileLink = Color(0xFF2563EB) val PrimaryAction = Color(0xFF111111) - val PrimaryActionText = Color(0xFFFFFFFF) + val ContentOnAction = Color(0xFFFFFFFF) val ConnectHeroBg = Color(0xFFE6EDFF) val ConnectHeroAccent = Color(0xFF9DB4FF) val ConnectHeroSecondary = Color(0xFFC9C5FF) val ConnectHeroSurface = Color(0xFFF8FAFF) val ConnectScanAccent = Color(0xFFFFD021) - val ModalScrim = Color(0x44000000) + val Scrim = Color(0x44000000) + val ShellScrim = Color(0x24000000) + val MediaBackground = Color(0xFF000000) + val MediaScrim = Color(0xB8000000) + val MediaControlBackground = Color(0x8C000000) + val ToastBackground = Color(0xD1171717) + val ShadowFaint = Color(0x08000000) + val ShadowSubtle = Color(0x12000000) + val ShadowMedium = Color(0x18000000) + val ShadowStrong = Color(0x24000000) + val FloatingBorder = Color(0x18000000) val Soft = Color(0xFFF4F3F0) val FloatingPanelBg = Color(0xFFF7F7F5) - val Green = Color(0xFF27C46A) - val Red = Color(0xFFE04F4F) + val StatusSuccess = Color(0xFF27C46A) + val StatusDanger = Color(0xFFE04F4F) val CodeLineNumber = Color(0xFFAAA69D) val CodeKeyword = Color(0xFF8F3F71) val CodeString = Color(0xFF477A4A) @@ -45,6 +56,7 @@ internal object MobileDesignColors { object Dark { val StartWindowBackground = Color(0xFF000000) + val Transparent = Color(0x00000000) val PageBg = Color(0xFF151514) val PageBgFade = Color(0x00151514) val Ink = Color(0xFFF4F3EF) @@ -55,17 +67,27 @@ internal object MobileDesignColors { val Accent = Color(0xFF5B5954) val FileLink = Color(0xFF60A5FA) val PrimaryAction = Color(0xFF454540) - val PrimaryActionText = Color(0xFFFFFFFF) + val ContentOnAction = Color(0xFFFFFFFF) val ConnectHeroBg = Color(0xFF2B2B29) val ConnectHeroAccent = Color(0xFF4A4944) val ConnectHeroSecondary = Color(0xFF3C3B38) val ConnectHeroSurface = Color(0xFF252522) val ConnectScanAccent = Color(0xFFFFD021) - val ModalScrim = Color(0x44000000) + val Scrim = Color(0x44000000) + val ShellScrim = Color(0x24000000) + val MediaBackground = Color(0xFF000000) + val MediaScrim = Color(0xB8000000) + val MediaControlBackground = Color(0x8C000000) + val ToastBackground = Color(0xD1171717) + val ShadowFaint = Color(0x08000000) + val ShadowSubtle = Color(0x12000000) + val ShadowMedium = Color(0x18000000) + val ShadowStrong = Color(0x24000000) + val FloatingBorder = Color(0x18000000) val Soft = Color(0xFF2D2C28) val FloatingPanelBg = Color(0xFF1E1E1C) - val Green = Color(0xFF3BD47B) - val Red = Color(0xFFFF6B6B) + val StatusSuccess = Color(0xFF3BD47B) + val StatusDanger = Color(0xFFFF6B6B) val CodeLineNumber = Color(0xFF77756E) val CodeKeyword = Color(0xFFD99AC4) val CodeString = Color(0xFF9BCB9D) diff --git a/src/apps/mobile/design-system/components/mobile-components.json b/src/apps/mobile/design-system/components/mobile-components.json index b34ef604b9..66f1945e78 100644 --- a/src/apps/mobile/design-system/components/mobile-components.json +++ b/src/apps/mobile/design-system/components/mobile-components.json @@ -12,7 +12,7 @@ "purpose": "Expresses one primary, secondary, quiet, or destructive workflow action with consistent emphasis.", "anatomy": ["touch_target", "action_label", "semantic_surface", "optional_hairline_border"], "states": ["primary", "secondary", "quiet", "destructive", "disabled", "busy"], - "tokens": ["sheet_action_height", "primary_action", "primary_action_text", "card", "soft", "line", "red", "label_large"], + "tokens": ["sheet_action_height", "primary_action", "content_on_action", "card", "soft", "line", "status_danger", "label_large"], "platformNotes": "The semantic style is shared; a workflow may override height when its context requires a larger target, while preserving typography, radius, color, and disabled treatment." }, "conversation_header": { @@ -45,9 +45,9 @@ }, "adaptive_modal_surface": { "purpose": "Hosts settings, connection, creation, selection, and detail flows without crossing a physical fold or obscuring more of the workspace than necessary.", - "anatomy": ["modal_scrim", "paper_surface", "header", "scroll_content", "action_rail"], + "anatomy": ["scrim", "paper_surface", "header", "scroll_content", "action_rail"], "states": ["compact_bottom", "wide_side", "fold_operate", "busy", "error"], - "tokens": ["modal_scrim", "sheet_top_radius", "sheet_side_radius", "sheet_horizontal_padding", "sheet_header_height", "sheet_action_height", "card", "line", "structure"], + "tokens": ["scrim", "sheet_top_radius", "sheet_side_radius", "sheet_horizontal_padding", "sheet_header_height", "sheet_action_height", "card", "line", "structure"], "platformNotes": "Use each platform's native modal lifecycle, accessibility focus, and back gesture; placement comes from the shared adaptive policy and visual geometry comes from these tokens." }, "action_popover": { @@ -61,7 +61,7 @@ "purpose": "Presents actions for a session row without stacking confirmation UI.", "anatomy": ["optional_drag_handle", "session_identity", "action_rows", "in_place_confirmation"], "states": ["compact_bottom", "wide_popover", "confirming_delete", "busy"], - "tokens": ["sheet_action_height", "popover_radius", "card", "line", "soft", "red"], + "tokens": ["sheet_action_height", "popover_radius", "card", "line", "soft", "status_danger"], "platformNotes": "Compact session lists use a transparent native sheet hosting the same 16-unit paper surface that wide lists anchor as a popover; deletion confirmation replaces the action rows in place. This is distinct from the active conversation header's action_popover." }, "selection_surface": { @@ -75,7 +75,7 @@ "purpose": "Confirms destructive or high-impact actions inside the surface that initiated them.", "anatomy": ["specific_consequence", "cancel_action", "destructive_action"], "states": ["idle", "confirming", "submitting", "failed"], - "tokens": ["sheet_action_height", "red", "soft", "line"], + "tokens": ["sheet_action_height", "status_danger", "soft", "line"], "platformNotes": "Prefer an in-place confirmation step over stacking a second modal and a second scrim." }, "settings_card": { @@ -103,7 +103,7 @@ "purpose": "Guides desktop pairing from preparation through scanning, with a manual-code fallback that stays inside the connect surface.", "anatomy": ["hero_wash", "back_control", "desktop_or_scanner_glyph", "instructions", "primary_action", "manual_pairing_overlay", "conditional_account_credentials", "status_feedback"], "states": ["intro", "scan", "manual", "account_auth", "connecting", "failed", "paired"], - "tokens": ["connect_hero_bg", "connect_hero_surface", "modal_scrim", "sheet_side_radius", "primary_action", "card", "soft", "line"], + "tokens": ["connect_hero_bg", "connect_hero_surface", "scrim", "sheet_side_radius", "primary_action", "card", "soft", "line"], "platformNotes": "Camera capture and permission prompts remain native. The manual form is an in-surface overlay with the shared scrim and 34-unit card, not a second system sheet. Account-protected links add username and password fields in that same card; passwords remain transient view state and are cleared on submit or dismiss." }, "remote_create_surface": { @@ -117,7 +117,7 @@ "purpose": "Explains which desktop is being controlled, how it is connected, and which permission policy that desktop applies.", "anatomy": ["modal_header", "profile_entry", "current_control_card", "connection_source", "alternate_connection_entry", "permission_mode_card", "in_place_full_access_confirmation"], "states": ["disconnected", "connecting", "connected_by_account", "connected_by_pairing", "permission_loading", "permission_failed", "confirming_full_access", "account_page"], - "tokens": ["sheet_header_height", "settings_prominent_card_radius", "settings_compact_card_radius", "modal_scrim", "card", "soft", "line", "red"], + "tokens": ["sheet_header_height", "settings_prominent_card_radius", "settings_compact_card_radius", "scrim", "card", "soft", "line", "status_danger"], "platformNotes": "The account page replaces this page inside the same adaptive modal. Full-access confirmation replaces content inside the permission card; it never opens a system alert or a second sheet." }, "file_preview_surface": { diff --git a/src/apps/mobile/design-system/preview/generated/mobile-design-data.js b/src/apps/mobile/design-system/preview/generated/mobile-design-data.js index ae3635f005..9536156582 100644 --- a/src/apps/mobile/design-system/preview/generated/mobile-design-data.js +++ b/src/apps/mobile/design-system/preview/generated/mobile-design-data.js @@ -10,6 +10,10 @@ export const mobileTokens = { "light": "#FFFFFF", "dark": "#000000" }, + "transparent": { + "light": "#00000000", + "dark": "#00000000" + }, "page_bg": { "light": "#FFFFFF", "dark": "#151514" @@ -50,7 +54,7 @@ export const mobileTokens = { "light": "#111111", "dark": "#454540" }, - "primary_action_text": { + "content_on_action": { "light": "#FFFFFF", "dark": "#FFFFFF" }, @@ -74,10 +78,50 @@ export const mobileTokens = { "light": "#FFD021", "dark": "#FFD021" }, - "modal_scrim": { + "scrim": { "light": "#44000000", "dark": "#44000000" }, + "shell_scrim": { + "light": "#24000000", + "dark": "#24000000" + }, + "media_background": { + "light": "#FF000000", + "dark": "#FF000000" + }, + "media_scrim": { + "light": "#B8000000", + "dark": "#B8000000" + }, + "media_control_background": { + "light": "#8C000000", + "dark": "#8C000000" + }, + "toast_background": { + "light": "#D1171717", + "dark": "#D1171717" + }, + "shadow_faint": { + "light": "#08000000", + "dark": "#08000000" + }, + "shadow_subtle": { + "light": "#12000000", + "dark": "#12000000" + }, + "shadow_medium": { + "light": "#18000000", + "dark": "#18000000" + }, + "shadow_strong": { + "light": "#24000000", + "dark": "#24000000" + }, + "floating_border": { + "light": "#18000000", + "dark": "#18000000" + }, "soft": { "light": "#F4F3F0", "dark": "#2D2C28" @@ -86,11 +130,11 @@ export const mobileTokens = { "light": "#F7F7F5", "dark": "#1E1E1C" }, - "green": { + "status_success": { "light": "#27C46A", "dark": "#3BD47B" }, - "red": { + "status_danger": { "light": "#E04F4F", "dark": "#FF6B6B" }, @@ -328,11 +372,11 @@ export const mobileComponents = { "tokens": [ "sheet_action_height", "primary_action", - "primary_action_text", + "content_on_action", "card", "soft", "line", - "red", + "status_danger", "label_large" ], "platformNotes": "The semantic style is shared; a workflow may override height when its context requires a larger target, while preserving typography, radius, color, and disabled treatment." @@ -443,7 +487,7 @@ export const mobileComponents = { "adaptive_modal_surface": { "purpose": "Hosts settings, connection, creation, selection, and detail flows without crossing a physical fold or obscuring more of the workspace than necessary.", "anatomy": [ - "modal_scrim", + "scrim", "paper_surface", "header", "scroll_content", @@ -457,7 +501,7 @@ export const mobileComponents = { "error" ], "tokens": [ - "modal_scrim", + "scrim", "sheet_top_radius", "sheet_side_radius", "sheet_horizontal_padding", @@ -519,7 +563,7 @@ export const mobileComponents = { "card", "line", "soft", - "red" + "status_danger" ], "platformNotes": "Compact session lists use a transparent native sheet hosting the same 16-unit paper surface that wide lists anchor as a popover; deletion confirmation replaces the action rows in place. This is distinct from the active conversation header's action_popover." }, @@ -565,7 +609,7 @@ export const mobileComponents = { ], "tokens": [ "sheet_action_height", - "red", + "status_danger", "soft", "line" ], @@ -683,7 +727,7 @@ export const mobileComponents = { "tokens": [ "connect_hero_bg", "connect_hero_surface", - "modal_scrim", + "scrim", "sheet_side_radius", "primary_action", "card", @@ -748,11 +792,11 @@ export const mobileComponents = { "sheet_header_height", "settings_prominent_card_radius", "settings_compact_card_radius", - "modal_scrim", + "scrim", "card", "soft", "line", - "red" + "status_danger" ], "platformNotes": "The account page replaces this page inside the same adaptive modal. Full-access confirmation replaces content inside the permission card; it never opens a system alert or a second sheet." }, diff --git a/src/apps/mobile/design-system/preview/index.html b/src/apps/mobile/design-system/preview/index.html index 113418417e..5fbd430c07 100644 --- a/src/apps/mobile/design-system/preview/index.html +++ b/src/apps/mobile/design-system/preview/index.html @@ -1,9 +1,11 @@ - + BitFun Mobile Parity Bench + + diff --git a/src/apps/mobile/design-system/preview/preview.css b/src/apps/mobile/design-system/preview/preview.css index fd8d1f8c40..33fe204b36 100644 --- a/src/apps/mobile/design-system/preview/preview.css +++ b/src/apps/mobile/design-system/preview/preview.css @@ -1,8 +1,8 @@ :root { color-scheme: light; - font-family: Inter, "SF Pro Text", "HarmonyOS Sans", system-ui, sans-serif; - background: #efeee9; - color: #171717; + font-family: var(--bf-font-family-sans); + background: var(--bf-color-surface-workbench); + color: var(--bf-color-content-primary); } * { box-sizing: border-box; } @@ -12,8 +12,8 @@ body { min-width: 1040px; min-height: 100vh; background: - linear-gradient(#0000 31px, rgb(23 23 23 / 0.035) 32px), - #efeee9; + linear-gradient(transparent 31px, color-mix(in srgb, var(--bf-color-content-primary) 3.5%, transparent) 32px), + var(--bf-color-surface-workbench); background-size: 100% 32px; } @@ -35,8 +35,8 @@ button, input, select { font: inherit; } .eyebrow { margin: 0 0 11px; - color: #706f6a; - font: 600 11px/1.2 ui-monospace, "SFMono-Regular", monospace; + color: var(--bf-color-content-muted); + font: 600 11px/1.2 var(--bf-font-family-mono); letter-spacing: 0.13em; } @@ -50,7 +50,7 @@ h1 { .intro { max-width: 720px; margin: 13px 0 0; - color: #595853; + color: var(--bf-color-content-secondary); font-size: 14px; line-height: 1.7; } @@ -60,19 +60,19 @@ h1 { align-items: center; gap: 9px; padding: 9px 12px; - border: 1px solid #d9d7d1; + border: 1px solid var(--bf-color-border-default); border-radius: 999px; - background: #f7f7f5; - color: #4b4a46; - font: 600 11px/1 ui-monospace, monospace; + background: var(--bf-color-surface-panel); + color: var(--bf-color-content-secondary); + font: 600 11px/1 var(--bf-font-family-mono); } .baseline-key span { width: 8px; height: 8px; border-radius: 50%; - background: #2563eb; - box-shadow: 0 0 0 4px rgb(37 99 235 / 0.13); + background: var(--bf-color-link-default); + box-shadow: 0 0 0 4px color-mix(in srgb, var(--bf-color-link-default) 13%, transparent); } .toolbar { @@ -81,9 +81,9 @@ h1 { gap: 18px; align-items: end; padding: 18px 20px; - border: 1px solid #d9d7d1; + border: 1px solid var(--bf-color-border-default); border-radius: 18px 18px 0 0; - background: rgb(253 253 251 / 0.9); + background: color-mix(in srgb, var(--bf-color-surface-panel) 90%, transparent); backdrop-filter: blur(16px); } @@ -93,8 +93,8 @@ h1 { } .toolbar label > span { - color: #706f6a; - font: 600 11px/1.2 ui-monospace, monospace; + color: var(--bf-color-content-muted); + font: 600 11px/1.2 var(--bf-font-family-mono); letter-spacing: 0.05em; } @@ -102,10 +102,10 @@ select { width: 100%; height: 38px; padding: 0 34px 0 12px; - border: 1px solid #d9d7d1; + border: 1px solid var(--bf-color-field-border); border-radius: 10px; - background: #fff; - color: #171717; + background: var(--bf-color-field-background); + color: var(--bf-color-content-primary); } .range-control { @@ -113,8 +113,8 @@ select { } .range-control span { grid-column: 1 / -1; } -.range-control input { width: 100%; accent-color: #171717; } -.range-control output { color: #706f6a; font: 12px ui-monospace, monospace; } +.range-control input { width: 100%; accent-color: var(--bf-color-accent-default); } +.range-control output { color: var(--bf-color-content-muted); font: 12px var(--bf-font-family-mono); } .check-control { display: flex; @@ -124,7 +124,7 @@ select { white-space: nowrap; } -.check-control input { width: 16px; height: 16px; accent-color: #171717; } +.check-control input { width: 16px; height: 16px; accent-color: var(--bf-color-accent-default); } .scenario-note { display: flex; @@ -132,14 +132,14 @@ select { align-items: baseline; min-height: 46px; padding: 14px 20px; - border: 1px solid #d9d7d1; + border: 1px solid var(--bf-color-border-default); border-top: 0; - background: #f7f7f5; - color: #706f6a; + background: var(--bf-color-surface-panel); + color: var(--bf-color-content-muted); font-size: 12px; } -.scenario-note strong { color: #171717; } +.scenario-note strong { color: var(--bf-color-content-primary); } .platform-grid { display: grid; @@ -151,13 +151,13 @@ select { .platform-card { min-width: 0; overflow: hidden; - border: 1px solid #d3d1cb; + border: 1px solid var(--bf-color-border-default); border-radius: 20px; - background: #fdfdfb; - box-shadow: 0 18px 50px rgb(23 23 23 / 0.07); + background: var(--bf-color-surface-panel); + box-shadow: var(--bf-shadow-overlay); } -.platform-card[data-platform="harmonyos"] { border-top: 3px solid #2563eb; } +.platform-card[data-platform="harmonyos"] { border-top: 3px solid var(--bf-color-link-default); } .platform-heading { display: flex; @@ -165,7 +165,7 @@ select { gap: 10px; min-height: 62px; padding: 12px 15px; - border-bottom: 1px solid #e9e7e2; + border-bottom: 1px solid var(--bf-color-border-subtle); } .platform-mark { @@ -174,29 +174,29 @@ select { width: 34px; height: 34px; border-radius: 10px; - background: #171717; - color: #fff; - font: 700 12px/1 ui-monospace, monospace; + background: var(--bf-color-action-primary-background); + color: var(--bf-color-action-primary-content); + font: 700 12px/1 var(--bf-font-family-mono); } -.platform-card[data-platform="harmonyos"] .platform-mark { background: #2563eb; } +.platform-card[data-platform="harmonyos"] .platform-mark { background: var(--bf-color-link-default); } .platform-title { min-width: 0; } .platform-title strong { display: block; font-size: 13px; } -.platform-title span { display: block; margin-top: 3px; color: #7d7b75; font-size: 10px; } +.platform-title span { display: block; margin-top: 3px; color: var(--bf-color-content-muted); font-size: 10px; } .capture-button { margin-left: auto; padding: 8px 10px; - border: 1px solid #d9d7d1; + border: 1px solid var(--bf-color-border-default); border-radius: 9px; - background: #fff; - color: #45443f; + background: var(--bf-color-field-background); + color: var(--bf-color-content-secondary); cursor: pointer; font-size: 11px; } -.capture-button:hover { border-color: #a5a39b; } +.capture-button:hover { border-color: var(--bf-color-field-border-hover); } .capture-button input { display: none; } .viewport-stage { @@ -206,7 +206,7 @@ select { min-height: 690px; padding: 22px; overflow: hidden; - background: #e9e7e2; + background: var(--bf-color-surface-subtle); } .device-screen { @@ -216,11 +216,11 @@ select { aspect-ratio: var(--viewport-width) / var(--viewport-height); max-height: 646px; overflow: hidden; - border: 1px solid rgb(23 23 23 / 0.25); + border: 1px solid color-mix(in srgb, var(--bf-color-content-primary) 25%, transparent); border-radius: 28px; - background: var(--page-bg); - color: var(--ink); - box-shadow: 0 20px 60px rgb(23 23 23 / 0.18); + background: var(--mobile-page-bg); + color: var(--mobile-ink); + box-shadow: var(--bf-shadow-overlay); container-type: inline-size; } @@ -245,111 +245,111 @@ select { display: flex; align-items: center; gap: 6px; - height: calc(var(--connection-strip-height) * 1px); - padding: 0 calc(var(--content-gutter) * 1px); - border-bottom: 1px solid var(--line); + height: calc(var(--mobile-connection-strip-height) * 1px); + padding: 0 calc(var(--mobile-content-gutter) * 1px); + border-bottom: 1px solid var(--mobile-line); font-size: 11px; } .screen-meta strong { font-size: 12px; } -.screen-meta span { margin-left: auto; color: var(--muted); font-family: ui-monospace, monospace; font-size: 9px; } +.screen-meta span { margin-left: auto; color: var(--mobile-muted); font-family: ui-monospace, monospace; font-size: 9px; } .conversation-header { display: grid; - grid-template-columns: calc(var(--control-touch-size) * 1px) 1fr calc(var(--control-touch-size) * 1px); + grid-template-columns: calc(var(--mobile-control-touch-size) * 1px) 1fr calc(var(--mobile-control-touch-size) * 1px); align-items: center; gap: 8px; - height: calc(var(--conversation-header-height) * 1px); - padding: 8px calc(var(--content-gutter) * 1px); + height: calc(var(--mobile-conversation-header-height) * 1px); + padding: 8px calc(var(--mobile-content-gutter) * 1px); } .circle-control { display: grid; place-items: center; - width: calc(var(--control-touch-size) * 1px); - height: calc(var(--control-touch-size) * 1px); - border: 1px solid var(--line); + width: calc(var(--mobile-control-touch-size) * 1px); + height: calc(var(--mobile-control-touch-size) * 1px); + border: 1px solid var(--mobile-line); border-radius: 50%; - background: var(--card); - box-shadow: 0 3px 10px rgb(23 23 23 / 0.08); - color: var(--ink); + background: var(--mobile-card); + box-shadow: 0 3px 10px var(--mobile-shadow-medium); + color: var(--mobile-ink); font-size: 18px; } .header-copy { min-width: 0; text-align: center; } .header-copy strong, .header-copy span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .header-copy strong { - font-size: calc(var(--conversation-header-title-size) * 1px); - line-height: calc(var(--conversation-header-title-line-height) * 1px); - font-weight: var(--conversation-header-title-weight); + font-size: calc(var(--mobile-conversation-header-title-size) * 1px); + line-height: calc(var(--mobile-conversation-header-title-line-height) * 1px); + font-weight: var(--mobile-conversation-header-title-weight); } .header-copy span { margin-top: 3px; - color: var(--muted); - font-size: calc(var(--label-medium-size) * 1px); - line-height: calc(var(--label-medium-line-height) * 1px); - font-weight: var(--label-medium-weight); + color: var(--mobile-muted); + font-size: calc(var(--mobile-label-medium-size) * 1px); + line-height: calc(var(--mobile-label-medium-line-height) * 1px); + font-weight: var(--mobile-label-medium-weight); } .timeline { flex: 1; display: flex; flex-direction: column; - gap: calc(var(--message-spacing) * 1px); + gap: calc(var(--mobile-message-spacing) * 1px); min-height: 0; - padding: calc(var(--timeline-top-padding) * 1px) calc(var(--content-gutter) * 1px); + padding: calc(var(--mobile-timeline-top-padding) * 1px) calc(var(--mobile-content-gutter) * 1px); } .message { - max-width: calc(var(--message-bubble-max-width) * 1px); + max-width: calc(var(--mobile-message-bubble-max-width) * 1px); padding: - calc(var(--message-bubble-vertical-padding) * 1px) - calc(var(--message-bubble-horizontal-padding) * 1px); - border: 1px solid var(--line); - border-radius: calc(var(--message-bubble-radius) * 1px); - background: var(--card); - font-size: calc(var(--body-medium-size) * 1px); - line-height: calc(var(--body-medium-line-height) * 1px); - font-weight: var(--body-medium-weight); + calc(var(--mobile-message-bubble-vertical-padding) * 1px) + calc(var(--mobile-message-bubble-horizontal-padding) * 1px); + border: 1px solid var(--mobile-line); + border-radius: calc(var(--mobile-message-bubble-radius) * 1px); + background: var(--mobile-card); + font-size: calc(var(--mobile-body-medium-size) * 1px); + line-height: calc(var(--mobile-body-medium-line-height) * 1px); + font-weight: var(--mobile-body-medium-weight); } -.message.user { align-self: flex-end; background: var(--soft); } +.message.user { align-self: flex-end; background: var(--mobile-soft); } .connection-note { align-self: center; padding: 5px 9px; border-radius: 999px; - background: var(--soft); - color: var(--muted); + background: var(--mobile-soft); + color: var(--mobile-muted); font: 10px/1.2 ui-monospace, monospace; } -.composer-zone { padding: 8px calc(var(--content-gutter) * 1px) 14px; } +.composer-zone { padding: 8px calc(var(--mobile-content-gutter) * 1px) 14px; } .composer { display: grid; - grid-template-columns: calc(var(--composer-action-size) * 1px) 1fr calc(var(--composer-action-size) * 1px); + grid-template-columns: calc(var(--mobile-composer-action-size) * 1px) 1fr calc(var(--mobile-composer-action-size) * 1px); align-items: center; gap: 5px; - min-height: calc(var(--composer-collapsed-height) * 1px); + min-height: calc(var(--mobile-composer-collapsed-height) * 1px); padding: 0 8px; border: 0; - border-radius: calc(var(--composer-collapsed-radius) * 1px); - background: var(--card); - box-shadow: 0 2px 10px rgb(23 23 23 / 0.08); + border-radius: calc(var(--mobile-composer-collapsed-radius) * 1px); + background: var(--mobile-card); + box-shadow: 0 2px 10px var(--mobile-shadow-medium); } -.composer.has-draft { min-height: 76px; border-radius: calc(var(--composer-expanded-radius) * 1px); } -.composer button { width: 40px; height: 40px; border: 0; background: transparent; color: var(--ink); font-size: 19px; } +.composer.has-draft { min-height: 76px; border-radius: calc(var(--mobile-composer-expanded-radius) * 1px); } +.composer button { width: 40px; height: 40px; border: 0; background: transparent; color: var(--mobile-ink); font-size: 19px; } .composer-copy { min-width: 0; - color: var(--muted); - font-size: calc(var(--body-large-size) * 1px); - line-height: calc(var(--body-large-line-height) * 1px); - font-weight: var(--body-large-weight); + color: var(--mobile-muted); + font-size: calc(var(--mobile-body-large-size) * 1px); + line-height: calc(var(--mobile-body-large-line-height) * 1px); + font-weight: var(--mobile-body-large-weight); } -.composer.has-draft .composer-copy { color: var(--ink); } -.composer .primary { border-radius: 50%; background: var(--primary-action); color: var(--primary-action-text); } +.composer.has-draft .composer-copy { color: var(--mobile-ink); } +.composer .primary { border-radius: 50%; background: var(--mobile-primary-action); color: var(--mobile-content-on-action); } .native-shot { position: absolute; @@ -359,8 +359,8 @@ select { width: 100%; height: 100%; object-fit: contain; - background: #111; - opacity: var(--native-opacity, 1); + background: var(--mobile-media-background); + opacity: var(--native-opacity); } .device-screen.has-native .native-shot { display: block; } @@ -372,8 +372,8 @@ select { z-index: 5; display: none; background-image: - linear-gradient(rgb(37 99 235 / 0.2) 1px, transparent 1px), - linear-gradient(90deg, rgb(37 99 235 / 0.14) 1px, transparent 1px); + linear-gradient(color-mix(in srgb, var(--bf-color-link-default) 20%, transparent) 1px, transparent 1px), + linear-gradient(90deg, color-mix(in srgb, var(--bf-color-link-default) 14%, transparent) 1px, transparent 1px); background-size: 8px 8px; } @@ -384,20 +384,20 @@ select { grid-template-columns: auto 1fr; gap: 12px; padding: 10px 15px; - border-top: 1px solid #e9e7e2; - color: #77756e; - font: 10px/1.4 ui-monospace, monospace; + border-top: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-muted); + font: 10px/1.4 var(--bf-font-family-mono); } -.capture-status strong { color: #45443f; } +.capture-status strong { color: var(--bf-color-content-secondary); } .capture-status span { text-align: right; } .capture-status em { grid-column: 1 / -1; - color: #706f6a; + color: var(--bf-color-content-muted); font-style: normal; text-align: right; } -.capture-aspect-warning .capture-status strong { color: #9a5b13; } +.capture-aspect-warning .capture-status strong { color: var(--bf-color-status-warning-content); } @media (max-width: 1180px) { .bench-shell { padding-inline: 20px; } diff --git a/src/apps/mobile/design-system/preview/preview.js b/src/apps/mobile/design-system/preview/preview.js index 51c4358329..f9d4e4002f 100644 --- a/src/apps/mobile/design-system/preview/preview.js +++ b/src/apps/mobile/design-system/preview/preview.js @@ -125,13 +125,13 @@ function platformCard(platform, scenario, appearance) { function applyTokens(element, appearance) { for (const [name, pair] of Object.entries(mobileTokens.colors)) { - element.style.setProperty(`--${name.replaceAll('_', '-')}`, pair[appearance]); + element.style.setProperty(`--mobile-${name.replaceAll('_', '-')}`, mobileColorToCss(pair[appearance])); } for (const [name, value] of Object.entries(mobileTokens.geometry)) { - element.style.setProperty(`--${name.replaceAll('_', '-')}`, String(value)); + element.style.setProperty(`--mobile-${name.replaceAll('_', '-')}`, String(value)); } for (const [name, token] of Object.entries(mobileTokens.typography)) { - const prefix = `--${name.replaceAll('_', '-')}`; + const prefix = `--mobile-${name.replaceAll('_', '-')}`; element.style.setProperty(`${prefix}-size`, String(token.size)); element.style.setProperty(`${prefix}-line-height`, String(token.lineHeight)); element.style.setProperty(`${prefix}-weight`, String(token.weight)); @@ -203,7 +203,7 @@ function containedPixels(image, width, height) { canvas.width = width; canvas.height = height; const context = canvas.getContext('2d', { willReadFrequently: true }); - context.fillStyle = '#111111'; + context.fillStyle = mobileColorToCss(mobileTokens.colors.media_background.dark); context.fillRect(0, 0, width, height); const scale = Math.min(width / image.naturalWidth, height / image.naturalHeight); const drawWidth = image.naturalWidth * scale; @@ -211,3 +211,10 @@ function containedPixels(image, width, height) { context.drawImage(image, (width - drawWidth) / 2, (height - drawHeight) / 2, drawWidth, drawHeight); return context.getImageData(0, 0, width, height).data; } + +function mobileColorToCss(value) { + if (!/^#[0-9A-F]{8}$/i.test(value)) return value; + const alpha = value.slice(1, 3); + const rgb = value.slice(3); + return `#${rgb}${alpha}`; +} diff --git a/src/apps/mobile/design-system/tokens/mobile-tokens.json b/src/apps/mobile/design-system/tokens/mobile-tokens.json index 2b9e730d86..e5ea9f26ab 100644 --- a/src/apps/mobile/design-system/tokens/mobile-tokens.json +++ b/src/apps/mobile/design-system/tokens/mobile-tokens.json @@ -6,6 +6,7 @@ }, "colors": { "start_window_background": { "light": "#FFFFFF", "dark": "#000000" }, + "transparent": { "light": "#00000000", "dark": "#00000000" }, "page_bg": { "light": "#FFFFFF", "dark": "#151514" }, "page_bg_fade": { "light": "#00FFFFFF", "dark": "#00151514" }, "ink": { "light": "#171717", "dark": "#F4F3EF" }, @@ -16,17 +17,27 @@ "accent": { "light": "#111111", "dark": "#5B5954" }, "file_link": { "light": "#2563EB", "dark": "#60A5FA" }, "primary_action": { "light": "#111111", "dark": "#454540" }, - "primary_action_text": { "light": "#FFFFFF", "dark": "#FFFFFF" }, + "content_on_action": { "light": "#FFFFFF", "dark": "#FFFFFF" }, "connect_hero_bg": { "light": "#E6EDFF", "dark": "#2B2B29" }, "connect_hero_accent": { "light": "#9DB4FF", "dark": "#4A4944" }, "connect_hero_secondary": { "light": "#C9C5FF", "dark": "#3C3B38" }, "connect_hero_surface": { "light": "#F8FAFF", "dark": "#252522" }, "connect_scan_accent": { "light": "#FFD021", "dark": "#FFD021" }, - "modal_scrim": { "light": "#44000000", "dark": "#44000000" }, + "scrim": { "light": "#44000000", "dark": "#44000000" }, + "shell_scrim": { "light": "#24000000", "dark": "#24000000" }, + "media_background": { "light": "#FF000000", "dark": "#FF000000" }, + "media_scrim": { "light": "#B8000000", "dark": "#B8000000" }, + "media_control_background": { "light": "#8C000000", "dark": "#8C000000" }, + "toast_background": { "light": "#D1171717", "dark": "#D1171717" }, + "shadow_faint": { "light": "#08000000", "dark": "#08000000" }, + "shadow_subtle": { "light": "#12000000", "dark": "#12000000" }, + "shadow_medium": { "light": "#18000000", "dark": "#18000000" }, + "shadow_strong": { "light": "#24000000", "dark": "#24000000" }, + "floating_border": { "light": "#18000000", "dark": "#18000000" }, "soft": { "light": "#F4F3F0", "dark": "#2D2C28" }, "floating_panel_bg": { "light": "#F7F7F5", "dark": "#1E1E1C" }, - "green": { "light": "#27C46A", "dark": "#3BD47B" }, - "red": { "light": "#E04F4F", "dark": "#FF6B6B" }, + "status_success": { "light": "#27C46A", "dark": "#3BD47B" }, + "status_danger": { "light": "#E04F4F", "dark": "#FF6B6B" }, "code_line_number": { "light": "#AAA69D", "dark": "#77756E" }, "code_keyword": { "light": "#8F3F71", "dark": "#D99AC4" }, "code_string": { "light": "#477A4A", "dark": "#9BCB9D" }, diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/entryability/EntryAbility.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/entryability/EntryAbility.ets index 558a1305a7..a343768a06 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/entryability/EntryAbility.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/entryability/EntryAbility.ets @@ -1,6 +1,7 @@ import { AbilityConstant, Configuration, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; import { window } from '@kit.ArkUI'; +import { MobileDesignColors } from '../generated/MobileDesignTokens'; const DOMAIN = 0x0000; const TAG = 'BitFunRemote'; @@ -87,12 +88,14 @@ export default class EntryAbility extends UIAbility { return; } const dark = colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK; + const background = dark ? MobileDesignColors.pageBg.dark : MobileDesignColors.pageBg.light; + const content = dark ? MobileDesignColors.ink.dark : MobileDesignColors.ink.light; try { this.mainWindow.setWindowSystemBarProperties({ - statusBarColor: dark ? '#151514' : '#FDFDFB', - navigationBarColor: dark ? '#151514' : '#FDFDFB', - statusBarContentColor: dark ? '#F4F3EF' : '#171717', - navigationBarContentColor: dark ? '#F4F3EF' : '#171717' + statusBarColor: background, + navigationBarColor: background, + statusBarContentColor: content, + navigationBarContentColor: content }); } catch (err) { hilog.error(DOMAIN, TAG, 'Failed to update system bars. Cause: %{public}s', JSON.stringify(err)); diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/generated/MobileDesignTokens.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/generated/MobileDesignTokens.ets index 163d78917d..a8363f8486 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/generated/MobileDesignTokens.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/generated/MobileDesignTokens.ets @@ -1,5 +1,61 @@ // Generated by scripts/mobile-ui-design-system.mjs. Do not edit. +export class MobileColorPair { + readonly light: string; + readonly dark: string; + + constructor(light: string, dark: string) { + this.light = light; + this.dark = dark; + } +} + +export class MobileDesignColors { + static readonly startWindowBackground: MobileColorPair = new MobileColorPair("#FFFFFF", "#000000"); + static readonly transparent: MobileColorPair = new MobileColorPair("#00000000", "#00000000"); + static readonly pageBg: MobileColorPair = new MobileColorPair("#FFFFFF", "#151514"); + static readonly pageBgFade: MobileColorPair = new MobileColorPair("#00FFFFFF", "#00151514"); + static readonly ink: MobileColorPair = new MobileColorPair("#171717", "#F4F3EF"); + static readonly muted: MobileColorPair = new MobileColorPair("#706F6A", "#AAA8A0"); + static readonly subtle: MobileColorPair = new MobileColorPair("#A5A39B", "#77756E"); + static readonly line: MobileColorPair = new MobileColorPair("#E9E7E2", "#363531"); + static readonly card: MobileColorPair = new MobileColorPair("#FFFFFF", "#252522"); + static readonly accent: MobileColorPair = new MobileColorPair("#111111", "#5B5954"); + static readonly fileLink: MobileColorPair = new MobileColorPair("#2563EB", "#60A5FA"); + static readonly primaryAction: MobileColorPair = new MobileColorPair("#111111", "#454540"); + static readonly contentOnAction: MobileColorPair = new MobileColorPair("#FFFFFF", "#FFFFFF"); + static readonly connectHeroBg: MobileColorPair = new MobileColorPair("#E6EDFF", "#2B2B29"); + static readonly connectHeroAccent: MobileColorPair = new MobileColorPair("#9DB4FF", "#4A4944"); + static readonly connectHeroSecondary: MobileColorPair = new MobileColorPair("#C9C5FF", "#3C3B38"); + static readonly connectHeroSurface: MobileColorPair = new MobileColorPair("#F8FAFF", "#252522"); + static readonly connectScanAccent: MobileColorPair = new MobileColorPair("#FFD021", "#FFD021"); + static readonly scrim: MobileColorPair = new MobileColorPair("#44000000", "#44000000"); + static readonly shellScrim: MobileColorPair = new MobileColorPair("#24000000", "#24000000"); + static readonly mediaBackground: MobileColorPair = new MobileColorPair("#FF000000", "#FF000000"); + static readonly mediaScrim: MobileColorPair = new MobileColorPair("#B8000000", "#B8000000"); + static readonly mediaControlBackground: MobileColorPair = new MobileColorPair("#8C000000", "#8C000000"); + static readonly toastBackground: MobileColorPair = new MobileColorPair("#D1171717", "#D1171717"); + static readonly shadowFaint: MobileColorPair = new MobileColorPair("#08000000", "#08000000"); + static readonly shadowSubtle: MobileColorPair = new MobileColorPair("#12000000", "#12000000"); + static readonly shadowMedium: MobileColorPair = new MobileColorPair("#18000000", "#18000000"); + static readonly shadowStrong: MobileColorPair = new MobileColorPair("#24000000", "#24000000"); + static readonly floatingBorder: MobileColorPair = new MobileColorPair("#18000000", "#18000000"); + static readonly soft: MobileColorPair = new MobileColorPair("#F4F3F0", "#2D2C28"); + static readonly floatingPanelBg: MobileColorPair = new MobileColorPair("#F7F7F5", "#1E1E1C"); + static readonly statusSuccess: MobileColorPair = new MobileColorPair("#27C46A", "#3BD47B"); + static readonly statusDanger: MobileColorPair = new MobileColorPair("#E04F4F", "#FF6B6B"); + static readonly codeLineNumber: MobileColorPair = new MobileColorPair("#AAA69D", "#77756E"); + static readonly codeKeyword: MobileColorPair = new MobileColorPair("#8F3F71", "#D99AC4"); + static readonly codeString: MobileColorPair = new MobileColorPair("#477A4A", "#9BCB9D"); + static readonly codeNumber: MobileColorPair = new MobileColorPair("#9A5B13", "#E3B36D"); + static readonly codeComment: MobileColorPair = new MobileColorPair("#7A8078", "#96958D"); + static readonly codeFunction: MobileColorPair = new MobileColorPair("#2C6693", "#8CBCE0"); + static readonly codeType: MobileColorPair = new MobileColorPair("#865A20", "#D5B27F"); + static readonly codeConstant: MobileColorPair = new MobileColorPair("#A04444", "#E79A9A"); + static readonly codeProperty: MobileColorPair = new MobileColorPair("#466D78", "#9CC8D0"); + static readonly codeTargetBg: MobileColorPair = new MobileColorPair("#FFF1BE", "#5A4E24"); +} + export class MobileTypographyToken { readonly size: number; readonly lineHeight: number; diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AccountProfilePanel.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AccountProfilePanel.ets index 40b466d796..3af8301e0d 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AccountProfilePanel.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AccountProfilePanel.ets @@ -2,7 +2,7 @@ import { MobileDesignGeometry, MobileDesignTypography } from '../../generated/Mo import { RemoteI18n } from '../../i18n/RemoteI18n'; import { CloudAccountDevice } from '../../services/CloudAccountClient'; import { AccountDeviceSelectionPolicy } from '../policy/AccountDeviceSelectionPolicy'; -import { CARD, GREEN, INK, LINE, MUTED, PAGE_BG, RED, SOFT } from './Theme'; +import { CARD, STATUS_SUCCESS, INK, LINE, MUTED, PAGE_BG, STATUS_DANGER, SOFT } from './Theme'; import { DefaultAccountAvatar } from './DefaultAccountAvatar'; import { SheetCloseHeader } from './SheetCloseHeader'; @@ -91,7 +91,7 @@ export struct AccountProfilePanel { RemoteI18n.t('remote.settings.accountNotSignedIn')) .fontSize(MobileDesignTypography.bodySmall.size) .fontWeight(FontWeight.Medium) - .fontColor(this.isAccountAuthenticated() ? GREEN : MUTED) + .fontColor(this.isAccountAuthenticated() ? STATUS_SUCCESS : MUTED) } .width('100%') .constraintSize({ minHeight: 72 }) @@ -161,7 +161,7 @@ export struct AccountProfilePanel { Text(this.isAccountAuthenticated() ? RemoteI18n.t('remote.settings.accountSignedIn') : RemoteI18n.t('remote.settings.accountNotSignedIn')) .fontSize(MobileDesignTypography.bodyMedium.size) - .fontColor(this.isAccountAuthenticated() ? GREEN : MUTED) + .fontColor(this.isAccountAuthenticated() ? STATUS_SUCCESS : MUTED) } .width('100%') @@ -228,7 +228,7 @@ export struct AccountProfilePanel { } if (this.accountDevicesError.length > 0 && this.desktopDevices().length > 0) { Text(this.accountDevicesError) - .fontSize(MobileDesignTypography.bodySmall.size).lineHeight(MobileDesignTypography.bodySmall.lineHeight).fontColor(RED).width('100%') + .fontSize(MobileDesignTypography.bodySmall.size).lineHeight(MobileDesignTypography.bodySmall.lineHeight).fontColor(STATUS_DANGER).width('100%') } } .width('100%') @@ -256,7 +256,7 @@ export struct AccountProfilePanel { .fontSize(MobileDesignTypography.titleSmall.size).fontWeight(FontWeight.Medium).fontColor(INK) .maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }) Text(this.deviceStatus(device)) - .fontSize(MobileDesignTypography.bodySmall.size).fontColor(device.online ? GREEN : MUTED) + .fontSize(MobileDesignTypography.bodySmall.size).fontColor(device.online ? STATUS_SUCCESS : MUTED) } .layoutWeight(1) .alignItems(HorizontalAlign.Start) @@ -327,10 +327,10 @@ export struct AccountProfilePanel { } Row({ space: 14 }) { SymbolGlyph($r('sys.symbol.arrow_right_and_square')) - .fontSize(22).fontColor([RED]).width(24).height(24) + .fontSize(22).fontColor([STATUS_DANGER]).width(24).height(24) Text(this.logoutBusy ? RemoteI18n.t('remote.settings.accountLoggingOut') : RemoteI18n.t('remote.settings.accountLogout')) - .fontSize(MobileDesignTypography.titleMedium.size).fontWeight(FontWeight.Medium).fontColor(RED) + .fontSize(MobileDesignTypography.titleMedium.size).fontWeight(FontWeight.Medium).fontColor(STATUS_DANGER) } .width('100%') .constraintSize({ minHeight: 62 }) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AdaptiveSheetOptions.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AdaptiveSheetOptions.ets index 7b1ae8250c..60251d4855 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AdaptiveSheetOptions.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AdaptiveSheetOptions.ets @@ -1,4 +1,5 @@ import { +import { SCRIM, TRANSPARENT } from './Theme'; SettingsPlacement, SettingsPlacementMode } from '../policy/SettingsPlacementPolicy'; @@ -13,8 +14,8 @@ export class AdaptiveSheetOptions { return { height: placement.height, keyboardAvoidMode: SheetKeyboardAvoidMode.RESIZE_ONLY, - backgroundColor: '#00000000', - maskColor: '#44000000', + backgroundColor: TRANSPARENT, + maskColor: SCRIM, showClose: false, dragBar }; @@ -25,8 +26,8 @@ export class AdaptiveSheetOptions { width: placement.width, keyboardAvoidMode: SheetKeyboardAvoidMode.RESIZE_ONLY, preferType: SheetType.SIDE, - backgroundColor: '#00000000', - maskColor: '#44000000', + backgroundColor: TRANSPARENT, + maskColor: SCRIM, showClose: false, dragBar: false }; @@ -37,8 +38,8 @@ export class AdaptiveSheetOptions { width: placement.width, keyboardAvoidMode: SheetKeyboardAvoidMode.RESIZE_ONLY, preferType: SheetType.CENTER, - backgroundColor: '#00000000', - maskColor: '#44000000', + backgroundColor: TRANSPARENT, + maskColor: SCRIM, showClose: false, dragBar: false }; @@ -47,8 +48,8 @@ export class AdaptiveSheetOptions { return { height: placement.height, keyboardAvoidMode: SheetKeyboardAvoidMode.RESIZE_ONLY, - backgroundColor: '#00000000', - maskColor: '#44000000', + backgroundColor: TRANSPARENT, + maskColor: SCRIM, showClose: false, dragBar }; @@ -56,8 +57,8 @@ export class AdaptiveSheetOptions { return { height: SheetSize.LARGE, keyboardAvoidMode: SheetKeyboardAvoidMode.RESIZE_ONLY, - backgroundColor: '#00000000', - maskColor: '#44000000', + backgroundColor: TRANSPARENT, + maskColor: SCRIM, showClose: false, dragBar }; diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppActionButton.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppActionButton.ets index 8a2960c9e9..a293be8a22 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppActionButton.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppActionButton.ets @@ -1,5 +1,5 @@ import { MobileDesignGeometry, MobileDesignTypography } from '../../generated/MobileDesignTokens'; -import { CARD, INK, LINE, PRIMARY_ACTION, PRIMARY_ACTION_TEXT, RED, SOFT } from './Theme'; +import { CARD, CONTENT_ON_ACTION, INK, LINE, PRIMARY_ACTION, SOFT, STATUS_DANGER } from './Theme'; /** Visual intent for a product action. Layout may still choose its own width and height. */ export enum AppActionStyle { @@ -24,7 +24,7 @@ export struct AppActionButton { .height(this.actionHeight) .fontSize(MobileDesignTypography.labelLarge.size) .fontWeight(FontWeight.Medium) - .fontColor(this.isFilled() ? PRIMARY_ACTION_TEXT : INK) + .fontColor(this.isFilled() ? CONTENT_ON_ACTION : INK) .backgroundColor(this.actionBackgroundColor()) .border({ width: this.style === AppActionStyle.Secondary ? 1 : 0, color: LINE }) .borderRadius(this.actionHeight / 2) @@ -41,7 +41,7 @@ export struct AppActionButton { private actionBackgroundColor(): ResourceColor { if (this.style === AppActionStyle.Primary) return PRIMARY_ACTION; - if (this.style === AppActionStyle.Destructive) return RED; + if (this.style === AppActionStyle.Destructive) return STATUS_DANGER; if (this.style === AppActionStyle.Quiet) return SOFT; return CARD; } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppShell.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppShell.ets index 8d6be34bea..d0ffa737ef 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppShell.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppShell.ets @@ -7,7 +7,11 @@ import { SettingsSheetKind } from '../policy/SettingsPlacementPolicy'; import { AdaptiveSheetOptions } from './AdaptiveSheetOptions'; -import { PAGE_BG } from './Theme'; +import { + PAGE_BG, + SHELL_SCRIM, + TRANSPARENT, +} from './Theme'; const WIDE_SHEET_RADIUS: number = 30; @@ -77,7 +81,7 @@ export struct AppShell { .clip(true) .shadow({ radius: this.shellState.showSidebar ? 34 : 0, - color: this.shellState.showSidebar ? '#24000000' : '#00000000', + color: this.shellState.showSidebar ? SHELL_SCRIM : TRANSPARENT, offsetX: this.shellState.showSidebar ? -10 : 0 }) .blur(this.shellState.showSidebar ? 1.1 : 0) @@ -112,7 +116,7 @@ export struct AppShell { .clip(this.usesWideSheetChrome(this.settingsPlacement)) .shadow({ radius: this.usesWideSheetChrome(this.settingsPlacement) ? 30 : 0, - color: this.usesWideSheetChrome(this.settingsPlacement) ? '#22000000' : '#00000000', + color: this.usesWideSheetChrome(this.settingsPlacement) ? SHELL_SCRIM : TRANSPARENT, offsetY: this.usesWideSheetChrome(this.settingsPlacement) ? 12 : 0 }) } @@ -128,7 +132,7 @@ export struct AppShell { .clip(this.usesWideSheetChrome(this.connectPlacement)) .shadow({ radius: this.usesWideSheetChrome(this.connectPlacement) ? 30 : 0, - color: this.usesWideSheetChrome(this.connectPlacement) ? '#22000000' : '#00000000', + color: this.usesWideSheetChrome(this.connectPlacement) ? SHELL_SCRIM : TRANSPARENT, offsetY: this.usesWideSheetChrome(this.connectPlacement) ? 12 : 0 }) } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppSidebar.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppSidebar.ets index ca626ef7c1..495d8797c2 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppSidebar.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppSidebar.ets @@ -1,7 +1,7 @@ import { MobileDesignGeometry, MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RemoteSession } from '../../model/RemoteModels'; import { RemoteI18n } from '../../i18n/RemoteI18n'; -import { CARD, INK, LINE, MUTED, PAGE_BG, PAGE_BG_FADE, SOFT, SUBTLE } from './Theme'; +import { CARD, INK, LINE, MUTED, PAGE_BG, PAGE_BG_FADE, SCRIM, SOFT, SUBTLE, TRANSPARENT } from './Theme'; import { SidebarToggleButton } from './SidebarToggleButton'; import { SessionActionPresentation, SessionActionSurface } from './SessionActionSurface'; import { AdaptiveSheetOptions } from './AdaptiveSheetOptions'; @@ -215,7 +215,7 @@ export struct AppSidebar { .width(MobileDesignGeometry.controlTouchSize) .height(MobileDesignGeometry.controlTouchSize) .padding(0) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .borderRadius(12) .stateEffect(true) .accessibilityText(RemoteI18n.t('remote.actions')) @@ -230,7 +230,7 @@ export struct AppSidebar { .width(MobileDesignGeometry.controlTouchSize) .height(MobileDesignGeometry.controlTouchSize) .padding(0) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .borderRadius(12) .stateEffect(true) .accessibilityText(RemoteI18n.t('common.search')) @@ -338,7 +338,7 @@ export struct AppSidebar { .width(48) .height(48) .padding(0) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .borderRadius(12) .stateEffect(true) .onClick(() => { @@ -440,7 +440,7 @@ export struct AppSidebar { .height(46) .padding({ left: 12, right: 68 }) .margin({ top: 8 }) - .backgroundColor(this.archivedSessionsExpanded ? SOFT : '#00000000') + .backgroundColor(this.archivedSessionsExpanded ? SOFT : TRANSPARENT) .borderRadius(10) .onClick(() => { this.archivedSessionsExpanded = !this.archivedSessionsExpanded; @@ -460,14 +460,14 @@ export struct AppSidebar { } .width('100%').height(44) .padding({ left: 12, right: 4 }) - .backgroundColor(this.selectedSessionId === session.id ? SOFT : '#00000000') + .backgroundColor(this.selectedSessionId === session.id ? SOFT : TRANSPARENT) .borderRadius(10) .onClick(() => this.openSession(session)) .gesture(LongPressGesture({ repeat: false }).onAction(() => this.openSessionActions(session))) .bindPopup(this.showCollapseButton && this.activeActionSessionId === session.id, { builder: () => { this.SessionActionPopover() }, placement: Placement.Right, - popupColor: '#00000000', + popupColor: TRANSPARENT, enableArrow: false, autoCancel: true, mask: false, @@ -496,7 +496,7 @@ export struct AppSidebar { .height(44) .padding({ left: 12, right: 4 }) .backgroundColor(this.selectedSessionId === item.id || this.activeActionSessionId === item.id ? - SOFT : '#00000000') + SOFT : TRANSPARENT) .borderRadius(10) .onClick(() => { this.openSession(item); @@ -505,7 +505,7 @@ export struct AppSidebar { .bindPopup(this.showCollapseButton && this.activeActionSessionId === item.id, { builder: () => { this.SessionActionPopover() }, placement: Placement.Right, - popupColor: '#00000000', + popupColor: TRANSPARENT, enableArrow: false, autoCancel: true, mask: false, @@ -711,8 +711,8 @@ export struct AppSidebar { private sessionActionSheetOptions(): SheetOptions { return { height: this.actionSessionIsGeneralChat() ? 380 : 300, - backgroundColor: '#00000000', - maskColor: '#44000000', + backgroundColor: TRANSPARENT, + maskColor: SCRIM, showClose: false, dragBar: false }; diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/BitFunAccountLoginPage.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/BitFunAccountLoginPage.ets index 88c24eb110..0c6adf875b 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/BitFunAccountLoginPage.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/BitFunAccountLoginPage.ets @@ -7,7 +7,7 @@ import { LINE, MUTED, PAGE_BG_FADE, - RED, + STATUS_DANGER, SUBTLE } from './Theme'; import { SheetActionFooter } from './SheetActionFooter'; @@ -94,7 +94,7 @@ export struct BitFunAccountLoginPage { Text(this.errorText) .fontSize(MobileDesignTypography.bodySmall.size) .lineHeight(MobileDesignTypography.bodySmall.lineHeight) - .fontColor(RED) + .fontColor(STATUS_DANGER) .width('100%') .margin({ top: 12, left: 4, right: 4 }) } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatMessageBubble.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatMessageBubble.ets index de5ee1c27f..bb77bee144 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatMessageBubble.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatMessageBubble.ets @@ -6,7 +6,7 @@ import { ChatMessageStructurePolicy, StructuredRenderGroup } from '../policy/Cha import { AssistantProcessLayoutPolicy } from '../policy/AssistantProcessLayoutPolicy'; import { ConversationMessageRenderPolicy } from '../policy/ConversationMessageRenderPolicy'; import { ThinkingPresentationPolicy } from '../policy/ThinkingPresentationPolicy'; -import { ACCENT, INK, LINE, RED } from './Theme'; +import { ACCENT, INK, LINE, STATUS_DANGER } from './Theme'; import { MessageBodyMarkdown, MessageFileCards, MessageImageGallery, MessageMarkdown } from './ChatMessageContent'; import { ChatMessageRetryAction, ChatTypingDots, ChatUserMessageBubble } from './ChatMessageChrome'; import { SubagentTaskCard } from './SubagentTaskCard'; @@ -121,7 +121,7 @@ export struct ChatMessageBubble { Text(RemoteI18n.t('chat.responseFailed')) .fontSize(MobileDesignTypography.labelSmall.size) .fontWeight(FontWeight.Medium) - .fontColor(RED) + .fontColor(STATUS_DANGER) Text(errorText.trim()) .fontSize(MobileDesignTypography.bodySmall.size) .lineHeight(MobileDesignTypography.bodySmall.lineHeight) @@ -138,7 +138,7 @@ export struct ChatMessageBubble { } .width('100%') .padding({ left: 12, top: 2, bottom: 2 }) - .border({ width: { left: 2 }, color: RED }) + .border({ width: { left: 2 }, color: STATUS_DANGER }) .alignItems(HorizontalAlign.Start) } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatMessageChrome.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatMessageChrome.ets index 1c3c357d66..d38e42b2d1 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatMessageChrome.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatMessageChrome.ets @@ -2,7 +2,7 @@ import { MobileDesignGeometry, MobileDesignTypography } from '../../generated/Mo import { RemoteI18n } from '../../i18n/RemoteI18n'; import { ConversationUiMessage } from '../state/ConversationUiModels'; import { MessageImageGallery } from './ChatMessageContent'; -import { ACCENT, INK, MUTED, PRIMARY_ACTION_TEXT, RED, SOFT } from './Theme'; +import { ACCENT, INK, MUTED, CONTENT_ON_ACTION, STATUS_DANGER, SOFT } from './Theme'; @ComponentV2 export struct ChatTypingDots { @@ -49,10 +49,10 @@ export struct ChatMessageRetryAction { Row({ space: 8 }) { Text(this.assistant ? RemoteI18n.t('generalChat.replyInterrupted') : RemoteI18n.t('chat.sendFailed')) .fontSize(MobileDesignTypography.labelSmall.size) - .fontColor(RED) + .fontColor(STATUS_DANGER) Text(RemoteI18n.t('common.retry')) .fontSize(MobileDesignTypography.labelSmall.size) - .fontColor(PRIMARY_ACTION_TEXT) + .fontColor(CONTENT_ON_ACTION) .height(28) .padding({ left: 10, right: 10 }) .backgroundColor(ACCENT) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatTimeline.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatTimeline.ets index 4db8c96ac5..eb8104bcfa 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatTimeline.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ChatTimeline.ets @@ -13,7 +13,14 @@ import { ObservableChatTimelineItem } from '../../model/ChatTimelineModels'; import { ChatSurface } from '../state/ChatSurface'; -import { CARD, INK, LINE, MUTED, RED } from './Theme'; +import { + CARD, + INK, + LINE, + MUTED, + SHADOW_SUBTLE, + STATUS_DANGER, +} from './Theme'; import { ChatMessageBubble, ChatUserMessageRow } from './ChatMessageBubble'; import { RemoteLogger } from '../../services/RemoteLogger'; @@ -324,7 +331,7 @@ export struct ChatTimeline { .height(42) .backgroundColor(CARD) .borderRadius(21) - .shadow({ radius: 14, color: '#14000000', offsetY: 5 }) + .shadow({ radius: 14, color: SHADOW_SUBTLE, offsetY: 5 }) .margin({ bottom: 4 }) .onClick(() => { this.stickToBottom = true; @@ -346,7 +353,7 @@ export struct ChatTimeline { .width(38) .height(38) .fontSize(MobileDesignTypography.headlineSmall.size) - .fontColor(this.connectionState === 'failed' ? RED : MUTED) + .fontColor(this.connectionState === 'failed' ? STATUS_DANGER : MUTED) .textAlign(TextAlign.Center) .backgroundColor(CARD) .borderRadius(14) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/CompactMenuButton.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/CompactMenuButton.ets index 2f228cf558..46507219ca 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/CompactMenuButton.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/CompactMenuButton.ets @@ -1,5 +1,6 @@ import { RemoteI18n } from '../../i18n/RemoteI18n'; import { TemplateIcon } from './TemplateIcon'; +import { TRANSPARENT } from './Theme'; @ComponentV2 export struct CompactMenuButton { @@ -17,7 +18,7 @@ export struct CompactMenuButton { .width(this.controlSize) .height(this.controlSize) .padding(0) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .borderRadius(12) .stateEffect(true) .accessibilityText(RemoteI18n.t('sidebar.more')) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ComposerBar.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ComposerBar.ets index b4d96a088c..d80eb24abe 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ComposerBar.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ComposerBar.ets @@ -11,15 +11,21 @@ import { import { ConversationModelPresentationPolicy } from '../policy/ConversationModelPresentationPolicy'; import { CARD, + CONTENT_ON_ACTION, FLOATING_PANEL_BG, - GREEN, INK, LINE, + MEDIA_SCRIM, MUTED, PRIMARY_ACTION, - PRIMARY_ACTION_TEXT, - RED, - SOFT + SCRIM, + SHADOW_FAINT, + SHADOW_MEDIUM, + SHADOW_SUBTLE, + SOFT, + STATUS_DANGER, + STATUS_SUCCESS, + TRANSPARENT } from './Theme'; export enum ComposerPresentation { @@ -97,7 +103,7 @@ export struct ComposerBar { top: 8, bottom: this.presentation === ComposerPresentation.Floating ? 16 : 12 }) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .bindSheet($$this.showModelSelectorSheet, this.ModelSelector(true), this.modelSelectorSheetOptions()) } @@ -165,7 +171,7 @@ export struct ComposerBar { .borderRadius(this.composerRadius()) .shadow({ radius: this.presentation === ComposerPresentation.Floating ? 14 : 8, - color: this.presentation === ComposerPresentation.Floating ? '#10000000' : '#08000000', + color: this.presentation === ComposerPresentation.Floating ? SHADOW_SUBTLE : SHADOW_FAINT, offsetY: this.presentation === ComposerPresentation.Floating ? 4 : 2 }) .animation({ duration: MobileDesignMotion.structure, curve: Curve.EaseOut }) @@ -194,14 +200,14 @@ export struct ComposerBar { .height(32) .constraintSize({ maxWidth: 220 }) .padding({ left: 4, right: 4 }) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .accessibilityText(`${RemoteI18n.t('chat.selectModel')} · ${this.displaySelectedModel()}`) .bindPopup(this.showModelSelectorPopover, { builder: () => { this.ModelSelector(false) }, placement: Placement.Top, - popupColor: '#00000000', + popupColor: TRANSPARENT, enableArrow: false, autoCancel: true, mask: false, @@ -264,8 +270,8 @@ export struct ComposerBar { .backgroundColor(asSheet ? CARD : FLOATING_PANEL_BG) .borderRadius(asSheet ? { topLeft: 20, topRight: 20 } : MobileDesignGeometry.composerModelSelectorRadius) - .border({ width: asSheet ? 0 : 1, color: asSheet ? '#00000000' : LINE }) - .shadow({ radius: asSheet ? 0 : 18, color: asSheet ? '#00000000' : '#18000000', offsetY: 7 }) + .border({ width: asSheet ? 0 : 1, color: asSheet ? TRANSPARENT : LINE }) + .shadow({ radius: asSheet ? 0 : 18, color: asSheet ? TRANSPARENT : SHADOW_MEDIUM, offsetY: 7 }) } @Builder @@ -300,7 +306,7 @@ export struct ComposerBar { .width('100%') .height(MobileDesignGeometry.composerModelSelectorRowHeight) .padding({ left: 10, right: 10 }) - .backgroundColor(this.isSelectedModel(model) ? SOFT : '#00000000') + .backgroundColor(this.isSelectedModel(model) ? SOFT : TRANSPARENT) .borderRadius(MobileDesignGeometry.composerModelSelectorRowRadius) .onClick(() => { this.closeModelSelector(); @@ -338,8 +344,8 @@ export struct ComposerBar { .height(this.isComposerExpanded() ? COMPOSER_EXPANDED_INPUT_HEIGHT : COMPOSER_INPUT_HEIGHT) .fontSize(MobileDesignTypography.bodyLarge.size) .fontColor(INK) - .placeholderColor(this.isVoiceListening ? GREEN : MUTED) - .backgroundColor('#00000000') + .placeholderColor(this.isVoiceListening ? STATUS_SUCCESS : MUTED) + .backgroundColor(TRANSPARENT) .borderRadius(20) .padding({ left: this.isVoiceListening ? 0 : 4, @@ -369,9 +375,9 @@ export struct ComposerBar { .height(this.isComposerExpanded() ? COMPOSER_EXPANDED_INPUT_HEIGHT : COMPOSER_INPUT_HEIGHT) .alignItems(VerticalAlign.Center) .padding({ left: this.isVoiceListening ? 12 : 0, right: 0 }) - .backgroundColor(this.isVoiceListening ? SOFT : '#00000000') + .backgroundColor(this.isVoiceListening ? SOFT : TRANSPARENT) .borderRadius(20) - .border({ width: this.isVoiceListening ? 1 : 0, color: this.isVoiceListening ? GREEN : '#00000000' }) + .border({ width: this.isVoiceListening ? 1 : 0, color: this.isVoiceListening ? STATUS_SUCCESS : TRANSPARENT }) } @Builder @@ -450,22 +456,22 @@ export struct ComposerBar { Text('') .width(3) .height(10) - .backgroundColor(GREEN) + .backgroundColor(STATUS_SUCCESS) .borderRadius(2) Text('') .width(3) .height(18) - .backgroundColor(GREEN) + .backgroundColor(STATUS_SUCCESS) .borderRadius(2) Text('') .width(3) .height(24) - .backgroundColor(GREEN) + .backgroundColor(STATUS_SUCCESS) .borderRadius(2) Text('') .width(3) .height(14) - .backgroundColor(GREEN) + .backgroundColor(STATUS_SUCCESS) .borderRadius(2) } .width(22) @@ -508,7 +514,7 @@ export struct ComposerBar { .fontSize(MobileDesignTypography.bodyLarge.size) .fontColor(CARD) .textAlign(TextAlign.Center) - .backgroundColor('#AA222222') + .backgroundColor(MEDIA_SCRIM) .borderRadius(16) .margin({ top: 0, right: 0 }) .accessibilityText(RemoteI18n.t('chat.removeImage')) @@ -659,8 +665,8 @@ export struct ComposerBar { private modelSelectorSheetOptions(): SheetOptions { return { height: Math.min(480, 86 + this.modelListHeight()), - backgroundColor: '#00000000', - maskColor: '#44000000', + backgroundColor: TRANSPARENT, + maskColor: SCRIM, showClose: false, dragBar: true }; @@ -684,14 +690,14 @@ export struct ComposerBar { action === ComposerPrimaryAction.Idle) { return SOFT; } - return this.isVoiceListening ? GREEN : RED; + return this.isVoiceListening ? STATUS_SUCCESS : STATUS_DANGER; } private primaryActionForegroundColor(): ResourceColor { const action = this.primaryAction(); if (action === ComposerPrimaryAction.Send || action === ComposerPrimaryAction.Voice || action === ComposerPrimaryAction.Stop) { - return PRIMARY_ACTION_TEXT; + return CONTENT_ON_ACTION; } return MUTED; } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectAccountDevicePage.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectAccountDevicePage.ets index ca70ba69b7..6bc92654dc 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectAccountDevicePage.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectAccountDevicePage.ets @@ -1,7 +1,7 @@ import { MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RemoteI18n } from '../../i18n/RemoteI18n'; import { CloudAccountDevice } from '../../services/CloudAccountClient'; -import { ACCENT, CARD, GREEN, INK, LINE, MUTED, PAGE_BG, RED, SOFT } from './Theme'; +import { ACCENT, CARD, STATUS_SUCCESS, INK, LINE, MUTED, PAGE_BG, STATUS_DANGER, SOFT } from './Theme'; import { AccountDeviceSelectionPolicy } from '../policy/AccountDeviceSelectionPolicy'; import { NavigationBackButton } from './NavigationBackButton'; @@ -74,7 +74,7 @@ export struct ConnectAccountDevicePage { (this.accountDevicesError.length > 0 ? RemoteI18n.t('common.retry') : RemoteI18n.t('common.refresh'))) .fontSize(MobileDesignTypography.bodyMedium.size) .fontColor(this.accountDevicesBusy ? MUTED : - (this.accountDevicesError.length > 0 ? RED : ACCENT)) + (this.accountDevicesError.length > 0 ? STATUS_DANGER : ACCENT)) .onClick(async () => { await this.refreshAccountDevices(); }) } .width('100%').height(38) @@ -148,7 +148,7 @@ export struct ConnectAccountDevicePage { .fontSize(MobileDesignTypography.titleSmall.size).fontWeight(FontWeight.Medium).fontColor(INK) .maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }) Text(this.accountDeviceStatus(device)) - .fontSize(MobileDesignTypography.bodySmall.size).fontColor(device.online ? GREEN : MUTED) + .fontSize(MobileDesignTypography.bodySmall.size).fontColor(device.online ? STATUS_SUCCESS : MUTED) } .layoutWeight(1) .alignItems(HorizontalAlign.Start) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectManualPairingOverlay.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectManualPairingOverlay.ets index 49582df9e6..6b24e251eb 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectManualPairingOverlay.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectManualPairingOverlay.ets @@ -1,6 +1,6 @@ import { MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RemoteI18n } from '../../i18n/RemoteI18n'; -import { CARD, INK, LINE, MODAL_SCRIM, MUTED, SOFT } from './Theme'; +import { CARD, INK, LINE, MUTED, SCRIM, SOFT } from './Theme'; import { AppActionButton, AppActionStyle } from './AppActionButton'; @ComponentV2 @@ -21,7 +21,7 @@ export struct ConnectManualPairingOverlay { Text('') .width('100%') .height('100%') - .backgroundColor(MODAL_SCRIM) + .backgroundColor(SCRIM) .onClick(this.onCancel) Column({ space: 20 }) { diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectView.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectView.ets index 72eecd12d4..dd1399dfef 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectView.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConnectView.ets @@ -21,8 +21,8 @@ import { import { DetectedUrlAction } from '../../services/ConnectScanDecisionPolicy'; import { InlineQrScanner } from './platform/InlineQrScanner'; import { CARD, CONNECT_HERO_ACCENT, CONNECT_HERO_BG, CONNECT_HERO_SECONDARY, - CONNECT_HERO_SURFACE, CONNECT_SCAN_ACCENT, GREEN, INK, LINE, MUTED, PAGE_BG, RED, SOFT, - SUBTLE } from './Theme'; + CONNECT_HERO_SURFACE, CONNECT_SCAN_ACCENT, INK, LINE, MUTED, PAGE_BG, SHADOW_MEDIUM, SOFT, + STATUS_DANGER, STATUS_SUCCESS, SUBTLE } from './Theme'; const SCAN_FRAME_SIZE: number = 248; const SCAN_CORNER_SIZE: number = 56; @@ -342,7 +342,7 @@ export struct ConnectView { Text('') .width(SCAN_FRAME_SIZE) .height(SCAN_FRAME_SIZE) - .backgroundColor('#18000000') + .backgroundColor(SHADOW_MEDIUM) .borderRadius(28) this.ScanCorner(SCAN_CORNER_INSET, SCAN_CORNER_INSET, true, true) this.ScanCorner( @@ -447,10 +447,10 @@ export struct ConnectView { private statusDotColor(): ResourceColor { if (this.isConnected) { - return GREEN; + return STATUS_SUCCESS; } if (this.isConnectError()) { - return RED; + return STATUS_DANGER; } if (this.isBusy || this.connectionState === 'parsing' || this.connectionState === 'pairing' || this.connectionState === 'reconnecting') { return INK; diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationHeader.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationHeader.ets index 80ea620a9b..4adbab11a0 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationHeader.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationHeader.ets @@ -1,6 +1,16 @@ import { RemoteI18n } from '../../i18n/RemoteI18n'; import { MobileDesignGeometry, MobileDesignTypography } from '../../generated/MobileDesignTokens'; -import { ACCENT, CARD, INK, LINE, MUTED, PAGE_BG, PRIMARY_ACTION_TEXT, SOFT } from './Theme'; +import { + ACCENT, + CARD, + CONTENT_ON_ACTION, + INK, + LINE, + MUTED, + PAGE_BG, + SOFT, + TRANSPARENT, +} from './Theme'; import { CompactMenuButton } from './CompactMenuButton'; import { NavigationBackButton } from './NavigationBackButton'; import { TemplateIcon } from './TemplateIcon'; @@ -134,7 +144,7 @@ export struct ConversationHeader { .width(MobileDesignGeometry.controlTouchSize) .height(MobileDesignGeometry.controlTouchSize) .padding(0) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .borderRadius(12) .stateEffect(true) .accessibilityText(RemoteI18n.t('sidebar.more')) @@ -143,7 +153,7 @@ export struct ConversationHeader { this.actionsMenu(); }, placement: Placement.BottomRight, - popupColor: '#00000000', + popupColor: TRANSPARENT, enableArrow: false, autoCancel: true, mask: false, @@ -182,7 +192,7 @@ export struct ConversationHeader { .width(52) .height(42) .fontSize(MobileDesignTypography.bodySmall.size) - .fontColor(PRIMARY_ACTION_TEXT) + .fontColor(CONTENT_ON_ACTION) .textAlign(TextAlign.Center) .backgroundColor(this.renameTitle.trim().length > 0 ? ACCENT : SOFT) .borderRadius(14) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationView.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationView.ets index b170fe7c81..398c827e52 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationView.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationView.ets @@ -24,7 +24,17 @@ import { import { ComposerBar, ComposerPresentation } from './ComposerBar'; import { ConversationHeader } from './ConversationHeader'; import { ConversationHeaderPolicy, ConversationHeaderPresentation } from '../policy/ConversationHeaderPolicy'; -import { FLOATING_PANEL_BG, GREEN, INK, LINE, MUTED, PAGE_BG, RED, SOFT } from './Theme'; +import { + FLOATING_PANEL_BG, + INK, + LINE, + MUTED, + PAGE_BG, + SOFT, + STATUS_DANGER, + STATUS_SUCCESS, + TRANSPARENT, +} from './Theme'; @ComponentV2 export struct ConversationView { @@ -334,7 +344,7 @@ export struct ConversationView { .width('100%').height(48) .padding({ left: 8, right: 8 }) .borderRadius(10) - .backgroundColor(selected ? SOFT : '#00000000') + .backgroundColor(selected ? SOFT : TRANSPARENT) .onClick(() => { action() this.showHeaderActions = false @@ -375,7 +385,7 @@ export struct ConversationView { private statusColor(): ResourceColor { if (this.canStop && this.connectionState === 'connected') { - return GREEN; + return STATUS_SUCCESS; } return this.connectionColor(); } @@ -440,10 +450,10 @@ export struct ConversationView { private connectionColor(): ResourceColor { const tone = ConnectionStatusPresenter.tone(this.connectionState); if (tone === 'ok') { - return GREEN; + return STATUS_SUCCESS; } if (tone === 'error') { - return RED; + return STATUS_DANGER; } return MUTED; } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationViewSettings.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationViewSettings.ets index 3eba8e2968..aa60b040cd 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationViewSettings.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ConversationViewSettings.ets @@ -3,7 +3,14 @@ import { RemoteI18n } from '../../i18n/RemoteI18n'; import { RecentWorkspaceEntry, RemoteSession } from '../../model/RemoteModels'; import { RemoteLogger } from '../../services/RemoteLogger'; import { ConversationSessionFilterPolicy } from '../policy/ConversationSessionFilterPolicy'; -import { CARD, INK, LINE, MUTED, PAGE_BG } from './Theme'; +import { + CARD, + INK, + LINE, + MUTED, + PAGE_BG, + TRANSPARENT, +} from './Theme'; @ComponentV2 struct WorkspaceFilterSection { @@ -31,7 +38,7 @@ struct WorkspaceFilterSection { .width('100%') .height(46) .padding({ left: 10, right: 10 }) - .backgroundColor(this.currentValue.length === 0 ? CARD : '#00000000') + .backgroundColor(this.currentValue.length === 0 ? CARD : TRANSPARENT) .border({ width: { bottom: 1 }, color: LINE }) .onClick(() => this.selectWorkspace('')) ForEach(this.options, (item: RecentWorkspaceEntry) => { @@ -52,7 +59,7 @@ struct WorkspaceFilterSection { .height(46) .padding({ left: 10, right: 10 }) .backgroundColor(ConversationSessionFilterPolicy.workspacePathsEqual(this.currentValue, item.path) - ? CARD : '#00000000') + ? CARD : TRANSPARENT) .border({ width: { bottom: 1 }, color: LINE }) .onClick(() => this.selectWorkspace(item.path)) }, (item: RecentWorkspaceEntry): string => item.path) @@ -216,7 +223,7 @@ export struct ConversationViewSettings { .width('100%') .height(48) .padding({ left: 10, right: 10 }) - .backgroundColor(this.selectedSortMode === mode ? CARD : '#00000000') + .backgroundColor(this.selectedSortMode === mode ? CARD : TRANSPARENT) .opacity(_revision % 2 === 0 ? 1 : 0.999) .border({ width: { bottom: 1 }, color: LINE }) .onClick(() => this.selectSortMode(mode)) @@ -240,7 +247,7 @@ export struct ConversationViewSettings { .width('100%') .height(46) .padding({ left: 10, right: 10 }) - .backgroundColor(selected ? CARD : '#00000000') + .backgroundColor(selected ? CARD : TRANSPARENT) .opacity(_revision % 2 === 0 ? 1 : 0.999) .border({ width: { bottom: 1 }, color: LINE }) .onClick(() => action(value)) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/FilePreviewSurface.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/FilePreviewSurface.ets index 41a1e4dec4..587b671071 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/FilePreviewSurface.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/FilePreviewSurface.ets @@ -30,7 +30,8 @@ import { LINE, MUTED, PAGE_BG, - SOFT + SOFT, + TRANSPARENT, } from './Theme'; @ComponentV2 @@ -330,7 +331,7 @@ export struct FilePreviewSurface { Span(token.text) .fontColor(this.syntaxTokenColor(token.kind)) .textBackgroundStyle({ - color: this.isTargetLine(token.lineNumber) ? CODE_TARGET_BG : '#00000000' + color: this.isTargetLine(token.lineNumber) ? CODE_TARGET_BG : TRANSPARENT }) }, (token: CodeSyntaxToken) => token.id) } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ModelServiceSettingsPanel.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ModelServiceSettingsPanel.ets index 7bf6f871c1..11d561d5a9 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ModelServiceSettingsPanel.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ModelServiceSettingsPanel.ets @@ -5,7 +5,7 @@ import { RemoteModelCatalog, RemoteModelConfig } from '../../model/RemoteModels' import { GENERAL_CHAT_LOCAL_MODEL_ID } from '../../services/general-chat/GeneralChatConfigStore'; import { ModelServiceSettingsPolicy } from '../policy/ModelServiceSettingsPolicy'; import { SettingsSheetState } from '../state/SettingsSheetState'; -import { CARD, GREEN, INK, LINE, MUTED, RED, SOFT, SUBTLE } from './Theme'; +import { CARD, INK, LINE, MUTED, SOFT, STATUS_DANGER, STATUS_SUCCESS, SUBTLE, TRANSPARENT } from './Theme'; import { SheetCloseHeader } from './SheetCloseHeader'; import { AppActionButton, AppActionStyle } from './AppActionButton'; @@ -216,7 +216,7 @@ export struct ModelServiceSettingsPanel { .width('100%') .height(ModelServiceSettingsPolicy.ACCOUNT_MODEL_ROW_HEIGHT) .padding({ left: 10, right: 10 }) - .backgroundColor(this.isSelectedModel(model) ? SOFT : '#00000000') + .backgroundColor(this.isSelectedModel(model) ? SOFT : TRANSPARENT) .borderRadius(9) .onClick(() => { this.onSelectModel(model.id); @@ -275,7 +275,7 @@ export struct ModelServiceSettingsPanel { Text(this.feedbackText) .fontSize(MobileDesignTypography.bodySmall.size) .lineHeight(MobileDesignTypography.bodySmall.lineHeight) - .fontColor(this.feedbackIsError ? RED : GREEN) + .fontColor(this.feedbackIsError ? STATUS_DANGER : STATUS_SUCCESS) .width('100%') } } @@ -504,7 +504,7 @@ export struct ModelServiceSettingsPanel { RemoteI18n.t('settings.modelService.clearKey')) .fontSize(MobileDesignTypography.bodySmall.size) .fontWeight(FontWeight.Medium) - .fontColor(this.sheetState.draftClearApiKey ? INK : RED) + .fontColor(this.sheetState.draftClearApiKey ? INK : STATUS_DANGER) .width('100%') .onClick(() => { this.sheetState.draftClearApiKey = !this.sheetState.draftClearApiKey; diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/NavigationBackButton.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/NavigationBackButton.ets index 4b57ca9a08..fa1b16d2dc 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/NavigationBackButton.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/NavigationBackButton.ets @@ -1,5 +1,6 @@ import { RemoteI18n } from '../../i18n/RemoteI18n'; import { TemplateIcon } from './TemplateIcon'; +import { TRANSPARENT } from './Theme'; /** App-wide floating page return affordance. */ @ComponentV2 @@ -19,7 +20,7 @@ export struct NavigationBackButton { .width(this.controlSize) .height(this.controlSize) .padding(0) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .borderRadius(12) .stateEffect(true) .opacity(this.isEnabled ? 1 : 0.4) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteControlSettingsSheet.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteControlSettingsSheet.ets index d054aa7ae1..34fa7b687e 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteControlSettingsSheet.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteControlSettingsSheet.ets @@ -1,6 +1,6 @@ import { MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RemoteI18n } from '../../i18n/RemoteI18n'; -import { CARD, INK, LINE, MUTED, PAGE_BG, RED, SOFT } from './Theme'; +import { CARD, INK, LINE, MUTED, PAGE_BG, SOFT, STATUS_DANGER } from './Theme'; import { CloudAccountDevice } from '../../services/CloudAccountClient'; import { RemotePermissionMode } from '../../model/RemoteModels'; import { DefaultAccountAvatar } from './DefaultAccountAvatar'; @@ -340,7 +340,7 @@ export struct RemoteControlSettingsSheet { .width('100%') .height(28) .fontSize(MobileDesignTypography.labelSmall.size) - .fontColor(this.permissionModeError.length > 0 ? RED : MUTED) + .fontColor(this.permissionModeError.length > 0 ? STATUS_DANGER : MUTED) .padding({ left: 18, right: 18, top: 4 }) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) @@ -398,7 +398,7 @@ export struct RemoteControlSettingsSheet { .width('100%') .fontSize(MobileDesignTypography.titleSmall.size) .fontWeight(FontWeight.Bold) - .fontColor(RED) + .fontColor(STATUS_DANGER) Text(RemoteI18n.t('remote.permissions.fullAccessWarningBody')) .width('100%') .fontSize(MobileDesignTypography.bodySmall.size) @@ -425,7 +425,7 @@ export struct RemoteControlSettingsSheet { .width('100%') .padding({ left: 16, right: 16, top: 14, bottom: 16 }) .backgroundColor(CARD) - .border({ width: 1, color: RED }) + .border({ width: 1, color: STATUS_DANGER }) .borderRadius(18) .margin({ left: 12, right: 12, bottom: 14 }) } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteSessionList.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteSessionList.ets index 73cfee96a8..128d462ae6 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteSessionList.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteSessionList.ets @@ -1,7 +1,16 @@ import { MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RecentWorkspaceEntry, RemoteSession } from '../../model/RemoteModels'; import { RemoteI18n } from '../../i18n/RemoteI18n'; -import { CARD, INK, MUTED, SOFT } from './Theme'; +import { + CARD, + FLOATING_BORDER, + INK, + MUTED, + SCRIM, + SHADOW_MEDIUM, + SOFT, + TRANSPARENT, +} from './Theme'; import { SessionActionPresentation, SessionActionSurface } from './SessionActionSurface'; import { AdaptiveSheetOptions } from './AdaptiveSheetOptions'; import { @@ -271,7 +280,7 @@ export struct RemoteSessionList { this.ProjectCreateMenu(project.path) }, placement: Placement.Top, - popupColor: '#00000000', + popupColor: TRANSPARENT, enableArrow: false, autoCancel: true, mask: false, @@ -325,8 +334,8 @@ export struct RemoteSessionList { .padding({ top: 8, bottom: 8 }) .backgroundColor(CARD) .borderRadius(14) - .border({ width: 1, color: '#18000000' }) - .shadow({ radius: 20, color: '#1A000000', offsetY: 8 }) + .border({ width: 1, color: FLOATING_BORDER }) + .shadow({ radius: 20, color: SHADOW_MEDIUM, offsetY: 8 }) } @Builder @@ -690,8 +699,8 @@ export struct RemoteSessionList { private sessionActionSheetOptions(): SheetOptions { return { height: 300, - backgroundColor: '#00000000', - maskColor: '#44000000', + backgroundColor: TRANSPARENT, + maskColor: SCRIM, showClose: false, dragBar: false }; diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteSessionRow.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteSessionRow.ets index 4a50bc5fb0..abd78bdd6a 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteSessionRow.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/RemoteSessionRow.ets @@ -2,7 +2,12 @@ import { MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RemoteSession } from '../../model/RemoteModels'; import { RemoteI18n } from '../../i18n/RemoteI18n'; import { SessionActionPresentation } from './SessionActionSurface'; -import { INK, MUTED, SOFT } from './Theme'; +import { + INK, + MUTED, + SOFT, + TRANSPARENT, +} from './Theme'; @ComponentV2 export struct RemoteSessionRow { @@ -55,7 +60,7 @@ export struct RemoteSessionRow { .height(this.metadata.length > 0 ? 56 : 46) .padding({ left: this.nested ? 0 : 10, right: 4 }) .alignItems(VerticalAlign.Center) - .backgroundColor(this.selected ? SOFT : '#00000000') + .backgroundColor(this.selected ? SOFT : TRANSPARENT) .borderRadius(10) .onTouch((event: TouchEvent) => { if (this.busy) return; @@ -69,7 +74,7 @@ export struct RemoteSessionRow { .bindPopup(this.actionPresentation === SessionActionPresentation.Popover && this.showActionPopover, { builder: () => { this.actionsPopup() }, placement: Placement.Right, - popupColor: '#00000000', + popupColor: TRANSPARENT, enableArrow: false, autoCancel: true, mask: false, diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SessionActionSurface.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SessionActionSurface.ets index 411055175f..4dc4a140cd 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SessionActionSurface.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SessionActionSurface.ets @@ -1,6 +1,6 @@ import { MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RemoteI18n } from '../../i18n/RemoteI18n'; -import { CARD, INK, LINE, MUTED, RED } from './Theme'; +import { CARD, INK, LINE, MUTED, SHADOW_MEDIUM, STATUS_DANGER, TRANSPARENT } from './Theme'; import { AppActionButton, AppActionStyle } from './AppActionButton'; export enum SessionActionPresentation { @@ -108,7 +108,7 @@ export struct SessionActionSurface { .borderRadius(16) .shadow({ radius: this.presentation === SessionActionPresentation.Popover ? 20 : 0, - color: this.presentation === SessionActionPresentation.Popover ? '#1A000000' : '#00000000', + color: this.presentation === SessionActionPresentation.Popover ? SHADOW_MEDIUM : TRANSPARENT, offsetY: this.presentation === SessionActionPresentation.Popover ? 8 : 0 }) .alignItems(HorizontalAlign.Center) @@ -121,7 +121,7 @@ export struct SessionActionSurface { Text(label) .layoutWeight(1) .fontSize(MobileDesignTypography.titleSmall.size) - .fontColor(destructive ? RED : INK) + .fontColor(destructive ? STATUS_DANGER : INK) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) } @@ -129,7 +129,7 @@ export struct SessionActionSurface { .height(46) .padding({ left: 10, right: 10 }) .borderRadius(8) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .onClick(action) } @@ -142,7 +142,7 @@ export struct SessionActionSurface { } else if (kind === 'archive') { SymbolGlyph($r('sys.symbol.archivebox')) .fontSize(19) - .fontColor([destructive ? RED : MUTED]) + .fontColor([destructive ? STATUS_DANGER : MUTED]) } else if (kind === 'export') { SymbolGlyph($r('sys.symbol.cloud')) .fontSize(19) @@ -150,7 +150,7 @@ export struct SessionActionSurface { } else { SymbolGlyph($r('sys.symbol.trash')) .fontSize(19) - .fontColor([RED]) + .fontColor([STATUS_DANGER]) } } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SheetCloseButton.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SheetCloseButton.ets index cde0b444b3..55336f6e5b 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SheetCloseButton.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SheetCloseButton.ets @@ -1,6 +1,6 @@ import { MobileDesignGeometry } from '../../generated/MobileDesignTokens'; import { RemoteI18n } from '../../i18n/RemoteI18n'; -import { INK } from './Theme'; +import { INK, TRANSPARENT } from './Theme'; /** Quiet top-right close affordance with a full-size touch target. */ @ComponentV2 @@ -19,7 +19,7 @@ export struct SheetCloseButton { .width(this.touchSize) .height(this.touchSize) .padding(0) - .backgroundColor('#00000000') + .backgroundColor(TRANSPARENT) .borderRadius(12) .stateEffect(true) .opacity(this.isEnabled ? 1 : 0.4) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarDeviceGroup.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarDeviceGroup.ets index 5c4c1f6e64..d88d1d1cbd 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarDeviceGroup.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarDeviceGroup.ets @@ -13,7 +13,14 @@ import { } from '../policy/SessionListProjection'; import { ConversationSessionFilterPolicy } from '../policy/ConversationSessionFilterPolicy'; import { SidebarDirectoryPreviewPolicy } from '../policy/SidebarDirectoryPreviewPolicy'; -import { GREEN, INK, MUTED, SOFT, SUBTLE } from './Theme'; +import { + INK, + MUTED, + SOFT, + STATUS_SUCCESS, + SUBTLE, + TRANSPARENT, +} from './Theme'; /** * One keyed disclosure boundary per workspace. Disclosure and request state @@ -187,7 +194,7 @@ struct SidebarWorkspaceGroup { Text('') .width(7) .height(7) - .backgroundColor(GREEN) + .backgroundColor(STATUS_SUCCESS) .borderRadius(4) } } @@ -205,7 +212,7 @@ struct SidebarWorkspaceGroup { .height(44) .padding({ left: this.bodyIndent + 34, right: 10 }) .alignItems(VerticalAlign.Center) - .backgroundColor(item.id === this.selectedSessionId ? SOFT : '#00000000') + .backgroundColor(item.id === this.selectedSessionId ? SOFT : TRANSPARENT) .borderRadius(10) .onClick(() => { this.onOpenSession(item); diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarGlyphs.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarGlyphs.ets index 11bdba7192..8ea984d339 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarGlyphs.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarGlyphs.ets @@ -1,4 +1,4 @@ -import { CARD, GREEN, INK, MUTED } from './Theme'; +import { CARD, STATUS_SUCCESS, INK, MUTED } from './Theme'; import { TemplateIcon } from './TemplateIcon'; @ComponentV2 @@ -46,7 +46,7 @@ export struct SidebarGlyph { Stack({ alignContent: Alignment.Center }) { if (this.connectionState === 'connected' || this.connectionState === 'reconnecting') { TemplateIcon({ src: $r('app.media.remote_ref_sidebar_connected'), iconWidth: 35, iconHeight: 34 }) - Text('').width(8).height(8).backgroundColor(GREEN).borderRadius(4) + Text('').width(8).height(8).backgroundColor(STATUS_SUCCESS).borderRadius(4) .position({ x: 24, y: 22 }) } else { TemplateIcon({ src: $r('app.media.remote_logo'), iconWidth: 34, iconHeight: 34, tint: MUTED }) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarToggleButton.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarToggleButton.ets index 0845df285f..341d421f9c 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarToggleButton.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarToggleButton.ets @@ -1,5 +1,12 @@ import { RemoteI18n } from '../../i18n/RemoteI18n'; -import { CARD, INK, LINE, MUTED } from './Theme'; +import { + CARD, + INK, + LINE, + MUTED, + SHADOW_SUBTLE, + TRANSPARENT, +} from './Theme'; @ComponentV2 export struct SidebarToggleButton { @@ -33,12 +40,12 @@ export struct SidebarToggleButton { } .width(this.controlSize) .height(this.controlSize) - .backgroundColor(this.restore ? CARD : '#00000000') + .backgroundColor(this.restore ? CARD : TRANSPARENT) .border({ width: this.restore ? 1 : 0, color: LINE }) .borderRadius(this.restore ? this.controlSize / 2 : 8) .shadow({ radius: this.restore ? 14 : 0, - color: this.restore ? '#12000000' : '#00000000', + color: this.restore ? SHADOW_SUBTLE : TRANSPARENT, offsetY: this.restore ? 5 : 0 }) .accessibilityText(RemoteI18n.t(this.restore ? 'sidebar.restore' : 'sidebar.collapse')) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarWorkspaceSection.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarWorkspaceSection.ets index 34290d8221..500c000db5 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarWorkspaceSection.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SidebarWorkspaceSection.ets @@ -15,7 +15,7 @@ import { SettingsSheetKind } from '../policy/SettingsPlacementPolicy'; import { AdaptiveSheetOptions } from './AdaptiveSheetOptions'; -import { GREEN, INK, MUTED, SUBTLE } from './Theme'; +import { STATUS_SUCCESS, INK, MUTED, SUBTLE } from './Theme'; import { SidebarDeviceGroup } from './SidebarDeviceGroup'; import { SidebarChevronIcon, @@ -165,7 +165,7 @@ export struct SidebarWorkspaceSection { Text('') .width(8) .height(8) - .backgroundColor(entry.online ? GREEN : SUBTLE) + .backgroundColor(entry.online ? STATUS_SUCCESS : SUBTLE) .borderRadius(4) .hitTestBehavior(HitTestMode.None) } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SubagentTaskCard.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SubagentTaskCard.ets index d96e9af28d..396ebcd3e8 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SubagentTaskCard.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/SubagentTaskCard.ets @@ -2,7 +2,15 @@ import { MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RemoteI18n } from '../../i18n/RemoteI18n'; import { ConversationUiMessageItem, ConversationUiQuestionAnswer } from '../state/ConversationUiModels'; import { ChatMessageStructurePolicy } from '../policy/ChatMessageStructurePolicy'; -import { CARD, INK, LINE, MUTED, RED, SOFT } from './Theme'; +import { + CARD, + INK, + LINE, + MUTED, + SOFT, + STATUS_DANGER, + TRANSPARENT, +} from './Theme'; import { ThinkingBlock } from './ThinkingBlock'; import { ToolStatusList } from './ToolStatusList'; import { ToolGlyph } from './ToolGlyphs'; @@ -28,13 +36,13 @@ export struct SubagentTaskCard { Row({ space: 8 }) { Stack({ alignContent: Alignment.BottomEnd }) { Stack({ alignContent: Alignment.Center }) { - ToolGlyph({ kind: 'task', color: this.isError() ? RED : MUTED }) + ToolGlyph({ kind: 'task', color: this.isError() ? STATUS_DANGER : MUTED }) } .width(18) .height(18) .backgroundColor(SOFT) .borderRadius(5) - .border({ width: 1, color: this.isError() ? RED : LINE }) + .border({ width: 1, color: this.isError() ? STATUS_DANGER : LINE }) if (this.isRunning() || this.isError()) { Text(this.isError() ? '!' : '•') .width(10) @@ -43,7 +51,7 @@ export struct SubagentTaskCard { .fontWeight(FontWeight.Bold) .fontColor(CARD) .textAlign(TextAlign.Center) - .backgroundColor(this.isError() ? RED : MUTED) + .backgroundColor(this.isError() ? STATUS_DANGER : MUTED) .borderRadius(5) .border({ width: 1, color: CARD }) } @@ -52,13 +60,13 @@ export struct SubagentTaskCard { .height(20) Text(this.title) .fontSize(MobileDesignTypography.bodySmall.size) - .fontColor(this.isError() ? RED : MUTED) + .fontColor(this.isError() ? STATUS_DANGER : MUTED) .layoutWeight(1) .maxLines(1) .textOverflow({ overflow: TextOverflow.Ellipsis }) Text(this.statusText()) .fontSize(MobileDesignTypography.labelSmall.size) - .fontColor(this.isError() ? RED : MUTED) + .fontColor(this.isError() ? STATUS_DANGER : MUTED) .maxLines(1) if (this.hasProcessItems()) { SymbolGlyph(this.expanded ? $r('sys.symbol.chevron_up') : $r('sys.symbol.chevron_down')) @@ -87,7 +95,7 @@ export struct SubagentTaskCard { top: this.isEmphasized() ? 6 : 0, bottom: this.isEmphasized() ? 6 : 0 }) - .backgroundColor(this.isEmphasized() || this.expanded ? SOFT : '#00000000') + .backgroundColor(this.isEmphasized() || this.expanded ? SOFT : TRANSPARENT) .borderRadius(this.isEmphasized() ? 14 : 8) .border({ width: this.isEmphasized() || this.expanded ? 1 : 0, color: LINE }) .accessibilityText(`${this.title}, ${this.statusText()}`) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/Theme.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/Theme.ets index c368ccd746..9118db74cf 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/Theme.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/Theme.ets @@ -1,6 +1,7 @@ export const PAGE_BG: ResourceColor = $r('app.color.page_bg'); /** PAGE_BG at zero alpha, per theme — the transparent end of a fade-out. */ export const PAGE_BG_FADE: ResourceColor = $r('app.color.page_bg_fade'); +export const TRANSPARENT: ResourceColor = $r('app.color.transparent'); export const INK: ResourceColor = $r('app.color.ink'); export const MUTED: ResourceColor = $r('app.color.muted'); export const SUBTLE: ResourceColor = $r('app.color.subtle'); @@ -9,17 +10,27 @@ export const CARD: ResourceColor = $r('app.color.card'); export const ACCENT: ResourceColor = $r('app.color.accent'); export const FILE_LINK: ResourceColor = $r('app.color.file_link'); export const PRIMARY_ACTION: ResourceColor = $r('app.color.primary_action'); -export const PRIMARY_ACTION_TEXT: ResourceColor = $r('app.color.primary_action_text'); +export const CONTENT_ON_ACTION: ResourceColor = $r('app.color.content_on_action'); export const CONNECT_HERO_BG: ResourceColor = $r('app.color.connect_hero_bg'); export const CONNECT_HERO_ACCENT: ResourceColor = $r('app.color.connect_hero_accent'); export const CONNECT_HERO_SECONDARY: ResourceColor = $r('app.color.connect_hero_secondary'); export const CONNECT_HERO_SURFACE: ResourceColor = $r('app.color.connect_hero_surface'); export const CONNECT_SCAN_ACCENT: ResourceColor = $r('app.color.connect_scan_accent'); -export const MODAL_SCRIM: ResourceColor = $r('app.color.modal_scrim'); +export const SCRIM: ResourceColor = $r('app.color.scrim'); +export const SHELL_SCRIM: ResourceColor = $r('app.color.shell_scrim'); +export const MEDIA_BACKGROUND: ResourceColor = $r('app.color.media_background'); +export const MEDIA_SCRIM: ResourceColor = $r('app.color.media_scrim'); +export const MEDIA_CONTROL_BACKGROUND: ResourceColor = $r('app.color.media_control_background'); +export const TOAST_BACKGROUND: ResourceColor = $r('app.color.toast_background'); +export const SHADOW_FAINT: ResourceColor = $r('app.color.shadow_faint'); +export const SHADOW_SUBTLE: ResourceColor = $r('app.color.shadow_subtle'); +export const SHADOW_MEDIUM: ResourceColor = $r('app.color.shadow_medium'); +export const SHADOW_STRONG: ResourceColor = $r('app.color.shadow_strong'); +export const FLOATING_BORDER: ResourceColor = $r('app.color.floating_border'); export const SOFT: ResourceColor = $r('app.color.soft'); export const FLOATING_PANEL_BG: ResourceColor = $r('app.color.floating_panel_bg'); -export const GREEN: ResourceColor = $r('app.color.green'); -export const RED: ResourceColor = $r('app.color.red'); +export const STATUS_SUCCESS: ResourceColor = $r('app.color.status_success'); +export const STATUS_DANGER: ResourceColor = $r('app.color.status_danger'); export const CODE_LINE_NUMBER: ResourceColor = $r('app.color.code_line_number'); export const CODE_KEYWORD: ResourceColor = $r('app.color.code_keyword'); export const CODE_STRING: ResourceColor = $r('app.color.code_string'); diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ToolInteractionPanels.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ToolInteractionPanels.ets index ef53e2c5f5..7eefbd01df 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ToolInteractionPanels.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ToolInteractionPanels.ets @@ -1,7 +1,7 @@ import { MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RemoteI18n } from '../../i18n/RemoteI18n'; import { ConversationUiQuestionAnswer } from '../state/ConversationUiModels'; -import { ACCENT, CARD, INK, LINE, MUTED, PRIMARY_ACTION_TEXT, RED, SOFT } from './Theme'; +import { ACCENT, CARD, INK, LINE, MUTED, CONTENT_ON_ACTION, STATUS_DANGER, SOFT } from './Theme'; interface QuestionOption { label: string; @@ -42,7 +42,7 @@ export struct ToolConfirmationPanel { Row({ space: 8 }) { Text(RemoteI18n.t('chat.approve')) .fontSize(MobileDesignTypography.labelMedium.size) - .fontColor(PRIMARY_ACTION_TEXT) + .fontColor(CONTENT_ON_ACTION) .textAlign(TextAlign.Center) .height(32) .layoutWeight(1) @@ -89,7 +89,7 @@ export struct ToolConfirmationPanel { .backgroundColor(SOFT) .borderRadius(14) .padding(10) - .border({ width: 1, color: this.inputError.length > 0 ? RED : LINE }) + .border({ width: 1, color: this.inputError.length > 0 ? STATUS_DANGER : LINE }) .defaultFocus(false) .enabled(true) .onChange((value: string) => { @@ -97,7 +97,7 @@ export struct ToolConfirmationPanel { this.inputError = ''; }) if (this.inputError.length > 0) { - Text(this.inputError).fontSize(MobileDesignTypography.labelSmall.size).fontColor(RED) + Text(this.inputError).fontSize(MobileDesignTypography.labelSmall.size).fontColor(STATUS_DANGER) } } .width('100%') @@ -160,7 +160,7 @@ export struct ToolQuestionAnswerPanel { Row() { Text(RemoteI18n.t('chat.submitAnswer')) .fontSize(MobileDesignTypography.labelMedium.size) - .fontColor(this.canSubmit() ? PRIMARY_ACTION_TEXT : MUTED) + .fontColor(this.canSubmit() ? CONTENT_ON_ACTION : MUTED) .textAlign(TextAlign.Center) .height(32) .layoutWeight(1) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ToolStatusList.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ToolStatusList.ets index 80bc1cb6f3..bc081ce77b 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ToolStatusList.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/ToolStatusList.ets @@ -5,7 +5,17 @@ import { ToolFileReference, ToolFileReferenceResolver } from '../policy/ToolFile import { ActivityGroupPolicy, ActivityRowPlan, ActivityThinkingPart } from '../policy/ActivityGroupPolicy'; import { ToolCollapseGroup, ToolCollapsePolicy } from '../policy/ToolCollapsePolicy'; import { ToolStatusPresentationPolicy } from '../policy/ToolStatusPresentationPolicy'; -import { CARD, FILE_LINK, GREEN, INK, LINE, MUTED, RED, SOFT } from './Theme'; +import { + CARD, + FILE_LINK, + INK, + LINE, + MUTED, + SOFT, + STATUS_DANGER, + STATUS_SUCCESS, + TRANSPARENT, +} from './Theme'; import { ThinkingBlock } from './ThinkingBlock'; import { ToolGlyph } from './ToolGlyphs'; import { ToolConfirmationPanel, ToolQuestionAnswerPanel } from './ToolInteractionPanels'; @@ -120,7 +130,7 @@ export struct ToolStatusList { this.ToolStatusIcon(tool) Text(this.toolLineLabel(tool)) .fontSize(MobileDesignTypography.bodySmall.size) - .fontColor(this.hasToolError(tool) ? RED : + .fontColor(this.hasToolError(tool) ? STATUS_DANGER : (this.toolFilePath(tool).length > 0 ? FILE_LINK : MUTED)) .layoutWeight(1) .maxLines(1) @@ -235,7 +245,7 @@ export struct ToolStatusList { .height(18) .backgroundColor(this.summaryTypeBg(entry)) .borderRadius(5) - .border({ width: 1, color: '#00000000' }) + .border({ width: 1, color: TRANSPARENT }) } @Builder @@ -288,7 +298,7 @@ export struct ToolStatusList { Text(value) .fontSize(MobileDesignTypography.labelSmall.size) .lineHeight(MobileDesignTypography.labelSmall.lineHeight) - .fontColor(isError ? RED : MUTED) + .fontColor(isError ? STATUS_DANGER : MUTED) .width('100%') .maxLines(5) .textOverflow({ overflow: TextOverflow.Ellipsis }) @@ -329,7 +339,7 @@ export struct ToolStatusList { if (this.isEmphasizedToolRow(tool, index)) { return SOFT; } - return '#00000000'; + return TRANSPARENT; } private toolRowBorderWidth(tool: ConversationUiToolStatus, index: number): number { @@ -719,10 +729,10 @@ export struct ToolStatusList { private toolTypeColor(tool: ConversationUiToolStatus): ResourceColor { if (this.isDeleteTool(tool)) { - return RED; + return STATUS_DANGER; } if (this.isTodoTool(tool) || this.isFileCreateTool(tool)) { - return GREEN; + return STATUS_SUCCESS; } return MUTED; } @@ -733,7 +743,7 @@ export struct ToolStatusList { private toolTypeBorderColor(tool: ConversationUiToolStatus): ResourceColor { if (this.hasToolError(tool)) { - return RED; + return STATUS_DANGER; } return LINE; } @@ -757,7 +767,7 @@ export struct ToolStatusList { private toolStatusColor(tool: ConversationUiToolStatus): ResourceColor { if (this.hasToolError(tool)) { - return RED; + return STATUS_DANGER; } return MUTED; } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/WatchProvisionCard.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/WatchProvisionCard.ets index e627539e1f..35fe15f1e4 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/WatchProvisionCard.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/WatchProvisionCard.ets @@ -1,7 +1,7 @@ import { MobileDesignTypography } from '../../generated/MobileDesignTokens'; import { RemoteI18n } from '../../i18n/RemoteI18n'; import { WatchProvisionPhase, WatchProvisionState } from '../state/WatchProvisionState'; -import { CARD, GREEN, INK, LINE, MODAL_SCRIM, MUTED, PRIMARY_ACTION, PRIMARY_ACTION_TEXT, RED, SOFT, +import { CARD, STATUS_SUCCESS, INK, LINE, SCRIM, MUTED, PRIMARY_ACTION, CONTENT_ON_ACTION, STATUS_DANGER, SOFT, SUBTLE } from './Theme'; /** @@ -23,7 +23,7 @@ export struct WatchProvisionCard { Text('') .width('100%') .height('100%') - .backgroundColor(MODAL_SCRIM) + .backgroundColor(SCRIM) .onClick(() => { // Tapping away while the desktop is minting would leave the watch // with no answer and no card to explain it. @@ -88,7 +88,7 @@ export struct WatchProvisionCard { Text(this.state.message) .fontSize(MobileDesignTypography.bodySmall.size) .lineHeight(MobileDesignTypography.bodySmall.lineHeight) - .fontColor(RED) + .fontColor(STATUS_DANGER) .width('100%') } } @@ -110,7 +110,7 @@ export struct WatchProvisionCard { Text(this.state.message) .fontSize(MobileDesignTypography.bodyLarge.size) .lineHeight(MobileDesignTypography.bodyLarge.lineHeight) - .fontColor(this.state.phase === WatchProvisionPhase.Done ? GREEN : RED) + .fontColor(this.state.phase === WatchProvisionPhase.Done ? STATUS_SUCCESS : STATUS_DANGER) .width('100%') } @@ -130,7 +130,7 @@ export struct WatchProvisionCard { .height(56) .fontSize(MobileDesignTypography.labelLarge.size) .fontWeight(FontWeight.Bold) - .fontColor(PRIMARY_ACTION_TEXT) + .fontColor(CONTENT_ON_ACTION) .backgroundColor(PRIMARY_ACTION) .borderRadius(28) .onClick(() => { this.onApprove(''); }) @@ -155,7 +155,7 @@ export struct WatchProvisionCard { .height(56) .fontSize(MobileDesignTypography.labelLarge.size) .fontWeight(FontWeight.Bold) - .fontColor(PRIMARY_ACTION_TEXT) + .fontColor(CONTENT_ON_ACTION) .backgroundColor(PRIMARY_ACTION) .borderRadius(28) .enabled(this.password.length > 0) @@ -173,7 +173,7 @@ export struct WatchProvisionCard { .height(56) .fontSize(MobileDesignTypography.labelLarge.size) .fontWeight(FontWeight.Bold) - .fontColor(PRIMARY_ACTION_TEXT) + .fontColor(CONTENT_ON_ACTION) .backgroundColor(PRIMARY_ACTION) .borderRadius(28) .onClick(this.onDismiss) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/WideConversationHost.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/WideConversationHost.ets index 97d6028435..9af1b41574 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/WideConversationHost.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/WideConversationHost.ets @@ -26,7 +26,12 @@ import { } from './remote/RemoteSurfaceHost'; import { SidebarToggleButton } from './SidebarToggleButton'; import { SidebarWorkspaceSection } from './SidebarWorkspaceSection'; -import { FLOATING_PANEL_BG, LINE, PAGE_BG } from './Theme'; +import { + FLOATING_PANEL_BG, + LINE, + PAGE_BG, + SHADOW_SUBTLE, +} from './Theme'; const WIDE_DETAIL_CONTENT_MAX_WIDTH: number = 920; @@ -171,7 +176,7 @@ export struct WideConversationHost { } .width('100%').height('100%').backgroundColor(FLOATING_PANEL_BG) .borderRadius(18).clip(true) - .shadow({ radius: 24, color: '#14000000', offsetX: 4, offsetY: 8 }) + .shadow({ radius: 24, color: SHADOW_SUBTLE, offsetX: 4, offsetY: 8 }) } .width(WideLayoutGeometry.masterPaneWidth(this.filePreviewLayout, this.wideMasterPaneWidth)) .height('100%').padding({ left: 10, right: 6, top: 10, bottom: 10 }).backgroundColor(PAGE_BG) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/remote/RemoteSurfaceHost.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/remote/RemoteSurfaceHost.ets index 705b8996d7..cb610ea4d2 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/remote/RemoteSurfaceHost.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/remote/RemoteSurfaceHost.ets @@ -20,7 +20,7 @@ import { SettingsPlacementPolicy, SettingsSheetKind } from '../../policy/SettingsPlacementPolicy'; -import { CARD, GREEN, INK, LINE, MUTED, PAGE_BG, PRIMARY_ACTION, PRIMARY_ACTION_TEXT, RED } from '../Theme'; +import { CARD, STATUS_SUCCESS, INK, LINE, MUTED, PAGE_BG, PRIMARY_ACTION, CONTENT_ON_ACTION, STATUS_DANGER } from '../Theme'; export enum RemoteSurfaceMode { Master = 'master', @@ -150,7 +150,7 @@ export struct RemoteSurfaceHost { Text(RemoteI18n.t('remote.settings.reconnect')) .fontSize(MobileDesignTypography.bodySmall.size) .fontWeight(FontWeight.Medium) - .fontColor(PRIMARY_ACTION_TEXT) + .fontColor(CONTENT_ON_ACTION) .height(28) .padding({ left: 12, right: 12 }) .backgroundColor(PRIMARY_ACTION) @@ -194,7 +194,7 @@ export struct RemoteSurfaceHost { Text(RemoteI18n.t('remote.connectText')) .fontSize(MobileDesignTypography.bodySmall.size).lineHeight(MobileDesignTypography.bodySmall.lineHeight).fontColor(MUTED).textAlign(TextAlign.Center) Text(RemoteI18n.t('connect.connect')) - .width(136).height(44).fontSize(MobileDesignTypography.titleSmall.size).fontColor(PRIMARY_ACTION_TEXT) + .width(136).height(44).fontSize(MobileDesignTypography.titleSmall.size).fontColor(CONTENT_ON_ACTION) .backgroundColor(PRIMARY_ACTION).textAlign(TextAlign.Center).borderRadius(22) .onClick(() => this.actions.onRemoteHome.connectWorkspace()) } @@ -244,13 +244,13 @@ export struct RemoteSurfaceHost { if (this.canReconnect()) { Text(RemoteI18n.t('remote.settings.reconnect')) .width(148).height(46).fontSize(MobileDesignTypography.titleSmall.size).fontWeight(FontWeight.Medium) - .fontColor(PRIMARY_ACTION_TEXT).backgroundColor(PRIMARY_ACTION) + .fontColor(CONTENT_ON_ACTION).backgroundColor(PRIMARY_ACTION) .textAlign(TextAlign.Center).borderRadius(23).margin({ top: 12 }) .onClick(() => this.actions.onRemoteHome.reconnect()) } else { Text(RemoteI18n.t('remote.startSession')) .width(148).height(46).fontSize(MobileDesignTypography.titleSmall.size).fontWeight(FontWeight.Medium) - .fontColor(PRIMARY_ACTION_TEXT).backgroundColor(PRIMARY_ACTION) + .fontColor(CONTENT_ON_ACTION).backgroundColor(PRIMARY_ACTION) .textAlign(TextAlign.Center).borderRadius(23).margin({ top: 12 }) .onClick(() => this.createSession('code')) } @@ -401,9 +401,9 @@ export struct RemoteSurfaceHost { } private statusColor(): ResourceColor { - if (this.remotePageState.connectionState === 'connected') return GREEN; + if (this.remotePageState.connectionState === 'connected') return STATUS_SUCCESS; if (this.remotePageState.connectionState === 'failed' || this.remotePageState.connectionState === 'disconnected') { - return RED; + return STATUS_DANGER; } return MUTED; } diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/preview/MobileDesignGallery.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/preview/MobileDesignGallery.ets index 08c1801201..0931b6fb20 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/preview/MobileDesignGallery.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/preview/MobileDesignGallery.ets @@ -6,7 +6,7 @@ import { } from '../../generated/MobilePreviewScenarios'; import { ComposerBar, ComposerPresentation } from '../components/ComposerBar'; import { ConversationHeader } from '../components/ConversationHeader'; -import { INK, LINE, MUTED, PAGE_BG, SOFT } from '../components/Theme'; +import { INK, LINE, MUTED, PAGE_BG, SOFT, TRANSPARENT } from '../components/Theme'; @Entry @ComponentV2 @@ -104,7 +104,7 @@ struct MobileDesignGallery { top: message.role === 'user' ? MobileDesignGeometry.messageBubbleVerticalPadding : 2, bottom: message.role === 'user' ? MobileDesignGeometry.messageBubbleVerticalPadding : 2 }) - .backgroundColor(message.role === 'user' ? SOFT : '#00000000') + .backgroundColor(message.role === 'user' ? SOFT : TRANSPARENT) .borderRadius(message.role === 'user' ? MobileDesignGeometry.messageBubbleRadius : 0) if (message.role !== 'user') { Blank() diff --git a/src/apps/mobile/harmonyos/entry/src/main/resources/base/element/color.json b/src/apps/mobile/harmonyos/entry/src/main/resources/base/element/color.json index cdce3f4543..46f9729710 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/resources/base/element/color.json +++ b/src/apps/mobile/harmonyos/entry/src/main/resources/base/element/color.json @@ -4,6 +4,10 @@ "name": "start_window_background", "value": "#FFFFFF" }, + { + "name": "transparent", + "value": "#00000000" + }, { "name": "page_bg", "value": "#FFFFFF" @@ -45,7 +49,7 @@ "value": "#111111" }, { - "name": "primary_action_text", + "name": "content_on_action", "value": "#FFFFFF" }, { @@ -69,9 +73,49 @@ "value": "#FFD021" }, { - "name": "modal_scrim", + "name": "scrim", "value": "#44000000" }, + { + "name": "shell_scrim", + "value": "#24000000" + }, + { + "name": "media_background", + "value": "#FF000000" + }, + { + "name": "media_scrim", + "value": "#B8000000" + }, + { + "name": "media_control_background", + "value": "#8C000000" + }, + { + "name": "toast_background", + "value": "#D1171717" + }, + { + "name": "shadow_faint", + "value": "#08000000" + }, + { + "name": "shadow_subtle", + "value": "#12000000" + }, + { + "name": "shadow_medium", + "value": "#18000000" + }, + { + "name": "shadow_strong", + "value": "#24000000" + }, + { + "name": "floating_border", + "value": "#18000000" + }, { "name": "soft", "value": "#F4F3F0" @@ -81,11 +125,11 @@ "value": "#F7F7F5" }, { - "name": "green", + "name": "status_success", "value": "#27C46A" }, { - "name": "red", + "name": "status_danger", "value": "#E04F4F" }, { diff --git a/src/apps/mobile/harmonyos/entry/src/main/resources/dark/element/color.json b/src/apps/mobile/harmonyos/entry/src/main/resources/dark/element/color.json index e29074a8f5..6d08d86a85 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/resources/dark/element/color.json +++ b/src/apps/mobile/harmonyos/entry/src/main/resources/dark/element/color.json @@ -4,6 +4,10 @@ "name": "start_window_background", "value": "#000000" }, + { + "name": "transparent", + "value": "#00000000" + }, { "name": "page_bg", "value": "#151514" @@ -45,7 +49,7 @@ "value": "#454540" }, { - "name": "primary_action_text", + "name": "content_on_action", "value": "#FFFFFF" }, { @@ -69,9 +73,49 @@ "value": "#FFD021" }, { - "name": "modal_scrim", + "name": "scrim", "value": "#44000000" }, + { + "name": "shell_scrim", + "value": "#24000000" + }, + { + "name": "media_background", + "value": "#FF000000" + }, + { + "name": "media_scrim", + "value": "#B8000000" + }, + { + "name": "media_control_background", + "value": "#8C000000" + }, + { + "name": "toast_background", + "value": "#D1171717" + }, + { + "name": "shadow_faint", + "value": "#08000000" + }, + { + "name": "shadow_subtle", + "value": "#12000000" + }, + { + "name": "shadow_medium", + "value": "#18000000" + }, + { + "name": "shadow_strong", + "value": "#24000000" + }, + { + "name": "floating_border", + "value": "#18000000" + }, { "name": "soft", "value": "#2D2C28" @@ -81,11 +125,11 @@ "value": "#1E1E1C" }, { - "name": "green", + "name": "status_success", "value": "#3BD47B" }, { - "name": "red", + "name": "status_danger", "value": "#FF6B6B" }, { diff --git a/src/apps/mobile/ios/BitFun/Features/Account/AccountSettingsView.swift b/src/apps/mobile/ios/BitFun/Features/Account/AccountSettingsView.swift index 1dd2a2332d..64f73489e9 100644 --- a/src/apps/mobile/ios/BitFun/Features/Account/AccountSettingsView.swift +++ b/src/apps/mobile/ios/BitFun/Features/Account/AccountSettingsView.swift @@ -59,7 +59,7 @@ struct AccountSettingsView: View { if let error = model.coreErrorMessage, !error.isEmpty { Text(error) .font(.system(size: 13)) - .foregroundStyle(BitFunTheme.red) + .foregroundStyle(BitFunTheme.statusDanger) .padding(.top, 12) } @@ -68,11 +68,11 @@ struct AccountSettingsView: View { password = "" } label: { HStack(spacing: 8) { - if model.accountBusy { ProgressView().tint(.white) } + if model.accountBusy { ProgressView().tint(BitFunTheme.contentOnAction) } Text(model.localized(model.accountBusy ? "正在登录" : "登录")) } .font(.system(size: 17, weight: .bold)) - .foregroundStyle(.white) + .foregroundStyle(BitFunTheme.contentOnAction) .frame(maxWidth: .infinity, minHeight: 56) .background(canLogin ? BitFunTheme.accent : BitFunTheme.muted.opacity(0.35)) .clipShape(RoundedRectangle(cornerRadius: 18)) @@ -117,11 +117,11 @@ struct AccountSettingsView: View { Button { model.retryAccountFailure() } label: { HStack(spacing: 8) { - if model.accountBusy { ProgressView().tint(.white) } + if model.accountBusy { ProgressView().tint(BitFunTheme.contentOnAction) } Text(model.localized(model.accountBusy ? "正在重试" : "重试加载设备")) } .font(.system(size: 17, weight: .bold)) - .foregroundStyle(.white) + .foregroundStyle(BitFunTheme.contentOnAction) .frame(maxWidth: .infinity, minHeight: 56) .background(BitFunTheme.accent) .clipShape(RoundedRectangle(cornerRadius: 18)) @@ -184,7 +184,7 @@ struct AccountSettingsView: View { Spacer() Text(model.localized("已登录")) .font(.system(size: 14)) - .foregroundStyle(BitFunTheme.green) + .foregroundStyle(BitFunTheme.statusSuccess) } Text(model.localizedFormat("当前以 %@ 登录。", model.accountUser ?? "")) .font(.system(size: 14)) @@ -259,7 +259,7 @@ struct AccountSettingsView: View { } label: { Text(model.localized("退出账号")) .font(.system(size: 16, weight: .medium)) - .foregroundStyle(BitFunTheme.red) + .foregroundStyle(BitFunTheme.statusDanger) .frame(maxWidth: .infinity, minHeight: 54) .background(BitFunTheme.card) .clipShape(RoundedRectangle(cornerRadius: 16)) @@ -344,13 +344,13 @@ struct SettingsDeviceRow: View { .lineLimit(1) Text(MobileLocalization.text(device.online ? "在线" : "离线")) .font(.system(size: 12)) - .foregroundStyle(device.online ? BitFunTheme.green : BitFunTheme.muted) + .foregroundStyle(device.online ? BitFunTheme.statusSuccess : BitFunTheme.muted) } Spacer(minLength: 12) if device.selected { Image(systemName: "checkmark.circle.fill") .font(.system(size: 18)) - .foregroundStyle(BitFunTheme.green) + .foregroundStyle(BitFunTheme.statusSuccess) } else { Image(systemName: "chevron.right") .font(.system(size: 14, weight: .medium)) diff --git a/src/apps/mobile/ios/BitFun/Features/Chat/ChatTimelineView.swift b/src/apps/mobile/ios/BitFun/Features/Chat/ChatTimelineView.swift index d2f5f7b76d..e87810eba4 100644 --- a/src/apps/mobile/ios/BitFun/Features/Chat/ChatTimelineView.swift +++ b/src/apps/mobile/ios/BitFun/Features/Chat/ChatTimelineView.swift @@ -29,7 +29,7 @@ struct ChatTimelineView: View { if model.timelineRows.isEmpty && model.isSending { TypingIndicator().frame(maxWidth: .infinity, alignment: .leading) } - Color.clear.frame(height: 1).id("timeline-bottom") + BitFunTheme.transparent.frame(height: 1).id("timeline-bottom") } .padding(.horizontal, MobileDesignGeometry.contentGutter) .padding(.top, MobileDesignGeometry.timelineTopPadding) @@ -61,7 +61,7 @@ struct ChatTimelineView: View { .background(BitFunTheme.card) .clipShape(Circle()) .overlay(Circle().stroke(BitFunTheme.line, lineWidth: 1)) - .shadow(color: .black.opacity(0.09), radius: 8, y: 3) + .shadow(color: BitFunTheme.shadowMedium, radius: 8, y: 3) } .buttonStyle(.plain) .padding(18) @@ -112,7 +112,7 @@ private struct ConversationRowView: View { Button { model.retryMessage(row.text) } label: { Label(model.localized("重新发送"), systemImage: "arrow.clockwise") .font(MobileDesignTypography.labelSmall.font) - .foregroundStyle(BitFunTheme.red) + .foregroundStyle(BitFunTheme.statusDanger) } .buttonStyle(.plain) } @@ -143,7 +143,7 @@ private struct ConversationRowView: View { Button { model.retryMessage(row.text) } label: { Label(model.localized("重试"), systemImage: "arrow.clockwise") .font(MobileDesignTypography.labelSmall.font) - .foregroundStyle(BitFunTheme.red) + .foregroundStyle(BitFunTheme.statusDanger) } .buttonStyle(.plain) } @@ -415,7 +415,7 @@ private struct FileReferenceCard: View { .foregroundStyle(BitFunTheme.muted).lineLimit(1) if let status = model.downloadStatus(for: reference.remotePath) { Text(status).font(MobileDesignTypography.labelSmall.font) - .foregroundStyle(model.downloadPhase == .failed ? BitFunTheme.red : BitFunTheme.muted) + .foregroundStyle(model.downloadPhase == .failed ? BitFunTheme.statusDanger : BitFunTheme.muted) .lineLimit(1) } } @@ -478,11 +478,11 @@ private struct FullScreenTimelineImage: View { var body: some View { ZStack(alignment: .topTrailing) { - Color.black.ignoresSafeArea() + BitFunTheme.mediaBackground.ignoresSafeArea() if let uiImage = image.uiImage { Image(uiImage: uiImage).resizable().scaledToFit().ignoresSafeArea() } Button { dismiss() } label: { - Image(systemName: "xmark").font(.system(size: 15, weight: .semibold)).foregroundStyle(.white) - .frame(width: 44, height: 44).background(Color.black.opacity(0.55)).clipShape(Circle()) + Image(systemName: "xmark").font(.system(size: 15, weight: .semibold)).foregroundStyle(BitFunTheme.contentOnAction) + .frame(width: 44, height: 44).background(BitFunTheme.mediaControlBackground).clipShape(Circle()) } .buttonStyle(.plain).padding(20) } @@ -624,14 +624,14 @@ private struct ToolStatusRow: View { if tool.actions.contains("CANCEL") { Button { model.cancelTool(tool.id) } label: { Text(model.localized("停止执行")) - .font(MobileDesignTypography.labelMedium.font).foregroundStyle(BitFunTheme.red) + .font(MobileDesignTypography.labelMedium.font).foregroundStyle(BitFunTheme.statusDanger) .frame(maxWidth: .infinity, minHeight: 40).background(BitFunTheme.card).clipShape(Capsule()) - .overlay(Capsule().stroke(BitFunTheme.red.opacity(0.5), lineWidth: 1)) + .overlay(Capsule().stroke(BitFunTheme.statusDanger.opacity(0.5), lineWidth: 1)) } .buttonStyle(.plain) } } - .padding(emphasized ? 10 : 0).background(emphasized ? BitFunTheme.soft : Color.clear) + .padding(emphasized ? 10 : 0).background(emphasized ? BitFunTheme.soft : BitFunTheme.transparent) .clipShape(RoundedRectangle(cornerRadius: 14)) .overlay { if emphasized { RoundedRectangle(cornerRadius: 14).stroke(BitFunTheme.line, lineWidth: 1) } } } @@ -646,7 +646,7 @@ private struct ToolStatusRow: View { .overlay(RoundedRectangle(cornerRadius: 11).stroke(BitFunTheme.line, lineWidth: 1)) Button { model.answerTool(tool.id, answer: answer); answer = "" } label: { Text(model.localized("发送回复")) - .font(MobileDesignTypography.labelMedium.font).foregroundStyle(.white) + .font(MobileDesignTypography.labelMedium.font).foregroundStyle(BitFunTheme.contentOnAction) .frame(maxWidth: .infinity, minHeight: 40) .background(answer.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || model.busy ? BitFunTheme.muted : BitFunTheme.accent) .clipShape(Capsule()) @@ -696,10 +696,10 @@ private struct ToolStatusRow: View { } Button { submitStructuredAnswers() } label: { HStack { - if model.busy { ProgressView().controlSize(.small).tint(.white) } + if model.busy { ProgressView().controlSize(.small).tint(BitFunTheme.contentOnAction) } Text(model.localized("发送回复")) } - .font(MobileDesignTypography.labelMedium.font).foregroundStyle(.white) + .font(MobileDesignTypography.labelMedium.font).foregroundStyle(BitFunTheme.contentOnAction) .frame(maxWidth: .infinity, minHeight: 40) .background(structuredAnswersValid && !model.busy ? BitFunTheme.accent : BitFunTheme.muted) .clipShape(Capsule()) @@ -770,7 +770,7 @@ private struct ToolStatusRow: View { private func toolAction(_ label: String, primary: Bool, action: @escaping () -> Void) -> some View { Button(action: action) { Text(label).font(MobileDesignTypography.labelMedium.font) - .foregroundStyle(primary ? Color.white : BitFunTheme.ink) + .foregroundStyle(primary ? BitFunTheme.contentOnAction : BitFunTheme.ink) .frame(maxWidth: .infinity, minHeight: 40).background(primary ? BitFunTheme.accent : BitFunTheme.card) .clipShape(Capsule()).overlay { if !primary { Capsule().stroke(BitFunTheme.line, lineWidth: 1) } } } @@ -826,7 +826,7 @@ private struct ToolStatusRow: View { } private var statusColor: Color { - switch tool.phase { case "FAILED": BitFunTheme.red; case "COMPLETED": BitFunTheme.green; default: BitFunTheme.muted } + switch tool.phase { case "FAILED": BitFunTheme.statusDanger; case "COMPLETED": BitFunTheme.statusSuccess; default: BitFunTheme.muted } } private var statusMark: String { diff --git a/src/apps/mobile/ios/BitFun/Features/Chat/ComposerBar.swift b/src/apps/mobile/ios/BitFun/Features/Chat/ComposerBar.swift index c0a74f7c49..3da7c24d36 100644 --- a/src/apps/mobile/ios/BitFun/Features/Chat/ComposerBar.swift +++ b/src/apps/mobile/ios/BitFun/Features/Chat/ComposerBar.swift @@ -62,7 +62,7 @@ struct ComposerBar: View { : MobileDesignGeometry.composerCollapsedRadius ) ) - .shadow(color: .black.opacity(0.05), radius: 10, y: 2) + .shadow(color: BitFunTheme.shadowSubtle, radius: 10, y: 2) .padding(.horizontal, MobileDesignGeometry.contentGutter) .padding(.top, 8) .padding(.bottom, 14) @@ -184,7 +184,7 @@ struct ComposerBar: View { "", text: $model.draft, prompt: Text(speech.isListening ? model.localized("正在聆听") : placeholder) - .foregroundColor(speech.isListening ? BitFunTheme.green : BitFunTheme.muted), + .foregroundColor(speech.isListening ? BitFunTheme.statusSuccess : BitFunTheme.muted), axis: .vertical ) .font(MobileDesignTypography.bodyLarge.font) @@ -199,10 +199,10 @@ struct ComposerBar: View { } .padding(.leading, speech.isListening ? 12 : 4) .padding(.trailing, 4) - .background(speech.isListening ? BitFunTheme.soft : Color.clear) + .background(speech.isListening ? BitFunTheme.soft : BitFunTheme.transparent) .overlay( RoundedRectangle(cornerRadius: 20) - .stroke(speech.isListening ? BitFunTheme.green : Color.clear, lineWidth: 1) + .stroke(speech.isListening ? BitFunTheme.statusSuccess : BitFunTheme.transparent, lineWidth: 1) ) .clipShape(RoundedRectangle(cornerRadius: 20)) } @@ -292,9 +292,9 @@ struct ComposerBar: View { Button { model.removeComposerImage(id: attachment.id) } label: { Image(systemName: "xmark") .font(.system(size: 9, weight: .bold)) - .foregroundStyle(Color.white) + .foregroundStyle(BitFunTheme.contentOnAction) .frame(width: 20, height: 20) - .background(Color.black.opacity(0.72)) + .background(BitFunTheme.mediaScrim) .clipShape(Circle()) } .buttonStyle(.plain) @@ -343,7 +343,7 @@ struct ComposerBar: View { HStack(spacing: 10) { Image(systemName: option.selected ? "checkmark.circle" : "circle") .font(.system(size: 16)) - .foregroundStyle(option.selected ? BitFunTheme.ink : Color.clear) + .foregroundStyle(option.selected ? BitFunTheme.ink : BitFunTheme.transparent) .frame(width: 20, height: 20) VStack(alignment: .leading, spacing: 2) { Text(option.primaryLabel) @@ -359,7 +359,7 @@ struct ComposerBar: View { } .padding(.horizontal, 10) .frame(height: MobileDesignGeometry.composerModelSelectorRowHeight) - .background(option.selected ? BitFunTheme.soft : Color.clear) + .background(option.selected ? BitFunTheme.soft : BitFunTheme.transparent) .clipShape( RoundedRectangle( cornerRadius: MobileDesignGeometry.composerModelSelectorRowRadius @@ -447,7 +447,7 @@ private struct ListeningWave: View { HStack(spacing: 2) { ForEach([8.0, 14.0, 10.0, 17.0], id: \.self) { height in Capsule() - .fill(BitFunTheme.green) + .fill(BitFunTheme.statusSuccess) .frame(width: 2, height: height) } } diff --git a/src/apps/mobile/ios/BitFun/Features/Chat/ConversationHeader.swift b/src/apps/mobile/ios/BitFun/Features/Chat/ConversationHeader.swift index b8b4e138b1..e978062fd2 100644 --- a/src/apps/mobile/ios/BitFun/Features/Chat/ConversationHeader.swift +++ b/src/apps/mobile/ios/BitFun/Features/Chat/ConversationHeader.swift @@ -31,12 +31,12 @@ struct ConversationHeader: View { .background(BitFunTheme.card) .overlay(Circle().stroke(BitFunTheme.line, lineWidth: 1)) .clipShape(Circle()) - .shadow(color: .black.opacity(0.07), radius: 8, y: 3) + .shadow(color: BitFunTheme.shadowMedium, radius: 8, y: 3) } .buttonStyle(.plain) .accessibilityLabel(MobileLocalization.text(sidebarActionLabel)) } else { - Color.clear + BitFunTheme.transparent .frame( width: MobileDesignGeometry.controlTouchSize, height: MobileDesignGeometry.controlTouchSize @@ -70,7 +70,7 @@ struct ConversationHeader: View { if model.selectedSession != nil { actionsMenu } else { - Color.clear + BitFunTheme.transparent .frame( width: MobileDesignGeometry.controlTouchSize, height: MobileDesignGeometry.controlTouchSize @@ -109,7 +109,7 @@ struct ConversationHeader: View { .background(BitFunTheme.card) .overlay(Circle().stroke(BitFunTheme.line, lineWidth: 1)) .clipShape(Circle()) - .shadow(color: .black.opacity(0.07), radius: 8, y: 3) + .shadow(color: BitFunTheme.shadowMedium, radius: 8, y: 3) } .buttonStyle(.plain) .accessibilityLabel(model.localized("会话操作")) @@ -153,7 +153,7 @@ struct ConversationHeader: View { Button(action: action) { Text(model.localized(title)) .font(.system(size: 13, weight: .medium)) - .foregroundStyle(primary && enabled ? Color.white : BitFunTheme.ink) + .foregroundStyle(primary && enabled ? BitFunTheme.contentOnAction : BitFunTheme.ink) .frame(width: 52, height: 42) .background(primary && enabled ? BitFunTheme.accent : BitFunTheme.soft) .clipShape(RoundedRectangle(cornerRadius: 14)) @@ -230,7 +230,7 @@ struct ConversationActionsPopover: View { } .padding(.horizontal, 8) .frame(height: MobileDesignGeometry.popoverActionHeight) - .background(selected ? BitFunTheme.soft : Color.clear) + .background(selected ? BitFunTheme.soft : BitFunTheme.transparent) .clipShape(RoundedRectangle(cornerRadius: 10)) } .buttonStyle(.plain) diff --git a/src/apps/mobile/ios/BitFun/Features/DesignSystem/AdaptiveModalComponents.swift b/src/apps/mobile/ios/BitFun/Features/DesignSystem/AdaptiveModalComponents.swift index 7412027386..6f55a1c2f3 100644 --- a/src/apps/mobile/ios/BitFun/Features/DesignSystem/AdaptiveModalComponents.swift +++ b/src/apps/mobile/ios/BitFun/Features/DesignSystem/AdaptiveModalComponents.swift @@ -80,7 +80,7 @@ struct BitFunModalCard: View { .clipShape(RoundedRectangle(cornerRadius: radius)) .overlay( RoundedRectangle(cornerRadius: radius) - .stroke(bordered ? BitFunTheme.line : Color.clear, lineWidth: 1) + .stroke(bordered ? BitFunTheme.line : BitFunTheme.transparent, lineWidth: 1) ) } } @@ -117,7 +117,7 @@ struct SignedOutConnectionActions: View { Button(action: onOpenAccount) { Text(accountTitle) .font(.system(size: fontSize, weight: .bold)) - .foregroundStyle(.white) + .foregroundStyle(BitFunTheme.contentOnAction) .frame(maxWidth: .infinity, minHeight: buttonHeight) .background(BitFunTheme.accent) .clipShape(Capsule()) @@ -240,7 +240,7 @@ private struct BitFunAdaptiveModalModifier: ViewModifier { @ViewBuilder private var sideCover: some View { let cover = ZStack(alignment: .trailing) { - MobileDesignColors.modalScrim + BitFunTheme.scrim .ignoresSafeArea() .contentShape(Rectangle()) .onTapGesture { isPresented = false } @@ -264,11 +264,11 @@ private struct BitFunAdaptiveModalModifier: ViewModifier { ) .stroke(BitFunTheme.line, lineWidth: 1) ) - .shadow(color: .black.opacity(0.14), radius: 18, x: -5, y: 8) + .shadow(color: BitFunTheme.shadowStrong, radius: 18, x: -5, y: 8) .accessibilityAddTraits(.isModal) } if #available(iOS 16.4, *) { - cover.presentationBackground(.clear) + cover.presentationBackground(BitFunTheme.transparent) } else { cover } diff --git a/src/apps/mobile/ios/BitFun/Features/DesignSystem/GeneratedMobileDesignTokens.swift b/src/apps/mobile/ios/BitFun/Features/DesignSystem/GeneratedMobileDesignTokens.swift index 29476555d0..5e770be879 100644 --- a/src/apps/mobile/ios/BitFun/Features/DesignSystem/GeneratedMobileDesignTokens.swift +++ b/src/apps/mobile/ios/BitFun/Features/DesignSystem/GeneratedMobileDesignTokens.swift @@ -13,6 +13,7 @@ struct MobileTypographyToken { enum MobileDesignColors { static let startWindowBackground = dynamic(light: 0xFFFFFFFF, dark: 0xFF000000) + static let transparent = dynamic(light: 0x00000000, dark: 0x00000000) static let pageBg = dynamic(light: 0xFFFFFFFF, dark: 0xFF151514) static let pageBgFade = dynamic(light: 0x00FFFFFF, dark: 0x00151514) static let ink = dynamic(light: 0xFF171717, dark: 0xFFF4F3EF) @@ -23,17 +24,27 @@ enum MobileDesignColors { static let accent = dynamic(light: 0xFF111111, dark: 0xFF5B5954) static let fileLink = dynamic(light: 0xFF2563EB, dark: 0xFF60A5FA) static let primaryAction = dynamic(light: 0xFF111111, dark: 0xFF454540) - static let primaryActionText = dynamic(light: 0xFFFFFFFF, dark: 0xFFFFFFFF) + static let contentOnAction = dynamic(light: 0xFFFFFFFF, dark: 0xFFFFFFFF) static let connectHeroBg = dynamic(light: 0xFFE6EDFF, dark: 0xFF2B2B29) static let connectHeroAccent = dynamic(light: 0xFF9DB4FF, dark: 0xFF4A4944) static let connectHeroSecondary = dynamic(light: 0xFFC9C5FF, dark: 0xFF3C3B38) static let connectHeroSurface = dynamic(light: 0xFFF8FAFF, dark: 0xFF252522) static let connectScanAccent = dynamic(light: 0xFFFFD021, dark: 0xFFFFD021) - static let modalScrim = dynamic(light: 0x44000000, dark: 0x44000000) + static let scrim = dynamic(light: 0x44000000, dark: 0x44000000) + static let shellScrim = dynamic(light: 0x24000000, dark: 0x24000000) + static let mediaBackground = dynamic(light: 0xFF000000, dark: 0xFF000000) + static let mediaScrim = dynamic(light: 0xB8000000, dark: 0xB8000000) + static let mediaControlBackground = dynamic(light: 0x8C000000, dark: 0x8C000000) + static let toastBackground = dynamic(light: 0xD1171717, dark: 0xD1171717) + static let shadowFaint = dynamic(light: 0x08000000, dark: 0x08000000) + static let shadowSubtle = dynamic(light: 0x12000000, dark: 0x12000000) + static let shadowMedium = dynamic(light: 0x18000000, dark: 0x18000000) + static let shadowStrong = dynamic(light: 0x24000000, dark: 0x24000000) + static let floatingBorder = dynamic(light: 0x18000000, dark: 0x18000000) static let soft = dynamic(light: 0xFFF4F3F0, dark: 0xFF2D2C28) static let floatingPanelBg = dynamic(light: 0xFFF7F7F5, dark: 0xFF1E1E1C) - static let green = dynamic(light: 0xFF27C46A, dark: 0xFF3BD47B) - static let red = dynamic(light: 0xFFE04F4F, dark: 0xFFFF6B6B) + static let statusSuccess = dynamic(light: 0xFF27C46A, dark: 0xFF3BD47B) + static let statusDanger = dynamic(light: 0xFFE04F4F, dark: 0xFFFF6B6B) static let codeLineNumber = dynamic(light: 0xFFAAA69D, dark: 0xFF77756E) static let codeKeyword = dynamic(light: 0xFF8F3F71, dark: 0xFFD99AC4) static let codeString = dynamic(light: 0xFF477A4A, dark: 0xFF9BCB9D) diff --git a/src/apps/mobile/ios/BitFun/Features/Pairing/PairingSheet.swift b/src/apps/mobile/ios/BitFun/Features/Pairing/PairingSheet.swift index 23b008f26c..1264ef27d5 100644 --- a/src/apps/mobile/ios/BitFun/Features/Pairing/PairingSheet.swift +++ b/src/apps/mobile/ios/BitFun/Features/Pairing/PairingSheet.swift @@ -104,7 +104,7 @@ struct PairingSheet: View { Text(model.localized("扫描二维码")) .font(.system(size: 24, weight: .bold)).foregroundStyle(BitFunTheme.ink) if let error = model.pairingError { - Text(error).font(.system(size: 13)).foregroundStyle(BitFunTheme.red) + Text(error).font(.system(size: 13)).foregroundStyle(BitFunTheme.statusDanger) .multilineTextAlignment(.center) } } @@ -158,7 +158,7 @@ struct PairingSheet: View { (!hints.requiresAccount || (!effectiveUserID.isEmpty && !pairingPassword.isEmpty)) return ZStack { - MobileDesignColors.modalScrim + BitFunTheme.scrim .ignoresSafeArea() .onTapGesture { if !model.pairingBusy { @@ -210,7 +210,7 @@ struct PairingSheet: View { .lineSpacing(3) } if let error = model.pairingError { - Text(error).font(.system(size: 13)).foregroundStyle(BitFunTheme.red) + Text(error).font(.system(size: 13)).foregroundStyle(BitFunTheme.statusDanger) } HStack(spacing: 12) { pairingButton("取消", primary: false) { @@ -247,7 +247,7 @@ struct PairingSheet: View { Button(action: action) { Text(model.localized(title)) .font(.system(size: 19, weight: .bold)) - .foregroundStyle(primary ? Color.white : BitFunTheme.ink) + .foregroundStyle(primary ? BitFunTheme.contentOnAction : BitFunTheme.ink) .frame(maxWidth: .infinity, minHeight: 58) .background(primary ? BitFunTheme.accent : BitFunTheme.soft) .clipShape(Capsule()) diff --git a/src/apps/mobile/ios/BitFun/Features/Remote/RemoteHomeViews.swift b/src/apps/mobile/ios/BitFun/Features/Remote/RemoteHomeViews.swift index bc891e35e7..7c2b923621 100644 --- a/src/apps/mobile/ios/BitFun/Features/Remote/RemoteHomeViews.swift +++ b/src/apps/mobile/ios/BitFun/Features/Remote/RemoteHomeViews.swift @@ -28,7 +28,7 @@ struct RemoteHomeView: View { .padding(.horizontal, 20) Button(model.localized("连接")) { model.connectRemote() } .font(.system(size: 15, weight: .medium)) - .foregroundStyle(.white) + .foregroundStyle(BitFunTheme.contentOnAction) .frame(width: 136, height: 44) .background(BitFunTheme.accent) .clipShape(Capsule()) @@ -74,7 +74,7 @@ struct RemoteConnectedHomeView: View { .multilineTextAlignment(.center) Button { model.remoteCreateOpen = true } label: { Label(model.localized("新建远程会话"), systemImage: "plus") - .font(MobileDesignTypography.labelMedium.font).foregroundStyle(.white) + .font(MobileDesignTypography.labelMedium.font).foregroundStyle(BitFunTheme.contentOnAction) .frame(minWidth: 176, minHeight: 44).background(BitFunTheme.accent).clipShape(Capsule()) } .buttonStyle(.plain) @@ -104,7 +104,7 @@ struct ConnectionStatusBar: View { let onRetry: () -> Void var body: some View { HStack(spacing: 8) { - Circle().fill(phase == .reconnecting ? BitFunTheme.muted : BitFunTheme.red).frame(width: 8, height: 8) + Circle().fill(phase == .reconnecting ? BitFunTheme.muted : BitFunTheme.statusDanger).frame(width: 8, height: 8) Text(MobileLocalization.text(phase == .reconnecting ? "正在恢复连接" : "连接不可用")) .font(.system(size: 13, weight: .medium)) Text( diff --git a/src/apps/mobile/ios/BitFun/Features/Shell/BitFunTheme.swift b/src/apps/mobile/ios/BitFun/Features/Shell/BitFunTheme.swift index 79e5b3bce8..8220eb2c31 100644 --- a/src/apps/mobile/ios/BitFun/Features/Shell/BitFunTheme.swift +++ b/src/apps/mobile/ios/BitFun/Features/Shell/BitFunTheme.swift @@ -3,14 +3,26 @@ import SwiftUI enum BitFunTheme { // Generated from the HarmonyOS baseline through the mobile design contract. static let page = MobileDesignColors.pageBg + static let transparent = MobileDesignColors.transparent static let card = MobileDesignColors.card static let soft = MobileDesignColors.soft static let ink = MobileDesignColors.ink static let muted = MobileDesignColors.muted static let line = MobileDesignColors.line static let accent = MobileDesignColors.accent - static let green = MobileDesignColors.green - static let red = MobileDesignColors.red + static let contentOnAction = MobileDesignColors.contentOnAction + static let scrim = MobileDesignColors.scrim + static let shellScrim = MobileDesignColors.shellScrim + static let mediaBackground = MobileDesignColors.mediaBackground + static let mediaScrim = MobileDesignColors.mediaScrim + static let mediaControlBackground = MobileDesignColors.mediaControlBackground + static let toastBackground = MobileDesignColors.toastBackground + static let shadowSubtle = MobileDesignColors.shadowSubtle + static let shadowMedium = MobileDesignColors.shadowMedium + static let shadowStrong = MobileDesignColors.shadowStrong + static let floatingBorder = MobileDesignColors.floatingBorder + static let statusSuccess = MobileDesignColors.statusSuccess + static let statusDanger = MobileDesignColors.statusDanger } struct CircleControl: View { @@ -28,7 +40,7 @@ struct CircleControl: View { .background(BitFunTheme.card) .overlay(Circle().stroke(BitFunTheme.line, lineWidth: 1)) .clipShape(Circle()) - .shadow(color: .black.opacity(0.07), radius: 8, y: 3) + .shadow(color: BitFunTheme.shadowMedium, radius: 8, y: 3) } .buttonStyle(.plain) .accessibilityLabel(systemName) diff --git a/src/apps/mobile/ios/BitFun/Features/Shell/MobileShellView.swift b/src/apps/mobile/ios/BitFun/Features/Shell/MobileShellView.swift index c480fdd4ba..2c683b60c7 100644 --- a/src/apps/mobile/ios/BitFun/Features/Shell/MobileShellView.swift +++ b/src/apps/mobile/ios/BitFun/Features/Shell/MobileShellView.swift @@ -17,7 +17,7 @@ struct MobileShellView: View { if sessionActionsOpen, let anchor { let frame = proxy[anchor] ZStack(alignment: .topLeading) { - Color.clear + BitFunTheme.transparent .contentShape(Rectangle()) .onTapGesture { sessionActionsOpen = false } ConversationActionsPopover( @@ -45,7 +45,7 @@ struct MobileShellView: View { let frame = proxy[anchor] let remote = model.surface == .remote ZStack(alignment: .topLeading) { - Color.clear + BitFunTheme.transparent .contentShape(Rectangle()) .onTapGesture { sidebarActionSession = nil } SessionActionSurface( @@ -83,10 +83,10 @@ struct MobileShellView: View { if let message = model.toastMessage { Text(message) .font(.system(size: 13, weight: .medium)) - .foregroundStyle(Color.white) + .foregroundStyle(BitFunTheme.contentOnAction) .padding(.horizontal, 16) .frame(minHeight: 38) - .background(Color.black.opacity(0.82)) + .background(BitFunTheme.toastBackground) .clipShape(Capsule()) .padding(.bottom, 86) .transition(.move(edge: .bottom).combined(with: .opacity)) @@ -231,7 +231,7 @@ struct MobileShellView: View { } .clipShape(RoundedRectangle(cornerRadius: !sidebarVisible && model.drawerOpen ? 28 : 0)) .shadow( - color: !sidebarVisible && model.drawerOpen ? .black.opacity(0.14) : .clear, + color: !sidebarVisible && model.drawerOpen ? BitFunTheme.shellScrim : BitFunTheme.transparent, radius: !sidebarVisible && model.drawerOpen ? 34 : 0, x: !sidebarVisible && model.drawerOpen ? -10 : 0 ) diff --git a/src/apps/mobile/ios/BitFun/Features/Shell/RemoteCreateSessionView.swift b/src/apps/mobile/ios/BitFun/Features/Shell/RemoteCreateSessionView.swift index b957a76ed8..d638b0fd7e 100644 --- a/src/apps/mobile/ios/BitFun/Features/Shell/RemoteCreateSessionView.swift +++ b/src/apps/mobile/ios/BitFun/Features/Shell/RemoteCreateSessionView.swift @@ -64,7 +64,7 @@ struct RemoteCreateSessionView: View { let anchor = anchors[kind] { let frame = proxy[anchor] ZStack(alignment: .topLeading) { - Color.clear + BitFunTheme.transparent .contentShape(Rectangle()) .onTapGesture { pickerKind = nil } selectionContent(kind: kind, includeHeader: false) @@ -171,7 +171,7 @@ struct RemoteCreateSessionView: View { "", text: $instruction, prompt: Text(model.localized(speech.isListening ? "正在聆听" : "告诉 BitFun 要做什么")) - .foregroundColor(speech.isListening ? BitFunTheme.green : BitFunTheme.muted), + .foregroundColor(speech.isListening ? BitFunTheme.statusSuccess : BitFunTheme.muted), axis: .vertical ) .font(MobileDesignTypography.bodyLarge.font) @@ -206,13 +206,13 @@ struct RemoteCreateSessionView: View { Group { if model.remoteCreateSubmitting { ProgressView() - .tint(Color.white) + .tint(BitFunTheme.contentOnAction) } else { Image(systemName: instruction.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? (speech.isListening ? "stop.fill" : "mic.fill") : "arrow.up") .font(.system(size: 17, weight: .semibold)) - .foregroundStyle(canSubmit ? Color.white : BitFunTheme.ink) + .foregroundStyle(canSubmit ? BitFunTheme.contentOnAction : BitFunTheme.ink) } } .frame( @@ -235,7 +235,7 @@ struct RemoteCreateSessionView: View { .frame(minHeight: MobileDesignGeometry.composerExpandedHeight) .background(BitFunTheme.card) .clipShape(RoundedRectangle(cornerRadius: MobileDesignGeometry.composerExpandedRadius)) - .shadow(color: .black.opacity(0.05), radius: 10, y: 2) + .shadow(color: BitFunTheme.shadowSubtle, radius: 10, y: 2) .padding(.horizontal, MobileDesignGeometry.contentGutter) .padding(.top, 8) .padding(.bottom, 14) @@ -249,7 +249,7 @@ struct RemoteCreateSessionView: View { private func createStatus(message: String, retryTitle: String, action: @escaping () -> Void) -> some View { HStack(alignment: .top, spacing: 8) { Image(systemName: "exclamationmark.triangle") - .foregroundStyle(BitFunTheme.red) + .foregroundStyle(BitFunTheme.statusDanger) Text(message) .font(.system(size: 13)) .foregroundStyle(BitFunTheme.ink) @@ -410,7 +410,7 @@ struct RemoteCreateSessionView: View { HStack(spacing: 12) { Image(systemName: selected ? "checkmark.circle" : "circle") .font(.system(size: 19)) - .foregroundStyle(selected ? BitFunTheme.ink : Color.clear) + .foregroundStyle(selected ? BitFunTheme.ink : BitFunTheme.transparent) .frame(width: 20) Image(systemName: icon) .font(.system(size: 19, weight: .medium)) diff --git a/src/apps/mobile/ios/BitFun/Features/Shell/RemoteFilePreviewView.swift b/src/apps/mobile/ios/BitFun/Features/Shell/RemoteFilePreviewView.swift index abf2a62a31..15b9924f7f 100644 --- a/src/apps/mobile/ios/BitFun/Features/Shell/RemoteFilePreviewView.swift +++ b/src/apps/mobile/ios/BitFun/Features/Shell/RemoteFilePreviewView.swift @@ -148,10 +148,10 @@ struct RemoteFilePreviewSheet: View { Image(systemName: "checkmark.circle") } else if model.downloadPhase == .failed { Image(systemName: "exclamationmark.triangle") - .foregroundStyle(BitFunTheme.red) + .foregroundStyle(BitFunTheme.statusDanger) } Text(status).font(MobileDesignTypography.labelSmall.font) - .foregroundStyle(model.downloadPhase == .failed ? BitFunTheme.red : BitFunTheme.muted) + .foregroundStyle(model.downloadPhase == .failed ? BitFunTheme.statusDanger : BitFunTheme.muted) .lineLimit(2) if model.downloadPhase == .failed { Button(model.localized("重试")) { model.retryRemoteDownload() } @@ -222,7 +222,7 @@ struct RemoteFilePreviewSheet: View { MarkdownMessageView(text: block.text, model: model) .id(block.startLine) .background(GeometryReader { geometry in - Color.clear.preference( + BitFunTheme.transparent.preference( key: FilePreviewVisibleLinePreferenceKey.self, value: { let frame = geometry.frame(in: .named("file-preview-scroll")) @@ -253,7 +253,7 @@ struct RemoteFilePreviewSheet: View { .foregroundStyle(BitFunTheme.ink) .frame(maxWidth: .infinity, alignment: .leading) .background(GeometryReader { geometry in - Color.clear.preference( + BitFunTheme.transparent.preference( key: FilePreviewVisibleLinePreferenceKey.self, value: { let frame = geometry.frame(in: .named("file-preview-scroll")) diff --git a/src/apps/mobile/ios/BitFun/Features/Shell/RemoteSettingsViews.swift b/src/apps/mobile/ios/BitFun/Features/Shell/RemoteSettingsViews.swift index 65a8a00f7f..8f4db32e3c 100644 --- a/src/apps/mobile/ios/BitFun/Features/Shell/RemoteSettingsViews.swift +++ b/src/apps/mobile/ios/BitFun/Features/Shell/RemoteSettingsViews.swift @@ -375,7 +375,7 @@ struct RemoteControlSettingsView: View { if let failure = model.remotePermissionFailure, !failure.isEmpty { Text(failure) - .font(.system(size: 12)).foregroundStyle(BitFunTheme.red) + .font(.system(size: 12)).foregroundStyle(BitFunTheme.statusDanger) .padding(.horizontal, 18).padding(.bottom, 10) } @@ -389,7 +389,7 @@ struct RemoteControlSettingsView: View { private var fullAccessConfirmation: some View { VStack(alignment: .leading, spacing: 10) { Text(model.localized("确认完全访问")) - .font(.system(size: 15, weight: .bold)).foregroundStyle(BitFunTheme.red) + .font(.system(size: 15, weight: .bold)).foregroundStyle(BitFunTheme.statusDanger) Text(model.localized("完全访问会取消所有操作确认。仅在你信任当前桌面端时启用。")) .font(.system(size: 13)).foregroundStyle(BitFunTheme.ink).lineSpacing(4) HStack(spacing: 10) { @@ -401,7 +401,7 @@ struct RemoteControlSettingsView: View { } } .padding(16) - .overlay(RoundedRectangle(cornerRadius: 18).stroke(BitFunTheme.red, lineWidth: 1)) + .overlay(RoundedRectangle(cornerRadius: 18).stroke(BitFunTheme.statusDanger, lineWidth: 1)) .padding(.horizontal, 12).padding(.bottom, 14) } @@ -465,9 +465,9 @@ struct RemoteControlSettingsView: View { Button(action: action) { Text(model.localized(title)) .font(.system(size: 14, weight: .medium)) - .foregroundStyle(destructive ? Color.white : BitFunTheme.ink) + .foregroundStyle(destructive ? BitFunTheme.contentOnAction : BitFunTheme.ink) .frame(maxWidth: .infinity, minHeight: 42) - .background(destructive ? BitFunTheme.red : BitFunTheme.soft) + .background(destructive ? BitFunTheme.statusDanger : BitFunTheme.soft) .clipShape(Capsule()) } .buttonStyle(.plain) @@ -652,7 +652,7 @@ struct GeneralChatConfigSheet: View { } label: { HStack(spacing: 10) { Image(systemName: option.selected ? "checkmark.circle" : "circle") - .foregroundStyle(option.selected ? BitFunTheme.ink : Color.clear) + .foregroundStyle(option.selected ? BitFunTheme.ink : BitFunTheme.transparent) .frame(width: 20, height: 20) VStack(alignment: .leading, spacing: 2) { Text(option.primaryLabel) @@ -667,7 +667,7 @@ struct GeneralChatConfigSheet: View { } .padding(.horizontal, 10) .frame(height: MobileDesignGeometry.modelAccountRowHeight) - .background(option.selected ? BitFunTheme.soft : Color.clear) + .background(option.selected ? BitFunTheme.soft : BitFunTheme.transparent) .clipShape(RoundedRectangle(cornerRadius: 9)) } .buttonStyle(.plain) @@ -698,7 +698,7 @@ struct GeneralChatConfigSheet: View { } label: { Text(model.localized(clearAPIKey ? "保留已保存的 Key" : "清除已保存的 API Key")) .font(MobileDesignTypography.bodySmall.font) - .foregroundStyle(clearAPIKey ? BitFunTheme.ink : BitFunTheme.red) + .foregroundStyle(clearAPIKey ? BitFunTheme.ink : BitFunTheme.statusDanger) } .buttonStyle(.plain) } @@ -723,11 +723,11 @@ struct GeneralChatConfigSheet: View { } if let failure = model.generalConfigFailure { Text(configFailureText(failure)) - .font(MobileDesignTypography.bodySmall.font).foregroundStyle(BitFunTheme.red) + .font(MobileDesignTypography.bodySmall.font).foregroundStyle(BitFunTheme.statusDanger) } if let message = model.generalConnectionTestMessage { Text(message).font(MobileDesignTypography.bodySmall.font) - .foregroundStyle(message == model.localized("连接成功") ? BitFunTheme.green : BitFunTheme.red) + .foregroundStyle(message == model.localized("连接成功") ? BitFunTheme.statusSuccess : BitFunTheme.statusDanger) } } .padding(.horizontal, 16) @@ -806,7 +806,7 @@ struct GeneralChatConfigSheet: View { Button(action: action) { Text(model.localized(title)) .font(MobileDesignTypography.bodyLarge.font.weight(.medium)) - .foregroundStyle(primary ? Color.white : BitFunTheme.ink) + .foregroundStyle(primary ? BitFunTheme.contentOnAction : BitFunTheme.ink) .frame(maxWidth: .infinity, minHeight: 50) .background(primary ? BitFunTheme.accent : BitFunTheme.soft) .clipShape(Capsule()) diff --git a/src/apps/mobile/ios/BitFun/Features/Shell/SessionActionComponents.swift b/src/apps/mobile/ios/BitFun/Features/Shell/SessionActionComponents.swift index a65122e5e1..942c0beda5 100644 --- a/src/apps/mobile/ios/BitFun/Features/Shell/SessionActionComponents.swift +++ b/src/apps/mobile/ios/BitFun/Features/Shell/SessionActionComponents.swift @@ -75,7 +75,7 @@ struct SessionActionSurface: View { .stroke(BitFunTheme.line, lineWidth: 1) ) .shadow( - color: presentation == .popover ? BitFunTheme.line : .clear, + color: presentation == .popover ? BitFunTheme.line : BitFunTheme.transparent, radius: presentation == .popover ? 20 : 0, y: presentation == .popover ? 8 : 0 ) @@ -132,8 +132,8 @@ struct SessionActionSurface: View { } confirmationButton( "删除", - fill: BitFunTheme.red, - foreground: .white, + fill: BitFunTheme.statusDanger, + foreground: BitFunTheme.contentOnAction, emphasized: true ) { onDelete() @@ -153,11 +153,11 @@ struct SessionActionSurface: View { HStack(spacing: 12) { Image(systemName: icon) .font(.system(size: 19, weight: .regular)) - .foregroundStyle(destructive ? BitFunTheme.red : BitFunTheme.muted) + .foregroundStyle(destructive ? BitFunTheme.statusDanger : BitFunTheme.muted) .frame(width: 23, height: 23) Text(model.localized(title)) .font(.system(size: 15)) - .foregroundStyle(destructive ? BitFunTheme.red : BitFunTheme.ink) + .foregroundStyle(destructive ? BitFunTheme.statusDanger : BitFunTheme.ink) Spacer(minLength: 0) } .padding(.horizontal, 10) diff --git a/src/apps/mobile/ios/BitFun/Features/Shell/SidebarView.swift b/src/apps/mobile/ios/BitFun/Features/Shell/SidebarView.swift index 8dbeef7b1d..a5df9c31bd 100644 --- a/src/apps/mobile/ios/BitFun/Features/Shell/SidebarView.swift +++ b/src/apps/mobile/ios/BitFun/Features/Shell/SidebarView.swift @@ -127,7 +127,7 @@ struct SidebarView: View { let frame = proxy[anchor] let menuHeight = MobileDesignGeometry.compactPopoverActionHeight * 2 + 16 ZStack(alignment: .topLeading) { - Color.clear + BitFunTheme.transparent .contentShape(Rectangle()) .onTapGesture { workspaceCreatePath = nil } workspaceCreateMenu(workspace) @@ -199,7 +199,7 @@ struct SidebarView: View { .background(BitFunTheme.card) .overlay(Circle().stroke(BitFunTheme.line, lineWidth: 1)) .clipShape(Circle()) - .shadow(color: .black.opacity(0.08), radius: 10, y: 4) + .shadow(color: BitFunTheme.shadowMedium, radius: 10, y: 4) } .buttonStyle(.plain) .accessibilityLabel(Text(model.localized("搜索"))) @@ -368,8 +368,8 @@ struct SidebarView: View { Text(device.name).font(.system(size: 15, weight: current ? .medium : .regular)) .foregroundStyle(BitFunTheme.ink).lineLimit(1) Spacer(minLength: 0) - Circle().fill(device.online ? BitFunTheme.green : BitFunTheme.muted).frame(width: 7, height: 7) - if current { Text(model.localized("当前控制")).font(.system(size: 11)).foregroundStyle(BitFunTheme.green) } + Circle().fill(device.online ? BitFunTheme.statusSuccess : BitFunTheme.muted).frame(width: 7, height: 7) + if current { Text(model.localized("当前控制")).font(.system(size: 11)).foregroundStyle(BitFunTheme.statusSuccess) } if device.status == "LOADING" { ProgressView().controlSize(.small) } Image(systemName: device.expanded ? "chevron.down" : "chevron.right") .font(.system(size: 12, weight: .medium)).foregroundStyle(BitFunTheme.muted) @@ -391,7 +391,7 @@ struct SidebarView: View { .padding(.horizontal, 18).frame(height: 42) } else if device.status == "FAILED" { Button { model.retryDeviceDirectory(device) } label: { - Text(model.localized("工作区加载失败,点按重试")).font(.system(size: 13)).foregroundStyle(BitFunTheme.red) + Text(model.localized("工作区加载失败,点按重试")).font(.system(size: 13)).foregroundStyle(BitFunTheme.statusDanger) .frame(maxWidth: .infinity, minHeight: 42, alignment: .leading).padding(.leading, 18) }.buttonStyle(.plain) } else if device.status == "READY" && device.online && device.workspaces.isEmpty && device.sessions.isEmpty { @@ -459,7 +459,7 @@ struct SidebarView: View { Button { model.retryRemoteWorkspaces() } label: { Text(model.localized("工作区加载失败,点按重试")) .font(.system(size: 13)) - .foregroundStyle(BitFunTheme.red) + .foregroundStyle(BitFunTheme.statusDanger) .frame(maxWidth: .infinity, minHeight: 42, alignment: .leading) .padding(.horizontal, 10) } @@ -723,7 +723,7 @@ struct SidebarView: View { .foregroundStyle(BitFunTheme.ink) .lineLimit(1) Spacer(minLength: 0) - Circle().fill(BitFunTheme.green).frame(width: 7, height: 7) + Circle().fill(BitFunTheme.statusSuccess).frame(width: 7, height: 7) ReferenceImage(assetName: "SidebarDownGlyph", width: 14, height: 14) } .padding(.horizontal, 10) @@ -787,7 +787,7 @@ struct SidebarView: View { .background(BitFunTheme.card) .overlay(RoundedRectangle(cornerRadius: 23).stroke(BitFunTheme.line, lineWidth: 1)) .clipShape(Capsule()) - .shadow(color: .black.opacity(0.08), radius: 10, y: 4) + .shadow(color: BitFunTheme.shadowMedium, radius: 10, y: 4) } .buttonStyle(.plain) Spacer(minLength: 0) @@ -796,7 +796,7 @@ struct SidebarView: View { .frame(width: 46, height: 46) .background(BitFunTheme.card) .clipShape(Circle()) - .shadow(color: .black.opacity(0.08), radius: 10, y: 4) + .shadow(color: BitFunTheme.shadowMedium, radius: 10, y: 4) } .buttonStyle(.plain) .accessibilityLabel(Text(model.localized("设置"))) @@ -861,7 +861,7 @@ private struct SidebarRecentRow: View { .padding(.leading, 12) .padding(.trailing, 4) .frame(minHeight: metadata == nil ? 44 : 56) - .background(selected ? BitFunTheme.soft : .clear) + .background(selected ? BitFunTheme.soft : BitFunTheme.transparent) .clipShape(RoundedRectangle(cornerRadius: 10)) } } @@ -939,7 +939,7 @@ private struct SidebarWorkspaceRow: View { } .padding(.horizontal, 10) .frame(height: 46) - .background(workspace.selected ? BitFunTheme.soft.opacity(0.75) : Color.clear) + .background(workspace.selected ? BitFunTheme.soft.opacity(0.75) : BitFunTheme.transparent) .clipShape(RoundedRectangle(cornerRadius: 10)) if expanded { @@ -955,7 +955,7 @@ private struct SidebarWorkspaceRow: View { Button { onOpenSession(session) } label: { HStack(spacing: 10) { if ["running", "active", "in_progress"].contains(session.status.lowercased()) { - Circle().fill(BitFunTheme.green).frame(width: 7, height: 7) + Circle().fill(BitFunTheme.statusSuccess).frame(width: 7, height: 7) } Image(systemName: "doc") .font(.system(size: 18, weight: .regular)) @@ -999,7 +999,7 @@ private struct SidebarWorkspaceRow: View { .padding(.leading, 32) .padding(.trailing, 4) .frame(minHeight: metadata(session) == nil ? 44 : 56) - .background(isSelected(session) ? BitFunTheme.soft : Color.clear) + .background(isSelected(session) ? BitFunTheme.soft : BitFunTheme.transparent) .clipShape(RoundedRectangle(cornerRadius: 9)) } if workspace.sessions.count > sessionLimit { diff --git a/src/apps/mobile/ios/BitFun/Infrastructure/Platform/QRCodeScannerView.swift b/src/apps/mobile/ios/BitFun/Infrastructure/Platform/QRCodeScannerView.swift index 60345439c4..f61ebe92a8 100644 --- a/src/apps/mobile/ios/BitFun/Infrastructure/Platform/QRCodeScannerView.swift +++ b/src/apps/mobile/ios/BitFun/Infrastructure/Platform/QRCodeScannerView.swift @@ -21,11 +21,11 @@ final class QRScannerController: UIViewController, AVCaptureMetadataOutputObject override func viewDidLoad() { super.viewDidLoad() - view.backgroundColor = .black + view.backgroundColor = UIColor(BitFunTheme.mediaBackground) let close = UIButton(type: .system) close.setImage(UIImage(systemName: "xmark"), for: .normal) - close.tintColor = .white - close.backgroundColor = UIColor.black.withAlphaComponent(0.55) + close.tintColor = UIColor(BitFunTheme.contentOnAction) + close.backgroundColor = UIColor(BitFunTheme.mediaControlBackground) close.layer.cornerRadius = 22 close.addAction(UIAction { [weak self] _ in self?.dismiss(animated: true) }, for: .touchUpInside) close.translatesAutoresizingMaskIntoConstraints = false diff --git a/src/apps/relay-server/static/assets/ChatPage-DseABuXP.js b/src/apps/relay-server/static/assets/ChatPage-B79eLrUh.js similarity index 86% rename from src/apps/relay-server/static/assets/ChatPage-DseABuXP.js rename to src/apps/relay-server/static/assets/ChatPage-B79eLrUh.js index e79b0c3e49..a08651e3e7 100644 --- a/src/apps/relay-server/static/assets/ChatPage-DseABuXP.js +++ b/src/apps/relay-server/static/assets/ChatPage-B79eLrUh.js @@ -1,18 +1,18 @@ -import{g as me,j as h,R as it,c as mn,u as Ye,a as Ft,b as Zo,r as N,d as Gs,e as on,S as Zs,_ as Xs,i as Ks,m as Ys}from"./index-BNRAmblM.js";function Qs(e,t){const n={};return(e[e.length-1]===""?[...e,""]:e).join((n.padRight?" ":"")+","+(n.padLeft===!1?"":" ")).trim()}const Js=/^[$_\p{ID_Start}][$_\u{200C}\u{200D}\p{ID_Continue}]*$/u,eu=/^[$_\p{ID_Start}][-$_\u{200C}\u{200D}\p{ID_Continue}]*$/u,tu={};function Zi(e,t){return(tu.jsx?eu:Js).test(e)}const nu=/[ \t\n\f\r]/g;function ru(e){return typeof e=="object"?e.type==="text"?Xi(e.value):!1:Xi(e)}function Xi(e){return e.replace(nu,"")===""}class Yt{constructor(t,n,r){this.normal=n,this.property=t,r&&(this.space=r)}}Yt.prototype.normal={};Yt.prototype.property={};Yt.prototype.space=void 0;function Xo(e,t){const n={},r={};for(const i of e)Object.assign(n,i.property),Object.assign(r,i.normal);return new Yt(n,r,t)}function ri(e){return e.toLowerCase()}class Be{constructor(t,n){this.attribute=n,this.property=t}}Be.prototype.attribute="";Be.prototype.booleanish=!1;Be.prototype.boolean=!1;Be.prototype.commaOrSpaceSeparated=!1;Be.prototype.commaSeparated=!1;Be.prototype.defined=!1;Be.prototype.mustUseProperty=!1;Be.prototype.number=!1;Be.prototype.overloadedBoolean=!1;Be.prototype.property="";Be.prototype.spaceSeparated=!1;Be.prototype.space=void 0;let iu=0;const Q=vt(),Ee=vt(),ii=vt(),F=vt(),ge=vt(),Lt=vt(),We=vt();function vt(){return 2**++iu}const ai=Object.freeze(Object.defineProperty({__proto__:null,boolean:Q,booleanish:Ee,commaOrSpaceSeparated:We,commaSeparated:Lt,number:F,overloadedBoolean:ii,spaceSeparated:ge},Symbol.toStringTag,{value:"Module"})),Mn=Object.keys(ai);class wi extends Be{constructor(t,n,r,i){let o=-1;if(super(t,n),Ki(this,"space",i),typeof r=="number")for(;++o4&&n.slice(0,4)==="data"&&uu.test(t)){if(t.charAt(4)==="-"){const o=t.slice(5).replace(Yi,du);r="data"+o.charAt(0).toUpperCase()+o.slice(1)}else{const o=t.slice(4);if(!Yi.test(o)){let a=o.replace(su,pu);a.charAt(0)!=="-"&&(a="-"+a),t="data"+a}}i=wi}return new i(r,t)}function pu(e){return"-"+e.toLowerCase()}function du(e){return e.charAt(1).toUpperCase()}const fu=Xo([Ko,au,Jo,el,tl],"html"),Si=Xo([Ko,ou,Jo,el,tl],"svg");function hu(e){return e.join(" ").trim()}var Et={},Fn,Qi;function gu(){if(Qi)return Fn;Qi=1;var e=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//g,t=/\n/g,n=/^\s*/,r=/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/,i=/^:\s*/,o=/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/,a=/^[;\s]*/,l=/^\s+|\s+$/g,s=` -`,u="/",p="*",c="",f="comment",d="declaration";function g(S,x){if(typeof S!="string")throw new TypeError("First argument must be a string");if(!S)return[];x=x||{};var v=1,y=1;function _(P){var z=P.match(t);z&&(v+=z.length);var G=P.lastIndexOf(s);y=~G?P.length-G:y+P.length}function C(){var P={line:v,column:y};return function(z){return z.position=new m(P),A(),z}}function m(P){this.start=P,this.end={line:v,column:y},this.source=x.source}m.prototype.content=S;function T(P){var z=new Error(x.source+":"+v+":"+y+": "+P);if(z.reason=P,z.filename=x.source,z.line=v,z.column=y,z.source=S,!x.silent)throw z}function j(P){var z=P.exec(S);if(z){var G=z[0];return _(G),S=S.slice(G.length),z}}function A(){j(n)}function E(P){var z;for(P=P||[];z=R();)z!==!1&&P.push(z);return P}function R(){var P=C();if(!(u!=S.charAt(0)||p!=S.charAt(1))){for(var z=2;c!=S.charAt(z)&&(p!=S.charAt(z)||u!=S.charAt(z+1));)++z;if(z+=2,c===S.charAt(z-1))return T("End of comment missing");var G=S.slice(2,z-2);return y+=2,_(G),S=S.slice(z),y+=2,P({type:f,comment:G})}}function M(){var P=C(),z=j(r);if(z){if(R(),!j(i))return T("property missing ':'");var G=j(o),J=P({type:d,property:k(z[0].replace(e,c)),value:G?k(G[0].replace(e,c)):c});return j(a),J}}function H(){var P=[];E(P);for(var z;z=M();)z!==!1&&(P.push(z),E(P));return P}return A(),H()}function k(S){return S?S.replace(l,c):c}return Fn=g,Fn}var Ji;function mu(){if(Ji)return Et;Ji=1;var e=Et&&Et.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(Et,"__esModule",{value:!0}),Et.default=n;const t=e(gu());function n(r,i){let o=null;if(!r||typeof r!="string")return o;const a=(0,t.default)(r),l=typeof i=="function";return a.forEach(s=>{if(s.type!=="declaration")return;const{property:u,value:p}=s;l?i(u,p,s):p&&(o=o||{},o[u]=p)}),o}return Et}var zt={},ea;function yu(){if(ea)return zt;ea=1,Object.defineProperty(zt,"__esModule",{value:!0}),zt.camelCase=void 0;var e=/^--[a-zA-Z0-9_-]+$/,t=/-([a-z])/g,n=/^[^-]+$/,r=/^-(webkit|moz|ms|o|khtml)-/,i=/^-(ms)-/,o=function(u){return!u||n.test(u)||e.test(u)},a=function(u,p){return p.toUpperCase()},l=function(u,p){return"".concat(p,"-")},s=function(u,p){return p===void 0&&(p={}),o(u)?u:(u=u.toLowerCase(),p.reactCompat?u=u.replace(i,l):u=u.replace(r,l),u.replace(t,a))};return zt.camelCase=s,zt}var Pt,ta;function bu(){if(ta)return Pt;ta=1;var e=Pt&&Pt.__importDefault||function(i){return i&&i.__esModule?i:{default:i}},t=e(mu()),n=yu();function r(i,o){var a={};return!i||typeof i!="string"||(0,t.default)(i,function(l,s){l&&s&&(a[(0,n.camelCase)(l,o)]=s)}),a}return r.default=r,Pt=r,Pt}var xu=bu();const ku=me(xu),nl=rl("end"),_i=rl("start");function rl(e){return t;function t(n){const r=n&&n.position&&n.position[e]||{};if(typeof r.line=="number"&&r.line>0&&typeof r.column=="number"&&r.column>0)return{line:r.line,column:r.column,offset:typeof r.offset=="number"&&r.offset>-1?r.offset:void 0}}}function vu(e){const t=_i(e),n=nl(e);if(t&&n)return{start:t,end:n}}function qt(e){return!e||typeof e!="object"?"":"position"in e||"type"in e?na(e.position):"start"in e||"end"in e?na(e):"line"in e||"column"in e?oi(e):""}function oi(e){return ra(e&&e.line)+":"+ra(e&&e.column)}function na(e){return oi(e&&e.start)+"-"+oi(e&&e.end)}function ra(e){return e&&typeof e=="number"?e:1}class Oe extends Error{constructor(t,n,r){super(),typeof n=="string"&&(r=n,n=void 0);let i="",o={},a=!1;if(n&&("line"in n&&"column"in n?o={place:n}:"start"in n&&"end"in n?o={place:n}:"type"in n?o={ancestors:[n],place:n.position}:o={...n}),typeof t=="string"?i=t:!o.cause&&t&&(a=!0,i=t.message,o.cause=t),!o.ruleId&&!o.source&&typeof r=="string"){const s=r.indexOf(":");s===-1?o.ruleId=r:(o.source=r.slice(0,s),o.ruleId=r.slice(s+1))}if(!o.place&&o.ancestors&&o.ancestors){const s=o.ancestors[o.ancestors.length-1];s&&(o.place=s.position)}const l=o.place&&"start"in o.place?o.place.start:o.place;this.ancestors=o.ancestors||void 0,this.cause=o.cause||void 0,this.column=l?l.column:void 0,this.fatal=void 0,this.file="",this.message=i,this.line=l?l.line:void 0,this.name=qt(o.place)||"1:1",this.place=o.place||void 0,this.reason=this.message,this.ruleId=o.ruleId||void 0,this.source=o.source||void 0,this.stack=a&&o.cause&&typeof o.cause.stack=="string"?o.cause.stack:"",this.actual=void 0,this.expected=void 0,this.note=void 0,this.url=void 0}}Oe.prototype.file="";Oe.prototype.name="";Oe.prototype.reason="";Oe.prototype.message="";Oe.prototype.stack="";Oe.prototype.column=void 0;Oe.prototype.line=void 0;Oe.prototype.ancestors=void 0;Oe.prototype.cause=void 0;Oe.prototype.fatal=void 0;Oe.prototype.place=void 0;Oe.prototype.ruleId=void 0;Oe.prototype.source=void 0;const Ei={}.hasOwnProperty,wu=new Map,Su=/[A-Z]/g,_u=new Set(["table","tbody","thead","tfoot","tr"]),Eu=new Set(["td","th"]),il="https://github.com/syntax-tree/hast-util-to-jsx-runtime";function Cu(e,t){if(!t||t.Fragment===void 0)throw new TypeError("Expected `Fragment` in options");const n=t.filePath||void 0;let r;if(t.development){if(typeof t.jsxDEV!="function")throw new TypeError("Expected `jsxDEV` in options when `development: true`");r=Ou(n,t.jsxDEV)}else{if(typeof t.jsx!="function")throw new TypeError("Expected `jsx` in production options");if(typeof t.jsxs!="function")throw new TypeError("Expected `jsxs` in production options");r=Ru(n,t.jsx,t.jsxs)}const i={Fragment:t.Fragment,ancestors:[],components:t.components||{},create:r,elementAttributeNameCase:t.elementAttributeNameCase||"react",evaluater:t.createEvaluater?t.createEvaluater():void 0,filePath:n,ignoreInvalidStyle:t.ignoreInvalidStyle||!1,passKeys:t.passKeys!==!1,passNode:t.passNode||!1,schema:t.space==="svg"?Si:fu,stylePropertyNameCase:t.stylePropertyNameCase||"dom",tableCellAlignToStyle:t.tableCellAlignToStyle!==!1},o=al(i,e,void 0);return o&&typeof o!="string"?o:i.create(e,i.Fragment,{children:o||void 0},void 0)}function al(e,t,n){if(t.type==="element")return Tu(e,t,n);if(t.type==="mdxFlowExpression"||t.type==="mdxTextExpression")return Au(e,t);if(t.type==="mdxJsxFlowElement"||t.type==="mdxJsxTextElement")return Nu(e,t,n);if(t.type==="mdxjsEsm")return Lu(e,t);if(t.type==="root")return Iu(e,t,n);if(t.type==="text")return ju(e,t)}function Tu(e,t,n){const r=e.schema;let i=r;t.tagName.toLowerCase()==="svg"&&r.space==="html"&&(i=Si,e.schema=i),e.ancestors.push(t);const o=ll(e,t.tagName,!1),a=Du(e,t);let l=Ti(e,t);return _u.has(t.tagName)&&(l=l.filter(function(s){return typeof s=="string"?!ru(s):!0})),ol(e,a,o,t),Ci(a,l),e.ancestors.pop(),e.schema=r,e.create(t,o,a,n)}function Au(e,t){if(t.data&&t.data.estree&&e.evaluater){const r=t.data.estree.body[0];return r.type,e.evaluater.evaluateExpression(r.expression)}Gt(e,t.position)}function Lu(e,t){if(t.data&&t.data.estree&&e.evaluater)return e.evaluater.evaluateProgram(t.data.estree);Gt(e,t.position)}function Nu(e,t,n){const r=e.schema;let i=r;t.name==="svg"&&r.space==="html"&&(i=Si,e.schema=i),e.ancestors.push(t);const o=t.name===null?e.Fragment:ll(e,t.name,!0),a=Mu(e,t),l=Ti(e,t);return ol(e,a,o,t),Ci(a,l),e.ancestors.pop(),e.schema=r,e.create(t,o,a,n)}function Iu(e,t,n){const r={};return Ci(r,Ti(e,t)),e.create(t,e.Fragment,r,n)}function ju(e,t){return t.value}function ol(e,t,n,r){typeof n!="string"&&n!==e.Fragment&&e.passNode&&(t.node=r)}function Ci(e,t){if(t.length>0){const n=t.length>1?t:t[0];n&&(e.children=n)}}function Ru(e,t,n){return r;function r(i,o,a,l){const u=Array.isArray(a.children)?n:t;return l?u(o,a,l):u(o,a)}}function Ou(e,t){return n;function n(r,i,o,a){const l=Array.isArray(o.children),s=_i(r);return t(i,o,a,l,{columnNumber:s?s.column-1:void 0,fileName:e,lineNumber:s?s.line:void 0},void 0)}}function Du(e,t){const n={};let r,i;for(i in t.properties)if(i!=="children"&&Ei.call(t.properties,i)){const o=Fu(e,i,t.properties[i]);if(o){const[a,l]=o;e.tableCellAlignToStyle&&a==="align"&&typeof l=="string"&&Eu.has(t.tagName)?r=l:n[a]=l}}if(r){const o=n.style||(n.style={});o[e.stylePropertyNameCase==="css"?"text-align":"textAlign"]=r}return n}function Mu(e,t){const n={};for(const r of t.attributes)if(r.type==="mdxJsxExpressionAttribute")if(r.data&&r.data.estree&&e.evaluater){const o=r.data.estree.body[0];o.type;const a=o.expression;a.type;const l=a.properties[0];l.type,Object.assign(n,e.evaluater.evaluateExpression(l.argument))}else Gt(e,t.position);else{const i=r.name;let o;if(r.value&&typeof r.value=="object")if(r.value.data&&r.value.data.estree&&e.evaluater){const l=r.value.data.estree.body[0];l.type,o=e.evaluater.evaluateExpression(l.expression)}else Gt(e,t.position);else o=r.value===null?!0:r.value;n[i]=o}return n}function Ti(e,t){const n=[];let r=-1;const i=e.passKeys?new Map:wu;for(;++ri?0:i+t:t=t>i?i:t,n=n>0?n:0,r.length<1e4)a=Array.from(r),a.unshift(t,n),e.splice(...a);else for(n&&e.splice(t,n);o0?(Ve(e,e.length,0,t),e):t}const oa={}.hasOwnProperty;function ul(e){const t={};let n=-1;for(;++n13&&n<32||n>126&&n<160||n>55295&&n<57344||n>64975&&n<65008||(n&65535)===65535||(n&65535)===65534||n>1114111?"�":String.fromCodePoint(n)}function Ke(e){return e.replace(/[\t\n\r ]+/g," ").replace(/^ | $/g,"").toLowerCase().toUpperCase()}const De=pt(/[A-Za-z]/),Re=pt(/[\dA-Za-z]/),Vu=pt(/[#-'*+\--9=?A-Z^-~]/);function yn(e){return e!==null&&(e<32||e===127)}const li=pt(/\d/),Gu=pt(/[\dA-Fa-f]/),Zu=pt(/[!-/:-@[-`{-~]/);function W(e){return e!==null&&e<-2}function he(e){return e!==null&&(e<0||e===32)}function ne(e){return e===-2||e===-1||e===32}const En=pt(new RegExp("\\p{P}|\\p{S}","u")),kt=pt(/\s/);function pt(e){return t;function t(n){return n!==null&&n>-1&&e.test(String.fromCharCode(n))}}function Ot(e){const t=[];let n=-1,r=0,i=0;for(;++n55295&&o<57344){const l=e.charCodeAt(n+1);o<56320&&l>56319&&l<57344?(a=String.fromCharCode(o,l),i=1):a="�"}else a=String.fromCharCode(o);a&&(t.push(e.slice(r,n),encodeURIComponent(a)),r=n+i+1,a=""),i&&(n+=i,i=0)}return t.join("")+e.slice(r)}function oe(e,t,n,r){const i=r?r-1:Number.POSITIVE_INFINITY;let o=0;return a;function a(s){return ne(s)?(e.enter(n),l(s)):t(s)}function l(s){return ne(s)&&o++a))return;const T=t.events.length;let j=T,A,E;for(;j--;)if(t.events[j][0]==="exit"&&t.events[j][1].type==="chunkFlow"){if(A){E=t.events[j][1].end;break}A=!0}for(x(r),m=T;my;){const C=n[_];t.containerState=C[1],C[0].exit.call(t,e)}n.length=y}function v(){i.write([null]),o=void 0,i=void 0,t.containerState._closeFlow=void 0}}function Ju(e,t,n){return oe(e,e.attempt(this.parser.constructs.document,t,n),"linePrefix",this.parser.constructs.disable.null.includes("codeIndented")?void 0:4)}function jt(e){if(e===null||he(e)||kt(e))return 1;if(En(e))return 2}function Cn(e,t,n){const r=[];let i=-1;for(;++i1&&e[n][1].end.offset-e[n][1].start.offset>1?2:1;const c={...e[r][1].end},f={...e[n][1].start};sa(c,-s),sa(f,s),a={type:s>1?"strongSequence":"emphasisSequence",start:c,end:{...e[r][1].end}},l={type:s>1?"strongSequence":"emphasisSequence",start:{...e[n][1].start},end:f},o={type:s>1?"strongText":"emphasisText",start:{...e[r][1].end},end:{...e[n][1].start}},i={type:s>1?"strong":"emphasis",start:{...a.start},end:{...l.end}},e[r][1].end={...a.start},e[n][1].start={...l.end},u=[],e[r][1].end.offset-e[r][1].start.offset&&(u=Ge(u,[["enter",e[r][1],t],["exit",e[r][1],t]])),u=Ge(u,[["enter",i,t],["enter",a,t],["exit",a,t],["enter",o,t]]),u=Ge(u,Cn(t.parser.constructs.insideSpan.null,e.slice(r+1,n),t)),u=Ge(u,[["exit",o,t],["enter",l,t],["exit",l,t],["exit",i,t]]),e[n][1].end.offset-e[n][1].start.offset?(p=2,u=Ge(u,[["enter",e[n][1],t],["exit",e[n][1],t]])):p=0,Ve(e,r-1,n-r+3,u),n=r+u.length-p-2;break}}for(n=-1;++n0&&ne(m)?oe(e,v,"linePrefix",o+1)(m):v(m)}function v(m){return m===null||W(m)?e.check(ua,k,_)(m):(e.enter("codeFlowValue"),y(m))}function y(m){return m===null||W(m)?(e.exit("codeFlowValue"),v(m)):(e.consume(m),y)}function _(m){return e.exit("codeFenced"),t(m)}function C(m,T,j){let A=0;return E;function E(z){return m.enter("lineEnding"),m.consume(z),m.exit("lineEnding"),R}function R(z){return m.enter("codeFencedFence"),ne(z)?oe(m,M,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(z):M(z)}function M(z){return z===l?(m.enter("codeFencedFenceSequence"),H(z)):j(z)}function H(z){return z===l?(A++,m.consume(z),H):A>=a?(m.exit("codeFencedFenceSequence"),ne(z)?oe(m,P,"whitespace")(z):P(z)):j(z)}function P(z){return z===null||W(z)?(m.exit("codeFencedFence"),T(z)):j(z)}}}function pc(e,t,n){const r=this;return i;function i(a){return a===null?n(a):(e.enter("lineEnding"),e.consume(a),e.exit("lineEnding"),o)}function o(a){return r.parser.lazy[r.now().line]?n(a):t(a)}}const Pn={name:"codeIndented",tokenize:fc},dc={partial:!0,tokenize:hc};function fc(e,t,n){const r=this;return i;function i(u){return e.enter("codeIndented"),oe(e,o,"linePrefix",5)(u)}function o(u){const p=r.events[r.events.length-1];return p&&p[1].type==="linePrefix"&&p[2].sliceSerialize(p[1],!0).length>=4?a(u):n(u)}function a(u){return u===null?s(u):W(u)?e.attempt(dc,a,s)(u):(e.enter("codeFlowValue"),l(u))}function l(u){return u===null||W(u)?(e.exit("codeFlowValue"),a(u)):(e.consume(u),l)}function s(u){return e.exit("codeIndented"),t(u)}}function hc(e,t,n){const r=this;return i;function i(a){return r.parser.lazy[r.now().line]?n(a):W(a)?(e.enter("lineEnding"),e.consume(a),e.exit("lineEnding"),i):oe(e,o,"linePrefix",5)(a)}function o(a){const l=r.events[r.events.length-1];return l&&l[1].type==="linePrefix"&&l[2].sliceSerialize(l[1],!0).length>=4?t(a):W(a)?i(a):n(a)}}const gc={name:"codeText",previous:yc,resolve:mc,tokenize:bc};function mc(e){let t=e.length-4,n=3,r,i;if((e[n][1].type==="lineEnding"||e[n][1].type==="space")&&(e[t][1].type==="lineEnding"||e[t][1].type==="space")){for(r=n;++r=this.left.length+this.right.length)throw new RangeError("Cannot access index `"+t+"` in a splice buffer of size `"+(this.left.length+this.right.length)+"`");return tthis.left.length?this.right.slice(this.right.length-r+this.left.length,this.right.length-t+this.left.length).reverse():this.left.slice(t).concat(this.right.slice(this.right.length-r+this.left.length).reverse())}splice(t,n,r){const i=n||0;this.setCursor(Math.trunc(t));const o=this.right.splice(this.right.length-i,Number.POSITIVE_INFINITY);return r&&Bt(this.left,r),o.reverse()}pop(){return this.setCursor(Number.POSITIVE_INFINITY),this.left.pop()}push(t){this.setCursor(Number.POSITIVE_INFINITY),this.left.push(t)}pushMany(t){this.setCursor(Number.POSITIVE_INFINITY),Bt(this.left,t)}unshift(t){this.setCursor(0),this.right.push(t)}unshiftMany(t){this.setCursor(0),Bt(this.right,t.reverse())}setCursor(t){if(!(t===this.left.length||t>this.left.length&&this.right.length===0||t<0&&this.left.length===0))if(t=4?t(a):e.interrupt(r.parser.constructs.flow,n,t)(a)}}function gl(e,t,n,r,i,o,a,l,s){const u=s||Number.POSITIVE_INFINITY;let p=0;return c;function c(x){return x===60?(e.enter(r),e.enter(i),e.enter(o),e.consume(x),e.exit(o),f):x===null||x===32||x===41||yn(x)?n(x):(e.enter(r),e.enter(a),e.enter(l),e.enter("chunkString",{contentType:"string"}),k(x))}function f(x){return x===62?(e.enter(o),e.consume(x),e.exit(o),e.exit(i),e.exit(r),t):(e.enter(l),e.enter("chunkString",{contentType:"string"}),d(x))}function d(x){return x===62?(e.exit("chunkString"),e.exit(l),f(x)):x===null||x===60||W(x)?n(x):(e.consume(x),x===92?g:d)}function g(x){return x===60||x===62||x===92?(e.consume(x),d):d(x)}function k(x){return!p&&(x===null||x===41||he(x))?(e.exit("chunkString"),e.exit(l),e.exit(a),e.exit(r),t(x)):p999||d===null||d===91||d===93&&!s||d===94&&!l&&"_hiddenFootnoteSupport"in a.parser.constructs?n(d):d===93?(e.exit(o),e.enter(i),e.consume(d),e.exit(i),e.exit(r),t):W(d)?(e.enter("lineEnding"),e.consume(d),e.exit("lineEnding"),p):(e.enter("chunkString",{contentType:"string"}),c(d))}function c(d){return d===null||d===91||d===93||W(d)||l++>999?(e.exit("chunkString"),p(d)):(e.consume(d),s||(s=!ne(d)),d===92?f:c)}function f(d){return d===91||d===92||d===93?(e.consume(d),l++,c):c(d)}}function yl(e,t,n,r,i,o){let a;return l;function l(f){return f===34||f===39||f===40?(e.enter(r),e.enter(i),e.consume(f),e.exit(i),a=f===40?41:f,s):n(f)}function s(f){return f===a?(e.enter(i),e.consume(f),e.exit(i),e.exit(r),t):(e.enter(o),u(f))}function u(f){return f===a?(e.exit(o),s(a)):f===null?n(f):W(f)?(e.enter("lineEnding"),e.consume(f),e.exit("lineEnding"),oe(e,u,"linePrefix")):(e.enter("chunkString",{contentType:"string"}),p(f))}function p(f){return f===a||f===null||W(f)?(e.exit("chunkString"),u(f)):(e.consume(f),f===92?c:p)}function c(f){return f===a||f===92?(e.consume(f),p):p(f)}}function Ut(e,t){let n;return r;function r(i){return W(i)?(e.enter("lineEnding"),e.consume(i),e.exit("lineEnding"),n=!0,r):ne(i)?oe(e,r,n?"linePrefix":"lineSuffix")(i):t(i)}}const Cc={name:"definition",tokenize:Ac},Tc={partial:!0,tokenize:Lc};function Ac(e,t,n){const r=this;let i;return o;function o(d){return e.enter("definition"),a(d)}function a(d){return ml.call(r,e,l,n,"definitionLabel","definitionLabelMarker","definitionLabelString")(d)}function l(d){return i=Ke(r.sliceSerialize(r.events[r.events.length-1][1]).slice(1,-1)),d===58?(e.enter("definitionMarker"),e.consume(d),e.exit("definitionMarker"),s):n(d)}function s(d){return he(d)?Ut(e,u)(d):u(d)}function u(d){return gl(e,p,n,"definitionDestination","definitionDestinationLiteral","definitionDestinationLiteralMarker","definitionDestinationRaw","definitionDestinationString")(d)}function p(d){return e.attempt(Tc,c,c)(d)}function c(d){return ne(d)?oe(e,f,"whitespace")(d):f(d)}function f(d){return d===null||W(d)?(e.exit("definition"),r.parser.defined.push(i),t(d)):n(d)}}function Lc(e,t,n){return r;function r(l){return he(l)?Ut(e,i)(l):n(l)}function i(l){return yl(e,o,n,"definitionTitle","definitionTitleMarker","definitionTitleString")(l)}function o(l){return ne(l)?oe(e,a,"whitespace")(l):a(l)}function a(l){return l===null||W(l)?t(l):n(l)}}const Nc={name:"hardBreakEscape",tokenize:Ic};function Ic(e,t,n){return r;function r(o){return e.enter("hardBreakEscape"),e.consume(o),i}function i(o){return W(o)?(e.exit("hardBreakEscape"),t(o)):n(o)}}const jc={name:"headingAtx",resolve:Rc,tokenize:Oc};function Rc(e,t){let n=e.length-2,r=3,i,o;return e[r][1].type==="whitespace"&&(r+=2),n-2>r&&e[n][1].type==="whitespace"&&(n-=2),e[n][1].type==="atxHeadingSequence"&&(r===n-1||n-4>r&&e[n-2][1].type==="whitespace")&&(n-=r+1===n?2:4),n>r&&(i={type:"atxHeadingText",start:e[r][1].start,end:e[n][1].end},o={type:"chunkText",start:e[r][1].start,end:e[n][1].end,contentType:"text"},Ve(e,r,n-r+1,[["enter",i,t],["enter",o,t],["exit",o,t],["exit",i,t]])),e}function Oc(e,t,n){let r=0;return i;function i(p){return e.enter("atxHeading"),o(p)}function o(p){return e.enter("atxHeadingSequence"),a(p)}function a(p){return p===35&&r++<6?(e.consume(p),a):p===null||he(p)?(e.exit("atxHeadingSequence"),l(p)):n(p)}function l(p){return p===35?(e.enter("atxHeadingSequence"),s(p)):p===null||W(p)?(e.exit("atxHeading"),t(p)):ne(p)?oe(e,l,"whitespace")(p):(e.enter("atxHeadingText"),u(p))}function s(p){return p===35?(e.consume(p),s):(e.exit("atxHeadingSequence"),l(p))}function u(p){return p===null||p===35||he(p)?(e.exit("atxHeadingText"),l(p)):(e.consume(p),u)}}const Dc=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],pa=["pre","script","style","textarea"],Mc={concrete:!0,name:"htmlFlow",resolveTo:Pc,tokenize:Bc},Fc={partial:!0,tokenize:qc},zc={partial:!0,tokenize:$c};function Pc(e){let t=e.length;for(;t--&&!(e[t][0]==="enter"&&e[t][1].type==="htmlFlow"););return t>1&&e[t-2][1].type==="linePrefix"&&(e[t][1].start=e[t-2][1].start,e[t+1][1].start=e[t-2][1].start,e.splice(t-2,2)),e}function Bc(e,t,n){const r=this;let i,o,a,l,s;return u;function u(b){return p(b)}function p(b){return e.enter("htmlFlow"),e.enter("htmlFlowData"),e.consume(b),c}function c(b){return b===33?(e.consume(b),f):b===47?(e.consume(b),o=!0,k):b===63?(e.consume(b),i=3,r.interrupt?t:w):De(b)?(e.consume(b),a=String.fromCharCode(b),S):n(b)}function f(b){return b===45?(e.consume(b),i=2,d):b===91?(e.consume(b),i=5,l=0,g):De(b)?(e.consume(b),i=4,r.interrupt?t:w):n(b)}function d(b){return b===45?(e.consume(b),r.interrupt?t:w):n(b)}function g(b){const Z="CDATA[";return b===Z.charCodeAt(l++)?(e.consume(b),l===Z.length?r.interrupt?t:M:g):n(b)}function k(b){return De(b)?(e.consume(b),a=String.fromCharCode(b),S):n(b)}function S(b){if(b===null||b===47||b===62||he(b)){const Z=b===47,ee=a.toLowerCase();return!Z&&!o&&pa.includes(ee)?(i=1,r.interrupt?t(b):M(b)):Dc.includes(a.toLowerCase())?(i=6,Z?(e.consume(b),x):r.interrupt?t(b):M(b)):(i=7,r.interrupt&&!r.parser.lazy[r.now().line]?n(b):o?v(b):y(b))}return b===45||Re(b)?(e.consume(b),a+=String.fromCharCode(b),S):n(b)}function x(b){return b===62?(e.consume(b),r.interrupt?t:M):n(b)}function v(b){return ne(b)?(e.consume(b),v):E(b)}function y(b){return b===47?(e.consume(b),E):b===58||b===95||De(b)?(e.consume(b),_):ne(b)?(e.consume(b),y):E(b)}function _(b){return b===45||b===46||b===58||b===95||Re(b)?(e.consume(b),_):C(b)}function C(b){return b===61?(e.consume(b),m):ne(b)?(e.consume(b),C):y(b)}function m(b){return b===null||b===60||b===61||b===62||b===96?n(b):b===34||b===39?(e.consume(b),s=b,T):ne(b)?(e.consume(b),m):j(b)}function T(b){return b===s?(e.consume(b),s=null,A):b===null||W(b)?n(b):(e.consume(b),T)}function j(b){return b===null||b===34||b===39||b===47||b===60||b===61||b===62||b===96||he(b)?C(b):(e.consume(b),j)}function A(b){return b===47||b===62||ne(b)?y(b):n(b)}function E(b){return b===62?(e.consume(b),R):n(b)}function R(b){return b===null||W(b)?M(b):ne(b)?(e.consume(b),R):n(b)}function M(b){return b===45&&i===2?(e.consume(b),G):b===60&&i===1?(e.consume(b),J):b===62&&i===4?(e.consume(b),K):b===63&&i===3?(e.consume(b),w):b===93&&i===5?(e.consume(b),ie):W(b)&&(i===6||i===7)?(e.exit("htmlFlowData"),e.check(Fc,Y,H)(b)):b===null||W(b)?(e.exit("htmlFlowData"),H(b)):(e.consume(b),M)}function H(b){return e.check(zc,P,Y)(b)}function P(b){return e.enter("lineEnding"),e.consume(b),e.exit("lineEnding"),z}function z(b){return b===null||W(b)?H(b):(e.enter("htmlFlowData"),M(b))}function G(b){return b===45?(e.consume(b),w):M(b)}function J(b){return b===47?(e.consume(b),a="",U):M(b)}function U(b){if(b===62){const Z=a.toLowerCase();return pa.includes(Z)?(e.consume(b),K):M(b)}return De(b)&&a.length<8?(e.consume(b),a+=String.fromCharCode(b),U):M(b)}function ie(b){return b===93?(e.consume(b),w):M(b)}function w(b){return b===62?(e.consume(b),K):b===45&&i===2?(e.consume(b),w):M(b)}function K(b){return b===null||W(b)?(e.exit("htmlFlowData"),Y(b)):(e.consume(b),K)}function Y(b){return e.exit("htmlFlow"),t(b)}}function $c(e,t,n){const r=this;return i;function i(a){return W(a)?(e.enter("lineEnding"),e.consume(a),e.exit("lineEnding"),o):n(a)}function o(a){return r.parser.lazy[r.now().line]?n(a):t(a)}}function qc(e,t,n){return r;function r(i){return e.enter("lineEnding"),e.consume(i),e.exit("lineEnding"),e.attempt(Qt,t,n)}}const Uc={name:"htmlText",tokenize:Hc};function Hc(e,t,n){const r=this;let i,o,a;return l;function l(w){return e.enter("htmlText"),e.enter("htmlTextData"),e.consume(w),s}function s(w){return w===33?(e.consume(w),u):w===47?(e.consume(w),C):w===63?(e.consume(w),y):De(w)?(e.consume(w),j):n(w)}function u(w){return w===45?(e.consume(w),p):w===91?(e.consume(w),o=0,g):De(w)?(e.consume(w),v):n(w)}function p(w){return w===45?(e.consume(w),d):n(w)}function c(w){return w===null?n(w):w===45?(e.consume(w),f):W(w)?(a=c,J(w)):(e.consume(w),c)}function f(w){return w===45?(e.consume(w),d):c(w)}function d(w){return w===62?G(w):w===45?f(w):c(w)}function g(w){const K="CDATA[";return w===K.charCodeAt(o++)?(e.consume(w),o===K.length?k:g):n(w)}function k(w){return w===null?n(w):w===93?(e.consume(w),S):W(w)?(a=k,J(w)):(e.consume(w),k)}function S(w){return w===93?(e.consume(w),x):k(w)}function x(w){return w===62?G(w):w===93?(e.consume(w),x):k(w)}function v(w){return w===null||w===62?G(w):W(w)?(a=v,J(w)):(e.consume(w),v)}function y(w){return w===null?n(w):w===63?(e.consume(w),_):W(w)?(a=y,J(w)):(e.consume(w),y)}function _(w){return w===62?G(w):y(w)}function C(w){return De(w)?(e.consume(w),m):n(w)}function m(w){return w===45||Re(w)?(e.consume(w),m):T(w)}function T(w){return W(w)?(a=T,J(w)):ne(w)?(e.consume(w),T):G(w)}function j(w){return w===45||Re(w)?(e.consume(w),j):w===47||w===62||he(w)?A(w):n(w)}function A(w){return w===47?(e.consume(w),G):w===58||w===95||De(w)?(e.consume(w),E):W(w)?(a=A,J(w)):ne(w)?(e.consume(w),A):G(w)}function E(w){return w===45||w===46||w===58||w===95||Re(w)?(e.consume(w),E):R(w)}function R(w){return w===61?(e.consume(w),M):W(w)?(a=R,J(w)):ne(w)?(e.consume(w),R):A(w)}function M(w){return w===null||w===60||w===61||w===62||w===96?n(w):w===34||w===39?(e.consume(w),i=w,H):W(w)?(a=M,J(w)):ne(w)?(e.consume(w),M):(e.consume(w),P)}function H(w){return w===i?(e.consume(w),i=void 0,z):w===null?n(w):W(w)?(a=H,J(w)):(e.consume(w),H)}function P(w){return w===null||w===34||w===39||w===60||w===61||w===96?n(w):w===47||w===62||he(w)?A(w):(e.consume(w),P)}function z(w){return w===47||w===62||he(w)?A(w):n(w)}function G(w){return w===62?(e.consume(w),e.exit("htmlTextData"),e.exit("htmlText"),t):n(w)}function J(w){return e.exit("htmlTextData"),e.enter("lineEnding"),e.consume(w),e.exit("lineEnding"),U}function U(w){return ne(w)?oe(e,ie,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(w):ie(w)}function ie(w){return e.enter("htmlTextData"),a(w)}}const Ni={name:"labelEnd",resolveAll:Zc,resolveTo:Xc,tokenize:Kc},Wc={tokenize:Yc},Vc={tokenize:Qc},Gc={tokenize:Jc};function Zc(e){let t=-1;const n=[];for(;++t=3&&(u===null||W(u))?(e.exit("thematicBreak"),t(u)):n(u)}function s(u){return u===i?(e.consume(u),r++,s):(e.exit("thematicBreakSequence"),ne(u)?oe(e,l,"whitespace")(u):l(u))}}const Pe={continuation:{tokenize:up},exit:pp,name:"list",tokenize:sp},op={partial:!0,tokenize:dp},lp={partial:!0,tokenize:cp};function sp(e,t,n){const r=this,i=r.events[r.events.length-1];let o=i&&i[1].type==="linePrefix"?i[2].sliceSerialize(i[1],!0).length:0,a=0;return l;function l(d){const g=r.containerState.type||(d===42||d===43||d===45?"listUnordered":"listOrdered");if(g==="listUnordered"?!r.containerState.marker||d===r.containerState.marker:li(d)){if(r.containerState.type||(r.containerState.type=g,e.enter(g,{_container:!0})),g==="listUnordered")return e.enter("listItemPrefix"),d===42||d===45?e.check(fn,n,u)(d):u(d);if(!r.interrupt||d===49)return e.enter("listItemPrefix"),e.enter("listItemValue"),s(d)}return n(d)}function s(d){return li(d)&&++a<10?(e.consume(d),s):(!r.interrupt||a<2)&&(r.containerState.marker?d===r.containerState.marker:d===41||d===46)?(e.exit("listItemValue"),u(d)):n(d)}function u(d){return e.enter("listItemMarker"),e.consume(d),e.exit("listItemMarker"),r.containerState.marker=r.containerState.marker||d,e.check(Qt,r.interrupt?n:p,e.attempt(op,f,c))}function p(d){return r.containerState.initialBlankLine=!0,o++,f(d)}function c(d){return ne(d)?(e.enter("listItemPrefixWhitespace"),e.consume(d),e.exit("listItemPrefixWhitespace"),f):n(d)}function f(d){return r.containerState.size=o+r.sliceSerialize(e.exit("listItemPrefix"),!0).length,t(d)}}function up(e,t,n){const r=this;return r.containerState._closeFlow=void 0,e.check(Qt,i,o);function i(l){return r.containerState.furtherBlankLines=r.containerState.furtherBlankLines||r.containerState.initialBlankLine,oe(e,t,"listItemIndent",r.containerState.size+1)(l)}function o(l){return r.containerState.furtherBlankLines||!ne(l)?(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,a(l)):(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,e.attempt(lp,t,a)(l))}function a(l){return r.containerState._closeFlow=!0,r.interrupt=void 0,oe(e,e.attempt(Pe,t,n),"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(l)}}function cp(e,t,n){const r=this;return oe(e,i,"listItemIndent",r.containerState.size+1);function i(o){const a=r.events[r.events.length-1];return a&&a[1].type==="listItemIndent"&&a[2].sliceSerialize(a[1],!0).length===r.containerState.size?t(o):n(o)}}function pp(e){e.exit(this.containerState.type)}function dp(e,t,n){const r=this;return oe(e,i,"listItemPrefixWhitespace",r.parser.constructs.disable.null.includes("codeIndented")?void 0:5);function i(o){const a=r.events[r.events.length-1];return!ne(o)&&a&&a[1].type==="listItemPrefixWhitespace"?t(o):n(o)}}const da={name:"setextUnderline",resolveTo:fp,tokenize:hp};function fp(e,t){let n=e.length,r,i,o;for(;n--;)if(e[n][0]==="enter"){if(e[n][1].type==="content"){r=n;break}e[n][1].type==="paragraph"&&(i=n)}else e[n][1].type==="content"&&e.splice(n,1),!o&&e[n][1].type==="definition"&&(o=n);const a={type:"setextHeading",start:{...e[r][1].start},end:{...e[e.length-1][1].end}};return e[i][1].type="setextHeadingText",o?(e.splice(i,0,["enter",a,t]),e.splice(o+1,0,["exit",e[r][1],t]),e[r][1].end={...e[o][1].end}):e[r][1]=a,e.push(["exit",a,t]),e}function hp(e,t,n){const r=this;let i;return o;function o(u){let p=r.events.length,c;for(;p--;)if(r.events[p][1].type!=="lineEnding"&&r.events[p][1].type!=="linePrefix"&&r.events[p][1].type!=="content"){c=r.events[p][1].type==="paragraph";break}return!r.parser.lazy[r.now().line]&&(r.interrupt||c)?(e.enter("setextHeadingLine"),i=u,a(u)):n(u)}function a(u){return e.enter("setextHeadingLineSequence"),l(u)}function l(u){return u===i?(e.consume(u),l):(e.exit("setextHeadingLineSequence"),ne(u)?oe(e,s,"lineSuffix")(u):s(u))}function s(u){return u===null||W(u)?(e.exit("setextHeadingLine"),t(u)):n(u)}}const gp={tokenize:mp};function mp(e){const t=this,n=e.attempt(Qt,r,e.attempt(this.parser.constructs.flowInitial,i,oe(e,e.attempt(this.parser.constructs.flow,i,e.attempt(vc,i)),"linePrefix")));return n;function r(o){if(o===null){e.consume(o);return}return e.enter("lineEndingBlank"),e.consume(o),e.exit("lineEndingBlank"),t.currentConstruct=void 0,n}function i(o){if(o===null){e.consume(o);return}return e.enter("lineEnding"),e.consume(o),e.exit("lineEnding"),t.currentConstruct=void 0,n}}const yp={resolveAll:xl()},bp=bl("string"),xp=bl("text");function bl(e){return{resolveAll:xl(e==="text"?kp:void 0),tokenize:t};function t(n){const r=this,i=this.parser.constructs[e],o=n.attempt(i,a,l);return a;function a(p){return u(p)?o(p):l(p)}function l(p){if(p===null){n.consume(p);return}return n.enter("data"),n.consume(p),s}function s(p){return u(p)?(n.exit("data"),o(p)):(n.consume(p),s)}function u(p){if(p===null)return!0;const c=i[p];let f=-1;if(c)for(;++f-1){const l=a[0];typeof l=="string"?a[0]=l.slice(r):a.shift()}o>0&&a.push(e[i].slice(0,o))}return a}function Rp(e,t){let n=-1;const r=[];let i;for(;++n4&&n.slice(0,4)==="data"&&uu.test(t)){if(t.charAt(4)==="-"){const o=t.slice(5).replace(Yi,du);r="data"+o.charAt(0).toUpperCase()+o.slice(1)}else{const o=t.slice(4);if(!Yi.test(o)){let a=o.replace(su,pu);a.charAt(0)!=="-"&&(a="-"+a),t="data"+a}}i=wi}return new i(r,t)}function pu(e){return"-"+e.toLowerCase()}function du(e){return e.charAt(1).toUpperCase()}const fu=Xo([Ko,au,Jo,el,tl],"html"),Si=Xo([Ko,ou,Jo,el,tl],"svg");function hu(e){return e.join(" ").trim()}var Et={},Fn,Qi;function gu(){if(Qi)return Fn;Qi=1;var e=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//g,t=/\n/g,n=/^\s*/,r=/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/,i=/^:\s*/,o=/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/,a=/^[;\s]*/,l=/^\s+|\s+$/g,s=` +`,u="/",p="*",c="",f="comment",d="declaration";function g(S,x){if(typeof S!="string")throw new TypeError("First argument must be a string");if(!S)return[];x=x||{};var v=1,b=1;function _(P){var z=P.match(t);z&&(v+=z.length);var G=P.lastIndexOf(s);b=~G?P.length-G:b+P.length}function C(){var P={line:v,column:b};return function(z){return z.position=new m(P),A(),z}}function m(P){this.start=P,this.end={line:v,column:b},this.source=x.source}m.prototype.content=S;function T(P){var z=new Error(x.source+":"+v+":"+b+": "+P);if(z.reason=P,z.filename=x.source,z.line=v,z.column=b,z.source=S,!x.silent)throw z}function j(P){var z=P.exec(S);if(z){var G=z[0];return _(G),S=S.slice(G.length),z}}function A(){j(n)}function E(P){var z;for(P=P||[];z=R();)z!==!1&&P.push(z);return P}function R(){var P=C();if(!(u!=S.charAt(0)||p!=S.charAt(1))){for(var z=2;c!=S.charAt(z)&&(p!=S.charAt(z)||u!=S.charAt(z+1));)++z;if(z+=2,c===S.charAt(z-1))return T("End of comment missing");var G=S.slice(2,z-2);return b+=2,_(G),S=S.slice(z),b+=2,P({type:f,comment:G})}}function M(){var P=C(),z=j(r);if(z){if(R(),!j(i))return T("property missing ':'");var G=j(o),J=P({type:d,property:k(z[0].replace(e,c)),value:G?k(G[0].replace(e,c)):c});return j(a),J}}function H(){var P=[];E(P);for(var z;z=M();)z!==!1&&(P.push(z),E(P));return P}return A(),H()}function k(S){return S?S.replace(l,c):c}return Fn=g,Fn}var Ji;function mu(){if(Ji)return Et;Ji=1;var e=Et&&Et.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(Et,"__esModule",{value:!0}),Et.default=n;const t=e(gu());function n(r,i){let o=null;if(!r||typeof r!="string")return o;const a=(0,t.default)(r),l=typeof i=="function";return a.forEach(s=>{if(s.type!=="declaration")return;const{property:u,value:p}=s;l?i(u,p,s):p&&(o=o||{},o[u]=p)}),o}return Et}var zt={},ea;function bu(){if(ea)return zt;ea=1,Object.defineProperty(zt,"__esModule",{value:!0}),zt.camelCase=void 0;var e=/^--[a-zA-Z0-9_-]+$/,t=/-([a-z])/g,n=/^[^-]+$/,r=/^-(webkit|moz|ms|o|khtml)-/,i=/^-(ms)-/,o=function(u){return!u||n.test(u)||e.test(u)},a=function(u,p){return p.toUpperCase()},l=function(u,p){return"".concat(p,"-")},s=function(u,p){return p===void 0&&(p={}),o(u)?u:(u=u.toLowerCase(),p.reactCompat?u=u.replace(i,l):u=u.replace(r,l),u.replace(t,a))};return zt.camelCase=s,zt}var Pt,ta;function yu(){if(ta)return Pt;ta=1;var e=Pt&&Pt.__importDefault||function(i){return i&&i.__esModule?i:{default:i}},t=e(mu()),n=bu();function r(i,o){var a={};return!i||typeof i!="string"||(0,t.default)(i,function(l,s){l&&s&&(a[(0,n.camelCase)(l,o)]=s)}),a}return r.default=r,Pt=r,Pt}var xu=yu();const ku=me(xu),nl=rl("end"),_i=rl("start");function rl(e){return t;function t(n){const r=n&&n.position&&n.position[e]||{};if(typeof r.line=="number"&&r.line>0&&typeof r.column=="number"&&r.column>0)return{line:r.line,column:r.column,offset:typeof r.offset=="number"&&r.offset>-1?r.offset:void 0}}}function vu(e){const t=_i(e),n=nl(e);if(t&&n)return{start:t,end:n}}function qt(e){return!e||typeof e!="object"?"":"position"in e||"type"in e?na(e.position):"start"in e||"end"in e?na(e):"line"in e||"column"in e?oi(e):""}function oi(e){return ra(e&&e.line)+":"+ra(e&&e.column)}function na(e){return oi(e&&e.start)+"-"+oi(e&&e.end)}function ra(e){return e&&typeof e=="number"?e:1}class Oe extends Error{constructor(t,n,r){super(),typeof n=="string"&&(r=n,n=void 0);let i="",o={},a=!1;if(n&&("line"in n&&"column"in n?o={place:n}:"start"in n&&"end"in n?o={place:n}:"type"in n?o={ancestors:[n],place:n.position}:o={...n}),typeof t=="string"?i=t:!o.cause&&t&&(a=!0,i=t.message,o.cause=t),!o.ruleId&&!o.source&&typeof r=="string"){const s=r.indexOf(":");s===-1?o.ruleId=r:(o.source=r.slice(0,s),o.ruleId=r.slice(s+1))}if(!o.place&&o.ancestors&&o.ancestors){const s=o.ancestors[o.ancestors.length-1];s&&(o.place=s.position)}const l=o.place&&"start"in o.place?o.place.start:o.place;this.ancestors=o.ancestors||void 0,this.cause=o.cause||void 0,this.column=l?l.column:void 0,this.fatal=void 0,this.file="",this.message=i,this.line=l?l.line:void 0,this.name=qt(o.place)||"1:1",this.place=o.place||void 0,this.reason=this.message,this.ruleId=o.ruleId||void 0,this.source=o.source||void 0,this.stack=a&&o.cause&&typeof o.cause.stack=="string"?o.cause.stack:"",this.actual=void 0,this.expected=void 0,this.note=void 0,this.url=void 0}}Oe.prototype.file="";Oe.prototype.name="";Oe.prototype.reason="";Oe.prototype.message="";Oe.prototype.stack="";Oe.prototype.column=void 0;Oe.prototype.line=void 0;Oe.prototype.ancestors=void 0;Oe.prototype.cause=void 0;Oe.prototype.fatal=void 0;Oe.prototype.place=void 0;Oe.prototype.ruleId=void 0;Oe.prototype.source=void 0;const Ei={}.hasOwnProperty,wu=new Map,Su=/[A-Z]/g,_u=new Set(["table","tbody","thead","tfoot","tr"]),Eu=new Set(["td","th"]),il="https://github.com/syntax-tree/hast-util-to-jsx-runtime";function Cu(e,t){if(!t||t.Fragment===void 0)throw new TypeError("Expected `Fragment` in options");const n=t.filePath||void 0;let r;if(t.development){if(typeof t.jsxDEV!="function")throw new TypeError("Expected `jsxDEV` in options when `development: true`");r=Ou(n,t.jsxDEV)}else{if(typeof t.jsx!="function")throw new TypeError("Expected `jsx` in production options");if(typeof t.jsxs!="function")throw new TypeError("Expected `jsxs` in production options");r=Ru(n,t.jsx,t.jsxs)}const i={Fragment:t.Fragment,ancestors:[],components:t.components||{},create:r,elementAttributeNameCase:t.elementAttributeNameCase||"react",evaluater:t.createEvaluater?t.createEvaluater():void 0,filePath:n,ignoreInvalidStyle:t.ignoreInvalidStyle||!1,passKeys:t.passKeys!==!1,passNode:t.passNode||!1,schema:t.space==="svg"?Si:fu,stylePropertyNameCase:t.stylePropertyNameCase||"dom",tableCellAlignToStyle:t.tableCellAlignToStyle!==!1},o=al(i,e,void 0);return o&&typeof o!="string"?o:i.create(e,i.Fragment,{children:o||void 0},void 0)}function al(e,t,n){if(t.type==="element")return Tu(e,t,n);if(t.type==="mdxFlowExpression"||t.type==="mdxTextExpression")return Au(e,t);if(t.type==="mdxJsxFlowElement"||t.type==="mdxJsxTextElement")return Nu(e,t,n);if(t.type==="mdxjsEsm")return Lu(e,t);if(t.type==="root")return Iu(e,t,n);if(t.type==="text")return ju(e,t)}function Tu(e,t,n){const r=e.schema;let i=r;t.tagName.toLowerCase()==="svg"&&r.space==="html"&&(i=Si,e.schema=i),e.ancestors.push(t);const o=ll(e,t.tagName,!1),a=Du(e,t);let l=Ti(e,t);return _u.has(t.tagName)&&(l=l.filter(function(s){return typeof s=="string"?!ru(s):!0})),ol(e,a,o,t),Ci(a,l),e.ancestors.pop(),e.schema=r,e.create(t,o,a,n)}function Au(e,t){if(t.data&&t.data.estree&&e.evaluater){const r=t.data.estree.body[0];return r.type,e.evaluater.evaluateExpression(r.expression)}Gt(e,t.position)}function Lu(e,t){if(t.data&&t.data.estree&&e.evaluater)return e.evaluater.evaluateProgram(t.data.estree);Gt(e,t.position)}function Nu(e,t,n){const r=e.schema;let i=r;t.name==="svg"&&r.space==="html"&&(i=Si,e.schema=i),e.ancestors.push(t);const o=t.name===null?e.Fragment:ll(e,t.name,!0),a=Mu(e,t),l=Ti(e,t);return ol(e,a,o,t),Ci(a,l),e.ancestors.pop(),e.schema=r,e.create(t,o,a,n)}function Iu(e,t,n){const r={};return Ci(r,Ti(e,t)),e.create(t,e.Fragment,r,n)}function ju(e,t){return t.value}function ol(e,t,n,r){typeof n!="string"&&n!==e.Fragment&&e.passNode&&(t.node=r)}function Ci(e,t){if(t.length>0){const n=t.length>1?t:t[0];n&&(e.children=n)}}function Ru(e,t,n){return r;function r(i,o,a,l){const u=Array.isArray(a.children)?n:t;return l?u(o,a,l):u(o,a)}}function Ou(e,t){return n;function n(r,i,o,a){const l=Array.isArray(o.children),s=_i(r);return t(i,o,a,l,{columnNumber:s?s.column-1:void 0,fileName:e,lineNumber:s?s.line:void 0},void 0)}}function Du(e,t){const n={};let r,i;for(i in t.properties)if(i!=="children"&&Ei.call(t.properties,i)){const o=Fu(e,i,t.properties[i]);if(o){const[a,l]=o;e.tableCellAlignToStyle&&a==="align"&&typeof l=="string"&&Eu.has(t.tagName)?r=l:n[a]=l}}if(r){const o=n.style||(n.style={});o[e.stylePropertyNameCase==="css"?"text-align":"textAlign"]=r}return n}function Mu(e,t){const n={};for(const r of t.attributes)if(r.type==="mdxJsxExpressionAttribute")if(r.data&&r.data.estree&&e.evaluater){const o=r.data.estree.body[0];o.type;const a=o.expression;a.type;const l=a.properties[0];l.type,Object.assign(n,e.evaluater.evaluateExpression(l.argument))}else Gt(e,t.position);else{const i=r.name;let o;if(r.value&&typeof r.value=="object")if(r.value.data&&r.value.data.estree&&e.evaluater){const l=r.value.data.estree.body[0];l.type,o=e.evaluater.evaluateExpression(l.expression)}else Gt(e,t.position);else o=r.value===null?!0:r.value;n[i]=o}return n}function Ti(e,t){const n=[];let r=-1;const i=e.passKeys?new Map:wu;for(;++ri?0:i+t:t=t>i?i:t,n=n>0?n:0,r.length<1e4)a=Array.from(r),a.unshift(t,n),e.splice(...a);else for(n&&e.splice(t,n);o0?(Ve(e,e.length,0,t),e):t}const oa={}.hasOwnProperty;function ul(e){const t={};let n=-1;for(;++n13&&n<32||n>126&&n<160||n>55295&&n<57344||n>64975&&n<65008||(n&65535)===65535||(n&65535)===65534||n>1114111?"�":String.fromCodePoint(n)}function Ke(e){return e.replace(/[\t\n\r ]+/g," ").replace(/^ | $/g,"").toLowerCase().toUpperCase()}const De=pt(/[A-Za-z]/),Re=pt(/[\dA-Za-z]/),Vu=pt(/[#-'*+\--9=?A-Z^-~]/);function bn(e){return e!==null&&(e<32||e===127)}const li=pt(/\d/),Gu=pt(/[\dA-Fa-f]/),Zu=pt(/[!-/:-@[-`{-~]/);function W(e){return e!==null&&e<-2}function he(e){return e!==null&&(e<0||e===32)}function ne(e){return e===-2||e===-1||e===32}const En=pt(new RegExp("\\p{P}|\\p{S}","u")),kt=pt(/\s/);function pt(e){return t;function t(n){return n!==null&&n>-1&&e.test(String.fromCharCode(n))}}function Ot(e){const t=[];let n=-1,r=0,i=0;for(;++n55295&&o<57344){const l=e.charCodeAt(n+1);o<56320&&l>56319&&l<57344?(a=String.fromCharCode(o,l),i=1):a="�"}else a=String.fromCharCode(o);a&&(t.push(e.slice(r,n),encodeURIComponent(a)),r=n+i+1,a=""),i&&(n+=i,i=0)}return t.join("")+e.slice(r)}function oe(e,t,n,r){const i=r?r-1:Number.POSITIVE_INFINITY;let o=0;return a;function a(s){return ne(s)?(e.enter(n),l(s)):t(s)}function l(s){return ne(s)&&o++a))return;const T=t.events.length;let j=T,A,E;for(;j--;)if(t.events[j][0]==="exit"&&t.events[j][1].type==="chunkFlow"){if(A){E=t.events[j][1].end;break}A=!0}for(x(r),m=T;mb;){const C=n[_];t.containerState=C[1],C[0].exit.call(t,e)}n.length=b}function v(){i.write([null]),o=void 0,i=void 0,t.containerState._closeFlow=void 0}}function Ju(e,t,n){return oe(e,e.attempt(this.parser.constructs.document,t,n),"linePrefix",this.parser.constructs.disable.null.includes("codeIndented")?void 0:4)}function jt(e){if(e===null||he(e)||kt(e))return 1;if(En(e))return 2}function Cn(e,t,n){const r=[];let i=-1;for(;++i1&&e[n][1].end.offset-e[n][1].start.offset>1?2:1;const c={...e[r][1].end},f={...e[n][1].start};sa(c,-s),sa(f,s),a={type:s>1?"strongSequence":"emphasisSequence",start:c,end:{...e[r][1].end}},l={type:s>1?"strongSequence":"emphasisSequence",start:{...e[n][1].start},end:f},o={type:s>1?"strongText":"emphasisText",start:{...e[r][1].end},end:{...e[n][1].start}},i={type:s>1?"strong":"emphasis",start:{...a.start},end:{...l.end}},e[r][1].end={...a.start},e[n][1].start={...l.end},u=[],e[r][1].end.offset-e[r][1].start.offset&&(u=Ge(u,[["enter",e[r][1],t],["exit",e[r][1],t]])),u=Ge(u,[["enter",i,t],["enter",a,t],["exit",a,t],["enter",o,t]]),u=Ge(u,Cn(t.parser.constructs.insideSpan.null,e.slice(r+1,n),t)),u=Ge(u,[["exit",o,t],["enter",l,t],["exit",l,t],["exit",i,t]]),e[n][1].end.offset-e[n][1].start.offset?(p=2,u=Ge(u,[["enter",e[n][1],t],["exit",e[n][1],t]])):p=0,Ve(e,r-1,n-r+3,u),n=r+u.length-p-2;break}}for(n=-1;++n0&&ne(m)?oe(e,v,"linePrefix",o+1)(m):v(m)}function v(m){return m===null||W(m)?e.check(ua,k,_)(m):(e.enter("codeFlowValue"),b(m))}function b(m){return m===null||W(m)?(e.exit("codeFlowValue"),v(m)):(e.consume(m),b)}function _(m){return e.exit("codeFenced"),t(m)}function C(m,T,j){let A=0;return E;function E(z){return m.enter("lineEnding"),m.consume(z),m.exit("lineEnding"),R}function R(z){return m.enter("codeFencedFence"),ne(z)?oe(m,M,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(z):M(z)}function M(z){return z===l?(m.enter("codeFencedFenceSequence"),H(z)):j(z)}function H(z){return z===l?(A++,m.consume(z),H):A>=a?(m.exit("codeFencedFenceSequence"),ne(z)?oe(m,P,"whitespace")(z):P(z)):j(z)}function P(z){return z===null||W(z)?(m.exit("codeFencedFence"),T(z)):j(z)}}}function pc(e,t,n){const r=this;return i;function i(a){return a===null?n(a):(e.enter("lineEnding"),e.consume(a),e.exit("lineEnding"),o)}function o(a){return r.parser.lazy[r.now().line]?n(a):t(a)}}const Pn={name:"codeIndented",tokenize:fc},dc={partial:!0,tokenize:hc};function fc(e,t,n){const r=this;return i;function i(u){return e.enter("codeIndented"),oe(e,o,"linePrefix",5)(u)}function o(u){const p=r.events[r.events.length-1];return p&&p[1].type==="linePrefix"&&p[2].sliceSerialize(p[1],!0).length>=4?a(u):n(u)}function a(u){return u===null?s(u):W(u)?e.attempt(dc,a,s)(u):(e.enter("codeFlowValue"),l(u))}function l(u){return u===null||W(u)?(e.exit("codeFlowValue"),a(u)):(e.consume(u),l)}function s(u){return e.exit("codeIndented"),t(u)}}function hc(e,t,n){const r=this;return i;function i(a){return r.parser.lazy[r.now().line]?n(a):W(a)?(e.enter("lineEnding"),e.consume(a),e.exit("lineEnding"),i):oe(e,o,"linePrefix",5)(a)}function o(a){const l=r.events[r.events.length-1];return l&&l[1].type==="linePrefix"&&l[2].sliceSerialize(l[1],!0).length>=4?t(a):W(a)?i(a):n(a)}}const gc={name:"codeText",previous:bc,resolve:mc,tokenize:yc};function mc(e){let t=e.length-4,n=3,r,i;if((e[n][1].type==="lineEnding"||e[n][1].type==="space")&&(e[t][1].type==="lineEnding"||e[t][1].type==="space")){for(r=n;++r=this.left.length+this.right.length)throw new RangeError("Cannot access index `"+t+"` in a splice buffer of size `"+(this.left.length+this.right.length)+"`");return tthis.left.length?this.right.slice(this.right.length-r+this.left.length,this.right.length-t+this.left.length).reverse():this.left.slice(t).concat(this.right.slice(this.right.length-r+this.left.length).reverse())}splice(t,n,r){const i=n||0;this.setCursor(Math.trunc(t));const o=this.right.splice(this.right.length-i,Number.POSITIVE_INFINITY);return r&&Bt(this.left,r),o.reverse()}pop(){return this.setCursor(Number.POSITIVE_INFINITY),this.left.pop()}push(t){this.setCursor(Number.POSITIVE_INFINITY),this.left.push(t)}pushMany(t){this.setCursor(Number.POSITIVE_INFINITY),Bt(this.left,t)}unshift(t){this.setCursor(0),this.right.push(t)}unshiftMany(t){this.setCursor(0),Bt(this.right,t.reverse())}setCursor(t){if(!(t===this.left.length||t>this.left.length&&this.right.length===0||t<0&&this.left.length===0))if(t=4?t(a):e.interrupt(r.parser.constructs.flow,n,t)(a)}}function gl(e,t,n,r,i,o,a,l,s){const u=s||Number.POSITIVE_INFINITY;let p=0;return c;function c(x){return x===60?(e.enter(r),e.enter(i),e.enter(o),e.consume(x),e.exit(o),f):x===null||x===32||x===41||bn(x)?n(x):(e.enter(r),e.enter(a),e.enter(l),e.enter("chunkString",{contentType:"string"}),k(x))}function f(x){return x===62?(e.enter(o),e.consume(x),e.exit(o),e.exit(i),e.exit(r),t):(e.enter(l),e.enter("chunkString",{contentType:"string"}),d(x))}function d(x){return x===62?(e.exit("chunkString"),e.exit(l),f(x)):x===null||x===60||W(x)?n(x):(e.consume(x),x===92?g:d)}function g(x){return x===60||x===62||x===92?(e.consume(x),d):d(x)}function k(x){return!p&&(x===null||x===41||he(x))?(e.exit("chunkString"),e.exit(l),e.exit(a),e.exit(r),t(x)):p999||d===null||d===91||d===93&&!s||d===94&&!l&&"_hiddenFootnoteSupport"in a.parser.constructs?n(d):d===93?(e.exit(o),e.enter(i),e.consume(d),e.exit(i),e.exit(r),t):W(d)?(e.enter("lineEnding"),e.consume(d),e.exit("lineEnding"),p):(e.enter("chunkString",{contentType:"string"}),c(d))}function c(d){return d===null||d===91||d===93||W(d)||l++>999?(e.exit("chunkString"),p(d)):(e.consume(d),s||(s=!ne(d)),d===92?f:c)}function f(d){return d===91||d===92||d===93?(e.consume(d),l++,c):c(d)}}function bl(e,t,n,r,i,o){let a;return l;function l(f){return f===34||f===39||f===40?(e.enter(r),e.enter(i),e.consume(f),e.exit(i),a=f===40?41:f,s):n(f)}function s(f){return f===a?(e.enter(i),e.consume(f),e.exit(i),e.exit(r),t):(e.enter(o),u(f))}function u(f){return f===a?(e.exit(o),s(a)):f===null?n(f):W(f)?(e.enter("lineEnding"),e.consume(f),e.exit("lineEnding"),oe(e,u,"linePrefix")):(e.enter("chunkString",{contentType:"string"}),p(f))}function p(f){return f===a||f===null||W(f)?(e.exit("chunkString"),u(f)):(e.consume(f),f===92?c:p)}function c(f){return f===a||f===92?(e.consume(f),p):p(f)}}function Ut(e,t){let n;return r;function r(i){return W(i)?(e.enter("lineEnding"),e.consume(i),e.exit("lineEnding"),n=!0,r):ne(i)?oe(e,r,n?"linePrefix":"lineSuffix")(i):t(i)}}const Cc={name:"definition",tokenize:Ac},Tc={partial:!0,tokenize:Lc};function Ac(e,t,n){const r=this;let i;return o;function o(d){return e.enter("definition"),a(d)}function a(d){return ml.call(r,e,l,n,"definitionLabel","definitionLabelMarker","definitionLabelString")(d)}function l(d){return i=Ke(r.sliceSerialize(r.events[r.events.length-1][1]).slice(1,-1)),d===58?(e.enter("definitionMarker"),e.consume(d),e.exit("definitionMarker"),s):n(d)}function s(d){return he(d)?Ut(e,u)(d):u(d)}function u(d){return gl(e,p,n,"definitionDestination","definitionDestinationLiteral","definitionDestinationLiteralMarker","definitionDestinationRaw","definitionDestinationString")(d)}function p(d){return e.attempt(Tc,c,c)(d)}function c(d){return ne(d)?oe(e,f,"whitespace")(d):f(d)}function f(d){return d===null||W(d)?(e.exit("definition"),r.parser.defined.push(i),t(d)):n(d)}}function Lc(e,t,n){return r;function r(l){return he(l)?Ut(e,i)(l):n(l)}function i(l){return bl(e,o,n,"definitionTitle","definitionTitleMarker","definitionTitleString")(l)}function o(l){return ne(l)?oe(e,a,"whitespace")(l):a(l)}function a(l){return l===null||W(l)?t(l):n(l)}}const Nc={name:"hardBreakEscape",tokenize:Ic};function Ic(e,t,n){return r;function r(o){return e.enter("hardBreakEscape"),e.consume(o),i}function i(o){return W(o)?(e.exit("hardBreakEscape"),t(o)):n(o)}}const jc={name:"headingAtx",resolve:Rc,tokenize:Oc};function Rc(e,t){let n=e.length-2,r=3,i,o;return e[r][1].type==="whitespace"&&(r+=2),n-2>r&&e[n][1].type==="whitespace"&&(n-=2),e[n][1].type==="atxHeadingSequence"&&(r===n-1||n-4>r&&e[n-2][1].type==="whitespace")&&(n-=r+1===n?2:4),n>r&&(i={type:"atxHeadingText",start:e[r][1].start,end:e[n][1].end},o={type:"chunkText",start:e[r][1].start,end:e[n][1].end,contentType:"text"},Ve(e,r,n-r+1,[["enter",i,t],["enter",o,t],["exit",o,t],["exit",i,t]])),e}function Oc(e,t,n){let r=0;return i;function i(p){return e.enter("atxHeading"),o(p)}function o(p){return e.enter("atxHeadingSequence"),a(p)}function a(p){return p===35&&r++<6?(e.consume(p),a):p===null||he(p)?(e.exit("atxHeadingSequence"),l(p)):n(p)}function l(p){return p===35?(e.enter("atxHeadingSequence"),s(p)):p===null||W(p)?(e.exit("atxHeading"),t(p)):ne(p)?oe(e,l,"whitespace")(p):(e.enter("atxHeadingText"),u(p))}function s(p){return p===35?(e.consume(p),s):(e.exit("atxHeadingSequence"),l(p))}function u(p){return p===null||p===35||he(p)?(e.exit("atxHeadingText"),l(p)):(e.consume(p),u)}}const Dc=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],pa=["pre","script","style","textarea"],Mc={concrete:!0,name:"htmlFlow",resolveTo:Pc,tokenize:Bc},Fc={partial:!0,tokenize:qc},zc={partial:!0,tokenize:$c};function Pc(e){let t=e.length;for(;t--&&!(e[t][0]==="enter"&&e[t][1].type==="htmlFlow"););return t>1&&e[t-2][1].type==="linePrefix"&&(e[t][1].start=e[t-2][1].start,e[t+1][1].start=e[t-2][1].start,e.splice(t-2,2)),e}function Bc(e,t,n){const r=this;let i,o,a,l,s;return u;function u(y){return p(y)}function p(y){return e.enter("htmlFlow"),e.enter("htmlFlowData"),e.consume(y),c}function c(y){return y===33?(e.consume(y),f):y===47?(e.consume(y),o=!0,k):y===63?(e.consume(y),i=3,r.interrupt?t:w):De(y)?(e.consume(y),a=String.fromCharCode(y),S):n(y)}function f(y){return y===45?(e.consume(y),i=2,d):y===91?(e.consume(y),i=5,l=0,g):De(y)?(e.consume(y),i=4,r.interrupt?t:w):n(y)}function d(y){return y===45?(e.consume(y),r.interrupt?t:w):n(y)}function g(y){const Z="CDATA[";return y===Z.charCodeAt(l++)?(e.consume(y),l===Z.length?r.interrupt?t:M:g):n(y)}function k(y){return De(y)?(e.consume(y),a=String.fromCharCode(y),S):n(y)}function S(y){if(y===null||y===47||y===62||he(y)){const Z=y===47,ee=a.toLowerCase();return!Z&&!o&&pa.includes(ee)?(i=1,r.interrupt?t(y):M(y)):Dc.includes(a.toLowerCase())?(i=6,Z?(e.consume(y),x):r.interrupt?t(y):M(y)):(i=7,r.interrupt&&!r.parser.lazy[r.now().line]?n(y):o?v(y):b(y))}return y===45||Re(y)?(e.consume(y),a+=String.fromCharCode(y),S):n(y)}function x(y){return y===62?(e.consume(y),r.interrupt?t:M):n(y)}function v(y){return ne(y)?(e.consume(y),v):E(y)}function b(y){return y===47?(e.consume(y),E):y===58||y===95||De(y)?(e.consume(y),_):ne(y)?(e.consume(y),b):E(y)}function _(y){return y===45||y===46||y===58||y===95||Re(y)?(e.consume(y),_):C(y)}function C(y){return y===61?(e.consume(y),m):ne(y)?(e.consume(y),C):b(y)}function m(y){return y===null||y===60||y===61||y===62||y===96?n(y):y===34||y===39?(e.consume(y),s=y,T):ne(y)?(e.consume(y),m):j(y)}function T(y){return y===s?(e.consume(y),s=null,A):y===null||W(y)?n(y):(e.consume(y),T)}function j(y){return y===null||y===34||y===39||y===47||y===60||y===61||y===62||y===96||he(y)?C(y):(e.consume(y),j)}function A(y){return y===47||y===62||ne(y)?b(y):n(y)}function E(y){return y===62?(e.consume(y),R):n(y)}function R(y){return y===null||W(y)?M(y):ne(y)?(e.consume(y),R):n(y)}function M(y){return y===45&&i===2?(e.consume(y),G):y===60&&i===1?(e.consume(y),J):y===62&&i===4?(e.consume(y),K):y===63&&i===3?(e.consume(y),w):y===93&&i===5?(e.consume(y),ie):W(y)&&(i===6||i===7)?(e.exit("htmlFlowData"),e.check(Fc,Y,H)(y)):y===null||W(y)?(e.exit("htmlFlowData"),H(y)):(e.consume(y),M)}function H(y){return e.check(zc,P,Y)(y)}function P(y){return e.enter("lineEnding"),e.consume(y),e.exit("lineEnding"),z}function z(y){return y===null||W(y)?H(y):(e.enter("htmlFlowData"),M(y))}function G(y){return y===45?(e.consume(y),w):M(y)}function J(y){return y===47?(e.consume(y),a="",U):M(y)}function U(y){if(y===62){const Z=a.toLowerCase();return pa.includes(Z)?(e.consume(y),K):M(y)}return De(y)&&a.length<8?(e.consume(y),a+=String.fromCharCode(y),U):M(y)}function ie(y){return y===93?(e.consume(y),w):M(y)}function w(y){return y===62?(e.consume(y),K):y===45&&i===2?(e.consume(y),w):M(y)}function K(y){return y===null||W(y)?(e.exit("htmlFlowData"),Y(y)):(e.consume(y),K)}function Y(y){return e.exit("htmlFlow"),t(y)}}function $c(e,t,n){const r=this;return i;function i(a){return W(a)?(e.enter("lineEnding"),e.consume(a),e.exit("lineEnding"),o):n(a)}function o(a){return r.parser.lazy[r.now().line]?n(a):t(a)}}function qc(e,t,n){return r;function r(i){return e.enter("lineEnding"),e.consume(i),e.exit("lineEnding"),e.attempt(Qt,t,n)}}const Uc={name:"htmlText",tokenize:Hc};function Hc(e,t,n){const r=this;let i,o,a;return l;function l(w){return e.enter("htmlText"),e.enter("htmlTextData"),e.consume(w),s}function s(w){return w===33?(e.consume(w),u):w===47?(e.consume(w),C):w===63?(e.consume(w),b):De(w)?(e.consume(w),j):n(w)}function u(w){return w===45?(e.consume(w),p):w===91?(e.consume(w),o=0,g):De(w)?(e.consume(w),v):n(w)}function p(w){return w===45?(e.consume(w),d):n(w)}function c(w){return w===null?n(w):w===45?(e.consume(w),f):W(w)?(a=c,J(w)):(e.consume(w),c)}function f(w){return w===45?(e.consume(w),d):c(w)}function d(w){return w===62?G(w):w===45?f(w):c(w)}function g(w){const K="CDATA[";return w===K.charCodeAt(o++)?(e.consume(w),o===K.length?k:g):n(w)}function k(w){return w===null?n(w):w===93?(e.consume(w),S):W(w)?(a=k,J(w)):(e.consume(w),k)}function S(w){return w===93?(e.consume(w),x):k(w)}function x(w){return w===62?G(w):w===93?(e.consume(w),x):k(w)}function v(w){return w===null||w===62?G(w):W(w)?(a=v,J(w)):(e.consume(w),v)}function b(w){return w===null?n(w):w===63?(e.consume(w),_):W(w)?(a=b,J(w)):(e.consume(w),b)}function _(w){return w===62?G(w):b(w)}function C(w){return De(w)?(e.consume(w),m):n(w)}function m(w){return w===45||Re(w)?(e.consume(w),m):T(w)}function T(w){return W(w)?(a=T,J(w)):ne(w)?(e.consume(w),T):G(w)}function j(w){return w===45||Re(w)?(e.consume(w),j):w===47||w===62||he(w)?A(w):n(w)}function A(w){return w===47?(e.consume(w),G):w===58||w===95||De(w)?(e.consume(w),E):W(w)?(a=A,J(w)):ne(w)?(e.consume(w),A):G(w)}function E(w){return w===45||w===46||w===58||w===95||Re(w)?(e.consume(w),E):R(w)}function R(w){return w===61?(e.consume(w),M):W(w)?(a=R,J(w)):ne(w)?(e.consume(w),R):A(w)}function M(w){return w===null||w===60||w===61||w===62||w===96?n(w):w===34||w===39?(e.consume(w),i=w,H):W(w)?(a=M,J(w)):ne(w)?(e.consume(w),M):(e.consume(w),P)}function H(w){return w===i?(e.consume(w),i=void 0,z):w===null?n(w):W(w)?(a=H,J(w)):(e.consume(w),H)}function P(w){return w===null||w===34||w===39||w===60||w===61||w===96?n(w):w===47||w===62||he(w)?A(w):(e.consume(w),P)}function z(w){return w===47||w===62||he(w)?A(w):n(w)}function G(w){return w===62?(e.consume(w),e.exit("htmlTextData"),e.exit("htmlText"),t):n(w)}function J(w){return e.exit("htmlTextData"),e.enter("lineEnding"),e.consume(w),e.exit("lineEnding"),U}function U(w){return ne(w)?oe(e,ie,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(w):ie(w)}function ie(w){return e.enter("htmlTextData"),a(w)}}const Ni={name:"labelEnd",resolveAll:Zc,resolveTo:Xc,tokenize:Kc},Wc={tokenize:Yc},Vc={tokenize:Qc},Gc={tokenize:Jc};function Zc(e){let t=-1;const n=[];for(;++t=3&&(u===null||W(u))?(e.exit("thematicBreak"),t(u)):n(u)}function s(u){return u===i?(e.consume(u),r++,s):(e.exit("thematicBreakSequence"),ne(u)?oe(e,l,"whitespace")(u):l(u))}}const Pe={continuation:{tokenize:up},exit:pp,name:"list",tokenize:sp},op={partial:!0,tokenize:dp},lp={partial:!0,tokenize:cp};function sp(e,t,n){const r=this,i=r.events[r.events.length-1];let o=i&&i[1].type==="linePrefix"?i[2].sliceSerialize(i[1],!0).length:0,a=0;return l;function l(d){const g=r.containerState.type||(d===42||d===43||d===45?"listUnordered":"listOrdered");if(g==="listUnordered"?!r.containerState.marker||d===r.containerState.marker:li(d)){if(r.containerState.type||(r.containerState.type=g,e.enter(g,{_container:!0})),g==="listUnordered")return e.enter("listItemPrefix"),d===42||d===45?e.check(fn,n,u)(d):u(d);if(!r.interrupt||d===49)return e.enter("listItemPrefix"),e.enter("listItemValue"),s(d)}return n(d)}function s(d){return li(d)&&++a<10?(e.consume(d),s):(!r.interrupt||a<2)&&(r.containerState.marker?d===r.containerState.marker:d===41||d===46)?(e.exit("listItemValue"),u(d)):n(d)}function u(d){return e.enter("listItemMarker"),e.consume(d),e.exit("listItemMarker"),r.containerState.marker=r.containerState.marker||d,e.check(Qt,r.interrupt?n:p,e.attempt(op,f,c))}function p(d){return r.containerState.initialBlankLine=!0,o++,f(d)}function c(d){return ne(d)?(e.enter("listItemPrefixWhitespace"),e.consume(d),e.exit("listItemPrefixWhitespace"),f):n(d)}function f(d){return r.containerState.size=o+r.sliceSerialize(e.exit("listItemPrefix"),!0).length,t(d)}}function up(e,t,n){const r=this;return r.containerState._closeFlow=void 0,e.check(Qt,i,o);function i(l){return r.containerState.furtherBlankLines=r.containerState.furtherBlankLines||r.containerState.initialBlankLine,oe(e,t,"listItemIndent",r.containerState.size+1)(l)}function o(l){return r.containerState.furtherBlankLines||!ne(l)?(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,a(l)):(r.containerState.furtherBlankLines=void 0,r.containerState.initialBlankLine=void 0,e.attempt(lp,t,a)(l))}function a(l){return r.containerState._closeFlow=!0,r.interrupt=void 0,oe(e,e.attempt(Pe,t,n),"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(l)}}function cp(e,t,n){const r=this;return oe(e,i,"listItemIndent",r.containerState.size+1);function i(o){const a=r.events[r.events.length-1];return a&&a[1].type==="listItemIndent"&&a[2].sliceSerialize(a[1],!0).length===r.containerState.size?t(o):n(o)}}function pp(e){e.exit(this.containerState.type)}function dp(e,t,n){const r=this;return oe(e,i,"listItemPrefixWhitespace",r.parser.constructs.disable.null.includes("codeIndented")?void 0:5);function i(o){const a=r.events[r.events.length-1];return!ne(o)&&a&&a[1].type==="listItemPrefixWhitespace"?t(o):n(o)}}const da={name:"setextUnderline",resolveTo:fp,tokenize:hp};function fp(e,t){let n=e.length,r,i,o;for(;n--;)if(e[n][0]==="enter"){if(e[n][1].type==="content"){r=n;break}e[n][1].type==="paragraph"&&(i=n)}else e[n][1].type==="content"&&e.splice(n,1),!o&&e[n][1].type==="definition"&&(o=n);const a={type:"setextHeading",start:{...e[r][1].start},end:{...e[e.length-1][1].end}};return e[i][1].type="setextHeadingText",o?(e.splice(i,0,["enter",a,t]),e.splice(o+1,0,["exit",e[r][1],t]),e[r][1].end={...e[o][1].end}):e[r][1]=a,e.push(["exit",a,t]),e}function hp(e,t,n){const r=this;let i;return o;function o(u){let p=r.events.length,c;for(;p--;)if(r.events[p][1].type!=="lineEnding"&&r.events[p][1].type!=="linePrefix"&&r.events[p][1].type!=="content"){c=r.events[p][1].type==="paragraph";break}return!r.parser.lazy[r.now().line]&&(r.interrupt||c)?(e.enter("setextHeadingLine"),i=u,a(u)):n(u)}function a(u){return e.enter("setextHeadingLineSequence"),l(u)}function l(u){return u===i?(e.consume(u),l):(e.exit("setextHeadingLineSequence"),ne(u)?oe(e,s,"lineSuffix")(u):s(u))}function s(u){return u===null||W(u)?(e.exit("setextHeadingLine"),t(u)):n(u)}}const gp={tokenize:mp};function mp(e){const t=this,n=e.attempt(Qt,r,e.attempt(this.parser.constructs.flowInitial,i,oe(e,e.attempt(this.parser.constructs.flow,i,e.attempt(vc,i)),"linePrefix")));return n;function r(o){if(o===null){e.consume(o);return}return e.enter("lineEndingBlank"),e.consume(o),e.exit("lineEndingBlank"),t.currentConstruct=void 0,n}function i(o){if(o===null){e.consume(o);return}return e.enter("lineEnding"),e.consume(o),e.exit("lineEnding"),t.currentConstruct=void 0,n}}const bp={resolveAll:xl()},yp=yl("string"),xp=yl("text");function yl(e){return{resolveAll:xl(e==="text"?kp:void 0),tokenize:t};function t(n){const r=this,i=this.parser.constructs[e],o=n.attempt(i,a,l);return a;function a(p){return u(p)?o(p):l(p)}function l(p){if(p===null){n.consume(p);return}return n.enter("data"),n.consume(p),s}function s(p){return u(p)?(n.exit("data"),o(p)):(n.consume(p),s)}function u(p){if(p===null)return!0;const c=i[p];let f=-1;if(c)for(;++f-1){const l=a[0];typeof l=="string"?a[0]=l.slice(r):a.shift()}o>0&&a.push(e[i].slice(0,o))}return a}function Rp(e,t){let n=-1;const r=[];let i;for(;++n0){const ke=B.tokenStack[B.tokenStack.length-1];(ke[1]||ha).call(B,void 0,ke[0])}for(D.position={start:st(L.length>0?L[0][1].start:{line:1,column:1,offset:0}),end:st(L.length>0?L[L.length-2][1].end:{line:1,column:1,offset:0})},re=-1;++re0){const ke=B.tokenStack[B.tokenStack.length-1];(ke[1]||ha).call(B,void 0,ke[0])}for(D.position={start:st(L.length>0?L[0][1].start:{line:1,column:1,offset:0}),end:st(L.length>0?L[L.length-2][1].end:{line:1,column:1,offset:0})},re=-1;++re0&&(r.className=["language-"+i[0]]);let o={type:"element",tagName:"code",properties:r,children:[{type:"text",value:n}]};return t.meta&&(o.data={meta:t.meta}),e.patch(t,o),o=e.applyData(t,o),o={type:"element",tagName:"pre",properties:{},children:[o]},e.patch(t,o),o}function Gp(e,t){const n={type:"element",tagName:"del",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function Zp(e,t){const n={type:"element",tagName:"em",properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function Xp(e,t){const n=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",r=String(t.identifier).toUpperCase(),i=Ot(r.toLowerCase()),o=e.footnoteOrder.indexOf(r);let a,l=e.footnoteCounts.get(r);l===void 0?(l=0,e.footnoteOrder.push(r),a=e.footnoteOrder.length):a=o+1,l+=1,e.footnoteCounts.set(r,l);const s={type:"element",tagName:"a",properties:{href:"#"+n+"fn-"+i,id:n+"fnref-"+i+(l>1?"-"+l:""),dataFootnoteRef:!0,ariaDescribedBy:["footnote-label"]},children:[{type:"text",value:String(a)}]};e.patch(t,s);const u={type:"element",tagName:"sup",properties:{},children:[s]};return e.patch(t,u),e.applyData(t,u)}function Kp(e,t){const n={type:"element",tagName:"h"+t.depth,properties:{},children:e.all(t)};return e.patch(t,n),e.applyData(t,n)}function Yp(e,t){if(e.options.allowDangerousHtml){const n={type:"raw",value:t.value};return e.patch(t,n),e.applyData(t,n)}}function wl(e,t){const n=t.referenceType;let r="]";if(n==="collapsed"?r+="[]":n==="full"&&(r+="["+(t.label||t.identifier)+"]"),t.type==="imageReference")return[{type:"text",value:"!["+t.alt+r}];const i=e.all(t),o=i[0];o&&o.type==="text"?o.value="["+o.value:i.unshift({type:"text",value:"["});const a=i[i.length-1];return a&&a.type==="text"?a.value+=r:i.push({type:"text",value:r}),i}function Qp(e,t){const n=String(t.identifier).toUpperCase(),r=e.definitionById.get(n);if(!r)return wl(e,t);const i={src:Ot(r.url||""),alt:t.alt};r.title!==null&&r.title!==void 0&&(i.title=r.title);const o={type:"element",tagName:"img",properties:i,children:[]};return e.patch(t,o),e.applyData(t,o)}function Jp(e,t){const n={src:Ot(t.url)};t.alt!==null&&t.alt!==void 0&&(n.alt=t.alt),t.title!==null&&t.title!==void 0&&(n.title=t.title);const r={type:"element",tagName:"img",properties:n,children:[]};return e.patch(t,r),e.applyData(t,r)}function ed(e,t){const n={type:"text",value:t.value.replace(/\r?\n|\r/g," ")};e.patch(t,n);const r={type:"element",tagName:"code",properties:{},children:[n]};return e.patch(t,r),e.applyData(t,r)}function td(e,t){const n=String(t.identifier).toUpperCase(),r=e.definitionById.get(n);if(!r)return wl(e,t);const i={href:Ot(r.url||"")};r.title!==null&&r.title!==void 0&&(i.title=r.title);const o={type:"element",tagName:"a",properties:i,children:e.all(t)};return e.patch(t,o),e.applyData(t,o)}function nd(e,t){const n={href:Ot(t.url)};t.title!==null&&t.title!==void 0&&(n.title=t.title);const r={type:"element",tagName:"a",properties:n,children:e.all(t)};return e.patch(t,r),e.applyData(t,r)}function rd(e,t,n){const r=e.all(t),i=n?id(n):Sl(t),o={},a=[];if(typeof t.checked=="boolean"){const p=r[0];let c;p&&p.type==="element"&&p.tagName==="p"?c=p:(c={type:"element",tagName:"p",properties:{},children:[]},r.unshift(c)),c.children.length>0&&c.children.unshift({type:"text",value:" "}),c.children.unshift({type:"element",tagName:"input",properties:{type:"checkbox",checked:t.checked,disabled:!0},children:[]}),o.className=["task-list-item"]}let l=-1;for(;++l1}function ad(e,t){const n={},r=e.all(t);let i=-1;for(typeof t.start=="number"&&t.start!==1&&(n.start=t.start);++i0){const a={type:"element",tagName:"tbody",properties:{},children:e.wrap(n,!0)},l=_i(t.children[1]),s=nl(t.children[t.children.length-1]);l&&s&&(a.position={start:l,end:s}),i.push(a)}const o={type:"element",tagName:"table",properties:{},children:e.wrap(i,!0)};return e.patch(t,o),e.applyData(t,o)}function cd(e,t,n){const r=n?n.children:void 0,o=(r?r.indexOf(t):1)===0?"th":"td",a=n&&n.type==="table"?n.align:void 0,l=a?a.length:t.children.length;let s=-1;const u=[];for(;++s0,!0),r[0]),i=r.index+r[0].length,r=n.exec(t);return o.push(ya(t.slice(i),i>0,!1)),o.join("")}function ya(e,t,n){let r=0,i=e.length;if(t){let o=e.codePointAt(r);for(;o===ga||o===ma;)r++,o=e.codePointAt(r)}if(n){let o=e.codePointAt(i-1);for(;o===ga||o===ma;)i--,o=e.codePointAt(i-1)}return i>r?e.slice(r,i):""}function fd(e,t){const n={type:"text",value:dd(String(t.value))};return e.patch(t,n),e.applyData(t,n)}function hd(e,t){const n={type:"element",tagName:"hr",properties:{},children:[]};return e.patch(t,n),e.applyData(t,n)}const gd={blockquote:Hp,break:Wp,code:Vp,delete:Gp,emphasis:Zp,footnoteReference:Xp,heading:Kp,html:Yp,imageReference:Qp,image:Jp,inlineCode:ed,linkReference:td,link:nd,listItem:rd,list:ad,paragraph:od,root:ld,strong:sd,table:ud,tableCell:pd,tableRow:cd,text:fd,thematicBreak:hd,toml:ln,yaml:ln,definition:ln,footnoteDefinition:ln};function ln(){}const _l=-1,Tn=0,Ht=1,bn=2,Ii=3,ji=4,Ri=5,Oi=6,El=7,Cl=8,ba=typeof self=="object"?self:globalThis,md=(e,t)=>{const n=(i,o)=>(e.set(o,i),i),r=i=>{if(e.has(i))return e.get(i);const[o,a]=t[i];switch(o){case Tn:case _l:return n(a,i);case Ht:{const l=n([],i);for(const s of a)l.push(r(s));return l}case bn:{const l=n({},i);for(const[s,u]of a)l[r(s)]=r(u);return l}case Ii:return n(new Date(a),i);case ji:{const{source:l,flags:s}=a;return n(new RegExp(l,s),i)}case Ri:{const l=n(new Map,i);for(const[s,u]of a)l.set(r(s),r(u));return l}case Oi:{const l=n(new Set,i);for(const s of a)l.add(r(s));return l}case El:{const{name:l,message:s}=a;return n(new ba[l](s),i)}case Cl:return n(BigInt(a),i);case"BigInt":return n(Object(BigInt(a)),i);case"ArrayBuffer":return n(new Uint8Array(a).buffer,a);case"DataView":{const{buffer:l}=new Uint8Array(a);return n(new DataView(l),a)}}return n(new ba[o](a),i)};return r},xa=e=>md(new Map,e)(0),Ct="",{toString:yd}={},{keys:bd}=Object,$t=e=>{const t=typeof e;if(t!=="object"||!e)return[Tn,t];const n=yd.call(e).slice(8,-1);switch(n){case"Array":return[Ht,Ct];case"Object":return[bn,Ct];case"Date":return[Ii,Ct];case"RegExp":return[ji,Ct];case"Map":return[Ri,Ct];case"Set":return[Oi,Ct];case"DataView":return[Ht,n]}return n.includes("Array")?[Ht,n]:n.includes("Error")?[El,n]:[bn,n]},sn=([e,t])=>e===Tn&&(t==="function"||t==="symbol"),xd=(e,t,n,r)=>{const i=(a,l)=>{const s=r.push(a)-1;return n.set(l,s),s},o=a=>{if(n.has(a))return n.get(a);let[l,s]=$t(a);switch(l){case Tn:{let p=a;switch(s){case"bigint":l=Cl,p=a.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+s);p=null;break;case"undefined":return i([_l],a)}return i([l,p],a)}case Ht:{if(s){let f=a;return s==="DataView"?f=new Uint8Array(a.buffer):s==="ArrayBuffer"&&(f=new Uint8Array(a)),i([s,[...f]],a)}const p=[],c=i([l,p],a);for(const f of a)p.push(o(f));return c}case bn:{if(s)switch(s){case"BigInt":return i([s,a.toString()],a);case"Boolean":case"Number":case"String":return i([s,a.valueOf()],a)}if(t&&"toJSON"in a)return o(a.toJSON());const p=[],c=i([l,p],a);for(const f of bd(a))(e||!sn($t(a[f])))&&p.push([o(f),o(a[f])]);return c}case Ii:return i([l,a.toISOString()],a);case ji:{const{source:p,flags:c}=a;return i([l,{source:p,flags:c}],a)}case Ri:{const p=[],c=i([l,p],a);for(const[f,d]of a)(e||!(sn($t(f))||sn($t(d))))&&p.push([o(f),o(d)]);return c}case Oi:{const p=[],c=i([l,p],a);for(const f of a)(e||!sn($t(f)))&&p.push(o(f));return c}}const{message:u}=a;return i([l,{name:s,message:u}],a)};return o},ka=(e,{json:t,lossy:n}={})=>{const r=[];return xd(!(t||n),!!t,new Map,r)(e),r},xn=typeof structuredClone=="function"?(e,t)=>t&&("json"in t||"lossy"in t)?xa(ka(e,t)):structuredClone(e):(e,t)=>xa(ka(e,t));function kd(e,t){const n=[{type:"text",value:"↩"}];return t>1&&n.push({type:"element",tagName:"sup",properties:{},children:[{type:"text",value:String(t)}]}),n}function vd(e,t){return"Back to reference "+(e+1)+(t>1?"-"+t:"")}function wd(e){const t=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",n=e.options.footnoteBackContent||kd,r=e.options.footnoteBackLabel||vd,i=e.options.footnoteLabel||"Footnotes",o=e.options.footnoteLabelTagName||"h2",a=e.options.footnoteLabelProperties||{className:["sr-only"]},l=[];let s=-1;for(;++s0&&g.push({type:"text",value:" "});let v=typeof n=="string"?n:n(s,d);typeof v=="string"&&(v={type:"text",value:v}),g.push({type:"element",tagName:"a",properties:{href:"#"+t+"fnref-"+f+(d>1?"-"+d:""),dataFootnoteBackref:"",ariaLabel:typeof r=="string"?r:r(s,d),className:["data-footnote-backref"]},children:Array.isArray(v)?v:[v]})}const S=p[p.length-1];if(S&&S.type==="element"&&S.tagName==="p"){const v=S.children[S.children.length-1];v&&v.type==="text"?v.value+=" ":S.children.push({type:"text",value:" "}),S.children.push(...g)}else p.push(...g);const x={type:"element",tagName:"li",properties:{id:t+"fn-"+f},children:e.wrap(p,!0)};e.patch(u,x),l.push(x)}if(l.length!==0)return{type:"element",tagName:"section",properties:{dataFootnotes:!0,className:["footnotes"]},children:[{type:"element",tagName:o,properties:{...xn(a),id:"footnote-label"},children:[{type:"text",value:i}]},{type:"text",value:` +`});const u={type:"element",tagName:"li",properties:o,children:a};return e.patch(t,u),e.applyData(t,u)}function id(e){let t=!1;if(e.type==="list"){t=e.spread||!1;const n=e.children;let r=-1;for(;!t&&++r1}function ad(e,t){const n={},r=e.all(t);let i=-1;for(typeof t.start=="number"&&t.start!==1&&(n.start=t.start);++i0){const a={type:"element",tagName:"tbody",properties:{},children:e.wrap(n,!0)},l=_i(t.children[1]),s=nl(t.children[t.children.length-1]);l&&s&&(a.position={start:l,end:s}),i.push(a)}const o={type:"element",tagName:"table",properties:{},children:e.wrap(i,!0)};return e.patch(t,o),e.applyData(t,o)}function cd(e,t,n){const r=n?n.children:void 0,o=(r?r.indexOf(t):1)===0?"th":"td",a=n&&n.type==="table"?n.align:void 0,l=a?a.length:t.children.length;let s=-1;const u=[];for(;++s0,!0),r[0]),i=r.index+r[0].length,r=n.exec(t);return o.push(ba(t.slice(i),i>0,!1)),o.join("")}function ba(e,t,n){let r=0,i=e.length;if(t){let o=e.codePointAt(r);for(;o===ga||o===ma;)r++,o=e.codePointAt(r)}if(n){let o=e.codePointAt(i-1);for(;o===ga||o===ma;)i--,o=e.codePointAt(i-1)}return i>r?e.slice(r,i):""}function fd(e,t){const n={type:"text",value:dd(String(t.value))};return e.patch(t,n),e.applyData(t,n)}function hd(e,t){const n={type:"element",tagName:"hr",properties:{},children:[]};return e.patch(t,n),e.applyData(t,n)}const gd={blockquote:Hp,break:Wp,code:Vp,delete:Gp,emphasis:Zp,footnoteReference:Xp,heading:Kp,html:Yp,imageReference:Qp,image:Jp,inlineCode:ed,linkReference:td,link:nd,listItem:rd,list:ad,paragraph:od,root:ld,strong:sd,table:ud,tableCell:pd,tableRow:cd,text:fd,thematicBreak:hd,toml:ln,yaml:ln,definition:ln,footnoteDefinition:ln};function ln(){}const _l=-1,Tn=0,Ht=1,yn=2,Ii=3,ji=4,Ri=5,Oi=6,El=7,Cl=8,ya=typeof self=="object"?self:globalThis,md=(e,t)=>{const n=(i,o)=>(e.set(o,i),i),r=i=>{if(e.has(i))return e.get(i);const[o,a]=t[i];switch(o){case Tn:case _l:return n(a,i);case Ht:{const l=n([],i);for(const s of a)l.push(r(s));return l}case yn:{const l=n({},i);for(const[s,u]of a)l[r(s)]=r(u);return l}case Ii:return n(new Date(a),i);case ji:{const{source:l,flags:s}=a;return n(new RegExp(l,s),i)}case Ri:{const l=n(new Map,i);for(const[s,u]of a)l.set(r(s),r(u));return l}case Oi:{const l=n(new Set,i);for(const s of a)l.add(r(s));return l}case El:{const{name:l,message:s}=a;return n(new ya[l](s),i)}case Cl:return n(BigInt(a),i);case"BigInt":return n(Object(BigInt(a)),i);case"ArrayBuffer":return n(new Uint8Array(a).buffer,a);case"DataView":{const{buffer:l}=new Uint8Array(a);return n(new DataView(l),a)}}return n(new ya[o](a),i)};return r},xa=e=>md(new Map,e)(0),Ct="",{toString:bd}={},{keys:yd}=Object,$t=e=>{const t=typeof e;if(t!=="object"||!e)return[Tn,t];const n=bd.call(e).slice(8,-1);switch(n){case"Array":return[Ht,Ct];case"Object":return[yn,Ct];case"Date":return[Ii,Ct];case"RegExp":return[ji,Ct];case"Map":return[Ri,Ct];case"Set":return[Oi,Ct];case"DataView":return[Ht,n]}return n.includes("Array")?[Ht,n]:n.includes("Error")?[El,n]:[yn,n]},sn=([e,t])=>e===Tn&&(t==="function"||t==="symbol"),xd=(e,t,n,r)=>{const i=(a,l)=>{const s=r.push(a)-1;return n.set(l,s),s},o=a=>{if(n.has(a))return n.get(a);let[l,s]=$t(a);switch(l){case Tn:{let p=a;switch(s){case"bigint":l=Cl,p=a.toString();break;case"function":case"symbol":if(e)throw new TypeError("unable to serialize "+s);p=null;break;case"undefined":return i([_l],a)}return i([l,p],a)}case Ht:{if(s){let f=a;return s==="DataView"?f=new Uint8Array(a.buffer):s==="ArrayBuffer"&&(f=new Uint8Array(a)),i([s,[...f]],a)}const p=[],c=i([l,p],a);for(const f of a)p.push(o(f));return c}case yn:{if(s)switch(s){case"BigInt":return i([s,a.toString()],a);case"Boolean":case"Number":case"String":return i([s,a.valueOf()],a)}if(t&&"toJSON"in a)return o(a.toJSON());const p=[],c=i([l,p],a);for(const f of yd(a))(e||!sn($t(a[f])))&&p.push([o(f),o(a[f])]);return c}case Ii:return i([l,a.toISOString()],a);case ji:{const{source:p,flags:c}=a;return i([l,{source:p,flags:c}],a)}case Ri:{const p=[],c=i([l,p],a);for(const[f,d]of a)(e||!(sn($t(f))||sn($t(d))))&&p.push([o(f),o(d)]);return c}case Oi:{const p=[],c=i([l,p],a);for(const f of a)(e||!sn($t(f)))&&p.push(o(f));return c}}const{message:u}=a;return i([l,{name:s,message:u}],a)};return o},ka=(e,{json:t,lossy:n}={})=>{const r=[];return xd(!(t||n),!!t,new Map,r)(e),r},xn=typeof structuredClone=="function"?(e,t)=>t&&("json"in t||"lossy"in t)?xa(ka(e,t)):structuredClone(e):(e,t)=>xa(ka(e,t));function kd(e,t){const n=[{type:"text",value:"↩"}];return t>1&&n.push({type:"element",tagName:"sup",properties:{},children:[{type:"text",value:String(t)}]}),n}function vd(e,t){return"Back to reference "+(e+1)+(t>1?"-"+t:"")}function wd(e){const t=typeof e.options.clobberPrefix=="string"?e.options.clobberPrefix:"user-content-",n=e.options.footnoteBackContent||kd,r=e.options.footnoteBackLabel||vd,i=e.options.footnoteLabel||"Footnotes",o=e.options.footnoteLabelTagName||"h2",a=e.options.footnoteLabelProperties||{className:["sr-only"]},l=[];let s=-1;for(;++s0&&g.push({type:"text",value:" "});let v=typeof n=="string"?n:n(s,d);typeof v=="string"&&(v={type:"text",value:v}),g.push({type:"element",tagName:"a",properties:{href:"#"+t+"fnref-"+f+(d>1?"-"+d:""),dataFootnoteBackref:"",ariaLabel:typeof r=="string"?r:r(s,d),className:["data-footnote-backref"]},children:Array.isArray(v)?v:[v]})}const S=p[p.length-1];if(S&&S.type==="element"&&S.tagName==="p"){const v=S.children[S.children.length-1];v&&v.type==="text"?v.value+=" ":S.children.push({type:"text",value:" "}),S.children.push(...g)}else p.push(...g);const x={type:"element",tagName:"li",properties:{id:t+"fn-"+f},children:e.wrap(p,!0)};e.patch(u,x),l.push(x)}if(l.length!==0)return{type:"element",tagName:"section",properties:{dataFootnotes:!0,className:["footnotes"]},children:[{type:"element",tagName:o,properties:{...xn(a),id:"footnote-label"},children:[{type:"text",value:i}]},{type:"text",value:` `},{type:"element",tagName:"ol",properties:{},children:e.wrap(l,!0)},{type:"text",value:` `}]}}const An=(function(e){if(e==null)return Cd;if(typeof e=="function")return Ln(e);if(typeof e=="object")return Array.isArray(e)?Sd(e):_d(e);if(typeof e=="string")return Ed(e);throw new Error("Expected function, string, or object as test")});function Sd(e){const t=[];let n=-1;for(;++n":""))+")"})}return f;function f(){let d=Tl,g,k,S;if((!t||o(s,u,p[p.length-1]||void 0))&&(d=Nd(n(s,p)),d[0]===ui))return d;if("children"in s&&s.children){const x=s;if(x.children&&d[0]!==Ld)for(k=(r?x.children.length:-1)+a,S=p.concat(x);k>-1&&k0&&n.push({type:"text",value:` `}),n}function va(e){let t=0,n=e.charCodeAt(t);for(;n===9||n===32;)t++,n=e.charCodeAt(t);return e.slice(t)}function wa(e,t){const n=jd(e,t),r=n.one(e,void 0),i=wd(n),o=Array.isArray(r)?{type:"root",children:r}:r||{type:"root",children:[]};return i&&o.children.push({type:"text",value:` -`},i),o}function Fd(e,t){return e&&"run"in e?async function(n,r){const i=wa(n,{file:r,...t});await e.run(i,r)}:function(n,r){return wa(n,{file:r,...e||t})}}function Sa(e){if(e)throw e}var $n,_a;function zd(){if(_a)return $n;_a=1;var e=Object.prototype.hasOwnProperty,t=Object.prototype.toString,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=function(u){return typeof Array.isArray=="function"?Array.isArray(u):t.call(u)==="[object Array]"},o=function(u){if(!u||t.call(u)!=="[object Object]")return!1;var p=e.call(u,"constructor"),c=u.constructor&&u.constructor.prototype&&e.call(u.constructor.prototype,"isPrototypeOf");if(u.constructor&&!p&&!c)return!1;var f;for(f in u);return typeof f>"u"||e.call(u,f)},a=function(u,p){n&&p.name==="__proto__"?n(u,p.name,{enumerable:!0,configurable:!0,value:p.newValue,writable:!0}):u[p.name]=p.newValue},l=function(u,p){if(p==="__proto__")if(e.call(u,p)){if(r)return r(u,p).value}else return;return u[p]};return $n=function s(){var u,p,c,f,d,g,k=arguments[0],S=1,x=arguments.length,v=!1;for(typeof k=="boolean"&&(v=k,k=arguments[1]||{},S=2),(k==null||typeof k!="object"&&typeof k!="function")&&(k={});Sa.length;let s;l&&a.push(i);try{s=e.apply(this,a)}catch(u){const p=u;if(l&&n)throw p;return i(p)}l||(s&&s.then&&typeof s.then=="function"?s.then(o,i):s instanceof Error?i(s):o(s))}function i(a,...l){n||(n=!0,t(a,...l))}function o(a){i(null,a)}}const et={basename:qd,dirname:Ud,extname:Hd,join:Wd,sep:"/"};function qd(e,t){if(t!==void 0&&typeof t!="string")throw new TypeError('"ext" argument must be a string');Jt(e);let n=0,r=-1,i=e.length,o;if(t===void 0||t.length===0||t.length>e.length){for(;i--;)if(e.codePointAt(i)===47){if(o){n=i+1;break}}else r<0&&(o=!0,r=i+1);return r<0?"":e.slice(n,r)}if(t===e)return"";let a=-1,l=t.length-1;for(;i--;)if(e.codePointAt(i)===47){if(o){n=i+1;break}}else a<0&&(o=!0,a=i+1),l>-1&&(e.codePointAt(i)===t.codePointAt(l--)?l<0&&(r=i):(l=-1,r=a));return n===r?r=a:r<0&&(r=e.length),e.slice(n,r)}function Ud(e){if(Jt(e),e.length===0)return".";let t=-1,n=e.length,r;for(;--n;)if(e.codePointAt(n)===47){if(r){t=n;break}}else r||(r=!0);return t<0?e.codePointAt(0)===47?"/":".":t===1&&e.codePointAt(0)===47?"//":e.slice(0,t)}function Hd(e){Jt(e);let t=e.length,n=-1,r=0,i=-1,o=0,a;for(;t--;){const l=e.codePointAt(t);if(l===47){if(a){r=t+1;break}continue}n<0&&(a=!0,n=t+1),l===46?i<0?i=t:o!==1&&(o=1):i>-1&&(o=-1)}return i<0||n<0||o===0||o===1&&i===n-1&&i===r+1?"":e.slice(i,n)}function Wd(...e){let t=-1,n;for(;++t0&&e.codePointAt(e.length-1)===47&&(n+="/"),t?"/"+n:n}function Gd(e,t){let n="",r=0,i=-1,o=0,a=-1,l,s;for(;++a<=e.length;){if(a2){if(s=n.lastIndexOf("/"),s!==n.length-1){s<0?(n="",r=0):(n=n.slice(0,s),r=n.length-1-n.lastIndexOf("/")),i=a,o=0;continue}}else if(n.length>0){n="",r=0,i=a,o=0;continue}}t&&(n=n.length>0?n+"/..":"..",r=2)}else n.length>0?n+="/"+e.slice(i+1,a):n=e.slice(i+1,a),r=a-i-1;i=a,o=0}else l===46&&o>-1?o++:o=-1}return n}function Jt(e){if(typeof e!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}const Zd={cwd:Xd};function Xd(){return"/"}function di(e){return!!(e!==null&&typeof e=="object"&&"href"in e&&e.href&&"protocol"in e&&e.protocol&&e.auth===void 0)}function Kd(e){if(typeof e=="string")e=new URL(e);else if(!di(e)){const t=new TypeError('The "path" argument must be of type string or an instance of URL. Received `'+e+"`");throw t.code="ERR_INVALID_ARG_TYPE",t}if(e.protocol!=="file:"){const t=new TypeError("The URL must be of scheme file");throw t.code="ERR_INVALID_URL_SCHEME",t}return Yd(e)}function Yd(e){if(e.hostname!==""){const r=new TypeError('File URL host must be "localhost" or empty on darwin');throw r.code="ERR_INVALID_FILE_URL_HOST",r}const t=e.pathname;let n=-1;for(;++n0){let[d,...g]=p;const k=r[f][1];pi(k)&&pi(d)&&(d=qn(!0,k,d)),r[f]=[u,d,...g]}}}}const tf=new Mi().freeze();function Vn(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `parser`")}function Gn(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `compiler`")}function Zn(e,t){if(t)throw new Error("Cannot call `"+e+"` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.")}function Ca(e){if(!pi(e)||typeof e.type!="string")throw new TypeError("Expected node, got `"+e+"`")}function Ta(e,t,n){if(!n)throw new Error("`"+e+"` finished async. Use `"+t+"` instead")}function un(e){return nf(e)?e:new Ll(e)}function nf(e){return!!(e&&typeof e=="object"&&"message"in e&&"messages"in e)}function rf(e){return typeof e=="string"||af(e)}function af(e){return!!(e&&typeof e=="object"&&"byteLength"in e&&"byteOffset"in e)}const of="https://github.com/remarkjs/react-markdown/blob/main/changelog.md",Aa=[],La={allowDangerousHtml:!0},lf=/^(https?|ircs?|mailto|xmpp)$/i,sf=[{from:"astPlugins",id:"remove-buggy-html-in-markdown-parser"},{from:"allowDangerousHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"allowNode",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowElement"},{from:"allowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowedElements"},{from:"className",id:"remove-classname"},{from:"disallowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"disallowedElements"},{from:"escapeHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"includeElementIndex",id:"#remove-includeelementindex"},{from:"includeNodeIndex",id:"change-includenodeindex-to-includeelementindex"},{from:"linkTarget",id:"remove-linktarget"},{from:"plugins",id:"change-plugins-to-remarkplugins",to:"remarkPlugins"},{from:"rawSourcePos",id:"#remove-rawsourcepos"},{from:"renderers",id:"change-renderers-to-components",to:"components"},{from:"source",id:"change-source-to-children",to:"children"},{from:"sourcePos",id:"#remove-sourcepos"},{from:"transformImageUri",id:"#add-urltransform",to:"urlTransform"},{from:"transformLinkUri",id:"#add-urltransform",to:"urlTransform"}];function uf(e){const t=cf(e),n=pf(e);return df(t.runSync(t.parse(n),n),e)}function cf(e){const t=e.rehypePlugins||Aa,n=e.remarkPlugins||Aa,r=e.remarkRehypeOptions?{...e.remarkRehypeOptions,...La}:La;return tf().use(Up).use(n).use(Fd,r).use(t)}function pf(e){const t=e.children||"",n=new Ll;return typeof t=="string"&&(n.value=t),n}function df(e,t){const n=t.allowedElements,r=t.allowElement,i=t.components,o=t.disallowedElements,a=t.skipHtml,l=t.unwrapDisallowed,s=t.urlTransform||ff;for(const p of sf)Object.hasOwn(t,p.from)&&(""+p.from+(p.to?"use `"+p.to+"` instead":"remove it")+of+p.id,void 0);return Di(e,u),Cu(e,{Fragment:h.Fragment,components:i,ignoreInvalidStyle:!0,jsx:h.jsx,jsxs:h.jsxs,passKeys:!0,passNode:!0});function u(p,c,f){if(p.type==="raw"&&f&&typeof c=="number")return a?f.children.splice(c,1):f.children[c]={type:"text",value:p.value},c;if(p.type==="element"){let d;for(d in zn)if(Object.hasOwn(zn,d)&&Object.hasOwn(p.properties,d)){const g=p.properties[d],k=zn[d];(k===null||k.includes(p.tagName))&&(p.properties[d]=s(String(g||""),d,p))}}if(p.type==="element"){let d=n?!n.includes(p.tagName):o?o.includes(p.tagName):!1;if(!d&&r&&typeof c=="number"&&(d=!r(p,c,f)),d&&f&&typeof c=="number")return l&&p.children?f.children.splice(c,1,...p.children):f.children.splice(c,1),c}}}function ff(e){const t=e.indexOf(":"),n=e.indexOf("?"),r=e.indexOf("#"),i=e.indexOf("/");return t===-1||i!==-1&&t>i||n!==-1&&t>n||r!==-1&&t>r||lf.test(e.slice(0,t))?e:""}function Na(e,t){const n=String(e);if(typeof t!="string")throw new TypeError("Expected character");let r=0,i=n.indexOf(t);for(;i!==-1;)r++,i=n.indexOf(t,i+t.length);return r}function hf(e){if(typeof e!="string")throw new TypeError("Expected a string");return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}function gf(e,t,n){const i=An((n||{}).ignore||[]),o=mf(t);let a=-1;for(;++a0?{type:"text",value:m}:void 0),m===!1?f.lastIndex=_+1:(g!==_&&v.push({type:"text",value:u.value.slice(g,_)}),Array.isArray(m)?v.push(...m):m&&v.push(m),g=_+y[0].length,x=!0),!f.global)break;y=f.exec(u.value)}return x?(g?\]}]+$/.exec(e);if(!t)return[e,void 0];e=e.slice(0,t.index);let n=t[0],r=n.indexOf(")");const i=Na(e,"(");let o=Na(e,")");for(;r!==-1&&i>o;)e+=n.slice(0,r+1),n=n.slice(r+1),r=n.indexOf(")"),o++;return[e,n]}function If(e,t){const n=e.input.charCodeAt(e.index-1);return(e.index===0||kt(n)||En(n))&&!0}Nl.peek=Bf;function jf(){this.buffer()}function Rf(e){this.enter({type:"footnoteReference",identifier:"",label:""},e)}function Of(){this.buffer()}function Df(e){this.enter({type:"footnoteDefinition",identifier:"",label:"",children:[]},e)}function Mf(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=Ke(this.sliceSerialize(e)).toLowerCase(),n.label=t}function Ff(e){this.exit(e)}function zf(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=Ke(this.sliceSerialize(e)).toLowerCase(),n.label=t}function Pf(e){this.exit(e)}function Bf(){return"["}function Nl(e,t,n,r){const i=n.createTracker(r);let o=i.move("[^");const a=n.enter("footnoteReference"),l=n.enter("reference");return o+=i.move(n.safe(n.associationId(e),{after:"]",before:o})),l(),a(),o+=i.move("]"),o}function $f(){return{enter:{gfmFootnoteCallString:jf,gfmFootnoteCall:Rf,gfmFootnoteDefinitionLabelString:Of,gfmFootnoteDefinition:Df},exit:{gfmFootnoteCallString:Mf,gfmFootnoteCall:Ff,gfmFootnoteDefinitionLabelString:zf,gfmFootnoteDefinition:Pf}}}function qf(e){let t=!1;return e&&e.firstLineBlank&&(t=!0),{handlers:{footnoteDefinition:n,footnoteReference:Nl},unsafe:[{character:"[",inConstruct:["label","phrasing","reference"]}]};function n(r,i,o,a){const l=o.createTracker(a);let s=l.move("[^");const u=o.enter("footnoteDefinition"),p=o.enter("label");return s+=l.move(o.safe(o.associationId(r),{before:s,after:"]"})),p(),s+=l.move("]:"),r.children&&r.children.length>0&&(l.shift(4),s+=l.move((t?` -`:" ")+o.indentLines(o.containerFlow(r,l.current()),t?Il:Uf))),u(),s}}function Uf(e,t,n){return t===0?e:Il(e,t,n)}function Il(e,t,n){return(n?"":" ")+e}const Hf=["autolink","destinationLiteral","destinationRaw","reference","titleQuote","titleApostrophe"];jl.peek=Xf;function Wf(){return{canContainEols:["delete"],enter:{strikethrough:Gf},exit:{strikethrough:Zf}}}function Vf(){return{unsafe:[{character:"~",inConstruct:"phrasing",notInConstruct:Hf}],handlers:{delete:jl}}}function Gf(e){this.enter({type:"delete",children:[]},e)}function Zf(e){this.exit(e)}function jl(e,t,n,r){const i=n.createTracker(r),o=n.enter("strikethrough");let a=i.move("~~");return a+=n.containerPhrasing(e,{...i.current(),before:a,after:"~"}),a+=i.move("~~"),o(),a}function Xf(){return"~"}function Kf(e){return e.length}function Yf(e,t){const n=t||{},r=(n.align||[]).concat(),i=n.stringLength||Kf,o=[],a=[],l=[],s=[];let u=0,p=-1;for(;++pu&&(u=e[p].length);++xs[x])&&(s[x]=y)}k.push(v)}a[p]=k,l[p]=S}let c=-1;if(typeof r=="object"&&"length"in r)for(;++cs[c]&&(s[c]=v),d[c]=v),f[c]=y}a.splice(1,0,f),l.splice(1,0,d),p=-1;const g=[];for(;++p"u"||e.call(u,f)},a=function(u,p){n&&p.name==="__proto__"?n(u,p.name,{enumerable:!0,configurable:!0,value:p.newValue,writable:!0}):u[p.name]=p.newValue},l=function(u,p){if(p==="__proto__")if(e.call(u,p)){if(r)return r(u,p).value}else return;return u[p]};return $n=function s(){var u,p,c,f,d,g,k=arguments[0],S=1,x=arguments.length,v=!1;for(typeof k=="boolean"&&(v=k,k=arguments[1]||{},S=2),(k==null||typeof k!="object"&&typeof k!="function")&&(k={});Sa.length;let s;l&&a.push(i);try{s=e.apply(this,a)}catch(u){const p=u;if(l&&n)throw p;return i(p)}l||(s&&s.then&&typeof s.then=="function"?s.then(o,i):s instanceof Error?i(s):o(s))}function i(a,...l){n||(n=!0,t(a,...l))}function o(a){i(null,a)}}const et={basename:qd,dirname:Ud,extname:Hd,join:Wd,sep:"/"};function qd(e,t){if(t!==void 0&&typeof t!="string")throw new TypeError('"ext" argument must be a string');Jt(e);let n=0,r=-1,i=e.length,o;if(t===void 0||t.length===0||t.length>e.length){for(;i--;)if(e.codePointAt(i)===47){if(o){n=i+1;break}}else r<0&&(o=!0,r=i+1);return r<0?"":e.slice(n,r)}if(t===e)return"";let a=-1,l=t.length-1;for(;i--;)if(e.codePointAt(i)===47){if(o){n=i+1;break}}else a<0&&(o=!0,a=i+1),l>-1&&(e.codePointAt(i)===t.codePointAt(l--)?l<0&&(r=i):(l=-1,r=a));return n===r?r=a:r<0&&(r=e.length),e.slice(n,r)}function Ud(e){if(Jt(e),e.length===0)return".";let t=-1,n=e.length,r;for(;--n;)if(e.codePointAt(n)===47){if(r){t=n;break}}else r||(r=!0);return t<0?e.codePointAt(0)===47?"/":".":t===1&&e.codePointAt(0)===47?"//":e.slice(0,t)}function Hd(e){Jt(e);let t=e.length,n=-1,r=0,i=-1,o=0,a;for(;t--;){const l=e.codePointAt(t);if(l===47){if(a){r=t+1;break}continue}n<0&&(a=!0,n=t+1),l===46?i<0?i=t:o!==1&&(o=1):i>-1&&(o=-1)}return i<0||n<0||o===0||o===1&&i===n-1&&i===r+1?"":e.slice(i,n)}function Wd(...e){let t=-1,n;for(;++t0&&e.codePointAt(e.length-1)===47&&(n+="/"),t?"/"+n:n}function Gd(e,t){let n="",r=0,i=-1,o=0,a=-1,l,s;for(;++a<=e.length;){if(a2){if(s=n.lastIndexOf("/"),s!==n.length-1){s<0?(n="",r=0):(n=n.slice(0,s),r=n.length-1-n.lastIndexOf("/")),i=a,o=0;continue}}else if(n.length>0){n="",r=0,i=a,o=0;continue}}t&&(n=n.length>0?n+"/..":"..",r=2)}else n.length>0?n+="/"+e.slice(i+1,a):n=e.slice(i+1,a),r=a-i-1;i=a,o=0}else l===46&&o>-1?o++:o=-1}return n}function Jt(e){if(typeof e!="string")throw new TypeError("Path must be a string. Received "+JSON.stringify(e))}const Zd={cwd:Xd};function Xd(){return"/"}function di(e){return!!(e!==null&&typeof e=="object"&&"href"in e&&e.href&&"protocol"in e&&e.protocol&&e.auth===void 0)}function Kd(e){if(typeof e=="string")e=new URL(e);else if(!di(e)){const t=new TypeError('The "path" argument must be of type string or an instance of URL. Received `'+e+"`");throw t.code="ERR_INVALID_ARG_TYPE",t}if(e.protocol!=="file:"){const t=new TypeError("The URL must be of scheme file");throw t.code="ERR_INVALID_URL_SCHEME",t}return Yd(e)}function Yd(e){if(e.hostname!==""){const r=new TypeError('File URL host must be "localhost" or empty on darwin');throw r.code="ERR_INVALID_FILE_URL_HOST",r}const t=e.pathname;let n=-1;for(;++n0){let[d,...g]=p;const k=r[f][1];pi(k)&&pi(d)&&(d=qn(!0,k,d)),r[f]=[u,d,...g]}}}}const tf=new Mi().freeze();function Vn(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `parser`")}function Gn(e,t){if(typeof t!="function")throw new TypeError("Cannot `"+e+"` without `compiler`")}function Zn(e,t){if(t)throw new Error("Cannot call `"+e+"` on a frozen processor.\nCreate a new processor first, by calling it: use `processor()` instead of `processor`.")}function Ca(e){if(!pi(e)||typeof e.type!="string")throw new TypeError("Expected node, got `"+e+"`")}function Ta(e,t,n){if(!n)throw new Error("`"+e+"` finished async. Use `"+t+"` instead")}function un(e){return nf(e)?e:new Ll(e)}function nf(e){return!!(e&&typeof e=="object"&&"message"in e&&"messages"in e)}function rf(e){return typeof e=="string"||af(e)}function af(e){return!!(e&&typeof e=="object"&&"byteLength"in e&&"byteOffset"in e)}const of="https://github.com/remarkjs/react-markdown/blob/main/changelog.md",Aa=[],La={allowDangerousHtml:!0},lf=/^(https?|ircs?|mailto|xmpp)$/i,sf=[{from:"astPlugins",id:"remove-buggy-html-in-markdown-parser"},{from:"allowDangerousHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"allowNode",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowElement"},{from:"allowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"allowedElements"},{from:"className",id:"remove-classname"},{from:"disallowedTypes",id:"replace-allownode-allowedtypes-and-disallowedtypes",to:"disallowedElements"},{from:"escapeHtml",id:"remove-buggy-html-in-markdown-parser"},{from:"includeElementIndex",id:"#remove-includeelementindex"},{from:"includeNodeIndex",id:"change-includenodeindex-to-includeelementindex"},{from:"linkTarget",id:"remove-linktarget"},{from:"plugins",id:"change-plugins-to-remarkplugins",to:"remarkPlugins"},{from:"rawSourcePos",id:"#remove-rawsourcepos"},{from:"renderers",id:"change-renderers-to-components",to:"components"},{from:"source",id:"change-source-to-children",to:"children"},{from:"sourcePos",id:"#remove-sourcepos"},{from:"transformImageUri",id:"#add-urltransform",to:"urlTransform"},{from:"transformLinkUri",id:"#add-urltransform",to:"urlTransform"}];function uf(e){const t=cf(e),n=pf(e);return df(t.runSync(t.parse(n),n),e)}function cf(e){const t=e.rehypePlugins||Aa,n=e.remarkPlugins||Aa,r=e.remarkRehypeOptions?{...e.remarkRehypeOptions,...La}:La;return tf().use(Up).use(n).use(Fd,r).use(t)}function pf(e){const t=e.children||"",n=new Ll;return typeof t=="string"&&(n.value=t),n}function df(e,t){const n=t.allowedElements,r=t.allowElement,i=t.components,o=t.disallowedElements,a=t.skipHtml,l=t.unwrapDisallowed,s=t.urlTransform||ff;for(const p of sf)Object.hasOwn(t,p.from)&&(""+p.from+(p.to?"use `"+p.to+"` instead":"remove it")+of+p.id,void 0);return Di(e,u),Cu(e,{Fragment:h.Fragment,components:i,ignoreInvalidStyle:!0,jsx:h.jsx,jsxs:h.jsxs,passKeys:!0,passNode:!0});function u(p,c,f){if(p.type==="raw"&&f&&typeof c=="number")return a?f.children.splice(c,1):f.children[c]={type:"text",value:p.value},c;if(p.type==="element"){let d;for(d in zn)if(Object.hasOwn(zn,d)&&Object.hasOwn(p.properties,d)){const g=p.properties[d],k=zn[d];(k===null||k.includes(p.tagName))&&(p.properties[d]=s(String(g||""),d,p))}}if(p.type==="element"){let d=n?!n.includes(p.tagName):o?o.includes(p.tagName):!1;if(!d&&r&&typeof c=="number"&&(d=!r(p,c,f)),d&&f&&typeof c=="number")return l&&p.children?f.children.splice(c,1,...p.children):f.children.splice(c,1),c}}}function ff(e){const t=e.indexOf(":"),n=e.indexOf("?"),r=e.indexOf("#"),i=e.indexOf("/");return t===-1||i!==-1&&t>i||n!==-1&&t>n||r!==-1&&t>r||lf.test(e.slice(0,t))?e:""}function Na(e,t){const n=String(e);if(typeof t!="string")throw new TypeError("Expected character");let r=0,i=n.indexOf(t);for(;i!==-1;)r++,i=n.indexOf(t,i+t.length);return r}function hf(e){if(typeof e!="string")throw new TypeError("Expected a string");return e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d")}function gf(e,t,n){const i=An((n||{}).ignore||[]),o=mf(t);let a=-1;for(;++a0?{type:"text",value:m}:void 0),m===!1?f.lastIndex=_+1:(g!==_&&v.push({type:"text",value:u.value.slice(g,_)}),Array.isArray(m)?v.push(...m):m&&v.push(m),g=_+b[0].length,x=!0),!f.global)break;b=f.exec(u.value)}return x?(g?\]}]+$/.exec(e);if(!t)return[e,void 0];e=e.slice(0,t.index);let n=t[0],r=n.indexOf(")");const i=Na(e,"(");let o=Na(e,")");for(;r!==-1&&i>o;)e+=n.slice(0,r+1),n=n.slice(r+1),r=n.indexOf(")"),o++;return[e,n]}function If(e,t){const n=e.input.charCodeAt(e.index-1);return(e.index===0||kt(n)||En(n))&&!0}Nl.peek=Bf;function jf(){this.buffer()}function Rf(e){this.enter({type:"footnoteReference",identifier:"",label:""},e)}function Of(){this.buffer()}function Df(e){this.enter({type:"footnoteDefinition",identifier:"",label:"",children:[]},e)}function Mf(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=Ke(this.sliceSerialize(e)).toLowerCase(),n.label=t}function Ff(e){this.exit(e)}function zf(e){const t=this.resume(),n=this.stack[this.stack.length-1];n.type,n.identifier=Ke(this.sliceSerialize(e)).toLowerCase(),n.label=t}function Pf(e){this.exit(e)}function Bf(){return"["}function Nl(e,t,n,r){const i=n.createTracker(r);let o=i.move("[^");const a=n.enter("footnoteReference"),l=n.enter("reference");return o+=i.move(n.safe(n.associationId(e),{after:"]",before:o})),l(),a(),o+=i.move("]"),o}function $f(){return{enter:{gfmFootnoteCallString:jf,gfmFootnoteCall:Rf,gfmFootnoteDefinitionLabelString:Of,gfmFootnoteDefinition:Df},exit:{gfmFootnoteCallString:Mf,gfmFootnoteCall:Ff,gfmFootnoteDefinitionLabelString:zf,gfmFootnoteDefinition:Pf}}}function qf(e){let t=!1;return e&&e.firstLineBlank&&(t=!0),{handlers:{footnoteDefinition:n,footnoteReference:Nl},unsafe:[{character:"[",inConstruct:["label","phrasing","reference"]}]};function n(r,i,o,a){const l=o.createTracker(a);let s=l.move("[^");const u=o.enter("footnoteDefinition"),p=o.enter("label");return s+=l.move(o.safe(o.associationId(r),{before:s,after:"]"})),p(),s+=l.move("]:"),r.children&&r.children.length>0&&(l.shift(4),s+=l.move((t?` +`:" ")+o.indentLines(o.containerFlow(r,l.current()),t?Il:Uf))),u(),s}}function Uf(e,t,n){return t===0?e:Il(e,t,n)}function Il(e,t,n){return(n?"":" ")+e}const Hf=["autolink","destinationLiteral","destinationRaw","reference","titleQuote","titleApostrophe"];jl.peek=Xf;function Wf(){return{canContainEols:["delete"],enter:{strikethrough:Gf},exit:{strikethrough:Zf}}}function Vf(){return{unsafe:[{character:"~",inConstruct:"phrasing",notInConstruct:Hf}],handlers:{delete:jl}}}function Gf(e){this.enter({type:"delete",children:[]},e)}function Zf(e){this.exit(e)}function jl(e,t,n,r){const i=n.createTracker(r),o=n.enter("strikethrough");let a=i.move("~~");return a+=n.containerPhrasing(e,{...i.current(),before:a,after:"~"}),a+=i.move("~~"),o(),a}function Xf(){return"~"}function Kf(e){return e.length}function Yf(e,t){const n=t||{},r=(n.align||[]).concat(),i=n.stringLength||Kf,o=[],a=[],l=[],s=[];let u=0,p=-1;for(;++pu&&(u=e[p].length);++xs[x])&&(s[x]=b)}k.push(v)}a[p]=k,l[p]=S}let c=-1;if(typeof r=="object"&&"length"in r)for(;++cs[c]&&(s[c]=v),d[c]=v),f[c]=b}a.splice(1,0,f),l.splice(1,0,d),p=-1;const g=[];for(;++p "),o.shift(2);const a=n.indentLines(n.containerFlow(e,o.current()),eh);return i(),a}function eh(e,t,n){return">"+(n?"":" ")+e}function th(e,t){return ja(e,t.inConstruct,!0)&&!ja(e,t.notInConstruct,!1)}function ja(e,t,n){if(typeof t=="string"&&(t=[t]),!t||t.length===0)return n;let r=-1;for(;++ra&&(a=o):o=1,i=r+t.length,r=n.indexOf(t,i);return a}function rh(e,t){return!!(t.options.fences===!1&&e.value&&!e.lang&&/[^ \r\n]/.test(e.value)&&!/^[\t ]*(?:[\r\n]|$)|(?:^|[\r\n])[\t ]*$/.test(e.value))}function ih(e){const t=e.options.fence||"`";if(t!=="`"&&t!=="~")throw new Error("Cannot serialize code with `"+t+"` for `options.fence`, expected `` ` `` or `~`");return t}function ah(e,t,n,r){const i=ih(n),o=e.value||"",a=i==="`"?"GraveAccent":"Tilde";if(rh(e,n)){const c=n.enter("codeIndented"),f=n.indentLines(o,oh);return c(),f}const l=n.createTracker(r),s=i.repeat(Math.max(nh(o,i)+1,3)),u=n.enter("codeFenced");let p=l.move(s);if(e.lang){const c=n.enter(`codeFencedLang${a}`);p+=l.move(n.safe(e.lang,{before:p,after:" ",encode:["`"],...l.current()})),c()}if(e.lang&&e.meta){const c=n.enter(`codeFencedMeta${a}`);p+=l.move(" "),p+=l.move(n.safe(e.meta,{before:p,after:` @@ -24,16 +24,16 @@ import{g as me,j as h,R as it,c as mn,u as Ye,a as Ft,b as Zo,r as N,d as Gs,e a `});return c(),p(),f+` `+(i===1?"=":"-").repeat(f.length-(Math.max(f.lastIndexOf("\r"),f.lastIndexOf(` `))+1))}const a="#".repeat(i),l=n.enter("headingAtx"),s=n.enter("phrasing");o.move(a+" ");let u=n.containerPhrasing(e,{before:"# ",after:` -`,...o.current()});return/^[\t ]/.test(u)&&(u=Zt(u.charCodeAt(0))+u.slice(1)),u=u?a+" "+u:a,n.options.closeAtx&&(u+=" "+a),s(),l(),u}Ol.peek=dh;function Ol(e){return e.value||""}function dh(){return"<"}Dl.peek=fh;function Dl(e,t,n,r){const i=Fi(n),o=i==='"'?"Quote":"Apostrophe",a=n.enter("image");let l=n.enter("label");const s=n.createTracker(r);let u=s.move("![");return u+=s.move(n.safe(e.alt,{before:u,after:"]",...s.current()})),u+=s.move("]("),l(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(l=n.enter("destinationLiteral"),u+=s.move("<"),u+=s.move(n.safe(e.url,{before:u,after:">",...s.current()})),u+=s.move(">")):(l=n.enter("destinationRaw"),u+=s.move(n.safe(e.url,{before:u,after:e.title?" ":")",...s.current()}))),l(),e.title&&(l=n.enter(`title${o}`),u+=s.move(" "+i),u+=s.move(n.safe(e.title,{before:u,after:i,...s.current()})),u+=s.move(i),l()),u+=s.move(")"),a(),u}function fh(){return"!"}Ml.peek=hh;function Ml(e,t,n,r){const i=e.referenceType,o=n.enter("imageReference");let a=n.enter("label");const l=n.createTracker(r);let s=l.move("![");const u=n.safe(e.alt,{before:s,after:"]",...l.current()});s+=l.move(u+"]["),a();const p=n.stack;n.stack=[],a=n.enter("reference");const c=n.safe(n.associationId(e),{before:s,after:"]",...l.current()});return a(),n.stack=p,o(),i==="full"||!u||u!==c?s+=l.move(c+"]"):i==="shortcut"?s=s.slice(0,-1):s+=l.move("]"),s}function hh(){return"!"}Fl.peek=gh;function Fl(e,t,n){let r=e.value||"",i="`",o=-1;for(;new RegExp("(^|[^`])"+i+"([^`]|$)").test(r);)i+="`";for(/[^ \r\n]/.test(r)&&(/^[ \r\n]/.test(r)&&/[ \r\n]$/.test(r)||/^`|`$/.test(r))&&(r=" "+r+" ");++o\u007F]/.test(e.url))}Pl.peek=mh;function Pl(e,t,n,r){const i=Fi(n),o=i==='"'?"Quote":"Apostrophe",a=n.createTracker(r);let l,s;if(zl(e,n)){const p=n.stack;n.stack=[],l=n.enter("autolink");let c=a.move("<");return c+=a.move(n.containerPhrasing(e,{before:c,after:">",...a.current()})),c+=a.move(">"),l(),n.stack=p,c}l=n.enter("link"),s=n.enter("label");let u=a.move("[");return u+=a.move(n.containerPhrasing(e,{before:u,after:"](",...a.current()})),u+=a.move("]("),s(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(s=n.enter("destinationLiteral"),u+=a.move("<"),u+=a.move(n.safe(e.url,{before:u,after:">",...a.current()})),u+=a.move(">")):(s=n.enter("destinationRaw"),u+=a.move(n.safe(e.url,{before:u,after:e.title?" ":")",...a.current()}))),s(),e.title&&(s=n.enter(`title${o}`),u+=a.move(" "+i),u+=a.move(n.safe(e.title,{before:u,after:i,...a.current()})),u+=a.move(i),s()),u+=a.move(")"),l(),u}function mh(e,t,n){return zl(e,n)?"<":"["}Bl.peek=yh;function Bl(e,t,n,r){const i=e.referenceType,o=n.enter("linkReference");let a=n.enter("label");const l=n.createTracker(r);let s=l.move("[");const u=n.containerPhrasing(e,{before:s,after:"]",...l.current()});s+=l.move(u+"]["),a();const p=n.stack;n.stack=[],a=n.enter("reference");const c=n.safe(n.associationId(e),{before:s,after:"]",...l.current()});return a(),n.stack=p,o(),i==="full"||!u||u!==c?s+=l.move(c+"]"):i==="shortcut"?s=s.slice(0,-1):s+=l.move("]"),s}function yh(){return"["}function zi(e){const t=e.options.bullet||"*";if(t!=="*"&&t!=="+"&&t!=="-")throw new Error("Cannot serialize items with `"+t+"` for `options.bullet`, expected `*`, `+`, or `-`");return t}function bh(e){const t=zi(e),n=e.options.bulletOther;if(!n)return t==="*"?"-":"*";if(n!=="*"&&n!=="+"&&n!=="-")throw new Error("Cannot serialize items with `"+n+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(n===t)throw new Error("Expected `bullet` (`"+t+"`) and `bulletOther` (`"+n+"`) to be different");return n}function xh(e){const t=e.options.bulletOrdered||".";if(t!=="."&&t!==")")throw new Error("Cannot serialize items with `"+t+"` for `options.bulletOrdered`, expected `.` or `)`");return t}function $l(e){const t=e.options.rule||"*";if(t!=="*"&&t!=="-"&&t!=="_")throw new Error("Cannot serialize rules with `"+t+"` for `options.rule`, expected `*`, `-`, or `_`");return t}function kh(e,t,n,r){const i=n.enter("list"),o=n.bulletCurrent;let a=e.ordered?xh(n):zi(n);const l=e.ordered?a==="."?")":".":bh(n);let s=t&&n.bulletLastUsed?a===n.bulletLastUsed:!1;if(!e.ordered){const p=e.children?e.children[0]:void 0;if((a==="*"||a==="-")&&p&&(!p.children||!p.children[0])&&n.stack[n.stack.length-1]==="list"&&n.stack[n.stack.length-2]==="listItem"&&n.stack[n.stack.length-3]==="list"&&n.stack[n.stack.length-4]==="listItem"&&n.indexStack[n.indexStack.length-1]===0&&n.indexStack[n.indexStack.length-2]===0&&n.indexStack[n.indexStack.length-3]===0&&(s=!0),$l(n)===a&&p){let c=-1;for(;++c-1?t.start:1)+(n.options.incrementListMarker===!1?0:t.children.indexOf(e))+o);let a=o.length+1;(i==="tab"||i==="mixed"&&(t&&t.type==="list"&&t.spread||e.spread))&&(a=Math.ceil(a/4)*4);const l=n.createTracker(r);l.move(o+" ".repeat(a-o.length)),l.shift(a);const s=n.enter("listItem"),u=n.indentLines(n.containerFlow(e,l.current()),p);return s(),u;function p(c,f,d){return f?(d?"":" ".repeat(a))+c:(d?o:o+" ".repeat(a-o.length))+c}}function Sh(e,t,n,r){const i=n.enter("paragraph"),o=n.enter("phrasing"),a=n.containerPhrasing(e,r);return o(),i(),a}const _h=An(["break","delete","emphasis","footnote","footnoteReference","image","imageReference","inlineCode","inlineMath","link","linkReference","mdxJsxTextElement","mdxTextExpression","strong","text","textDirective"]);function Eh(e,t,n,r){return(e.children.some(function(a){return _h(a)})?n.containerPhrasing:n.containerFlow).call(n,e,r)}function Ch(e){const t=e.options.strong||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize strong with `"+t+"` for `options.strong`, expected `*`, or `_`");return t}ql.peek=Th;function ql(e,t,n,r){const i=Ch(n),o=n.enter("strong"),a=n.createTracker(r),l=a.move(i+i);let s=a.move(n.containerPhrasing(e,{after:i,before:l,...a.current()}));const u=s.charCodeAt(0),p=kn(r.before.charCodeAt(r.before.length-1),u,i);p.inside&&(s=Zt(u)+s.slice(1));const c=s.charCodeAt(s.length-1),f=kn(r.after.charCodeAt(0),c,i);f.inside&&(s=s.slice(0,-1)+Zt(c));const d=a.move(i+i);return o(),n.attentionEncodeSurroundingInfo={after:f.outside,before:p.outside},l+s+d}function Th(e,t,n){return n.options.strong||"*"}function Ah(e,t,n,r){return n.safe(e.value,r)}function Lh(e){const t=e.options.ruleRepetition||3;if(t<3)throw new Error("Cannot serialize rules with repetition `"+t+"` for `options.ruleRepetition`, expected `3` or more");return t}function Nh(e,t,n){const r=($l(n)+(n.options.ruleSpaces?" ":"")).repeat(Lh(n));return n.options.ruleSpaces?r.slice(0,-1):r}const Ul={blockquote:Jf,break:Ra,code:ah,definition:lh,emphasis:Rl,hardBreak:Ra,heading:ph,html:Ol,image:Dl,imageReference:Ml,inlineCode:Fl,link:Pl,linkReference:Bl,list:kh,listItem:wh,paragraph:Sh,root:Eh,strong:ql,text:Ah,thematicBreak:Nh};function Ih(){return{enter:{table:jh,tableData:Oa,tableHeader:Oa,tableRow:Oh},exit:{codeText:Dh,table:Rh,tableData:Qn,tableHeader:Qn,tableRow:Qn}}}function jh(e){const t=e._align;this.enter({type:"table",align:t.map(function(n){return n==="none"?null:n}),children:[]},e),this.data.inTable=!0}function Rh(e){this.exit(e),this.data.inTable=void 0}function Oh(e){this.enter({type:"tableRow",children:[]},e)}function Qn(e){this.exit(e)}function Oa(e){this.enter({type:"tableCell",children:[]},e)}function Dh(e){let t=this.resume();this.data.inTable&&(t=t.replace(/\\([\\|])/g,Mh));const n=this.stack[this.stack.length-1];n.type,n.value=t,this.exit(e)}function Mh(e,t){return t==="|"?t:e}function Fh(e){const t=e||{},n=t.tableCellPadding,r=t.tablePipeAlign,i=t.stringLength,o=n?" ":"|";return{unsafe:[{character:"\r",inConstruct:"tableCell"},{character:` +`,...o.current()});return/^[\t ]/.test(u)&&(u=Zt(u.charCodeAt(0))+u.slice(1)),u=u?a+" "+u:a,n.options.closeAtx&&(u+=" "+a),s(),l(),u}Ol.peek=dh;function Ol(e){return e.value||""}function dh(){return"<"}Dl.peek=fh;function Dl(e,t,n,r){const i=Fi(n),o=i==='"'?"Quote":"Apostrophe",a=n.enter("image");let l=n.enter("label");const s=n.createTracker(r);let u=s.move("![");return u+=s.move(n.safe(e.alt,{before:u,after:"]",...s.current()})),u+=s.move("]("),l(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(l=n.enter("destinationLiteral"),u+=s.move("<"),u+=s.move(n.safe(e.url,{before:u,after:">",...s.current()})),u+=s.move(">")):(l=n.enter("destinationRaw"),u+=s.move(n.safe(e.url,{before:u,after:e.title?" ":")",...s.current()}))),l(),e.title&&(l=n.enter(`title${o}`),u+=s.move(" "+i),u+=s.move(n.safe(e.title,{before:u,after:i,...s.current()})),u+=s.move(i),l()),u+=s.move(")"),a(),u}function fh(){return"!"}Ml.peek=hh;function Ml(e,t,n,r){const i=e.referenceType,o=n.enter("imageReference");let a=n.enter("label");const l=n.createTracker(r);let s=l.move("![");const u=n.safe(e.alt,{before:s,after:"]",...l.current()});s+=l.move(u+"]["),a();const p=n.stack;n.stack=[],a=n.enter("reference");const c=n.safe(n.associationId(e),{before:s,after:"]",...l.current()});return a(),n.stack=p,o(),i==="full"||!u||u!==c?s+=l.move(c+"]"):i==="shortcut"?s=s.slice(0,-1):s+=l.move("]"),s}function hh(){return"!"}Fl.peek=gh;function Fl(e,t,n){let r=e.value||"",i="`",o=-1;for(;new RegExp("(^|[^`])"+i+"([^`]|$)").test(r);)i+="`";for(/[^ \r\n]/.test(r)&&(/^[ \r\n]/.test(r)&&/[ \r\n]$/.test(r)||/^`|`$/.test(r))&&(r=" "+r+" ");++o\u007F]/.test(e.url))}Pl.peek=mh;function Pl(e,t,n,r){const i=Fi(n),o=i==='"'?"Quote":"Apostrophe",a=n.createTracker(r);let l,s;if(zl(e,n)){const p=n.stack;n.stack=[],l=n.enter("autolink");let c=a.move("<");return c+=a.move(n.containerPhrasing(e,{before:c,after:">",...a.current()})),c+=a.move(">"),l(),n.stack=p,c}l=n.enter("link"),s=n.enter("label");let u=a.move("[");return u+=a.move(n.containerPhrasing(e,{before:u,after:"](",...a.current()})),u+=a.move("]("),s(),!e.url&&e.title||/[\0- \u007F]/.test(e.url)?(s=n.enter("destinationLiteral"),u+=a.move("<"),u+=a.move(n.safe(e.url,{before:u,after:">",...a.current()})),u+=a.move(">")):(s=n.enter("destinationRaw"),u+=a.move(n.safe(e.url,{before:u,after:e.title?" ":")",...a.current()}))),s(),e.title&&(s=n.enter(`title${o}`),u+=a.move(" "+i),u+=a.move(n.safe(e.title,{before:u,after:i,...a.current()})),u+=a.move(i),s()),u+=a.move(")"),l(),u}function mh(e,t,n){return zl(e,n)?"<":"["}Bl.peek=bh;function Bl(e,t,n,r){const i=e.referenceType,o=n.enter("linkReference");let a=n.enter("label");const l=n.createTracker(r);let s=l.move("[");const u=n.containerPhrasing(e,{before:s,after:"]",...l.current()});s+=l.move(u+"]["),a();const p=n.stack;n.stack=[],a=n.enter("reference");const c=n.safe(n.associationId(e),{before:s,after:"]",...l.current()});return a(),n.stack=p,o(),i==="full"||!u||u!==c?s+=l.move(c+"]"):i==="shortcut"?s=s.slice(0,-1):s+=l.move("]"),s}function bh(){return"["}function zi(e){const t=e.options.bullet||"*";if(t!=="*"&&t!=="+"&&t!=="-")throw new Error("Cannot serialize items with `"+t+"` for `options.bullet`, expected `*`, `+`, or `-`");return t}function yh(e){const t=zi(e),n=e.options.bulletOther;if(!n)return t==="*"?"-":"*";if(n!=="*"&&n!=="+"&&n!=="-")throw new Error("Cannot serialize items with `"+n+"` for `options.bulletOther`, expected `*`, `+`, or `-`");if(n===t)throw new Error("Expected `bullet` (`"+t+"`) and `bulletOther` (`"+n+"`) to be different");return n}function xh(e){const t=e.options.bulletOrdered||".";if(t!=="."&&t!==")")throw new Error("Cannot serialize items with `"+t+"` for `options.bulletOrdered`, expected `.` or `)`");return t}function $l(e){const t=e.options.rule||"*";if(t!=="*"&&t!=="-"&&t!=="_")throw new Error("Cannot serialize rules with `"+t+"` for `options.rule`, expected `*`, `-`, or `_`");return t}function kh(e,t,n,r){const i=n.enter("list"),o=n.bulletCurrent;let a=e.ordered?xh(n):zi(n);const l=e.ordered?a==="."?")":".":yh(n);let s=t&&n.bulletLastUsed?a===n.bulletLastUsed:!1;if(!e.ordered){const p=e.children?e.children[0]:void 0;if((a==="*"||a==="-")&&p&&(!p.children||!p.children[0])&&n.stack[n.stack.length-1]==="list"&&n.stack[n.stack.length-2]==="listItem"&&n.stack[n.stack.length-3]==="list"&&n.stack[n.stack.length-4]==="listItem"&&n.indexStack[n.indexStack.length-1]===0&&n.indexStack[n.indexStack.length-2]===0&&n.indexStack[n.indexStack.length-3]===0&&(s=!0),$l(n)===a&&p){let c=-1;for(;++c-1?t.start:1)+(n.options.incrementListMarker===!1?0:t.children.indexOf(e))+o);let a=o.length+1;(i==="tab"||i==="mixed"&&(t&&t.type==="list"&&t.spread||e.spread))&&(a=Math.ceil(a/4)*4);const l=n.createTracker(r);l.move(o+" ".repeat(a-o.length)),l.shift(a);const s=n.enter("listItem"),u=n.indentLines(n.containerFlow(e,l.current()),p);return s(),u;function p(c,f,d){return f?(d?"":" ".repeat(a))+c:(d?o:o+" ".repeat(a-o.length))+c}}function Sh(e,t,n,r){const i=n.enter("paragraph"),o=n.enter("phrasing"),a=n.containerPhrasing(e,r);return o(),i(),a}const _h=An(["break","delete","emphasis","footnote","footnoteReference","image","imageReference","inlineCode","inlineMath","link","linkReference","mdxJsxTextElement","mdxTextExpression","strong","text","textDirective"]);function Eh(e,t,n,r){return(e.children.some(function(a){return _h(a)})?n.containerPhrasing:n.containerFlow).call(n,e,r)}function Ch(e){const t=e.options.strong||"*";if(t!=="*"&&t!=="_")throw new Error("Cannot serialize strong with `"+t+"` for `options.strong`, expected `*`, or `_`");return t}ql.peek=Th;function ql(e,t,n,r){const i=Ch(n),o=n.enter("strong"),a=n.createTracker(r),l=a.move(i+i);let s=a.move(n.containerPhrasing(e,{after:i,before:l,...a.current()}));const u=s.charCodeAt(0),p=kn(r.before.charCodeAt(r.before.length-1),u,i);p.inside&&(s=Zt(u)+s.slice(1));const c=s.charCodeAt(s.length-1),f=kn(r.after.charCodeAt(0),c,i);f.inside&&(s=s.slice(0,-1)+Zt(c));const d=a.move(i+i);return o(),n.attentionEncodeSurroundingInfo={after:f.outside,before:p.outside},l+s+d}function Th(e,t,n){return n.options.strong||"*"}function Ah(e,t,n,r){return n.safe(e.value,r)}function Lh(e){const t=e.options.ruleRepetition||3;if(t<3)throw new Error("Cannot serialize rules with repetition `"+t+"` for `options.ruleRepetition`, expected `3` or more");return t}function Nh(e,t,n){const r=($l(n)+(n.options.ruleSpaces?" ":"")).repeat(Lh(n));return n.options.ruleSpaces?r.slice(0,-1):r}const Ul={blockquote:Jf,break:Ra,code:ah,definition:lh,emphasis:Rl,hardBreak:Ra,heading:ph,html:Ol,image:Dl,imageReference:Ml,inlineCode:Fl,link:Pl,linkReference:Bl,list:kh,listItem:wh,paragraph:Sh,root:Eh,strong:ql,text:Ah,thematicBreak:Nh};function Ih(){return{enter:{table:jh,tableData:Oa,tableHeader:Oa,tableRow:Oh},exit:{codeText:Dh,table:Rh,tableData:Qn,tableHeader:Qn,tableRow:Qn}}}function jh(e){const t=e._align;this.enter({type:"table",align:t.map(function(n){return n==="none"?null:n}),children:[]},e),this.data.inTable=!0}function Rh(e){this.exit(e),this.data.inTable=void 0}function Oh(e){this.enter({type:"tableRow",children:[]},e)}function Qn(e){this.exit(e)}function Oa(e){this.enter({type:"tableCell",children:[]},e)}function Dh(e){let t=this.resume();this.data.inTable&&(t=t.replace(/\\([\\|])/g,Mh));const n=this.stack[this.stack.length-1];n.type,n.value=t,this.exit(e)}function Mh(e,t){return t==="|"?t:e}function Fh(e){const t=e||{},n=t.tableCellPadding,r=t.tablePipeAlign,i=t.stringLength,o=n?" ":"|";return{unsafe:[{character:"\r",inConstruct:"tableCell"},{character:` `,inConstruct:"tableCell"},{atBreak:!0,character:"|",after:"[ :-]"},{character:"|",inConstruct:"tableCell"},{atBreak:!0,character:":",after:"-"},{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{inlineCode:f,table:a,tableCell:s,tableRow:l}};function a(d,g,k,S){return u(p(d,k,S),d.align)}function l(d,g,k,S){const x=c(d,k,S),v=u([x]);return v.slice(0,v.indexOf(` -`))}function s(d,g,k,S){const x=k.enter("tableCell"),v=k.enter("phrasing"),y=k.containerPhrasing(d,{...S,before:o,after:o});return v(),x(),y}function u(d,g){return Yf(d,{align:g,alignDelimiters:r,padding:n,stringLength:i})}function p(d,g,k){const S=d.children;let x=-1;const v=[],y=g.enter("table");for(;++x0&&!n&&(e[e.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),n}const tg={tokenize:ug,partial:!0};function ng(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:og,continuation:{tokenize:lg},exit:sg}},text:{91:{name:"gfmFootnoteCall",tokenize:ag},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:rg,resolveTo:ig}}}}function rg(e,t,n){const r=this;let i=r.events.length;const o=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let a;for(;i--;){const s=r.events[i][1];if(s.type==="labelImage"){a=s;break}if(s.type==="gfmFootnoteCall"||s.type==="labelLink"||s.type==="label"||s.type==="image"||s.type==="link")break}return l;function l(s){if(!a||!a._balanced)return n(s);const u=Ke(r.sliceSerialize({start:a.end,end:r.now()}));return u.codePointAt(0)!==94||!o.includes(u.slice(1))?n(s):(e.enter("gfmFootnoteCallLabelMarker"),e.consume(s),e.exit("gfmFootnoteCallLabelMarker"),t(s))}}function ig(e,t){let n=e.length;for(;n--;)if(e[n][1].type==="labelImage"&&e[n][0]==="enter"){e[n][1];break}e[n+1][1].type="data",e[n+3][1].type="gfmFootnoteCallLabelMarker";const r={type:"gfmFootnoteCall",start:Object.assign({},e[n+3][1].start),end:Object.assign({},e[e.length-1][1].end)},i={type:"gfmFootnoteCallMarker",start:Object.assign({},e[n+3][1].end),end:Object.assign({},e[n+3][1].end)};i.end.column++,i.end.offset++,i.end._bufferIndex++;const o={type:"gfmFootnoteCallString",start:Object.assign({},i.end),end:Object.assign({},e[e.length-1][1].start)},a={type:"chunkString",contentType:"string",start:Object.assign({},o.start),end:Object.assign({},o.end)},l=[e[n+1],e[n+2],["enter",r,t],e[n+3],e[n+4],["enter",i,t],["exit",i,t],["enter",o,t],["enter",a,t],["exit",a,t],["exit",o,t],e[e.length-2],e[e.length-1],["exit",r,t]];return e.splice(n,e.length-n+1,...l),e}function ag(e,t,n){const r=this,i=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let o=0,a;return l;function l(c){return e.enter("gfmFootnoteCall"),e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),s}function s(c){return c!==94?n(c):(e.enter("gfmFootnoteCallMarker"),e.consume(c),e.exit("gfmFootnoteCallMarker"),e.enter("gfmFootnoteCallString"),e.enter("chunkString").contentType="string",u)}function u(c){if(o>999||c===93&&!a||c===null||c===91||he(c))return n(c);if(c===93){e.exit("chunkString");const f=e.exit("gfmFootnoteCallString");return i.includes(Ke(r.sliceSerialize(f)))?(e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),e.exit("gfmFootnoteCall"),t):n(c)}return he(c)||(a=!0),o++,e.consume(c),c===92?p:u}function p(c){return c===91||c===92||c===93?(e.consume(c),o++,u):u(c)}}function og(e,t,n){const r=this,i=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let o,a=0,l;return s;function s(g){return e.enter("gfmFootnoteDefinition")._container=!0,e.enter("gfmFootnoteDefinitionLabel"),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionLabelMarker"),u}function u(g){return g===94?(e.enter("gfmFootnoteDefinitionMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionMarker"),e.enter("gfmFootnoteDefinitionLabelString"),e.enter("chunkString").contentType="string",p):n(g)}function p(g){if(a>999||g===93&&!l||g===null||g===91||he(g))return n(g);if(g===93){e.exit("chunkString");const k=e.exit("gfmFootnoteDefinitionLabelString");return o=Ke(r.sliceSerialize(k)),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionLabelMarker"),e.exit("gfmFootnoteDefinitionLabel"),f}return he(g)||(l=!0),a++,e.consume(g),g===92?c:p}function c(g){return g===91||g===92||g===93?(e.consume(g),a++,p):p(g)}function f(g){return g===58?(e.enter("definitionMarker"),e.consume(g),e.exit("definitionMarker"),i.includes(o)||i.push(o),oe(e,d,"gfmFootnoteDefinitionWhitespace")):n(g)}function d(g){return t(g)}}function lg(e,t,n){return e.check(Qt,t,e.attempt(tg,t,n))}function sg(e){e.exit("gfmFootnoteDefinition")}function ug(e,t,n){const r=this;return oe(e,i,"gfmFootnoteDefinitionIndent",5);function i(o){const a=r.events[r.events.length-1];return a&&a[1].type==="gfmFootnoteDefinitionIndent"&&a[2].sliceSerialize(a[1],!0).length===4?t(o):n(o)}}function cg(e){let n=(e||{}).singleTilde;const r={name:"strikethrough",tokenize:o,resolveAll:i};return n==null&&(n=!0),{text:{126:r},insideSpan:{null:[r]},attentionMarkers:{null:[126]}};function i(a,l){let s=-1;for(;++s1?s(g):(a.consume(g),c++,d);if(c<2&&!n)return s(g);const S=a.exit("strikethroughSequenceTemporary"),x=jt(g);return S._open=!x||x===2&&!!k,S._close=!k||k===2&&!!x,l(g)}}}class pg{constructor(){this.map=[]}add(t,n,r){dg(this,t,n,r)}consume(t){if(this.map.sort(function(o,a){return o[0]-a[0]}),this.map.length===0)return;let n=this.map.length;const r=[];for(;n>0;)n-=1,r.push(t.slice(this.map[n][0]+this.map[n][1]),this.map[n][2]),t.length=this.map[n][0];r.push(t.slice()),t.length=0;let i=r.pop();for(;i;){for(const o of i)t.push(o);i=r.pop()}this.map.length=0}}function dg(e,t,n,r){let i=0;if(!(n===0&&r.length===0)){for(;i-1;){const P=r.events[R][1].type;if(P==="lineEnding"||P==="linePrefix")R--;else break}const M=R>-1?r.events[R][1].type:null,H=M==="tableHead"||M==="tableRow"?m:s;return H===m&&r.parser.lazy[r.now().line]?n(E):H(E)}function s(E){return e.enter("tableHead"),e.enter("tableRow"),u(E)}function u(E){return E===124||(a=!0,o+=1),p(E)}function p(E){return E===null?n(E):W(E)?o>1?(o=0,r.interrupt=!0,e.exit("tableRow"),e.enter("lineEnding"),e.consume(E),e.exit("lineEnding"),d):n(E):ne(E)?oe(e,p,"whitespace")(E):(o+=1,a&&(a=!1,i+=1),E===124?(e.enter("tableCellDivider"),e.consume(E),e.exit("tableCellDivider"),a=!0,p):(e.enter("data"),c(E)))}function c(E){return E===null||E===124||he(E)?(e.exit("data"),p(E)):(e.consume(E),E===92?f:c)}function f(E){return E===92||E===124?(e.consume(E),c):c(E)}function d(E){return r.interrupt=!1,r.parser.lazy[r.now().line]?n(E):(e.enter("tableDelimiterRow"),a=!1,ne(E)?oe(e,g,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(E):g(E))}function g(E){return E===45||E===58?S(E):E===124?(a=!0,e.enter("tableCellDivider"),e.consume(E),e.exit("tableCellDivider"),k):C(E)}function k(E){return ne(E)?oe(e,S,"whitespace")(E):S(E)}function S(E){return E===58?(o+=1,a=!0,e.enter("tableDelimiterMarker"),e.consume(E),e.exit("tableDelimiterMarker"),x):E===45?(o+=1,x(E)):E===null||W(E)?_(E):C(E)}function x(E){return E===45?(e.enter("tableDelimiterFiller"),v(E)):C(E)}function v(E){return E===45?(e.consume(E),v):E===58?(a=!0,e.exit("tableDelimiterFiller"),e.enter("tableDelimiterMarker"),e.consume(E),e.exit("tableDelimiterMarker"),y):(e.exit("tableDelimiterFiller"),y(E))}function y(E){return ne(E)?oe(e,_,"whitespace")(E):_(E)}function _(E){return E===124?g(E):E===null||W(E)?!a||i!==o?C(E):(e.exit("tableDelimiterRow"),e.exit("tableHead"),t(E)):C(E)}function C(E){return n(E)}function m(E){return e.enter("tableRow"),T(E)}function T(E){return E===124?(e.enter("tableCellDivider"),e.consume(E),e.exit("tableCellDivider"),T):E===null||W(E)?(e.exit("tableRow"),t(E)):ne(E)?oe(e,T,"whitespace")(E):(e.enter("data"),j(E))}function j(E){return E===null||E===124||he(E)?(e.exit("data"),T(E)):(e.consume(E),E===92?A:j)}function A(E){return E===92||E===124?(e.consume(E),j):j(E)}}function mg(e,t){let n=-1,r=!0,i=0,o=[0,0,0,0],a=[0,0,0,0],l=!1,s=0,u,p,c;const f=new pg;for(;++nn[2]+1){const g=n[2]+1,k=n[3]-n[2]-1;e.add(g,k,[])}}e.add(n[3]+1,0,[["exit",c,t]])}return i!==void 0&&(o.end=Object.assign({},Tt(t.events,i)),e.add(i,0,[["exit",o,t]]),o=void 0),o}function Ma(e,t,n,r,i){const o=[],a=Tt(t.events,n);i&&(i.end=Object.assign({},a),o.push(["exit",i,t])),r.end=Object.assign({},a),o.push(["exit",r,t]),e.add(n+1,0,o)}function Tt(e,t){const n=e[t],r=n[0]==="enter"?"start":"end";return n[1][r]}const yg={name:"tasklistCheck",tokenize:xg};function bg(){return{text:{91:yg}}}function xg(e,t,n){const r=this;return i;function i(s){return r.previous!==null||!r._gfmTasklistFirstContentOfListItem?n(s):(e.enter("taskListCheck"),e.enter("taskListCheckMarker"),e.consume(s),e.exit("taskListCheckMarker"),o)}function o(s){return he(s)?(e.enter("taskListCheckValueUnchecked"),e.consume(s),e.exit("taskListCheckValueUnchecked"),a):s===88||s===120?(e.enter("taskListCheckValueChecked"),e.consume(s),e.exit("taskListCheckValueChecked"),a):n(s)}function a(s){return s===93?(e.enter("taskListCheckMarker"),e.consume(s),e.exit("taskListCheckMarker"),e.exit("taskListCheck"),l):n(s)}function l(s){return W(s)?t(s):ne(s)?e.check({tokenize:kg},t,n)(s):n(s)}}function kg(e,t,n){return oe(e,r,"whitespace");function r(i){return i===null?n(i):t(i)}}function vg(e){return ul([Vh(),ng(),cg(e),hg(),bg()])}const wg={};function Sg(e){const t=this,n=e||wg,r=t.data(),i=r.micromarkExtensions||(r.micromarkExtensions=[]),o=r.fromMarkdownExtensions||(r.fromMarkdownExtensions=[]),a=r.toMarkdownExtensions||(r.toMarkdownExtensions=[]);i.push(vg(n)),o.push(qh()),a.push(Uh(n))}function _g(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function Eg(e,t){if(e==null)return{};var n,r,i=_g(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;re.length)&&(t=e.length);for(var n=0,r=Array(t);n=4)return[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]}var Jn={};function Rg(e){if(e.length===0||e.length===1)return e;var t=e.join(".");return Jn[t]||(Jn[t]=jg(e)),Jn[t]}function Og(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0,r=e.filter(function(o){return o!=="token"}),i=Rg(r);return i.reduce(function(o,a){return At(At({},o),n[a])},t)}function za(e){return e.join(" ")}function Dg(e,t){var n=0;return function(r){return n+=1,r.map(function(i,o){return Jl({node:i,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(o)})})}}function Jl(e){var t=e.node,n=e.stylesheet,r=e.style,i=r===void 0?{}:r,o=e.useInlineStyles,a=e.key,l=t.properties,s=t.type,u=t.tagName,p=t.value;if(s==="text")return p;if(u){var c=Dg(n,o),f;if(!o)f=At(At({},l),{},{className:za(l.className)});else{var d=Object.keys(n).reduce(function(x,v){return v.split(".").forEach(function(y){x.includes(y)||x.push(y)}),x},[]),g=l.className&&l.className.includes("token")?["token"]:[],k=l.className&&g.concat(l.className.filter(function(x){return!d.includes(x)}));f=At(At({},l),{},{className:za(k)||void 0,style:Og(l.className,Object.assign({},l.style,i),n)})}var S=c(t.children);return it.createElement(u,mi({key:a},f),S)}}const Mg=(function(e,t){var n=e.listLanguages();return n.indexOf(t)!==-1});var Fg=["language","children","style","customStyle","codeTagProps","useInlineStyles","showLineNumbers","showInlineLineNumbers","startingLineNumber","lineNumberContainerStyle","lineNumberStyle","wrapLines","wrapLongLines","lineProps","renderer","PreTag","CodeTag","code","astGenerator"];function Pa(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(i){return Object.getOwnPropertyDescriptor(e,i).enumerable})),n.push.apply(n,r)}return n}function ct(e){for(var t=1;t0&&!n&&(e[e.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),n}const tg={tokenize:ug,partial:!0};function ng(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:og,continuation:{tokenize:lg},exit:sg}},text:{91:{name:"gfmFootnoteCall",tokenize:ag},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:rg,resolveTo:ig}}}}function rg(e,t,n){const r=this;let i=r.events.length;const o=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let a;for(;i--;){const s=r.events[i][1];if(s.type==="labelImage"){a=s;break}if(s.type==="gfmFootnoteCall"||s.type==="labelLink"||s.type==="label"||s.type==="image"||s.type==="link")break}return l;function l(s){if(!a||!a._balanced)return n(s);const u=Ke(r.sliceSerialize({start:a.end,end:r.now()}));return u.codePointAt(0)!==94||!o.includes(u.slice(1))?n(s):(e.enter("gfmFootnoteCallLabelMarker"),e.consume(s),e.exit("gfmFootnoteCallLabelMarker"),t(s))}}function ig(e,t){let n=e.length;for(;n--;)if(e[n][1].type==="labelImage"&&e[n][0]==="enter"){e[n][1];break}e[n+1][1].type="data",e[n+3][1].type="gfmFootnoteCallLabelMarker";const r={type:"gfmFootnoteCall",start:Object.assign({},e[n+3][1].start),end:Object.assign({},e[e.length-1][1].end)},i={type:"gfmFootnoteCallMarker",start:Object.assign({},e[n+3][1].end),end:Object.assign({},e[n+3][1].end)};i.end.column++,i.end.offset++,i.end._bufferIndex++;const o={type:"gfmFootnoteCallString",start:Object.assign({},i.end),end:Object.assign({},e[e.length-1][1].start)},a={type:"chunkString",contentType:"string",start:Object.assign({},o.start),end:Object.assign({},o.end)},l=[e[n+1],e[n+2],["enter",r,t],e[n+3],e[n+4],["enter",i,t],["exit",i,t],["enter",o,t],["enter",a,t],["exit",a,t],["exit",o,t],e[e.length-2],e[e.length-1],["exit",r,t]];return e.splice(n,e.length-n+1,...l),e}function ag(e,t,n){const r=this,i=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let o=0,a;return l;function l(c){return e.enter("gfmFootnoteCall"),e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),s}function s(c){return c!==94?n(c):(e.enter("gfmFootnoteCallMarker"),e.consume(c),e.exit("gfmFootnoteCallMarker"),e.enter("gfmFootnoteCallString"),e.enter("chunkString").contentType="string",u)}function u(c){if(o>999||c===93&&!a||c===null||c===91||he(c))return n(c);if(c===93){e.exit("chunkString");const f=e.exit("gfmFootnoteCallString");return i.includes(Ke(r.sliceSerialize(f)))?(e.enter("gfmFootnoteCallLabelMarker"),e.consume(c),e.exit("gfmFootnoteCallLabelMarker"),e.exit("gfmFootnoteCall"),t):n(c)}return he(c)||(a=!0),o++,e.consume(c),c===92?p:u}function p(c){return c===91||c===92||c===93?(e.consume(c),o++,u):u(c)}}function og(e,t,n){const r=this,i=r.parser.gfmFootnotes||(r.parser.gfmFootnotes=[]);let o,a=0,l;return s;function s(g){return e.enter("gfmFootnoteDefinition")._container=!0,e.enter("gfmFootnoteDefinitionLabel"),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionLabelMarker"),u}function u(g){return g===94?(e.enter("gfmFootnoteDefinitionMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionMarker"),e.enter("gfmFootnoteDefinitionLabelString"),e.enter("chunkString").contentType="string",p):n(g)}function p(g){if(a>999||g===93&&!l||g===null||g===91||he(g))return n(g);if(g===93){e.exit("chunkString");const k=e.exit("gfmFootnoteDefinitionLabelString");return o=Ke(r.sliceSerialize(k)),e.enter("gfmFootnoteDefinitionLabelMarker"),e.consume(g),e.exit("gfmFootnoteDefinitionLabelMarker"),e.exit("gfmFootnoteDefinitionLabel"),f}return he(g)||(l=!0),a++,e.consume(g),g===92?c:p}function c(g){return g===91||g===92||g===93?(e.consume(g),a++,p):p(g)}function f(g){return g===58?(e.enter("definitionMarker"),e.consume(g),e.exit("definitionMarker"),i.includes(o)||i.push(o),oe(e,d,"gfmFootnoteDefinitionWhitespace")):n(g)}function d(g){return t(g)}}function lg(e,t,n){return e.check(Qt,t,e.attempt(tg,t,n))}function sg(e){e.exit("gfmFootnoteDefinition")}function ug(e,t,n){const r=this;return oe(e,i,"gfmFootnoteDefinitionIndent",5);function i(o){const a=r.events[r.events.length-1];return a&&a[1].type==="gfmFootnoteDefinitionIndent"&&a[2].sliceSerialize(a[1],!0).length===4?t(o):n(o)}}function cg(e){let n=(e||{}).singleTilde;const r={name:"strikethrough",tokenize:o,resolveAll:i};return n==null&&(n=!0),{text:{126:r},insideSpan:{null:[r]},attentionMarkers:{null:[126]}};function i(a,l){let s=-1;for(;++s1?s(g):(a.consume(g),c++,d);if(c<2&&!n)return s(g);const S=a.exit("strikethroughSequenceTemporary"),x=jt(g);return S._open=!x||x===2&&!!k,S._close=!k||k===2&&!!x,l(g)}}}class pg{constructor(){this.map=[]}add(t,n,r){dg(this,t,n,r)}consume(t){if(this.map.sort(function(o,a){return o[0]-a[0]}),this.map.length===0)return;let n=this.map.length;const r=[];for(;n>0;)n-=1,r.push(t.slice(this.map[n][0]+this.map[n][1]),this.map[n][2]),t.length=this.map[n][0];r.push(t.slice()),t.length=0;let i=r.pop();for(;i;){for(const o of i)t.push(o);i=r.pop()}this.map.length=0}}function dg(e,t,n,r){let i=0;if(!(n===0&&r.length===0)){for(;i-1;){const P=r.events[R][1].type;if(P==="lineEnding"||P==="linePrefix")R--;else break}const M=R>-1?r.events[R][1].type:null,H=M==="tableHead"||M==="tableRow"?m:s;return H===m&&r.parser.lazy[r.now().line]?n(E):H(E)}function s(E){return e.enter("tableHead"),e.enter("tableRow"),u(E)}function u(E){return E===124||(a=!0,o+=1),p(E)}function p(E){return E===null?n(E):W(E)?o>1?(o=0,r.interrupt=!0,e.exit("tableRow"),e.enter("lineEnding"),e.consume(E),e.exit("lineEnding"),d):n(E):ne(E)?oe(e,p,"whitespace")(E):(o+=1,a&&(a=!1,i+=1),E===124?(e.enter("tableCellDivider"),e.consume(E),e.exit("tableCellDivider"),a=!0,p):(e.enter("data"),c(E)))}function c(E){return E===null||E===124||he(E)?(e.exit("data"),p(E)):(e.consume(E),E===92?f:c)}function f(E){return E===92||E===124?(e.consume(E),c):c(E)}function d(E){return r.interrupt=!1,r.parser.lazy[r.now().line]?n(E):(e.enter("tableDelimiterRow"),a=!1,ne(E)?oe(e,g,"linePrefix",r.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(E):g(E))}function g(E){return E===45||E===58?S(E):E===124?(a=!0,e.enter("tableCellDivider"),e.consume(E),e.exit("tableCellDivider"),k):C(E)}function k(E){return ne(E)?oe(e,S,"whitespace")(E):S(E)}function S(E){return E===58?(o+=1,a=!0,e.enter("tableDelimiterMarker"),e.consume(E),e.exit("tableDelimiterMarker"),x):E===45?(o+=1,x(E)):E===null||W(E)?_(E):C(E)}function x(E){return E===45?(e.enter("tableDelimiterFiller"),v(E)):C(E)}function v(E){return E===45?(e.consume(E),v):E===58?(a=!0,e.exit("tableDelimiterFiller"),e.enter("tableDelimiterMarker"),e.consume(E),e.exit("tableDelimiterMarker"),b):(e.exit("tableDelimiterFiller"),b(E))}function b(E){return ne(E)?oe(e,_,"whitespace")(E):_(E)}function _(E){return E===124?g(E):E===null||W(E)?!a||i!==o?C(E):(e.exit("tableDelimiterRow"),e.exit("tableHead"),t(E)):C(E)}function C(E){return n(E)}function m(E){return e.enter("tableRow"),T(E)}function T(E){return E===124?(e.enter("tableCellDivider"),e.consume(E),e.exit("tableCellDivider"),T):E===null||W(E)?(e.exit("tableRow"),t(E)):ne(E)?oe(e,T,"whitespace")(E):(e.enter("data"),j(E))}function j(E){return E===null||E===124||he(E)?(e.exit("data"),T(E)):(e.consume(E),E===92?A:j)}function A(E){return E===92||E===124?(e.consume(E),j):j(E)}}function mg(e,t){let n=-1,r=!0,i=0,o=[0,0,0,0],a=[0,0,0,0],l=!1,s=0,u,p,c;const f=new pg;for(;++nn[2]+1){const g=n[2]+1,k=n[3]-n[2]-1;e.add(g,k,[])}}e.add(n[3]+1,0,[["exit",c,t]])}return i!==void 0&&(o.end=Object.assign({},Tt(t.events,i)),e.add(i,0,[["exit",o,t]]),o=void 0),o}function Ma(e,t,n,r,i){const o=[],a=Tt(t.events,n);i&&(i.end=Object.assign({},a),o.push(["exit",i,t])),r.end=Object.assign({},a),o.push(["exit",r,t]),e.add(n+1,0,o)}function Tt(e,t){const n=e[t],r=n[0]==="enter"?"start":"end";return n[1][r]}const bg={name:"tasklistCheck",tokenize:xg};function yg(){return{text:{91:bg}}}function xg(e,t,n){const r=this;return i;function i(s){return r.previous!==null||!r._gfmTasklistFirstContentOfListItem?n(s):(e.enter("taskListCheck"),e.enter("taskListCheckMarker"),e.consume(s),e.exit("taskListCheckMarker"),o)}function o(s){return he(s)?(e.enter("taskListCheckValueUnchecked"),e.consume(s),e.exit("taskListCheckValueUnchecked"),a):s===88||s===120?(e.enter("taskListCheckValueChecked"),e.consume(s),e.exit("taskListCheckValueChecked"),a):n(s)}function a(s){return s===93?(e.enter("taskListCheckMarker"),e.consume(s),e.exit("taskListCheckMarker"),e.exit("taskListCheck"),l):n(s)}function l(s){return W(s)?t(s):ne(s)?e.check({tokenize:kg},t,n)(s):n(s)}}function kg(e,t,n){return oe(e,r,"whitespace");function r(i){return i===null?n(i):t(i)}}function vg(e){return ul([Vh(),ng(),cg(e),hg(),yg()])}const wg={};function Sg(e){const t=this,n=e||wg,r=t.data(),i=r.micromarkExtensions||(r.micromarkExtensions=[]),o=r.fromMarkdownExtensions||(r.fromMarkdownExtensions=[]),a=r.toMarkdownExtensions||(r.toMarkdownExtensions=[]);i.push(vg(n)),o.push(qh()),a.push(Uh(n))}function _g(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function Eg(e,t){if(e==null)return{};var n,r,i=_g(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;re.length)&&(t=e.length);for(var n=0,r=Array(t);n=4)return[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]}var Jn={};function Rg(e){if(e.length===0||e.length===1)return e;var t=e.join(".");return Jn[t]||(Jn[t]=jg(e)),Jn[t]}function Og(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0,r=e.filter(function(o){return o!=="token"}),i=Rg(r);return i.reduce(function(o,a){return At(At({},o),n[a])},t)}function za(e){return e.join(" ")}function Dg(e,t){var n=0;return function(r){return n+=1,r.map(function(i,o){return Jl({node:i,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(o)})})}}function Jl(e){var t=e.node,n=e.stylesheet,r=e.style,i=r===void 0?{}:r,o=e.useInlineStyles,a=e.key,l=t.properties,s=t.type,u=t.tagName,p=t.value;if(s==="text")return p;if(u){var c=Dg(n,o),f;if(!o)f=At(At({},l),{},{className:za(l.className)});else{var d=Object.keys(n).reduce(function(x,v){return v.split(".").forEach(function(b){x.includes(b)||x.push(b)}),x},[]),g=l.className&&l.className.includes("token")?["token"]:[],k=l.className&&g.concat(l.className.filter(function(x){return!d.includes(x)}));f=At(At({},l),{},{className:za(k)||void 0,style:Og(l.className,Object.assign({},l.style,i),n)})}var S=c(t.children);return it.createElement(u,mi({key:a},f),S)}}const Mg=(function(e,t){var n=e.listLanguages();return n.indexOf(t)!==-1});var Fg=["language","children","style","customStyle","codeTagProps","useInlineStyles","showLineNumbers","showInlineLineNumbers","startingLineNumber","lineNumberContainerStyle","lineNumberStyle","wrapLines","wrapLongLines","lineProps","renderer","PreTag","CodeTag","code","astGenerator"];function Pa(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(i){return Object.getOwnPropertyDescriptor(e,i).enumerable})),n.push.apply(n,r)}return n}function ct(e){for(var t=1;t1&&arguments[1]!==void 0?arguments[1]:[],n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[],r=0;r2&&arguments[2]!==void 0?arguments[2]:[];return hn({children:C,lineNumber:m,lineNumberStyle:l,largestLineNumber:a,showInlineLineNumbers:i,lineProps:n,className:T,showLineNumbers:r,wrapLongLines:s,wrapLines:t})}function k(C,m){if(r&&m&&i){var T=ts(l,m,a);C.unshift(es(m,T))}return C}function S(C,m){var T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:[];return t||T.length>0?g(C,m,T):k(C,m)}for(var x=function(){var m=p[d],T=m.children[0].value,j=Pg(T);if(j){var A=T.split(` `);A.forEach(function(E,R){var M=r&&c.length+o,H={type:"text",value:"".concat(E,` -`)};if(R===0){var P=p.slice(f+1,d).concat(hn({children:[H],className:m.properties.className})),z=S(P,M);c.push(z)}else if(R===A.length-1){var G=p[d+1]&&p[d+1].children&&p[d+1].children[0],J={type:"text",value:"".concat(E)};if(G){var U=hn({children:[J],className:m.properties.className});p.splice(d+1,0,U)}else{var ie=[J],w=S(ie,M,m.properties.className);c.push(w)}}else{var K=[H],Y=S(K,M,m.properties.className);c.push(Y)}}),f=d}d++};d4&&g.slice(0,4)===r&&i.test(d)&&(d.charAt(4)==="-"?k=s(d):d=u(d),S=t),new S(k,d))}function s(f){var d=f.slice(5).replace(o,c);return r+d.charAt(0).toUpperCase()+d.slice(1)}function u(f){var d=f.slice(4);return o.test(d)?f:(d=d.replace(a,p),d.charAt(0)!=="-"&&(d="-"+d),r+d)}function p(f){return"-"+f.toLowerCase()}function c(f){return f.charAt(1).toUpperCase()}return gr}var mr,ro;function rm(){if(ro)return mr;ro=1,mr=t;var e=/[#.]/g;function t(n,r){for(var i=n||"",o=r||"div",a={},l=0,s,u,p;l=48&&n<=57}return kr}var vr,co;function ub(){if(co)return vr;co=1,vr=e;function e(t){var n=typeof t=="string"?t.charCodeAt(0):t;return n>=97&&n<=102||n>=65&&n<=70||n>=48&&n<=57}return vr}var wr,po;function cb(){if(po)return wr;po=1,wr=e;function e(t){var n=typeof t=="string"?t.charCodeAt(0):t;return n>=97&&n<=122||n>=65&&n<=90}return wr}var Sr,fo;function pb(){if(fo)return Sr;fo=1;var e=cb(),t=ss();Sr=n;function n(r){return e(r)||t(r)}return Sr}var _r,ho;function db(){if(ho)return _r;ho=1;var e,t=59;_r=n;function n(r){var i="&"+r+";",o;return e=e||document.createElement("i"),e.innerHTML=i,o=e.textContent,o.charCodeAt(o.length-1)===t&&r!=="semi"||o===i?!1:o}return _r}var Er,go;function fb(){if(go)return Er;go=1;var e=lb,t=sb,n=ss(),r=ub(),i=pb(),o=db();Er=ie;var a={}.hasOwnProperty,l=String.fromCharCode,s=Function.prototype,u={warning:null,reference:null,text:null,warningContext:null,referenceContext:null,textContext:null,position:{},additional:null,attribute:!1,nonTerminated:!0},p=9,c=10,f=12,d=32,g=38,k=59,S=60,x=61,v=35,y=88,_=120,C=65533,m="named",T="hexadecimal",j="decimal",A={};A[T]=16,A[j]=10;var E={};E[m]=i,E[j]=n,E[T]=r;var R=1,M=2,H=3,P=4,z=5,G=6,J=7,U={};U[R]="Named character references must be terminated by a semicolon",U[M]="Numeric character references must be terminated by a semicolon",U[H]="Named character references cannot be empty",U[P]="Numeric character references cannot be empty",U[z]="Named character references must be known",U[G]="Numeric character references cannot be disallowed",U[J]="Numeric character references cannot be outside the permissible Unicode range";function ie(b,Z){var ee={},te,xe;Z||(Z={});for(xe in u)te=Z[xe],ee[xe]=te??u[xe];return(ee.position.indent||ee.position.start)&&(ee.indent=ee.position.indent||[],ee.position=ee.position.start),w(b,ee)}function w(b,Z){var ee=Z.additional,te=Z.nonTerminated,xe=Z.text,we=Z.reference,_e=Z.warning,Ce=Z.textContext,ye=Z.referenceContext,qe=Z.warningContext,le=Z.position,ce=Z.indent||[],Ze=b.length,Ae=0,Xe=-1,Me=le.column||1,dt=le.line||1,Fe="",Qe=[],Ue,ft,He,se,L,D,B,V,re,ke,Te,ve,je,pe,Se,ze,Le,Ne,be;for(typeof ee=="string"&&(ee=ee.charCodeAt(0)),ze=lt(),V=_e?Nn:s,Ae--,Ze++;++Ae65535&&(D-=65536,ke+=l(D>>>10|55296),D=56320|D&1023),D=ke+l(D))):pe!==m&&V(P,Ne)),D?(tn(),ze=lt(),Ae=be-1,Me+=be-je+1,Qe.push(D),Le=lt(),Le.offset++,we&&we.call(ye,D,{start:ze,end:Le},b.slice(je-1,be)),ze=Le):(se=b.slice(je-1,be),Fe+=se,Me+=se.length,Ae=be-1)}else L===10&&(dt++,Xe++,Me=0),L===L?(Fe+=l(L),Me++):tn();return Qe.join("");function lt(){return{line:dt,column:Me,offset:Ae+(le.offset||0)}}function Nn(ht,gt){var mt=lt();mt.column+=gt,mt.offset+=gt,_e.call(qe,U[ht],mt,ht)}function tn(){Fe&&(Qe.push(Fe),xe&&xe.call(Ce,Fe,{start:ze,end:lt()}),Fe="")}}function K(b){return b>=55296&&b<=57343||b>1114111}function Y(b){return b>=1&&b<=8||b===11||b>=13&&b<=31||b>=127&&b<=159||b>=64976&&b<=65007||(b&65535)===65535||(b&65535)===65534}return Er}var Cr={exports:{}},mo;function hb(){return mo||(mo=1,(function(e){var t=typeof window<"u"?window:typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?self:{};var n=(function(r){var i=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,o=0,a={},l={manual:r.Prism&&r.Prism.manual,disableWorkerMessageHandler:r.Prism&&r.Prism.disableWorkerMessageHandler,util:{encode:function v(y){return y instanceof s?new s(y.type,v(y.content),y.alias):Array.isArray(y)?y.map(v):y.replace(/&/g,"&").replace(/"u")return null;if("currentScript"in document)return document.currentScript;try{throw new Error}catch(C){var v=(/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(C.stack)||[])[1];if(v){var y=document.getElementsByTagName("script");for(var _ in y)if(y[_].src==v)return y[_]}return null}},isActive:function(v,y,_){for(var C="no-"+y;v;){var m=v.classList;if(m.contains(y))return!0;if(m.contains(C))return!1;v=v.parentElement}return!!_}},languages:{plain:a,plaintext:a,text:a,txt:a,extend:function(v,y){var _=l.util.clone(l.languages[v]);for(var C in y)_[C]=y[C];return _},insertBefore:function(v,y,_,C){C=C||l.languages;var m=C[v],T={};for(var j in m)if(m.hasOwnProperty(j)){if(j==y)for(var A in _)_.hasOwnProperty(A)&&(T[A]=_[A]);_.hasOwnProperty(j)||(T[j]=m[j])}var E=C[v];return C[v]=T,l.languages.DFS(l.languages,function(R,M){M===E&&R!=v&&(this[R]=T)}),T},DFS:function v(y,_,C,m){m=m||{};var T=l.util.objId;for(var j in y)if(y.hasOwnProperty(j)){_.call(y,j,y[j],C||j);var A=y[j],E=l.util.type(A);E==="Object"&&!m[T(A)]?(m[T(A)]=!0,v(A,_,null,m)):E==="Array"&&!m[T(A)]&&(m[T(A)]=!0,v(A,_,j,m))}}},plugins:{},highlightAll:function(v,y){l.highlightAllUnder(document,v,y)},highlightAllUnder:function(v,y,_){var C={callback:_,container:v,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};l.hooks.run("before-highlightall",C),C.elements=Array.prototype.slice.apply(C.container.querySelectorAll(C.selector)),l.hooks.run("before-all-elements-highlight",C);for(var m=0,T;T=C.elements[m++];)l.highlightElement(T,y===!0,C.callback)},highlightElement:function(v,y,_){var C=l.util.getLanguage(v),m=l.languages[C];l.util.setLanguage(v,C);var T=v.parentElement;T&&T.nodeName.toLowerCase()==="pre"&&l.util.setLanguage(T,C);var j=v.textContent,A={element:v,language:C,grammar:m,code:j};function E(M){A.highlightedCode=M,l.hooks.run("before-insert",A),A.element.innerHTML=A.highlightedCode,l.hooks.run("after-highlight",A),l.hooks.run("complete",A),_&&_.call(A.element)}if(l.hooks.run("before-sanity-check",A),T=A.element.parentElement,T&&T.nodeName.toLowerCase()==="pre"&&!T.hasAttribute("tabindex")&&T.setAttribute("tabindex","0"),!A.code){l.hooks.run("complete",A),_&&_.call(A.element);return}if(l.hooks.run("before-highlight",A),!A.grammar){E(l.util.encode(A.code));return}if(y&&r.Worker){var R=new Worker(l.filename);R.onmessage=function(M){E(M.data)},R.postMessage(JSON.stringify({language:A.language,code:A.code,immediateClose:!0}))}else E(l.highlight(A.code,A.grammar,A.language))},highlight:function(v,y,_){var C={code:v,grammar:y,language:_};if(l.hooks.run("before-tokenize",C),!C.grammar)throw new Error('The language "'+C.language+'" has no grammar.');return C.tokens=l.tokenize(C.code,C.grammar),l.hooks.run("after-tokenize",C),s.stringify(l.util.encode(C.tokens),C.language)},tokenize:function(v,y){var _=y.rest;if(_){for(var C in _)y[C]=_[C];delete y.rest}var m=new c;return f(m,m.head,v),p(v,m,y,m.head,0),g(m)},hooks:{all:{},add:function(v,y){var _=l.hooks.all;_[v]=_[v]||[],_[v].push(y)},run:function(v,y){var _=l.hooks.all[v];if(!(!_||!_.length))for(var C=0,m;m=_[C++];)m(y)}},Token:s};r.Prism=l;function s(v,y,_,C){this.type=v,this.content=y,this.alias=_,this.length=(C||"").length|0}s.stringify=function v(y,_){if(typeof y=="string")return y;if(Array.isArray(y)){var C="";return y.forEach(function(E){C+=v(E,_)}),C}var m={type:y.type,content:v(y.content,_),tag:"span",classes:["token",y.type],attributes:{},language:_},T=y.alias;T&&(Array.isArray(T)?Array.prototype.push.apply(m.classes,T):m.classes.push(T)),l.hooks.run("wrap",m);var j="";for(var A in m.attributes)j+=" "+A+'="'+(m.attributes[A]||"").replace(/"/g,""")+'"';return"<"+m.tag+' class="'+m.classes.join(" ")+'"'+j+">"+m.content+""};function u(v,y,_,C){v.lastIndex=y;var m=v.exec(_);if(m&&C&&m[1]){var T=m[1].length;m.index+=T,m[0]=m[0].slice(T)}return m}function p(v,y,_,C,m,T){for(var j in _)if(!(!_.hasOwnProperty(j)||!_[j])){var A=_[j];A=Array.isArray(A)?A:[A];for(var E=0;E=T.reach);ie+=U.value.length,U=U.next){var w=U.value;if(y.length>v.length)return;if(!(w instanceof s)){var K=1,Y;if(P){if(Y=u(J,ie,v,H),!Y||Y.index>=v.length)break;var te=Y.index,b=Y.index+Y[0].length,Z=ie;for(Z+=U.value.length;te>=Z;)U=U.next,Z+=U.value.length;if(Z-=U.value.length,ie=Z,U.value instanceof s)continue;for(var ee=U;ee!==y.tail&&(ZT.reach&&(T.reach=Ce);var ye=U.prev;we&&(ye=f(y,ye,we),ie+=we.length),d(y,ye,K);var qe=new s(j,M?l.tokenize(xe,M):xe,z,xe);if(U=f(y,ye,qe),_e&&f(y,U,_e),K>1){var le={cause:j+","+E,reach:Ce};p(v,y,_,U.prev,ie,le),T&&le.reach>T.reach&&(T.reach=le.reach)}}}}}}function c(){var v={value:null,prev:null,next:null},y={value:null,prev:v,next:null};v.next=y,this.head=v,this.tail=y,this.length=0}function f(v,y,_){var C=y.next,m={value:_,prev:y,next:C};return y.next=m,C.prev=m,v.length++,m}function d(v,y,_){for(var C=y.next,m=0;m<_&&C!==v.tail;m++)C=C.next;y.next=C,C.prev=y,v.length-=m}function g(v){for(var y=[],_=v.head.next;_!==v.tail;)y.push(_.value),_=_.next;return y}if(!r.document)return r.addEventListener&&(l.disableWorkerMessageHandler||r.addEventListener("message",function(v){var y=JSON.parse(v.data),_=y.language,C=y.code,m=y.immediateClose;r.postMessage(l.highlight(C,l.languages[_],_)),m&&r.close()},!1)),l;var k=l.util.currentScript();k&&(l.filename=k.src,k.hasAttribute("data-manual")&&(l.manual=!0));function S(){l.manual||l.highlightAll()}if(!l.manual){var x=document.readyState;x==="loading"||x==="interactive"&&k&&k.defer?document.addEventListener("DOMContentLoaded",S):window.requestAnimationFrame?window.requestAnimationFrame(S):window.setTimeout(S,16)}return l})(t);e.exports&&(e.exports=n),typeof mn<"u"&&(mn.Prism=n)})(Cr)),Cr.exports}var Tr,yo;function us(){if(yo)return Tr;yo=1,Tr=e,e.displayName="markup",e.aliases=["html","mathml","svg","xml","ssml","atom","rss"];function e(t){t.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},t.languages.markup.tag.inside["attr-value"].inside.entity=t.languages.markup.entity,t.languages.markup.doctype.inside["internal-subset"].inside=t.languages.markup,t.hooks.add("wrap",function(n){n.type==="entity"&&(n.attributes.title=n.content.value.replace(/&/,"&"))}),Object.defineProperty(t.languages.markup.tag,"addInlined",{value:function(r,i){var o={};o["language-"+i]={pattern:/(^$)/i,lookbehind:!0,inside:t.languages[i]},o.cdata=/^$/i;var a={"included-cdata":{pattern://i,inside:o}};a["language-"+i]={pattern:/[\s\S]+/,inside:t.languages[i]};var l={};l[r]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,function(){return r}),"i"),lookbehind:!0,greedy:!0,inside:a},t.languages.insertBefore("markup","cdata",l)}}),Object.defineProperty(t.languages.markup.tag,"addAttribute",{value:function(n,r){t.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+n+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[r,"language-"+r],inside:t.languages[r]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),t.languages.html=t.languages.markup,t.languages.mathml=t.languages.markup,t.languages.svg=t.languages.markup,t.languages.xml=t.languages.extend("markup",{}),t.languages.ssml=t.languages.xml,t.languages.atom=t.languages.xml,t.languages.rss=t.languages.xml}return Tr}var Ar,bo;function cs(){if(bo)return Ar;bo=1,Ar=e,e.displayName="css",e.aliases=[];function e(t){(function(n){var r=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;n.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+r.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+r.source+"$"),alias:"url"}}},selector:{pattern:RegExp(`(^|[{}\\s])[^{}\\s](?:[^{};"'\\s]|\\s+(?![\\s{])|`+r.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:r,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},n.languages.css.atrule.inside.rest=n.languages.css;var i=n.languages.markup;i&&(i.tag.addInlined("style","css"),i.tag.addAttribute("style","css"))})(t)}return Ar}var Lr,xo;function gb(){if(xo)return Lr;xo=1,Lr=e,e.displayName="clike",e.aliases=[];function e(t){t.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}}return Lr}var Nr,ko;function ps(){if(ko)return Nr;ko=1,Nr=e,e.displayName="javascript",e.aliases=["js"];function e(t){t.languages.javascript=t.languages.extend("clike",{"class-name":[t.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+(/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source)+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),t.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,t.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:t.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:t.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:t.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:t.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:t.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),t.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:t.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),t.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),t.languages.markup&&(t.languages.markup.tag.addInlined("script","javascript"),t.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),t.languages.js=t.languages.javascript}return Nr}var Ir,vo;function mb(){if(vo)return Ir;vo=1;var e=typeof globalThis=="object"?globalThis:typeof self=="object"?self:typeof window=="object"?window:typeof mn=="object"?mn:{},t=C();e.Prism={manual:!0,disableWorkerMessageHandler:!0};var n=sm(),r=fb(),i=hb(),o=us(),a=cs(),l=gb(),s=ps();t();var u={}.hasOwnProperty;function p(){}p.prototype=i;var c=new p;Ir=c,c.highlight=g,c.register=f,c.alias=d,c.registered=k,c.listLanguages=S,f(o),f(a),f(l),f(s),c.util.encode=y,c.Token.stringify=x;function f(m){if(typeof m!="function"||!m.displayName)throw new Error("Expected `function` for `grammar`, got `"+m+"`");c.languages[m.displayName]===void 0&&m(c)}function d(m,T){var j=c.languages,A=m,E,R,M,H;T&&(A={},A[m]=T);for(E in A)for(R=A[E],R=typeof R=="string"?[R]:R,M=R.length,H=-1;++H?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}}return jr}var Rr,So;function ds(){if(So)return Rr;So=1,Rr=e,e.displayName="c",e.aliases=[];function e(t){t.languages.c=t.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),t.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),t.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},t.languages.c.string],char:t.languages.c.char,comment:t.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:t.languages.c}}}}),t.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete t.languages.c.boolean}return Rr}var Or,_o;function xb(){if(_o)return Or;_o=1;var e=ds();Or=t,t.displayName="cpp",t.aliases=[];function t(n){n.register(e),(function(r){var i=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,o=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,function(){return i.source});r.languages.cpp=r.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,function(){return i.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:i,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),r.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,function(){return o})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),r.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:r.languages.cpp}}}}),r.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),r.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:r.languages.extend("cpp",{})}}),r.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},r.languages.cpp["base-clause"])})(n)}return Or}var Dr,Eo;function kb(){if(Eo)return Dr;Eo=1,Dr=e,e.displayName="csharp",e.aliases=["dotnet","cs"];function e(t){(function(n){function r(K,Y){return K.replace(/<<(\d+)>>/g,function(b,Z){return"(?:"+Y[+Z]+")"})}function i(K,Y,b){return RegExp(r(K,Y),"")}function o(K,Y){for(var b=0;b>/g,function(){return"(?:"+K+")"});return K.replace(/<>/g,"[^\\s\\S]")}var a={type:"bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",typeDeclaration:"class enum interface record struct",contextual:"add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",other:"abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield"};function l(K){return"\\b(?:"+K.trim().replace(/ /g,"|")+")\\b"}var s=l(a.typeDeclaration),u=RegExp(l(a.type+" "+a.typeDeclaration+" "+a.contextual+" "+a.other)),p=l(a.typeDeclaration+" "+a.contextual+" "+a.other),c=l(a.type+" "+a.typeDeclaration+" "+a.other),f=o(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source,2),d=o(/\((?:[^()]|<>)*\)/.source,2),g=/@?\b[A-Za-z_]\w*\b/.source,k=r(/<<0>>(?:\s*<<1>>)?/.source,[g,f]),S=r(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[p,k]),x=/\[\s*(?:,\s*)*\]/.source,v=r(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[S,x]),y=r(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[f,d,x]),_=r(/\(<<0>>+(?:,<<0>>+)+\)/.source,[y]),C=r(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[_,S,x]),m={keyword:u,punctuation:/[<>()?,.:[\]]/},T=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,j=/"(?:\\.|[^\\"\r\n])*"/.source,A=/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source;n.languages.csharp=n.languages.extend("clike",{string:[{pattern:i(/(^|[^$\\])<<0>>/.source,[A]),lookbehind:!0,greedy:!0},{pattern:i(/(^|[^@$\\])<<0>>/.source,[j]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:i(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[S]),lookbehind:!0,inside:m},{pattern:i(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[g,C]),lookbehind:!0,inside:m},{pattern:i(/(\busing\s+)<<0>>(?=\s*=)/.source,[g]),lookbehind:!0},{pattern:i(/(\b<<0>>\s+)<<1>>/.source,[s,k]),lookbehind:!0,inside:m},{pattern:i(/(\bcatch\s*\(\s*)<<0>>/.source,[S]),lookbehind:!0,inside:m},{pattern:i(/(\bwhere\s+)<<0>>/.source,[g]),lookbehind:!0},{pattern:i(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[v]),lookbehind:!0,inside:m},{pattern:i(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[C,c,g]),inside:m}],keyword:u,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),n.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),n.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:i(/([(,]\s*)<<0>>(?=\s*:)/.source,[g]),lookbehind:!0,alias:"punctuation"}}),n.languages.insertBefore("csharp","class-name",{namespace:{pattern:i(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[g]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:i(/(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source,[d]),lookbehind:!0,alias:"class-name",inside:m},"return-type":{pattern:i(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[C,S]),inside:m,alias:"class-name"},"constructor-invocation":{pattern:i(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[C]),lookbehind:!0,inside:m,alias:"class-name"},"generic-method":{pattern:i(/<<0>>\s*<<1>>(?=\s*\()/.source,[g,f]),inside:{function:i(/^<<0>>/.source,[g]),generic:{pattern:RegExp(f),alias:"class-name",inside:m}}},"type-list":{pattern:i(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[s,k,g,C,u.source,d,/\bnew\s*\(\s*\)/.source]),lookbehind:!0,inside:{"record-arguments":{pattern:i(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source,[k,d]),lookbehind:!0,greedy:!0,inside:n.languages.csharp},keyword:u,"class-name":{pattern:RegExp(C),greedy:!0,inside:m},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var E=j+"|"+T,R=r(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[E]),M=o(r(/[^"'/()]|<<0>>|\(<>*\)/.source,[R]),2),H=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,P=r(/<<0>>(?:\s*\(<<1>>*\))?/.source,[S,M]);n.languages.insertBefore("csharp","class-name",{attribute:{pattern:i(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[H,P]),lookbehind:!0,greedy:!0,inside:{target:{pattern:i(/^<<0>>(?=\s*:)/.source,[H]),alias:"keyword"},"attribute-arguments":{pattern:i(/\(<<0>>*\)/.source,[M]),inside:n.languages.csharp},"class-name":{pattern:RegExp(S),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var z=/:[^}\r\n]+/.source,G=o(r(/[^"'/()]|<<0>>|\(<>*\)/.source,[R]),2),J=r(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[G,z]),U=o(r(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source,[E]),2),ie=r(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[U,z]);function w(K,Y){return{interpolation:{pattern:i(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[K]),lookbehind:!0,inside:{"format-string":{pattern:i(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[Y,z]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:n.languages.csharp}}},string:/[\s\S]+/}}n.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:i(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[J]),lookbehind:!0,greedy:!0,inside:w(J,G)},{pattern:i(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[ie]),lookbehind:!0,greedy:!0,inside:w(ie,U)}],char:{pattern:RegExp(T),greedy:!0}}),n.languages.dotnet=n.languages.cs=n.languages.csharp})(t)}return Dr}var Mr,Co;function vb(){if(Co)return Mr;Co=1,Mr=e,e.displayName="bash",e.aliases=["shell"];function e(t){(function(n){var r="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",i={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},o={bash:i,environment:{pattern:RegExp("\\$"+r),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+r),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};n.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+r),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:o},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:i}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:o},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:o.entity}}],environment:{pattern:RegExp("\\$?"+r),alias:"constant"},variable:o.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},i.inside=n.languages.bash;for(var a=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],l=o.variable[1].inside,s=0;s|[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),n.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var r={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:n.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete n.languages.ruby.function;var i="(?:"+[/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,/\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,/<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|")+")",o=/(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;n.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp(/%r/.source+i+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp(/(^|[^:]):/.source+o),lookbehind:!0,greedy:!0},{pattern:RegExp(/([\r\n{(,][ \t]*)/.source+o+/(?=:(?!:))/.source),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),n.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp(/%[qQiIwWs]?/.source+i),greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp(/%x/.source+i),greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete n.languages.ruby.string,n.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),n.languages.rb=n.languages.ruby})(t)}return Fr}var zr,Ao;function Sb(){if(Ao)return zr;Ao=1,zr=e,e.displayName="diff",e.aliases=[];function e(t){(function(n){n.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var r={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(r).forEach(function(i){var o=r[i],a=[];/^\w+$/.test(i)||a.push(/\w+/.exec(i)[0]),i==="diff"&&a.push("bold"),n.languages.diff[i]={pattern:RegExp("^(?:["+o+`].*(?:\r +`)};if(R===0){var P=p.slice(f+1,d).concat(hn({children:[H],className:m.properties.className})),z=S(P,M);c.push(z)}else if(R===A.length-1){var G=p[d+1]&&p[d+1].children&&p[d+1].children[0],J={type:"text",value:"".concat(E)};if(G){var U=hn({children:[J],className:m.properties.className});p.splice(d+1,0,U)}else{var ie=[J],w=S(ie,M,m.properties.className);c.push(w)}}else{var K=[H],Y=S(K,M,m.properties.className);c.push(Y)}}),f=d}d++};d4&&g.slice(0,4)===r&&i.test(d)&&(d.charAt(4)==="-"?k=s(d):d=u(d),S=t),new S(k,d))}function s(f){var d=f.slice(5).replace(o,c);return r+d.charAt(0).toUpperCase()+d.slice(1)}function u(f){var d=f.slice(4);return o.test(d)?f:(d=d.replace(a,p),d.charAt(0)!=="-"&&(d="-"+d),r+d)}function p(f){return"-"+f.toLowerCase()}function c(f){return f.charAt(1).toUpperCase()}return gr}var mr,ro;function rm(){if(ro)return mr;ro=1,mr=t;var e=/[#.]/g;function t(n,r){for(var i=n||"",o=r||"div",a={},l=0,s,u,p;l=48&&n<=57}return kr}var vr,co;function uy(){if(co)return vr;co=1,vr=e;function e(t){var n=typeof t=="string"?t.charCodeAt(0):t;return n>=97&&n<=102||n>=65&&n<=70||n>=48&&n<=57}return vr}var wr,po;function cy(){if(po)return wr;po=1,wr=e;function e(t){var n=typeof t=="string"?t.charCodeAt(0):t;return n>=97&&n<=122||n>=65&&n<=90}return wr}var Sr,fo;function py(){if(fo)return Sr;fo=1;var e=cy(),t=ss();Sr=n;function n(r){return e(r)||t(r)}return Sr}var _r,ho;function dy(){if(ho)return _r;ho=1;var e,t=59;_r=n;function n(r){var i="&"+r+";",o;return e=e||document.createElement("i"),e.innerHTML=i,o=e.textContent,o.charCodeAt(o.length-1)===t&&r!=="semi"||o===i?!1:o}return _r}var Er,go;function fy(){if(go)return Er;go=1;var e=ly,t=sy,n=ss(),r=uy(),i=py(),o=dy();Er=ie;var a={}.hasOwnProperty,l=String.fromCharCode,s=Function.prototype,u={warning:null,reference:null,text:null,warningContext:null,referenceContext:null,textContext:null,position:{},additional:null,attribute:!1,nonTerminated:!0},p=9,c=10,f=12,d=32,g=38,k=59,S=60,x=61,v=35,b=88,_=120,C=65533,m="named",T="hexadecimal",j="decimal",A={};A[T]=16,A[j]=10;var E={};E[m]=i,E[j]=n,E[T]=r;var R=1,M=2,H=3,P=4,z=5,G=6,J=7,U={};U[R]="Named character references must be terminated by a semicolon",U[M]="Numeric character references must be terminated by a semicolon",U[H]="Named character references cannot be empty",U[P]="Numeric character references cannot be empty",U[z]="Named character references must be known",U[G]="Numeric character references cannot be disallowed",U[J]="Numeric character references cannot be outside the permissible Unicode range";function ie(y,Z){var ee={},te,xe;Z||(Z={});for(xe in u)te=Z[xe],ee[xe]=te??u[xe];return(ee.position.indent||ee.position.start)&&(ee.indent=ee.position.indent||[],ee.position=ee.position.start),w(y,ee)}function w(y,Z){var ee=Z.additional,te=Z.nonTerminated,xe=Z.text,we=Z.reference,_e=Z.warning,Ce=Z.textContext,be=Z.referenceContext,qe=Z.warningContext,le=Z.position,ce=Z.indent||[],Ze=y.length,Ae=0,Xe=-1,Me=le.column||1,dt=le.line||1,Fe="",Qe=[],Ue,ft,He,se,L,D,B,V,re,ke,Te,ve,je,pe,Se,ze,Le,Ne,ye;for(typeof ee=="string"&&(ee=ee.charCodeAt(0)),ze=lt(),V=_e?Nn:s,Ae--,Ze++;++Ae65535&&(D-=65536,ke+=l(D>>>10|55296),D=56320|D&1023),D=ke+l(D))):pe!==m&&V(P,Ne)),D?(tn(),ze=lt(),Ae=ye-1,Me+=ye-je+1,Qe.push(D),Le=lt(),Le.offset++,we&&we.call(be,D,{start:ze,end:Le},y.slice(je-1,ye)),ze=Le):(se=y.slice(je-1,ye),Fe+=se,Me+=se.length,Ae=ye-1)}else L===10&&(dt++,Xe++,Me=0),L===L?(Fe+=l(L),Me++):tn();return Qe.join("");function lt(){return{line:dt,column:Me,offset:Ae+(le.offset||0)}}function Nn(ht,gt){var mt=lt();mt.column+=gt,mt.offset+=gt,_e.call(qe,U[ht],mt,ht)}function tn(){Fe&&(Qe.push(Fe),xe&&xe.call(Ce,Fe,{start:ze,end:lt()}),Fe="")}}function K(y){return y>=55296&&y<=57343||y>1114111}function Y(y){return y>=1&&y<=8||y===11||y>=13&&y<=31||y>=127&&y<=159||y>=64976&&y<=65007||(y&65535)===65535||(y&65535)===65534}return Er}var Cr={exports:{}},mo;function hy(){return mo||(mo=1,(function(e){var t=typeof window<"u"?window:typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?self:{};var n=(function(r){var i=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,o=0,a={},l={manual:r.Prism&&r.Prism.manual,disableWorkerMessageHandler:r.Prism&&r.Prism.disableWorkerMessageHandler,util:{encode:function v(b){return b instanceof s?new s(b.type,v(b.content),b.alias):Array.isArray(b)?b.map(v):b.replace(/&/g,"&").replace(/"u")return null;if("currentScript"in document)return document.currentScript;try{throw new Error}catch(C){var v=(/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(C.stack)||[])[1];if(v){var b=document.getElementsByTagName("script");for(var _ in b)if(b[_].src==v)return b[_]}return null}},isActive:function(v,b,_){for(var C="no-"+b;v;){var m=v.classList;if(m.contains(b))return!0;if(m.contains(C))return!1;v=v.parentElement}return!!_}},languages:{plain:a,plaintext:a,text:a,txt:a,extend:function(v,b){var _=l.util.clone(l.languages[v]);for(var C in b)_[C]=b[C];return _},insertBefore:function(v,b,_,C){C=C||l.languages;var m=C[v],T={};for(var j in m)if(m.hasOwnProperty(j)){if(j==b)for(var A in _)_.hasOwnProperty(A)&&(T[A]=_[A]);_.hasOwnProperty(j)||(T[j]=m[j])}var E=C[v];return C[v]=T,l.languages.DFS(l.languages,function(R,M){M===E&&R!=v&&(this[R]=T)}),T},DFS:function v(b,_,C,m){m=m||{};var T=l.util.objId;for(var j in b)if(b.hasOwnProperty(j)){_.call(b,j,b[j],C||j);var A=b[j],E=l.util.type(A);E==="Object"&&!m[T(A)]?(m[T(A)]=!0,v(A,_,null,m)):E==="Array"&&!m[T(A)]&&(m[T(A)]=!0,v(A,_,j,m))}}},plugins:{},highlightAll:function(v,b){l.highlightAllUnder(document,v,b)},highlightAllUnder:function(v,b,_){var C={callback:_,container:v,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};l.hooks.run("before-highlightall",C),C.elements=Array.prototype.slice.apply(C.container.querySelectorAll(C.selector)),l.hooks.run("before-all-elements-highlight",C);for(var m=0,T;T=C.elements[m++];)l.highlightElement(T,b===!0,C.callback)},highlightElement:function(v,b,_){var C=l.util.getLanguage(v),m=l.languages[C];l.util.setLanguage(v,C);var T=v.parentElement;T&&T.nodeName.toLowerCase()==="pre"&&l.util.setLanguage(T,C);var j=v.textContent,A={element:v,language:C,grammar:m,code:j};function E(M){A.highlightedCode=M,l.hooks.run("before-insert",A),A.element.innerHTML=A.highlightedCode,l.hooks.run("after-highlight",A),l.hooks.run("complete",A),_&&_.call(A.element)}if(l.hooks.run("before-sanity-check",A),T=A.element.parentElement,T&&T.nodeName.toLowerCase()==="pre"&&!T.hasAttribute("tabindex")&&T.setAttribute("tabindex","0"),!A.code){l.hooks.run("complete",A),_&&_.call(A.element);return}if(l.hooks.run("before-highlight",A),!A.grammar){E(l.util.encode(A.code));return}if(b&&r.Worker){var R=new Worker(l.filename);R.onmessage=function(M){E(M.data)},R.postMessage(JSON.stringify({language:A.language,code:A.code,immediateClose:!0}))}else E(l.highlight(A.code,A.grammar,A.language))},highlight:function(v,b,_){var C={code:v,grammar:b,language:_};if(l.hooks.run("before-tokenize",C),!C.grammar)throw new Error('The language "'+C.language+'" has no grammar.');return C.tokens=l.tokenize(C.code,C.grammar),l.hooks.run("after-tokenize",C),s.stringify(l.util.encode(C.tokens),C.language)},tokenize:function(v,b){var _=b.rest;if(_){for(var C in _)b[C]=_[C];delete b.rest}var m=new c;return f(m,m.head,v),p(v,m,b,m.head,0),g(m)},hooks:{all:{},add:function(v,b){var _=l.hooks.all;_[v]=_[v]||[],_[v].push(b)},run:function(v,b){var _=l.hooks.all[v];if(!(!_||!_.length))for(var C=0,m;m=_[C++];)m(b)}},Token:s};r.Prism=l;function s(v,b,_,C){this.type=v,this.content=b,this.alias=_,this.length=(C||"").length|0}s.stringify=function v(b,_){if(typeof b=="string")return b;if(Array.isArray(b)){var C="";return b.forEach(function(E){C+=v(E,_)}),C}var m={type:b.type,content:v(b.content,_),tag:"span",classes:["token",b.type],attributes:{},language:_},T=b.alias;T&&(Array.isArray(T)?Array.prototype.push.apply(m.classes,T):m.classes.push(T)),l.hooks.run("wrap",m);var j="";for(var A in m.attributes)j+=" "+A+'="'+(m.attributes[A]||"").replace(/"/g,""")+'"';return"<"+m.tag+' class="'+m.classes.join(" ")+'"'+j+">"+m.content+""};function u(v,b,_,C){v.lastIndex=b;var m=v.exec(_);if(m&&C&&m[1]){var T=m[1].length;m.index+=T,m[0]=m[0].slice(T)}return m}function p(v,b,_,C,m,T){for(var j in _)if(!(!_.hasOwnProperty(j)||!_[j])){var A=_[j];A=Array.isArray(A)?A:[A];for(var E=0;E=T.reach);ie+=U.value.length,U=U.next){var w=U.value;if(b.length>v.length)return;if(!(w instanceof s)){var K=1,Y;if(P){if(Y=u(J,ie,v,H),!Y||Y.index>=v.length)break;var te=Y.index,y=Y.index+Y[0].length,Z=ie;for(Z+=U.value.length;te>=Z;)U=U.next,Z+=U.value.length;if(Z-=U.value.length,ie=Z,U.value instanceof s)continue;for(var ee=U;ee!==b.tail&&(ZT.reach&&(T.reach=Ce);var be=U.prev;we&&(be=f(b,be,we),ie+=we.length),d(b,be,K);var qe=new s(j,M?l.tokenize(xe,M):xe,z,xe);if(U=f(b,be,qe),_e&&f(b,U,_e),K>1){var le={cause:j+","+E,reach:Ce};p(v,b,_,U.prev,ie,le),T&&le.reach>T.reach&&(T.reach=le.reach)}}}}}}function c(){var v={value:null,prev:null,next:null},b={value:null,prev:v,next:null};v.next=b,this.head=v,this.tail=b,this.length=0}function f(v,b,_){var C=b.next,m={value:_,prev:b,next:C};return b.next=m,C.prev=m,v.length++,m}function d(v,b,_){for(var C=b.next,m=0;m<_&&C!==v.tail;m++)C=C.next;b.next=C,C.prev=b,v.length-=m}function g(v){for(var b=[],_=v.head.next;_!==v.tail;)b.push(_.value),_=_.next;return b}if(!r.document)return r.addEventListener&&(l.disableWorkerMessageHandler||r.addEventListener("message",function(v){var b=JSON.parse(v.data),_=b.language,C=b.code,m=b.immediateClose;r.postMessage(l.highlight(C,l.languages[_],_)),m&&r.close()},!1)),l;var k=l.util.currentScript();k&&(l.filename=k.src,k.hasAttribute("data-manual")&&(l.manual=!0));function S(){l.manual||l.highlightAll()}if(!l.manual){var x=document.readyState;x==="loading"||x==="interactive"&&k&&k.defer?document.addEventListener("DOMContentLoaded",S):window.requestAnimationFrame?window.requestAnimationFrame(S):window.setTimeout(S,16)}return l})(t);e.exports&&(e.exports=n),typeof mn<"u"&&(mn.Prism=n)})(Cr)),Cr.exports}var Tr,bo;function us(){if(bo)return Tr;bo=1,Tr=e,e.displayName="markup",e.aliases=["html","mathml","svg","xml","ssml","atom","rss"];function e(t){t.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},t.languages.markup.tag.inside["attr-value"].inside.entity=t.languages.markup.entity,t.languages.markup.doctype.inside["internal-subset"].inside=t.languages.markup,t.hooks.add("wrap",function(n){n.type==="entity"&&(n.attributes.title=n.content.value.replace(/&/,"&"))}),Object.defineProperty(t.languages.markup.tag,"addInlined",{value:function(r,i){var o={};o["language-"+i]={pattern:/(^$)/i,lookbehind:!0,inside:t.languages[i]},o.cdata=/^$/i;var a={"included-cdata":{pattern://i,inside:o}};a["language-"+i]={pattern:/[\s\S]+/,inside:t.languages[i]};var l={};l[r]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,function(){return r}),"i"),lookbehind:!0,greedy:!0,inside:a},t.languages.insertBefore("markup","cdata",l)}}),Object.defineProperty(t.languages.markup.tag,"addAttribute",{value:function(n,r){t.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+n+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[r,"language-"+r],inside:t.languages[r]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),t.languages.html=t.languages.markup,t.languages.mathml=t.languages.markup,t.languages.svg=t.languages.markup,t.languages.xml=t.languages.extend("markup",{}),t.languages.ssml=t.languages.xml,t.languages.atom=t.languages.xml,t.languages.rss=t.languages.xml}return Tr}var Ar,yo;function cs(){if(yo)return Ar;yo=1,Ar=e,e.displayName="css",e.aliases=[];function e(t){(function(n){var r=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;n.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+r.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+r.source+"$"),alias:"url"}}},selector:{pattern:RegExp(`(^|[{}\\s])[^{}\\s](?:[^{};"'\\s]|\\s+(?![\\s{])|`+r.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:r,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},n.languages.css.atrule.inside.rest=n.languages.css;var i=n.languages.markup;i&&(i.tag.addInlined("style","css"),i.tag.addAttribute("style","css"))})(t)}return Ar}var Lr,xo;function gy(){if(xo)return Lr;xo=1,Lr=e,e.displayName="clike",e.aliases=[];function e(t){t.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}}return Lr}var Nr,ko;function ps(){if(ko)return Nr;ko=1,Nr=e,e.displayName="javascript",e.aliases=["js"];function e(t){t.languages.javascript=t.languages.extend("clike",{"class-name":[t.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+(/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source)+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),t.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,t.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:t.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:t.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:t.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:t.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:t.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),t.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:t.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),t.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),t.languages.markup&&(t.languages.markup.tag.addInlined("script","javascript"),t.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),t.languages.js=t.languages.javascript}return Nr}var Ir,vo;function my(){if(vo)return Ir;vo=1;var e=typeof globalThis=="object"?globalThis:typeof self=="object"?self:typeof window=="object"?window:typeof mn=="object"?mn:{},t=C();e.Prism={manual:!0,disableWorkerMessageHandler:!0};var n=sm(),r=fy(),i=hy(),o=us(),a=cs(),l=gy(),s=ps();t();var u={}.hasOwnProperty;function p(){}p.prototype=i;var c=new p;Ir=c,c.highlight=g,c.register=f,c.alias=d,c.registered=k,c.listLanguages=S,f(o),f(a),f(l),f(s),c.util.encode=b,c.Token.stringify=x;function f(m){if(typeof m!="function"||!m.displayName)throw new Error("Expected `function` for `grammar`, got `"+m+"`");c.languages[m.displayName]===void 0&&m(c)}function d(m,T){var j=c.languages,A=m,E,R,M,H;T&&(A={},A[m]=T);for(E in A)for(R=A[E],R=typeof R=="string"?[R]:R,M=R.length,H=-1;++H?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}}return jr}var Rr,So;function ds(){if(So)return Rr;So=1,Rr=e,e.displayName="c",e.aliases=[];function e(t){t.languages.c=t.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),t.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),t.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},t.languages.c.string],char:t.languages.c.char,comment:t.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:t.languages.c}}}}),t.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete t.languages.c.boolean}return Rr}var Or,_o;function xy(){if(_o)return Or;_o=1;var e=ds();Or=t,t.displayName="cpp",t.aliases=[];function t(n){n.register(e),(function(r){var i=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,o=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,function(){return i.source});r.languages.cpp=r.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,function(){return i.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:i,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),r.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,function(){return o})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),r.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:r.languages.cpp}}}}),r.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),r.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:r.languages.extend("cpp",{})}}),r.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},r.languages.cpp["base-clause"])})(n)}return Or}var Dr,Eo;function ky(){if(Eo)return Dr;Eo=1,Dr=e,e.displayName="csharp",e.aliases=["dotnet","cs"];function e(t){(function(n){function r(K,Y){return K.replace(/<<(\d+)>>/g,function(y,Z){return"(?:"+Y[+Z]+")"})}function i(K,Y,y){return RegExp(r(K,Y),"")}function o(K,Y){for(var y=0;y>/g,function(){return"(?:"+K+")"});return K.replace(/<>/g,"[^\\s\\S]")}var a={type:"bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",typeDeclaration:"class enum interface record struct",contextual:"add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",other:"abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield"};function l(K){return"\\b(?:"+K.trim().replace(/ /g,"|")+")\\b"}var s=l(a.typeDeclaration),u=RegExp(l(a.type+" "+a.typeDeclaration+" "+a.contextual+" "+a.other)),p=l(a.typeDeclaration+" "+a.contextual+" "+a.other),c=l(a.type+" "+a.typeDeclaration+" "+a.other),f=o(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source,2),d=o(/\((?:[^()]|<>)*\)/.source,2),g=/@?\b[A-Za-z_]\w*\b/.source,k=r(/<<0>>(?:\s*<<1>>)?/.source,[g,f]),S=r(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[p,k]),x=/\[\s*(?:,\s*)*\]/.source,v=r(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[S,x]),b=r(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[f,d,x]),_=r(/\(<<0>>+(?:,<<0>>+)+\)/.source,[b]),C=r(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[_,S,x]),m={keyword:u,punctuation:/[<>()?,.:[\]]/},T=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,j=/"(?:\\.|[^\\"\r\n])*"/.source,A=/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source;n.languages.csharp=n.languages.extend("clike",{string:[{pattern:i(/(^|[^$\\])<<0>>/.source,[A]),lookbehind:!0,greedy:!0},{pattern:i(/(^|[^@$\\])<<0>>/.source,[j]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:i(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[S]),lookbehind:!0,inside:m},{pattern:i(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[g,C]),lookbehind:!0,inside:m},{pattern:i(/(\busing\s+)<<0>>(?=\s*=)/.source,[g]),lookbehind:!0},{pattern:i(/(\b<<0>>\s+)<<1>>/.source,[s,k]),lookbehind:!0,inside:m},{pattern:i(/(\bcatch\s*\(\s*)<<0>>/.source,[S]),lookbehind:!0,inside:m},{pattern:i(/(\bwhere\s+)<<0>>/.source,[g]),lookbehind:!0},{pattern:i(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[v]),lookbehind:!0,inside:m},{pattern:i(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[C,c,g]),inside:m}],keyword:u,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),n.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),n.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:i(/([(,]\s*)<<0>>(?=\s*:)/.source,[g]),lookbehind:!0,alias:"punctuation"}}),n.languages.insertBefore("csharp","class-name",{namespace:{pattern:i(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[g]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:i(/(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source,[d]),lookbehind:!0,alias:"class-name",inside:m},"return-type":{pattern:i(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[C,S]),inside:m,alias:"class-name"},"constructor-invocation":{pattern:i(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[C]),lookbehind:!0,inside:m,alias:"class-name"},"generic-method":{pattern:i(/<<0>>\s*<<1>>(?=\s*\()/.source,[g,f]),inside:{function:i(/^<<0>>/.source,[g]),generic:{pattern:RegExp(f),alias:"class-name",inside:m}}},"type-list":{pattern:i(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[s,k,g,C,u.source,d,/\bnew\s*\(\s*\)/.source]),lookbehind:!0,inside:{"record-arguments":{pattern:i(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source,[k,d]),lookbehind:!0,greedy:!0,inside:n.languages.csharp},keyword:u,"class-name":{pattern:RegExp(C),greedy:!0,inside:m},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var E=j+"|"+T,R=r(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[E]),M=o(r(/[^"'/()]|<<0>>|\(<>*\)/.source,[R]),2),H=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,P=r(/<<0>>(?:\s*\(<<1>>*\))?/.source,[S,M]);n.languages.insertBefore("csharp","class-name",{attribute:{pattern:i(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[H,P]),lookbehind:!0,greedy:!0,inside:{target:{pattern:i(/^<<0>>(?=\s*:)/.source,[H]),alias:"keyword"},"attribute-arguments":{pattern:i(/\(<<0>>*\)/.source,[M]),inside:n.languages.csharp},"class-name":{pattern:RegExp(S),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var z=/:[^}\r\n]+/.source,G=o(r(/[^"'/()]|<<0>>|\(<>*\)/.source,[R]),2),J=r(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[G,z]),U=o(r(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source,[E]),2),ie=r(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[U,z]);function w(K,Y){return{interpolation:{pattern:i(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[K]),lookbehind:!0,inside:{"format-string":{pattern:i(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[Y,z]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:n.languages.csharp}}},string:/[\s\S]+/}}n.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:i(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[J]),lookbehind:!0,greedy:!0,inside:w(J,G)},{pattern:i(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[ie]),lookbehind:!0,greedy:!0,inside:w(ie,U)}],char:{pattern:RegExp(T),greedy:!0}}),n.languages.dotnet=n.languages.cs=n.languages.csharp})(t)}return Dr}var Mr,Co;function vy(){if(Co)return Mr;Co=1,Mr=e,e.displayName="bash",e.aliases=["shell"];function e(t){(function(n){var r="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",i={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},o={bash:i,environment:{pattern:RegExp("\\$"+r),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+r),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};n.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+r),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:o},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:i}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:o},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:o.entity}}],environment:{pattern:RegExp("\\$?"+r),alias:"constant"},variable:o.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},i.inside=n.languages.bash;for(var a=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],l=o.variable[1].inside,s=0;s|[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),n.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var r={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:n.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete n.languages.ruby.function;var i="(?:"+[/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,/\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,/<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|")+")",o=/(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;n.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp(/%r/.source+i+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp(/(^|[^:]):/.source+o),lookbehind:!0,greedy:!0},{pattern:RegExp(/([\r\n{(,][ \t]*)/.source+o+/(?=:(?!:))/.source),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),n.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp(/%[qQiIwWs]?/.source+i),greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp(/%x/.source+i),greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete n.languages.ruby.string,n.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),n.languages.rb=n.languages.ruby})(t)}return Fr}var zr,Ao;function Sy(){if(Ao)return zr;Ao=1,zr=e,e.displayName="diff",e.aliases=[];function e(t){(function(n){n.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var r={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(r).forEach(function(i){var o=r[i],a=[];/^\w+$/.test(i)||a.push(/\w+/.exec(i)[0]),i==="diff"&&a.push("bold"),n.languages.diff[i]={pattern:RegExp("^(?:["+o+`].*(?:\r ?| -|(?![\\s\\S])))+`,"m"),alias:a,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(i)[0]}}}}),Object.defineProperty(n.languages.diff,"PREFIXES",{value:r})})(t)}return zr}var Pr,Lo;function _b(){if(Lo)return Pr;Lo=1,Pr=e,e.displayName="markupTemplating",e.aliases=[];function e(t){(function(n){function r(i,o){return"___"+i.toUpperCase()+o+"___"}Object.defineProperties(n.languages["markup-templating"]={},{buildPlaceholders:{value:function(i,o,a,l){if(i.language===o){var s=i.tokenStack=[];i.code=i.code.replace(a,function(u){if(typeof l=="function"&&!l(u))return u;for(var p=s.length,c;i.code.indexOf(c=r(o,p))!==-1;)++p;return s[p]=u,c}),i.grammar=n.languages.markup}}},tokenizePlaceholders:{value:function(i,o){if(i.language!==o||!i.tokenStack)return;i.grammar=n.languages[o];var a=0,l=Object.keys(i.tokenStack);function s(u){for(var p=0;p=l.length);p++){var c=u[p];if(typeof c=="string"||c.content&&typeof c.content=="string"){var f=l[a],d=i.tokenStack[f],g=typeof c=="string"?c:c.content,k=r(o,f),S=g.indexOf(k);if(S>-1){++a;var x=g.substring(0,S),v=new n.Token(o,n.tokenize(d,i.grammar),"language-"+o,d),y=g.substring(S+k.length),_=[];x&&_.push.apply(_,s([x])),_.push(v),y&&_.push.apply(_,s([y])),typeof c=="string"?u.splice.apply(u,[p,1].concat(_)):c.content=_}}else c.content&&s(c.content)}return u}s(i.tokens)}}})})(t)}return Pr}var Br,No;function Eb(){if(No)return Br;No=1,Br=e,e.displayName="go",e.aliases=[];function e(t){t.languages.go=t.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),t.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete t.languages.go["class-name"]}return Br}var $r,Io;function Cb(){if(Io)return $r;Io=1,$r=e,e.displayName="java",e.aliases=[];function e(t){(function(n){var r=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,i=/(^|[^\w.])(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,o={pattern:RegExp(i+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};n.languages.java=n.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[o,{pattern:RegExp(i+/[A-Z]\w*(?=\s+\w+\s*[;,=()])/.source),lookbehind:!0,inside:o.inside}],keyword:r,function:[n.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),n.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),n.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":o,keyword:r,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,function(){return r.source})),lookbehind:!0,inside:{punctuation:/\./}}})})(t)}return $r}var qr,jo;function fs(){if(jo)return qr;jo=1,qr=e,e.displayName="typescript",e.aliases=["ts"];function e(t){(function(n){n.languages.typescript=n.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),n.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete n.languages.typescript.parameter,delete n.languages.typescript["literal-property"];var r=n.languages.extend("typescript",{});delete r["class-name"],n.languages.typescript["class-name"].inside=r,n.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:r}}}}),n.languages.ts=n.languages.typescript})(t)}return qr}var Ur,Ro;function Tb(){if(Ro)return Ur;Ro=1,Ur=e,e.displayName="json",e.aliases=["webmanifest"];function e(t){t.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},t.languages.webmanifest=t.languages.json}return Ur}var Hr,Oo;function hs(){if(Oo)return Hr;Oo=1,Hr=e,e.displayName="jsx",e.aliases=[];function e(t){(function(n){var r=n.util.clone(n.languages.javascript),i=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,o=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,a=/(?:\{*\.{3}(?:[^{}]|)*\})/.source;function l(p,c){return p=p.replace(//g,function(){return i}).replace(//g,function(){return o}).replace(//g,function(){return a}),RegExp(p,c)}a=l(a).source,n.languages.jsx=n.languages.extend("markup",r),n.languages.jsx.tag.pattern=l(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),n.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,n.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,n.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,n.languages.jsx.tag.inside.comment=r.comment,n.languages.insertBefore("inside","attr-name",{spread:{pattern:l(//.source),inside:n.languages.jsx}},n.languages.jsx.tag),n.languages.insertBefore("inside","special-attr",{script:{pattern:l(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:n.languages.jsx}}},n.languages.jsx.tag);var s=function(p){return p?typeof p=="string"?p:typeof p.content=="string"?p.content:p.content.map(s).join(""):""},u=function(p){for(var c=[],f=0;f0&&c[c.length-1].tagName===s(d.content[0].content[1])&&c.pop():d.content[d.content.length-1].content==="/>"||c.push({tagName:s(d.content[0].content[1]),openedBraces:0}):c.length>0&&d.type==="punctuation"&&d.content==="{"?c[c.length-1].openedBraces++:c.length>0&&c[c.length-1].openedBraces>0&&d.type==="punctuation"&&d.content==="}"?c[c.length-1].openedBraces--:g=!0),(g||typeof d=="string")&&c.length>0&&c[c.length-1].openedBraces===0){var k=s(d);f0&&(typeof p[f-1]=="string"||p[f-1].type==="plain-text")&&(k=s(p[f-1])+k,p.splice(f-1,1),f--),p[f]=new n.Token("plain-text",k,null,k)}d.content&&typeof d.content!="string"&&u(d.content)}};n.hooks.add("after-tokenize",function(p){p.language!=="jsx"&&p.language!=="tsx"||u(p.tokens)})})(t)}return Hr}var Wr,Do;function Ab(){if(Do)return Wr;Do=1,Wr=e,e.displayName="kotlin",e.aliases=["kt","kts"];function e(t){(function(n){n.languages.kotlin=n.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete n.languages.kotlin["class-name"];var r={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:n.languages.kotlin}};n.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:r},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:r},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete n.languages.kotlin.string,n.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),n.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),n.languages.kt=n.languages.kotlin,n.languages.kts=n.languages.kotlin})(t)}return Wr}var Vr,Mo;function Lb(){if(Mo)return Vr;Mo=1;var e=_b();Vr=t,t.displayName="php",t.aliases=[];function t(n){n.register(e),(function(r){var i=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,o=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],a=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,l=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;r.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:i,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s+)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:o,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:a,operator:l,punctuation:s};var u={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:r.languages.php},p=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:u}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:u}}];r.languages.insertBefore("php","variable",{string:p,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:i,string:p,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:o,number:a,operator:l,punctuation:s}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),r.hooks.add("before-tokenize",function(c){if(/<\?/.test(c.code)){var f=/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g;r.languages["markup-templating"].buildPlaceholders(c,"php",f)}}),r.hooks.add("after-tokenize",function(c){r.languages["markup-templating"].tokenizePlaceholders(c,"php")})})(n)}return Vr}var Gr,Fo;function Nb(){if(Fo)return Gr;Fo=1,Gr=e,e.displayName="markdown",e.aliases=["md"];function e(t){(function(n){var r=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function i(f){return f=f.replace(//g,function(){return r}),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+f+")")}var o=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,function(){return o}),l=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;n.languages.markdown=n.languages.extend("markup",{}),n.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:n.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+l+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+l+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(o),inside:n.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+l+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(o),alias:"important",inside:n.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:i(/\b__(?:(?!_)|_(?:(?!_))+_)+__\b|\*\*(?:(?!\*)|\*(?:(?!\*))+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:i(/\b_(?:(?!_)|__(?:(?!_))+__)+_\b|\*(?:(?!\*)|\*\*(?:(?!\*))+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:i(/(~~?)(?:(?!~))+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:i(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\]))+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach(function(f){["url","bold","italic","strike","code-snippet"].forEach(function(d){f!==d&&(n.languages.markdown[f].inside.content.inside[d]=n.languages.markdown[d])})}),n.hooks.add("after-tokenize",function(f){if(f.language!=="markdown"&&f.language!=="md")return;function d(g){if(!(!g||typeof g=="string"))for(var k=0,S=g.length;k",quot:'"'},p=String.fromCodePoint||String.fromCharCode;function c(f){var d=f.replace(s,"");return d=d.replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,function(g,k){if(k=k.toLowerCase(),k[0]==="#"){var S;return k[1]==="x"?S=parseInt(k.slice(2),16):S=Number(k.slice(1)),p(S)}else{var x=u[k];return x||g}}),d}n.languages.md=n.languages.markdown})(t)}return Gr}var Zr,zo;function Ib(){if(zo)return Zr;zo=1,Zr=e,e.displayName="python",e.aliases=["py"];function e(t){t.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},t.languages.python["string-interpolation"].inside.interpolation.inside.rest=t.languages.python,t.languages.py=t.languages.python}return Zr}var Xr,Po;function jb(){if(Po)return Xr;Po=1,Xr=e,e.displayName="rust",e.aliases=[];function e(t){(function(n){for(var r=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|)*\*\//.source,i=0;i<2;i++)r=r.replace(//g,function(){return r});r=r.replace(//g,function(){return/[^\s\S]/.source}),n.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+r),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},n.languages.rust["closure-params"].inside.rest=n.languages.rust,n.languages.rust.attribute.inside.string=n.languages.rust.string})(t)}return Xr}var Kr,Bo;function Rb(){if(Bo)return Kr;Bo=1,Kr=e,e.displayName="swift",e.aliases=[];function e(t){t.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp(/(^|[^"#])/.source+"(?:"+/"(?:\\(?:\((?:[^()]|\([^()]*\))*\)|\r\n|[^(])|[^\\\r\n"])*"/.source+"|"+/"""(?:\\(?:\((?:[^()]|\([^()]*\))*\)|[^(])|[^\\"]|"(?!""))*"""/.source+")"+/(?!["#])/.source),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp(/(^|[^"#])(#+)/.source+"(?:"+/"(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|\r\n|[^#])|[^\\\r\n])*?"/.source+"|"+/"""(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|[^#])|[^\\])*?"""/.source+")\\2"),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp(/#/.source+"(?:"+(/(?:elseif|if)\b/.source+"(?:[ ]*"+/(?:![ \t]*)?(?:\b\w+\b(?:[ \t]*\((?:[^()]|\([^()]*\))*\))?|\((?:[^()]|\([^()]*\))*\))(?:[ \t]*(?:&&|\|\|))?/.source+")+")+"|"+/(?:else|endif)\b/.source+")"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},t.languages.swift["string-literal"].forEach(function(n){n.inside.interpolation.inside=t.languages.swift})}return Kr}var Yr,$o;function Ob(){if($o)return Yr;$o=1,Yr=e,e.displayName="yaml",e.aliases=["yml"];function e(t){(function(n){var r=/[*&][^\s[\]{},]+/,i=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,o="(?:"+i.source+"(?:[ ]+"+r.source+")?|"+r.source+"(?:[ ]+"+i.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*/.source.replace(//g,function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source}),l=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function s(u,p){p=(p||"").replace(/m/g,"")+"m";var c=/([:\-,[{]\s*(?:\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<>/g,function(){return o}).replace(/<>/g,function(){return u});return RegExp(c,p)}n.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<>/g,function(){return o})),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\s*:\s)/.source.replace(/<>/g,function(){return o}).replace(/<>/g,function(){return"(?:"+a+"|"+l+")"})),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:s(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:s(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:s(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:s(l),lookbehind:!0,greedy:!0},number:{pattern:s(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:i,important:r,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},n.languages.yml=n.languages.yaml})(t)}return Yr}var Qr,qo;function Db(){if(qo)return Qr;qo=1;var e=hs(),t=fs();Qr=n,n.displayName="tsx",n.aliases=[];function n(r){r.register(e),r.register(t),(function(i){var o=i.util.clone(i.languages.typescript);i.languages.tsx=i.languages.extend("jsx",o),delete i.languages.tsx.parameter,delete i.languages.tsx["literal-property"];var a=i.languages.tsx.tag;a.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+a.pattern.source+")",a.pattern.flags),a.lookbehind=!0})(r)}return Qr}const Mb={'code[class*="language-"]':{color:"#393A34",fontFamily:'"Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",fontSize:".9em",lineHeight:"1.2em",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none"},'pre[class*="language-"]':{color:"#393A34",fontFamily:'"Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",fontSize:".9em",lineHeight:"1.2em",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none",padding:"1em",margin:".5em 0",overflow:"auto",border:"1px solid #dddddd",backgroundColor:"white"},'pre > code[class*="language-"]':{fontSize:"1em"},'pre[class*="language-"]::-moz-selection':{background:"#C1DEF1"},'pre[class*="language-"] ::-moz-selection':{background:"#C1DEF1"},'code[class*="language-"]::-moz-selection':{background:"#C1DEF1"},'code[class*="language-"] ::-moz-selection':{background:"#C1DEF1"},'pre[class*="language-"]::selection':{background:"#C1DEF1"},'pre[class*="language-"] ::selection':{background:"#C1DEF1"},'code[class*="language-"]::selection':{background:"#C1DEF1"},'code[class*="language-"] ::selection':{background:"#C1DEF1"},':not(pre) > code[class*="language-"]':{padding:".2em",paddingTop:"1px",paddingBottom:"1px",background:"#f8f8f8",border:"1px solid #dddddd"},comment:{color:"#008000",fontStyle:"italic"},prolog:{color:"#008000",fontStyle:"italic"},doctype:{color:"#008000",fontStyle:"italic"},cdata:{color:"#008000",fontStyle:"italic"},namespace:{Opacity:".7"},string:{color:"#A31515"},punctuation:{color:"#393A34"},operator:{color:"#393A34"},url:{color:"#36acaa"},symbol:{color:"#36acaa"},number:{color:"#36acaa"},boolean:{color:"#36acaa"},variable:{color:"#36acaa"},constant:{color:"#36acaa"},inserted:{color:"#36acaa"},atrule:{color:"#0000ff"},keyword:{color:"#0000ff"},"attr-value":{color:"#0000ff"},".language-autohotkey .token.selector":{color:"#0000ff"},".language-json .token.boolean":{color:"#0000ff"},".language-json .token.number":{color:"#0000ff"},'code[class*="language-css"]':{color:"#0000ff"},function:{color:"#393A34"},deleted:{color:"#9a050f"},".language-autohotkey .token.tag":{color:"#9a050f"},selector:{color:"#800000"},".language-autohotkey .token.keyword":{color:"#00009f"},important:{color:"#e90",fontWeight:"bold"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"},"class-name":{color:"#2B91AF"},".language-json .token.property":{color:"#2B91AF"},tag:{color:"#800000"},"attr-name":{color:"#ff0000"},property:{color:"#ff0000"},regex:{color:"#ff0000"},entity:{color:"#ff0000"},"directive.tag.tag":{background:"#ffff00",color:"#393A34"},".line-numbers.line-numbers .line-numbers-rows":{borderRightColor:"#a5a5a5"},".line-numbers .line-numbers-rows > span:before":{color:"#2B91AF"},".line-highlight.line-highlight":{background:"linear-gradient(to right, rgba(193, 222, 241, 0.2) 70%, rgba(221, 222, 241, 0))"}},Fb={'pre[class*="language-"]':{color:"#d4d4d4",fontSize:"13px",textShadow:"none",fontFamily:'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",lineHeight:"1.5",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none",padding:"1em",margin:".5em 0",overflow:"auto",background:"#1e1e1e"},'code[class*="language-"]':{color:"#d4d4d4",fontSize:"13px",textShadow:"none",fontFamily:'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",lineHeight:"1.5",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none"},'pre[class*="language-"]::selection':{textShadow:"none",background:"#264F78"},'code[class*="language-"]::selection':{textShadow:"none",background:"#264F78"},'pre[class*="language-"] *::selection':{textShadow:"none",background:"#264F78"},'code[class*="language-"] *::selection':{textShadow:"none",background:"#264F78"},':not(pre) > code[class*="language-"]':{padding:".1em .3em",borderRadius:".3em",color:"#db4c69",background:"#1e1e1e"},".namespace":{Opacity:".7"},"doctype.doctype-tag":{color:"#569CD6"},"doctype.name":{color:"#9cdcfe"},comment:{color:"#6a9955"},prolog:{color:"#6a9955"},punctuation:{color:"#d4d4d4"},".language-html .language-css .token.punctuation":{color:"#d4d4d4"},".language-html .language-javascript .token.punctuation":{color:"#d4d4d4"},property:{color:"#9cdcfe"},tag:{color:"#569cd6"},boolean:{color:"#569cd6"},number:{color:"#b5cea8"},constant:{color:"#9cdcfe"},symbol:{color:"#b5cea8"},inserted:{color:"#b5cea8"},unit:{color:"#b5cea8"},selector:{color:"#d7ba7d"},"attr-name":{color:"#9cdcfe"},string:{color:"#ce9178"},char:{color:"#ce9178"},builtin:{color:"#ce9178"},deleted:{color:"#ce9178"},".language-css .token.string.url":{textDecoration:"underline"},operator:{color:"#d4d4d4"},entity:{color:"#569cd6"},"operator.arrow":{color:"#569CD6"},atrule:{color:"#ce9178"},"atrule.rule":{color:"#c586c0"},"atrule.url":{color:"#9cdcfe"},"atrule.url.function":{color:"#dcdcaa"},"atrule.url.punctuation":{color:"#d4d4d4"},keyword:{color:"#569CD6"},"keyword.module":{color:"#c586c0"},"keyword.control-flow":{color:"#c586c0"},function:{color:"#dcdcaa"},"function.maybe-class-name":{color:"#dcdcaa"},regex:{color:"#d16969"},important:{color:"#569cd6"},italic:{fontStyle:"italic"},"class-name":{color:"#4ec9b0"},"maybe-class-name":{color:"#4ec9b0"},console:{color:"#9cdcfe"},parameter:{color:"#9cdcfe"},interpolation:{color:"#9cdcfe"},"punctuation.interpolation-punctuation":{color:"#569cd6"},variable:{color:"#9cdcfe"},"imports.maybe-class-name":{color:"#9cdcfe"},"exports.maybe-class-name":{color:"#9cdcfe"},escape:{color:"#d7ba7d"},"tag.punctuation":{color:"#808080"},cdata:{color:"#808080"},"attr-value":{color:"#ce9178"},"attr-value.punctuation":{color:"#ce9178"},"attr-value.punctuation.attr-equals":{color:"#d4d4d4"},namespace:{color:"#4ec9b0"},'pre[class*="language-javascript"]':{color:"#9cdcfe"},'code[class*="language-javascript"]':{color:"#9cdcfe"},'pre[class*="language-jsx"]':{color:"#9cdcfe"},'code[class*="language-jsx"]':{color:"#9cdcfe"},'pre[class*="language-typescript"]':{color:"#9cdcfe"},'code[class*="language-typescript"]':{color:"#9cdcfe"},'pre[class*="language-tsx"]':{color:"#9cdcfe"},'code[class*="language-tsx"]':{color:"#9cdcfe"},'pre[class*="language-css"]':{color:"#ce9178"},'code[class*="language-css"]':{color:"#ce9178"},'pre[class*="language-html"]':{color:"#d4d4d4"},'code[class*="language-html"]':{color:"#d4d4d4"},".language-regex .token.anchor":{color:"#dcdcaa"},".language-html .token.punctuation":{color:"#808080"},'pre[class*="language-"] > code[class*="language-"]':{position:"relative",zIndex:"1"},".line-highlight.line-highlight":{background:"#f7ebc6",boxShadow:"inset 5px 0 0 #f7d87c",zIndex:"0"}};var zb=vb();const gs=me(zb);var Pb=ds();const Bb=me(Pb);var $b=xb();const qb=me($b);var Ub=kb();const ms=me(Ub);var Hb=cs();const Wb=me(Hb);var Vb=Sb();const Gb=me(Vb);var Zb=Eb();const Xb=me(Zb);var Kb=Cb();const Yb=me(Kb);var Qb=ps();const ys=me(Qb);var Jb=Tb();const ex=me(Jb);var tx=hs();const nx=me(tx);var rx=Ab();const ix=me(rx);var ax=Nb();const bs=me(ax);var ox=us();const Ui=me(ox);var lx=Lb();const sx=me(lx);var ux=Ib();const xs=me(ux);var cx=wb();const ks=me(cx);var px=jb();const dx=me(px);var fx=bb();const hx=me(fx);var gx=Rb();const mx=me(gx);var yx=Db();const bx=me(yx);var xx=fs();const vs=me(xx);var kx=Ob();const ws=me(kx);function Je(e,t){Ks(e)||t(e instanceof Error?e.message:String(e))}const vx={bash:gs,c:Bb,cpp:qb,csharp:ms,css:Wb,diff:Gb,go:Xb,java:Yb,javascript:ys,json:ex,jsx:nx,kotlin:ix,markdown:bs,markup:Ui,php:sx,python:xs,ruby:ks,rust:dx,sql:hx,swift:mx,tsx:bx,typescript:vs,yaml:ws};Object.entries(vx).forEach(([e,t])=>{$e.registerLanguage(e,t)});$e.registerLanguage("cs",ms);$e.registerLanguage("html",Ui);$e.registerLanguage("js",ys);$e.registerLanguage("md",bs);$e.registerLanguage("py",xs);$e.registerLanguage("rb",ks);$e.registerLanguage("sh",gs);$e.registerLanguage("ts",vs);$e.registerLanguage("xml",Ui);$e.registerLanguage("yml",ws);function Wt(e){return e<1e3?`${Math.round(e)}ms`:`${(e/1e3).toFixed(1)}s`}function Hi(e,t){return e==="en-US"&&t!==1?"s":""}function wx(e,t){if(!e||e.length<=t)return e;const n=t-3,r=Math.ceil(n*.6),i=n-r;return e.slice(0,r)+"..."+e.slice(-i)}function Jr(e){return e.replace(/#img:\S+\s*/g,"").replace(/\[Image:.*?\]\n(?:Path:.*?\n|Image ID:.*?\n)?/g,"").trim()}function Ss(e){if(navigator.clipboard?.writeText)return navigator.clipboard.writeText(e);const t=document.createElement("textarea");t.value=e,t.style.cssText="position:fixed;left:-9999px;top:-9999px;opacity:0",document.body.appendChild(t),t.select();try{document.execCommand("copy")}finally{document.body.removeChild(t)}return Promise.resolve()}const Sx=({code:e})=>{const[t,n]=N.useState(!1),r=async()=>{try{await Ss(e),n(!0),setTimeout(()=>n(!1),2e3)}catch{}};return h.jsx("button",{className:`copy-button${t?" copy-success":""}`,onClick:r,type:"button",children:t?h.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("polyline",{points:"20 6 9 17 4 12"})}):h.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),h.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})})},vn="computer://",yi="file://",Uo="{{workspaceFolder}}",bi="bitfun.mobile.last_selected_model_id",_x=new Set(["js","jsx","ts","tsx","mjs","cjs","mts","cts","py","pyw","pyi","rs","go","java","kt","kts","scala","groovy","c","cpp","cc","cxx","h","hpp","hxx","hh","cs","rb","php","swift","vue","svelte","css","scss","less","sass","json","jsonc","yaml","yml","toml","xml","md","mdx","rst","txt","sh","bash","zsh","fish","ps1","bat","cmd","sql","graphql","gql","proto","lock","env","ini","cfg","conf","cj","ets","editorconfig","gitignore","log"]),Ex=new Set(["pdf","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp","rtf","pages","numbers","key","png","jpg","jpeg","gif","bmp","svg","webp","ico","tiff","tif","zip","tar","gz","bz2","7z","rar","dmg","iso","xz","mp3","wav","ogg","flac","aac","m4a","wma","mp4","avi","mkv","mov","webm","wmv","flv","csv","tsv","sqlite","db","parquet","epub","mobi","apk","ipa","exe","msi","deb","rpm","ttf","otf","woff","woff2"]);function wn(e){let t=e;e.startsWith(vn)?t=e.slice(vn.length):e.startsWith(yi)?t=e.slice(yi.length):e.startsWith("file:")&&(t=e.slice(5)),t.startsWith(Uo)&&(t=t.slice(Uo.length),t.startsWith("/")&&(t=t.slice(1))),/^\/[A-Za-z]:[\\/]/.test(t)&&(t=t.slice(1));try{return decodeURIComponent(t)}catch{return t}}function Cx(e){if(!e||e==="/")return null;let t;if(e.startsWith(vn)||e.startsWith(yi)||e.startsWith("file:"))t=wn(e);else{if(e.includes("://")||e.startsWith("#")||e.startsWith("//"))return null;t=wn(e)}if(t.startsWith("/")&&t.split("/").filter(Boolean).length<2)return null;const n=t.split("/").pop()||"",r=n.lastIndexOf(".");if(r<=0)return null;const i=n.slice(r+1).toLowerCase();if(!i)return null;if(t.startsWith("/")){if(_x.has(i))return null}else if(!Ex.has(i))return null;return t}function Tx(e){return e>=1024*1024?`${(e/(1024*1024)).toFixed(1)} MB`:e>=1024?`${Math.round(e/1024)} KB`:`${e} B`}const ei=({size:e=20,style:t})=>h.jsxs("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",style:t,"aria-hidden":"true",children:[h.jsx("path",{d:"M15.3929 4.05365L14.8912 4.61112L15.3929 4.05365ZM19.3517 7.61654L18.85 8.17402L19.3517 7.61654ZM21.654 10.1541L20.9689 10.4592V10.4592L21.654 10.1541ZM3.17157 20.8284L3.7019 20.2981H3.7019L3.17157 20.8284ZM20.8284 20.8284L20.2981 20.2981L20.2981 20.2981L20.8284 20.8284ZM14 21.25H10V22.75H14V21.25ZM2.75 14V10H1.25V14H2.75ZM21.25 13.5629V14H22.75V13.5629H21.25ZM14.8912 4.61112L18.85 8.17402L19.8534 7.05907L15.8947 3.49618L14.8912 4.61112ZM22.75 13.5629C22.75 11.8745 22.7651 10.8055 22.3391 9.84897L20.9689 10.4592C21.2349 11.0565 21.25 11.742 21.25 13.5629H22.75ZM18.85 8.17402C20.2034 9.3921 20.7029 9.86199 20.9689 10.4592L22.3391 9.84897C21.9131 8.89241 21.1084 8.18853 19.8534 7.05907L18.85 8.17402ZM10.0298 2.75C11.6116 2.75 12.2085 2.76158 12.7405 2.96573L13.2779 1.5653C12.4261 1.23842 11.498 1.25 10.0298 1.25V2.75ZM15.8947 3.49618C14.8087 2.51878 14.1297 1.89214 13.2779 1.5653L12.7405 2.96573C13.2727 3.16993 13.7215 3.55836 14.8912 4.61112L15.8947 3.49618ZM10 21.25C8.09318 21.25 6.73851 21.2484 5.71085 21.1102C4.70476 20.975 4.12511 20.7213 3.7019 20.2981L2.64124 21.3588C3.38961 22.1071 4.33855 22.4392 5.51098 22.5969C6.66182 22.7516 8.13558 22.75 10 22.75V21.25ZM1.25 14C1.25 15.8644 1.24841 17.3382 1.40313 18.489C1.56076 19.6614 1.89288 20.6104 2.64124 21.3588L3.7019 20.2981C3.27869 19.8749 3.02502 19.2952 2.88976 18.2892C2.75159 17.2615 2.75 15.9068 2.75 14H1.25ZM14 22.75C15.8644 22.75 17.3382 22.7516 18.489 22.5969C19.6614 22.4392 20.6104 22.1071 21.3588 21.3588L20.2981 20.2981C19.8749 20.7213 19.2952 20.975 18.2892 21.1102C17.2615 21.2484 15.9068 21.25 14 21.25V22.75ZM21.25 14C21.25 15.9068 21.2484 17.2615 21.1102 18.2892C20.975 19.2952 20.7213 19.8749 20.2981 20.2981L21.3588 21.3588C22.1071 20.6104 22.4392 19.6614 22.5969 18.489C22.7516 17.3382 22.75 15.8644 22.75 14H21.25ZM2.75 10C2.75 8.09318 2.75159 6.73851 2.88976 5.71085C3.02502 4.70476 3.27869 4.12511 3.7019 3.7019L2.64124 2.64124C1.89288 3.38961 1.56076 4.33855 1.40313 5.51098C1.24841 6.66182 1.25 8.13558 1.25 10H2.75ZM10.0298 1.25C8.15538 1.25 6.67442 1.24842 5.51887 1.40307C4.34232 1.56054 3.39019 1.8923 2.64124 2.64124L3.7019 3.7019C4.12453 3.27928 4.70596 3.02525 5.71785 2.88982C6.75075 2.75158 8.11311 2.75 10.0298 2.75V1.25Z",fill:"currentColor"}),h.jsx("path",{d:"M6 14.5H14",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"}),h.jsx("path",{d:"M6 18H11.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"}),h.jsx("path",{d:"M13 2.5V5C13 7.35702 13 8.53553 13.7322 9.26777C14.4645 10 15.643 10 18 10H22",stroke:"currentColor",strokeWidth:"1.5"})]}),Ho=({path:e,onGetFileInfo:t,onDownload:n})=>{const{t:r}=Ye(),[i,o]=N.useState({status:"loading"}),a=N.useRef(t);a.current=t,N.useEffect(()=>{let g=!1;return a.current(e).then(({name:k,size:S,mimeType:x})=>{g||o({status:"ready",name:k,size:S,mimeType:x})}).catch(k=>{g||o({status:"error",message:k instanceof Error?k.message:String(k)})}),()=>{g=!0}},[e]);const l=N.useCallback(async()=>{if(i.status!=="ready"&&i.status!=="done")return;const g=i;o({status:"downloading",name:g.name,size:g.size,mimeType:g.mimeType,progress:0});try{await n(e,(k,S)=>{o(x=>x.status!=="downloading"?x:{...x,progress:S>0?k/S:0})}),o({status:"done",name:g.name,size:g.size,mimeType:g.mimeType})}catch{o({status:"ready",name:g.name,size:g.size,mimeType:g.mimeType})}},[i,e,n]),s={display:"inline-flex",alignItems:"center",gap:"10px",padding:"10px 14px",border:"1px solid var(--border-subtle)",borderRadius:"10px",background:"var(--element-bg-subtle)",cursor:i.status==="ready"||i.status==="done"?"pointer":"default",maxWidth:"300px",verticalAlign:"middle",transition:"background 0.15s"},u="var(--color-text-muted)";if(i.status==="loading")return h.jsxs("span",{className:"file-card",style:s,children:[h.jsx(ei,{size:20,style:{color:u,flexShrink:0}}),h.jsx("span",{style:{fontSize:"0.8rem",opacity:.5},children:r("chat.fileLoading")})]});if(i.status==="error")return h.jsxs("span",{className:"file-card",style:{...s,cursor:"default",opacity:.5},title:i.message,children:[h.jsx(ei,{size:20,style:{color:u,flexShrink:0}}),h.jsx("span",{style:{fontSize:"0.8rem"},children:r("chat.fileUnavailable")})]});const{name:p,size:c}=i,f=i.status==="downloading",d=i.status==="done";return h.jsxs("span",{className:"file-card",style:s,onClick:l,role:"button",tabIndex:0,onKeyDown:g=>{(g.key==="Enter"||g.key===" ")&&l()},title:r(f?"chat.fileDownloading":d?"chat.fileDownloaded":"chat.clickToDownload"),children:[h.jsx(ei,{size:20,style:{color:u,flexShrink:0}}),h.jsxs("span",{style:{minWidth:0,overflow:"hidden"},children:[h.jsx("span",{style:{display:"block",fontSize:"0.85rem",fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"var(--color-text-primary)"},children:p}),h.jsx("span",{style:{display:"block",fontSize:"0.75rem",color:"var(--color-text-muted)",marginTop:"2px"},children:Tx(c)})]}),h.jsx("span",{style:{flexShrink:0,fontSize:"0.75rem",color:d?"var(--color-success)":"var(--color-text-muted)"},children:f?`${Math.round(i.progress*100)}%`:d?"✓":"↓"})]})},Kt=({content:e,onFileDownload:t,onGetFileInfo:n})=>{const{isDark:r}=Zo(),i=r?Fb:Mb,o=N.useMemo(()=>({code({className:a,children:l,...s}){const u=/language-(\w+)/.exec(a||""),p=String(l).replace(/\n$/,""),c=p.includes(` -`);return a?.startsWith("language-")||c?h.jsxs("div",{className:"code-block-wrapper",children:[h.jsx(Sx,{code:p}),h.jsx($e,{language:u?.[1]||"text",style:i,showLineNumbers:!0,customStyle:{margin:0,borderRadius:"8px",fontSize:"0.8rem",lineHeight:"1.5"},codeTagProps:{style:{fontFamily:"var(--font-family-mono)"}},lineNumberStyle:{color:"var(--color-text-muted)",paddingRight:"1em",textAlign:"right",userSelect:"none",minWidth:"2.5em"},children:p})]}):h.jsx("code",{className:"inline-code",...s,children:l})},a({href:a,children:l}){const s=typeof a=="string"&&a.startsWith(vn);if(s&&n&&t){const u=wn(a);return h.jsx(Ho,{path:u,onGetFileInfo:n,onDownload:t})}if(s&&t){const u=wn(a);return h.jsx("button",{className:"file-link",onClick:p=>{p.preventDefault(),p.stopPropagation(),t(u)},type:"button",style:{cursor:"pointer",color:"var(--color-accent-500)",textDecoration:"underline",background:"none",border:"none",font:"inherit",padding:0},children:l})}if(n&&t){const u=typeof a=="string"?Cx(a):null;if(u)return h.jsx(Ho,{path:u,onGetFileInfo:n,onDownload:t})}return typeof a=="string"&&(a.startsWith("http://")||a.startsWith("https://"))?h.jsx("a",{href:a,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--color-accent-500)",textDecoration:"underline"},children:l}):h.jsx("span",{style:{textDecoration:"underline",opacity:.7},children:l})},table({children:a}){return h.jsx("div",{className:"table-wrapper",children:h.jsx("table",{children:a})})},blockquote({children:a}){return h.jsx("blockquote",{className:"custom-blockquote",children:a})}}),[i,r,t,n]);return h.jsx(uf,{remarkPlugins:[Sg],components:o,urlTransform:a=>a.startsWith("computer://")||/^(https?|mailto|tel|file):/i.test(a)||a.startsWith("#")||a.startsWith("/")||!a.includes(":")?a:"",children:e})},xi=({thinking:e,streaming:t,isLastItem:n=!1})=>{const{t:r}=Ye(),[i,o]=N.useState(!!t),a=N.useRef(!1),l=N.useRef(null),[s,u]=N.useState({atTop:!0,atBottom:!0}),p=Cs(e,!!t);N.useEffect(()=>{a.current||(t?o(!0):n||o(!1))},[t,n]),N.useEffect(()=>{if(!t||!i)return;const k=l.current;if(!k)return;k.scrollHeight-k.scrollTop-k.clientHeight<80&&(k.scrollTop=k.scrollHeight)},[p,t,i]);const c=N.useCallback(()=>{const k=l.current;k&&u({atTop:k.scrollTop<4,atBottom:k.scrollHeight-k.scrollTop-k.clientHeight<4})},[]),f=N.useCallback(()=>{a.current=!0,o(k=>!k)},[]);if(!e&&!t)return null;const d=e.length,g=t&&d===0?r("chat.thinking"):r("chat.thoughtCharacters",{count:d});return h.jsxs("div",{className:`chat-thinking ${t?"chat-thinking--streaming":""}`,children:[h.jsxs("button",{className:"chat-thinking__toggle",onClick:f,children:[h.jsx("span",{className:`chat-thinking__chevron ${i?"is-open":""}`,children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-thinking__label",children:g})]}),h.jsx("div",{className:`chat-thinking__expand-container ${i?"is-expanded":""}`,children:h.jsx("div",{className:"chat-thinking__expand-inner",children:e&&h.jsx("div",{className:`chat-thinking__content-wrapper ${s.atTop?"at-top":""} ${s.atBottom?"at-bottom":""}`,ref:l,onScroll:c,children:h.jsx("div",{className:"chat-thinking__content",children:h.jsx(Kt,{content:t?p:e})})})})})]})},Sn={explore:"shared.tools.explore",read_file:"shared.tools.read",write_file:"shared.tools.write",list_directory:"tools.ls",bash:"shared.tools.shell",glob:"tools.glob",grep:"tools.grep",create_file:"shared.tools.write",delete_file:"tools.delete",Task:"tools.task",search:"shared.tools.search",edit_file:"shared.tools.edit",web_search:"tools.web",TodoWrite:"shared.tools.todo"},Ax=({tool:e})=>{const{t}=Ye(),[n,r]=N.useState(!1),i=N.useMemo(()=>{const u=e.tool_input;if(!u)return[];const p=u.todos||u.result?.todos;return Array.isArray(p)?p:[]},[e.tool_input]);if(i.length===0)return null;const o=i.filter(u=>u.status==="completed").length,a=o===i.length,l=i.find(u=>u.status==="in_progress"),s=u=>{switch(u){case"completed":return h.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"var(--color-success)",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("path",{d:"M22 11.08V12a10 10 0 1 1-5.93-9.14"}),h.jsx("path",{d:"m9 11 3 3L22 4"})]});case"in_progress":return h.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"var(--color-accent-500)",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("circle",{cx:"12",cy:"12",r:"10"}),h.jsx("polygon",{points:"10 8 16 12 10 16 10 8",fill:"var(--color-accent-500)"})]});case"cancelled":return h.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"var(--color-error)",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("circle",{cx:"12",cy:"12",r:"10"}),h.jsx("path",{d:"m15 9-6 6"}),h.jsx("path",{d:"m9 9 6 6"})]});default:return h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"var(--color-text-muted)",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("circle",{cx:"12",cy:"12",r:"10"})})}};return h.jsxs("div",{className:"chat-todo-card",children:[h.jsxs("div",{className:"chat-todo-card__header",onClick:()=>r(!n),children:[h.jsx("span",{className:"chat-todo-card__icon",children:h.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("rect",{x:"3",y:"5",width:"6",height:"6",rx:"1"}),h.jsx("path",{d:"m3 17 2 2 4-4"}),h.jsx("path",{d:"M13 6h8"}),h.jsx("path",{d:"M13 12h8"}),h.jsx("path",{d:"M13 18h8"})]})}),a&&!n?h.jsx("span",{className:"chat-todo-card__current chat-todo-card__current--done",children:t("chat.allTasksCompleted")}):l&&!n?h.jsx("span",{className:"chat-todo-card__current",children:l.content}):null,h.jsxs("span",{className:"chat-todo-card__right",children:[h.jsx("span",{className:"chat-todo-card__dots",children:i.map((u,p)=>h.jsx("span",{className:`chat-todo-card__dot chat-todo-card__dot--${u.status}`},u.id||p))}),h.jsxs("span",{className:"chat-todo-card__stats",children:[o,"/",i.length]})]}),h.jsx("span",{className:`chat-todo-card__chevron ${n?"is-expanded":""}`,children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("path",{d:"m6 9 6 6 6-6"})})})]}),n&&h.jsx("div",{className:"chat-todo-card__list",children:i.map((u,p)=>h.jsxs("div",{className:`chat-todo-card__item chat-todo-card__item--${u.status}`,children:[s(u.status),h.jsx("span",{className:"chat-todo-card__item-text",children:u.content})]},u.id||p))})]})};function Lx(e){const t=e.tool_input??(()=>{try{return JSON.parse(e.input_preview||"")}catch{return null}})();return t?{description:t.description,agentType:t.subagent_type}:null}function Nx(e,t){if(e.type==="thinking"){const n=(e.content||"").length;return t("chat.thoughtCharacters",{count:n})}if(e.type==="tool"&&e.tool){const n=e.tool,r=n.input_preview?`: ${n.input_preview}`:"";return`${n.name}${r}`}if(e.type==="text"){const n=(e.content||"").length;return t("chat.textCharacters",{count:n})}return""}const _s=({tool:e,now:t,subItems:n=[],onCancelTool:r})=>{const{t:i,language:o}=Ye(),a=N.useRef(null),l=N.useRef(0),[s,u]=N.useState(!1),p=e.status==="running",c=e.status==="completed",f=e.status==="failed"||e.status==="error",d=p&&!!r,g=Lx(e),k=c&&e.duration_ms!=null?Wt(e.duration_ms):p&&e.start_ms?Wt(t-e.start_ms):"",S=p?"running":c?"done":f?"error":"pending",x=n.filter(_=>_.type==="tool"&&_.tool),v=x.filter(_=>_.tool.status==="completed").length,y=x.filter(_=>_.tool.status==="running").length;return N.useEffect(()=>{s&&n.length>l.current&&a.current&&(a.current.scrollTop=a.current.scrollHeight),l.current=n.length},[n.length,s]),h.jsxs("div",{className:`chat-task-card chat-task-card--${S}`,children:[h.jsxs("div",{className:"chat-task-card__header",children:[h.jsx("span",{className:"chat-tool-card__icon",children:p?h.jsx("span",{className:"chat-tool-card__spinner"}):c?h.jsx("span",{className:"chat-tool-card__check",children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8.5L6.5 12L13 4",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}):f?h.jsx("span",{className:"chat-tool-card__error-icon",children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 4L12 12M12 4L4 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})})}):h.jsx("span",{className:"chat-tool-card__spinner"})}),h.jsx("span",{className:"chat-tool-card__name",children:g?.description||i("chat.task")}),g?.agentType&&h.jsx("span",{className:"chat-tool-card__type",children:g.agentType}),k&&h.jsx("span",{className:"chat-tool-card__duration",children:k}),d&&h.jsx("button",{className:"chat-tool-card__cancel",onClick:_=>{_.stopPropagation(),r?.(e.id)},"aria-label":i("common.cancel"),children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("rect",{x:"3",y:"3",width:"10",height:"10",rx:"2",fill:"currentColor"})})})]}),n.length>0&&h.jsxs(h.Fragment,{children:[h.jsxs("div",{className:"chat-task-card__summary",onClick:()=>u(_=>!_),children:[h.jsx("span",{className:"chat-task-card__stat",children:i("chat.toolCalls",{count:x.length,suffix:Hi(o,x.length)})}),h.jsxs("span",{className:"chat-task-card__stat-right",children:[h.jsx("span",{className:"chat-task-card__stat--done",children:i("chat.done",{count:v})}),y>0&&h.jsx("span",{className:"chat-task-card__stat--running",children:i("chat.running",{count:y})})]}),h.jsx("span",{className:`chat-task-card__chevron ${s?"is-expanded":""}`,children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("path",{d:"m6 9 6 6 6-6"})})})]}),s&&h.jsx("div",{className:"chat-task-card__steps",ref:a,children:n.map((_,C)=>{if(_.type==="thinking")return h.jsxs("div",{className:"chat-task-card__step chat-task-card__step--thinking",children:[h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("path",{d:"m6 9 6 6 6-6"})}),h.jsx("span",{children:Nx(_,i)})]},`sub-think-${C}`);if(_.type==="tool"&&_.tool){const m=_.tool,T=m.status==="completed",j=m.status==="failed"||m.status==="error";return h.jsxs("div",{className:`chat-task-card__step chat-task-card__step--tool ${T?"is-done":j?"is-error":"is-running"}`,children:[T?h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8.5L6.5 12L13 4",stroke:"var(--color-success)",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})}):j?h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 4L12 12M12 4L4 12",stroke:"var(--color-error)",strokeWidth:"2",strokeLinecap:"round"})}):h.jsx("span",{className:"chat-task-card__step-spinner"}),h.jsx("span",{className:"chat-task-card__step-name",children:m.name}),(()=>{const A=Es(m);return A?h.jsx("span",{className:"chat-task-card__step-preview",children:A}):null})(),T&&m.duration_ms!=null&&h.jsx("span",{className:"chat-task-card__step-duration",children:Wt(m.duration_ms)})]},`sub-tool-${m.id}-${C}`)}return null})})]})]})};function Es(e){if(!e.input_preview)return null;try{const t=JSON.parse(e.input_preview);if(!t||typeof t!="object")return null;const n=o=>{const a=o.replace(/\\/g,"/").split("/");return a[a.length-1]||o};let r=null;const i=t.file_path||t.path;switch(e.name){case"Read":case"Write":case"Edit":case"LS":case"StrReplace":case"delete_file":r=i?n(i):null;break;case"Glob":case"Grep":r=t.pattern||null;break;case"Bash":case"Shell":r=t.description||t.command||null;break;case"web_search":case"WebSearch":r=t.search_term||t.query||null;break;case"WebFetch":r=t.url||null;break;case"SemanticSearch":r=t.query||null;break;default:r=Object.values(t).find(a=>typeof a=="string"&&a.length>0&&a.length<80)||null}return r?r.length>60?r.slice(0,60)+"…":r:null}catch{return null}}const Wo=({tool:e,now:t,onCancelTool:n})=>{const{t:r}=Ye(),i=e.name.toLowerCase().replace(/[\s-]/g,"_"),o=Sn[i]||Sn[e.name],a=o?r(o):"Tool",l=e.status==="running",s=e.status==="completed",u=e.status==="failed"||e.status==="error",p=l&&!!n,c=Es(e),f=s&&e.duration_ms!=null?Wt(e.duration_ms):l&&e.start_ms?Wt(t-e.start_ms):"",d=l?"running":s?"done":u?"error":"pending";return h.jsx("div",{className:`chat-tool-card chat-tool-card--${d}`,children:h.jsxs("div",{className:"chat-tool-card__row",children:[h.jsx("span",{className:"chat-tool-card__icon",children:l?h.jsx("span",{className:"chat-tool-card__spinner"}):s?h.jsx("span",{className:"chat-tool-card__check",children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8.5L6.5 12L13 4",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}):u?h.jsx("span",{className:"chat-tool-card__error-icon",children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 4L12 12M12 4L4 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})})}):h.jsx("span",{className:"chat-tool-card__spinner"})}),h.jsxs("span",{className:"chat-tool-card__name",children:[e.name,c&&h.jsxs("span",{className:"chat-tool-card__preview",children:[" ",c]})]}),h.jsx("span",{className:"chat-tool-card__type",children:a}),f&&h.jsx("span",{className:"chat-tool-card__duration",children:f}),p&&h.jsx("button",{className:"chat-tool-card__cancel",onClick:g=>{g.stopPropagation(),n?.(e.id)},"aria-label":r("common.cancel"),children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("rect",{x:"3",y:"3",width:"10",height:"10",rx:"2",fill:"currentColor"})})})]})})},Ix=new Set(["Read","Grep","Glob","SemanticSearch"]);function jx(e,t){const n=new Map,r=[];for(const i of e){const o=i.name.toLowerCase().replace(/[\s-]/g,"_"),a=Sn[o]||Sn[i.name],l=a?t(a):i.name,s=l.toLowerCase(),u=n.get(s);if(u){u.count+=1;continue}n.set(s,{label:l,count:1}),r.push(s)}return r.map(i=>{const o=n.get(i);return`${o.label} ${o.count}`}).join(", ")}const Rx=({tools:e})=>{const{t}=Ye(),[n,r]=N.useState(!1);if(e.length===0)return null;const i=e.filter(s=>s.status==="completed").length,o=i===e.length,a=jx(e,t),l=o?t("chat.readToolsDone",{summary:a}):t("chat.readToolsRunning",{summary:a,doneCount:i});return h.jsxs("div",{className:`chat-thinking ${o?"":"chat-thinking--streaming"}`,children:[h.jsxs("button",{className:"chat-thinking__toggle",onClick:()=>r(s=>!s),children:[h.jsx("span",{className:`chat-thinking__chevron ${n?"is-open":""}`,children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-thinking__label",children:l})]}),n&&h.jsx("div",{className:"chat-thinking__content-wrapper at-top at-bottom",children:h.jsx("div",{className:"chat-thinking__content",children:e.map(s=>{const u=s.input_preview||"";return h.jsxs("div",{style:{fontSize:"12px",padding:"2px 0",opacity:.8},children:[s.status==="completed"?"✓":"⋯"," ",s.name," ",u]},s.id)})})})]})},Ox=2,ki=({tools:e,now:t,onCancelTool:n})=>{const{t:r,language:i}=Ye(),o=N.useRef(null),a=N.useRef(0),[l,s]=N.useState(!1);if(N.useEffect(()=>{l&&e.length>a.current&&o.current&&(o.current.scrollTop=o.current.scrollHeight),a.current=e.length},[e.length,l]),!e||e.length===0)return null;if(e.length<=Ox)return h.jsx("div",{className:"chat-tool-list",children:e.map(c=>h.jsx(Wo,{tool:c,now:t,onCancelTool:n},c.id))});const u=e.filter(c=>c.status==="running").length,p=e.filter(c=>c.status==="completed").length;return h.jsxs("div",{className:"chat-tool-list chat-tool-list--collapsed",children:[h.jsxs("div",{className:"chat-tool-list__header",onClick:()=>s(c=>!c),children:[h.jsx("span",{className:"chat-tool-list__count",children:r("chat.toolCalls",{count:e.length,suffix:Hi(i,e.length)})}),h.jsxs("span",{className:"chat-tool-list__stats",children:[p>0&&h.jsx("span",{className:"chat-tool-list__stat chat-tool-list__stat--done",children:r("chat.done",{count:p})}),u>0&&h.jsx("span",{className:"chat-tool-list__stat chat-tool-list__stat--running",children:r("chat.running",{count:u})})]}),h.jsx("span",{className:`chat-tool-list__chevron ${l?"is-expanded":""}`,children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("path",{d:"m6 9 6 6 6-6"})})})]}),l&&h.jsx("div",{className:"chat-tool-list__scroll",ref:o,children:e.map(c=>h.jsx(Wo,{tool:c,now:t,onCancelTool:n},c.id))})]})},ti=()=>h.jsxs("span",{className:"chat-msg__typing",children:[h.jsx("span",{}),h.jsx("span",{}),h.jsx("span",{})]});function Cs(e,t){const[n,r]=N.useState(t?"":e),i=N.useRef(t?0:e.length),o=N.useRef(e),a=N.useRef(null),l=N.useRef(3);return N.useEffect(()=>{if(!t){a.current&&(clearInterval(a.current),a.current=null),i.current=e.length,o.current=e,r(e);return}o.current=e,e.length0){const c=26.666666666666668;l.current=Math.max(Math.ceil(s/c),2),a.current||(a.current=setInterval(()=>{const f=o.current,d=i.current;if(d>=f.length){a.current&&(clearInterval(a.current),a.current=null);return}const g=Math.min(d+l.current,f.length);i.current=g,r(f.slice(0,g))},30))}},[e,t]),N.useEffect(()=>()=>{a.current&&clearInterval(a.current)},[]),n}const Ts=({content:e,onFileDownload:t,onGetFileInfo:n})=>{const r=Cs(e,!0);return h.jsx(Kt,{content:r,onFileDownload:t,onGetFileInfo:n})},_n=e=>!e||e.name!=="AskUserQuestion"||!e.tool_input?!1:!["completed","failed","cancelled","rejected"].includes(e.status);function Dx(e,t){const n=t.split(".");let r=e;for(const i of n){if(!r||typeof r!="object"||!(i in r))return null;r=r[i]}return typeof r=="string"?r:null}const Mx=new Set(["other",...Object.values(Ys).map(e=>Dx(e,"common.other")).filter(e=>!!e).map(e=>e.trim().toLowerCase())]),xt=e=>{const t=(e||"").trim().toLowerCase();return Mx.has(t)},As=({tool:e,onAnswer:t})=>{const{t:n,language:r}=Ye(),i=e.tool_input?.questions||[],[o,a]=N.useState({}),[l,s]=N.useState({}),[u,p]=N.useState(!1),[c,f]=N.useState(!1),d=N.useMemo(()=>i.map(x=>{const v=Array.isArray(x.options)?x.options:[],y=v.some(_=>xt(_?.label));return{...x,options:v,hasBuiltInOther:y}}),[i]);if(d.length===0)return null;const g=(x,v,y)=>{a(_=>{if(y){const C=_[x]||[];return{..._,[x]:C.includes(v)?C.filter(m=>m!==v):[...C,v]}}return{..._,[x]:_[x]===v?void 0:v}})},k=async()=>{if(!S||u||c)return;const x={};d.forEach((v,y)=>{const _=o[y],C=(l[y]||"").trim();Array.isArray(_)?x[String(y)]=_.map(m=>xt(m)&&C||m):xt(_)?x[String(y)]=C||_:x[String(y)]=_??""}),p(!0);try{await t(e.id,x),f(!0)}finally{p(!1)}},S=d.every((x,v)=>{const y=o[v];return(x.multiSelect?Array.isArray(y)&&y.length>0:!!y)?!(Array.isArray(y)?y.some(m=>xt(m)):xt(y))||!!(l[v]||"").trim():!1});return h.jsxs("div",{className:"chat-ask-card",children:[h.jsxs("div",{className:"chat-ask-card__header",children:[h.jsx("span",{className:"chat-ask-card__count",children:n("chat.askQuestionCount",{count:i.length,suffix:Hi(r,i.length)})}),!c&&!u&&h.jsx("span",{className:"chat-ask-card__waiting",children:n("chat.waiting")})]}),d.map((x,v)=>{const y=o[v],_=Array.isArray(y)?y.some(C=>xt(C)):xt(y);return h.jsxs("div",{className:"chat-ask-card__question",children:[h.jsxs("div",{className:"chat-ask-card__question-header",children:[h.jsx("span",{className:"chat-ask-card__tag",children:x.header}),h.jsx("span",{className:"chat-ask-card__question-text",children:x.question})]}),h.jsxs("div",{className:"chat-ask-card__options",children:[(x.options||[]).map((C,m)=>{const T=x.multiSelect?(o[v]||[]).includes(C.label):o[v]===C.label;return h.jsxs("button",{className:`chat-ask-card__option ${T?"is-selected":""}`,onClick:()=>g(v,C.label,x.multiSelect),disabled:c||u,children:[h.jsx("span",{className:`chat-ask-card__radio ${x.multiSelect?"chat-ask-card__radio--multi":""}`,children:T&&h.jsx("svg",{width:"8",height:"8",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8L6.5 11.5L13 4.5",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-ask-card__option-label",children:C.label}),C.description&&h.jsx("span",{className:"chat-ask-card__option-desc",children:C.description})]},m)}),!x.hasBuiltInOther&&h.jsxs("button",{className:`chat-ask-card__option ${_?"is-selected":""}`,onClick:()=>g(v,"Other",x.multiSelect),disabled:c||u,children:[h.jsx("span",{className:`chat-ask-card__radio ${x.multiSelect?"chat-ask-card__radio--multi":""}`,children:_&&h.jsx("svg",{width:"8",height:"8",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8L6.5 11.5L13 4.5",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-ask-card__option-label",children:n("common.other")}),h.jsx("span",{className:"chat-ask-card__option-desc",children:n("common.customTextInput")})]}),_&&h.jsx("input",{className:"chat-ask-card__custom-input",placeholder:n("common.typeYourAnswer"),value:l[v]||"",onChange:C=>s(m=>({...m,[v]:C.target.value})),disabled:c||u})]})]},v)}),h.jsxs("button",{className:"chat-ask-card__submit chat-ask-card__submit--bottom",disabled:!S||c||u,onClick:k,children:[h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M2 8L6 12L14 4",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})}),n(c?"common.submitted":u?"common.submitting":"common.submit")]})]})};function Ls(e){const t=[];let n=null;for(const r of e){if(r.type==="tool"&&r.tool?.name==="Task"){const i={...r,subItems:[]};t.push(i),n=i;continue}if(r.is_subagent&&n){n.subItems.push(r);continue}r.is_subagent||t.push(r)}return t}function Nt(e){const t=[];for(const n of e){const r=t[t.length-1];r&&r.type===n.type?r.entries.push(n):t.push({type:n.type,entries:[n]})}return t}function Ns(e,t,n){return n?e.map((r,i)=>h.jsx(As,{tool:r.tool,onAnswer:n},`${t}-ask-${r.tool.id}-${i}`)):null}function It(e,t,n,r,i,o,a,l){return e.map((s,u)=>{if(s.type==="thinking"){const p=s.entries.map(f=>f.content||"").join(` +|(?![\\s\\S])))+`,"m"),alias:a,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(i)[0]}}}}),Object.defineProperty(n.languages.diff,"PREFIXES",{value:r})})(t)}return zr}var Pr,Lo;function _y(){if(Lo)return Pr;Lo=1,Pr=e,e.displayName="markupTemplating",e.aliases=[];function e(t){(function(n){function r(i,o){return"___"+i.toUpperCase()+o+"___"}Object.defineProperties(n.languages["markup-templating"]={},{buildPlaceholders:{value:function(i,o,a,l){if(i.language===o){var s=i.tokenStack=[];i.code=i.code.replace(a,function(u){if(typeof l=="function"&&!l(u))return u;for(var p=s.length,c;i.code.indexOf(c=r(o,p))!==-1;)++p;return s[p]=u,c}),i.grammar=n.languages.markup}}},tokenizePlaceholders:{value:function(i,o){if(i.language!==o||!i.tokenStack)return;i.grammar=n.languages[o];var a=0,l=Object.keys(i.tokenStack);function s(u){for(var p=0;p=l.length);p++){var c=u[p];if(typeof c=="string"||c.content&&typeof c.content=="string"){var f=l[a],d=i.tokenStack[f],g=typeof c=="string"?c:c.content,k=r(o,f),S=g.indexOf(k);if(S>-1){++a;var x=g.substring(0,S),v=new n.Token(o,n.tokenize(d,i.grammar),"language-"+o,d),b=g.substring(S+k.length),_=[];x&&_.push.apply(_,s([x])),_.push(v),b&&_.push.apply(_,s([b])),typeof c=="string"?u.splice.apply(u,[p,1].concat(_)):c.content=_}}else c.content&&s(c.content)}return u}s(i.tokens)}}})})(t)}return Pr}var Br,No;function Ey(){if(No)return Br;No=1,Br=e,e.displayName="go",e.aliases=[];function e(t){t.languages.go=t.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),t.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete t.languages.go["class-name"]}return Br}var $r,Io;function Cy(){if(Io)return $r;Io=1,$r=e,e.displayName="java",e.aliases=[];function e(t){(function(n){var r=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,i=/(^|[^\w.])(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,o={pattern:RegExp(i+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};n.languages.java=n.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[o,{pattern:RegExp(i+/[A-Z]\w*(?=\s+\w+\s*[;,=()])/.source),lookbehind:!0,inside:o.inside}],keyword:r,function:[n.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),n.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),n.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":o,keyword:r,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,function(){return r.source})),lookbehind:!0,inside:{punctuation:/\./}}})})(t)}return $r}var qr,jo;function fs(){if(jo)return qr;jo=1,qr=e,e.displayName="typescript",e.aliases=["ts"];function e(t){(function(n){n.languages.typescript=n.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),n.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete n.languages.typescript.parameter,delete n.languages.typescript["literal-property"];var r=n.languages.extend("typescript",{});delete r["class-name"],n.languages.typescript["class-name"].inside=r,n.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:r}}}}),n.languages.ts=n.languages.typescript})(t)}return qr}var Ur,Ro;function Ty(){if(Ro)return Ur;Ro=1,Ur=e,e.displayName="json",e.aliases=["webmanifest"];function e(t){t.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},t.languages.webmanifest=t.languages.json}return Ur}var Hr,Oo;function hs(){if(Oo)return Hr;Oo=1,Hr=e,e.displayName="jsx",e.aliases=[];function e(t){(function(n){var r=n.util.clone(n.languages.javascript),i=/(?:\s|\/\/.*(?!.)|\/\*(?:[^*]|\*(?!\/))\*\/)/.source,o=/(?:\{(?:\{(?:\{[^{}]*\}|[^{}])*\}|[^{}])*\})/.source,a=/(?:\{*\.{3}(?:[^{}]|)*\})/.source;function l(p,c){return p=p.replace(//g,function(){return i}).replace(//g,function(){return o}).replace(//g,function(){return a}),RegExp(p,c)}a=l(a).source,n.languages.jsx=n.languages.extend("markup",r),n.languages.jsx.tag.pattern=l(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),n.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,n.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,n.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,n.languages.jsx.tag.inside.comment=r.comment,n.languages.insertBefore("inside","attr-name",{spread:{pattern:l(//.source),inside:n.languages.jsx}},n.languages.jsx.tag),n.languages.insertBefore("inside","special-attr",{script:{pattern:l(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:n.languages.jsx}}},n.languages.jsx.tag);var s=function(p){return p?typeof p=="string"?p:typeof p.content=="string"?p.content:p.content.map(s).join(""):""},u=function(p){for(var c=[],f=0;f0&&c[c.length-1].tagName===s(d.content[0].content[1])&&c.pop():d.content[d.content.length-1].content==="/>"||c.push({tagName:s(d.content[0].content[1]),openedBraces:0}):c.length>0&&d.type==="punctuation"&&d.content==="{"?c[c.length-1].openedBraces++:c.length>0&&c[c.length-1].openedBraces>0&&d.type==="punctuation"&&d.content==="}"?c[c.length-1].openedBraces--:g=!0),(g||typeof d=="string")&&c.length>0&&c[c.length-1].openedBraces===0){var k=s(d);f0&&(typeof p[f-1]=="string"||p[f-1].type==="plain-text")&&(k=s(p[f-1])+k,p.splice(f-1,1),f--),p[f]=new n.Token("plain-text",k,null,k)}d.content&&typeof d.content!="string"&&u(d.content)}};n.hooks.add("after-tokenize",function(p){p.language!=="jsx"&&p.language!=="tsx"||u(p.tokens)})})(t)}return Hr}var Wr,Do;function Ay(){if(Do)return Wr;Do=1,Wr=e,e.displayName="kotlin",e.aliases=["kt","kts"];function e(t){(function(n){n.languages.kotlin=n.languages.extend("clike",{keyword:{pattern:/(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,lookbehind:!0},function:[{pattern:/(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,greedy:!0},{pattern:/(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,lookbehind:!0,greedy:!0}],number:/\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,operator:/\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/}),delete n.languages.kotlin["class-name"];var r={"interpolation-punctuation":{pattern:/^\$\{?|\}$/,alias:"punctuation"},expression:{pattern:/[\s\S]+/,inside:n.languages.kotlin}};n.languages.insertBefore("kotlin","string",{"string-literal":[{pattern:/"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,alias:"multiline",inside:{interpolation:{pattern:/\$(?:[a-z_]\w*|\{[^{}]*\})/i,inside:r},string:/[\s\S]+/}},{pattern:/"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,alias:"singleline",inside:{interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,lookbehind:!0,inside:r},string:/[\s\S]+/}}],char:{pattern:/'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,greedy:!0}}),delete n.languages.kotlin.string,n.languages.insertBefore("kotlin","keyword",{annotation:{pattern:/\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,alias:"builtin"}}),n.languages.insertBefore("kotlin","function",{label:{pattern:/\b\w+@|@\w+\b/,alias:"symbol"}}),n.languages.kt=n.languages.kotlin,n.languages.kts=n.languages.kotlin})(t)}return Wr}var Vr,Mo;function Ly(){if(Mo)return Vr;Mo=1;var e=_y();Vr=t,t.displayName="php",t.aliases=[];function t(n){n.register(e),(function(r){var i=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,o=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],a=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,l=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;r.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:i,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s+)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:o,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:a,operator:l,punctuation:s};var u={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:r.languages.php},p=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:u}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:u}}];r.languages.insertBefore("php","variable",{string:p,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:i,string:p,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:o,number:a,operator:l,punctuation:s}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),r.hooks.add("before-tokenize",function(c){if(/<\?/.test(c.code)){var f=/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g;r.languages["markup-templating"].buildPlaceholders(c,"php",f)}}),r.hooks.add("after-tokenize",function(c){r.languages["markup-templating"].tokenizePlaceholders(c,"php")})})(n)}return Vr}var Gr,Fo;function Ny(){if(Fo)return Gr;Fo=1,Gr=e,e.displayName="markdown",e.aliases=["md"];function e(t){(function(n){var r=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function i(f){return f=f.replace(//g,function(){return r}),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+f+")")}var o=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,function(){return o}),l=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;n.languages.markdown=n.languages.extend("markup",{}),n.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:n.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+l+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+l+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(o),inside:n.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+l+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(o),alias:"important",inside:n.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:i(/\b__(?:(?!_)|_(?:(?!_))+_)+__\b|\*\*(?:(?!\*)|\*(?:(?!\*))+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:i(/\b_(?:(?!_)|__(?:(?!_))+__)+_\b|\*(?:(?!\*)|\*\*(?:(?!\*))+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:i(/(~~?)(?:(?!~))+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:i(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\]))+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach(function(f){["url","bold","italic","strike","code-snippet"].forEach(function(d){f!==d&&(n.languages.markdown[f].inside.content.inside[d]=n.languages.markdown[d])})}),n.hooks.add("after-tokenize",function(f){if(f.language!=="markdown"&&f.language!=="md")return;function d(g){if(!(!g||typeof g=="string"))for(var k=0,S=g.length;k",quot:'"'},p=String.fromCodePoint||String.fromCharCode;function c(f){var d=f.replace(s,"");return d=d.replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi,function(g,k){if(k=k.toLowerCase(),k[0]==="#"){var S;return k[1]==="x"?S=parseInt(k.slice(2),16):S=Number(k.slice(1)),p(S)}else{var x=u[k];return x||g}}),d}n.languages.md=n.languages.markdown})(t)}return Gr}var Zr,zo;function Iy(){if(zo)return Zr;zo=1,Zr=e,e.displayName="python",e.aliases=["py"];function e(t){t.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},t.languages.python["string-interpolation"].inside.interpolation.inside.rest=t.languages.python,t.languages.py=t.languages.python}return Zr}var Xr,Po;function jy(){if(Po)return Xr;Po=1,Xr=e,e.displayName="rust",e.aliases=[];function e(t){(function(n){for(var r=/\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|)*\*\//.source,i=0;i<2;i++)r=r.replace(//g,function(){return r});r=r.replace(//g,function(){return/[^\s\S]/.source}),n.languages.rust={comment:[{pattern:RegExp(/(^|[^\\])/.source+r),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|trait|type|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\b\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},n.languages.rust["closure-params"].inside.rest=n.languages.rust,n.languages.rust.attribute.inside.string=n.languages.rust.string})(t)}return Xr}var Kr,Bo;function Ry(){if(Bo)return Kr;Bo=1,Kr=e,e.displayName="swift",e.aliases=[];function e(t){t.languages.swift={comment:{pattern:/(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,lookbehind:!0,greedy:!0},"string-literal":[{pattern:RegExp(/(^|[^"#])/.source+"(?:"+/"(?:\\(?:\((?:[^()]|\([^()]*\))*\)|\r\n|[^(])|[^\\\r\n"])*"/.source+"|"+/"""(?:\\(?:\((?:[^()]|\([^()]*\))*\)|[^(])|[^\\"]|"(?!""))*"""/.source+")"+/(?!["#])/.source),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\\($/,alias:"punctuation"},punctuation:/\\(?=[\r\n])/,string:/[\s\S]+/}},{pattern:RegExp(/(^|[^"#])(#+)/.source+"(?:"+/"(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|\r\n|[^#])|[^\\\r\n])*?"/.source+"|"+/"""(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|[^#])|[^\\])*?"""/.source+")\\2"),lookbehind:!0,greedy:!0,inside:{interpolation:{pattern:/(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,lookbehind:!0,inside:null},"interpolation-punctuation":{pattern:/^\)|\\#+\($/,alias:"punctuation"},string:/[\s\S]+/}}],directive:{pattern:RegExp(/#/.source+"(?:"+(/(?:elseif|if)\b/.source+"(?:[ ]*"+/(?:![ \t]*)?(?:\b\w+\b(?:[ \t]*\((?:[^()]|\([^()]*\))*\))?|\((?:[^()]|\([^()]*\))*\))(?:[ \t]*(?:&&|\|\|))?/.source+")+")+"|"+/(?:else|endif)\b/.source+")"),alias:"property",inside:{"directive-name":/^#\w+/,boolean:/\b(?:false|true)\b/,number:/\b\d+(?:\.\d+)*\b/,operator:/!|&&|\|\||[<>]=?/,punctuation:/[(),]/}},literal:{pattern:/#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,alias:"constant"},"other-directive":{pattern:/#\w+\b/,alias:"property"},attribute:{pattern:/@\w+/,alias:"atrule"},"function-definition":{pattern:/(\bfunc\s+)\w+/,lookbehind:!0,alias:"function"},label:{pattern:/\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,lookbehind:!0,alias:"important"},keyword:/\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,boolean:/\b(?:false|true)\b/,nil:{pattern:/\bnil\b/,alias:"constant"},"short-argument":/\$\d+\b/,omit:{pattern:/\b_\b/,alias:"keyword"},number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,"class-name":/\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,function:/\b[a-z_]\w*(?=\s*\()/i,constant:/\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,operator:/[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,punctuation:/[{}[\]();,.:\\]/},t.languages.swift["string-literal"].forEach(function(n){n.inside.interpolation.inside=t.languages.swift})}return Kr}var Yr,$o;function Oy(){if($o)return Yr;$o=1,Yr=e,e.displayName="yaml",e.aliases=["yml"];function e(t){(function(n){var r=/[*&][^\s[\]{},]+/,i=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,o="(?:"+i.source+"(?:[ ]+"+r.source+")?|"+r.source+"(?:[ ]+"+i.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*/.source.replace(//g,function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source}),l=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function s(u,p){p=(p||"").replace(/m/g,"")+"m";var c=/([:\-,[{]\s*(?:\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<>/g,function(){return o}).replace(/<>/g,function(){return u});return RegExp(c,p)}n.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<>/g,function(){return o})),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\s*:\s)/.source.replace(/<>/g,function(){return o}).replace(/<>/g,function(){return"(?:"+a+"|"+l+")"})),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:s(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:s(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:s(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:s(l),lookbehind:!0,greedy:!0},number:{pattern:s(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:i,important:r,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},n.languages.yml=n.languages.yaml})(t)}return Yr}var Qr,qo;function Dy(){if(qo)return Qr;qo=1;var e=hs(),t=fs();Qr=n,n.displayName="tsx",n.aliases=[];function n(r){r.register(e),r.register(t),(function(i){var o=i.util.clone(i.languages.typescript);i.languages.tsx=i.languages.extend("jsx",o),delete i.languages.tsx.parameter,delete i.languages.tsx["literal-property"];var a=i.languages.tsx.tag;a.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+a.pattern.source+")",a.pattern.flags),a.lookbehind=!0})(r)}return Qr}const My={'code[class*="language-"]':{color:"#393A34",fontFamily:'"Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",fontSize:".9em",lineHeight:"1.2em",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none"},'pre[class*="language-"]':{color:"#393A34",fontFamily:'"Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",fontSize:".9em",lineHeight:"1.2em",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none",padding:"1em",margin:".5em 0",overflow:"auto",border:"1px solid #dddddd",backgroundColor:"white"},'pre > code[class*="language-"]':{fontSize:"1em"},'pre[class*="language-"]::-moz-selection':{background:"#C1DEF1"},'pre[class*="language-"] ::-moz-selection':{background:"#C1DEF1"},'code[class*="language-"]::-moz-selection':{background:"#C1DEF1"},'code[class*="language-"] ::-moz-selection':{background:"#C1DEF1"},'pre[class*="language-"]::selection':{background:"#C1DEF1"},'pre[class*="language-"] ::selection':{background:"#C1DEF1"},'code[class*="language-"]::selection':{background:"#C1DEF1"},'code[class*="language-"] ::selection':{background:"#C1DEF1"},':not(pre) > code[class*="language-"]':{padding:".2em",paddingTop:"1px",paddingBottom:"1px",background:"#f8f8f8",border:"1px solid #dddddd"},comment:{color:"#008000",fontStyle:"italic"},prolog:{color:"#008000",fontStyle:"italic"},doctype:{color:"#008000",fontStyle:"italic"},cdata:{color:"#008000",fontStyle:"italic"},namespace:{Opacity:".7"},string:{color:"#A31515"},punctuation:{color:"#393A34"},operator:{color:"#393A34"},url:{color:"#36acaa"},symbol:{color:"#36acaa"},number:{color:"#36acaa"},boolean:{color:"#36acaa"},variable:{color:"#36acaa"},constant:{color:"#36acaa"},inserted:{color:"#36acaa"},atrule:{color:"#0000ff"},keyword:{color:"#0000ff"},"attr-value":{color:"#0000ff"},".language-autohotkey .token.selector":{color:"#0000ff"},".language-json .token.boolean":{color:"#0000ff"},".language-json .token.number":{color:"#0000ff"},'code[class*="language-css"]':{color:"#0000ff"},function:{color:"#393A34"},deleted:{color:"#9a050f"},".language-autohotkey .token.tag":{color:"#9a050f"},selector:{color:"#800000"},".language-autohotkey .token.keyword":{color:"#00009f"},important:{color:"#e90",fontWeight:"bold"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"},"class-name":{color:"#2B91AF"},".language-json .token.property":{color:"#2B91AF"},tag:{color:"#800000"},"attr-name":{color:"#ff0000"},property:{color:"#ff0000"},regex:{color:"#ff0000"},entity:{color:"#ff0000"},"directive.tag.tag":{background:"#ffff00",color:"#393A34"},".line-numbers.line-numbers .line-numbers-rows":{borderRightColor:"#a5a5a5"},".line-numbers .line-numbers-rows > span:before":{color:"#2B91AF"},".line-highlight.line-highlight":{background:"linear-gradient(to right, rgba(193, 222, 241, 0.2) 70%, rgba(221, 222, 241, 0))"}},Fy={'pre[class*="language-"]':{color:"#d4d4d4",fontSize:"13px",textShadow:"none",fontFamily:'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",lineHeight:"1.5",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none",padding:"1em",margin:".5em 0",overflow:"auto",background:"#1e1e1e"},'code[class*="language-"]':{color:"#d4d4d4",fontSize:"13px",textShadow:"none",fontFamily:'Menlo, Monaco, Consolas, "Andale Mono", "Ubuntu Mono", "Courier New", monospace',direction:"ltr",textAlign:"left",whiteSpace:"pre",wordSpacing:"normal",wordBreak:"normal",lineHeight:"1.5",MozTabSize:"4",OTabSize:"4",tabSize:"4",WebkitHyphens:"none",MozHyphens:"none",msHyphens:"none",hyphens:"none"},'pre[class*="language-"]::selection':{textShadow:"none",background:"#264F78"},'code[class*="language-"]::selection':{textShadow:"none",background:"#264F78"},'pre[class*="language-"] *::selection':{textShadow:"none",background:"#264F78"},'code[class*="language-"] *::selection':{textShadow:"none",background:"#264F78"},':not(pre) > code[class*="language-"]':{padding:".1em .3em",borderRadius:".3em",color:"#db4c69",background:"#1e1e1e"},".namespace":{Opacity:".7"},"doctype.doctype-tag":{color:"#569CD6"},"doctype.name":{color:"#9cdcfe"},comment:{color:"#6a9955"},prolog:{color:"#6a9955"},punctuation:{color:"#d4d4d4"},".language-html .language-css .token.punctuation":{color:"#d4d4d4"},".language-html .language-javascript .token.punctuation":{color:"#d4d4d4"},property:{color:"#9cdcfe"},tag:{color:"#569cd6"},boolean:{color:"#569cd6"},number:{color:"#b5cea8"},constant:{color:"#9cdcfe"},symbol:{color:"#b5cea8"},inserted:{color:"#b5cea8"},unit:{color:"#b5cea8"},selector:{color:"#d7ba7d"},"attr-name":{color:"#9cdcfe"},string:{color:"#ce9178"},char:{color:"#ce9178"},builtin:{color:"#ce9178"},deleted:{color:"#ce9178"},".language-css .token.string.url":{textDecoration:"underline"},operator:{color:"#d4d4d4"},entity:{color:"#569cd6"},"operator.arrow":{color:"#569CD6"},atrule:{color:"#ce9178"},"atrule.rule":{color:"#c586c0"},"atrule.url":{color:"#9cdcfe"},"atrule.url.function":{color:"#dcdcaa"},"atrule.url.punctuation":{color:"#d4d4d4"},keyword:{color:"#569CD6"},"keyword.module":{color:"#c586c0"},"keyword.control-flow":{color:"#c586c0"},function:{color:"#dcdcaa"},"function.maybe-class-name":{color:"#dcdcaa"},regex:{color:"#d16969"},important:{color:"#569cd6"},italic:{fontStyle:"italic"},"class-name":{color:"#4ec9b0"},"maybe-class-name":{color:"#4ec9b0"},console:{color:"#9cdcfe"},parameter:{color:"#9cdcfe"},interpolation:{color:"#9cdcfe"},"punctuation.interpolation-punctuation":{color:"#569cd6"},variable:{color:"#9cdcfe"},"imports.maybe-class-name":{color:"#9cdcfe"},"exports.maybe-class-name":{color:"#9cdcfe"},escape:{color:"#d7ba7d"},"tag.punctuation":{color:"#808080"},cdata:{color:"#808080"},"attr-value":{color:"#ce9178"},"attr-value.punctuation":{color:"#ce9178"},"attr-value.punctuation.attr-equals":{color:"#d4d4d4"},namespace:{color:"#4ec9b0"},'pre[class*="language-javascript"]':{color:"#9cdcfe"},'code[class*="language-javascript"]':{color:"#9cdcfe"},'pre[class*="language-jsx"]':{color:"#9cdcfe"},'code[class*="language-jsx"]':{color:"#9cdcfe"},'pre[class*="language-typescript"]':{color:"#9cdcfe"},'code[class*="language-typescript"]':{color:"#9cdcfe"},'pre[class*="language-tsx"]':{color:"#9cdcfe"},'code[class*="language-tsx"]':{color:"#9cdcfe"},'pre[class*="language-css"]':{color:"#ce9178"},'code[class*="language-css"]':{color:"#ce9178"},'pre[class*="language-html"]':{color:"#d4d4d4"},'code[class*="language-html"]':{color:"#d4d4d4"},".language-regex .token.anchor":{color:"#dcdcaa"},".language-html .token.punctuation":{color:"#808080"},'pre[class*="language-"] > code[class*="language-"]':{position:"relative",zIndex:"1"},".line-highlight.line-highlight":{background:"#f7ebc6",boxShadow:"inset 5px 0 0 #f7d87c",zIndex:"0"}};var zy=vy();const gs=me(zy);var Py=ds();const By=me(Py);var $y=xy();const qy=me($y);var Uy=ky();const ms=me(Uy);var Hy=cs();const Wy=me(Hy);var Vy=Sy();const Gy=me(Vy);var Zy=Ey();const Xy=me(Zy);var Ky=Cy();const Yy=me(Ky);var Qy=ps();const bs=me(Qy);var Jy=Ty();const ex=me(Jy);var tx=hs();const nx=me(tx);var rx=Ay();const ix=me(rx);var ax=Ny();const ys=me(ax);var ox=us();const Ui=me(ox);var lx=Ly();const sx=me(lx);var ux=Iy();const xs=me(ux);var cx=wy();const ks=me(cx);var px=jy();const dx=me(px);var fx=yy();const hx=me(fx);var gx=Ry();const mx=me(gx);var bx=Dy();const yx=me(bx);var xx=fs();const vs=me(xx);var kx=Oy();const ws=me(kx);function Je(e,t){Ks(e)||t(e instanceof Error?e.message:String(e))}const vx={bash:gs,c:By,cpp:qy,csharp:ms,css:Wy,diff:Gy,go:Xy,java:Yy,javascript:bs,json:ex,jsx:nx,kotlin:ix,markdown:ys,markup:Ui,php:sx,python:xs,ruby:ks,rust:dx,sql:hx,swift:mx,tsx:yx,typescript:vs,yaml:ws};Object.entries(vx).forEach(([e,t])=>{$e.registerLanguage(e,t)});$e.registerLanguage("cs",ms);$e.registerLanguage("html",Ui);$e.registerLanguage("js",bs);$e.registerLanguage("md",ys);$e.registerLanguage("py",xs);$e.registerLanguage("rb",ks);$e.registerLanguage("sh",gs);$e.registerLanguage("ts",vs);$e.registerLanguage("xml",Ui);$e.registerLanguage("yml",ws);function Wt(e){return e<1e3?`${Math.round(e)}ms`:`${(e/1e3).toFixed(1)}s`}function Hi(e,t){return e==="en-US"&&t!==1?"s":""}function wx(e,t){if(!e||e.length<=t)return e;const n=t-3,r=Math.ceil(n*.6),i=n-r;return e.slice(0,r)+"..."+e.slice(-i)}function Jr(e){return e.replace(/#img:\S+\s*/g,"").replace(/\[Image:.*?\]\n(?:Path:.*?\n|Image ID:.*?\n)?/g,"").trim()}function Ss(e){if(navigator.clipboard?.writeText)return navigator.clipboard.writeText(e);const t=document.createElement("textarea");t.value=e,t.style.cssText="position:fixed;left:-9999px;top:-9999px;opacity:0",document.body.appendChild(t),t.select();try{document.execCommand("copy")}finally{document.body.removeChild(t)}return Promise.resolve()}const Sx=({code:e})=>{const[t,n]=N.useState(!1),r=async()=>{try{await Ss(e),n(!0),setTimeout(()=>n(!1),2e3)}catch{}};return h.jsx("button",{className:`copy-button${t?" copy-success":""}`,onClick:r,type:"button",children:t?h.jsx("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("polyline",{points:"20 6 9 17 4 12"})}):h.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),h.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]})})},vn="computer://",bi="file://",Uo="{{workspaceFolder}}",yi="bitfun.mobile.last_selected_model_id",_x=new Set(["js","jsx","ts","tsx","mjs","cjs","mts","cts","py","pyw","pyi","rs","go","java","kt","kts","scala","groovy","c","cpp","cc","cxx","h","hpp","hxx","hh","cs","rb","php","swift","vue","svelte","css","scss","less","sass","json","jsonc","yaml","yml","toml","xml","md","mdx","rst","txt","sh","bash","zsh","fish","ps1","bat","cmd","sql","graphql","gql","proto","lock","env","ini","cfg","conf","cj","ets","editorconfig","gitignore","log"]),Ex=new Set(["pdf","doc","docx","xls","xlsx","ppt","pptx","odt","ods","odp","rtf","pages","numbers","key","png","jpg","jpeg","gif","bmp","svg","webp","ico","tiff","tif","zip","tar","gz","bz2","7z","rar","dmg","iso","xz","mp3","wav","ogg","flac","aac","m4a","wma","mp4","avi","mkv","mov","webm","wmv","flv","csv","tsv","sqlite","db","parquet","epub","mobi","apk","ipa","exe","msi","deb","rpm","ttf","otf","woff","woff2"]);function wn(e){let t=e;e.startsWith(vn)?t=e.slice(vn.length):e.startsWith(bi)?t=e.slice(bi.length):e.startsWith("file:")&&(t=e.slice(5)),t.startsWith(Uo)&&(t=t.slice(Uo.length),t.startsWith("/")&&(t=t.slice(1))),/^\/[A-Za-z]:[\\/]/.test(t)&&(t=t.slice(1));try{return decodeURIComponent(t)}catch{return t}}function Cx(e){if(!e||e==="/")return null;let t;if(e.startsWith(vn)||e.startsWith(bi)||e.startsWith("file:"))t=wn(e);else{if(e.includes("://")||e.startsWith("#")||e.startsWith("//"))return null;t=wn(e)}if(t.startsWith("/")&&t.split("/").filter(Boolean).length<2)return null;const n=t.split("/").pop()||"",r=n.lastIndexOf(".");if(r<=0)return null;const i=n.slice(r+1).toLowerCase();if(!i)return null;if(t.startsWith("/")){if(_x.has(i))return null}else if(!Ex.has(i))return null;return t}function Tx(e){return e>=1024*1024?`${(e/(1024*1024)).toFixed(1)} MB`:e>=1024?`${Math.round(e/1024)} KB`:`${e} B`}const ei=({size:e=20,style:t})=>h.jsxs("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",style:t,"aria-hidden":"true",children:[h.jsx("path",{d:"M15.3929 4.05365L14.8912 4.61112L15.3929 4.05365ZM19.3517 7.61654L18.85 8.17402L19.3517 7.61654ZM21.654 10.1541L20.9689 10.4592V10.4592L21.654 10.1541ZM3.17157 20.8284L3.7019 20.2981H3.7019L3.17157 20.8284ZM20.8284 20.8284L20.2981 20.2981L20.2981 20.2981L20.8284 20.8284ZM14 21.25H10V22.75H14V21.25ZM2.75 14V10H1.25V14H2.75ZM21.25 13.5629V14H22.75V13.5629H21.25ZM14.8912 4.61112L18.85 8.17402L19.8534 7.05907L15.8947 3.49618L14.8912 4.61112ZM22.75 13.5629C22.75 11.8745 22.7651 10.8055 22.3391 9.84897L20.9689 10.4592C21.2349 11.0565 21.25 11.742 21.25 13.5629H22.75ZM18.85 8.17402C20.2034 9.3921 20.7029 9.86199 20.9689 10.4592L22.3391 9.84897C21.9131 8.89241 21.1084 8.18853 19.8534 7.05907L18.85 8.17402ZM10.0298 2.75C11.6116 2.75 12.2085 2.76158 12.7405 2.96573L13.2779 1.5653C12.4261 1.23842 11.498 1.25 10.0298 1.25V2.75ZM15.8947 3.49618C14.8087 2.51878 14.1297 1.89214 13.2779 1.5653L12.7405 2.96573C13.2727 3.16993 13.7215 3.55836 14.8912 4.61112L15.8947 3.49618ZM10 21.25C8.09318 21.25 6.73851 21.2484 5.71085 21.1102C4.70476 20.975 4.12511 20.7213 3.7019 20.2981L2.64124 21.3588C3.38961 22.1071 4.33855 22.4392 5.51098 22.5969C6.66182 22.7516 8.13558 22.75 10 22.75V21.25ZM1.25 14C1.25 15.8644 1.24841 17.3382 1.40313 18.489C1.56076 19.6614 1.89288 20.6104 2.64124 21.3588L3.7019 20.2981C3.27869 19.8749 3.02502 19.2952 2.88976 18.2892C2.75159 17.2615 2.75 15.9068 2.75 14H1.25ZM14 22.75C15.8644 22.75 17.3382 22.7516 18.489 22.5969C19.6614 22.4392 20.6104 22.1071 21.3588 21.3588L20.2981 20.2981C19.8749 20.7213 19.2952 20.975 18.2892 21.1102C17.2615 21.2484 15.9068 21.25 14 21.25V22.75ZM21.25 14C21.25 15.9068 21.2484 17.2615 21.1102 18.2892C20.975 19.2952 20.7213 19.8749 20.2981 20.2981L21.3588 21.3588C22.1071 20.6104 22.4392 19.6614 22.5969 18.489C22.7516 17.3382 22.75 15.8644 22.75 14H21.25ZM2.75 10C2.75 8.09318 2.75159 6.73851 2.88976 5.71085C3.02502 4.70476 3.27869 4.12511 3.7019 3.7019L2.64124 2.64124C1.89288 3.38961 1.56076 4.33855 1.40313 5.51098C1.24841 6.66182 1.25 8.13558 1.25 10H2.75ZM10.0298 1.25C8.15538 1.25 6.67442 1.24842 5.51887 1.40307C4.34232 1.56054 3.39019 1.8923 2.64124 2.64124L3.7019 3.7019C4.12453 3.27928 4.70596 3.02525 5.71785 2.88982C6.75075 2.75158 8.11311 2.75 10.0298 2.75V1.25Z",fill:"currentColor"}),h.jsx("path",{d:"M6 14.5H14",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"}),h.jsx("path",{d:"M6 18H11.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"}),h.jsx("path",{d:"M13 2.5V5C13 7.35702 13 8.53553 13.7322 9.26777C14.4645 10 15.643 10 18 10H22",stroke:"currentColor",strokeWidth:"1.5"})]}),Ho=({path:e,onGetFileInfo:t,onDownload:n})=>{const{t:r}=Ye(),[i,o]=N.useState({status:"loading"}),a=N.useRef(t);a.current=t,N.useEffect(()=>{let g=!1;return a.current(e).then(({name:k,size:S,mimeType:x})=>{g||o({status:"ready",name:k,size:S,mimeType:x})}).catch(k=>{g||o({status:"error",message:k instanceof Error?k.message:String(k)})}),()=>{g=!0}},[e]);const l=N.useCallback(async()=>{if(i.status!=="ready"&&i.status!=="done")return;const g=i;o({status:"downloading",name:g.name,size:g.size,mimeType:g.mimeType,progress:0});try{await n(e,(k,S)=>{o(x=>x.status!=="downloading"?x:{...x,progress:S>0?k/S:0})}),o({status:"done",name:g.name,size:g.size,mimeType:g.mimeType})}catch{o({status:"ready",name:g.name,size:g.size,mimeType:g.mimeType})}},[i,e,n]),s={display:"inline-flex",alignItems:"center",gap:"10px",padding:"10px 14px",border:"1px solid var(--bf-color-border-subtle)",borderRadius:"10px",background:"var(--bf-color-surface-subtle)",cursor:i.status==="ready"||i.status==="done"?"pointer":"default",maxWidth:"300px",verticalAlign:"middle",transition:"background 0.15s"},u="var(--bf-color-content-muted)";if(i.status==="loading")return h.jsxs("span",{className:"file-card",style:s,children:[h.jsx(ei,{size:20,style:{color:u,flexShrink:0}}),h.jsx("span",{style:{fontSize:"0.8rem",opacity:.5},children:r("chat.fileLoading")})]});if(i.status==="error")return h.jsxs("span",{className:"file-card",style:{...s,cursor:"default",opacity:.5},title:i.message,children:[h.jsx(ei,{size:20,style:{color:u,flexShrink:0}}),h.jsx("span",{style:{fontSize:"0.8rem"},children:r("chat.fileUnavailable")})]});const{name:p,size:c}=i,f=i.status==="downloading",d=i.status==="done";return h.jsxs("span",{className:"file-card",style:s,onClick:l,role:"button",tabIndex:0,onKeyDown:g=>{(g.key==="Enter"||g.key===" ")&&l()},title:r(f?"chat.fileDownloading":d?"chat.fileDownloaded":"chat.clickToDownload"),children:[h.jsx(ei,{size:20,style:{color:u,flexShrink:0}}),h.jsxs("span",{style:{minWidth:0,overflow:"hidden"},children:[h.jsx("span",{style:{display:"block",fontSize:"0.85rem",fontWeight:500,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",color:"var(--bf-color-content-primary)"},children:p}),h.jsx("span",{style:{display:"block",fontSize:"0.75rem",color:"var(--bf-color-content-muted)",marginTop:"2px"},children:Tx(c)})]}),h.jsx("span",{style:{flexShrink:0,fontSize:"0.75rem",color:d?"var(--bf-color-status-success-content)":"var(--bf-color-content-muted)"},children:f?`${Math.round(i.progress*100)}%`:d?"✓":"↓"})]})},Kt=({content:e,onFileDownload:t,onGetFileInfo:n})=>{const{isDark:r}=Zo(),i=r?Fy:My,o=N.useMemo(()=>({code({className:a,children:l,...s}){const u=/language-(\w+)/.exec(a||""),p=String(l).replace(/\n$/,""),c=p.includes(` +`);return a?.startsWith("language-")||c?h.jsxs("div",{className:"code-block-wrapper",children:[h.jsx(Sx,{code:p}),h.jsx($e,{language:u?.[1]||"text",style:i,showLineNumbers:!0,customStyle:{margin:0,borderRadius:"8px",fontSize:"0.8rem",lineHeight:"1.5"},codeTagProps:{style:{fontFamily:"var(--font-family-mono)"}},lineNumberStyle:{color:"var(--bf-color-content-muted)",paddingRight:"1em",textAlign:"right",userSelect:"none",minWidth:"2.5em"},children:p})]}):h.jsx("code",{className:"inline-code",...s,children:l})},a({href:a,children:l}){const s=typeof a=="string"&&a.startsWith(vn);if(s&&n&&t){const u=wn(a);return h.jsx(Ho,{path:u,onGetFileInfo:n,onDownload:t})}if(s&&t){const u=wn(a);return h.jsx("button",{className:"file-link",onClick:p=>{p.preventDefault(),p.stopPropagation(),t(u)},type:"button",style:{cursor:"pointer",color:"var(--bf-color-accent-default)",textDecoration:"underline",background:"none",border:"none",font:"inherit",padding:0},children:l})}if(n&&t){const u=typeof a=="string"?Cx(a):null;if(u)return h.jsx(Ho,{path:u,onGetFileInfo:n,onDownload:t})}return typeof a=="string"&&(a.startsWith("http://")||a.startsWith("https://"))?h.jsx("a",{href:a,target:"_blank",rel:"noopener noreferrer",style:{color:"var(--bf-color-accent-default)",textDecoration:"underline"},children:l}):h.jsx("span",{style:{textDecoration:"underline",opacity:.7},children:l})},table({children:a}){return h.jsx("div",{className:"table-wrapper",children:h.jsx("table",{children:a})})},blockquote({children:a}){return h.jsx("blockquote",{className:"custom-blockquote",children:a})}}),[i,r,t,n]);return h.jsx(uf,{remarkPlugins:[Sg],components:o,urlTransform:a=>a.startsWith("computer://")||/^(https?|mailto|tel|file):/i.test(a)||a.startsWith("#")||a.startsWith("/")||!a.includes(":")?a:"",children:e})},xi=({thinking:e,streaming:t,isLastItem:n=!1})=>{const{t:r}=Ye(),[i,o]=N.useState(!!t),a=N.useRef(!1),l=N.useRef(null),[s,u]=N.useState({atTop:!0,atBottom:!0}),p=Cs(e,!!t);N.useEffect(()=>{a.current||(t?o(!0):n||o(!1))},[t,n]),N.useEffect(()=>{if(!t||!i)return;const k=l.current;if(!k)return;k.scrollHeight-k.scrollTop-k.clientHeight<80&&(k.scrollTop=k.scrollHeight)},[p,t,i]);const c=N.useCallback(()=>{const k=l.current;k&&u({atTop:k.scrollTop<4,atBottom:k.scrollHeight-k.scrollTop-k.clientHeight<4})},[]),f=N.useCallback(()=>{a.current=!0,o(k=>!k)},[]);if(!e&&!t)return null;const d=e.length,g=t&&d===0?r("chat.thinking"):r("chat.thoughtCharacters",{count:d});return h.jsxs("div",{className:`chat-thinking ${t?"chat-thinking--streaming":""}`,children:[h.jsxs("button",{className:"chat-thinking__toggle",onClick:f,children:[h.jsx("span",{className:`chat-thinking__chevron ${i?"is-open":""}`,children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-thinking__label",children:g})]}),h.jsx("div",{className:`chat-thinking__expand-container ${i?"is-expanded":""}`,children:h.jsx("div",{className:"chat-thinking__expand-inner",children:e&&h.jsx("div",{className:`chat-thinking__content-wrapper ${s.atTop?"at-top":""} ${s.atBottom?"at-bottom":""}`,ref:l,onScroll:c,children:h.jsx("div",{className:"chat-thinking__content",children:h.jsx(Kt,{content:t?p:e})})})})})]})},Sn={explore:"shared.tools.explore",read_file:"shared.tools.read",write_file:"shared.tools.write",list_directory:"tools.ls",bash:"shared.tools.shell",glob:"tools.glob",grep:"tools.grep",create_file:"shared.tools.write",delete_file:"tools.delete",Task:"tools.task",search:"shared.tools.search",edit_file:"shared.tools.edit",web_search:"tools.web",TodoWrite:"shared.tools.todo"},Ax=({tool:e})=>{const{t}=Ye(),[n,r]=N.useState(!1),i=N.useMemo(()=>{const u=e.tool_input;if(!u)return[];const p=u.todos||u.result?.todos;return Array.isArray(p)?p:[]},[e.tool_input]);if(i.length===0)return null;const o=i.filter(u=>u.status==="completed").length,a=o===i.length,l=i.find(u=>u.status==="in_progress"),s=u=>{switch(u){case"completed":return h.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"var(--bf-color-status-success-content)",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("path",{d:"M22 11.08V12a10 10 0 1 1-5.93-9.14"}),h.jsx("path",{d:"m9 11 3 3L22 4"})]});case"in_progress":return h.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"var(--bf-color-accent-default)",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("circle",{cx:"12",cy:"12",r:"10"}),h.jsx("polygon",{points:"10 8 16 12 10 16 10 8",fill:"var(--bf-color-accent-default)"})]});case"cancelled":return h.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"var(--bf-color-status-danger-content)",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("circle",{cx:"12",cy:"12",r:"10"}),h.jsx("path",{d:"m15 9-6 6"}),h.jsx("path",{d:"m9 9 6 6"})]});default:return h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"var(--bf-color-content-muted)",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("circle",{cx:"12",cy:"12",r:"10"})})}};return h.jsxs("div",{className:"chat-todo-card",children:[h.jsxs("div",{className:"chat-todo-card__header",onClick:()=>r(!n),children:[h.jsx("span",{className:"chat-todo-card__icon",children:h.jsxs("svg",{width:"14",height:"14",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("rect",{x:"3",y:"5",width:"6",height:"6",rx:"1"}),h.jsx("path",{d:"m3 17 2 2 4-4"}),h.jsx("path",{d:"M13 6h8"}),h.jsx("path",{d:"M13 12h8"}),h.jsx("path",{d:"M13 18h8"})]})}),a&&!n?h.jsx("span",{className:"chat-todo-card__current chat-todo-card__current--done",children:t("chat.allTasksCompleted")}):l&&!n?h.jsx("span",{className:"chat-todo-card__current",children:l.content}):null,h.jsxs("span",{className:"chat-todo-card__right",children:[h.jsx("span",{className:"chat-todo-card__dots",children:i.map((u,p)=>h.jsx("span",{className:`chat-todo-card__dot chat-todo-card__dot--${u.status}`},u.id||p))}),h.jsxs("span",{className:"chat-todo-card__stats",children:[o,"/",i.length]})]}),h.jsx("span",{className:`chat-todo-card__chevron ${n?"is-expanded":""}`,children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("path",{d:"m6 9 6 6 6-6"})})})]}),n&&h.jsx("div",{className:"chat-todo-card__list",children:i.map((u,p)=>h.jsxs("div",{className:`chat-todo-card__item chat-todo-card__item--${u.status}`,children:[s(u.status),h.jsx("span",{className:"chat-todo-card__item-text",children:u.content})]},u.id||p))})]})};function Lx(e){const t=e.tool_input??(()=>{try{return JSON.parse(e.input_preview||"")}catch{return null}})();return t?{description:t.description,agentType:t.subagent_type}:null}function Nx(e,t){if(e.type==="thinking"){const n=(e.content||"").length;return t("chat.thoughtCharacters",{count:n})}if(e.type==="tool"&&e.tool){const n=e.tool,r=n.input_preview?`: ${n.input_preview}`:"";return`${n.name}${r}`}if(e.type==="text"){const n=(e.content||"").length;return t("chat.textCharacters",{count:n})}return""}const _s=({tool:e,now:t,subItems:n=[],onCancelTool:r})=>{const{t:i,language:o}=Ye(),a=N.useRef(null),l=N.useRef(0),[s,u]=N.useState(!1),p=e.status==="running",c=e.status==="completed",f=e.status==="failed"||e.status==="error",d=p&&!!r,g=Lx(e),k=c&&e.duration_ms!=null?Wt(e.duration_ms):p&&e.start_ms?Wt(t-e.start_ms):"",S=p?"running":c?"done":f?"error":"pending",x=n.filter(_=>_.type==="tool"&&_.tool),v=x.filter(_=>_.tool.status==="completed").length,b=x.filter(_=>_.tool.status==="running").length;return N.useEffect(()=>{s&&n.length>l.current&&a.current&&(a.current.scrollTop=a.current.scrollHeight),l.current=n.length},[n.length,s]),h.jsxs("div",{className:`chat-task-card chat-task-card--${S}`,children:[h.jsxs("div",{className:"chat-task-card__header",children:[h.jsx("span",{className:"chat-tool-card__icon",children:p?h.jsx("span",{className:"chat-tool-card__spinner"}):c?h.jsx("span",{className:"chat-tool-card__check",children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8.5L6.5 12L13 4",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}):f?h.jsx("span",{className:"chat-tool-card__error-icon",children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 4L12 12M12 4L4 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})})}):h.jsx("span",{className:"chat-tool-card__spinner"})}),h.jsx("span",{className:"chat-tool-card__name",children:g?.description||i("chat.task")}),g?.agentType&&h.jsx("span",{className:"chat-tool-card__type",children:g.agentType}),k&&h.jsx("span",{className:"chat-tool-card__duration",children:k}),d&&h.jsx("button",{className:"chat-tool-card__cancel",onClick:_=>{_.stopPropagation(),r?.(e.id)},"aria-label":i("common.cancel"),children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("rect",{x:"3",y:"3",width:"10",height:"10",rx:"2",fill:"currentColor"})})})]}),n.length>0&&h.jsxs(h.Fragment,{children:[h.jsxs("div",{className:"chat-task-card__summary",onClick:()=>u(_=>!_),children:[h.jsx("span",{className:"chat-task-card__stat",children:i("chat.toolCalls",{count:x.length,suffix:Hi(o,x.length)})}),h.jsxs("span",{className:"chat-task-card__stat-right",children:[h.jsx("span",{className:"chat-task-card__stat--done",children:i("chat.done",{count:v})}),b>0&&h.jsx("span",{className:"chat-task-card__stat--running",children:i("chat.running",{count:b})})]}),h.jsx("span",{className:`chat-task-card__chevron ${s?"is-expanded":""}`,children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("path",{d:"m6 9 6 6 6-6"})})})]}),s&&h.jsx("div",{className:"chat-task-card__steps",ref:a,children:n.map((_,C)=>{if(_.type==="thinking")return h.jsxs("div",{className:"chat-task-card__step chat-task-card__step--thinking",children:[h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("path",{d:"m6 9 6 6 6-6"})}),h.jsx("span",{children:Nx(_,i)})]},`sub-think-${C}`);if(_.type==="tool"&&_.tool){const m=_.tool,T=m.status==="completed",j=m.status==="failed"||m.status==="error";return h.jsxs("div",{className:`chat-task-card__step chat-task-card__step--tool ${T?"is-done":j?"is-error":"is-running"}`,children:[T?h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8.5L6.5 12L13 4",stroke:"var(--bf-color-status-success-content)",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})}):j?h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 4L12 12M12 4L4 12",stroke:"var(--bf-color-status-danger-content)",strokeWidth:"2",strokeLinecap:"round"})}):h.jsx("span",{className:"chat-task-card__step-spinner"}),h.jsx("span",{className:"chat-task-card__step-name",children:m.name}),(()=>{const A=Es(m);return A?h.jsx("span",{className:"chat-task-card__step-preview",children:A}):null})(),T&&m.duration_ms!=null&&h.jsx("span",{className:"chat-task-card__step-duration",children:Wt(m.duration_ms)})]},`sub-tool-${m.id}-${C}`)}return null})})]})]})};function Es(e){if(!e.input_preview)return null;try{const t=JSON.parse(e.input_preview);if(!t||typeof t!="object")return null;const n=o=>{const a=o.replace(/\\/g,"/").split("/");return a[a.length-1]||o};let r=null;const i=t.file_path||t.path;switch(e.name){case"Read":case"Write":case"Edit":case"LS":case"StrReplace":case"delete_file":r=i?n(i):null;break;case"Glob":case"Grep":r=t.pattern||null;break;case"Bash":case"Shell":r=t.description||t.command||null;break;case"web_search":case"WebSearch":r=t.search_term||t.query||null;break;case"WebFetch":r=t.url||null;break;case"SemanticSearch":r=t.query||null;break;default:r=Object.values(t).find(a=>typeof a=="string"&&a.length>0&&a.length<80)||null}return r?r.length>60?r.slice(0,60)+"…":r:null}catch{return null}}const Wo=({tool:e,now:t,onCancelTool:n})=>{const{t:r}=Ye(),i=e.name.toLowerCase().replace(/[\s-]/g,"_"),o=Sn[i]||Sn[e.name],a=o?r(o):"Tool",l=e.status==="running",s=e.status==="completed",u=e.status==="failed"||e.status==="error",p=l&&!!n,c=Es(e),f=s&&e.duration_ms!=null?Wt(e.duration_ms):l&&e.start_ms?Wt(t-e.start_ms):"",d=l?"running":s?"done":u?"error":"pending";return h.jsx("div",{className:`chat-tool-card chat-tool-card--${d}`,children:h.jsxs("div",{className:"chat-tool-card__row",children:[h.jsx("span",{className:"chat-tool-card__icon",children:l?h.jsx("span",{className:"chat-tool-card__spinner"}):s?h.jsx("span",{className:"chat-tool-card__check",children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8.5L6.5 12L13 4",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}):u?h.jsx("span",{className:"chat-tool-card__error-icon",children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 4L12 12M12 4L4 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})})}):h.jsx("span",{className:"chat-tool-card__spinner"})}),h.jsxs("span",{className:"chat-tool-card__name",children:[e.name,c&&h.jsxs("span",{className:"chat-tool-card__preview",children:[" ",c]})]}),h.jsx("span",{className:"chat-tool-card__type",children:a}),f&&h.jsx("span",{className:"chat-tool-card__duration",children:f}),p&&h.jsx("button",{className:"chat-tool-card__cancel",onClick:g=>{g.stopPropagation(),n?.(e.id)},"aria-label":r("common.cancel"),children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("rect",{x:"3",y:"3",width:"10",height:"10",rx:"2",fill:"currentColor"})})})]})})},Ix=new Set(["Read","Grep","Glob","SemanticSearch"]);function jx(e,t){const n=new Map,r=[];for(const i of e){const o=i.name.toLowerCase().replace(/[\s-]/g,"_"),a=Sn[o]||Sn[i.name],l=a?t(a):i.name,s=l.toLowerCase(),u=n.get(s);if(u){u.count+=1;continue}n.set(s,{label:l,count:1}),r.push(s)}return r.map(i=>{const o=n.get(i);return`${o.label} ${o.count}`}).join(", ")}const Rx=({tools:e})=>{const{t}=Ye(),[n,r]=N.useState(!1);if(e.length===0)return null;const i=e.filter(s=>s.status==="completed").length,o=i===e.length,a=jx(e,t),l=o?t("chat.readToolsDone",{summary:a}):t("chat.readToolsRunning",{summary:a,doneCount:i});return h.jsxs("div",{className:`chat-thinking ${o?"":"chat-thinking--streaming"}`,children:[h.jsxs("button",{className:"chat-thinking__toggle",onClick:()=>r(s=>!s),children:[h.jsx("span",{className:`chat-thinking__chevron ${n?"is-open":""}`,children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-thinking__label",children:l})]}),n&&h.jsx("div",{className:"chat-thinking__content-wrapper at-top at-bottom",children:h.jsx("div",{className:"chat-thinking__content",children:e.map(s=>{const u=s.input_preview||"";return h.jsxs("div",{style:{fontSize:"12px",padding:"2px 0",opacity:.8},children:[s.status==="completed"?"✓":"⋯"," ",s.name," ",u]},s.id)})})})]})},Ox=2,ki=({tools:e,now:t,onCancelTool:n})=>{const{t:r,language:i}=Ye(),o=N.useRef(null),a=N.useRef(0),[l,s]=N.useState(!1);if(N.useEffect(()=>{l&&e.length>a.current&&o.current&&(o.current.scrollTop=o.current.scrollHeight),a.current=e.length},[e.length,l]),!e||e.length===0)return null;if(e.length<=Ox)return h.jsx("div",{className:"chat-tool-list",children:e.map(c=>h.jsx(Wo,{tool:c,now:t,onCancelTool:n},c.id))});const u=e.filter(c=>c.status==="running").length,p=e.filter(c=>c.status==="completed").length;return h.jsxs("div",{className:"chat-tool-list chat-tool-list--collapsed",children:[h.jsxs("div",{className:"chat-tool-list__header",onClick:()=>s(c=>!c),children:[h.jsx("span",{className:"chat-tool-list__count",children:r("chat.toolCalls",{count:e.length,suffix:Hi(i,e.length)})}),h.jsxs("span",{className:"chat-tool-list__stats",children:[p>0&&h.jsx("span",{className:"chat-tool-list__stat chat-tool-list__stat--done",children:r("chat.done",{count:p})}),u>0&&h.jsx("span",{className:"chat-tool-list__stat chat-tool-list__stat--running",children:r("chat.running",{count:u})})]}),h.jsx("span",{className:`chat-tool-list__chevron ${l?"is-expanded":""}`,children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("path",{d:"m6 9 6 6 6-6"})})})]}),l&&h.jsx("div",{className:"chat-tool-list__scroll",ref:o,children:e.map(c=>h.jsx(Wo,{tool:c,now:t,onCancelTool:n},c.id))})]})},ti=()=>h.jsxs("span",{className:"chat-msg__typing",children:[h.jsx("span",{}),h.jsx("span",{}),h.jsx("span",{})]});function Cs(e,t){const[n,r]=N.useState(t?"":e),i=N.useRef(t?0:e.length),o=N.useRef(e),a=N.useRef(null),l=N.useRef(3);return N.useEffect(()=>{if(!t){a.current&&(clearInterval(a.current),a.current=null),i.current=e.length,o.current=e,r(e);return}o.current=e,e.length0){const c=26.666666666666668;l.current=Math.max(Math.ceil(s/c),2),a.current||(a.current=setInterval(()=>{const f=o.current,d=i.current;if(d>=f.length){a.current&&(clearInterval(a.current),a.current=null);return}const g=Math.min(d+l.current,f.length);i.current=g,r(f.slice(0,g))},30))}},[e,t]),N.useEffect(()=>()=>{a.current&&clearInterval(a.current)},[]),n}const Ts=({content:e,onFileDownload:t,onGetFileInfo:n})=>{const r=Cs(e,!0);return h.jsx(Kt,{content:r,onFileDownload:t,onGetFileInfo:n})},_n=e=>!e||e.name!=="AskUserQuestion"||!e.tool_input?!1:!["completed","failed","cancelled","rejected"].includes(e.status);function Dx(e,t){const n=t.split(".");let r=e;for(const i of n){if(!r||typeof r!="object"||!(i in r))return null;r=r[i]}return typeof r=="string"?r:null}const Mx=new Set(["other",...Object.values(Ys).map(e=>Dx(e,"common.other")).filter(e=>!!e).map(e=>e.trim().toLowerCase())]),xt=e=>{const t=(e||"").trim().toLowerCase();return Mx.has(t)},As=({tool:e,onAnswer:t})=>{const{t:n,language:r}=Ye(),i=e.tool_input?.questions||[],[o,a]=N.useState({}),[l,s]=N.useState({}),[u,p]=N.useState(!1),[c,f]=N.useState(!1),d=N.useMemo(()=>i.map(x=>{const v=Array.isArray(x.options)?x.options:[],b=v.some(_=>xt(_?.label));return{...x,options:v,hasBuiltInOther:b}}),[i]);if(d.length===0)return null;const g=(x,v,b)=>{a(_=>{if(b){const C=_[x]||[];return{..._,[x]:C.includes(v)?C.filter(m=>m!==v):[...C,v]}}return{..._,[x]:_[x]===v?void 0:v}})},k=async()=>{if(!S||u||c)return;const x={};d.forEach((v,b)=>{const _=o[b],C=(l[b]||"").trim();Array.isArray(_)?x[String(b)]=_.map(m=>xt(m)&&C||m):xt(_)?x[String(b)]=C||_:x[String(b)]=_??""}),p(!0);try{await t(e.id,x),f(!0)}finally{p(!1)}},S=d.every((x,v)=>{const b=o[v];return(x.multiSelect?Array.isArray(b)&&b.length>0:!!b)?!(Array.isArray(b)?b.some(m=>xt(m)):xt(b))||!!(l[v]||"").trim():!1});return h.jsxs("div",{className:"chat-ask-card",children:[h.jsxs("div",{className:"chat-ask-card__header",children:[h.jsx("span",{className:"chat-ask-card__count",children:n("chat.askQuestionCount",{count:i.length,suffix:Hi(r,i.length)})}),!c&&!u&&h.jsx("span",{className:"chat-ask-card__waiting",children:n("chat.waiting")})]}),d.map((x,v)=>{const b=o[v],_=Array.isArray(b)?b.some(C=>xt(C)):xt(b);return h.jsxs("div",{className:"chat-ask-card__question",children:[h.jsxs("div",{className:"chat-ask-card__question-header",children:[h.jsx("span",{className:"chat-ask-card__tag",children:x.header}),h.jsx("span",{className:"chat-ask-card__question-text",children:x.question})]}),h.jsxs("div",{className:"chat-ask-card__options",children:[(x.options||[]).map((C,m)=>{const T=x.multiSelect?(o[v]||[]).includes(C.label):o[v]===C.label;return h.jsxs("button",{className:`chat-ask-card__option ${T?"is-selected":""}`,onClick:()=>g(v,C.label,x.multiSelect),disabled:c||u,children:[h.jsx("span",{className:`chat-ask-card__radio ${x.multiSelect?"chat-ask-card__radio--multi":""}`,children:T&&h.jsx("svg",{width:"8",height:"8",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8L6.5 11.5L13 4.5",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-ask-card__option-label",children:C.label}),C.description&&h.jsx("span",{className:"chat-ask-card__option-desc",children:C.description})]},m)}),!x.hasBuiltInOther&&h.jsxs("button",{className:`chat-ask-card__option ${_?"is-selected":""}`,onClick:()=>g(v,"Other",x.multiSelect),disabled:c||u,children:[h.jsx("span",{className:`chat-ask-card__radio ${x.multiSelect?"chat-ask-card__radio--multi":""}`,children:_&&h.jsx("svg",{width:"8",height:"8",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M3 8L6.5 11.5L13 4.5",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-ask-card__option-label",children:n("common.other")}),h.jsx("span",{className:"chat-ask-card__option-desc",children:n("common.customTextInput")})]}),_&&h.jsx("input",{className:"chat-ask-card__custom-input",placeholder:n("common.typeYourAnswer"),value:l[v]||"",onChange:C=>s(m=>({...m,[v]:C.target.value})),disabled:c||u})]})]},v)}),h.jsxs("button",{className:"chat-ask-card__submit chat-ask-card__submit--bottom",disabled:!S||c||u,onClick:k,children:[h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M2 8L6 12L14 4",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})}),n(c?"common.submitted":u?"common.submitting":"common.submit")]})]})};function Ls(e){const t=[];let n=null;for(const r of e){if(r.type==="tool"&&r.tool?.name==="Task"){const i={...r,subItems:[]};t.push(i),n=i;continue}if(r.is_subagent&&n){n.subItems.push(r);continue}r.is_subagent||t.push(r)}return t}function Nt(e){const t=[];for(const n of e){const r=t[t.length-1];r&&r.type===n.type?r.entries.push(n):t.push({type:n.type,entries:[n]})}return t}function Ns(e,t,n){return n?e.map((r,i)=>h.jsx(As,{tool:r.tool,onAnswer:n},`${t}-ask-${r.tool.id}-${i}`)):null}function It(e,t,n,r,i,o,a,l){return e.map((s,u)=>{if(s.type==="thinking"){const p=s.entries.map(f=>f.content||"").join(` -`),c=l&&u===e.length-1;return h.jsx(xi,{thinking:p,streaming:c,isLastItem:c},`${t}-thinking-${u}`)}if(s.type==="tool"){const p=[];let c=[],f=[];const d=()=>{f.length>0&&(p.push(h.jsx(Rx,{tools:f},`${t}-read-${u}-${p.length}`)),f=[])},g=()=>{c.length>0&&(p.push(h.jsx(ki,{tools:c,now:n,onCancelTool:r},`${t}-tl-${u}-${p.length}`)),c=[])},k=()=>{d(),g()};for(const S of s.entries)S.tool?.name==="Task"?(k(),p.push(h.jsx(_s,{tool:S.tool,now:n,subItems:S.subItems,onCancelTool:r},`${t}-task-${u}-${p.length}`))):S.tool?.name==="TodoWrite"?(k(),p.push(h.jsx(Ax,{tool:S.tool},`${t}-todo-${u}-${p.length}`))):S.tool&&Ix.has(S.tool.name)?(g(),f.push(S.tool)):S.tool&&(d(),c.push(S.tool));return k(),h.jsx(it.Fragment,{children:p},`${t}-tool-${u}`)}if(s.type==="text"){const p=s.entries.map(c=>c.content||"").join("");return p?h.jsx("div",{className:"chat-msg__assistant-content",children:i?h.jsx(Ts,{content:p,onFileDownload:o,onGetFileInfo:a}):h.jsx(Kt,{content:p,onFileDownload:o,onGetFileInfo:a})},`${t}-text-${u}`):null}return null})}function Vo(e,t,n,r,i,o){const a=Ls(e),l=a.filter(c=>_n(c.tool));if(l.length===0)return It(Nt(a),"ordered",t,n,!1,i,o);const s=[],u=[];let p=!1;for(const c of a)_n(c.tool)?p=!0:p?u.push(c):s.push(c);return h.jsxs(h.Fragment,{children:[It(Nt(s),"ordered-before",t,n,!1,i,o),Ns(l,"ordered",r),It(Nt(u),"ordered-after",t,n,!1,i,o)]})}function Fx(e,t,n,r,i,o,a,l){const s=Ls(e),u=s.filter(g=>_n(g.tool)),p=g=>{i()&&n.cancelTool(g,"User cancelled").catch(k=>{Je(k,r)})};if(u.length===0)return It(Nt(s),"active",t,p,!0,a,l,!0);const c=[],f=[];let d=!1;for(const g of s)_n(g.tool)?d=!0:d?f.push(g):c.push(g);return h.jsxs(h.Fragment,{children:[It(Nt(c),"active-before",t,p,!0,a,l,!0),Ns(u,"active",o),It(Nt(f),"active-after",t,p,!0,a,l,!0)]})}const zx=({isDark:e})=>h.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:e?h.jsx("path",{d:"M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM3 8a5 5 0 0 1 5-5v10a5 5 0 0 1-5-5Z",fill:"currentColor"}):h.jsx("path",{d:"M8 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 1Zm0 11a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 12Zm7-4a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 15 8ZM3 8a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 3 8Zm9.95-3.54a.5.5 0 0 1 0 .71l-.71.7a.5.5 0 1 1-.7-.7l.7-.71a.5.5 0 0 1 .71 0ZM5.46 11.24a.5.5 0 0 1 0 .71l-.7.71a.5.5 0 0 1-.71-.71l.7-.71a.5.5 0 0 1 .71 0Zm7.08 1.42a.5.5 0 0 1-.7 0l-.71-.71a.5.5 0 0 1 .7-.7l.71.7a.5.5 0 0 1 0 .71ZM5.46 4.76a.5.5 0 0 1-.71 0l-.71-.7a.5.5 0 0 1 .71-.71l.7.7a.5.5 0 0 1 0 .71ZM8 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z",fill:"currentColor"})}),vi=({className:e,size:t=10})=>h.jsxs("svg",{className:e,width:t,height:t,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[h.jsx("path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.937A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .962 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.582a.5.5 0 0 1 0 .962L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.962 0z"}),h.jsx("path",{d:"M20 3v4"}),h.jsx("path",{d:"M22 5h-4"}),h.jsx("path",{d:"M4 17v2"}),h.jsx("path",{d:"M5 18H3"})]});function Is(e){const t=e.trim();return t?t.charAt(0).toUpperCase()+t.slice(1):"Unknown"}function Px(e){const t=e.name?.trim();return t||Is(e.provider)}function Bx(e){return e?`${Math.round(e/1e3)}k`:null}function $x(e){return e.enabled&&Array.isArray(e.capabilities)&&e.capabilities.includes("text_chat")}function ut(e,t){const n=e?.trim();if(!n||n==="primary")return"primary";if(n==="fast"){const r=t?.default_models?.fast;return r&&at(r,t)?n:"primary"}return at(n,t)?n:"primary"}function qx(){return typeof window>"u"?null:window.localStorage.getItem(bi)?.trim()||null}function ni(e){if(typeof window>"u")return;const t=e.trim();if(!t){window.localStorage.removeItem(bi);return}window.localStorage.setItem(bi,t)}function Ux(e,t){const n=e?.trim();if(!n)return{modelId:null,fallbackApplied:!1};const r=ut(n,t);return{modelId:r,fallbackApplied:r!==n}}function at(e,t){return t&&t.models.find(n=>n.id===e)||null}function js(e,t){const n=ut(e,t);return n==="primary"?at(t?.default_models?.primary||"",t):n==="fast"?at(t?.default_models?.fast||"",t)||at(t?.default_models?.primary||"",t):at(n,t)}function Vt(e){if(!e)return null;const t=[Px(e)],n=Bx(e.context_window);return n&&t.push(n),t.join(" · ")}function gn(e){return e&&(e.model_name||e.name)||""}function Go(e,t){if(e?.reasoning?.status!=="known")return;const n=t?.session_reasoning_preset?.trim();if(n)return e.reasoning.presets?.find(r=>r.id===n)?.label||n}function Hx(e,t,n){if(e==="primary"||e==="fast"){const i=js(e,t);return{label:n(e==="primary"?"chat.modelPrimary":"chat.modelFast"),meta:Vt(i)||n(e==="primary"?"chat.modelPrimaryDesc":"chat.modelFastDesc"),enableThinking:i?.reasoning?.status==="known",reasoningEffort:Go(i,t)}}const r=at(e,t);return r?{label:gn(r),meta:Vt(r),enableThinking:r.reasoning?.status==="known",reasoningEffort:Go(r,t)}:{label:n("chat.modelPrimary"),meta:n("chat.modelPrimaryDesc"),enableThinking:!1}}const Wx=({catalog:e,selectedModelId:t,disabled:n,onSelect:r})=>{const{t:i}=Ye(),[o,a]=N.useState(!1),l=N.useRef(null),s=N.useMemo(()=>ut(t,e),[e,t]),u=N.useMemo(()=>(e?.models||[]).filter($x),[e]),p=N.useMemo(()=>at(e?.default_models?.primary||"",e),[e]),c=N.useMemo(()=>at(e?.default_models?.fast||"",e),[e]),f=N.useMemo(()=>Hx(s,e,i),[e,s,i]);if(N.useEffect(()=>{if(!o)return;const g=k=>{l.current&&!l.current.contains(k.target)&&a(!1)};return document.addEventListener("mousedown",g),()=>document.removeEventListener("mousedown",g)},[o]),!e)return null;const d=async g=>{await r(g),a(!1)};return h.jsxs("div",{className:"chat-model-selector",ref:l,children:[h.jsxs("button",{className:`chat-model-selector__trigger${o?" chat-model-selector__trigger--open":""}`,type:"button",onClick:()=>a(g=>!g),disabled:n,"aria-label":i("chat.modelSelection"),children:[h.jsx("span",{className:"chat-model-selector__icon","aria-hidden":"true",children:h.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",children:[h.jsx("rect",{x:"4",y:"4",width:"6",height:"6",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7"}),h.jsx("rect",{x:"14",y:"4",width:"6",height:"6",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7"}),h.jsx("rect",{x:"9",y:"14",width:"6",height:"6",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7"}),h.jsx("path",{d:"M10 7h4M12 10v4",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round"})]})}),h.jsxs("span",{className:"chat-model-selector__name",children:[h.jsx("span",{className:"chat-model-selector__name-text",children:f.label}),f.enableThinking&&h.jsx(vi,{className:"chat-model-selector__thinking",size:9})]}),f.reasoningEffort&&h.jsx("span",{className:"chat-model-selector__effort",children:f.reasoningEffort}),h.jsx("span",{className:"chat-model-selector__chevron","aria-hidden":"true",children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 6L8 10L12 6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),o&&h.jsxs("div",{className:"chat-model-selector__dropdown",children:[h.jsx("div",{className:"chat-model-selector__header",children:i("chat.modelSelection")}),h.jsx("button",{className:`chat-model-selector__option${s==="primary"?" is-selected":""}`,type:"button",onClick:()=>{d("primary")},children:h.jsxs("span",{className:"chat-model-selector__option-main",children:[h.jsx("span",{className:"chat-model-selector__option-name",children:i("chat.modelPrimary")}),h.jsxs("span",{className:"chat-model-selector__option-meta chat-model-selector__option-meta--stacked",children:[h.jsx("span",{className:"chat-model-selector__option-meta-line",children:gn(p)||i("chat.modelPrimary")}),h.jsx("span",{className:"chat-model-selector__option-meta-line",children:Vt(p)||i("chat.modelPrimaryDesc")})]})]})}),h.jsx("button",{className:`chat-model-selector__option${s==="fast"?" is-selected":""}`,type:"button",onClick:()=>{d("fast")},children:h.jsxs("span",{className:"chat-model-selector__option-main",children:[h.jsx("span",{className:"chat-model-selector__option-name",children:i("chat.modelFast")}),h.jsxs("span",{className:"chat-model-selector__option-meta chat-model-selector__option-meta--stacked",children:[h.jsx("span",{className:"chat-model-selector__option-meta-line",children:gn(c)||i("chat.modelFast")}),h.jsx("span",{className:"chat-model-selector__option-meta-line",children:Vt(c)||i("chat.modelFastDesc")})]})]})}),h.jsx("div",{className:"chat-model-selector__divider"}),h.jsx("div",{className:"chat-model-selector__list",children:u.map(g=>{const k=s===g.id;return h.jsx("button",{className:`chat-model-selector__option${k?" is-selected":""}`,type:"button",onClick:()=>{d(g.id)},children:h.jsxs("span",{className:"chat-model-selector__option-main",children:[h.jsxs("span",{className:"chat-model-selector__option-name",children:[h.jsx("span",{className:"chat-model-selector__option-name-text",children:gn(g)}),g.reasoning?.status==="known"&&h.jsx(vi,{className:"chat-model-selector__option-thinking",size:10})]}),h.jsx("span",{className:"chat-model-selector__option-meta",children:Vt(g)||Is(g.provider)})]})},g.id)})})]})]})},Vx=({catalog:e,selectedModelId:t,disabled:n,onSelect:r})=>{const{t:i}=Ye(),[o,a]=N.useState(!1),l=N.useRef(null),s=N.useMemo(()=>js(t,e),[e,t]),u=N.useMemo(()=>[...s?.reasoning?.presets||[]].sort((k,S)=>k.order-S.order),[s]),p=e?.session_reasoning_preset?.trim()||null,c=p?u.find(k=>k.id===p)?.label||p:i("chat.reasoningAuto"),f=e?.reasoning_preset_selection_supported===!0,d=n||!f;if(N.useEffect(()=>{if(!o)return;const k=S=>{l.current&&!l.current.contains(S.target)&&a(!1)};return document.addEventListener("mousedown",k),()=>document.removeEventListener("mousedown",k)},[o]),s?.reasoning?.status!=="known"||u.length===0)return null;const g=async k=>{await r(k),a(!1)};return h.jsxs("div",{className:"chat-model-selector chat-reasoning-selector",ref:l,children:[h.jsxs("button",{className:`chat-model-selector__trigger chat-reasoning-selector__trigger${o?" chat-model-selector__trigger--open":""}`,type:"button",onClick:()=>a(k=>!k),disabled:d,"aria-label":i("chat.reasoningSelection"),children:[h.jsx(vi,{className:"chat-model-selector__thinking",size:10}),h.jsx("span",{className:"chat-model-selector__name chat-reasoning-selector__name",children:h.jsx("span",{className:"chat-model-selector__name-text",children:c})}),h.jsx("span",{className:"chat-model-selector__chevron","aria-hidden":"true",children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 6L8 10L12 6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),o&&f&&h.jsxs("div",{className:"chat-model-selector__dropdown chat-reasoning-selector__dropdown",children:[h.jsx("div",{className:"chat-model-selector__header",children:i("chat.reasoningSelection")}),h.jsxs("div",{className:"chat-model-selector__list",children:[h.jsx("button",{className:`chat-model-selector__option${p===null?" is-selected":""}`,type:"button",onClick:()=>{g(null)},children:h.jsx("span",{className:"chat-model-selector__option-name",children:i("chat.reasoningAuto")})}),u.map(k=>h.jsx("button",{className:`chat-model-selector__option${p===k.id?" is-selected":""}`,type:"button",onClick:()=>{g(k.id)},children:h.jsx("span",{className:"chat-model-selector__option-name",children:k.label})},k.id))]})]})]})},Zx=({sessionMgr:e,sessionId:t,sessionName:n,onBack:r,autoFocus:i})=>{const{t:o}=Ye(),{getMessages:a,setMessages:l,appendNewMessages:s,activeTurn:u,setActiveTurn:p,error:c,setError:f,currentWorkspace:d,updateSessionName:g}=Ft(),{isDark:k,toggleTheme:S}=Zo(),x=a(t),[v,y]=N.useState(""),[_,C]=N.useState(n),[m,T]=N.useState(null),[j,A]=N.useState("primary"),[E,R]=N.useState(!1),[M,H]=N.useState([]),[P,z]=N.useState(!1),[G,J]=N.useState(null),[U,ie]=N.useState(!!i),w=N.useRef(null),K=N.useRef(null),Y=N.useRef(null),b=N.useRef(null),Z=N.useRef(0),[ee,te]=N.useState(!1),[xe,we]=N.useState(!0),_e=N.useRef(!1),Ce=N.useRef(!0),ye=Gs(e),qe=N.useRef({sessionMgr:e,sessionId:t,epoch:ye,active:!0});(qe.current.sessionMgr!==e||qe.current.sessionId!==t||qe.current.epoch!==ye)&&(qe.current={sessionMgr:e,sessionId:t,epoch:ye,active:!0});const le=N.useCallback(()=>{const I=qe.current;return!I.active||I.sessionMgr!==e||I.sessionId!==t||I.epoch!==e.controlTargetEpoch?null:I.epoch},[ye,t,e]),ce=N.useCallback(I=>{const O=qe.current;return I!==null&&O.active&&O.sessionMgr===e&&O.sessionId===t&&O.epoch===I&&e.controlTargetEpoch===I},[ye,t,e]),Ze=N.useRef(!1),Ae=N.useRef(0),Xe=N.useRef(null),Me=N.useRef(null),[dt,Fe]=N.useState(new Set),[Qe,Ue]=N.useState(null),[ft,He]=N.useState(!1),[se,L]=N.useState(null),[D,B]=N.useState(null),[V,re]=N.useState(!1),ke=N.useRef(),Te=N.useRef({x:0,y:0}),ve=N.useRef(),je=N.useRef({sessionMgr:e,sessionId:t,epoch:ye});N.useLayoutEffect(()=>{const I=je.current,O=I.sessionMgr!==e||I.sessionId!==t||I.epoch!==ye,$=qe.current;return $.active=$.sessionMgr===e&&$.sessionId===t&&$.epoch===ye&&e.controlTargetEpoch===ye,O&&(Z.current+=1,Ae.current+=1,_e.current=!1,Ce.current=!0,te(!1),we(!0),R(!1),z(!1),J(null),Ze.current=!1,T(null),A("primary"),l(t,[]),L(null),re(!1),B(null),Ue(null),Fe(new Set),He(!1),p(null),ke.current&&(clearTimeout(ke.current),ke.current=void 0),ve.current&&(clearTimeout(ve.current),ve.current=void 0),b.current?.stop(),b.current=null),je.current={sessionMgr:e,sessionId:t,epoch:ye},()=>{$.active=!1,Z.current+=1,Ae.current+=1,b.current?.stop()}},[ye,t,e,p,l]);const pe=u!=null&&u.status==="active",[Se,ze]=N.useState(()=>Date.now()),Le=N.useCallback(async(I,O)=>{const $=le();if($===null)throw new on;try{if(await e.answerQuestion(I,O),!ce($))throw new on}catch(q){throw Je(q,f),q}},[le,ce,e,f]),Ne=N.useCallback(async I=>{const O=le();if(O===null)throw new on;const $=await e.getFileInfo(I,t);if(!ce(O))throw new on;return $},[le,ce,t,e]),be=N.useCallback(async(I,O)=>{const $=le();if($!==null)try{const{name:q,contentBase64:fe,mimeType:Ie}=await e.readFile(I,t,(_t,Vs)=>{ce($)&&O?.(_t,Vs)});if(!ce($))return;const de=atob(fe),ae=new Uint8Array(de.length);for(let _t=0;_t{const I=le();if(I===null)return null;const O=++Ae.current;try{const $=await e.getModelCatalog(t);if(O!==Ae.current||!ce(I))return null;if(T($),!Ze.current){const q=Ux(qx(),$),fe=ut($.session_model_id,$),Ie=q.modelId||fe;if(q.modelId&&q.modelId!==fe){const de=$.reasoning_preset_selection_supported===!0?await e.setSessionModelSelection(t,q.modelId,null):{model_id:await e.setSessionModel(t,q.modelId),reasoning_preset:null};if(O!==Ae.current||!ce(I))return null;const ae=ut(de.model_id,$);A(ae),T(X=>X&&{...X,session_model_id:ae,session_reasoning_preset:de.reasoning_preset}),q.fallbackApplied&&ni(ae)}else A(Ie),q.fallbackApplied&&ni(Ie);Ze.current=!0}return $}catch($){return O===Ae.current&&ce(I)&&Je($,f),null}},[le,ce,t,e,f]),Nn=N.useCallback(async I=>{if(E||pe||P)return;const O=le();if(O!==null){R(!0);try{const $=m?.reasoning_preset_selection_supported===!0?await e.setSessionModelSelection(t,I,null):{model_id:await e.setSessionModel(t,I),reasoning_preset:null};if(!ce(O))return;const q=ut($.model_id,m);A(q),T(fe=>fe&&{...fe,session_model_id:q,session_reasoning_preset:$.reasoning_preset}),ni(q)}catch($){Je($,f)}finally{ce(O)&&R(!1)}}},[le,P,ce,pe,m,E,t,e,f]),tn=N.useCallback(async I=>{if(E||pe||P||m?.reasoning_preset_selection_supported!==!0)return;const O=le();if(O!==null){R(!0);try{const $=await e.setSessionModelSelection(t,j,I);if(!ce(O))return;const q=ut($.model_id,m);A(q),T(fe=>fe&&{...fe,session_model_id:q,session_reasoning_preset:$.reasoning_preset})}catch($){Je($,f)}finally{ce(O)&&R(!1)}}},[le,P,ce,pe,m,E,j,t,e,f]);N.useEffect(()=>{if(!pe)return;const I=setInterval(()=>ze(Date.now()),500);return()=>clearInterval(I)},[pe]),N.useEffect(()=>{if(!c)return;const I=setTimeout(()=>f(null),5e3);return()=>clearTimeout(I)},[c,f]),N.useEffect(()=>{if(!Qe)return;const I=setTimeout(()=>Ue(null),3200);return()=>clearTimeout(I)},[Qe]);const ht=N.useCallback(async I=>{if(I&&(_e.current||!Ce.current))return;const O=le();if(O===null)return;const $=++Z.current;try{_e.current=!0,te(!0);const q=await e.getSessionMessages(t,50,I);if($!==Z.current||!ce(O))return;if(I){const fe=a(t);l(t,[...q.messages,...fe])}else l(t,q.messages);we(q.has_more),Ce.current=q.has_more}catch(q){$===Z.current&&ce(O)&&Je(q,f)}finally{$===Z.current&&ce(O)&&(_e.current=!1,te(!1))}},[le,a,ce,t,e,f,l]),gt=()=>{ke.current&&(clearTimeout(ke.current),ke.current=void 0)},mt=N.useCallback((I,O)=>{V||(gt(),Te.current={x:O.touches[0].clientX,y:O.touches[0].clientY},ke.current=setTimeout(()=>{L(I),ke.current=void 0},500))},[V]),In=N.useCallback(I=>{const O=Math.abs(I.touches[0].clientX-Te.current.x),$=Math.abs(I.touches[0].clientY-Te.current.y);(O>10||$>10)&>()},[]),wt=N.useCallback(()=>{gt()},[]),Dt=N.useCallback(I=>{ve.current&&clearTimeout(ve.current),B(I),ve.current=setTimeout(()=>B(null),2e3)},[]),Rs=N.useCallback(async()=>{if(!se)return;const I=Jr(se.content);try{await Ss(I),Dt(o("chat.messageCopied"))}catch{Dt(o("chat.copyFailed"))}L(null)},[se,Dt,o]),Os=N.useCallback(async()=>{if(!se||se.role!=="user")return;const I=le();if(I===null)return;const O=Jr(se.content);if(!O)return;L(null);const $=se.images?.length?se.images.map((q,fe)=>{const Ie=q.data_url.split(";")[0]?.replace("data:","")||"image/png";return{id:`mobile_resend_${Date.now()}_${fe}`,data_url:q.data_url,mime_type:Ie,metadata:{name:q.name,source:"remote"}}}):void 0;try{if(await e.sendMessage(t,O,"agentic",$),!ce(I))return;b.current?.nudge()}catch(q){Je(q,f)}},[le,ce,se,t,e,f]),Ds=N.useCallback(async()=>{if(se){re(!0);try{Ft.getState().deleteMessage(t,se.id),Dt(o("chat.messageDeleted"))}finally{re(!1),L(null)}}},[se,t,Dt,o]);N.useEffect(()=>()=>{gt(),ve.current&&clearTimeout(ve.current)},[]);const St=N.useRef(!0),yt=N.useRef(!1),jn=N.useRef(!1),Ms=80,Fs=N.useCallback(()=>{const I=Me.current;if(!I)return;const $=I.scrollHeight-I.scrollTop-I.clientHeight0&&ht(q[0].id)}},[xe,ee,a,t,ht]),zs=N.useCallback(()=>{yt.current=!0,St.current=!0,He(!1),jn.current=!1,Xe.current?.scrollIntoView({behavior:"smooth"})},[]),Mt=N.useRef(!1),nn=N.useRef(!1),rn=N.useRef(0);N.useEffect(()=>{Ze.current=!1,Ce.current=!0,_e.current=!1,we(!0),te(!1),T(null),A("primary")},[t]),N.useEffect(()=>{Mt.current=!1,nn.current=!1;const I=++rn.current;let O=!1;const $=le();if($===null)return;const q=()=>!O&&rn.current===I&&ce($);return Promise.all([ht(),lt()]).then(([fe,Ie])=>{if(!q())return;const de=Ft.getState().getMessages(t).length;nn.current=!0;const ae=new Zs(e,t,X=>{q()&&(X.message_snapshot?l(t,X.message_snapshot):X.new_messages&&X.new_messages.length>0&&s(t,X.new_messages),X.total_msg_count!=null&&Ft.getState().getMessages(t).length!==X.total_msg_count&&e.getSessionMessages(t,200).then(nt=>{q()&&Ft.getState().setMessages(t,nt.messages)}).catch(()=>{}),X.title&&(C(X.title),g(t,X.title)),X.model_catalog&&(T(X.model_catalog),A(ut(X.model_catalog.session_model_id,X.model_catalog))),p(X.active_turn??null))},Ie?.version||0);ae.start(de),b.current=ae}),()=>{O=!0,rn.current===I&&(rn.current+=1),b.current?.stop(),b.current=null,p(null)}},[s,le,ce,ht,lt,t,e,p,l,g]);const an=N.useRef(0);N.useLayoutEffect(()=>{if(!nn.current||x.length===0)return;nn.current=!1;const I=Me.current;I&&(I.scrollTop=I.scrollHeight),Mt.current=!0,an.current=x.length},[x]),N.useEffect(()=>{if(Mt.current&&x.length!==an.current){const I=x.length>an.current;an.current=x.length,I&&!ee&&St.current&&(yt.current=!0,Xe.current?.scrollIntoView({behavior:"smooth"}))}},[x.length,ee]),N.useEffect(()=>{!Mt.current||!pe||St.current&&(yt.current=!0,Xe.current?.scrollIntoView({behavior:"auto"}))},[u,pe]),N.useEffect(()=>{G&&(yt.current=!0,St.current=!0,Xe.current?.scrollIntoView({behavior:"smooth"}))},[G]),N.useEffect(()=>{if(!Mt.current||!pe)return;const I=Me.current;if(!I)return;const O=setInterval(()=>{if(!St.current)return;const $=I.scrollHeight-I.scrollTop-I.clientHeight;$>10&&$<400&&(yt.current=!0,I.scrollTo({top:I.scrollHeight,behavior:"smooth"}))},300);return()=>clearInterval(O)},[pe]);const Rn=N.useCallback(async()=>{const I=v.trim(),O=M;if(!I&&O.length===0||P)return;const $=le();if($===null)return;const q=pe;y(""),H([]),q||ie(!1);const fe=O.length>0,Ie=fe?O.map((de,ae)=>{const X=de.dataUrl.split(";")[0]?.replace("data:","")||"image/png";return{id:`mobile_img_${Date.now()}_${ae}`,data_url:de.dataUrl,mime_type:X,metadata:{name:de.name,source:"remote"}}}):void 0;fe&&(J({id:`opt_${Date.now()}`,text:I||"",images:O.map(de=>({name:de.name,data_url:de.dataUrl}))}),z(!0));try{if(await e.sendMessage(t,I||o("chat.imageAttachmentFallback"),"agentic",Ie),!ce($))return;b.current?.nudge(),q&&Ue(o("chat.messageQueued"))}catch(de){Je(de,f)}finally{ce($)&&(z(!1),J(null))}},[le,P,v,ce,pe,M,t,e,f,o]),Ps=N.useCallback(()=>{K.current?.click()},[]),Bs=N.useCallback(async I=>{const O=I.target.files;if(!O)return;const $=5,q=$-M.length,fe=Array.from(O).slice(0,q),{compressImageFile:Ie}=await Xs(async()=>{const{compressImageFile:de}=await import("./imageCompressor-Cy77l5Xt.js");return{compressImageFile:de}},[],import.meta.url);for(const de of fe)try{const ae=await Ie(de);H(X=>X.length>=$?X:[...X,{name:ae.name,dataUrl:ae.dataUrl}])}catch{const ae=new FileReader;ae.onload=()=>{const X=ae.result;H(ue=>ue.length>=$?ue:[...ue,{name:de.name,dataUrl:X}])},ae.readAsDataURL(de)}I.target.value=""},[M.length]),$s=N.useCallback(I=>{H(O=>O.filter(($,q)=>q!==I))},[]),Wi=N.useCallback(()=>{ie(!0),requestAnimationFrame(()=>w.current?.focus())},[]);N.useEffect(()=>{i&&requestAnimationFrame(()=>w.current?.focus())},[i]),N.useEffect(()=>{if(!U)return;const I=O=>{Y.current&&!Y.current.contains(O.target)&&!v.trim()&&M.length===0&&ie(!1)};return document.addEventListener("mousedown",I),()=>document.removeEventListener("mousedown",I)},[U,v,M.length]);const On=N.useRef(!1),qs=N.useCallback(()=>{On.current=!0},[]),Us=N.useCallback(()=>{setTimeout(()=>{On.current=!1},0)},[]),Hs=I=>{if(I.key==="Enter"&&!I.shiftKey){if(I.nativeEvent.isComposing||On.current)return;I.preventDefault(),Rn()}},Ws=async()=>{if(le()!==null)try{await e.cancelTask(t,u?.turn_id)}catch{}},Vi=d?.project_name||d?.path?.split("/").pop()||"",Dn=d?.git_branch,Gi=_||n||o("chat.session");return h.jsxs("div",{className:"chat-page",children:[h.jsx("div",{className:"chat-page__header",children:h.jsxs("div",{className:"chat-page__header-row",children:[h.jsx("button",{className:"chat-page__back",onClick:r,"aria-label":o("common.back"),children:h.jsx("svg",{width:"18",height:"18",viewBox:"0 0 20 20",fill:"none",children:h.jsx("path",{d:"M12 4L6 10L12 16",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsxs("div",{className:"chat-page__header-center",children:[h.jsx("span",{className:"chat-page__title",title:Gi,children:Gi}),Vi&&h.jsxs("div",{className:"chat-page__header-workspace",title:d?.path,children:[h.jsx("span",{className:"chat-page__workspace-name",children:Vi}),Dn&&h.jsxs("span",{className:"chat-page__workspace-branch",title:Dn,children:[h.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("line",{x1:"6",x2:"6",y1:"3",y2:"15"}),h.jsx("circle",{cx:"18",cy:"6",r:"3"}),h.jsx("circle",{cx:"6",cy:"18",r:"3"}),h.jsx("path",{d:"M18 9a9 9 0 0 1-9 9"})]}),wx(Dn,28)]})]})]}),h.jsx("div",{className:"chat-page__header-right",children:h.jsx("button",{className:"chat-page__theme-btn",onClick:S,"aria-label":o("common.toggleTheme"),children:h.jsx(zx,{isDark:k})})})]})}),h.jsxs("div",{className:"chat-page__messages",ref:Me,onScroll:Fs,children:[ee&&h.jsx("div",{className:"chat-page__load-more-indicator",children:o("chat.loadingOlderMessages")}),(()=>{const I=x.reduceRight((O,$,q)=>O<0&&$.role==="user"?q:O,-1);return x.map((O,$)=>{if(O.role==="system"||O.role==="tool")return null;if(O.role==="user"){const ae=Jr(O.content);return h.jsx("div",{className:`chat-msg chat-msg--user${se?.id===O.id?" chat-msg--menu-active":""}`,onTouchStart:X=>mt(O,X),onTouchMove:In,onTouchEnd:wt,onTouchCancel:wt,onContextMenu:X=>{X.preventDefault(),L(O)},children:h.jsxs("div",{className:"chat-msg__user-card",children:[h.jsx("div",{className:"chat-msg__user-avatar",children:"U"}),h.jsxs("div",{className:"chat-msg__user-content",children:[ae,O.images&&O.images.length>0&&h.jsx("div",{className:"chat-msg__user-images",children:O.images.map((X,ue)=>h.jsx("img",{src:X.data_url,alt:X.name,className:"chat-msg__user-image"},ue))})]})]})},O.id)}const q=O.items&&O.items.length>0,fe=O.thinking||O.tools&&O.tools.length>0||O.content;if(!q&&!fe)return null;const Ie=$mt(O,ae),onTouchMove:In,onTouchEnd:wt,onTouchCancel:wt,onContextMenu:ae=>{ae.preventDefault(),L(O)},children:h.jsxs("button",{className:"chat-msg__response-toggle",onClick:()=>Fe(ae=>{const X=new Set(ae);return X.add(O.id),X}),children:[h.jsx("span",{className:"chat-msg__response-chevron",children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-msg__response-label",children:o("chat.showResponse")})]})},O.id):h.jsxs("div",{className:`chat-msg chat-msg--assistant${se?.id===O.id?" chat-msg--menu-active":""}`,onTouchStart:ae=>mt(O,ae),onTouchMove:In,onTouchEnd:wt,onTouchCancel:wt,onContextMenu:ae=>{ae.preventDefault(),L(O)},children:[Ie&&de&&h.jsxs("button",{className:"chat-msg__response-toggle",onClick:()=>Fe(ae=>{const X=new Set(ae);return X.delete(O.id),X}),children:[h.jsx("span",{className:"chat-msg__response-chevron is-open",children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-msg__response-label",children:o("chat.hideResponse")})]}),q?Vo(O.items,Se,void 0,Le,be,Ne):h.jsxs(h.Fragment,{children:[O.thinking&&h.jsx(xi,{thinking:O.thinking}),O.tools&&O.tools.length>0&&h.jsx(ki,{tools:O.tools,now:Se}),O.content&&h.jsx("div",{className:"chat-msg__assistant-content",children:h.jsx(Kt,{content:O.content,onFileDownload:be,onGetFileInfo:Ne})})]})]},O.id)})})(),u&&(()=>{const I=u,O=I.status==="active";if(I.items&&I.items.length>0)return h.jsxs("div",{className:"chat-msg chat-msg--assistant",children:[O?Fx(I.items,Se,e,f,()=>le()!==null,Le,be,Ne):Vo(I.items,Se,void 0,void 0,be,Ne),O&&!I.thinking&&!I.text&&I.tools.length===0&&h.jsx("div",{className:"chat-msg__assistant-content",children:h.jsx(ti,{})})]});const $=I.tools.filter(ue=>ue.name==="Task"),q=$.some(ue=>ue.status==="running"),fe=I.tools.filter(ue=>ue.name==="AskUserQuestion"&&ue.status==="running"&&ue.tool_input),Ie=new Set(fe.map(ue=>ue.id)),de=I.tools.filter(ue=>ue.name!=="Task"&&!Ie.has(ue.id)),ae=q?[...I.thinking?[{type:"thinking",content:I.thinking}]:[],...de.map(ue=>({type:"tool",tool:ue}))]:[],X=ue=>{le()!==null&&e.cancelTool(ue,o("common.cancel")).catch(nt=>{Je(nt,f)})};return h.jsxs("div",{className:"chat-msg chat-msg--assistant",children:[!q&&(I.thinking||O)&&h.jsx(xi,{thinking:I.thinking,streaming:O,isLastItem:O}),$.map(ue=>h.jsx(_s,{tool:ue,now:Se,subItems:ue.status==="running"?ae:void 0,onCancelTool:X},ue.id)),!q&&de.length>0&&h.jsx(ki,{tools:de,now:Se,onCancelTool:X}),O&&fe.map(ue=>h.jsx(As,{tool:ue,onAnswer:Le},ue.id)),!q&&I.text?h.jsx("div",{className:"chat-msg__assistant-content",children:O?h.jsx(Ts,{content:I.text,onFileDownload:be,onGetFileInfo:Ne}):h.jsx(Kt,{content:I.text,onFileDownload:be,onGetFileInfo:Ne})}):O&&!I.thinking&&I.tools.length===0?h.jsx("div",{className:"chat-msg__assistant-content",children:h.jsx(ti,{})}):null]})})(),G&&h.jsx("div",{className:"chat-msg chat-msg--user",children:h.jsxs("div",{className:"chat-msg__user-card",children:[h.jsx("div",{className:"chat-msg__user-avatar",children:"U"}),h.jsxs("div",{className:"chat-msg__user-content",children:[G.text,G.images.length>0&&h.jsx("div",{className:"chat-msg__user-images",children:G.images.map((I,O)=>h.jsx("img",{src:I.data_url,alt:I.name,className:"chat-msg__user-image"},O))})]})]})}),P&&h.jsx("div",{className:"chat-msg chat-msg--assistant",children:h.jsx("div",{className:"chat-msg__assistant-card",children:h.jsxs("div",{className:"chat-msg__image-analyzing",children:[h.jsx("div",{className:"chat-msg__image-analyzing-icon",children:h.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("circle",{cx:"12",cy:"12",r:"3"}),h.jsx("path",{d:"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"})]})}),h.jsx("span",{children:o("chat.analyzingImage")}),h.jsx(ti,{})]})})}),h.jsx("div",{ref:Xe})]}),ft&&h.jsx("button",{type:"button",className:"chat-page__scroll-to-bottom",onClick:zs,"aria-label":o("chat.scrollToBottom"),children:h.jsx("svg",{"aria-hidden":"true",focusable:"false",width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("polyline",{points:"6 9 12 15 18 9"})})}),se&&h.jsx("div",{className:"chat-msg__menu-overlay",onClick:()=>L(null),children:h.jsxs("div",{className:"chat-msg__menu-sheet",onClick:I=>I.stopPropagation(),children:[h.jsx("div",{className:"chat-msg__menu-handle"}),h.jsxs("div",{className:"chat-msg__menu-actions",children:[h.jsxs("button",{className:"chat-msg__menu-btn",onClick:Rs,children:[h.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),h.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]}),h.jsx("span",{children:o("chat.copyMessage")})]}),se.role==="user"&&h.jsxs("button",{className:"chat-msg__menu-btn",onClick:Os,children:[h.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("polyline",{points:"23 4 23 10 17 10"}),h.jsx("path",{d:"M20.49 15a9 9 0 1 1-2.12-9.36L23 10"})]}),h.jsx("span",{children:o("chat.resendMessage")})]}),h.jsxs("button",{className:"chat-msg__menu-btn chat-msg__menu-btn--danger",onClick:Ds,disabled:V,children:[h.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("polyline",{points:"3 6 5 6 21 6"}),h.jsx("path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"})]}),h.jsx("span",{children:V?"...":o("chat.deleteMessage")})]})]}),h.jsx("button",{className:"chat-msg__menu-cancel",onClick:()=>L(null),children:o("common.cancel")})]})}),D&&h.jsx("div",{className:"chat-page__toast",role:"alert","aria-live":"assertive",children:D}),h.jsx("input",{ref:K,type:"file",accept:"image/png,image/jpeg,image/jpg,image/gif,image/webp",multiple:!0,style:{display:"none"},onChange:Bs}),h.jsx("div",{className:`chat-page__input-wrap ${U?"is-expanded":""}`,ref:Y,children:h.jsxs("div",{className:"chat-page__input-box",onClick:U?void 0:Wi,children:[h.jsx("div",{className:"chat-page__input-area",children:U?h.jsx("textarea",{ref:w,className:"chat-page__input",placeholder:o("chat.inputPlaceholder"),value:v,onChange:I=>y(I.target.value),onKeyDown:Hs,onCompositionStart:qs,onCompositionEnd:Us,rows:1,disabled:P}):h.jsx("span",{className:"chat-page__input-placeholder",children:o(P?"chat.imageAnalyzingPlaceholder":pe?"chat.collapsedStreamingPlaceholder":"chat.collapsedInputPlaceholder")})}),h.jsxs("div",{className:"chat-page__input-actions",children:[h.jsxs("div",{className:"chat-page__input-actions-left",children:[U&&h.jsxs(h.Fragment,{children:[h.jsx(Wx,{catalog:m,selectedModelId:j,disabled:P||pe||E,onSelect:Nn}),h.jsx(Vx,{catalog:m,selectedModelId:j,disabled:P||pe||E,onSelect:tn})]}),U&&M.length>0&&h.jsx("div",{className:"chat-page__image-preview-row",children:M.map((I,O)=>h.jsxs("div",{className:"chat-page__image-thumb",children:[h.jsx("img",{src:I.dataUrl,alt:I.name}),h.jsx("button",{className:"chat-page__image-remove",onClick:()=>$s(O),children:"×"})]},O))})]}),h.jsxs("div",{className:"chat-page__input-actions-right",children:[U&&h.jsx("button",{className:"chat-page__action-btn",onClick:Ps,disabled:P||M.length>=5,"aria-label":o("common.attachImage"),children:h.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}),h.jsx("circle",{cx:"9",cy:"9",r:"2"}),h.jsx("path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"})]})}),P?h.jsx("button",{className:"chat-page__send-btn is-stop","aria-label":o("common.stop"),disabled:!0,children:h.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",style:{animation:"analyzeSpin 2s linear infinite"},children:[h.jsx("circle",{cx:"12",cy:"12",r:"3"}),h.jsx("path",{d:"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2"})]})}):pe?h.jsxs("div",{className:"chat-page__stream-actions",children:[h.jsx("button",{type:"button",className:"chat-page__send-btn is-stop",onClick:Ws,"aria-label":o("common.stop"),children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("rect",{x:"3",y:"3",width:"10",height:"10",rx:"2",fill:"currentColor"})})}),h.jsx("button",{type:"button",className:"chat-page__send-btn",onClick:U?Rn:Wi,disabled:!v.trim()&&M.length===0,"aria-label":o("common.submit"),children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 20 20",fill:"none",children:h.jsx("path",{d:"M10 3L10 17M10 3L5 8M10 3L15 8",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]}):h.jsx("button",{className:"chat-page__send-btn",onClick:U?Rn:void 0,disabled:!v.trim()&&M.length===0,children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 20 20",fill:"none",children:h.jsx("path",{d:"M10 3L10 17M10 3L5 8M10 3L15 8",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})]})}),c&&h.jsx("div",{className:"chat-page__toast",onClick:()=>f(null),children:c}),Qe&&h.jsx("div",{className:"chat-page__toast chat-page__toast--info",onClick:()=>Ue(null),children:Qe})]})};export{Zx as default}; +`),c=l&&u===e.length-1;return h.jsx(xi,{thinking:p,streaming:c,isLastItem:c},`${t}-thinking-${u}`)}if(s.type==="tool"){const p=[];let c=[],f=[];const d=()=>{f.length>0&&(p.push(h.jsx(Rx,{tools:f},`${t}-read-${u}-${p.length}`)),f=[])},g=()=>{c.length>0&&(p.push(h.jsx(ki,{tools:c,now:n,onCancelTool:r},`${t}-tl-${u}-${p.length}`)),c=[])},k=()=>{d(),g()};for(const S of s.entries)S.tool?.name==="Task"?(k(),p.push(h.jsx(_s,{tool:S.tool,now:n,subItems:S.subItems,onCancelTool:r},`${t}-task-${u}-${p.length}`))):S.tool?.name==="TodoWrite"?(k(),p.push(h.jsx(Ax,{tool:S.tool},`${t}-todo-${u}-${p.length}`))):S.tool&&Ix.has(S.tool.name)?(g(),f.push(S.tool)):S.tool&&(d(),c.push(S.tool));return k(),h.jsx(it.Fragment,{children:p},`${t}-tool-${u}`)}if(s.type==="text"){const p=s.entries.map(c=>c.content||"").join("");return p?h.jsx("div",{className:"chat-msg__assistant-content",children:i?h.jsx(Ts,{content:p,onFileDownload:o,onGetFileInfo:a}):h.jsx(Kt,{content:p,onFileDownload:o,onGetFileInfo:a})},`${t}-text-${u}`):null}return null})}function Vo(e,t,n,r,i,o){const a=Ls(e),l=a.filter(c=>_n(c.tool));if(l.length===0)return It(Nt(a),"ordered",t,n,!1,i,o);const s=[],u=[];let p=!1;for(const c of a)_n(c.tool)?p=!0:p?u.push(c):s.push(c);return h.jsxs(h.Fragment,{children:[It(Nt(s),"ordered-before",t,n,!1,i,o),Ns(l,"ordered",r),It(Nt(u),"ordered-after",t,n,!1,i,o)]})}function Fx(e,t,n,r,i,o,a,l){const s=Ls(e),u=s.filter(g=>_n(g.tool)),p=g=>{i()&&n.cancelTool(g,"User cancelled").catch(k=>{Je(k,r)})};if(u.length===0)return It(Nt(s),"active",t,p,!0,a,l,!0);const c=[],f=[];let d=!1;for(const g of s)_n(g.tool)?d=!0:d?f.push(g):c.push(g);return h.jsxs(h.Fragment,{children:[It(Nt(c),"active-before",t,p,!0,a,l,!0),Ns(u,"active",o),It(Nt(f),"active-after",t,p,!0,a,l,!0)]})}const zx=({isDark:e})=>h.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:e?h.jsx("path",{d:"M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM3 8a5 5 0 0 1 5-5v10a5 5 0 0 1-5-5Z",fill:"currentColor"}):h.jsx("path",{d:"M8 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 1Zm0 11a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 12Zm7-4a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 15 8ZM3 8a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 3 8Zm9.95-3.54a.5.5 0 0 1 0 .71l-.71.7a.5.5 0 1 1-.7-.7l.7-.71a.5.5 0 0 1 .71 0ZM5.46 11.24a.5.5 0 0 1 0 .71l-.7.71a.5.5 0 0 1-.71-.71l.7-.71a.5.5 0 0 1 .71 0Zm7.08 1.42a.5.5 0 0 1-.7 0l-.71-.71a.5.5 0 0 1 .7-.7l.71.7a.5.5 0 0 1 0 .71ZM5.46 4.76a.5.5 0 0 1-.71 0l-.71-.7a.5.5 0 0 1 .71-.71l.7.7a.5.5 0 0 1 0 .71ZM8 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z",fill:"currentColor"})}),vi=({className:e,size:t=10})=>h.jsxs("svg",{className:e,width:t,height:t,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:[h.jsx("path",{d:"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.937A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .962 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.582a.5.5 0 0 1 0 .962L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.962 0z"}),h.jsx("path",{d:"M20 3v4"}),h.jsx("path",{d:"M22 5h-4"}),h.jsx("path",{d:"M4 17v2"}),h.jsx("path",{d:"M5 18H3"})]});function Is(e){const t=e.trim();return t?t.charAt(0).toUpperCase()+t.slice(1):"Unknown"}function Px(e){const t=e.name?.trim();return t||Is(e.provider)}function Bx(e){return e?`${Math.round(e/1e3)}k`:null}function $x(e){return e.enabled&&Array.isArray(e.capabilities)&&e.capabilities.includes("text_chat")}function ut(e,t){const n=e?.trim();if(!n||n==="primary")return"primary";if(n==="fast"){const r=t?.default_models?.fast;return r&&at(r,t)?n:"primary"}return at(n,t)?n:"primary"}function qx(){return typeof window>"u"?null:window.localStorage.getItem(yi)?.trim()||null}function ni(e){if(typeof window>"u")return;const t=e.trim();if(!t){window.localStorage.removeItem(yi);return}window.localStorage.setItem(yi,t)}function Ux(e,t){const n=e?.trim();if(!n)return{modelId:null,fallbackApplied:!1};const r=ut(n,t);return{modelId:r,fallbackApplied:r!==n}}function at(e,t){return t&&t.models.find(n=>n.id===e)||null}function js(e,t){const n=ut(e,t);return n==="primary"?at(t?.default_models?.primary||"",t):n==="fast"?at(t?.default_models?.fast||"",t)||at(t?.default_models?.primary||"",t):at(n,t)}function Vt(e){if(!e)return null;const t=[Px(e)],n=Bx(e.context_window);return n&&t.push(n),t.join(" · ")}function gn(e){return e&&(e.model_name||e.name)||""}function Go(e,t){if(e?.reasoning?.status!=="known")return;const n=t?.session_reasoning_preset?.trim();if(n)return e.reasoning.presets?.find(r=>r.id===n)?.label||n}function Hx(e,t,n){if(e==="primary"||e==="fast"){const i=js(e,t);return{label:n(e==="primary"?"chat.modelPrimary":"chat.modelFast"),meta:Vt(i)||n(e==="primary"?"chat.modelPrimaryDesc":"chat.modelFastDesc"),enableThinking:i?.reasoning?.status==="known",reasoningEffort:Go(i,t)}}const r=at(e,t);return r?{label:gn(r),meta:Vt(r),enableThinking:r.reasoning?.status==="known",reasoningEffort:Go(r,t)}:{label:n("chat.modelPrimary"),meta:n("chat.modelPrimaryDesc"),enableThinking:!1}}const Wx=({catalog:e,selectedModelId:t,disabled:n,onSelect:r})=>{const{t:i}=Ye(),[o,a]=N.useState(!1),l=N.useRef(null),s=N.useMemo(()=>ut(t,e),[e,t]),u=N.useMemo(()=>(e?.models||[]).filter($x),[e]),p=N.useMemo(()=>at(e?.default_models?.primary||"",e),[e]),c=N.useMemo(()=>at(e?.default_models?.fast||"",e),[e]),f=N.useMemo(()=>Hx(s,e,i),[e,s,i]);if(N.useEffect(()=>{if(!o)return;const g=k=>{l.current&&!l.current.contains(k.target)&&a(!1)};return document.addEventListener("mousedown",g),()=>document.removeEventListener("mousedown",g)},[o]),!e)return null;const d=async g=>{await r(g),a(!1)};return h.jsxs("div",{className:"chat-model-selector",ref:l,children:[h.jsxs("button",{className:`chat-model-selector__trigger${o?" chat-model-selector__trigger--open":""}`,type:"button",onClick:()=>a(g=>!g),disabled:n,"aria-label":i("chat.modelSelection"),children:[h.jsx("span",{className:"chat-model-selector__icon","aria-hidden":"true",children:h.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",children:[h.jsx("rect",{x:"4",y:"4",width:"6",height:"6",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7"}),h.jsx("rect",{x:"14",y:"4",width:"6",height:"6",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7"}),h.jsx("rect",{x:"9",y:"14",width:"6",height:"6",rx:"1.5",stroke:"currentColor",strokeWidth:"1.7"}),h.jsx("path",{d:"M10 7h4M12 10v4",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round"})]})}),h.jsxs("span",{className:"chat-model-selector__name",children:[h.jsx("span",{className:"chat-model-selector__name-text",children:f.label}),f.enableThinking&&h.jsx(vi,{className:"chat-model-selector__thinking",size:9})]}),f.reasoningEffort&&h.jsx("span",{className:"chat-model-selector__effort",children:f.reasoningEffort}),h.jsx("span",{className:"chat-model-selector__chevron","aria-hidden":"true",children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 6L8 10L12 6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),o&&h.jsxs("div",{className:"chat-model-selector__dropdown",children:[h.jsx("div",{className:"chat-model-selector__header",children:i("chat.modelSelection")}),h.jsx("button",{className:`chat-model-selector__option${s==="primary"?" is-selected":""}`,type:"button",onClick:()=>{d("primary")},children:h.jsxs("span",{className:"chat-model-selector__option-main",children:[h.jsx("span",{className:"chat-model-selector__option-name",children:i("chat.modelPrimary")}),h.jsxs("span",{className:"chat-model-selector__option-meta chat-model-selector__option-meta--stacked",children:[h.jsx("span",{className:"chat-model-selector__option-meta-line",children:gn(p)||i("chat.modelPrimary")}),h.jsx("span",{className:"chat-model-selector__option-meta-line",children:Vt(p)||i("chat.modelPrimaryDesc")})]})]})}),h.jsx("button",{className:`chat-model-selector__option${s==="fast"?" is-selected":""}`,type:"button",onClick:()=>{d("fast")},children:h.jsxs("span",{className:"chat-model-selector__option-main",children:[h.jsx("span",{className:"chat-model-selector__option-name",children:i("chat.modelFast")}),h.jsxs("span",{className:"chat-model-selector__option-meta chat-model-selector__option-meta--stacked",children:[h.jsx("span",{className:"chat-model-selector__option-meta-line",children:gn(c)||i("chat.modelFast")}),h.jsx("span",{className:"chat-model-selector__option-meta-line",children:Vt(c)||i("chat.modelFastDesc")})]})]})}),h.jsx("div",{className:"chat-model-selector__divider"}),h.jsx("div",{className:"chat-model-selector__list",children:u.map(g=>{const k=s===g.id;return h.jsx("button",{className:`chat-model-selector__option${k?" is-selected":""}`,type:"button",onClick:()=>{d(g.id)},children:h.jsxs("span",{className:"chat-model-selector__option-main",children:[h.jsxs("span",{className:"chat-model-selector__option-name",children:[h.jsx("span",{className:"chat-model-selector__option-name-text",children:gn(g)}),g.reasoning?.status==="known"&&h.jsx(vi,{className:"chat-model-selector__option-thinking",size:10})]}),h.jsx("span",{className:"chat-model-selector__option-meta",children:Vt(g)||Is(g.provider)})]})},g.id)})})]})]})},Vx=({catalog:e,selectedModelId:t,disabled:n,onSelect:r})=>{const{t:i}=Ye(),[o,a]=N.useState(!1),l=N.useRef(null),s=N.useMemo(()=>js(t,e),[e,t]),u=N.useMemo(()=>[...s?.reasoning?.presets||[]].sort((k,S)=>k.order-S.order),[s]),p=e?.session_reasoning_preset?.trim()||null,c=p?u.find(k=>k.id===p)?.label||p:i("chat.reasoningAuto"),f=e?.reasoning_preset_selection_supported===!0,d=n||!f;if(N.useEffect(()=>{if(!o)return;const k=S=>{l.current&&!l.current.contains(S.target)&&a(!1)};return document.addEventListener("mousedown",k),()=>document.removeEventListener("mousedown",k)},[o]),s?.reasoning?.status!=="known"||u.length===0)return null;const g=async k=>{await r(k),a(!1)};return h.jsxs("div",{className:"chat-model-selector chat-reasoning-selector",ref:l,children:[h.jsxs("button",{className:`chat-model-selector__trigger chat-reasoning-selector__trigger${o?" chat-model-selector__trigger--open":""}`,type:"button",onClick:()=>a(k=>!k),disabled:d,"aria-label":i("chat.reasoningSelection"),children:[h.jsx(vi,{className:"chat-model-selector__thinking",size:10}),h.jsx("span",{className:"chat-model-selector__name chat-reasoning-selector__name",children:h.jsx("span",{className:"chat-model-selector__name-text",children:c})}),h.jsx("span",{className:"chat-model-selector__chevron","aria-hidden":"true",children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M4 6L8 10L12 6",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),o&&f&&h.jsxs("div",{className:"chat-model-selector__dropdown chat-reasoning-selector__dropdown",children:[h.jsx("div",{className:"chat-model-selector__header",children:i("chat.reasoningSelection")}),h.jsxs("div",{className:"chat-model-selector__list",children:[h.jsx("button",{className:`chat-model-selector__option${p===null?" is-selected":""}`,type:"button",onClick:()=>{g(null)},children:h.jsx("span",{className:"chat-model-selector__option-name",children:i("chat.reasoningAuto")})}),u.map(k=>h.jsx("button",{className:`chat-model-selector__option${p===k.id?" is-selected":""}`,type:"button",onClick:()=>{g(k.id)},children:h.jsx("span",{className:"chat-model-selector__option-name",children:k.label})},k.id))]})]})]})},Zx=({sessionMgr:e,sessionId:t,sessionName:n,onBack:r,autoFocus:i})=>{const{t:o}=Ye(),{getMessages:a,setMessages:l,appendNewMessages:s,activeTurn:u,setActiveTurn:p,error:c,setError:f,currentWorkspace:d,updateSessionName:g}=Ft(),{isDark:k,toggleTheme:S}=Zo(),x=a(t),[v,b]=N.useState(""),[_,C]=N.useState(n),[m,T]=N.useState(null),[j,A]=N.useState("primary"),[E,R]=N.useState(!1),[M,H]=N.useState([]),[P,z]=N.useState(!1),[G,J]=N.useState(null),[U,ie]=N.useState(!!i),w=N.useRef(null),K=N.useRef(null),Y=N.useRef(null),y=N.useRef(null),Z=N.useRef(0),[ee,te]=N.useState(!1),[xe,we]=N.useState(!0),_e=N.useRef(!1),Ce=N.useRef(!0),be=Gs(e),qe=N.useRef({sessionMgr:e,sessionId:t,epoch:be,active:!0});(qe.current.sessionMgr!==e||qe.current.sessionId!==t||qe.current.epoch!==be)&&(qe.current={sessionMgr:e,sessionId:t,epoch:be,active:!0});const le=N.useCallback(()=>{const I=qe.current;return!I.active||I.sessionMgr!==e||I.sessionId!==t||I.epoch!==e.controlTargetEpoch?null:I.epoch},[be,t,e]),ce=N.useCallback(I=>{const O=qe.current;return I!==null&&O.active&&O.sessionMgr===e&&O.sessionId===t&&O.epoch===I&&e.controlTargetEpoch===I},[be,t,e]),Ze=N.useRef(!1),Ae=N.useRef(0),Xe=N.useRef(null),Me=N.useRef(null),[dt,Fe]=N.useState(new Set),[Qe,Ue]=N.useState(null),[ft,He]=N.useState(!1),[se,L]=N.useState(null),[D,B]=N.useState(null),[V,re]=N.useState(!1),ke=N.useRef(),Te=N.useRef({x:0,y:0}),ve=N.useRef(),je=N.useRef({sessionMgr:e,sessionId:t,epoch:be});N.useLayoutEffect(()=>{const I=je.current,O=I.sessionMgr!==e||I.sessionId!==t||I.epoch!==be,$=qe.current;return $.active=$.sessionMgr===e&&$.sessionId===t&&$.epoch===be&&e.controlTargetEpoch===be,O&&(Z.current+=1,Ae.current+=1,_e.current=!1,Ce.current=!0,te(!1),we(!0),R(!1),z(!1),J(null),Ze.current=!1,T(null),A("primary"),l(t,[]),L(null),re(!1),B(null),Ue(null),Fe(new Set),He(!1),p(null),ke.current&&(clearTimeout(ke.current),ke.current=void 0),ve.current&&(clearTimeout(ve.current),ve.current=void 0),y.current?.stop(),y.current=null),je.current={sessionMgr:e,sessionId:t,epoch:be},()=>{$.active=!1,Z.current+=1,Ae.current+=1,y.current?.stop()}},[be,t,e,p,l]);const pe=u!=null&&u.status==="active",[Se,ze]=N.useState(()=>Date.now()),Le=N.useCallback(async(I,O)=>{const $=le();if($===null)throw new on;try{if(await e.answerQuestion(I,O),!ce($))throw new on}catch(q){throw Je(q,f),q}},[le,ce,e,f]),Ne=N.useCallback(async I=>{const O=le();if(O===null)throw new on;const $=await e.getFileInfo(I,t);if(!ce(O))throw new on;return $},[le,ce,t,e]),ye=N.useCallback(async(I,O)=>{const $=le();if($!==null)try{const{name:q,contentBase64:fe,mimeType:Ie}=await e.readFile(I,t,(_t,Vs)=>{ce($)&&O?.(_t,Vs)});if(!ce($))return;const de=atob(fe),ae=new Uint8Array(de.length);for(let _t=0;_t{const I=le();if(I===null)return null;const O=++Ae.current;try{const $=await e.getModelCatalog(t);if(O!==Ae.current||!ce(I))return null;if(T($),!Ze.current){const q=Ux(qx(),$),fe=ut($.session_model_id,$),Ie=q.modelId||fe;if(q.modelId&&q.modelId!==fe){const de=$.reasoning_preset_selection_supported===!0?await e.setSessionModelSelection(t,q.modelId,null):{model_id:await e.setSessionModel(t,q.modelId),reasoning_preset:null};if(O!==Ae.current||!ce(I))return null;const ae=ut(de.model_id,$);A(ae),T(X=>X&&{...X,session_model_id:ae,session_reasoning_preset:de.reasoning_preset}),q.fallbackApplied&&ni(ae)}else A(Ie),q.fallbackApplied&&ni(Ie);Ze.current=!0}return $}catch($){return O===Ae.current&&ce(I)&&Je($,f),null}},[le,ce,t,e,f]),Nn=N.useCallback(async I=>{if(E||pe||P)return;const O=le();if(O!==null){R(!0);try{const $=m?.reasoning_preset_selection_supported===!0?await e.setSessionModelSelection(t,I,null):{model_id:await e.setSessionModel(t,I),reasoning_preset:null};if(!ce(O))return;const q=ut($.model_id,m);A(q),T(fe=>fe&&{...fe,session_model_id:q,session_reasoning_preset:$.reasoning_preset}),ni(q)}catch($){Je($,f)}finally{ce(O)&&R(!1)}}},[le,P,ce,pe,m,E,t,e,f]),tn=N.useCallback(async I=>{if(E||pe||P||m?.reasoning_preset_selection_supported!==!0)return;const O=le();if(O!==null){R(!0);try{const $=await e.setSessionModelSelection(t,j,I);if(!ce(O))return;const q=ut($.model_id,m);A(q),T(fe=>fe&&{...fe,session_model_id:q,session_reasoning_preset:$.reasoning_preset})}catch($){Je($,f)}finally{ce(O)&&R(!1)}}},[le,P,ce,pe,m,E,j,t,e,f]);N.useEffect(()=>{if(!pe)return;const I=setInterval(()=>ze(Date.now()),500);return()=>clearInterval(I)},[pe]),N.useEffect(()=>{if(!c)return;const I=setTimeout(()=>f(null),5e3);return()=>clearTimeout(I)},[c,f]),N.useEffect(()=>{if(!Qe)return;const I=setTimeout(()=>Ue(null),3200);return()=>clearTimeout(I)},[Qe]);const ht=N.useCallback(async I=>{if(I&&(_e.current||!Ce.current))return;const O=le();if(O===null)return;const $=++Z.current;try{_e.current=!0,te(!0);const q=await e.getSessionMessages(t,50,I);if($!==Z.current||!ce(O))return;if(I){const fe=a(t);l(t,[...q.messages,...fe])}else l(t,q.messages);we(q.has_more),Ce.current=q.has_more}catch(q){$===Z.current&&ce(O)&&Je(q,f)}finally{$===Z.current&&ce(O)&&(_e.current=!1,te(!1))}},[le,a,ce,t,e,f,l]),gt=()=>{ke.current&&(clearTimeout(ke.current),ke.current=void 0)},mt=N.useCallback((I,O)=>{V||(gt(),Te.current={x:O.touches[0].clientX,y:O.touches[0].clientY},ke.current=setTimeout(()=>{L(I),ke.current=void 0},500))},[V]),In=N.useCallback(I=>{const O=Math.abs(I.touches[0].clientX-Te.current.x),$=Math.abs(I.touches[0].clientY-Te.current.y);(O>10||$>10)&>()},[]),wt=N.useCallback(()=>{gt()},[]),Dt=N.useCallback(I=>{ve.current&&clearTimeout(ve.current),B(I),ve.current=setTimeout(()=>B(null),2e3)},[]),Rs=N.useCallback(async()=>{if(!se)return;const I=Jr(se.content);try{await Ss(I),Dt(o("chat.messageCopied"))}catch{Dt(o("chat.copyFailed"))}L(null)},[se,Dt,o]),Os=N.useCallback(async()=>{if(!se||se.role!=="user")return;const I=le();if(I===null)return;const O=Jr(se.content);if(!O)return;L(null);const $=se.images?.length?se.images.map((q,fe)=>{const Ie=q.data_url.split(";")[0]?.replace("data:","")||"image/png";return{id:`mobile_resend_${Date.now()}_${fe}`,data_url:q.data_url,mime_type:Ie,metadata:{name:q.name,source:"remote"}}}):void 0;try{if(await e.sendMessage(t,O,"agentic",$),!ce(I))return;y.current?.nudge()}catch(q){Je(q,f)}},[le,ce,se,t,e,f]),Ds=N.useCallback(async()=>{if(se){re(!0);try{Ft.getState().deleteMessage(t,se.id),Dt(o("chat.messageDeleted"))}finally{re(!1),L(null)}}},[se,t,Dt,o]);N.useEffect(()=>()=>{gt(),ve.current&&clearTimeout(ve.current)},[]);const St=N.useRef(!0),bt=N.useRef(!1),jn=N.useRef(!1),Ms=80,Fs=N.useCallback(()=>{const I=Me.current;if(!I)return;const $=I.scrollHeight-I.scrollTop-I.clientHeight0&&ht(q[0].id)}},[xe,ee,a,t,ht]),zs=N.useCallback(()=>{bt.current=!0,St.current=!0,He(!1),jn.current=!1,Xe.current?.scrollIntoView({behavior:"smooth"})},[]),Mt=N.useRef(!1),nn=N.useRef(!1),rn=N.useRef(0);N.useEffect(()=>{Ze.current=!1,Ce.current=!0,_e.current=!1,we(!0),te(!1),T(null),A("primary")},[t]),N.useEffect(()=>{Mt.current=!1,nn.current=!1;const I=++rn.current;let O=!1;const $=le();if($===null)return;const q=()=>!O&&rn.current===I&&ce($);return Promise.all([ht(),lt()]).then(([fe,Ie])=>{if(!q())return;const de=Ft.getState().getMessages(t).length;nn.current=!0;const ae=new Zs(e,t,X=>{q()&&(X.message_snapshot?l(t,X.message_snapshot):X.new_messages&&X.new_messages.length>0&&s(t,X.new_messages),X.total_msg_count!=null&&Ft.getState().getMessages(t).length!==X.total_msg_count&&e.getSessionMessages(t,200).then(nt=>{q()&&Ft.getState().setMessages(t,nt.messages)}).catch(()=>{}),X.title&&(C(X.title),g(t,X.title)),X.model_catalog&&(T(X.model_catalog),A(ut(X.model_catalog.session_model_id,X.model_catalog))),p(X.active_turn??null))},Ie?.version||0);ae.start(de),y.current=ae}),()=>{O=!0,rn.current===I&&(rn.current+=1),y.current?.stop(),y.current=null,p(null)}},[s,le,ce,ht,lt,t,e,p,l,g]);const an=N.useRef(0);N.useLayoutEffect(()=>{if(!nn.current||x.length===0)return;nn.current=!1;const I=Me.current;I&&(I.scrollTop=I.scrollHeight),Mt.current=!0,an.current=x.length},[x]),N.useEffect(()=>{if(Mt.current&&x.length!==an.current){const I=x.length>an.current;an.current=x.length,I&&!ee&&St.current&&(bt.current=!0,Xe.current?.scrollIntoView({behavior:"smooth"}))}},[x.length,ee]),N.useEffect(()=>{!Mt.current||!pe||St.current&&(bt.current=!0,Xe.current?.scrollIntoView({behavior:"auto"}))},[u,pe]),N.useEffect(()=>{G&&(bt.current=!0,St.current=!0,Xe.current?.scrollIntoView({behavior:"smooth"}))},[G]),N.useEffect(()=>{if(!Mt.current||!pe)return;const I=Me.current;if(!I)return;const O=setInterval(()=>{if(!St.current)return;const $=I.scrollHeight-I.scrollTop-I.clientHeight;$>10&&$<400&&(bt.current=!0,I.scrollTo({top:I.scrollHeight,behavior:"smooth"}))},300);return()=>clearInterval(O)},[pe]);const Rn=N.useCallback(async()=>{const I=v.trim(),O=M;if(!I&&O.length===0||P)return;const $=le();if($===null)return;const q=pe;b(""),H([]),q||ie(!1);const fe=O.length>0,Ie=fe?O.map((de,ae)=>{const X=de.dataUrl.split(";")[0]?.replace("data:","")||"image/png";return{id:`mobile_img_${Date.now()}_${ae}`,data_url:de.dataUrl,mime_type:X,metadata:{name:de.name,source:"remote"}}}):void 0;fe&&(J({id:`opt_${Date.now()}`,text:I||"",images:O.map(de=>({name:de.name,data_url:de.dataUrl}))}),z(!0));try{if(await e.sendMessage(t,I||o("chat.imageAttachmentFallback"),"agentic",Ie),!ce($))return;y.current?.nudge(),q&&Ue(o("chat.messageQueued"))}catch(de){Je(de,f)}finally{ce($)&&(z(!1),J(null))}},[le,P,v,ce,pe,M,t,e,f,o]),Ps=N.useCallback(()=>{K.current?.click()},[]),Bs=N.useCallback(async I=>{const O=I.target.files;if(!O)return;const $=5,q=$-M.length,fe=Array.from(O).slice(0,q),{compressImageFile:Ie}=await Xs(async()=>{const{compressImageFile:de}=await import("./imageCompressor-Cy77l5Xt.js");return{compressImageFile:de}},[],import.meta.url);for(const de of fe)try{const ae=await Ie(de);H(X=>X.length>=$?X:[...X,{name:ae.name,dataUrl:ae.dataUrl}])}catch{const ae=new FileReader;ae.onload=()=>{const X=ae.result;H(ue=>ue.length>=$?ue:[...ue,{name:de.name,dataUrl:X}])},ae.readAsDataURL(de)}I.target.value=""},[M.length]),$s=N.useCallback(I=>{H(O=>O.filter(($,q)=>q!==I))},[]),Wi=N.useCallback(()=>{ie(!0),requestAnimationFrame(()=>w.current?.focus())},[]);N.useEffect(()=>{i&&requestAnimationFrame(()=>w.current?.focus())},[i]),N.useEffect(()=>{if(!U)return;const I=O=>{Y.current&&!Y.current.contains(O.target)&&!v.trim()&&M.length===0&&ie(!1)};return document.addEventListener("mousedown",I),()=>document.removeEventListener("mousedown",I)},[U,v,M.length]);const On=N.useRef(!1),qs=N.useCallback(()=>{On.current=!0},[]),Us=N.useCallback(()=>{setTimeout(()=>{On.current=!1},0)},[]),Hs=I=>{if(I.key==="Enter"&&!I.shiftKey){if(I.nativeEvent.isComposing||On.current)return;I.preventDefault(),Rn()}},Ws=async()=>{if(le()!==null)try{await e.cancelTask(t,u?.turn_id)}catch{}},Vi=d?.project_name||d?.path?.split("/").pop()||"",Dn=d?.git_branch,Gi=_||n||o("chat.session");return h.jsxs("div",{className:"chat-page",children:[h.jsx("div",{className:"chat-page__header",children:h.jsxs("div",{className:"chat-page__header-row",children:[h.jsx("button",{className:"chat-page__back",onClick:r,"aria-label":o("common.back"),children:h.jsx("svg",{width:"18",height:"18",viewBox:"0 0 20 20",fill:"none",children:h.jsx("path",{d:"M12 4L6 10L12 16",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsxs("div",{className:"chat-page__header-center",children:[h.jsx("span",{className:"chat-page__title",title:Gi,children:Gi}),Vi&&h.jsxs("div",{className:"chat-page__header-workspace",title:d?.path,children:[h.jsx("span",{className:"chat-page__workspace-name",children:Vi}),Dn&&h.jsxs("span",{className:"chat-page__workspace-branch",title:Dn,children:[h.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("line",{x1:"6",x2:"6",y1:"3",y2:"15"}),h.jsx("circle",{cx:"18",cy:"6",r:"3"}),h.jsx("circle",{cx:"6",cy:"18",r:"3"}),h.jsx("path",{d:"M18 9a9 9 0 0 1-9 9"})]}),wx(Dn,28)]})]})]}),h.jsx("div",{className:"chat-page__header-right",children:h.jsx("button",{className:"chat-page__theme-btn",onClick:S,"aria-label":o("common.toggleTheme"),children:h.jsx(zx,{isDark:k})})})]})}),h.jsxs("div",{className:"chat-page__messages",ref:Me,onScroll:Fs,children:[ee&&h.jsx("div",{className:"chat-page__load-more-indicator",children:o("chat.loadingOlderMessages")}),(()=>{const I=x.reduceRight((O,$,q)=>O<0&&$.role==="user"?q:O,-1);return x.map((O,$)=>{if(O.role==="system"||O.role==="tool")return null;if(O.role==="user"){const ae=Jr(O.content);return h.jsx("div",{className:`chat-msg chat-msg--user${se?.id===O.id?" chat-msg--menu-active":""}`,onTouchStart:X=>mt(O,X),onTouchMove:In,onTouchEnd:wt,onTouchCancel:wt,onContextMenu:X=>{X.preventDefault(),L(O)},children:h.jsxs("div",{className:"chat-msg__user-card",children:[h.jsx("div",{className:"chat-msg__user-avatar",children:"U"}),h.jsxs("div",{className:"chat-msg__user-content",children:[ae,O.images&&O.images.length>0&&h.jsx("div",{className:"chat-msg__user-images",children:O.images.map((X,ue)=>h.jsx("img",{src:X.data_url,alt:X.name,className:"chat-msg__user-image"},ue))})]})]})},O.id)}const q=O.items&&O.items.length>0,fe=O.thinking||O.tools&&O.tools.length>0||O.content;if(!q&&!fe)return null;const Ie=$mt(O,ae),onTouchMove:In,onTouchEnd:wt,onTouchCancel:wt,onContextMenu:ae=>{ae.preventDefault(),L(O)},children:h.jsxs("button",{className:"chat-msg__response-toggle",onClick:()=>Fe(ae=>{const X=new Set(ae);return X.add(O.id),X}),children:[h.jsx("span",{className:"chat-msg__response-chevron",children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-msg__response-label",children:o("chat.showResponse")})]})},O.id):h.jsxs("div",{className:`chat-msg chat-msg--assistant${se?.id===O.id?" chat-msg--menu-active":""}`,onTouchStart:ae=>mt(O,ae),onTouchMove:In,onTouchEnd:wt,onTouchCancel:wt,onContextMenu:ae=>{ae.preventDefault(),L(O)},children:[Ie&&de&&h.jsxs("button",{className:"chat-msg__response-toggle",onClick:()=>Fe(ae=>{const X=new Set(ae);return X.delete(O.id),X}),children:[h.jsx("span",{className:"chat-msg__response-chevron is-open",children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("path",{d:"M6 4L10 8L6 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}),h.jsx("span",{className:"chat-msg__response-label",children:o("chat.hideResponse")})]}),q?Vo(O.items,Se,void 0,Le,ye,Ne):h.jsxs(h.Fragment,{children:[O.thinking&&h.jsx(xi,{thinking:O.thinking}),O.tools&&O.tools.length>0&&h.jsx(ki,{tools:O.tools,now:Se}),O.content&&h.jsx("div",{className:"chat-msg__assistant-content",children:h.jsx(Kt,{content:O.content,onFileDownload:ye,onGetFileInfo:Ne})})]})]},O.id)})})(),u&&(()=>{const I=u,O=I.status==="active";if(I.items&&I.items.length>0)return h.jsxs("div",{className:"chat-msg chat-msg--assistant",children:[O?Fx(I.items,Se,e,f,()=>le()!==null,Le,ye,Ne):Vo(I.items,Se,void 0,void 0,ye,Ne),O&&!I.thinking&&!I.text&&I.tools.length===0&&h.jsx("div",{className:"chat-msg__assistant-content",children:h.jsx(ti,{})})]});const $=I.tools.filter(ue=>ue.name==="Task"),q=$.some(ue=>ue.status==="running"),fe=I.tools.filter(ue=>ue.name==="AskUserQuestion"&&ue.status==="running"&&ue.tool_input),Ie=new Set(fe.map(ue=>ue.id)),de=I.tools.filter(ue=>ue.name!=="Task"&&!Ie.has(ue.id)),ae=q?[...I.thinking?[{type:"thinking",content:I.thinking}]:[],...de.map(ue=>({type:"tool",tool:ue}))]:[],X=ue=>{le()!==null&&e.cancelTool(ue,o("common.cancel")).catch(nt=>{Je(nt,f)})};return h.jsxs("div",{className:"chat-msg chat-msg--assistant",children:[!q&&(I.thinking||O)&&h.jsx(xi,{thinking:I.thinking,streaming:O,isLastItem:O}),$.map(ue=>h.jsx(_s,{tool:ue,now:Se,subItems:ue.status==="running"?ae:void 0,onCancelTool:X},ue.id)),!q&&de.length>0&&h.jsx(ki,{tools:de,now:Se,onCancelTool:X}),O&&fe.map(ue=>h.jsx(As,{tool:ue,onAnswer:Le},ue.id)),!q&&I.text?h.jsx("div",{className:"chat-msg__assistant-content",children:O?h.jsx(Ts,{content:I.text,onFileDownload:ye,onGetFileInfo:Ne}):h.jsx(Kt,{content:I.text,onFileDownload:ye,onGetFileInfo:Ne})}):O&&!I.thinking&&I.tools.length===0?h.jsx("div",{className:"chat-msg__assistant-content",children:h.jsx(ti,{})}):null]})})(),G&&h.jsx("div",{className:"chat-msg chat-msg--user",children:h.jsxs("div",{className:"chat-msg__user-card",children:[h.jsx("div",{className:"chat-msg__user-avatar",children:"U"}),h.jsxs("div",{className:"chat-msg__user-content",children:[G.text,G.images.length>0&&h.jsx("div",{className:"chat-msg__user-images",children:G.images.map((I,O)=>h.jsx("img",{src:I.data_url,alt:I.name,className:"chat-msg__user-image"},O))})]})]})}),P&&h.jsx("div",{className:"chat-msg chat-msg--assistant",children:h.jsx("div",{className:"chat-msg__assistant-card",children:h.jsxs("div",{className:"chat-msg__image-analyzing",children:[h.jsx("div",{className:"chat-msg__image-analyzing-icon",children:h.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("circle",{cx:"12",cy:"12",r:"3"}),h.jsx("path",{d:"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"})]})}),h.jsx("span",{children:o("chat.analyzingImage")}),h.jsx(ti,{})]})})}),h.jsx("div",{ref:Xe})]}),ft&&h.jsx("button",{type:"button",className:"chat-page__scroll-to-bottom",onClick:zs,"aria-label":o("chat.scrollToBottom"),children:h.jsx("svg",{"aria-hidden":"true",focusable:"false",width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:h.jsx("polyline",{points:"6 9 12 15 18 9"})})}),se&&h.jsx("div",{className:"chat-msg__menu-overlay",onClick:()=>L(null),children:h.jsxs("div",{className:"chat-msg__menu-sheet",onClick:I=>I.stopPropagation(),children:[h.jsx("div",{className:"chat-msg__menu-handle"}),h.jsxs("div",{className:"chat-msg__menu-actions",children:[h.jsxs("button",{className:"chat-msg__menu-btn",onClick:Rs,children:[h.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("rect",{x:"9",y:"9",width:"13",height:"13",rx:"2",ry:"2"}),h.jsx("path",{d:"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"})]}),h.jsx("span",{children:o("chat.copyMessage")})]}),se.role==="user"&&h.jsxs("button",{className:"chat-msg__menu-btn",onClick:Os,children:[h.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("polyline",{points:"23 4 23 10 17 10"}),h.jsx("path",{d:"M20.49 15a9 9 0 1 1-2.12-9.36L23 10"})]}),h.jsx("span",{children:o("chat.resendMessage")})]}),h.jsxs("button",{className:"chat-msg__menu-btn chat-msg__menu-btn--danger",onClick:Ds,disabled:V,children:[h.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("polyline",{points:"3 6 5 6 21 6"}),h.jsx("path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"})]}),h.jsx("span",{children:V?"...":o("chat.deleteMessage")})]})]}),h.jsx("button",{className:"chat-msg__menu-cancel",onClick:()=>L(null),children:o("common.cancel")})]})}),D&&h.jsx("div",{className:"chat-page__toast",role:"alert","aria-live":"assertive",children:D}),h.jsx("input",{ref:K,type:"file",accept:"image/png,image/jpeg,image/jpg,image/gif,image/webp",multiple:!0,style:{display:"none"},onChange:Bs}),h.jsx("div",{className:`chat-page__input-wrap ${U?"is-expanded":""}`,ref:Y,children:h.jsxs("div",{className:"chat-page__input-box",onClick:U?void 0:Wi,children:[h.jsx("div",{className:"chat-page__input-area",children:U?h.jsx("textarea",{ref:w,className:"chat-page__input",placeholder:o("chat.inputPlaceholder"),value:v,onChange:I=>b(I.target.value),onKeyDown:Hs,onCompositionStart:qs,onCompositionEnd:Us,rows:1,disabled:P}):h.jsx("span",{className:"chat-page__input-placeholder",children:o(P?"chat.imageAnalyzingPlaceholder":pe?"chat.collapsedStreamingPlaceholder":"chat.collapsedInputPlaceholder")})}),h.jsxs("div",{className:"chat-page__input-actions",children:[h.jsxs("div",{className:"chat-page__input-actions-left",children:[U&&h.jsxs(h.Fragment,{children:[h.jsx(Wx,{catalog:m,selectedModelId:j,disabled:P||pe||E,onSelect:Nn}),h.jsx(Vx,{catalog:m,selectedModelId:j,disabled:P||pe||E,onSelect:tn})]}),U&&M.length>0&&h.jsx("div",{className:"chat-page__image-preview-row",children:M.map((I,O)=>h.jsxs("div",{className:"chat-page__image-thumb",children:[h.jsx("img",{src:I.dataUrl,alt:I.name}),h.jsx("button",{className:"chat-page__image-remove",onClick:()=>$s(O),children:"×"})]},O))})]}),h.jsxs("div",{className:"chat-page__input-actions-right",children:[U&&h.jsx("button",{className:"chat-page__action-btn",onClick:Ps,disabled:P||M.length>=5,"aria-label":o("common.attachImage"),children:h.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[h.jsx("rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",ry:"2"}),h.jsx("circle",{cx:"9",cy:"9",r:"2"}),h.jsx("path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"})]})}),P?h.jsx("button",{className:"chat-page__send-btn is-stop","aria-label":o("common.stop"),disabled:!0,children:h.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",style:{animation:"analyzeSpin 2s linear infinite"},children:[h.jsx("circle",{cx:"12",cy:"12",r:"3"}),h.jsx("path",{d:"M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2"})]})}):pe?h.jsxs("div",{className:"chat-page__stream-actions",children:[h.jsx("button",{type:"button",className:"chat-page__send-btn is-stop",onClick:Ws,"aria-label":o("common.stop"),children:h.jsx("svg",{width:"10",height:"10",viewBox:"0 0 16 16",fill:"none",children:h.jsx("rect",{x:"3",y:"3",width:"10",height:"10",rx:"2",fill:"currentColor"})})}),h.jsx("button",{type:"button",className:"chat-page__send-btn",onClick:U?Rn:Wi,disabled:!v.trim()&&M.length===0,"aria-label":o("common.submit"),children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 20 20",fill:"none",children:h.jsx("path",{d:"M10 3L10 17M10 3L5 8M10 3L15 8",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]}):h.jsx("button",{className:"chat-page__send-btn",onClick:U?Rn:void 0,disabled:!v.trim()&&M.length===0,children:h.jsx("svg",{width:"12",height:"12",viewBox:"0 0 20 20",fill:"none",children:h.jsx("path",{d:"M10 3L10 17M10 3L5 8M10 3L15 8",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})]})]})]})}),c&&h.jsx("div",{className:"chat-page__toast",onClick:()=>f(null),children:c}),Qe&&h.jsx("div",{className:"chat-page__toast chat-page__toast--info",onClick:()=>Ue(null),children:Qe})]})};export{Zx as default}; diff --git a/src/apps/relay-server/static/assets/index-BNRAmblM.js b/src/apps/relay-server/static/assets/index-BNRAmblM.js deleted file mode 100644 index 820a3e352f..0000000000 --- a/src/apps/relay-server/static/assets/index-BNRAmblM.js +++ /dev/null @@ -1,9 +0,0 @@ -(function(){const l=document.createElement("link").relList;if(l&&l.supports&&l.supports("modulepreload"))return;for(const f of document.querySelectorAll('link[rel="modulepreload"]'))d(f);new MutationObserver(f=>{for(const m of f)if(m.type==="childList")for(const p of m.addedNodes)p.tagName==="LINK"&&p.rel==="modulepreload"&&d(p)}).observe(document,{childList:!0,subtree:!0});function a(f){const m={};return f.integrity&&(m.integrity=f.integrity),f.referrerPolicy&&(m.referrerPolicy=f.referrerPolicy),f.crossOrigin==="use-credentials"?m.credentials="include":f.crossOrigin==="anonymous"?m.credentials="omit":m.credentials="same-origin",m}function d(f){if(f.ep)return;f.ep=!0;const m=a(f);fetch(f.href,m)}})();let fi="dark";try{const o=localStorage.getItem("bitfun-mobile-theme");(o==="dark"||o==="light")&&(fi=o)}catch{window.matchMedia?.("(prefers-color-scheme: light)").matches&&(fi="light")}document.documentElement.setAttribute("data-theme",fi);document.documentElement.style.colorScheme=fi;var Mg=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Fd(o){return o&&o.__esModule&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o}var Xl={exports:{}},Ms={},Jl={exports:{}},we={};var Xc;function nh(){if(Xc)return we;Xc=1;var o=Symbol.for("react.element"),l=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),d=Symbol.for("react.strict_mode"),f=Symbol.for("react.profiler"),m=Symbol.for("react.provider"),p=Symbol.for("react.context"),_=Symbol.for("react.forward_ref"),w=Symbol.for("react.suspense"),E=Symbol.for("react.memo"),I=Symbol.for("react.lazy"),j=Symbol.iterator;function R(v){return v===null||typeof v!="object"?null:(v=j&&v[j]||v["@@iterator"],typeof v=="function"?v:null)}var B={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},F=Object.assign,$={};function W(v,T,re){this.props=v,this.context=T,this.refs=$,this.updater=re||B}W.prototype.isReactComponent={},W.prototype.setState=function(v,T){if(typeof v!="object"&&typeof v!="function"&&v!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,v,T,"setState")},W.prototype.forceUpdate=function(v){this.updater.enqueueForceUpdate(this,v,"forceUpdate")};function de(){}de.prototype=W.prototype;function b(v,T,re){this.props=v,this.context=T,this.refs=$,this.updater=re||B}var K=b.prototype=new de;K.constructor=b,F(K,W.prototype),K.isPureReactComponent=!0;var se=Array.isArray,_e=Object.prototype.hasOwnProperty,fe={current:null},ke={key:!0,ref:!0,__self:!0,__source:!0};function Se(v,T,re){var ue,pe={},ce=null,te=null;if(T!=null)for(ue in T.ref!==void 0&&(te=T.ref),T.key!==void 0&&(ce=""+T.key),T)_e.call(T,ue)&&!ke.hasOwnProperty(ue)&&(pe[ue]=T[ue]);var ge=arguments.length-2;if(ge===1)pe.children=re;else if(1>>1,T=D[v];if(0>>1;vf(pe,L))cef(te,pe)?(D[v]=te,D[ce]=L,v=ce):(D[v]=pe,D[ue]=L,v=ue);else if(cef(te,L))D[v]=te,D[ce]=L,v=ce;else break e}}return O}function f(D,O){var L=D.sortIndex-O.sortIndex;return L!==0?L:D.id-O.id}if(typeof performance=="object"&&typeof performance.now=="function"){var m=performance;o.unstable_now=function(){return m.now()}}else{var p=Date,_=p.now();o.unstable_now=function(){return p.now()-_}}var w=[],E=[],I=1,j=null,R=3,B=!1,F=!1,$=!1,W=typeof setTimeout=="function"?setTimeout:null,de=typeof clearTimeout=="function"?clearTimeout:null,b=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function K(D){for(var O=a(E);O!==null;){if(O.callback===null)d(E);else if(O.startTime<=D)d(E),O.sortIndex=O.expirationTime,l(w,O);else break;O=a(E)}}function se(D){if($=!1,K(D),!F)if(a(w)!==null)F=!0,ae(_e);else{var O=a(E);O!==null&&ne(se,O.startTime-D)}}function _e(D,O){F=!1,$&&($=!1,de(Se),Se=-1),B=!0;var L=R;try{for(K(O),j=a(w);j!==null&&(!(j.expirationTime>O)||D&&!Ce());){var v=j.callback;if(typeof v=="function"){j.callback=null,R=j.priorityLevel;var T=v(j.expirationTime<=O);O=o.unstable_now(),typeof T=="function"?j.callback=T:j===a(w)&&d(w),K(O)}else d(w);j=a(w)}if(j!==null)var re=!0;else{var ue=a(E);ue!==null&&ne(se,ue.startTime-O),re=!1}return re}finally{j=null,R=L,B=!1}}var fe=!1,ke=null,Se=-1,Te=5,Me=-1;function Ce(){return!(o.unstable_now()-MeD||125v?(D.sortIndex=L,l(E,D),a(w)===null&&D===a(E)&&($?(de(Se),Se=-1):$=!0,ne(se,L-v))):(D.sortIndex=T,l(w,D),F||B||(F=!0,ae(_e))),D},o.unstable_shouldYield=Ce,o.unstable_wrapCallback=function(D){var O=R;return function(){var L=R;R=O;try{return D.apply(this,arguments)}finally{R=L}}}})(na)),na}var rd;function ih(){return rd||(rd=1,ta.exports=oh()),ta.exports}var sd;function lh(){if(sd)return yt;sd=1;var o=xa(),l=ih();function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),w=Object.prototype.hasOwnProperty,E=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,I={},j={};function R(e){return w.call(j,e)?!0:w.call(I,e)?!1:E.test(e)?j[e]=!0:(I[e]=!0,!1)}function B(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function F(e,t,n,r){if(t===null||typeof t>"u"||B(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function $(e,t,n,r,s,i,c){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=s,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=i,this.removeEmptyString=c}var W={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){W[e]=new $(e,0,!1,e,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];W[t]=new $(t,1,!1,e[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(e){W[e]=new $(e,2,!1,e.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){W[e]=new $(e,2,!1,e,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){W[e]=new $(e,3,!1,e.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(e){W[e]=new $(e,3,!0,e,null,!1,!1)}),["capture","download"].forEach(function(e){W[e]=new $(e,4,!1,e,null,!1,!1)}),["cols","rows","size","span"].forEach(function(e){W[e]=new $(e,6,!1,e,null,!1,!1)}),["rowSpan","start"].forEach(function(e){W[e]=new $(e,5,!1,e.toLowerCase(),null,!1,!1)});var de=/[\-:]([a-z])/g;function b(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(de,b);W[t]=new $(t,1,!1,e,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(de,b);W[t]=new $(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(de,b);W[t]=new $(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(e){W[e]=new $(e,1,!1,e.toLowerCase(),null,!1,!1)}),W.xlinkHref=new $("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(e){W[e]=new $(e,1,!1,e.toLowerCase(),null,!0,!0)});function K(e,t,n,r){var s=W.hasOwnProperty(t)?W[t]:null;(s!==null?s.type!==0:r||!(2h||s[c]!==i[h]){var g=` -`+s[c].replace(" at new "," at ");return e.displayName&&g.includes("")&&(g=g.replace("",e.displayName)),g}while(1<=c&&0<=h);break}}}finally{re=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?T(e):""}function pe(e){switch(e.tag){case 5:return T(e.type);case 16:return T("Lazy");case 13:return T("Suspense");case 19:return T("SuspenseList");case 0:case 2:case 15:return e=ue(e.type,!1),e;case 11:return e=ue(e.type.render,!1),e;case 1:return e=ue(e.type,!0),e;default:return""}}function ce(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case ke:return"Fragment";case fe:return"Portal";case Te:return"Profiler";case Se:return"StrictMode";case Q:return"Suspense";case q:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Ce:return(e.displayName||"Context")+".Consumer";case Me:return(e._context.displayName||"Context")+".Provider";case me:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case ee:return t=e.displayName||null,t!==null?t:ce(e.type)||"Memo";case ae:t=e._payload,e=e._init;try{return ce(e(t))}catch{}}return null}function te(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return ce(t);case 8:return t===Se?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function ge(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function ye(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function De(e){var t=ye(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var s=n.get,i=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return s.call(this)},set:function(c){r=""+c,i.call(this,c)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(c){r=""+c},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function ct(e){e._valueTracker||(e._valueTracker=De(e))}function kt(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=ye(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function ze(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function $e(e,t){var n=t.checked;return L({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function Ie(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=ge(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function He(e,t){t=t.checked,t!=null&&K(e,"checked",t,!1)}function Ve(e,t){He(e,t);var n=ge(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Ye(e,t.type,n):t.hasOwnProperty("defaultValue")&&Ye(e,t.type,ge(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function jt(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function Ye(e,t,n){(t!=="number"||ze(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var nt=Array.isArray;function $t(e,t,n,r){if(e=e.options,t){t={};for(var s=0;s"+t.valueOf().toString()+"",t=St.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function Tt(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var Ee={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},le=["Webkit","ms","Moz","O"];Object.keys(Ee).forEach(function(e){le.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),Ee[t]=Ee[e]})});function hr(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||Ee.hasOwnProperty(e)&&Ee[e]?(""+t).trim():t+"px"}function Xr(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,s=hr(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,s):e[n]=s}}var Xn=L({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function mr(e,t){if(t){if(Xn[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(a(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(a(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(a(61))}if(t.style!=null&&typeof t.style!="object")throw Error(a(62))}}function gr(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var Tn=null;function vr(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var un=null,cn=null,dn=null;function fn(e){if(e=_s(e)){if(typeof un!="function")throw Error(a(280));var t=e.stateNode;t&&(t=mo(t),un(e.stateNode,e.type,t))}}function In(e){cn?dn?dn.push(e):dn=[e]:cn=e}function pn(){if(cn){var e=cn,t=dn;if(dn=cn=null,fn(e),t)for(e=0;e>>=0,e===0?32:31-(yf(e)/wf|0)|0}var Gs=64,Zs=4194304;function ns(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function Xs(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,s=e.suspendedLanes,i=e.pingedLanes,c=n&268435455;if(c!==0){var h=c&~s;h!==0?r=ns(h):(i&=c,i!==0&&(r=ns(i)))}else c=n&~s,c!==0?r=ns(c):i!==0&&(r=ns(i));if(r===0)return 0;if(t!==0&&t!==r&&(t&s)===0&&(s=r&-r,i=t&-t,s>=i||s===16&&(i&4194240)!==0))return t;if((r&4)!==0&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function rs(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-Kt(t),e[t]=n}function xf(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=ds),ba=" ",Ka=!1;function Qa(e,t){switch(e){case"keyup":return Zf.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function qa(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Nr=!1;function Jf(e,t){switch(e){case"compositionend":return qa(t);case"keypress":return t.which!==32?null:(Ka=!0,ba);case"textInput":return e=t.data,e===ba&&Ka?null:e;default:return null}}function ep(e,t){if(Nr)return e==="compositionend"||!Pi&&Qa(e,t)?(e=Ba(),ro=Ni=An=null,Nr=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=tu(n)}}function ru(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?ru(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function su(){for(var e=window,t=ze();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=ze(e.document)}return t}function Mi(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function up(e){var t=su(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&ru(n.ownerDocument.documentElement,n)){if(r!==null&&Mi(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var s=n.textContent.length,i=Math.min(r.start,s);r=r.end===void 0?i:Math.min(r.end,s),!e.extend&&i>r&&(s=r,r=i,i=s),s=nu(n,i);var c=nu(n,r);s&&c&&(e.rangeCount!==1||e.anchorNode!==s.node||e.anchorOffset!==s.offset||e.focusNode!==c.node||e.focusOffset!==c.offset)&&(t=t.createRange(),t.setStart(s.node,s.offset),e.removeAllRanges(),i>r?(e.addRange(t),e.extend(c.node,c.offset)):(t.setEnd(c.node,c.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,jr=null,zi=null,ms=null,Ui=!1;function ou(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Ui||jr==null||jr!==ze(r)||(r=jr,"selectionStart"in r&&Mi(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),ms&&hs(ms,r)||(ms=r,r=fo(zi,"onSelect"),0Pr||(e.current=Yi[Pr],Yi[Pr]=null,Pr--)}function Ae(e,t){Pr++,Yi[Pr]=e.current,e.current=t}var On={},it=Un(On),pt=Un(!1),er=On;function Dr(e,t){var n=e.type.contextTypes;if(!n)return On;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var s={},i;for(i in n)s[i]=t[i];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=s),s}function ht(e){return e=e.childContextTypes,e!=null}function go(){Oe(pt),Oe(it)}function _u(e,t,n){if(it.current!==On)throw Error(a(168));Ae(it,t),Ae(pt,n)}function ku(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var s in r)if(!(s in t))throw Error(a(108,te(e)||"Unknown",s));return L({},n,r)}function vo(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||On,er=it.current,Ae(it,e),Ae(pt,pt.current),!0}function Su(e,t,n){var r=e.stateNode;if(!r)throw Error(a(169));n?(e=ku(e,t,er),r.__reactInternalMemoizedMergedChildContext=e,Oe(pt),Oe(it),Ae(it,e)):Oe(pt),Ae(pt,n)}var gn=null,yo=!1,Gi=!1;function xu(e){gn===null?gn=[e]:gn.push(e)}function kp(e){yo=!0,xu(e)}function Bn(){if(!Gi&&gn!==null){Gi=!0;var e=0,t=Pe;try{var n=gn;for(Pe=1;e>=c,s-=c,vn=1<<32-Kt(t)+s|n<he?(tt=ie,ie=null):tt=ie.sibling;var Re=P(k,ie,x[he],U);if(Re===null){ie===null&&(ie=tt);break}e&&ie&&Re.alternate===null&&t(k,ie),y=i(Re,y,he),oe===null?J=Re:oe.sibling=Re,oe=Re,ie=tt}if(he===x.length)return n(k,ie),Be&&nr(k,he),J;if(ie===null){for(;hehe?(tt=ie,ie=null):tt=ie.sibling;var qn=P(k,ie,Re.value,U);if(qn===null){ie===null&&(ie=tt);break}e&&ie&&qn.alternate===null&&t(k,ie),y=i(qn,y,he),oe===null?J=qn:oe.sibling=qn,oe=qn,ie=tt}if(Re.done)return n(k,ie),Be&&nr(k,he),J;if(ie===null){for(;!Re.done;he++,Re=x.next())Re=M(k,Re.value,U),Re!==null&&(y=i(Re,y,he),oe===null?J=Re:oe.sibling=Re,oe=Re);return Be&&nr(k,he),J}for(ie=r(k,ie);!Re.done;he++,Re=x.next())Re=H(ie,k,he,Re.value,U),Re!==null&&(e&&Re.alternate!==null&&ie.delete(Re.key===null?he:Re.key),y=i(Re,y,he),oe===null?J=Re:oe.sibling=Re,oe=Re);return e&&ie.forEach(function(th){return t(k,th)}),Be&&nr(k,he),J}function Ke(k,y,x,U){if(typeof x=="object"&&x!==null&&x.type===ke&&x.key===null&&(x=x.props.children),typeof x=="object"&&x!==null){switch(x.$$typeof){case _e:e:{for(var J=x.key,oe=y;oe!==null;){if(oe.key===J){if(J=x.type,J===ke){if(oe.tag===7){n(k,oe.sibling),y=s(oe,x.props.children),y.return=k,k=y;break e}}else if(oe.elementType===J||typeof J=="object"&&J!==null&&J.$$typeof===ae&&Iu(J)===oe.type){n(k,oe.sibling),y=s(oe,x.props),y.ref=ks(k,oe,x),y.return=k,k=y;break e}n(k,oe);break}else t(k,oe);oe=oe.sibling}x.type===ke?(y=cr(x.props.children,k.mode,U,x.key),y.return=k,k=y):(U=Ko(x.type,x.key,x.props,null,k.mode,U),U.ref=ks(k,y,x),U.return=k,k=U)}return c(k);case fe:e:{for(oe=x.key;y!==null;){if(y.key===oe)if(y.tag===4&&y.stateNode.containerInfo===x.containerInfo&&y.stateNode.implementation===x.implementation){n(k,y.sibling),y=s(y,x.children||[]),y.return=k,k=y;break e}else{n(k,y);break}else t(k,y);y=y.sibling}y=Ql(x,k.mode,U),y.return=k,k=y}return c(k);case ae:return oe=x._init,Ke(k,y,oe(x._payload),U)}if(nt(x))return Z(k,y,x,U);if(O(x))return X(k,y,x,U);So(k,x)}return typeof x=="string"&&x!==""||typeof x=="number"?(x=""+x,y!==null&&y.tag===6?(n(k,y.sibling),y=s(y,x),y.return=k,k=y):(n(k,y),y=Kl(x,k.mode,U),y.return=k,k=y),c(k)):n(k,y)}return Ke}var Ur=Ru(!0),Lu=Ru(!1),xo=Un(null),Co=null,Or=null,nl=null;function rl(){nl=Or=Co=null}function sl(e){var t=xo.current;Oe(xo),e._currentValue=t}function ol(e,t,n){for(;e!==null;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,r!==null&&(r.childLanes|=t)):r!==null&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function Br(e,t){Co=e,nl=Or=null,e=e.dependencies,e!==null&&e.firstContext!==null&&((e.lanes&t)!==0&&(mt=!0),e.firstContext=null)}function At(e){var t=e._currentValue;if(nl!==e)if(e={context:e,memoizedValue:t,next:null},Or===null){if(Co===null)throw Error(a(308));Or=e,Co.dependencies={lanes:0,firstContext:e}}else Or=Or.next=e;return t}var rr=null;function il(e){rr===null?rr=[e]:rr.push(e)}function Pu(e,t,n,r){var s=t.interleaved;return s===null?(n.next=n,il(t)):(n.next=s.next,s.next=n),t.interleaved=n,wn(e,r)}function wn(e,t){e.lanes|=t;var n=e.alternate;for(n!==null&&(n.lanes|=t),n=e,e=e.return;e!==null;)e.childLanes|=t,n=e.alternate,n!==null&&(n.childLanes|=t),n=e,e=e.return;return n.tag===3?n.stateNode:null}var Fn=!1;function ll(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Du(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function _n(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Wn(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,(je&2)!==0){var s=r.pending;return s===null?t.next=t:(t.next=s.next,s.next=t),r.pending=t,wn(e,n)}return s=r.interleaved,s===null?(t.next=t,il(r)):(t.next=s.next,s.next=t),r.interleaved=t,wn(e,n)}function Eo(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194240)!==0)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ki(e,n)}}function Au(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var s=null,i=null;if(n=n.firstBaseUpdate,n!==null){do{var c={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};i===null?s=i=c:i=i.next=c,n=n.next}while(n!==null);i===null?s=i=t:i=i.next=t}else s=i=t;n={baseState:r.baseState,firstBaseUpdate:s,lastBaseUpdate:i,shared:r.shared,effects:r.effects},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function No(e,t,n,r){var s=e.updateQueue;Fn=!1;var i=s.firstBaseUpdate,c=s.lastBaseUpdate,h=s.shared.pending;if(h!==null){s.shared.pending=null;var g=h,N=g.next;g.next=null,c===null?i=N:c.next=N,c=g;var A=e.alternate;A!==null&&(A=A.updateQueue,h=A.lastBaseUpdate,h!==c&&(h===null?A.firstBaseUpdate=N:h.next=N,A.lastBaseUpdate=g))}if(i!==null){var M=s.baseState;c=0,A=N=g=null,h=i;do{var P=h.lane,H=h.eventTime;if((r&P)===P){A!==null&&(A=A.next={eventTime:H,lane:0,tag:h.tag,payload:h.payload,callback:h.callback,next:null});e:{var Z=e,X=h;switch(P=t,H=n,X.tag){case 1:if(Z=X.payload,typeof Z=="function"){M=Z.call(H,M,P);break e}M=Z;break e;case 3:Z.flags=Z.flags&-65537|128;case 0:if(Z=X.payload,P=typeof Z=="function"?Z.call(H,M,P):Z,P==null)break e;M=L({},M,P);break e;case 2:Fn=!0}}h.callback!==null&&h.lane!==0&&(e.flags|=64,P=s.effects,P===null?s.effects=[h]:P.push(h))}else H={eventTime:H,lane:P,tag:h.tag,payload:h.payload,callback:h.callback,next:null},A===null?(N=A=H,g=M):A=A.next=H,c|=P;if(h=h.next,h===null){if(h=s.shared.pending,h===null)break;P=h,h=P.next,P.next=null,s.lastBaseUpdate=P,s.shared.pending=null}}while(!0);if(A===null&&(g=M),s.baseState=g,s.firstBaseUpdate=N,s.lastBaseUpdate=A,t=s.shared.interleaved,t!==null){s=t;do c|=s.lane,s=s.next;while(s!==t)}else i===null&&(s.shared.lanes=0);ir|=c,e.lanes=c,e.memoizedState=M}}function Mu(e,t,n){if(e=t.effects,t.effects=null,e!==null)for(t=0;tn?n:4,e(!0);var r=fl.transition;fl.transition={};try{e(!1),t()}finally{Pe=n,fl.transition=r}}function ec(){return Mt().memoizedState}function Ep(e,t,n){var r=bn(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},tc(e))nc(t,n);else if(n=Pu(e,t,n,r),n!==null){var s=ft();Xt(n,e,r,s),rc(n,t,r)}}function Np(e,t,n){var r=bn(e),s={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(tc(e))nc(t,s);else{var i=e.alternate;if(e.lanes===0&&(i===null||i.lanes===0)&&(i=t.lastRenderedReducer,i!==null))try{var c=t.lastRenderedState,h=i(c,n);if(s.hasEagerState=!0,s.eagerState=h,Qt(h,c)){var g=t.interleaved;g===null?(s.next=s,il(t)):(s.next=g.next,g.next=s),t.interleaved=s;return}}catch{}n=Pu(e,t,s,r),n!==null&&(s=ft(),Xt(n,e,r,s),rc(n,t,r))}}function tc(e){var t=e.alternate;return e===We||t!==null&&t===We}function nc(e,t){Es=Io=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function rc(e,t,n){if((n&4194240)!==0){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,ki(e,n)}}var Po={readContext:At,useCallback:lt,useContext:lt,useEffect:lt,useImperativeHandle:lt,useInsertionEffect:lt,useLayoutEffect:lt,useMemo:lt,useReducer:lt,useRef:lt,useState:lt,useDebugValue:lt,useDeferredValue:lt,useTransition:lt,useMutableSource:lt,useSyncExternalStore:lt,useId:lt,unstable_isNewReconciler:!1},jp={readContext:At,useCallback:function(e,t){return rn().memoizedState=[e,t===void 0?null:t],e},useContext:At,useEffect:Ku,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,Ro(4194308,4,Yu.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Ro(4194308,4,e,t)},useInsertionEffect:function(e,t){return Ro(4,2,e,t)},useMemo:function(e,t){var n=rn();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=rn();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=Ep.bind(null,We,e),[r.memoizedState,e]},useRef:function(e){var t=rn();return e={current:e},t.memoizedState=e},useState:Vu,useDebugValue:wl,useDeferredValue:function(e){return rn().memoizedState=e},useTransition:function(){var e=Vu(!1),t=e[0];return e=Cp.bind(null,e[1]),rn().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=We,s=rn();if(Be){if(n===void 0)throw Error(a(407));n=n()}else{if(n=t(),et===null)throw Error(a(349));(or&30)!==0||Bu(r,t,n)}s.memoizedState=n;var i={value:n,getSnapshot:t};return s.queue=i,Ku(Wu.bind(null,r,i,e),[e]),r.flags|=2048,Ts(9,Fu.bind(null,r,i,n,t),void 0,null),n},useId:function(){var e=rn(),t=et.identifierPrefix;if(Be){var n=yn,r=vn;n=(r&~(1<<32-Kt(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=Ns++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=c.createElement(n,{is:r.is}):(e=c.createElement(n),n==="select"&&(c=e,r.multiple?c.multiple=!0:r.size&&(c.size=r.size))):e=c.createElementNS(e,n),e[tn]=t,e[ws]=r,xc(e,t,!1,!1),t.stateNode=e;e:{switch(c=gr(n,r),n){case"dialog":Ue("cancel",e),Ue("close",e),s=r;break;case"iframe":case"object":case"embed":Ue("load",e),s=r;break;case"video":case"audio":for(s=0;sVr&&(t.flags|=128,r=!0,Is(i,!1),t.lanes=4194304)}else{if(!r)if(e=jo(c),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),Is(i,!0),i.tail===null&&i.tailMode==="hidden"&&!c.alternate&&!Be)return at(t),null}else 2*Le()-i.renderingStartTime>Vr&&n!==1073741824&&(t.flags|=128,r=!0,Is(i,!1),t.lanes=4194304);i.isBackwards?(c.sibling=t.child,t.child=c):(n=i.last,n!==null?n.sibling=c:t.child=c,i.last=c)}return i.tail!==null?(t=i.tail,i.rendering=t,i.tail=t.sibling,i.renderingStartTime=Le(),t.sibling=null,n=Fe.current,Ae(Fe,r?n&1|2:n&1),t):(at(t),null);case 22:case 23:return Hl(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&(t.mode&1)!==0?(Nt&1073741824)!==0&&(at(t),t.subtreeFlags&6&&(t.flags|=8192)):at(t),null;case 24:return null;case 25:return null}throw Error(a(156,t.tag))}function Mp(e,t){switch(Xi(t),t.tag){case 1:return ht(t.type)&&go(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Fr(),Oe(pt),Oe(it),dl(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 5:return ul(t),null;case 13:if(Oe(Fe),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(a(340));zr()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return Oe(Fe),null;case 4:return Fr(),null;case 10:return sl(t.type._context),null;case 22:case 23:return Hl(),null;case 24:return null;default:return null}}var zo=!1,ut=!1,zp=typeof WeakSet=="function"?WeakSet:Set,G=null;function $r(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){be(e,t,r)}else n.current=null}function Ll(e,t,n){try{n()}catch(r){be(e,t,r)}}var Nc=!1;function Up(e,t){if(Hi=to,e=su(),Mi(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var s=r.anchorOffset,i=r.focusNode;r=r.focusOffset;try{n.nodeType,i.nodeType}catch{n=null;break e}var c=0,h=-1,g=-1,N=0,A=0,M=e,P=null;t:for(;;){for(var H;M!==n||s!==0&&M.nodeType!==3||(h=c+s),M!==i||r!==0&&M.nodeType!==3||(g=c+r),M.nodeType===3&&(c+=M.nodeValue.length),(H=M.firstChild)!==null;)P=M,M=H;for(;;){if(M===e)break t;if(P===n&&++N===s&&(h=c),P===i&&++A===r&&(g=c),(H=M.nextSibling)!==null)break;M=P,P=M.parentNode}M=H}n=h===-1||g===-1?null:{start:h,end:g}}else n=null}n=n||{start:0,end:0}}else n=null;for(Vi={focusedElem:e,selectionRange:n},to=!1,G=t;G!==null;)if(t=G,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,G=e;else for(;G!==null;){t=G;try{var Z=t.alternate;if((t.flags&1024)!==0)switch(t.tag){case 0:case 11:case 15:break;case 1:if(Z!==null){var X=Z.memoizedProps,Ke=Z.memoizedState,k=t.stateNode,y=k.getSnapshotBeforeUpdate(t.elementType===t.type?X:Yt(t.type,X),Ke);k.__reactInternalSnapshotBeforeUpdate=y}break;case 3:var x=t.stateNode.containerInfo;x.nodeType===1?x.textContent="":x.nodeType===9&&x.documentElement&&x.removeChild(x.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(a(163))}}catch(U){be(t,t.return,U)}if(e=t.sibling,e!==null){e.return=t.return,G=e;break}G=t.return}return Z=Nc,Nc=!1,Z}function Rs(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var s=r=r.next;do{if((s.tag&e)===e){var i=s.destroy;s.destroy=void 0,i!==void 0&&Ll(t,n,i)}s=s.next}while(s!==r)}}function Uo(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function Pl(e){var t=e.ref;if(t!==null){var n=e.stateNode;e.tag,e=n,typeof t=="function"?t(e):t.current=e}}function jc(e){var t=e.alternate;t!==null&&(e.alternate=null,jc(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[tn],delete t[ws],delete t[qi],delete t[wp],delete t[_p])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function Tc(e){return e.tag===5||e.tag===3||e.tag===4}function Ic(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||Tc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Dl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ho));else if(r!==4&&(e=e.child,e!==null))for(Dl(e,t,n),e=e.sibling;e!==null;)Dl(e,t,n),e=e.sibling}function Al(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(Al(e,t,n),e=e.sibling;e!==null;)Al(e,t,n),e=e.sibling}var rt=null,Gt=!1;function $n(e,t,n){for(n=n.child;n!==null;)Rc(e,t,n),n=n.sibling}function Rc(e,t,n){if(Lt&&typeof Lt.onCommitFiberUnmount=="function")try{Lt.onCommitFiberUnmount(en,n)}catch{}switch(n.tag){case 5:ut||$r(n,t);case 6:var r=rt,s=Gt;rt=null,$n(e,t,n),rt=r,Gt=s,rt!==null&&(Gt?(e=rt,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):rt.removeChild(n.stateNode));break;case 18:rt!==null&&(Gt?(e=rt,n=n.stateNode,e.nodeType===8?Qi(e.parentNode,n):e.nodeType===1&&Qi(e,n),as(e)):Qi(rt,n.stateNode));break;case 4:r=rt,s=Gt,rt=n.stateNode.containerInfo,Gt=!0,$n(e,t,n),rt=r,Gt=s;break;case 0:case 11:case 14:case 15:if(!ut&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){s=r=r.next;do{var i=s,c=i.destroy;i=i.tag,c!==void 0&&((i&2)!==0||(i&4)!==0)&&Ll(n,t,c),s=s.next}while(s!==r)}$n(e,t,n);break;case 1:if(!ut&&($r(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(h){be(n,t,h)}$n(e,t,n);break;case 21:$n(e,t,n);break;case 22:n.mode&1?(ut=(r=ut)||n.memoizedState!==null,$n(e,t,n),ut=r):$n(e,t,n);break;default:$n(e,t,n)}}function Lc(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new zp),t.forEach(function(r){var s=Kp.bind(null,e,r);n.has(r)||(n.add(r),r.then(s,s))})}}function Zt(e,t){var n=t.deletions;if(n!==null)for(var r=0;rs&&(s=c),r&=~i}if(r=s,r=Le()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*Bp(r/1960))-r,10e?16:e,Vn===null)var r=!1;else{if(e=Vn,Vn=null,$o=0,(je&6)!==0)throw Error(a(331));var s=je;for(je|=4,G=e.current;G!==null;){var i=G,c=i.child;if((G.flags&16)!==0){var h=i.deletions;if(h!==null){for(var g=0;gLe()-Ul?ar(e,0):zl|=n),vt(e,t)}function Vc(e,t){t===0&&((e.mode&1)===0?t=1:(t=Zs,Zs<<=1,(Zs&130023424)===0&&(Zs=4194304)));var n=ft();e=wn(e,t),e!==null&&(rs(e,t,n),vt(e,n))}function bp(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Vc(e,n)}function Kp(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,s=e.memoizedState;s!==null&&(n=s.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(a(314))}r!==null&&r.delete(t),Vc(e,n)}var bc;bc=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||pt.current)mt=!0;else{if((e.lanes&n)===0&&(t.flags&128)===0)return mt=!1,Dp(e,t,n);mt=(e.flags&131072)!==0}else mt=!1,Be&&(t.flags&1048576)!==0&&Cu(t,_o,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;Mo(e,t),e=t.pendingProps;var s=Dr(t,it.current);Br(t,n),s=hl(null,t,r,e,s,n);var i=ml();return t.flags|=1,typeof s=="object"&&s!==null&&typeof s.render=="function"&&s.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,ht(r)?(i=!0,vo(t)):i=!1,t.memoizedState=s.state!==null&&s.state!==void 0?s.state:null,ll(t),s.updater=Do,t.stateNode=s,s._reactInternals=t,kl(t,r,e,n),t=El(null,t,r,!0,i,n)):(t.tag=0,Be&&i&&Zi(t),dt(null,t,s,n),t=t.child),t;case 16:r=t.elementType;e:{switch(Mo(e,t),e=t.pendingProps,s=r._init,r=s(r._payload),t.type=r,s=t.tag=qp(r),e=Yt(r,e),s){case 0:t=Cl(null,t,r,e,n);break e;case 1:t=vc(null,t,r,e,n);break e;case 11:t=fc(null,t,r,e,n);break e;case 14:t=pc(null,t,r,Yt(r.type,e),n);break e}throw Error(a(306,r,""))}return t;case 0:return r=t.type,s=t.pendingProps,s=t.elementType===r?s:Yt(r,s),Cl(e,t,r,s,n);case 1:return r=t.type,s=t.pendingProps,s=t.elementType===r?s:Yt(r,s),vc(e,t,r,s,n);case 3:e:{if(yc(t),e===null)throw Error(a(387));r=t.pendingProps,i=t.memoizedState,s=i.element,Du(e,t),No(t,r,null,n);var c=t.memoizedState;if(r=c.element,i.isDehydrated)if(i={element:r,isDehydrated:!1,cache:c.cache,pendingSuspenseBoundaries:c.pendingSuspenseBoundaries,transitions:c.transitions},t.updateQueue.baseState=i,t.memoizedState=i,t.flags&256){s=Wr(Error(a(423)),t),t=wc(e,t,r,n,s);break e}else if(r!==s){s=Wr(Error(a(424)),t),t=wc(e,t,r,n,s);break e}else for(Et=zn(t.stateNode.containerInfo.firstChild),Ct=t,Be=!0,qt=null,n=Lu(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(zr(),r===s){t=kn(e,t,n);break e}dt(e,t,r,n)}t=t.child}return t;case 5:return zu(t),e===null&&el(t),r=t.type,s=t.pendingProps,i=e!==null?e.memoizedProps:null,c=s.children,bi(r,s)?c=null:i!==null&&bi(r,i)&&(t.flags|=32),gc(e,t),dt(e,t,c,n),t.child;case 6:return e===null&&el(t),null;case 13:return _c(e,t,n);case 4:return al(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=Ur(t,null,r,n):dt(e,t,r,n),t.child;case 11:return r=t.type,s=t.pendingProps,s=t.elementType===r?s:Yt(r,s),fc(e,t,r,s,n);case 7:return dt(e,t,t.pendingProps,n),t.child;case 8:return dt(e,t,t.pendingProps.children,n),t.child;case 12:return dt(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,s=t.pendingProps,i=t.memoizedProps,c=s.value,Ae(xo,r._currentValue),r._currentValue=c,i!==null)if(Qt(i.value,c)){if(i.children===s.children&&!pt.current){t=kn(e,t,n);break e}}else for(i=t.child,i!==null&&(i.return=t);i!==null;){var h=i.dependencies;if(h!==null){c=i.child;for(var g=h.firstContext;g!==null;){if(g.context===r){if(i.tag===1){g=_n(-1,n&-n),g.tag=2;var N=i.updateQueue;if(N!==null){N=N.shared;var A=N.pending;A===null?g.next=g:(g.next=A.next,A.next=g),N.pending=g}}i.lanes|=n,g=i.alternate,g!==null&&(g.lanes|=n),ol(i.return,n,t),h.lanes|=n;break}g=g.next}}else if(i.tag===10)c=i.type===t.type?null:i.child;else if(i.tag===18){if(c=i.return,c===null)throw Error(a(341));c.lanes|=n,h=c.alternate,h!==null&&(h.lanes|=n),ol(c,n,t),c=i.sibling}else c=i.child;if(c!==null)c.return=i;else for(c=i;c!==null;){if(c===t){c=null;break}if(i=c.sibling,i!==null){i.return=c.return,c=i;break}c=c.return}i=c}dt(e,t,s.children,n),t=t.child}return t;case 9:return s=t.type,r=t.pendingProps.children,Br(t,n),s=At(s),r=r(s),t.flags|=1,dt(e,t,r,n),t.child;case 14:return r=t.type,s=Yt(r,t.pendingProps),s=Yt(r.type,s),pc(e,t,r,s,n);case 15:return hc(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,s=t.pendingProps,s=t.elementType===r?s:Yt(r,s),Mo(e,t),t.tag=1,ht(r)?(e=!0,vo(t)):e=!1,Br(t,n),oc(t,r,s),kl(t,r,s,n),El(null,t,r,!0,e,n);case 19:return Sc(e,t,n);case 22:return mc(e,t,n)}throw Error(a(156,t.tag))};function Kc(e,t){return ts(e,t)}function Qp(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Ut(e,t,n,r){return new Qp(e,t,n,r)}function bl(e){return e=e.prototype,!(!e||!e.isReactComponent)}function qp(e){if(typeof e=="function")return bl(e)?1:0;if(e!=null){if(e=e.$$typeof,e===me)return 11;if(e===ee)return 14}return 2}function Qn(e,t){var n=e.alternate;return n===null?(n=Ut(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Ko(e,t,n,r,s,i){var c=2;if(r=e,typeof e=="function")bl(e)&&(c=1);else if(typeof e=="string")c=5;else e:switch(e){case ke:return cr(n.children,s,i,t);case Se:c=8,s|=8;break;case Te:return e=Ut(12,n,t,s|2),e.elementType=Te,e.lanes=i,e;case Q:return e=Ut(13,n,t,s),e.elementType=Q,e.lanes=i,e;case q:return e=Ut(19,n,t,s),e.elementType=q,e.lanes=i,e;case ne:return Qo(n,s,i,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case Me:c=10;break e;case Ce:c=9;break e;case me:c=11;break e;case ee:c=14;break e;case ae:c=16,r=null;break e}throw Error(a(130,e==null?e:typeof e,""))}return t=Ut(c,n,t,s),t.elementType=e,t.type=r,t.lanes=i,t}function cr(e,t,n,r){return e=Ut(7,e,r,t),e.lanes=n,e}function Qo(e,t,n,r){return e=Ut(22,e,r,t),e.elementType=ne,e.lanes=n,e.stateNode={isHidden:!1},e}function Kl(e,t,n){return e=Ut(6,e,null,t),e.lanes=n,e}function Ql(e,t,n){return t=Ut(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Yp(e,t,n,r,s){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=_i(0),this.expirationTimes=_i(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=_i(0),this.identifierPrefix=r,this.onRecoverableError=s,this.mutableSourceEagerHydrationData=null}function ql(e,t,n,r,s,i,c,h,g){return e=new Yp(e,t,n,h,g),t===1?(t=1,i===!0&&(t|=8)):t=0,i=Ut(3,null,null,t),e.current=i,i.stateNode=e,i.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},ll(i),e}function Gp(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(o)}catch(l){console.error(l)}}return o(),ea.exports=lh(),ea.exports}var id;function uh(){if(id)return ei;id=1;var o=ah();return ei.createRoot=o.createRoot,ei.hydrateRoot=o.hydrateRoot,ei}var ch=uh();const dh=Fd(ch),fh="modulepreload",ph=function(o,l){return new URL(o,l).href},ld={},hh=function(l,a,d){let f=Promise.resolve();if(a&&a.length>0){let E=function(I){return Promise.all(I.map(j=>Promise.resolve(j).then(R=>({status:"fulfilled",value:R}),R=>({status:"rejected",reason:R}))))};const p=document.getElementsByTagName("link"),_=document.querySelector("meta[property=csp-nonce]"),w=_?.nonce||_?.getAttribute("nonce");f=E(a.map(I=>{if(I=ph(I,d),I in ld)return;ld[I]=!0;const j=I.endsWith(".css"),R=j?'[rel="stylesheet"]':"";if(d)for(let F=p.length-1;F>=0;F--){const $=p[F];if($.href===I&&(!j||$.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${I}"]${R}`))return;const B=document.createElement("link");if(B.rel=j?"stylesheet":fh,j||(B.as="script"),B.crossOrigin="",B.href=I,w&&B.setAttribute("nonce",w),document.head.appendChild(B),j)return new Promise((F,$)=>{B.addEventListener("load",F),B.addEventListener("error",()=>$(new Error(`Unable to preload CSS for ${I}`)))})}))}function m(p){const _=new Event("vite:preloadError",{cancelable:!0});if(_.payload=p,window.dispatchEvent(_),!_.defaultPrevented)throw p}return f.then(p=>{for(const _ of p||[])_.status==="rejected"&&m(_.reason);return l().catch(m)})},Gn=[{id:"zh-CN",shortName:"中",aliases:["zh","zh-Hans","zh-CN"],contentFallbacks:["en-US"]},{id:"zh-TW",shortName:"繁",aliases:["zh-TW","zh-Hant","zh-HK","zh-MO"],contentFallbacks:["zh-CN","en-US"]},{id:"en-US",shortName:"EN",aliases:["en","en-US"],contentFallbacks:["zh-CN"]}],mh=["en-US","zh-CN"],gh=Gn.flatMap(o=>o.aliases.map(l=>({locale:o,alias:l.toLowerCase()}))).sort((o,l)=>l.alias.length-o.alias.length),ci="en-US",ra={"zh-CN":{product:{name:"BitFun",remote:"BitFun Remote"},features:{remoteControl:"远程控制",codeAgent:"代码助手",deepReview:"严格审查",settings:"设置",workspace:"工作区"},modes:{agentic:"代理模式",assistant:"助手模式",expert:"专家模式",review:"评审模式"},agents:{code:"代码会话",cowork:"协作会话",claw:"Claw",default:"默认助手"},tools:{explore:"探索",read:"读取",write:"写入",shell:"命令行",search:"搜索",edit:"编辑",todo:"待办"},connectionMethods:{lan:"局域网",ngrok:"Ngrok",bitfunServer:"BitFun Server",customServer:"自定义服务器",botFeishu:"飞书机器人",botTelegram:"Telegram Bot",botWeixin:"微信机器人"},statuses:{loading:"加载中",running:"运行中",done:"已完成",failed:"失败",cancelled:"已取消"}},"zh-TW":{product:{name:"BitFun",remote:"BitFun Remote"},features:{remoteControl:"遠端控制",codeAgent:"程式碼助手",deepReview:"嚴格審查",settings:"設定",workspace:"工作區"},modes:{agentic:"代理模式",assistant:"助手模式",expert:"專家模式",review:"審查模式"},agents:{code:"程式碼會話",cowork:"協作會話",claw:"Claw",default:"預設助手"},tools:{explore:"探索",read:"讀取",write:"寫入",shell:"命令列",search:"搜尋",edit:"編輯",todo:"待辦"},connectionMethods:{lan:"區域網路",ngrok:"Ngrok",bitfunServer:"BitFun Server",customServer:"自訂伺服器",botFeishu:"飛書機器人",botTelegram:"Telegram Bot",botWeixin:"微信機器人"},statuses:{loading:"載入中",running:"執行中",done:"已完成",failed:"失敗",cancelled:"已取消"}},"en-US":{product:{name:"BitFun",remote:"BitFun Remote"},features:{remoteControl:"Remote Control",codeAgent:"Code Agent",deepReview:"Review: Strict",settings:"Settings",workspace:"Workspace"},modes:{agentic:"Agentic Mode",assistant:"Assistant Mode",expert:"Expert Mode",review:"Review Mode"},agents:{code:"Code Session",cowork:"Cowork Session",claw:"Claw",default:"Default Assistant"},tools:{explore:"Explore",read:"Read",write:"Write",shell:"Shell",search:"Search",edit:"Edit",todo:"Todo"},connectionMethods:{lan:"LAN",ngrok:"Ngrok",bitfunServer:"BitFun Server",customServer:"Custom Server",botFeishu:"Feishu Bot",botTelegram:"Telegram Bot",botWeixin:"WeChat Bot"},statuses:{loading:"Loading",running:"Running",done:"Done",failed:"Failed",cancelled:"Cancelled"}}};function vh(o){return Gn.some(l=>l.id===o)}function Ca(o){const l=o?.trim().toLowerCase();if(!l)return null;const a=Gn.find(d=>d.id.toLowerCase()===l);return a?a.id:gh.find(({alias:d})=>l===d||l.startsWith(`${d}-`))?.locale.id??null}function yh(o){const l=Gn.findIndex(a=>a.id===o);return Gn[(l+1)%Gn.length].id}function wh(o){return Gn.find(l=>l.id===o)?.shortName??o}function _h(o,l=!1){const a=Ca(o),d=a?Gn.find(m=>m.id===a):null,f=d?[...l?[d.id]:[],...d.contentFallbacks]:[...mh];return Array.from(new Set(f))}const kh={"en-US":{shared:ra["en-US"],common:{back:"Back",continue:"Continue",cancel:"Cancel",switch:"Switch",loading:"Loading...",switchLanguage:"Switch language",toggleTheme:"Toggle theme",attachImage:"Attach image",stop:"Stop",submit:"Submit",submitting:"Submitting...",submitted:"Submitted",other:"Other",customTextInput:"Custom text input",typeYourAnswer:"Type your answer...",itemCount:"{count} items",justNow:"just now",minutesAgo:"{count}m ago",hoursAgo:"{count}h ago",daysAgo:"{count}d ago"},pairing:{enterUserIdToContinue:"Enter your user ID to continue",enterAccountToContinue:"Enter your BitFun account to continue",connectingAndPairing:"Connecting and pairing...",pairedLoadingSessions:"Paired! Loading sessions...",connectionError:"Connection error",invalidQrCode:"Invalid QR code: missing room or public key",userIdRequired:"User ID is required",usernameRequired:"Username is required",passwordRequired:"Password is required",tooManyAttempts:"Too many failed attempts. Try again in {seconds}s.",pairingFailed:"Pairing failed",fieldsTooLong:"Username or password is too long.",requestTimedOut:"The relay did not respond in time. Check the network and try again.",qrExpired:"This QR code has expired or the desktop stopped sharing. Scan a new code.",rateLimited:"Too many pairing attempts. Wait one minute, then scan or try again.",relayUnavailable:"The relay or desktop is temporarily unavailable. Try again shortly.",credentialsRejected:"The username or password was not accepted.",fieldLabel:"User ID",usernameLabel:"Username",passwordLabel:"Password",placeholder:"Enter a user ID",usernamePlaceholder:"Enter your username",passwordPlaceholder:"Enter your password",note:"The first successful connection binds this URL to your user ID for the current remote session.",accountNote:"Use the same BitFun account currently logged in on the scanned desktop. Your password is not saved on this phone.",connecting:"Connecting...",retryIn:"Retry in {seconds}s",continue:"Continue"},sessions:{switchWorkspace:"Switch workspace",selectWorkspace:"Select Workspace",noWorkspaces:"No workspaces found",noWorkspaceSelected:"No workspace selected",assistant:"Assistant",switchAssistant:"Switch assistant",selectAssistant:"Select Assistant",launch:"Launch",startRemoteFlow:"Start a new remote flow",codeSessionDesc:"For coding anywhere, anytime.",coworkSessionDesc:"For assisting with everyday work.",clawSession:"Claw Session",clawSessionDesc:"Personal assistant for daily tasks.",recent:"Recent",sessionHistory:"Session history",loadingSessions:"Loading sessions...",noSessions:"No sessions yet. Create one to get started.",untitledSession:"Untitled Session",loadingMore:"Loading more...",remoteCodeSession:"Remote Code Session",remoteCoworkSession:"Remote Cowork Session",remoteClawSession:"Remote Claw Session",agentCode:"Code",agentCowork:"Cowork",agentDefault:"Default",searchSessions:"Search sessions...",renameSession:"Rename",deleteSession:"Delete",confirmDelete:"Delete session?",confirmDeleteDesc:"This action cannot be undone.",renameTitle:"Rename Session",sessionNamePlaceholder:"Session name",cancel:"Cancel",save:"Save",emptySearch:"No sessions match your search.",deleted:"Session deleted",deleteFailed:"Delete failed",renameFailed:"Rename failed",disconnect:"Disconnect",disconnectConfirm:"Disconnect from current desktop? You can re-pair later.",reconnecting:"Reconnecting...",repair:"Pair again",connectionUnpaired:"Not connected",connectionChecking:"Checking connection...",connectionConnected:"Connected",connectionUnreachable:"Connection lost",continueSession:"Continue where you left off"},workspace:{loadingInfo:"Loading workspace info...",currentWorkspace:"Current Workspace",unknownProject:"Unknown Project",noWorkspaceOpen:"No workspace is currently open on the desktop.",noWorkspaceHint:"Select a recent workspace below, or open one on the desktop first.",selectWorkspace:"Select Workspace",recentWorkspaces:"Recent Workspaces",noRecentWorkspaces:"No recent workspaces found. Please open a workspace on the desktop first.",failedToSetWorkspace:"Failed to set workspace",openingWorkspace:"Opening workspace..."},chat:{session:"Session",loadingOlderMessages:"Loading older messages...",showResponse:"Show response",hideResponse:"Hide response",analyzingImage:"Analyzing image with image understanding model...",inputPlaceholder:"How can I help you...",collapsedInputPlaceholder:"Ask BitFun...",collapsedStreamingPlaceholder:"Replying...",messageQueued:"Message queued; it will run after the current step",imageAnalyzingPlaceholder:"Analyzing image...",imageAttachmentFallback:"(see attached images)",modelSelection:"Select model",modelPrimary:"Primary Model",modelPrimaryDesc:"Uses the configured primary model",modelFast:"Fast Model",modelFastDesc:"Uses the configured fast model",reasoningSelection:"Select reasoning effort",reasoningAuto:"Auto",askQuestionCount:"{count} question{suffix}",waiting:"Waiting",thinking:"Thinking...",allTasksCompleted:"All tasks completed",task:"Task",toolCalls:"{count} tool call{suffix}",done:"{count} done",running:"{count} running",thoughtCharacters:"Thought {count} characters",textCharacters:"Text {count} characters",readToolsDone:"{summary}",readToolsRunning:"{summary} ({doneCount} done)",fileLoading:"Loading...",fileUnavailable:"File unavailable",fileDownloading:"Downloading...",fileDownloaded:"Downloaded",clickToDownload:"Click to download",scrollToBottom:"Scroll to bottom",copyMessage:"Copy text",resendMessage:"Resend",deleteMessage:"Delete",messageCopied:"Copied",messageDeleted:"Deleted",copyFailed:"Copy failed"},devices:{title:"Devices",noDelegatedIdentity:"The paired desktop is not logged into a BitFun account. Log in on the desktop to enable multi-device control, then retry.",loading:"Loading...",refresh:"Refresh",retry:"Retry",noDevices:"No devices found",online:"Online",offline:"Offline",lastSeen:"Last seen {time}",current:"Current",pairedDesktop:"Paired",switchFailed:"Failed to switch device",loadFailed:"Could not load devices. Check the connection and retry.",identityFailed:"Could not request account access from the paired desktop.",authorizationExpired:"Account authorization expired. Keep the paired desktop online and retry.",deviceUnavailable:"This device is offline or did not respond.",unknownDevice:"Unnamed device",controllingDevice:"Controlling {name}"},tools:{ls:"LS",glob:"Glob",grep:"Grep",delete:"Delete",task:"Task",web:"Web"}},"zh-CN":{shared:ra["zh-CN"],common:{back:"返回",continue:"继续",cancel:"取消",switch:"切换",loading:"加载中...",switchLanguage:"切换语言",toggleTheme:"切换主题",attachImage:"添加图片",stop:"停止",submit:"提交",submitting:"提交中...",submitted:"已提交",other:"其他",customTextInput:"自定义输入",typeYourAnswer:"请输入你的回答...",itemCount:"{count} 项",justNow:"刚刚",minutesAgo:"{count} 分钟前",hoursAgo:"{count} 小时前",daysAgo:"{count} 天前"},pairing:{enterUserIdToContinue:"请输入你的用户 ID 继续",enterAccountToContinue:"请输入你的 BitFun 账号继续",connectingAndPairing:"正在连接并配对...",pairedLoadingSessions:"配对成功,正在加载会话...",connectionError:"连接异常",invalidQrCode:"二维码无效:缺少 room 或 public key",userIdRequired:"用户 ID 不能为空",usernameRequired:"用户名不能为空",passwordRequired:"密码不能为空",tooManyAttempts:"失败次数过多,请在 {seconds} 秒后重试。",pairingFailed:"配对失败",fieldsTooLong:"用户名或密码过长。",requestTimedOut:"中继服务响应超时,请检查网络后重试。",qrExpired:"此二维码已过期,或桌面端已停止共享,请重新扫码。",rateLimited:"配对尝试过多,请等待一分钟后重新扫码或重试。",relayUnavailable:"中继服务或桌面端暂时不可用,请稍后重试。",credentialsRejected:"用户名或密码未通过验证。",fieldLabel:"用户 ID",usernameLabel:"用户名",passwordLabel:"密码",placeholder:"请输入用户 ID",usernamePlaceholder:"请输入用户名",passwordPlaceholder:"请输入密码",note:"首次成功连接后,本次远程会话会把该 URL 绑定到你的用户 ID。",accountNote:"请使用被扫码桌面端当前登录的 BitFun 账号。密码不会保存在本机。",connecting:"连接中...",retryIn:"{seconds} 秒后重试",continue:"继续"},sessions:{switchWorkspace:"切换工作区",selectWorkspace:"选择工作区",noWorkspaces:"暂无工作区",noWorkspaceSelected:"未选择工作区",assistant:"助理",switchAssistant:"切换助理",selectAssistant:"选择助理",launch:"启动",startRemoteFlow:"开始一个新的远程流程",codeSessionDesc:"随时随地进行编码。",coworkSessionDesc:"处理日常协作与办公任务。",clawSession:"助理会话",clawSessionDesc:"处理日常任务的个人助手。",recent:"最近",sessionHistory:"会话历史",loadingSessions:"正在加载会话...",noSessions:"还没有会话,先创建一个开始吧。",untitledSession:"未命名会话",loadingMore:"正在加载更多...",remoteCodeSession:"远程代码会话",remoteCoworkSession:"远程协作会话",remoteClawSession:"远程助理会话",agentCode:"Code",agentCowork:"Cowork",agentDefault:"默认",searchSessions:"搜索会话...",renameSession:"重命名",deleteSession:"删除",confirmDelete:"确定删除此会话?",confirmDeleteDesc:"此操作无法撤销。",renameTitle:"重命名会话",sessionNamePlaceholder:"会话名称",cancel:"取消",save:"保存",emptySearch:"没有匹配的会话。",deleted:"会话已删除",deleteFailed:"删除失败",renameFailed:"重命名失败",disconnect:"断开连接",disconnectConfirm:"断开当前桌面连接?之后可重新配对。",reconnecting:"正在重新连接...",repair:"重新配对",connectionUnpaired:"未连接",connectionChecking:"检测连接中...",connectionConnected:"已连接",connectionUnreachable:"连接断开",continueSession:"继续上次会话"},workspace:{loadingInfo:"正在加载工作区信息...",currentWorkspace:"当前工作区",unknownProject:"未知项目",noWorkspaceOpen:"桌面端当前没有打开工作区。",noWorkspaceHint:"你可以在下方选择最近工作区,或先在桌面端打开一个工作区。",selectWorkspace:"选择工作区",recentWorkspaces:"最近工作区",noRecentWorkspaces:"没有找到最近工作区,请先在桌面端打开一个工作区。",failedToSetWorkspace:"设置工作区失败",openingWorkspace:"正在打开工作区..."},chat:{session:"会话",loadingOlderMessages:"正在加载更早的消息...",showResponse:"Show response",hideResponse:"Hide response",analyzingImage:"正在使用图像理解模型分析图片...",inputPlaceholder:"有什么可以帮您...",collapsedInputPlaceholder:"发消息...",collapsedStreamingPlaceholder:"正在回复...",messageQueued:"已加入队列,将在当前步骤结束后处理",imageAnalyzingPlaceholder:"正在分析图片...",imageAttachmentFallback:"(见附带图片)",modelSelection:"选择模型",modelPrimary:"Primary 模型",modelPrimaryDesc:"使用已配置的主力模型",modelFast:"Fast 模型",modelFastDesc:"使用已配置的快速模型",reasoningSelection:"选择思考强度",reasoningAuto:"Auto",askQuestionCount:"{count} 个问题{suffix}",waiting:"等待中",thinking:"思考中...",allTasksCompleted:"所有任务已完成",task:"任务",toolCalls:"{count} 次工具调用{suffix}",done:"已完成 {count}",running:"运行中 {count}",thoughtCharacters:"思考 {count} 个字符",textCharacters:"文本 {count} 个字符",readToolsDone:"{summary}",readToolsRunning:"{summary}(已完成 {doneCount})",fileLoading:"加载中...",fileUnavailable:"文件不可用",fileDownloading:"下载中...",fileDownloaded:"已下载",clickToDownload:"点击下载",scrollToBottom:"滚动到底部",copyMessage:"复制文本",resendMessage:"重新发送",deleteMessage:"删除",messageCopied:"已复制",messageDeleted:"已删除",copyFailed:"复制失败"},devices:{title:"设备",noDelegatedIdentity:"所连接的桌面端未登录 BitFun 账号。请在桌面端登录以启用多设备控制,然后重试。",loading:"加载中...",refresh:"刷新",retry:"重试",noDevices:"未找到设备",online:"在线",offline:"离线",lastSeen:"上次在线:{time}",current:"当前",pairedDesktop:"已配对",switchFailed:"切换设备失败",loadFailed:"无法加载设备,请检查连接后重试。",identityFailed:"无法从已配对桌面端获取账号访问权限。",authorizationExpired:"账号授权已过期,请保持已配对桌面端在线并重试。",deviceUnavailable:"该设备离线或未响应。",unknownDevice:"未命名设备",controllingDevice:"正在控制 {name}"},tools:{ls:"列表",glob:"Glob",grep:"Grep",delete:"删除",task:"任务",web:"网络"}},"zh-TW":{shared:ra["zh-TW"],common:{back:"返回",continue:"繼續",cancel:"取消",switch:"切換",loading:"加載中...",switchLanguage:"切換語言",toggleTheme:"切換主題",attachImage:"添加圖片",stop:"停止",submit:"提交",submitting:"提交中...",submitted:"已提交",other:"其他",customTextInput:"自定義輸入",typeYourAnswer:"請輸入你的回答...",itemCount:"{count} 項",justNow:"剛剛",minutesAgo:"{count} 分鐘前",hoursAgo:"{count} 小時前",daysAgo:"{count} 天前"},pairing:{enterUserIdToContinue:"請輸入你的用戶 ID 繼續",enterAccountToContinue:"請輸入你的 BitFun 帳號繼續",connectingAndPairing:"正在連接並配對...",pairedLoadingSessions:"配對成功,正在加載會話...",connectionError:"連接異常",invalidQrCode:"二維碼無效:缺少 room 或 public key",userIdRequired:"用戶 ID 不能為空",usernameRequired:"用戶名不能為空",passwordRequired:"密碼不能為空",tooManyAttempts:"失敗次數過多,請在 {seconds} 秒後重試。",pairingFailed:"配對失敗",fieldsTooLong:"帳號或密碼過長。",requestTimedOut:"中繼服務回應逾時,請檢查網路後重試。",qrExpired:"此 QR Code 已過期,或桌面端已停止分享,請重新掃描。",rateLimited:"配對嘗試過多,請等待一分鐘後重新掃描或重試。",relayUnavailable:"中繼服務或桌面端暫時無法使用,請稍後重試。",credentialsRejected:"帳號或密碼未通過驗證。",fieldLabel:"用戶 ID",usernameLabel:"用戶名",passwordLabel:"密碼",placeholder:"請輸入用戶 ID",usernamePlaceholder:"請輸入用戶名",passwordPlaceholder:"請輸入密碼",note:"首次成功連接後,本次遠程會話會把該 URL 綁定到你的用戶 ID。",accountNote:"請使用被掃碼桌面端目前登入的 BitFun 帳號。密碼不會保存在本機。",connecting:"連接中...",retryIn:"{seconds} 秒後重試",continue:"繼續"},sessions:{switchWorkspace:"切換工作區",selectWorkspace:"選擇工作區",noWorkspaces:"暫無工作區",noWorkspaceSelected:"未選擇工作區",assistant:"助理",switchAssistant:"切換助理",selectAssistant:"選擇助理",launch:"啟動",startRemoteFlow:"開始一個新的遠程流程",codeSessionDesc:"隨時隨地進行編碼。",coworkSessionDesc:"處理日常協作與辦公任務。",clawSession:"助理會話",clawSessionDesc:"處理日常任務的個人助手。",recent:"最近",sessionHistory:"會話歷史",loadingSessions:"正在加載會話...",noSessions:"還沒有會話,先創建一個開始吧。",untitledSession:"未命名會話",loadingMore:"正在加載更多...",remoteCodeSession:"遠程代碼會話",remoteCoworkSession:"遠程協作會話",remoteClawSession:"遠程助理會話",agentCode:"Code",agentCowork:"Cowork",agentDefault:"默認",searchSessions:"搜尋會話...",renameSession:"重新命名",deleteSession:"刪除",confirmDelete:"確定刪除此會話?",confirmDeleteDesc:"此操作無法復原。",renameTitle:"重新命名會話",sessionNamePlaceholder:"會話名稱",cancel:"取消",save:"儲存",emptySearch:"沒有匹配的會話。",deleted:"會話已刪除",deleteFailed:"刪除失敗",renameFailed:"重新命名失敗",disconnect:"斷開連接",disconnectConfirm:"斷開當前桌面連接?之後可重新配對。",reconnecting:"正在重新連接...",repair:"重新配對",connectionUnpaired:"未連接",connectionChecking:"檢測連接中...",connectionConnected:"已連接",connectionUnreachable:"連接斷開",continueSession:"繼續上次會話"},workspace:{loadingInfo:"正在加載工作區信息...",currentWorkspace:"當前工作區",unknownProject:"未知項目",noWorkspaceOpen:"桌面端當前沒有打開工作區。",noWorkspaceHint:"你可以在下方選擇最近工作區,或先在桌面端打開一個工作區。",selectWorkspace:"選擇工作區",recentWorkspaces:"最近工作區",noRecentWorkspaces:"沒有找到最近工作區,請先在桌面端打開一個工作區。",failedToSetWorkspace:"設置工作區失敗",openingWorkspace:"正在打開工作區..."},chat:{session:"會話",loadingOlderMessages:"正在加載更早的消息...",showResponse:"Show response",hideResponse:"Hide response",analyzingImage:"正在使用圖像理解模型分析圖片...",inputPlaceholder:"有什麼可以幫您...",collapsedInputPlaceholder:"發消息...",collapsedStreamingPlaceholder:"正在回覆...",messageQueued:"已加入隊列,將在當前步驟結束後處理",imageAnalyzingPlaceholder:"正在分析圖片...",imageAttachmentFallback:"(見附帶圖片)",modelSelection:"選擇模型",modelPrimary:"Primary 模型",modelPrimaryDesc:"使用已設定的主力模型",modelFast:"Fast 模型",modelFastDesc:"使用已設定的快速模型",reasoningSelection:"選擇思考強度",reasoningAuto:"Auto",askQuestionCount:"{count} 個問題{suffix}",waiting:"等待中",thinking:"思考中...",allTasksCompleted:"所有任務已完成",task:"任務",toolCalls:"{count} 次工具調用{suffix}",done:"已完成 {count}",running:"運行中 {count}",thoughtCharacters:"思考 {count} 個字符",textCharacters:"文本 {count} 個字符",readToolsDone:"{summary}",readToolsRunning:"{summary}(已完成 {doneCount})",fileLoading:"加載中...",fileUnavailable:"檔案不可用",fileDownloading:"下載中...",fileDownloaded:"已下載",clickToDownload:"點擊下載",scrollToBottom:"捲動到底部",copyMessage:"複製文本",resendMessage:"重新傳送",deleteMessage:"刪除",messageCopied:"已複製",messageDeleted:"已刪除",copyFailed:"複製失敗"},devices:{title:"設備",noDelegatedIdentity:"所連接的桌面端未登入 BitFun 帳號。請在桌面端登入以啟用多設備控制,然後重試。",loading:"加載中...",refresh:"重新整理",retry:"重試",noDevices:"未找到設備",online:"在線",offline:"離線",lastSeen:"上次在線:{time}",current:"目前",pairedDesktop:"已配對",switchFailed:"切換設備失敗",loadFailed:"無法載入裝置,請檢查連線後重試。",identityFailed:"無法從已配對桌面端取得帳號存取權限。",authorizationExpired:"帳號授權已過期,請保持已配對桌面端在線並重試。",deviceUnavailable:"該裝置離線或未回應。",unknownDevice:"未命名裝置",controllingDevice:"正在控制 {name}"},tools:{ls:"列表",glob:"Glob",grep:"Grep",delete:"刪除",task:"任務",web:"網絡"}}},Wd="bitfun-mobile-language";function Sh(o,l){const a=l.split(".");let d=o;for(const f of a){if(!d||typeof d!="object"||!(f in d))return null;d=d[f]}return typeof d=="string"?d:null}function xh(o,l){return l?o.replace(/\{(\w+)\}/g,(a,d)=>{const f=l[d];return f==null?"":String(f)}):o}function Ch(o,l,a){const d=_h(o,!0).map(f=>Sh(kh[f],l)).find(f=>f!==null)??l;return xh(d,a)}function Eh(){try{const l=localStorage.getItem(Wd);if(vh(l))return l}catch{}const o=Nh();return o||(Ca(navigator.language)??ci)}function Nh(){const o=[];try{o.push(new URLSearchParams(window.location.search).get("lang"))}catch{}const l=window.location.hash||"",a=l.indexOf("?");if(a>=0)try{const d=l.slice(a+1);o.push(new URLSearchParams(d).get("lang"))}catch{}for(const d of o){const f=Ca(d);if(f)return f}return null}const $d=C.createContext({language:ci,setLanguage:()=>{},toggleLanguage:()=>{},t:o=>o,formatDate:(o,l)=>new Intl.DateTimeFormat(ci,l).format(o),formatRelativeTime:o=>Hd(ci,o)});function Hd(o,l){const a=l instanceof Date?l.getTime():l,d=(a-Date.now())/1e3,f=Math.abs(d),m=new Intl.RelativeTimeFormat(o,{numeric:"auto"});return f<60?m.format(Math.round(d),"second"):f<3600?m.format(Math.round(d/60),"minute"):f<86400?m.format(Math.round(d/3600),"hour"):f<2592e3?m.format(Math.round(d/86400),"day"):new Intl.DateTimeFormat(o,{dateStyle:"medium",timeStyle:"short"}).format(a)}const jh=({children:o})=>{const[l,a]=C.useState(Eh);C.useLayoutEffect(()=>{document.documentElement.lang=l;try{localStorage.setItem(Wd,l)}catch{}},[l]);const d=C.useCallback(p=>{a(p)},[]),f=C.useCallback(()=>{a(yh)},[]),m=C.useMemo(()=>({language:l,setLanguage:d,toggleLanguage:f,t:(p,_)=>Ch(l,p,_),formatDate:(p,_)=>new Intl.DateTimeFormat(l,_).format(p),formatRelativeTime:p=>Hd(l,p)}),[l,d,f]);return u.jsx($d.Provider,{value:m,children:o})};function Zr(){return C.useContext($d)}const Ea=({className:o})=>{const{language:l,toggleLanguage:a,t:d}=Zr(),f=["mobile-lang-btn",o].filter(Boolean).join(" ");return u.jsx("button",{type:"button",className:f,onClick:a,"aria-label":d("common.switchLanguage"),title:d("common.switchLanguage"),children:wh(l)})};function Th(o){return o instanceof Uint8Array||ArrayBuffer.isView(o)&&o.constructor.name==="Uint8Array"}function Vd(o,l=""){if(!Number.isSafeInteger(o)||o<0){const a=l&&`"${l}" `;throw new Error(`${a}expected integer >= 0, got ${o}`)}}function Ws(o,l,a=""){const d=Th(o),f=o?.length,m=l!==void 0;if(!d||m&&f!==l){const p=a&&`"${a}" `,_=m?` of length ${l}`:"",w=d?`length=${f}`:`type=${typeof o}`;throw new Error(p+"expected Uint8Array"+_+", got "+w)}return o}const bd=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",Ih=Array.from({length:256},(o,l)=>l.toString(16).padStart(2,"0"));function Rh(o){if(Ws(o),bd)return o.toHex();let l="";for(let a=0;a=xn._0&&o<=xn._9)return o-xn._0;if(o>=xn.A&&o<=xn.F)return o-(xn.A-10);if(o>=xn.a&&o<=xn.f)return o-(xn.a-10)}function Lh(o){if(typeof o!="string")throw new Error("hex string expected, got "+typeof o);if(bd)return Uint8Array.fromHex(o);const l=o.length,a=l/2;if(l%2)throw new Error("hex string expected, got unpadded hex of length "+l);const d=new Uint8Array(a);for(let f=0,m=0;ftypeof o=="bigint"&&Kd<=o;function Uh(o,l,a){return di(o)&&di(l)&&di(a)&&l<=o&&oObject.entries(m).forEach(([_,w])=>d(_,w,p));f(l,!1),f(a,!0)}const Qd=BigInt(0);function qd(o,l){const a=o%l;return a>=Qd?a:l+a}function Jt(o,l,a){let d=o;for(;l-- >Qd;)d*=d,d%=a;return d}function Bh(o,l){return function(d){const f=o(d);return{secretKey:f,publicKey:l(f)}}}const zs=BigInt(0),Kr=BigInt(1),ti=BigInt(2);function Fh(o){return Oh(o,{adjustScalarBytes:"function",powPminus2:"function"}),Object.freeze({...o})}function Wh(o){const l=Fh(o),{P:a,type:d,adjustScalarBytes:f,powPminus2:m,randomBytes:p}=l,_=d==="x25519";if(!_&&d!=="x448")throw new Error("invalid type");const w=p||Ph,E=_?255:448,I=_?32:56,j=BigInt(_?9:5),R=BigInt(_?121665:39081),B=_?ti**BigInt(254):ti**BigInt(447),F=_?BigInt(8)*ti**BigInt(251)-Kr:BigInt(4)*ti**BigInt(445)-Kr,$=B+F+Kr,W=q=>qd(q,a),de=b(j);function b(q){return zh(W(q),I)}function K(q){const ee=va(Ws(q,I,"uCoordinate"));return _&&(ee[31]&=127),W(ud(ee))}function se(q){return ud(f(va(Ws(q,I,"scalar"))))}function _e(q,ee){const ae=Me(K(ee),se(q));if(ae===zs)throw new Error("invalid private or public key received");return b(ae)}function fe(q){return _e(q,de)}const ke=fe,Se=_e;function Te(q,ee,ae){const ne=W(q*(ee-ae));return ee=W(ee-ne),ae=W(ae+ne),{x_2:ee,x_3:ae}}function Me(q,ee){cd("u",q,zs,a),cd("scalar",ee,B,$);const ae=ee,ne=q;let D=Kr,O=zs,L=q,v=Kr,T=zs;for(let ue=BigInt(E-1);ue>=zs;ue--){const pe=ae>>ue&Kr;T^=pe,{x_2:D,x_3:L}=Te(T,D,L),{x_2:O,x_3:v}=Te(T,O,v),T=pe;const ce=D+O,te=W(ce*ce),ge=D-O,ye=W(ge*ge),De=te-ye,ct=L+v,kt=L-v,ze=W(kt*ce),$e=W(ct*ge),Ie=ze+$e,He=ze-$e;L=W(Ie*Ie),v=W(ne*W(He*He)),D=W(te*ye),O=W(De*(te+W(R*De)))}({x_2:D,x_3:L}=Te(T,D,L)),{x_2:O,x_3:v}=Te(T,O,v);const re=m(O);return W(D*re)}const Ce={secretKey:I,publicKey:I,seed:I},me=(q=w(I))=>(Ws(q,Ce.seed,"seed"),q),Q={randomSecretKey:me};return Object.freeze({keygen:Bh(me,ke),getSharedSecret:Se,getPublicKey:ke,scalarMult:_e,scalarMultBase:fe,utils:Q,GuBytes:de.slice(),lengths:Ce})}const $h=BigInt(1),dd=BigInt(2),Hh=BigInt(3),Vh=BigInt(5);BigInt(8);const Yd=BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed");function bh(o){const l=BigInt(10),a=BigInt(20),d=BigInt(40),f=BigInt(80),m=Yd,_=o*o%m*o%m,w=Jt(_,dd,m)*_%m,E=Jt(w,$h,m)*o%m,I=Jt(E,Vh,m)*E%m,j=Jt(I,l,m)*I%m,R=Jt(j,a,m)*j%m,B=Jt(R,d,m)*R%m,F=Jt(B,f,m)*B%m,$=Jt(F,f,m)*B%m,W=Jt($,l,m)*I%m;return{pow_p_5_8:Jt(W,dd,m)*o%m,b2:_}}function Kh(o){return o[0]&=248,o[31]&=127,o[31]|=64,o}const Gd=(()=>{const o=Yd;return Wh({P:o,type:"x25519",powPminus2:l=>{const{pow_p_5_8:a,b2:d}=bh(l);return qd(Jt(a,Hh,o)*d,o)},adjustScalarBytes:Kh})})();function Qh(o){return o instanceof Uint8Array||ArrayBuffer.isView(o)&&o.constructor.name==="Uint8Array"}function _t(o,l,a=""){const d=Qh(o),f=o?.length,m=l!==void 0;if(!d||m&&f!==l){const p=a&&`"${a}" `,_=m?` of length ${l}`:"",w=d?`length=${f}`:`type=${typeof o}`;throw new Error(p+"expected Uint8Array"+_+", got "+w)}return o}function pi(o,l=!0){if(o.destroyed)throw new Error("Hash instance has been destroyed");if(l&&o.finished)throw new Error("Hash#digest() has already been called")}function Zd(o,l){_t(o,void 0,"output");const a=l.outputLen;if(o.length{function a(d,...f){if(_t(d,void 0,"key"),!Yh)throw new Error("Non little-endian hardware is not yet supported");if(o.nonceLength!==void 0){const I=f[0];_t(I,o.varSizeNonce?void 0:o.nonceLength,"nonce")}const m=o.tagLength;m&&f[1]!==void 0&&_t(f[1],void 0,"AAD");const p=l(d,...f),_=(I,j)=>{if(j!==void 0){if(I!==2)throw new Error("cipher output not supported");_t(j,void 0,"output")}};let w=!1;return{encrypt(I,j){if(w)throw new Error("cannot encrypt() twice with same key + nonce");return w=!0,_t(I),_(p.encrypt.length,j),p.encrypt(I,j)},decrypt(I,j){if(_t(I),m&&I.length{const f=d&1;return{s3:a<<31|d>>>1,s2:l<<31|a>>>1,s1:o<<31|l>>>1,s0:o>>>1^em<<24&-(f&1)}},Ft=o=>(o>>>0&255)<<24|(o>>>8&255)<<16|(o>>>16&255)<<8|o>>>24&255|0;function nm(o){o.reverse();const l=o[15]&1;let a=0;for(let d=0;d>>1|a,a=(f&1)<<7}return o[0]^=-l&225,o}const rm=o=>o>64*1024?8:o>1024?4:2;class Xd{blockLen=Cn;outputLen=Cn;s0=0;s1=0;s2=0;s3=0;finished=!1;t;W;windowSize;constructor(l,a){_t(l,16,"key"),l=fr(l);const d=gi(l);let f=d.getUint32(0,!1),m=d.getUint32(4,!1),p=d.getUint32(8,!1),_=d.getUint32(12,!1);const w=[];for(let F=0;F<128;F++)w.push({s0:Ft(f),s1:Ft(m),s2:Ft(p),s3:Ft(_)}),{s0:f,s1:m,s2:p,s3:_}=tm(f,m,p,_);const E=rm(a||1024);if(![1,2,4,8].includes(E))throw new Error("ghash: invalid window size, expected 2, 4 or 8");this.W=E;const j=128/E,R=this.windowSize=2**E,B=[];for(let F=0;F>>E-se-1&1))continue;const{s0:fe,s1:ke,s2:Se,s3:Te}=w[E*F+se];W^=fe,de^=ke,b^=Se,K^=Te}B.push({s0:W,s1:de,s2:b,s3:K})}this.t=B}_updateBlock(l,a,d,f){l^=this.s0,a^=this.s1,d^=this.s2,f^=this.s3;const{W:m,t:p,windowSize:_}=this;let w=0,E=0,I=0,j=0;const R=(1<>>8*$&255;for(let de=8/m-1;de>=0;de--){const b=W>>>m*de&R,{s0:K,s1:se,s2:_e,s3:fe}=p[B*_+b];w^=K,E^=se,I^=_e,j^=fe,B+=1}}this.s0=w,this.s1=E,this.s2=I,this.s3=j}update(l){pi(this),_t(l),l=fr(l);const a=En(l),d=Math.floor(l.length/Cn),f=l.length%Cn;for(let m=0;mo(f,d.length).update(d).digest(),a=o(new Uint8Array(16),0);return l.outputLen=a.outputLen,l.blockLen=a.blockLen,l.create=(d,f)=>o(d,f),l}const fd=Jd((o,l)=>new Xd(o,l));Jd((o,l)=>new sm(o,l));const ya=16,om=4,ni=new Uint8Array(ya),im=283;function lm(o){if(![16,24,32].includes(o.length))throw new Error('"aes key" expected Uint8Array of length 16/24/32, got length='+o.length)}function ja(o){return o<<1^im&-(o>>7)}function pd(o,l){let a=0;for(;l>0;l>>=1)a^=o&-(l&1),o=ja(o);return a}const am=(()=>{const o=new Uint8Array(256);for(let a=0,d=1;a<256;a++,d^=ja(d))o[a]=d;const l=new Uint8Array(256);l[0]=99;for(let a=0;a<255;a++){let d=o[255-a];d|=d<<8,l[o[a]]=(d^d>>4^d>>5^d>>6^d>>7^99)&255}return Nn(o),l})(),um=o=>o<<24|o>>>8,sa=o=>o<<8|o>>>24;function cm(o,l){if(o.length!==256)throw new Error("Wrong sbox length");const a=new Uint32Array(256).map((E,I)=>l(o[I])),d=a.map(sa),f=d.map(sa),m=f.map(sa),p=new Uint32Array(256*256),_=new Uint32Array(256*256),w=new Uint16Array(256*256);for(let E=0;E<256;E++)for(let I=0;I<256;I++){const j=E*256+I;p[j]=a[E]^d[I],_[j]=f[E]^m[I],w[j]=o[E]<<8|o[I]}return{sbox:o,sbox2:w,T0:a,T1:d,T2:f,T3:m,T01:p,T23:_}}const ef=cm(am,o=>pd(o,3)<<24|o<<16|o<<8|pd(o,2)),dm=(()=>{const o=new Uint8Array(16);for(let l=0,a=1;l<16;l++,a=ja(a))o[l]=a;return o})();function fm(o){_t(o);const l=o.length;lm(o);const{sbox2:a}=ef,d=[];hi(o)||d.push(o=fr(o));const f=En(o),m=f.length,p=w=>Fs(a,w,w,w,w),_=new Uint32Array(l+28);_.set(f);for(let w=m;w<_.length;w++){let E=_[w-1];w%m===0?E=p(um(E))^dm[w/m-1]:m>6&&w%m===4&&(E=p(E)),_[w]=_[w-m]^E}return Nn(...d),_}function ri(o,l,a,d,f,m){return o[a<<8&65280|d>>>8&255]^l[f>>>8&65280|m>>>24&255]}function Fs(o,l,a,d,f){return o[l&255|a&65280]|o[d>>>16&255|f>>>16&65280]<<16}function hd(o,l,a,d,f){const{sbox2:m,T01:p,T23:_}=ef;let w=0;l^=o[w++],a^=o[w++],d^=o[w++],f^=o[w++];const E=o.length/4-2;for(let F=0;F>>0,_.setUint32(I,R,l),{s0:B,s1:F,s2:$,s3:W}=hd(o,p[0],p[1],p[2],p[3]);const de=ya*Math.floor(w.length/om);if(del+=String.fromCharCode(a)),btoa(l)}function mi(o){const l=atob(o),a=new Uint8Array(l.length);for(let d=0;df.abort(),d);try{const p=await fetch(l,{...a,signal:f.signal}),_=await p.arrayBuffer();return new Response(_,{status:p.status,statusText:p.statusText,headers:p.headers})}catch(p){throw p?.name==="AbortError"?new Error("Request timed out"):p}finally{window.clearTimeout(m)}}async fetchWithRetry(l,a,d){let f=null;const m=Date.now()+ym;for(let p=1;p<=ia;p+=1){try{const w=m-Date.now();if(w<=0)throw f??new Error("Relay request retry budget exceeded");const E=await this.fetchWithTimeout(l,a,Math.min(d,w));if(wm.has(E.status)&&p=m)throw f??new Error("Relay request retry budget exceeded");await new Promise(w=>window.setTimeout(w,_))}throw f}async pair(l,a){this.keyPair=await mm();const d=mi(l);this.sharedKey=await gm(this.keyPair,d);const f=a.mobileInstallId,m=this.getMobileDeviceName(),p=a.userId.trim(),_=a.mobileInstallId.trim(),w=a.password&&a.password.length>0?a.password:void 0,E=await this.fetchWithRetry(`${this.relayUrl}/api/rooms/${encodeURIComponent(this.roomId)}/pair`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({public_key:wa(this.keyPair.publicKey),device_id:f,device_name:m})},35e3);if(!E.ok)throw new Error(`Pairing failed: HTTP ${E.status}`);const I=await E.json(),j=await oi(this.sharedKey,I.encrypted_data,I.nonce),B={challenge_echo:JSON.parse(j).challenge,device_id:f,device_name:m,mobile_install_id:_,user_id:p};w&&(B.password=w);const{data:F,nonce:$}=await oa(this.sharedKey,JSON.stringify(B)),W=await this.fetchWithTimeout(`${this.relayUrl}/api/rooms/${encodeURIComponent(this.roomId)}/command`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({encrypted_data:F,nonce:$})},65e3);if(!W.ok)throw new Error(`Pairing verification failed: HTTP ${W.status}`);const de=await W.json(),b=await oi(this.sharedKey,de.encrypted_data,de.nonce),K=JSON.parse(b);if(K?.resp==="error")throw new Error(K?.message||"Pairing rejected");return K}async requestDelegatedIdentity(l){if(!l?.force&&this.hasDelegatedIdentity)return!0;const a=++this.delegatedIdentityRequestEpoch;l?.force&&(this.delegatedIdentityRefreshOwner=a);try{const d=await this.sendCommand({cmd:"get_delegated_identity"},{retryable:!0});if(this.delegatedIdentityRequestEpoch!==a)return!1;if(d?.resp==="delegate_identity"&&d.token&&d.master_key){const f=d.device_id??null,m={token:d.token,masterKey:mi(d.master_key),userId:d.user_id??null,homeDeviceId:f,generation:++this.delegatedIdentityGenerationValue};this.delegatedIdentity=m;const p={userId:m.userId,masterKey:m.masterKey.slice(),homeDeviceId:m.homeDeviceId},_=km(this.delegatedAccountIdentity,p),w=this.delegatedAccountIdentity!==null;_&&(this.delegatedAccountEpochValue+=1),this.delegatedAccountIdentity=p;const E=this.homeDeviceId,I=this.pairedDeviceIdValue===null||this.pairedDeviceIdValue===E;return this.homeDeviceId=f,_?this.setPairedDeviceId(f):I&&(this.pairedDeviceIdValue=f),_&&this.emitDelegatedAccountOwnerChange({kind:w?"replacement":"initial",epoch:this.delegatedAccountEpochValue,userId:m.userId,homeDeviceId:f}),!0}return this.commitDelegatedAccountUnavailable(),!1}finally{this.delegatedIdentityRefreshOwner===a&&(this.delegatedIdentityRefreshOwner=null)}}clearDelegatedIdentity(){this.delegatedIdentityRequestEpoch+=1,this.delegatedIdentityRefreshOwner=null,this.delegatedIdentity&&(this.delegatedIdentityGenerationValue+=1),this.delegatedIdentity=null}resetConnectionIdentity(){const l=this.controlTargetEpochValue;this.clearDelegatedIdentity(),this.commitDelegatedAccountUnavailable(),this.controlTargetEpochValue===l&&this.setPairedDeviceId(null)}onDelegatedAccountOwnerChange(l,a){return this.delegatedAccountOwnerListeners.add(l),a?.emitCurrent&&this.delegatedAccountIdentity&&l({kind:"initial",epoch:this.delegatedAccountEpochValue,userId:this.delegatedAccountIdentity.userId,homeDeviceId:this.delegatedAccountIdentity.homeDeviceId}),()=>this.delegatedAccountOwnerListeners.delete(l)}emitDelegatedAccountOwnerChange(l){for(const a of this.delegatedAccountOwnerListeners)a(l)}commitDelegatedAccountUnavailable(){if(this.delegatedIdentity&&(this.delegatedIdentityGenerationValue+=1),this.delegatedIdentity=null,!this.delegatedAccountIdentity){const l=this.pairedDeviceIdValue===null||this.pairedDeviceIdValue===this.homeDeviceId;this.homeDeviceId=null,l?this.pairedDeviceIdValue=null:this.setPairedDeviceId(null);return}this.delegatedAccountEpochValue+=1,this.delegatedAccountIdentity=null,this.homeDeviceId=null,this.setPairedDeviceId(null),this.emitDelegatedAccountOwnerChange({kind:"unavailable",epoch:this.delegatedAccountEpochValue,userId:null,homeDeviceId:null})}async sendCommand(l,a={}){if(!this.sharedKey)throw new Error("Not paired");const d=JSON.stringify(l),{data:f,nonce:m}=await oa(this.sharedKey,d),p=JSON.stringify({encrypted_data:f,nonce:m}),_=await(a.retryable?this.fetchWithRetry:this.fetchWithTimeout).call(this,`${this.relayUrl}/api/rooms/${encodeURIComponent(this.roomId)}/command`,{method:"POST",headers:{"Content-Type":"application/json"},body:p},a.retryable?2e4:65e3);if(!_.ok)throw new Error(`Command failed: HTTP ${_.status}`);const w=await _.json(),E=await oi(this.sharedKey,w.encrypted_data,w.nonce);return JSON.parse(E)}get isPaired(){return this.sharedKey!==null}get hasDelegatedIdentity(){return this.delegatedIdentity!==null}get pairedDeviceId(){return this.pairedDeviceIdValue}setPairedDeviceId(l){this.pairedDeviceIdValue=l,this.controlTargetEpochValue+=1;const a=this.getControlTargetSnapshot();for(const d of this.controlTargetListeners)d(a)}get controlTargetEpoch(){return this.controlTargetEpochValue}getControlTargetSnapshot(){return{deviceId:this.pairedDeviceIdValue,homeDeviceId:this.homeDeviceId,epoch:this.controlTargetEpochValue}}isControlTargetCurrent(l){return l.epoch===this.controlTargetEpochValue}onControlTargetChange(l){return this.controlTargetListeners.add(l),()=>this.controlTargetListeners.delete(l)}get delegatedIdentityGeneration(){return this.delegatedIdentityGenerationValue}get delegatedAccountEpoch(){return this.delegatedAccountEpochValue}get delegatedUserId(){return this.delegatedIdentity?.userId??null}requireDelegatedIdentity(){const l=this.delegatedIdentity;if(!l)throw new Error("No delegated identity");return l}isDelegatedIdentityCurrent(l){return this.delegatedIdentity?.generation===l.generation&&this.delegatedIdentityGenerationValue===l.generation&&this.delegatedIdentityRefreshOwner===null}ensureDelegatedIdentityCurrent(l,a){if(!this.isDelegatedIdentityCurrent(l))throw this.delegatedIdentityChangeError(a)}delegatedIdentityChangeError(l){return this.delegatedAccountEpochValue===l?new Ta:new md}async refreshDelegatedIdentityAfterUnauthorized(l){if(!this.isDelegatedIdentityCurrent(l))return this.hasDelegatedIdentity;try{return await this.requestDelegatedIdentity({force:!0})}catch{return!1}}async listDevices(){return this.withDelegatedAuthRetry(async l=>{const a=await this.fetchWithRetry(`${this.relayUrl}/api/devices`,{headers:{Authorization:`Bearer ${l.token}`}},2e4);if(!a.ok){const d=new Error(`List devices failed: HTTP ${a.status}`);throw d.status=a.status,d}return a.json()},{allowAccountReplacementRetry:!0})}async sendDeviceRpc(l,a,d={}){return this.withDelegatedAuthRetry(async f=>{const m=JSON.stringify(a),{data:p,nonce:_}=await oa(f.masterKey,m),w=await(d.retryable?this.fetchWithRetry:this.fetchWithTimeout).call(this,`${this.relayUrl}/api/devices/${encodeURIComponent(l)}/rpc`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${f.token}`},body:JSON.stringify({encrypted_data:p,nonce:_})},d.retryable?2e4:13e4);if(!w.ok){const R=new Error(`Device RPC failed: HTTP ${w.status}`);throw R.status=w.status,R}const E=await w.json(),I=await oi(f.masterKey,E.encrypted_data,E.nonce),j=JSON.parse(I);if(j?.resp==="error")throw new Error(j.message||"Remote error");return j},{allowAccountReplacementRetry:!1})}async withDelegatedAuthRetry(l,a){let d=this.requireDelegatedIdentity();const f=this.delegatedAccountEpochValue;this.ensureDelegatedIdentityCurrent(d,f);try{const m=await l(d);return this.ensureDelegatedIdentityCurrent(d,f),m}catch(m){if(!this.isDelegatedIdentityCurrent(d))throw this.delegatedIdentityChangeError(f);const p=m?.status,_=String(m?.message||m);if(!(p===401||_.includes("HTTP 401")||_.includes("Unauthorized")))throw m;if(!await this.refreshDelegatedIdentityAfterUnauthorized(d))throw new Error("No delegated identity");if(!a.allowAccountReplacementRetry&&this.delegatedAccountEpochValue!==f)throw new md;d=this.requireDelegatedIdentity();const I=await l(d);return this.ensureDelegatedIdentityCurrent(d,this.delegatedAccountEpochValue),I}}getMobileDeviceName(){const l=navigator.userAgent;return/iPhone/i.test(l)?"iPhone":/iPad/i.test(l)?"iPad":/Android/i.test(l)?"Android":"Mobile Browser"}}class rf extends Error{constructor(){super("Remote control target changed"),this.name="RemoteControlTargetChangedError"}}function Bt(o){return o instanceof rf}const xm=new Set(["get_workspace_info","list_recent_workspaces","list_assistants","list_sessions","get_session_messages","get_model_catalog","poll_session","ping","get_file_info","read_file_chunk"]);class Cm{client;constructor(l){this.client=l}get controlTargetEpoch(){return this.client.controlTargetEpoch}onControlTargetChange(l){return this.client.onControlTargetChange(l)}ensureControlTargetCurrent(l){if(!this.client.isControlTargetCurrent(l))throw new rf}async request(l,a=this.client.getControlTargetSnapshot()){this.ensureControlTargetCurrent(a);const d=`req_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,f={...l,_request_id:d},m=l.cmd,p=typeof m=="string"&&xm.has(m),_=a.deviceId,w=!!_&&_!==a.homeDeviceId;try{let E;w&&_?E=await this.client.sendDeviceRpc(_,f,{retryable:p}):E=await this.client.sendCommand(f,{retryable:p}),this.ensureControlTargetCurrent(a);const I=E;if(I.resp==="error")throw new Error(I.message||"Unknown error");return E}catch(E){throw this.ensureControlTargetCurrent(a),E}}async getWorkspaceInfo(){const l=await this.request({cmd:"get_workspace_info"});return{has_workspace:l.has_workspace,path:l.path,project_name:l.project_name,git_branch:l.git_branch,workspace_kind:l.workspace_kind,assistant_id:l.assistant_id,remote_connection_id:l.remote_connection_id,remote_ssh_host:l.remote_ssh_host}}async listRecentWorkspaces(){return(await this.request({cmd:"list_recent_workspaces"})).workspaces||[]}async setWorkspace(l,a){return this.request({cmd:"set_workspace",path:l,remote_connection_id:a?.remoteConnectionId,remote_ssh_host:a?.remoteSshHost})}async listAssistants(){return(await this.request({cmd:"list_assistants"})).assistants||[]}async setAssistant(l){return this.request({cmd:"set_assistant",path:l})}async listSessions(l,a=30,d=0,f,m){const p=await this.request({cmd:"list_sessions",workspace_path:l??null,remote_connection_id:m?.remoteConnectionId,remote_ssh_host:m?.remoteSshHost,limit:a,offset:d,query:f?.trim()||null});return{sessions:p.sessions||[],has_more:p.has_more??!1}}async createSession(l,a,d,f){return(await this.request({cmd:"create_session",agent_type:l||void 0,session_name:a||void 0,workspace_path:d??null,remote_connection_id:f?.remoteConnectionId,remote_ssh_host:f?.remoteSshHost})).session_id}async getSessionMessages(l,a,d){const f=await this.request({cmd:"get_session_messages",session_id:l,limit:a,before_message_id:d});return{messages:f.messages||[],has_more:f.has_more||!1}}async getModelCatalog(l){return(await this.request({cmd:"get_model_catalog",session_id:l??void 0})).catalog}async setSessionModel(l,a){return(await this.request({cmd:"set_session_model",session_id:l,model_id:a})).model_id}async setSessionModelSelection(l,a,d){const f=await this.request({cmd:"set_session_model",session_id:l,model_id:a,reasoning_preset:d});return{model_id:f.model_id,reasoning_preset:f.reasoning_preset??null}}async sendMessage(l,a,d,f){return(await this.request({cmd:"send_message",session_id:l,content:a,agent_type:d||void 0,image_contexts:f&&f.length>0?f:void 0})).turn_id}async cancelTask(l,a){await this.request({cmd:"cancel_task",session_id:l,turn_id:a??void 0})}async cancelTool(l,a){await this.request({cmd:"cancel_tool",tool_id:l,reason:a??void 0})}async deleteSession(l){await this.request({cmd:"delete_session",session_id:l})}async renameSession(l,a){await this.request({cmd:"update_session_title",session_id:l,title:a})}async answerQuestion(l,a){await this.request({cmd:"answer_question",tool_id:l,answers:a})}async pollSession(l,a,d,f=0){return this.request({cmd:"poll_session",session_id:l,since_version:a,known_msg_count:d,known_model_catalog_version:f})}async ping(){await this.request({cmd:"ping"})}async getFileInfo(l,a){const d=await this.request({cmd:"get_file_info",path:l,session_id:a??void 0});return{name:d.name,size:d.size,mimeType:d.mime_type}}async readFile(l,a,d){let m=0;const p=[];let _="",w="",E=0;const I=this.client.getControlTargetSnapshot();for(;;){const j=await this.request({cmd:"read_file_chunk",path:l,session_id:a??void 0,offset:m,limit:3145728},I);if(this.ensureControlTargetCurrent(I),p.push(j.chunk_base64),_=j.name,w=j.mime_type,E=j.total_size,m+=j.chunk_size,d?.(Math.min(m,E),E),m>=E||j.chunk_size===0)break}return this.ensureControlTargetCurrent(I),{name:_,contentBase64:p.join(""),mimeType:w,size:E}}}class zg{intervalId=null;sinceVersion=0;knownMsgCount=0;sessionId;sessionMgr;onUpdate;polling=!1;stopped=!1;hasActiveTurn=!1;knownModelCatalogVersion=0;turnJustEndedAt=null;TURN_JUST_ENDED_GRACE_PERIOD_MS=5e3;constructor(l,a,d,f=0){this.sessionMgr=l,this.sessionId=a,this.onUpdate=d,this.knownModelCatalogVersion=f}start(l=0){this.stopped=!1,this.knownMsgCount=l,this.tick(),document.addEventListener("visibilitychange",this.onVisibilityChange)}stop(){this.stopped=!0,this.intervalId!==null&&(clearTimeout(this.intervalId),this.intervalId=null),document.removeEventListener("visibilitychange",this.onVisibilityChange)}resetCursors(){this.sinceVersion=0,this.knownMsgCount=0}setKnownModelCatalogVersion(l){this.knownModelCatalogVersion=l}nudge(){this.hasActiveTurn=!0,this.intervalId!==null&&clearTimeout(this.intervalId),this.tick()}getInterval(){if(document.visibilityState!=="visible")return 5e3;const l=Date.now();return this.turnJustEndedAt!=null&&l-this.turnJustEndedAtthis.tick(),this.getInterval()))}onVisibilityChange=()=>{this.stopped||(document.visibilityState==="visible"?(this.intervalId!==null&&clearTimeout(this.intervalId),this.tick()):this.scheduleNext())};async tick(){if(this.stopped||this.polling){this.scheduleNext();return}this.polling=!0;try{const l=await this.sessionMgr.pollSession(this.sessionId,this.sinceVersion,this.knownMsgCount,this.knownModelCatalogVersion);if(l.changed){const a=this.hasActiveTurn,d=l.active_turn!=null&&l.active_turn.status==="active";this.hasActiveTurn=d,a&&!d&&(this.turnJustEndedAt=Date.now()),(l.new_messages&&l.new_messages.length>0||l.message_snapshot)&&(this.turnJustEndedAt=null),this.sinceVersion=l.version,l.total_msg_count!=null&&(this.knownMsgCount=l.total_msg_count),l.model_catalog?.version!=null&&(this.knownModelCatalogVersion=l.model_catalog.version),this.onUpdate(l)}}catch(l){console.error("[Poller] poll error",l)}finally{this.polling=!1,this.scheduleNext()}}}const gd=o=>{let l;const a=new Set,d=(E,I)=>{const j=typeof E=="function"?E(l):E;if(!Object.is(j,l)){const R=l;l=I??(typeof j!="object"||j===null)?j:Object.assign({},l,j),a.forEach(B=>B(l,R))}},f=()=>l,_={setState:d,getState:f,getInitialState:()=>w,subscribe:E=>(a.add(E),()=>a.delete(E))},w=l=o(d,f,_);return _},Em=(o=>o?gd(o):gd),Nm=o=>o;function jm(o,l=Nm){const a=Yr.useSyncExternalStore(o.subscribe,Yr.useCallback(()=>l(o.getState()),[o,l]),Yr.useCallback(()=>l(o.getInitialState()),[o,l]));return Yr.useDebugValue(a),a}const vd=o=>{const l=Em(o),a=d=>jm(l,d);return Object.assign(a,l),a},Tm=(o=>o?vd(o):vd),Wt=Tm((o,l)=>({connectionStatus:"idle",setConnectionStatus:a=>o({connectionStatus:a}),connectionHealth:"unpaired",setConnectionHealth:a=>o({connectionHealth:a}),currentWorkspace:null,setCurrentWorkspace:a=>o({currentWorkspace:a}),currentAssistant:null,setCurrentAssistant:a=>o({currentAssistant:a}),pairedDisplayMode:null,setPairedDisplayMode:a=>o({pairedDisplayMode:a}),authenticatedUserId:null,setAuthenticatedUserId:a=>o({authenticatedUserId:a}),authenticatedUserLabel:null,setAuthenticatedUserLabel:a=>o({authenticatedUserLabel:a}),controlTarget:null,setControlTarget:a=>o({controlTarget:a}),sessions:[],setSessions:a=>o({sessions:a}),appendSessions:a=>o(d=>({sessions:[...d.sessions,...a]})),updateSessionName:(a,d)=>o(f=>({sessions:f.sessions.map(m=>m.session_id===a?{...m,name:d}:m)})),removeSession:a=>o(d=>{const{[a]:f,...m}=d.messagesBySession;return{sessions:d.sessions.filter(p=>p.session_id!==a),messagesBySession:m}}),activeSessionId:null,setActiveSessionId:a=>o({activeSessionId:a}),messagesBySession:{},deletedMessageIds:{},getMessages:a=>{const d=l().messagesBySession[a]||[],f=l().deletedMessageIds[a];return f?d.filter(m=>!f.has(m.id)):d},setMessages:(a,d)=>o(f=>{const m=f.deletedMessageIds[a],p=m?d.filter(_=>!m.has(_.id)):d;return{messagesBySession:{...f.messagesBySession,[a]:p}}}),appendNewMessages:(a,d)=>o(f=>{if(d.length===0)return f;const m=f.messagesBySession[a]||[],p=new Set(m.map(E=>E.id)),_=f.deletedMessageIds[a],w=d.filter(E=>!p.has(E.id)&&!_?.has(E.id));return w.length===0?f:{messagesBySession:{...f.messagesBySession,[a]:[...m,...w]}}}),deleteMessage:(a,d)=>o(f=>{const m=f.messagesBySession[a],p=new Set(f.deletedMessageIds[a]||[]);return p.add(d),{deletedMessageIds:{...f.deletedMessageIds,[a]:p},messagesBySession:m?{...f.messagesBySession,[a]:m.filter(_=>_.id!==d)}:f.messagesBySession}}),activeTurn:null,setActiveTurn:a=>o({activeTurn:a}),error:null,setError:a=>o({error:a}),resetConnectionState:()=>o({connectionStatus:"idle",currentWorkspace:null,currentAssistant:null,pairedDisplayMode:null,authenticatedUserId:null,authenticatedUserLabel:null,controlTarget:null,sessions:[],activeSessionId:null,messagesBySession:{},deletedMessageIds:{},activeTurn:null,error:null}),resetForDeviceSwitch:()=>o({currentWorkspace:null,currentAssistant:null,pairedDisplayMode:null,sessions:[],activeSessionId:null,messagesBySession:{},deletedMessageIds:{},activeTurn:null,error:null})})),sf="transparent";function V(o,l){return`rgba(${o}, ${l})`}function ii(...o){return o.join(", ")}function Gr(o,l,a,d,f=["0.04","0.08","0.15","0.25","0.4"]){return{[`${o}-50`]:V(l,f[0]),[`${o}-100`]:V(l,f[1]),[`${o}-200`]:V(l,f[2]),[`${o}-300`]:V(l,f[3]),[`${o}-400`]:V(l,f[4]),[`${o}-500`]:a,[`${o}-600`]:d}}const of={"--color-static-white":"#ffffff","--size-radius-sm":"6px","--size-radius-base":"8px","--size-radius-lg":"12px","--size-radius-xl":"16px","--size-radius-2xl":"20px","--size-radius-full":"9999px","--size-gap-1":"4px","--size-gap-2":"8px","--size-gap-3":"12px","--size-gap-4":"16px","--size-gap-5":"20px","--size-gap-6":"24px","--size-gap-8":"32px","--size-gap-10":"40px","--size-gap-12":"48px","--size-gap-16":"64px","--motion-fast":"0.15s","--motion-base":"0.3s","--motion-slow":"0.6s","--easing-standard":"cubic-bezier(0.4, 0, 0.2, 1)","--font-family-sans":"'Noto Sans SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'SF Pro Display', Roboto, sans-serif","--font-family-mono":"'Menlo', 'SF Mono', 'Cascadia Code', 'Consolas', 'Liberation Mono', 'Courier New', 'Noto Sans Mono CJK SC', 'Noto Sans Mono', monospace","--font-weight-normal":"400","--font-weight-medium":"500","--font-weight-semibold":"600","--font-weight-bold":"700","--font-size-xs":"12px","--font-size-sm":"14px","--font-size-base":"15px","--font-size-lg":"16px","--font-size-xl":"18px","--font-size-2xl":"20px","--font-size-3xl":"24px","--line-height-tight":"1.2","--line-height-base":"1.5","--line-height-relaxed":"1.6"},Qr="0, 0, 0",wt="255, 255, 255",Im="96, 165, 250",Rm="139, 92, 246",Lm="236, 72, 153",yd="52, 211, 153",wd="245, 158, 11",_d="239, 68, 68",li="225, 171, 128",la="#121214",ka="#18181a",kd=ka,Pm="#e8e8e8",Sd="#b0b0b0",aa="#858585",Dm="#555555",Am="#60a5fa",Mm="#3b82f6",zm="#8b5cf6",Um="#7c3aed",Om="#ec4899",Bm="#db2777",Fm="#34d399",Wm="#f59e0b",$m="#ef4444",ua="#e1ab80",Hm="#f6d0a3",lf={"--color-bg-primary":la,"--color-bg-secondary":ka,"--color-bg-tertiary":la,"--color-bg-elevated":ka,"--color-bg-workbench":la,"--color-bg-scene":kd,"--color-bg-flowchat":kd,"--color-text-primary":Pm,"--color-text-secondary":Sd,"--color-text-muted":aa,"--color-text-disabled":Dm,"--element-bg-subtle":V(wt,"0.05"),"--element-bg-soft":V(wt,"0.095"),"--element-bg-base":V(wt,"0.125"),"--element-bg-medium":V(wt,"0.155"),"--element-bg-strong":V(wt,"0.19"),...Gr("--color-accent",Im,Am,Mm),...Gr("--color-purple",Rm,zm,Um),...Gr("--color-pink",Lm,Om,Bm),"--color-success":Fm,"--color-success-bg":V(yd,"0.1"),"--color-success-border":V(yd,"0.3"),"--color-warning":Wm,"--color-warning-bg":V(wd,"0.1"),"--color-warning-border":V(wd,"0.3"),"--color-error":$m,"--color-error-bg":V(_d,"0.1"),"--color-error-border":V(_d,"0.3"),"--color-info":ua,"--color-info-bg":V(li,"0.1"),"--color-info-border":V(li,"0.3"),"--color-highlight":ua,"--color-highlight-bg":V(li,"0.15"),"--color-overlay":V(Qr,"0.5"),"--border-subtle":V(wt,"0.12"),"--border-base":V(wt,"0.18"),"--border-medium":V(wt,"0.24"),"--border-strong":V(wt,"0.32"),"--border-prominent":V(li,"0.5"),"--shadow-xs":`0 1px 2px ${V(Qr,"0.9")}`,"--shadow-sm":`0 2px 4px ${V(Qr,"0.8")}`,"--shadow-base":`0 4px 8px ${V(Qr,"0.7")}`,"--shadow-lg":`0 8px 16px ${V(Qr,"0.6")}`,"--shadow-xl":`0 12px 24px ${V(Qr,"0.5")}`,"--blur-subtle":"blur(4px) saturate(1.05)","--blur-base":"blur(8px) saturate(1.1)",...of,"--opacity-disabled":"0.6","--opacity-hover":"0.8","--opacity-focus":"0.9","--scrollbar-thumb":V(wt,"0.15"),"--scrollbar-thumb-hover":V(wt,"0.24"),"--btn-default-bg":V(wt,"0.08"),"--btn-default-color":aa,"--btn-hover-bg":V(wt,"0.12"),"--btn-hover-color":Sd,"--btn-primary-bg":ua,"--btn-primary-color":"#000000","--btn-primary-hover-bg":Hm,"--btn-ghost-bg":sf,"--btn-ghost-color":aa,"--btn-ghost-hover-bg":V(wt,"0.095")},Ot="0, 0, 0",Yn="120, 120, 128",Us="60, 60, 67",ca="0, 122, 255",Vm="175, 82, 222",bm="236, 72, 153",da="255, 149, 0",xd="52, 199, 89",Cd="255, 59, 48",fa="#f3f3f5",Os="var(--color-static-white)",Ed="#18181a",pa="#48484a",Km="#8e8e93",Qm="#b0b0b0",ha="#007aff",Nd="#0066cc",qm="#af52de",Ym="#9536cc",Gm="#ec4899",Zm="#db2777",jd="#ff9500",Xm="#34c759",Jm="#ff3b30",af={"--color-bg-primary":fa,"--color-bg-secondary":Os,"--color-bg-tertiary":fa,"--color-bg-elevated":Os,"--color-bg-workbench":fa,"--color-bg-scene":Os,"--color-bg-flowchat":Os,"--color-text-primary":Ed,"--color-text-secondary":pa,"--color-text-muted":Km,"--color-text-disabled":Qm,"--element-bg-subtle":V(Yn,"0.04"),"--element-bg-soft":V(Yn,"0.08"),"--element-bg-base":V(Yn,"0.1"),"--element-bg-medium":V(Yn,"0.14"),"--element-bg-strong":V(Yn,"0.2"),...Gr("--color-accent",ca,ha,Nd,["0.04","0.08","0.14","0.22","0.36"]),...Gr("--color-purple",Vm,qm,Ym,["0.04","0.08","0.14","0.22","0.36"]),...Gr("--color-pink",bm,Gm,Zm,["0.04","0.08","0.14","0.22","0.36"]),"--color-success":Xm,"--color-success-bg":V(xd,"0.08"),"--color-success-border":V(xd,"0.25"),"--color-warning":jd,"--color-warning-bg":V(da,"0.08"),"--color-warning-border":V(da,"0.25"),"--color-error":Jm,"--color-error-bg":V(Cd,"0.08"),"--color-error-border":V(Cd,"0.25"),"--color-info":ha,"--color-info-bg":V(ca,"0.08"),"--color-info-border":V(ca,"0.25"),"--color-highlight":jd,"--color-highlight-bg":V(da,"0.1"),"--color-overlay":V(Ot,"0.3"),"--border-subtle":V(Us,"0.08"),"--border-base":V(Us,"0.14"),"--border-medium":V(Us,"0.22"),"--border-strong":V(Us,"0.3"),"--border-prominent":V(Us,"0.4"),"--shadow-xs":`0 1px 2px ${V(Ot,"0.04")}`,"--shadow-sm":ii(`0 1px 3px ${V(Ot,"0.06")}`,`0 1px 2px ${V(Ot,"0.04")}`),"--shadow-base":ii(`0 2px 8px ${V(Ot,"0.06")}`,`0 1px 3px ${V(Ot,"0.04")}`),"--shadow-lg":ii(`0 4px 16px ${V(Ot,"0.08")}`,`0 2px 6px ${V(Ot,"0.04")}`),"--shadow-xl":ii(`0 8px 24px ${V(Ot,"0.1")}`,`0 4px 8px ${V(Ot,"0.04")}`),"--blur-subtle":"blur(4px) saturate(1.2)","--blur-base":"blur(8px) saturate(1.4)",...of,"--opacity-disabled":"0.55","--opacity-hover":"0.75","--opacity-focus":"0.9","--scrollbar-thumb":V(Ot,"0.15"),"--scrollbar-thumb-hover":V(Ot,"0.25"),"--btn-default-bg":V(Yn,"0.08"),"--btn-default-color":pa,"--btn-hover-bg":V(Yn,"0.14"),"--btn-hover-color":Ed,"--btn-primary-bg":ha,"--btn-primary-color":Os,"--btn-primary-hover-bg":Nd,"--btn-ghost-bg":sf,"--btn-ghost-color":pa,"--btn-ghost-hover-bg":V(Yn,"0.08")},uf="bitfun-mobile-theme",Td="data-bitfun-theme",cf={dark:lf,light:af},Sa="--color-bg-primary",df="--color-text-primary";function $s(o,l){return cf[o][l]}function Id(o,l){const a=$s(o,Sa),d=$s(o,df),f=[":root {"];for(const[m,p]of Object.entries(l))f.push(` ${m}: ${p};`);return f.push(` color-scheme: ${o};`),f.push("}"),f.push(`html, body { background-color: ${a}; color: ${d}; color-scheme: ${o}; }`),f.join(` -`)}const eg={dark:Id("dark",lf),light:Id("light",af)};function tg(o){const l=document.documentElement,a=document.body,d=cf[o],f=document.createElement("style");f.setAttribute(Td,o),f.textContent=eg[o],document.head.appendChild(f),document.head.querySelectorAll(`style[${Td}]`).forEach(p=>{p!==f&&p.remove()});for(const p of Object.keys(d))l.style.setProperty(p,d[p]);l.style.setProperty("color-scheme",o),l.setAttribute("data-theme",o),l.setAttribute("data-theme-type",o),a.setAttribute("data-theme",o),a.style.backgroundColor=$s(o,Sa),a.style.color=$s(o,df);const m=document.querySelector('meta[name="theme-color"]');m&&(m.setAttribute("content",$s(o,Sa)),m.removeAttribute("media"))}function ng(){try{const o=localStorage.getItem(uf);if(o==="dark"||o==="light")return o}catch{}return window.matchMedia?.("(prefers-color-scheme: light)").matches?"light":"dark"}const ff=C.createContext({themeId:"dark",isDark:!0,setTheme:()=>{},toggleTheme:()=>{}}),rg=280;let Rd;const sg=({children:o})=>{const[l,a]=C.useState(ng);C.useLayoutEffect(()=>{const m=document.documentElement,p=m.getAttribute("data-theme"),_=p&&p!==l;_&&(clearTimeout(Rd),m.classList.add("theme-switching"),m.offsetHeight),tg(l),_&&(Rd=setTimeout(()=>{m.classList.remove("theme-switching")},rg+40));try{localStorage.setItem(uf,l)}catch{}},[l]);const d=C.useCallback(m=>a(m),[]),f=C.useCallback(()=>a(m=>m==="dark"?"light":"dark"),[]);return u.jsx(ff.Provider,{value:{themeId:l,isDark:l==="dark",setTheme:d,toggleTheme:f},children:o})};function pf(){return C.useContext(ff)}const hf=""+new URL("Logo-ICON-BOaKcXgO.png",import.meta.url).href,og=({isDark:o})=>u.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:o?u.jsx("path",{d:"M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM3 8a5 5 0 0 1 5-5v10a5 5 0 0 1-5-5Z",fill:"currentColor"}):u.jsx("path",{d:"M8 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 1Zm0 11a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 12Zm7-4a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 15 8ZM3 8a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 3 8Zm9.95-3.54a.5.5 0 0 1 0 .71l-.71.7a.5.5 0 1 1-.7-.7l.7-.71a.5.5 0 0 1 .71 0ZM5.46 11.24a.5.5 0 0 1 0 .71l-.7.71a.5.5 0 0 1-.71-.71l.7-.71a.5.5 0 0 1 .71 0Zm7.08 1.42a.5.5 0 0 1-.7 0l-.71-.71a.5.5 0 0 1 .7-.7l.71.7a.5.5 0 0 1 0 .71ZM5.46 4.76a.5.5 0 0 1-.71 0l-.71-.7a.5.5 0 0 1 .71-.71l.7.7a.5.5 0 0 1 0 .71ZM8 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z",fill:"currentColor"})}),Ld="bitfun.mobile.install_id",Pd="bitfun.mobile.user_id",dr="bitfun.mobile.user_id_lock_until",qr="bitfun.mobile.user_id_failure_count",ig=3,Dd=6e4;function lg(o){return o.includes("This remote URL is already protected")||o.includes("This mobile device must continue using the previously confirmed user ID")||o.includes("Invalid username or password")||o.includes("Missing password")||o.includes("Missing username")||o.includes("Too many pairing attempts")}function ag(o){try{const l=o.replace(/^wss:\/\//,"https://").replace(/^ws:\/\//,"http://").replace(/\/ws\/?$/,"").replace(/\/$/,""),a=new URL(l);return!["http:","https:"].includes(a.protocol)||!a.hostname||a.username||a.password||a.search||a.hash?null:a.toString().replace(/\/$/,"")}catch{return null}}function ug(o,l){return!!o&&o.length<=128&&/^[A-Za-z0-9_-]+$/.test(o)&&!["_store","page-data","pages"].includes(o)&&!!l&&l.length<=512&&/^[A-Za-z0-9+/=_-]+$/.test(l)}function cg(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`mobile-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function Ad(){const o=localStorage.getItem(Ld)?.trim();if(o)return o;const l=cg();return localStorage.setItem(Ld,l),l}function dg(){const o=window.location.hash,l=new URLSearchParams(o.replace(/^#\/pair\?/,"")),a=l.get("room"),d=l.get("pk"),f=l.get("relay"),m=l.get("auth")==="account",p=l.get("user")?.trim()||null;if(f)return{room:a,pk:d,httpBaseUrl:ag(f)??"",accountAuth:m,accountUsername:p};const _=window.location.origin,w=window.location.pathname.replace(/\/[^/]*$/,"").replace(/\/r\/[^/]*$/,"");return{room:a,pk:d,httpBaseUrl:_+w,accountAuth:m,accountUsername:p}}const fg=({onPaired:o})=>{const{t:l}=Zr(),{isDark:a,toggleTheme:d}=pf(),{connectionStatus:f,setConnectionStatus:m,setError:p,error:_,setAuthenticatedUserId:w,setAuthenticatedUserLabel:E}=Wt(),[I,j]=C.useState(""),[R,B]=C.useState(""),[F,$]=C.useState(!1),[W,de]=C.useState(0),[b,K]=C.useState(null),[se,_e]=C.useState(()=>Date.now()),fe=C.useRef(0),ke=C.useRef(null),Se=C.useRef(0),Te=C.useRef(async()=>{}),Me=C.useRef(o);Me.current=o;const Ce=C.useMemo(()=>dg(),[]),me=Ce.accountAuth,Q=!!b&&b>se,q=Q?Math.max(1,Math.ceil((b-se)/1e3)):0,ee=C.useCallback(async(L,v,T)=>{const re=Ce.room,ue=Ce.pk,pe=L.trim(),ce=v,te=T?.autoReconnect===!0,ge=T?.installId||Ad(),ye=ke.current,De=!!ye&&ye>Date.now(),ct=De?Math.max(1,Math.ceil((ye-Date.now())/1e3)):0,kt=++Se.current,ze=()=>Se.current===kt;if(!re||!ue||!ug(re,ue)||!Ce.httpBaseUrl){if(!ze())return;p(l("pairing.invalidQrCode")),m("error");return}if(!pe){if(!ze())return;p(l(me?"pairing.usernameRequired":"pairing.userIdRequired")),m("error");return}if(pe.length>128||ce.length>1024){if(!ze())return;p(l("pairing.fieldsTooLong")),m("error");return}if(me&&!ce){if(!ze())return;p(l("pairing.passwordRequired")),m("error");return}if(!te&&De){if(!ze())return;p(l("pairing.tooManyAttempts",{seconds:ct})),m("error");return}$(!0),p(null),m("pairing");const $e=new Sm(Ce.httpBaseUrl,re);try{const Ie=await $e.pair(ue,{userId:pe,mobileInstallId:ge,password:me?ce:void 0});if(!ze())return;m("paired"),localStorage.setItem(Pd,pe),localStorage.removeItem(qr),localStorage.removeItem(dr),de(0),K(null),B(""),w(Ie.authenticated_user_id??(me?null:pe)),E(pe);const He=new Cm($e),Ve=Wt.getState();Ie.has_workspace&&(Ie.workspace_kind==="assistant"&&Ie.path?(Ve.setPairedDisplayMode("assistant"),Ve.setCurrentAssistant({path:Ie.path,name:Ie.project_name??"Claw",assistant_id:Ie.assistant_id}),Ve.setCurrentWorkspace(null)):(Ve.setPairedDisplayMode("pro"),Ve.setCurrentWorkspace({has_workspace:!0,path:Ie.path,project_name:Ie.project_name,git_branch:Ie.git_branch,workspace_kind:Ie.workspace_kind,assistant_id:Ie.assistant_id,remote_connection_id:Ie.remote_connection_id,remote_ssh_host:Ie.remote_ssh_host}))),Ie.sessions&&Ve.setSessions(Ie.sessions);try{const jt=await Promise.race([$e.requestDelegatedIdentity(),new Promise(nt=>{window.setTimeout(()=>nt(!1),1e4)})]);if(!ze())return;const Ye=$e.homeDeviceId;if(jt&&Ye){Ve.setControlTarget({deviceId:Ye,deviceName:null,isHome:!0});const nt=$e.delegatedAccountEpoch,$t=$e.getControlTargetSnapshot();$e.listDevices().then(ln=>{if($e.delegatedAccountEpoch!==nt||!$e.isControlTargetCurrent($t)||$e.pairedDeviceId!==Ye)return;const Zn=ln.find(Ht=>Ht.device_id===Ye);Zn&&Wt.getState().setControlTarget({deviceId:Ye,deviceName:Zn.device_name,isHome:!0})}).catch(()=>{})}}catch{}if(!ze())return;Me.current($e,He)}catch(Ie){if(!ze())return;const He=Ie?.message||"",Ve=He.includes("timed out")?l("pairing.requestTimedOut"):He.includes("HTTP 404")?l("pairing.qrExpired"):He.includes("HTTP 429")?l("pairing.rateLimited"):He.includes("HTTP 503")||He.includes("HTTP 504")?l("pairing.relayUnavailable"):He||l("pairing.pairingFailed");if(!te&&lg(Ve)){const jt=fe.current+1,Ye=jt>=ig,nt=Ye?Date.now()+Dd:null;localStorage.setItem(qr,String(jt)),nt?localStorage.setItem(dr,String(nt)):localStorage.removeItem(dr),de(jt),K(nt),p(Ye?l("pairing.tooManyAttempts",{seconds:Math.ceil(Dd/1e3)}):He.includes("Too many pairing attempts")?l("pairing.rateLimited"):l("pairing.credentialsRejected"))}else p(Ve);m("error")}finally{ze()&&$(!1)}},[Ce.httpBaseUrl,Ce.pk,Ce.room,me,w,E,m,p,l]);Te.current=ee,C.useEffect(()=>{const L=localStorage.getItem(Pd)?.trim()??"",T=(Ce.accountUsername?.trim()??"")||L,re=Ad(),ue=Number(localStorage.getItem(qr)||"0"),pe=Number(localStorage.getItem(dr)||"0"),ce=pe>Date.now()?pe:null;pe&&!ce&&(localStorage.removeItem(dr),localStorage.removeItem(qr));const te=!me&&!!L&&!!re&&!!Ce.room&&!!Ce.pk;return j(T),de(ce?ue:0),K(ce),p(null),te?(m("pairing"),Te.current(L,"",{autoReconnect:!0,installId:re})):m("idle"),()=>{Se.current+=1}},[]),C.useEffect(()=>{fe.current=W,ke.current=b},[W,b]),C.useEffect(()=>{if(!b)return;if(b<=Date.now()){K(null),de(0),localStorage.removeItem(dr),localStorage.removeItem(qr);return}const L=window.setInterval(()=>{const v=Date.now();_e(v),b<=v&&(K(null),de(0),localStorage.removeItem(dr),localStorage.removeItem(qr))},1e3);return()=>window.clearInterval(L)},[b]);const ae=async()=>{await ee(I,R,{autoReconnect:!1})},ne={idle:l(me?"pairing.enterAccountToContinue":"pairing.enterUserIdToContinue"),pairing:l("pairing.connectingAndPairing"),paired:l("pairing.pairedLoadingSessions"),error:l("pairing.connectionError")},D=f==="pairing",O=f==="idle"||f==="error";return u.jsxs("div",{className:"pairing-page",children:[u.jsxs("div",{className:"pairing-page__actions",children:[u.jsx(Ea,{}),u.jsx("button",{className:"pairing-page__theme-btn",onClick:d,"aria-label":l("common.toggleTheme"),children:u.jsx(og,{isDark:a})})]}),u.jsx("img",{src:hf,alt:"BitFun",className:"pairing-page__logo"}),u.jsx("div",{className:"pairing-page__brand",children:l("shared.product.remote")}),u.jsx("div",{className:"pairing-page__spinner-wrap",children:D&&u.jsx("div",{className:"spinner"})}),u.jsx("div",{className:"pairing-page__state",children:ne[f]||f}),O&&u.jsxs("div",{className:"pairing-page__form",children:[u.jsxs("label",{className:"pairing-page__field",children:[u.jsx("span",{className:"pairing-page__field-label",children:l(me?"pairing.usernameLabel":"pairing.fieldLabel")}),u.jsx("input",{className:"pairing-page__input",type:"text",value:I,onChange:L=>j(L.target.value),placeholder:l(me?"pairing.usernamePlaceholder":"pairing.placeholder"),autoCapitalize:"off",autoCorrect:"off",autoComplete:"username",maxLength:128,disabled:F||Q})]}),me&&u.jsxs("label",{className:"pairing-page__field",children:[u.jsx("span",{className:"pairing-page__field-label",children:l("pairing.passwordLabel")}),u.jsx("input",{className:"pairing-page__input",type:"password",value:R,onChange:L=>B(L.target.value),placeholder:l("pairing.passwordPlaceholder"),autoComplete:"current-password",maxLength:1024,disabled:F||Q})]}),u.jsx("p",{className:"pairing-page__note",children:l(me?"pairing.accountNote":"pairing.note")}),u.jsx("button",{className:"pairing-page__retry",onClick:ae,disabled:F||Q,children:F?l("pairing.connecting"):Q?l("pairing.retryIn",{seconds:q}):l("pairing.continue")})]}),_&&u.jsx("div",{className:"pairing-page__error",children:_})]})},pg=({sessionMgr:o,onReady:l})=>{const{t:a}=Zr(),[d,f]=C.useState(null),[m,p]=C.useState([]),[_,w]=C.useState(!0),[E,I]=C.useState(!1),[j,R]=C.useState(null),[B,F]=C.useState(!1),$=C.useCallback(async()=>{try{const K=await o.getWorkspaceInfo();f(K)}catch(K){R(K.message)}finally{w(!1)}},[o]),W=C.useCallback(async()=>{try{const K=await o.listRecentWorkspaces();p(K)}catch(K){R(K.message)}},[o]);C.useEffect(()=>{$()},[$]);const de=async()=>{F(!0),await W()},b=C.useCallback(async K=>{if(!E){I(!0),R(null);try{const se=await o.setWorkspace(K.path,{remoteConnectionId:K.remote_connection_id,remoteSshHost:K.remote_ssh_host});se.success?(await $(),F(!1)):R(se.error||a("workspace.failedToSetWorkspace"))}catch(se){R(se.message)}finally{I(!1)}}},[$,o,E,a]);return _?u.jsx("div",{className:"workspace-page",children:u.jsxs("div",{className:"workspace-page__loading",children:[u.jsx("div",{className:"spinner"}),u.jsx("span",{children:a("workspace.loadingInfo")})]})}):u.jsxs("div",{className:"workspace-page",children:[u.jsxs("div",{className:"workspace-page__header",children:[u.jsx("h1",{children:a("shared.features.workspace")}),u.jsx(Ea,{})]}),u.jsxs("div",{className:"workspace-page__content",children:[d?.has_workspace?u.jsxs("div",{className:"workspace-page__current",children:[u.jsx("div",{className:"workspace-page__current-label",children:a("workspace.currentWorkspace")}),u.jsxs("div",{className:"workspace-page__current-card",children:[u.jsx("div",{className:"workspace-page__project-name",children:d.project_name||a("workspace.unknownProject")}),u.jsx("div",{className:"workspace-page__project-path",children:d.path}),d.git_branch&&u.jsxs("div",{className:"workspace-page__git-branch",children:[u.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:[u.jsx("circle",{cx:"5",cy:"4",r:"2",stroke:"currentColor",strokeWidth:"1.3"}),u.jsx("circle",{cx:"11",cy:"4",r:"2",stroke:"currentColor",strokeWidth:"1.3"}),u.jsx("circle",{cx:"5",cy:"12",r:"2",stroke:"currentColor",strokeWidth:"1.3"}),u.jsx("path",{d:"M5 6V10M11 6V8C11 9.1046 10.1046 10 9 10H5",stroke:"currentColor",strokeWidth:"1.3"})]}),d.git_branch]})]}),u.jsxs("div",{className:"workspace-page__actions",children:[u.jsx("button",{className:"workspace-page__btn workspace-page__btn--primary",onClick:l,children:a("common.continue")}),u.jsx("button",{className:"workspace-page__btn workspace-page__btn--secondary",onClick:de,children:a("common.switch")})]})]}):u.jsxs("div",{className:"workspace-page__no-workspace",children:[u.jsx("div",{className:"workspace-page__no-workspace-icon",children:u.jsx("svg",{width:"40",height:"40",viewBox:"0 0 16 16",fill:"none",children:u.jsx("path",{d:"M2 4V12C2 12.5523 2.44772 13 3 13H13C13.5523 13 14 12.5523 14 12V6C14 5.44772 13.5523 5 13 5H8L6.5 3H3C2.44772 3 2 3.44772 2 4Z",stroke:"currentColor",strokeWidth:"1.3",strokeLinejoin:"round"})})}),u.jsx("div",{className:"workspace-page__no-workspace-text",children:a("workspace.noWorkspaceOpen")}),u.jsx("div",{className:"workspace-page__no-workspace-hint",children:a("workspace.noWorkspaceHint")}),!B&&u.jsx("button",{className:"workspace-page__btn workspace-page__btn--primary",onClick:de,children:a("workspace.selectWorkspace")})]}),B&&u.jsxs("div",{className:"workspace-page__recent",children:[u.jsx("div",{className:"workspace-page__recent-label",children:a("workspace.recentWorkspaces")}),m.length===0?u.jsx("div",{className:"workspace-page__recent-empty",children:a("workspace.noRecentWorkspaces")}):u.jsx("div",{className:"workspace-page__recent-list",children:m.map(K=>u.jsxs("button",{className:"workspace-page__recent-item",onClick:()=>b(K),disabled:E,children:[u.jsx("div",{className:"workspace-page__recent-item-name",children:K.name}),u.jsx("div",{className:"workspace-page__recent-item-path",children:K.path})]},`${K.remote_connection_id??"local"}:${K.path}`))}),d?.has_workspace&&u.jsx("button",{className:"workspace-page__btn workspace-page__btn--secondary",onClick:()=>F(!1),children:a("common.cancel")})]}),E&&u.jsxs("div",{className:"workspace-page__switching",children:[u.jsx("div",{className:"spinner spinner--sm"}),u.jsx("span",{children:a("workspace.openingWorkspace")})]}),j&&u.jsx("div",{className:"workspace-page__error",children:j})]})]})};function hg(o){const l=C.useCallback(d=>o.onControlTargetChange(d),[o]),a=C.useCallback(()=>o.controlTargetEpoch,[o]);return C.useSyncExternalStore(l,a,a)}const ai=30,mg=(o,l=!1)=>{const a=o.nativeEvent;return l||a.isComposing||a.keyCode===229};function gg(o,l,a){return!o.active||o.sessionMgr!==l||o.epoch!==a||l.controlTargetEpoch!==a?null:a}function Md(o,l,a){const d=parseInt(o,10);if(!d||isNaN(d))return"";const f=new Date(d*1e3),p=new Date().getTime()-f.getTime(),_=Math.floor(p/6e4);if(_<1)return a("common.justNow");if(_<60)return a("common.minutesAgo",{count:_});const w=Math.floor(_/60);if(w<24)return a("common.hoursAgo",{count:w});const E=Math.floor(w/24);return E<7?a("common.daysAgo",{count:E}):l(f)}function zd(o,l){switch(o){case"code":case"agentic":return l("sessions.agentCode");case"cowork":case"Cowork":return l("sessions.agentCowork");case"claw":case"Claw":return l("shared.agents.claw");default:return o||l("sessions.agentDefault")}}function mf(o){return o==="cowork"||o==="Cowork"}function gf(o){return o==="claw"||o==="Claw"}function vg(o){return o.length===0?void 0:o.some(a=>a.workspace_kind!=null)?o.find(a=>a.workspace_kind!=="assistant"):o[0]}function Ud(o,l){if(!o||o.length<=l)return o;const a=l-3,d=Math.ceil(a*.6),f=a-d;return o.slice(0,d)+"..."+o.slice(-f)}function Bs({agentType:o}){return mf(o)?u.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}),u.jsx("circle",{cx:"9",cy:"7",r:"4"}),u.jsx("path",{d:"M22 21v-2a4 4 0 0 0-3-3.87"}),u.jsx("path",{d:"M16 3.13a4 4 0 0 1 0 7.75"})]}):gf(o)?u.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("rect",{width:"20",height:"14",x:"2",y:"5",rx:"2"}),u.jsx("path",{d:"M2 10h20"})]}):u.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"})})}const yg=()=>u.jsxs("svg",{width:"32",height:"32",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("polyline",{points:"4 17 10 11 4 5"}),u.jsx("line",{x1:"12",y1:"19",x2:"20",y2:"19"})]}),ma=()=>u.jsxs("svg",{width:"32",height:"32",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"M12 8V4H8"}),u.jsx("rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}),u.jsx("path",{d:"M2 14h2"}),u.jsx("path",{d:"M20 14h2"}),u.jsx("path",{d:"M15 13v2"}),u.jsx("path",{d:"M9 13v2"})]}),Od=()=>u.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.93a2 2 0 0 1 1.66.9l.82 1.2a2 2 0 0 0 1.66.9H18a2 2 0 0 1 2 2v2"})}),wg=({isDark:o})=>u.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:o?u.jsx("path",{d:"M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM3 8a5 5 0 0 1 5-5v10a5 5 0 0 1-5-5Z",fill:"currentColor"}):u.jsx("path",{d:"M8 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 1Zm0 11a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 12Zm7-4a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 15 8ZM3 8a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 3 8Zm9.95-3.54a.5.5 0 0 1 0 .71l-.71.7a.5.5 0 1 1-.7-.7l.7-.71a.5.5 0 0 1 .71 0ZM5.46 11.24a.5.5 0 0 1 0 .71l-.7.71a.5.5 0 0 1-.71-.71l.7-.71a.5.5 0 0 1 .71 0Zm7.08 1.42a.5.5 0 0 1-.7 0l-.71-.71a.5.5 0 0 1 .7-.7l.71.7a.5.5 0 0 1 0 .71ZM5.46 4.76a.5.5 0 0 1-.71 0l-.71-.7a.5.5 0 0 1 .71-.71l.7.7a.5.5 0 0 1 0 .71ZM8 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z",fill:"currentColor"})}),_g=({sessionMgr:o,onSelectSession:l,onOpenWorkspace:a,onDisconnect:d,onOpenDevices:f})=>{const m=C.useRef(!1),{t:p,formatDate:_}=Zr(),{sessions:w,setSessions:E,appendSessions:I,setError:j,currentWorkspace:R,setCurrentWorkspace:B,currentAssistant:F,setCurrentAssistant:$,setPairedDisplayMode:W,authenticatedUserLabel:de,connectionHealth:b,controlTarget:K}=Wt(),{isDark:se,toggleTheme:_e}=pf(),[fe,ke]=C.useState(!1),[Se,Te]=C.useState(!1),[Me,Ce]=C.useState(!1),[me,Q]=C.useState(!0),q=C.useRef(!0),[ee,ae]=C.useState(!1),[ne,D]=C.useState(()=>{const S=Wt.getState().pairedDisplayMode;return S==="assistant"||S==="pro"?S:"pro"}),[O,L]=C.useState([]),[v,T]=C.useState(!1),[re,ue]=C.useState([]),[pe,ce]=C.useState(!1),[te,ge]=C.useState(""),[ye,De]=C.useState(null),[ct,kt]=C.useState(null),[ze,$e]=C.useState(""),[Ie,He]=C.useState(null),[Ve,jt]=C.useState(!1),[Ye,nt]=C.useState(!1),[$t,ln]=C.useState(null),[Zn,Ht]=C.useState(!1),jn=C.useRef(),pr=C.useRef({x:0,y:0}),an=C.useRef(!1),St=C.useRef(),ot=hg(o),Tt=C.useRef({sessionMgr:o,epoch:ot,active:!0});(Tt.current.sessionMgr!==o||Tt.current.epoch!==ot)&&(Tt.current={sessionMgr:o,epoch:ot,active:!0});const Ee=C.useCallback(()=>gg(Tt.current,o,ot),[ot,o]),le=C.useCallback(S=>{const z=Tt.current;return S!==null&&z.active&&z.sessionMgr===o&&z.epoch===S&&o.controlTargetEpoch===S},[ot,o]),hr=te.trim().length>0,Xr=w.length>0&&!hr,Xn=()=>{jn.current&&(clearTimeout(jn.current),jn.current=void 0)},mr=C.useCallback((S,z)=>{Ve||Ye||(Xn(),an.current=!1,pr.current={x:z.touches[0].clientX,y:z.touches[0].clientY},jn.current=setTimeout(()=>{an.current=!0,De(S),jn.current=void 0},500))},[Ve,Ye]),gr=C.useCallback(S=>{const z=Math.abs(S.touches[0].clientX-pr.current.x),Y=Math.abs(S.touches[0].clientY-pr.current.y);(z>10||Y>10)&&Xn()},[]),Tn=C.useCallback(()=>{Xn()},[]),vr=C.useCallback((S,z)=>{if(an.current){z.preventDefault(),z.stopPropagation(),an.current=!1;return}l(S.session_id,S.name)},[l]),un=C.useCallback(S=>{St.current&&clearTimeout(St.current),ln(S),St.current=setTimeout(()=>ln(null),2500)},[]);C.useEffect(()=>()=>{Xn(),St.current&&clearTimeout(St.current)},[]);const cn=C.useCallback(async()=>{if(!ct||!ze.trim())return;const S=Ee();if(S!==null){nt(!0);try{if(await o.renameSession(ct.session_id,ze.trim()),!le(S))return;Wt.getState().updateSessionName(ct.session_id,ze.trim()),kt(null),De(null)}catch(z){le(S)&&!Bt(z)&&un(z.message||p("sessions.renameFailed"))}finally{le(S)&&nt(!1)}}},[Ee,le,ct,ze,o,un,p]),dn=C.useCallback(async()=>{if(!Ie)return;const S=Ee();if(S!==null){jt(!0);try{if(await o.deleteSession(Ie.session_id),!le(S))return;Wt.getState().removeSession(Ie.session_id),He(null),De(null),un(p("sessions.deleted"))}catch(z){le(S)&&!Bt(z)&&un(z.message||p("sessions.deleteFailed"))}finally{le(S)&&jt(!1)}}},[Ee,Ie,le,o,un,p]),[fn,In]=C.useState(0),[pn,yr]=C.useState(!1),Vt=C.useRef(0),wr=C.useRef(null),Xe=C.useRef(0),bt=C.useRef(void 0),_r=C.useRef(0),It=C.useRef(!1),Hs=C.useRef({sessionMgr:o,epoch:ot});C.useLayoutEffect(()=>{const S=Hs.current,z=S.sessionMgr!==o||S.epoch!==ot,Y=Tt.current;return Y.active=Y.sessionMgr===o&&Y.epoch===ot&&o.controlTargetEpoch===ot,z&&(q.current=!0,Q(!0),Xe.current+=1,Te(!1),Ce(!1),yr(!1),Xn(),an.current=!1,It.current=!1,In(0),St.current&&(clearTimeout(St.current),St.current=void 0),ke(!1),nt(!1),jt(!1),L([]),ue([]),T(!1),ce(!1),De(null),kt(null),$e(""),He(null),ln(null),Ht(!1),ge(""),D("pro"),ae(!1),E([]),B(null),$(null),W(null),j(null),Vt.current=0,bt.current=void 0),Hs.current={sessionMgr:o,epoch:ot},()=>{Y.active=!1,Xe.current+=1}},[ot,o,$,B,j,W,E]);const hn=C.useCallback(async()=>{const S=Ee();if(S!==null)try{const z=await o.listAssistants();if(!le(S))return;if(L(z),!F&&z.length>0){const Y=z.find(ve=>!ve.assistant_id)||z[0];return $(Y),Y.path}return F?.path}catch(z){le(S)&&!Bt(z)&&j(z.message);return}},[Ee,F,le,o,$,j]),Qe=C.useCallback(async(S,z="",Y)=>{const ve=Ee();if(ve===null)return;const xe=++Xe.current;Ce(!1),Te(!0),Vt.current=0;try{const Ne=await o.listSessions(S,ai,0,z,Y);if(xe!==Xe.current||!le(ve))return;E(Ne.sessions),ae(Ne.has_more),Vt.current=Ne.sessions.length}catch(Ne){if(xe!==Xe.current||!le(ve))return;Bt(Ne)||j(Ne.message)}finally{xe===Xe.current&&le(ve)&&Te(!1)}},[Ee,le,o,j,E]),kr=C.useCallback(async()=>{const S=Ee();if(S!==null)try{const z=await o.listRecentWorkspaces();if(!le(S))return;ue(z)}catch(z){le(S)&&!Bt(z)&&j(z.message)}},[Ee,le,o,j]),Jr=C.useCallback(async S=>{if(q.current)return;const z=Ee();if(z!==null)try{const Y=await o.setWorkspace(S.path,{remoteConnectionId:S.remote_connection_id,remoteSshHost:S.remote_ssh_host});if(!le(z))return;if(Y.success){const ve=Y.path||S.path,xe=Y.remote_connection_id??S.remote_connection_id,Ne=Y.remote_ssh_host??S.remote_ssh_host,en={remoteConnectionId:xe,remoteSshHost:Ne};B({has_workspace:!0,path:ve,project_name:Y.project_name||S.name,workspace_kind:xe||Ne?"remote":void 0,remote_connection_id:xe,remote_ssh_host:Ne}),ce(!1),Qe(ve,te,en)}else j(Y.error||"Failed to set workspace")}catch(Y){le(z)&&!Bt(Y)&&j(Y.message)}},[Ee,le,Qe,te,o,B,j]),es=C.useCallback(async()=>{const S=Ee();if(S===null)return!1;try{const z=await o.listRecentWorkspaces();if(!le(S))return!1;const Y=vg(z);if(!Y)return!1;const ve=await o.setWorkspace(Y.path,{remoteConnectionId:Y.remote_connection_id,remoteSshHost:Y.remote_ssh_host});if(!le(S))return!1;if(ve.success){const xe=ve.path||Y.path,Ne=ve.remote_connection_id??Y.remote_connection_id,en=ve.remote_ssh_host??Y.remote_ssh_host,Lt={remoteConnectionId:Ne,remoteSshHost:en};return B({has_workspace:!0,path:xe,project_name:ve.project_name||Y.name,workspace_kind:Ne||en?"remote":Y.workspace_kind,remote_connection_id:Ne,remote_ssh_host:en}),await Qe(xe,te,Lt),le(S)}return j(ve.error||p("workspace.failedToSetWorkspace")),!1}catch(z){return le(S)&&!Bt(z)&&j(z.message),!1}},[Ee,le,Qe,te,o,B,j,p]),Vs=C.useCallback(async(S,z="",Y)=>{if(Se||Me||!ee)return;const ve=Ee();if(ve===null)return;const xe=Xe.current;Ce(!0);try{const Ne=await o.listSessions(S,ai,Vt.current,z,Y);if(xe!==Xe.current||!le(ve))return;I(Ne.sessions),ae(Ne.has_more),Vt.current+=Ne.sessions.length}catch(Ne){if(xe!==Xe.current||!le(ve))return;Bt(Ne)||j(Ne.message)}finally{xe===Xe.current&&le(ve)&&Ce(!1)}},[I,Ee,ee,le,Se,Me,o,j]);C.useEffect(()=>{let S=!1;const z=Ee();if(z===null)return;const Y=()=>!S&&le(z);return(async()=>{try{const xe=await o.getWorkspaceInfo();if(!Y())return;if(xe.workspace_kind==="assistant"&&xe.path)$({path:xe.path,name:xe.project_name??"Claw",assistant_id:xe.assistant_id}),B(null),D("assistant"),bt.current=xe.path,await Qe(xe.path);else{D("pro");const Ne=xe.has_workspace?xe:null;B(Ne),Ne?.path?(bt.current=Ne.path,await Qe(Ne.path,"",{remoteConnectionId:Ne.remote_connection_id,remoteSshHost:Ne.remote_ssh_host})):await es()}}catch(xe){Y()&&!Bt(xe)&&j(xe.message)}finally{Y()&&(W(null),Te(!1),q.current=!1,Q(!1))}})(),()=>{S=!0}},[ot]);const Sr=C.useCallback(async()=>{const S=Ee();if(S===null)return;const z=++Xe.current;Ce(!1);try{if(ne==="pro"){const Y=await o.getWorkspaceInfo();if(z!==Xe.current||!le(S))return;if(Y.workspace_kind==="assistant"){B(null),E([]),ae(!1),Vt.current=0;return}const ve=Y.has_workspace?Y:null;B(ve);const xe=await o.listSessions(ve?.path,ai,0,te,{remoteConnectionId:ve?.remote_connection_id,remoteSshHost:ve?.remote_ssh_host});if(z!==Xe.current||!le(S))return;E(xe.sessions),ae(xe.has_more),Vt.current=xe.sessions.length}else{const Y=await o.listSessions(F?.path,ai,0,te);if(z!==Xe.current||!le(S))return;E(Y.sessions),ae(Y.has_more),Vt.current=Y.sessions.length}}catch{}finally{z===Xe.current&&le(S)&&(Te(!1),Ce(!1))}},[Ee,F?.path,ne,le,te,o,B,E]);C.useEffect(()=>{const S=setInterval(Sr,1e4);return()=>clearInterval(S)},[Sr]),C.useEffect(()=>{const S=ne==="assistant"?F?.path:R?.path;if(!S)return;if(bt.current===S){bt.current=void 0;return}const z=ne==="assistant"?void 0:{remoteConnectionId:R?.remote_connection_id,remoteSshHost:R?.remote_ssh_host},Y=setTimeout(()=>{Qe(S,te,z)},250);return()=>clearTimeout(Y)},[F?.path,R?.path,R?.remote_connection_id,R?.remote_ssh_host,ne,Qe,te]);const Rt=60,bs=C.useCallback(S=>{const z=wr.current;!z||z.scrollTop>0||pn||(_r.current=S.touches[0].clientY,It.current=!0)},[pn]),Ks=C.useCallback(S=>{if(!It.current)return;const z=S.touches[0].clientY-_r.current;z>0?In(Math.min(z*.5,80)):(It.current=!1,In(0))},[]),vi=C.useCallback(async()=>{if(!It.current)return;It.current=!1;const S=Ee();S!==null&&(fn>=Rt&&(yr(!0),In(Rt),await Sr(),le(S)&&yr(!1)),le(S)&&In(0))},[Ee,le,fn,Sr]),Qs=C.useCallback(S=>{const z=S.currentTarget;if(z.scrollHeight-z.scrollTop-z.clientHeight<150){const Y=ne==="assistant"?F?.path:R?.path,ve=ne==="assistant"?void 0:{remoteConnectionId:R?.remote_connection_id,remoteSshHost:R?.remote_ssh_host};Vs(Y,te,ve)}},[ne,F?.path,R?.path,R?.remote_connection_id,R?.remote_ssh_host,Vs,te]),xr=C.useCallback(async S=>{if(fe||q.current)return;const z=Ee();if(z!==null){ke(!0);try{const Y=ne==="assistant"?F?.path:R?.path,ve=ne==="assistant"?void 0:{remoteConnectionId:R?.remote_connection_id,remoteSshHost:R?.remote_ssh_host},xe=await o.createSession(S,void 0,Y,ve);if(!le(z)||(await Qe(Y,te,ve),!le(z)))return;const Ne=gf(S)?p("sessions.remoteClawSession"):mf(S)?p("sessions.remoteCoworkSession"):p("sessions.remoteCodeSession");l(xe,Ne,!0)}catch(Y){le(z)&&!Bt(Y)&&j(Y.message)}finally{le(z)&&ke(!1)}}},[fe,Ee,R?.path,R?.remote_connection_id,R?.remote_ssh_host,F?.path,ne,le,Qe,l,te,o,j,p]),ts=C.useCallback(async S=>{if(q.current)return;const z=Ee();if(z!==null)if(D(S),T(!1),S==="assistant"){const Y=await hn();if(!le(z))return;Qe(Y,te)}else R?.path?await Qe(R.path,te,{remoteConnectionId:R.remote_connection_id,remoteSshHost:R.remote_ssh_host}):await es()},[Ee,R?.path,le,hn,Qe,te,es]),qs=C.useCallback(async S=>{if(q.current)return;const z=Ee();if(z!==null)try{if(await o.setAssistant(S.path),!le(z))return;$(S),T(!1),Qe(S.path,te)}catch(Y){le(z)&&!Bt(Y)&&j(Y.message)}},[Ee,le,Qe,te,o,$,j]),Ys=R?.project_name||p("sessions.noWorkspaceSelected"),yi=F?.name||p("shared.agents.default"),Le=ne==="pro";return u.jsxs("div",{className:"session-list",children:[u.jsxs("div",{className:"session-list__header",children:[u.jsxs("div",{className:"session-list__header-brand",children:[u.jsx("img",{src:hf,alt:"BitFun",className:"session-list__logo"}),u.jsxs("div",{className:"session-list__header-copy",children:[u.jsx("h1",{children:p("shared.product.remote")}),de&&u.jsxs("span",{className:"session-list__header-account-name",children:[u.jsx("span",{className:`session-list__health-dot session-list__health-dot--${b}`,title:(()=>{switch(b){case"connected":return p("sessions.connectionConnected");case"checking":return p("sessions.connectionChecking");case"unreachable":return p("sessions.connectionUnreachable");default:return p("sessions.connectionUnpaired")}})()}),de,K&&!K.isHome&&K.deviceName&&u.jsx("span",{className:"session-list__header-target",title:p("devices.controllingDevice",{name:K.deviceName}),children:K.deviceName})]})]})]}),u.jsxs("div",{className:"session-list__header-actions",children:[f&&u.jsx("button",{className:`session-list__devices-btn ${K&&!K.isHome?"is-remote":""}`,onClick:f,title:p("devices.title"),"aria-label":p("devices.title"),children:u.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",ry:"2"}),u.jsx("line",{x1:"8",y1:"21",x2:"16",y2:"21"}),u.jsx("line",{x1:"12",y1:"17",x2:"12",y2:"21"})]})}),u.jsx(Ea,{className:"session-list__language-btn"}),u.jsx("button",{className:"session-list__theme-btn",onClick:_e,"aria-label":p("common.toggleTheme"),children:u.jsx(wg,{isDark:se})}),u.jsx("button",{className:"session-list__disconnect-btn",onClick:()=>Ht(!0),"aria-label":p("sessions.disconnect"),title:p("sessions.disconnect"),children:u.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"}),u.jsx("polyline",{points:"16 17 21 12 16 7"}),u.jsx("line",{x1:"21",y1:"12",x2:"9",y2:"12"})]})})]})]}),u.jsxs("div",{className:"session-list__items",ref:wr,onScroll:Qs,onTouchStart:bs,onTouchMove:Ks,onTouchEnd:vi,children:[(fn>0||pn)&&u.jsx("div",{className:"session-list__pull-indicator",style:{height:pn?Rt:fn},children:u.jsx("div",{className:`session-list__pull-spinner${pn||fn>=Rt?" is-active":""}`,children:u.jsx("svg",{width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",style:{transform:`rotate(${fn*4}deg)`,transition:pn?"transform 0s":void 0},children:u.jsx("path",{d:"M9 2V5M9 13V16M2 9H5M13 9H16M4.22 4.22L6.34 6.34M11.66 11.66L13.78 13.78M13.78 4.22L11.66 6.34M6.34 11.66L4.22 13.78",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})})})}),Xr&&u.jsxs("button",{type:"button",className:"session-list__resume-card",onClick:S=>vr(w[0],S),onTouchStart:S=>mr(w[0],S),onTouchMove:gr,onTouchEnd:Tn,onTouchCancel:Tn,onContextMenu:S=>{S.preventDefault(),De(w[0])},onKeyDown:S=>{(S.key==="Enter"||S.key===" ")&&(S.preventDefault(),l(w[0].session_id,w[0].name))},children:[u.jsx("div",{className:`session-list__item-icon session-list__resume-icon session-list__item-icon--${w[0].agent_type}`,children:u.jsx(Bs,{agentType:w[0].agent_type})}),u.jsxs("div",{className:"session-list__resume-body",children:[u.jsx("div",{className:"session-list__resume-label",children:p("sessions.continueSession")}),u.jsx("div",{className:"session-list__resume-name",children:w[0].name||p("sessions.untitledSession")}),u.jsxs("div",{className:"session-list__resume-meta",children:[u.jsx("span",{className:`session-list__agent-badge session-list__agent-badge--${w[0].agent_type}`,children:zd(w[0].agent_type,p)}),u.jsx("span",{className:"session-list__resume-time",children:Md(w[0].updated_at,_,p)})]})]}),u.jsx("span",{className:"session-list__resume-arrow",children:u.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("path",{d:"m9 18 6-6-6-6"})})})]}),u.jsxs("div",{className:"session-list__mode-toggle",children:[u.jsxs("button",{className:`session-list__mode-toggle-btn ${Le?"is-active":""}`,onClick:()=>ts("pro"),disabled:me,children:[u.jsx(yg,{}),u.jsx("span",{children:p("shared.modes.expert")})]}),u.jsxs("button",{className:`session-list__mode-toggle-btn ${Le?"":"is-active"}`,onClick:()=>ts("assistant"),disabled:me,children:[u.jsx(ma,{}),u.jsx("span",{children:p("shared.modes.assistant")})]})]}),Le&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"session-list__workspace-bar",onClick:()=>{q.current||(kr(),ce(!0))},children:[u.jsx("span",{className:"session-list__workspace-icon",children:u.jsx(Od,{})}),u.jsxs("div",{className:"session-list__workspace-copy",children:[u.jsx("span",{className:"session-list__workspace-label",children:p("shared.features.workspace")}),u.jsx("span",{className:"session-list__workspace-name",title:Ys,children:Ud(Ys,24)})]}),R?.git_branch&&u.jsxs("span",{className:"session-list__workspace-branch",children:[u.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("line",{x1:"6",x2:"6",y1:"3",y2:"15"}),u.jsx("circle",{cx:"18",cy:"6",r:"3"}),u.jsx("circle",{cx:"6",cy:"18",r:"3"}),u.jsx("path",{d:"M18 9a9 9 0 0 1-9 9"})]}),Ud(R.git_branch,20)]}),u.jsx("span",{className:"session-list__workspace-switch","aria-label":p("sessions.switchWorkspace"),children:u.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"m7 15 5 5 5-5"}),u.jsx("path",{d:"m7 9 5-5 5 5"})]})})]}),pe&&u.jsx("div",{className:"session-list__picker-overlay",onClick:()=>ce(!1),children:u.jsxs("div",{className:"session-list__picker-modal session-list__picker-modal--workspace",onClick:S=>S.stopPropagation(),children:[u.jsxs("div",{className:"session-list__picker-header",children:[u.jsx("h3",{children:p("sessions.selectWorkspace")}),u.jsx("button",{className:"session-list__picker-close",onClick:()=>ce(!1),children:u.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),u.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),u.jsx("div",{className:"session-list__picker-list",children:re.length===0?u.jsx("div",{className:"session-list__picker-empty",children:p("sessions.noWorkspaces")}):re.map((S,z)=>{const Y=R?.path===S.path&&(R?.remote_connection_id??void 0)===(S.remote_connection_id??void 0)&&(R?.remote_ssh_host??void 0)===(S.remote_ssh_host??void 0),ve=[S.remote_connection_id??"local",S.remote_ssh_host??"",S.path||String(z)].join(":");return u.jsxs("button",{className:`session-list__picker-item session-list__picker-item--workspace ${Y?"is-selected":""}`,onClick:()=>Jr(S),children:[u.jsx("span",{className:"session-list__picker-item-icon",children:u.jsx(Od,{})}),u.jsx("span",{className:"session-list__picker-item-name",children:S.name}),Y&&u.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("polyline",{points:"20 6 9 17 4 12"})})]},ve)})})]})})]}),!Le&&u.jsxs(u.Fragment,{children:[u.jsxs("div",{className:"session-list__assistant-bar",onClick:()=>{q.current||(hn(),T(!0))},children:[u.jsx("span",{className:"session-list__assistant-icon",children:u.jsx(ma,{})}),u.jsxs("div",{className:"session-list__assistant-copy",children:[u.jsx("span",{className:"session-list__assistant-label",children:p("sessions.assistant")}),u.jsx("span",{className:"session-list__assistant-name",children:yi})]}),u.jsx("span",{className:"session-list__assistant-switch","aria-label":p("sessions.switchAssistant"),children:u.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"m7 15 5 5 5-5"}),u.jsx("path",{d:"m7 9 5-5 5 5"})]})})]}),v&&u.jsx("div",{className:"session-list__picker-overlay",onClick:()=>T(!1),children:u.jsxs("div",{className:"session-list__picker-modal",onClick:S=>S.stopPropagation(),children:[u.jsxs("div",{className:"session-list__picker-header",children:[u.jsx("h3",{children:p("sessions.selectAssistant")}),u.jsx("button",{className:"session-list__picker-close",onClick:()=>T(!1),children:u.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),u.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),u.jsx("div",{className:"session-list__picker-list",children:O.map((S,z)=>u.jsxs("button",{className:`session-list__picker-item ${F?.path===S.path?"is-selected":""}`,onClick:()=>qs(S),children:[u.jsx("span",{className:"session-list__picker-item-icon",children:u.jsx(ma,{})}),u.jsx("span",{className:"session-list__picker-item-name",children:S.name}),F?.path===S.path&&u.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("polyline",{points:"20 6 9 17 4 12"})})]},S.path||z))})]})})]}),u.jsxs("section",{className:`session-list__panel ${Le?"":"session-list__panel--assistant"}`,children:[u.jsx("div",{className:"session-list__section-head",children:u.jsxs("div",{children:[u.jsx("div",{className:"session-list__section-kicker",children:p("sessions.launch")}),u.jsx("div",{className:"session-list__section-title",children:p("sessions.startRemoteFlow")})]})}),Le?R?u.jsxs("div",{className:"session-list__create-row",children:[u.jsxs("button",{className:"session-list__create-btn session-list__create-btn--code",onClick:()=>xr("code"),disabled:fe||me,children:[u.jsx("div",{className:"session-list__create-icon",children:u.jsx(Bs,{agentType:"code"})}),u.jsxs("div",{className:"session-list__create-copy",children:[u.jsx("span",{className:"session-list__create-title",children:p("shared.agents.code")}),u.jsx("span",{className:"session-list__create-desc",children:p("sessions.codeSessionDesc")})]}),u.jsx("span",{className:"session-list__create-arrow",children:u.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("path",{d:"m9 18 6-6-6-6"})})})]}),u.jsxs("button",{className:"session-list__create-btn session-list__create-btn--cowork",onClick:()=>xr("cowork"),disabled:fe||me,children:[u.jsx("div",{className:"session-list__create-icon",children:u.jsx(Bs,{agentType:"cowork"})}),u.jsxs("div",{className:"session-list__create-copy",children:[u.jsx("span",{className:"session-list__create-title",children:p("shared.agents.cowork")}),u.jsx("span",{className:"session-list__create-desc",children:p("sessions.coworkSessionDesc")})]}),u.jsx("span",{className:"session-list__create-arrow",children:u.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("path",{d:"m9 18 6-6-6-6"})})})]})]}):null:u.jsx("div",{className:"session-list__create-row",children:u.jsxs("button",{className:"session-list__create-btn session-list__create-btn--claw",onClick:()=>xr("claw"),disabled:fe||me,children:[u.jsx("div",{className:"session-list__create-icon",children:u.jsx(Bs,{agentType:"claw"})}),u.jsxs("div",{className:"session-list__create-copy",children:[u.jsx("span",{className:"session-list__create-title",children:p("sessions.clawSession")}),u.jsx("span",{className:"session-list__create-desc",children:p("sessions.clawSessionDesc")})]}),u.jsx("span",{className:"session-list__create-arrow",children:u.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("path",{d:"m9 18 6-6-6-6"})})})]})})]}),u.jsxs("section",{className:`session-list__panel session-list__panel--sessions ${Le?"":"session-list__panel--assistant"}`,children:[u.jsxs("div",{className:"session-list__section-head",children:[u.jsxs("div",{children:[u.jsx("div",{className:"session-list__section-kicker",children:p("sessions.recent")}),u.jsx("div",{className:"session-list__section-title",children:p("sessions.sessionHistory")})]}),u.jsx("div",{className:"session-list__section-meta",children:p("common.itemCount",{count:w.length})})]}),u.jsxs("div",{className:"session-list__search",children:[u.jsxs("svg",{className:"session-list__search-icon",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("circle",{cx:"11",cy:"11",r:"8"}),u.jsx("line",{x1:"21",y1:"21",x2:"16.65",y2:"16.65"})]}),u.jsx("input",{className:"session-list__search-input",type:"search",placeholder:p("sessions.searchSessions"),value:te,onChange:S=>ge(S.target.value),disabled:me,enterKeyHint:"search"}),te&&u.jsx("button",{className:"session-list__search-clear",onClick:()=>ge(""),"aria-label":"Clear",disabled:me,children:u.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),u.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),(Se||me)&&w.length===0&&u.jsx("div",{className:"session-list__empty",children:p("sessions.loadingSessions")}),!Se&&!me&&w.length===0&&!hr&&u.jsx("div",{className:"session-list__empty",children:p("sessions.noSessions")}),!Se&&!me&&w.length===0&&hr&&u.jsx("div",{className:"session-list__empty",children:p("sessions.emptySearch")}),u.jsx("div",{className:"session-list__cards",children:w.slice(Xr?1:0).map(S=>u.jsxs("div",{className:`session-list__item${ye?.session_id===S.session_id?" session-list__item--active":""}`,onClick:z=>vr(S,z),onTouchStart:z=>mr(S,z),onTouchMove:gr,onTouchEnd:Tn,onTouchCancel:Tn,onContextMenu:z=>{z.preventDefault(),De(S)},children:[u.jsx("div",{className:`session-list__item-icon session-list__item-icon--${S.agent_type}`,children:u.jsx(Bs,{agentType:S.agent_type})}),u.jsxs("div",{className:"session-list__item-body",children:[u.jsxs("div",{className:"session-list__item-top",children:[u.jsx("div",{className:"session-list__item-name",children:S.name||p("sessions.untitledSession")}),u.jsx("span",{className:`session-list__agent-badge session-list__agent-badge--${S.agent_type}`,children:zd(S.agent_type,p)})]}),u.jsx("div",{className:"session-list__item-time",children:Md(S.updated_at,_,p)})]})]},S.session_id))}),Me&&u.jsx("div",{className:"session-list__load-more",children:p("sessions.loadingMore")})]})]}),ye&&!ct&&!Ie&&u.jsx("div",{className:"session-list__menu-overlay",onClick:()=>De(null),children:u.jsxs("div",{className:"session-list__menu-sheet",onClick:S=>S.stopPropagation(),children:[u.jsx("div",{className:"session-list__menu-handle"}),u.jsx("div",{className:"session-list__menu-title",children:ye.name||p("sessions.untitledSession")}),u.jsxs("div",{className:"session-list__menu-actions",children:[u.jsxs("button",{className:"session-list__menu-btn",onClick:()=>{kt(ye),$e(ye.name||"")},children:[u.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"}),u.jsx("path",{d:"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"})]}),u.jsx("span",{children:p("sessions.renameSession")})]}),u.jsxs("button",{className:"session-list__menu-btn session-list__menu-btn--danger",onClick:()=>He(ye),children:[u.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("polyline",{points:"3 6 5 6 21 6"}),u.jsx("path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"})]}),u.jsx("span",{children:p("sessions.deleteSession")})]})]}),u.jsx("button",{className:"session-list__menu-cancel",onClick:()=>De(null),children:p("sessions.cancel")})]})}),ct&&u.jsx("div",{className:"session-list__picker-overlay",onClick:()=>!Ye&&kt(null),children:u.jsxs("div",{className:"session-list__rename-modal",onClick:S=>S.stopPropagation(),children:[u.jsx("h3",{className:"session-list__rename-title",children:p("sessions.renameTitle")}),u.jsx("input",{className:"session-list__rename-input",type:"text",value:ze,onChange:S=>$e(S.target.value),placeholder:p("sessions.sessionNamePlaceholder"),autoFocus:!0,onKeyDown:S=>{if((S.key==="Enter"||S.key==="Escape")&&mg(S,m.current)){S.stopPropagation();return}S.key==="Enter"&&cn(),S.key==="Escape"&&kt(null)},onCompositionStart:()=>{m.current=!0},onCompositionEnd:()=>{m.current=!1}}),u.jsxs("div",{className:"session-list__rename-actions",children:[u.jsx("button",{className:"session-list__rename-btn session-list__rename-btn--cancel",onClick:()=>kt(null),disabled:Ye,children:p("sessions.cancel")}),u.jsx("button",{className:"session-list__rename-btn session-list__rename-btn--save",onClick:cn,disabled:Ye||!ze.trim(),children:Ye?"...":p("sessions.save")})]})]})}),Ie&&u.jsx("div",{className:"session-list__picker-overlay",onClick:()=>!Ve&&He(null),onKeyDown:S=>{S.key==="Escape"&&He(null),S.key==="Enter"&&!Ve&&dn()},children:u.jsxs("div",{className:"session-list__confirm-modal",onClick:S=>S.stopPropagation(),children:[u.jsx("div",{className:"session-list__confirm-icon",children:u.jsxs("svg",{width:"28",height:"28",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("circle",{cx:"12",cy:"12",r:"10"}),u.jsx("line",{x1:"12",y1:"8",x2:"12",y2:"12"}),u.jsx("line",{x1:"12",y1:"16",x2:"12.01",y2:"16"})]})}),u.jsx("h3",{className:"session-list__confirm-title",children:p("sessions.confirmDelete")}),u.jsxs("p",{className:"session-list__confirm-desc",children:['"',Ie.name||p("sessions.untitledSession"),'"',u.jsx("br",{}),p("sessions.confirmDeleteDesc")]}),u.jsxs("div",{className:"session-list__confirm-actions",children:[u.jsx("button",{className:"session-list__confirm-btn session-list__confirm-btn--cancel",onClick:()=>He(null),disabled:Ve,children:p("sessions.cancel")}),u.jsx("button",{className:"session-list__confirm-btn session-list__confirm-btn--danger",onClick:dn,disabled:Ve,children:Ve?"...":p("sessions.deleteSession")})]})]})}),Zn&&u.jsx("div",{className:"session-list__picker-overlay",role:"alertdialog","aria-modal":"true","aria-labelledby":"disconnect-confirm-title","aria-describedby":"disconnect-confirm-desc",onClick:()=>Ht(!1),onKeyDown:S=>{S.key==="Escape"&&Ht(!1)},children:u.jsxs("div",{className:"session-list__confirm-modal",onClick:S=>S.stopPropagation(),children:[u.jsx("div",{className:"session-list__confirm-icon",children:u.jsxs("svg",{width:"28",height:"28",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"}),u.jsx("polyline",{points:"16 17 21 12 16 7"}),u.jsx("line",{x1:"21",y1:"12",x2:"9",y2:"12"})]})}),u.jsx("h3",{id:"disconnect-confirm-title",className:"session-list__confirm-title",children:p("sessions.disconnect")}),u.jsx("p",{id:"disconnect-confirm-desc",className:"session-list__confirm-desc",children:p("sessions.disconnectConfirm")}),u.jsxs("div",{className:"session-list__confirm-actions",children:[u.jsx("button",{className:"session-list__confirm-btn session-list__confirm-btn--cancel",onClick:()=>Ht(!1),autoFocus:!0,children:p("common.cancel")}),u.jsx("button",{className:"session-list__confirm-btn session-list__confirm-btn--danger",onClick:()=>{Ht(!1),d()},children:p("sessions.disconnect")})]})]})}),$t&&u.jsx("div",{className:"session-list__toast",role:"alert","aria-live":"assertive",children:$t})]})},kg=()=>u.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("path",{d:"m15 18-6-6 6-6"})}),Sg=()=>u.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}),u.jsx("path",{d:"M21 3v5h-5"}),u.jsx("path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}),u.jsx("path",{d:"M3 21v-5h5"})]}),xg=()=>u.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",ry:"2"}),u.jsx("line",{x1:"8",y1:"21",x2:"16",y2:"21"}),u.jsx("line",{x1:"12",y1:"17",x2:"12",y2:"21"})]}),Cg=()=>u.jsxs("svg",{width:"40",height:"40",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.4",strokeLinecap:"round",strokeLinejoin:"round",children:[u.jsx("circle",{cx:"12",cy:"8",r:"4"}),u.jsx("path",{d:"M6 21v-1a6 6 0 0 1 9-5.2"}),u.jsx("circle",{cx:"18",cy:"18",r:"4"}),u.jsx("path",{d:"M18 16.5v1.8l1.2 1.2"})]}),Eg=({client:o,onBack:l})=>{const{t:a,formatRelativeTime:d}=Zr(),{setControlTarget:f,resetForDeviceSwitch:m}=Wt(),[p,_]=C.useState([]),[w,E]=C.useState(o.hasDelegatedIdentity),[I,j]=C.useState(!o.hasDelegatedIdentity),[R,B]=C.useState(!1),[F,$]=C.useState(null),[W,de]=C.useState(null),b=C.useRef(!0),K=C.useRef(0),se=C.useRef(0),_e=C.useRef(0),fe=C.useMemo(()=>[...p].sort((Q,q)=>{const ee=Q.device_id===o.pairedDeviceId,ae=q.device_id===o.pairedDeviceId;return ee!==ae?ee?-1:1:Q.online!==q.online?Q.online?-1:1:(Q.device_name||Q.device_id).localeCompare(q.device_name||q.device_id)}),[o.pairedDeviceId,p]),ke=C.useCallback((Q,q)=>{const ee=String(Q?.message||Q);return ee.includes("HTTP 401")||ee.includes("No delegated identity")?a("devices.authorizationExpired"):ee.includes("HTTP 404")||ee.includes("HTTP 503")||ee.includes("HTTP 504")?a("devices.deviceUnavailable"):a(q)},[a]);C.useEffect(()=>(b.current=!0,()=>{b.current=!1,K.current+=1,se.current+=1,_e.current+=1}),[]);const Se=C.useCallback(async()=>{if(!o.hasDelegatedIdentity)return;const Q=++se.current,q=()=>b.current&&se.current===Q;try{const ee=await o.listDevices();if(!q())return;_(ee),de(null),E(!0)}catch(ee){if(!q()||_a(ee))return;String(ee?.message||ee).includes("No delegated identity")?(E(!1),_([])):de(ke(ee,"devices.loadFailed"))}},[o,ke]),Te=C.useCallback(async(Q=!1)=>{const q=++K.current;j(!0),de(null);let ee=!1;try{ee=await o.requestDelegatedIdentity({force:Q||!o.hasDelegatedIdentity})}catch(ae){ee=!1,b.current&&K.current===q&&de(ke(ae,"devices.identityFailed"))}return b.current&&K.current===q?(E(ee),j(!1),ee):!1},[o,ke]);C.useEffect(()=>{let Q;return(async()=>!await Te(!1)||!b.current||(B(!0),await Se(),b.current&&B(!1),Q=setInterval(Se,3e4)))(),()=>{Q&&clearInterval(Q)}},[Te,Se]);const Me=C.useCallback(async()=>{R||F||!await Te(!0)||(B(!0),await Se(),b.current&&B(!1))},[Te,R,Se,F]),Ce=C.useCallback(async Q=>{if(!Q.online||F||o.pairedDeviceId===Q.device_id)return;const q=++_e.current,ee=o.delegatedAccountEpoch;let ae=o.controlTargetEpoch;const ne=()=>b.current&&_e.current===q&&o.delegatedAccountEpoch===ee&&o.controlTargetEpoch===ae;$(Q.device_id),de(null);try{const D=await o.sendDeviceRpc(Q.device_id,{cmd:"host_invoke",command:"peer_mode_ping",args:{}},{retryable:!0});if(!ne())return;if(D.resp==="host_invoke_result"&&D.ok===!1)throw new Error(D.error||a("devices.switchFailed"));o.setPairedDeviceId(Q.device_id),ae=o.controlTargetEpoch,m(),f({deviceId:Q.device_id,deviceName:Q.device_name,isHome:Q.device_id===o.homeDeviceId}),l()}catch(D){if(!ne()||_a(D))return;String(D?.message||D).includes("No delegated identity")?(E(!1),_([])):de(ke(D,"devices.switchFailed"))}finally{b.current&&_e.current===q&&$(null)}},[o,ke,l,m,f,F,a]),me=()=>I?u.jsxs("div",{className:"devices-page__loading",children:[u.jsx("span",{className:"spinner"}),a("devices.loading")]}):w?R&&p.length===0?u.jsxs("div",{className:"devices-page__loading",children:[u.jsx("span",{className:"spinner"}),a("devices.loading")]}):p.length===0?u.jsx("div",{className:"devices-page__empty",children:a("devices.noDevices")}):u.jsx("div",{className:"devices-page__list",children:fe.map(Q=>{const q=o.pairedDeviceId===Q.device_id,ee=o.homeDeviceId===Q.device_id,ae=F===Q.device_id,ne=Q.online&&!q&&!F;return u.jsxs("button",{type:"button",className:["devices-page__device",Q.online?"is-online":"is-offline",q?"is-current":"",ae?"is-switching":""].filter(Boolean).join(" "),disabled:!ne,onClick:()=>ne&&Ce(Q),children:[u.jsx("span",{className:"devices-page__device-icon",children:u.jsx(xg,{})}),u.jsxs("span",{className:"devices-page__device-copy",children:[u.jsxs("span",{className:"devices-page__device-name-row",children:[u.jsx("span",{className:"devices-page__device-name",children:Q.device_name||a("devices.unknownDevice")}),q&&u.jsx("span",{className:"devices-page__badge devices-page__badge--current",children:a("devices.current")}),ee&&!q&&u.jsx("span",{className:"devices-page__badge",children:a("devices.pairedDesktop")})]}),u.jsxs("span",{className:"devices-page__device-meta",children:[u.jsx("span",{className:`devices-page__status-dot ${Q.online?"is-online":"is-offline"}`}),Q.online?a("devices.online"):Q.last_seen_at?a("devices.lastSeen",{time:d(Q.last_seen_at*1e3)}):a("devices.offline"),u.jsx("span",{className:"devices-page__device-id",children:Q.device_id.slice(0,8)})]})]}),ae?u.jsx("span",{className:"devices-page__device-spinner spinner"}):ne&&u.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:u.jsx("path",{d:"m9 18 6-6-6-6"})})]},Q.device_id)})}):u.jsxs("div",{className:"devices-page__empty-card",children:[u.jsx("span",{className:"devices-page__empty-icon",children:u.jsx(Cg,{})}),u.jsx("p",{className:"devices-page__empty-text",children:a("devices.noDelegatedIdentity")}),u.jsx("button",{type:"button",className:"devices-page__retry-btn",onClick:Me,children:a("devices.retry")})]});return u.jsxs("div",{className:"devices-page",children:[u.jsxs("div",{className:"devices-page__header",children:[u.jsx("button",{type:"button",className:"devices-page__back-btn",onClick:l,"aria-label":a("common.back"),children:u.jsx(kg,{})}),u.jsx("h2",{className:"devices-page__title",children:a("devices.title")}),u.jsx("button",{type:"button",className:`devices-page__refresh-btn ${R||I?"is-loading":""}`,onClick:Me,disabled:R||I||!!F,"aria-label":a("devices.refresh"),title:a("devices.refresh"),children:u.jsx(Sg,{})})]}),W&&u.jsx("div",{className:"devices-page__error",children:W}),u.jsx("div",{className:"devices-page__body",children:me()})]})};class Ng extends Yr.Component{constructor(l){super(l),this.state={hasError:!1,error:null}}static getDerivedStateFromError(l){return{hasError:!0,error:l}}componentDidCatch(l,a){console.error("[ErrorBoundary]",l.message,a.componentStack)}handleRetry=()=>{this.setState({hasError:!1,error:null})};render(){return this.state.hasError?u.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",padding:"32px",textAlign:"center",background:"var(--color-bg-primary)",color:"var(--color-text-primary)",fontFamily:"system-ui, sans-serif"},children:[u.jsx("div",{style:{fontSize:"48px",marginBottom:"16px"},children:"⚠"}),u.jsx("h2",{style:{fontSize:"18px",fontWeight:600,margin:"0 0 8px"},children:"Something went wrong"}),u.jsx("p",{style:{fontSize:"13px",color:"var(--color-text-muted)",margin:"0 0 24px",maxWidth:"280px"},children:this.state.error?.message||"An unexpected error occurred."}),u.jsx("button",{onClick:this.handleRetry,style:{padding:"12px 32px",border:"none",borderRadius:"14px",background:"var(--color-accent-500)",color:"var(--btn-primary-color)",fontSize:"15px",fontWeight:600,cursor:"pointer"},children:"Retry"})]}):this.props.children}}function jg(o){const l=Wt.getState(),a=o.kind==="initial"&&o.userId!==null&&l.authenticatedUserId!==null&&l.authenticatedUserId!==o.userId,d=o.kind==="replacement"||o.kind==="unavailable"||a;return d&&(l.resetForDeviceSwitch(),l.setAuthenticatedUserLabel(null)),o.kind==="unavailable"?(l.setAuthenticatedUserId(null),l.setControlTarget(null),!0):((o.userId!==null||o.kind==="replacement")&&l.setAuthenticatedUserId(o.userId),(d||l.controlTarget===null)&&l.setControlTarget(o.homeDeviceId?{deviceId:o.homeDeviceId,deviceName:null,isHome:!0}:null),d)}const Bd=15e3,Tg=1e4,Ig=250;function Rg(o,l){let a;return Promise.race([o.ping(),new Promise((d,f)=>{a=setTimeout(()=>f(new Error("ping timeout")),l)})]).finally(()=>{a&&clearTimeout(a)})}function Lg(o){const l=Wt(d=>d.setConnectionHealth),a=C.useRef();C.useEffect(()=>{let d=!1,f=0;if(!o){l("unpaired");return}const m=(E,I)=>{d||E!==f||(a.current&&clearTimeout(a.current),a.current=setTimeout(()=>{p(E)},I))},p=async E=>{if(!(d||E!==f))try{if(await Rg(o,Tg),d||E!==f)return;l("connected"),m(E,Bd)}catch(I){if(d||E!==f)return;if(Bt(I)||_a(I)){l("checking"),m(E,Ig);return}l("unreachable"),m(E,Bd)}},_=()=>{f+=1,a.current&&clearTimeout(a.current),l("checking"),p(f)},w=o.onControlTargetChange(_);return _(),()=>{d=!0,f+=1,w(),a.current&&clearTimeout(a.current)}},[o,l])}const ga=300,Pg=C.lazy(()=>hh(()=>import("./ChatPage-DseABuXP.js"),[],import.meta.url));function ui(o,l,a,d){return d?l===o?a==="push"?"nav-push-enter":"nav-pop-enter":a==="push"?"nav-push-exit":"nav-pop-exit":""}const Dg=()=>{const{t:o}=Zr(),[l,a]=C.useState("pairing"),[d,f]=C.useState(null),[m,p]=C.useState("Session"),[_,w]=C.useState(!1),E=Wt(O=>O.connectionHealth),I=C.useRef(null),j=C.useRef(null),R=C.useRef(null),[B,F]=C.useState(null);Lg(B);const[$,W]=C.useState(null),[de,b]=C.useState(null),K=C.useRef(),se=C.useRef(["pairing"]),_e=C.useRef(!1),fe=C.useCallback((O,L)=>{a(v=>(b(v),O)),W(L),clearTimeout(K.current),K.current=setTimeout(()=>{b(null),W(null)},ga),L==="push"?(se.current=[...se.current,O],_e.current||history.pushState({page:O},"")):L==="pop"&&(se.current=se.current.slice(0,-1),_e.current||history.back())},[]);C.useEffect(()=>()=>clearTimeout(K.current),[]),C.useEffect(()=>{const O=L=>{const T=L.target.closest("a");if(T&&T.href){const re=T.href;(re.startsWith("http://")||re.startsWith("https://"))&&(L.preventDefault(),L.stopPropagation(),window.open(re,"_blank","noopener,noreferrer"))}};return document.addEventListener("click",O,!0),()=>{document.removeEventListener("click",O,!0)}},[]);const ke=C.useCallback((O,L)=>{j.current?.(),I.current=O,j.current=O.onDelegatedAccountOwnerChange(v=>{I.current!==O||!jg(v)||(clearTimeout(K.current),f(null),p("Session"),w(!1),b(null),W(null),se.current=["pairing","sessions"],history.replaceState({page:"sessions"},""),a("sessions"))},{emitCurrent:!0}),R.current=L,F(L),se.current=["pairing","sessions"],history.pushState({page:"sessions"},""),a("sessions")},[]),Se=C.useCallback(()=>{fe("sessions","pop"),setTimeout(()=>f(null),ga)},[fe]),Te=C.useCallback(()=>{fe("sessions","pop")},[fe]),Me=C.useCallback(()=>{fe("sessions","pop")},[fe]);C.useEffect(()=>{const O=()=>{const L=se.current,v=L[L.length-1];if(v==="pairing"||v==="sessions"){history.pushState({page:v},"");return}_e.current=!0;try{v==="chat"?Se():v==="workspace"?Te():v==="devices"&&Me()}finally{_e.current=!1}};return window.addEventListener("popstate",O),()=>window.removeEventListener("popstate",O)},[Se,Te,Me]);const Ce=C.useCallback(()=>{fe("workspace","push")},[fe]),me=C.useCallback(()=>{fe("sessions","pop")},[fe]),Q=C.useCallback((O,L,v)=>{f(O),p(L||"Session"),w(!!v),fe("chat","push")},[fe]),q=C.useCallback(()=>{fe("sessions","pop"),setTimeout(()=>f(null),ga)},[fe]),ee=C.useCallback(()=>{j.current?.(),j.current=null,I.current?.resetConnectionIdentity(),I.current=null,R.current=null,F(null),f(null),p("Session"),w(!1),b(null),W(null),clearTimeout(K.current),localStorage.removeItem("bitfun.mobile.user_id"),Wt.getState().resetConnectionState(),se.current=["pairing"],a("pairing")},[]);C.useEffect(()=>()=>{j.current?.(),j.current=null},[]);const ae=$!==null,ne=l,D=O=>ne===O||ae&&de===O;return u.jsxs("div",{className:"mobile-app",children:[E==="unreachable"&&l!=="pairing"&&u.jsxs("div",{className:"mobile-reconnect-banner",role:"alert",children:[u.jsx("span",{className:"mobile-reconnect-spinner"}),u.jsx("span",{children:o("sessions.reconnecting")}),u.jsx("button",{type:"button",onClick:ee,children:o("sessions.repair")})]}),l==="pairing"&&u.jsx(fg,{onPaired:ke}),D("workspace")&&R.current&&u.jsx("div",{className:`nav-page ${ui("workspace",ne,$,ae)}`,children:u.jsx(pg,{sessionMgr:R.current,onReady:me})}),D("devices")&&I.current&&u.jsx("div",{className:`nav-page ${ui("devices",ne,$,ae)}`,children:u.jsx(Eg,{client:I.current,onBack:Me})}),D("sessions")&&R.current&&u.jsx("div",{className:`nav-page ${ui("sessions",ne,$,ae)}`,children:u.jsx(_g,{sessionMgr:R.current,onSelectSession:Q,onOpenWorkspace:Ce,onDisconnect:ee,onOpenDevices:()=>fe("devices","push")})}),D("chat")&&R.current&&d&&u.jsx("div",{className:`nav-page ${ui("chat",ne,$,ae)}`,children:u.jsx(C.Suspense,{fallback:u.jsx("div",{className:"spinner","aria-hidden":"true"}),children:u.jsx(Pg,{sessionMgr:R.current,sessionId:d,sessionName:m,onBack:q,autoFocus:_})})})]})},Ag=()=>u.jsx(sg,{children:u.jsx(Ng,{children:u.jsx(jh,{children:u.jsx(Dg,{})})})});dh.createRoot(document.getElementById("root")).render(u.jsx(Yr.StrictMode,{children:u.jsx(Ag,{})}));export{Yr as R,zg as S,hh as _,Wt as a,pf as b,Mg as c,hg as d,rf as e,Fd as g,Bt as i,u as j,kh as m,C as r,Zr as u}; diff --git a/src/apps/relay-server/static/assets/index-BfCWri29.js b/src/apps/relay-server/static/assets/index-BfCWri29.js new file mode 100644 index 0000000000..a0c0fe36e8 --- /dev/null +++ b/src/apps/relay-server/static/assets/index-BfCWri29.js @@ -0,0 +1,8 @@ +(function(){const l=document.createElement("link").relList;if(l&&l.supports&&l.supports("modulepreload"))return;for(const f of document.querySelectorAll('link[rel="modulepreload"]'))d(f);new MutationObserver(f=>{for(const m of f)if(m.type==="childList")for(const p of m.addedNodes)p.tagName==="LINK"&&p.rel==="modulepreload"&&d(p)}).observe(document,{childList:!0,subtree:!0});function a(f){const m={};return f.integrity&&(m.integrity=f.integrity),f.referrerPolicy&&(m.referrerPolicy=f.referrerPolicy),f.crossOrigin==="use-credentials"?m.credentials="include":f.crossOrigin==="anonymous"?m.credentials="omit":m.credentials="same-origin",m}function d(f){if(f.ep)return;f.ep=!0;const m=a(f);fetch(f.href,m)}})();const ad=Object.freeze({dark:{"color.accent.border":"color-mix(in srgb, #60a5fa 40%, transparent)","color.accent.borderSubtle":"color-mix(in srgb, #60a5fa 25%, transparent)","color.accent.default":"#60a5fa","color.accent.disabled":"rgba(96, 165, 250, 0.30)","color.accent.hover":"#3b82f6","color.accent.secondary":"#8b5cf6","color.accent.secondaryBorder":"color-mix(in srgb, #8b5cf6 25%, transparent)","color.accent.secondaryHover":"#7c6b99","color.accent.secondarySurface":"color-mix(in srgb, #8b5cf6 9%, transparent)","color.accent.secondarySurfaceStrong":"color-mix(in srgb, #8b5cf6 15%, transparent)","color.accent.surface":"color-mix(in srgb, #60a5fa 9%, transparent)","color.accent.surfaceStrong":"color-mix(in srgb, #60a5fa 15%, transparent)","color.accent.surfaceSubtle":"color-mix(in srgb, #60a5fa 5%, transparent)","color.action.neutral.border":"rgba(255, 255, 255, 0.18)","color.action.neutral.content":"#b0b0b0","color.action.neutral.contentDisabled":"#555555","color.action.neutral.fillBorder":"rgba(255, 255, 255, 0.1)","color.action.neutral.surface":"rgba(255, 255, 255, 0.1)","color.action.neutral.surfaceHover":"rgba(255, 255, 255, 0.12)","color.action.neutral.surfacePressed":"rgba(255, 255, 255, 0.15)","color.action.primary.background":"rgba(255, 255, 255, 0.16)","color.action.primary.content":"#f3f3f5","color.action.primary.hover":"rgba(255, 255, 255, 0.24)","color.action.primary.pressed":"rgba(255, 255, 255, 0.2)","color.action.quiet.content":"#b0b0b0","color.action.quiet.hover":"rgba(255, 255, 255, 0.06)","color.action.quiet.pressed":"rgba(255, 255, 255, 0.1)","color.action.secondary.background":"rgba(255, 255, 255, 0.06)","color.action.secondary.content":"#e8e8e8","color.action.secondary.hover":"rgba(255, 255, 255, 0.1)","color.action.secondary.pressed":"rgba(255, 255, 255, 0.12)","color.border.default":"rgba(255, 255, 255, 0.18)","color.border.strong":"rgba(255, 255, 255, 0.3)","color.border.subtle":"rgba(255, 255, 255, 0.12)","color.content.disabled":"#555555","color.content.inverse":"#0e0e10","color.content.muted":"#858585","color.content.onDark":"#ffffff","color.content.onLight":"#000000","color.content.primary":"#e8e8e8","color.content.secondary":"#b0b0b0","color.control.switch.thumb":"#ffffff","color.control.switch.track":"#555555","color.control.switch.trackChecked":"#34c78c","color.field.background":"#1c1c1f","color.field.backgroundHover":"rgba(255, 255, 255, 0.06)","color.field.border":"rgba(255, 255, 255, 0.18)","color.field.borderFocus":"#60a5fa","color.field.borderHover":"rgba(255, 255, 255, 0.24)","color.focus.ring":"#60a5fa","color.identity.assistant.border":"color-mix(in srgb, #ec4899 15%, transparent)","color.identity.assistant.content":"#ec4899","color.identity.assistant.contentHover":"#f472b6","color.identity.assistant.surface":"color-mix(in srgb, #ec4899 9%, transparent)","color.identity.assistant.surfaceSubtle":"color-mix(in srgb, #ec4899 5%, transparent)","color.keyHint.background":"rgba(255, 255, 255, 0.1)","color.link.default":"#60a5fa","color.link.hover":"#93c5fd","color.overlay.scrim":"rgba(0, 0, 0, 0.56)","color.scrollbar.thumb":"rgba(255, 255, 255, 0.12)","color.scrollbar.thumbHover":"rgba(255, 255, 255, 0.15)","color.status.danger.border":"rgba(239, 68, 68, 0.3)","color.status.danger.content":"#ef4444","color.status.danger.surface":"rgba(239, 68, 68, 0.1)","color.status.info.border":"rgba(255, 255, 255, 0.24)","color.status.info.content":"#a1a1aa","color.status.info.surface":"rgba(255, 255, 255, 0.08)","color.status.success.border":"rgba(52, 211, 153, 0.3)","color.status.success.content":"#34d399","color.status.success.surface":"rgba(52, 211, 153, 0.1)","color.status.warning.border":"rgba(245, 158, 11, 0.3)","color.status.warning.content":"#f59e0b","color.status.warning.surface":"rgba(245, 158, 11, 0.1)","color.surface.canvas":"#0e0e10","color.surface.chrome":"#0e0e10","color.surface.panel":"#1c1c1f","color.surface.raised":"#1c1c1f","color.surface.scene":"#1c1c1f","color.surface.subtle":"rgba(255, 255, 255, 0.06)","color.surface.tertiary":"#0e0e10","color.surface.workbench":"#0e0e10","effect.blur.base":"blur(8px) saturate(1.1)","effect.blur.medium":"blur(12px) saturate(1.2)","effect.blur.subtle":"blur(4px) saturate(1.05)","opacity.disabled":.6,"opacity.focus":.9,"opacity.hover":.8,"opacity.muted":.8,"shadow.accentGlow":"0 12px 32px color-mix(in srgb, #3b82f6 25%, transparent), 0 6px 16px color-mix(in srgb, #60a5fa 18%, transparent), 0 3px 8px rgba(0, 0, 0, 0.12)","shadow.base":"0 4px 8px rgba(0, 0, 0, 0.7)","shadow.composer":"0 2px 6px rgba(0, 0, 0, 0.32)","shadow.innerHighlight":"inset 0 1px 0 rgba(255, 255, 255, 0.08)","shadow.innerHighlightHover":"inset 0 1px 0 rgba(255, 255, 255, 0.24)","shadow.lg":"0 8px 16px rgba(0, 0, 0, 0.6)","shadow.menu":"0 4px 10px rgba(0, 0, 0, 0.48)","shadow.overlay":"0 4px 20px rgba(0, 0, 0, 0.48)","shadow.raised":"0 2px 4px rgba(0, 0, 0, 0.8)","shadow.sm":"0 2px 4px rgba(0, 0, 0, 0.8)","shadow.xl":"0 12px 24px rgba(0, 0, 0, 0.5)","shadow.xs":"0 1px 2px rgba(0, 0, 0, 0.9)"},highContrastDark:{"color.accent.border":"color-mix(in srgb, #60a5fa 40%, transparent)","color.accent.borderSubtle":"color-mix(in srgb, #60a5fa 25%, transparent)","color.accent.default":"#60a5fa","color.accent.disabled":"rgba(96, 165, 250, 0.30)","color.accent.hover":"#3b82f6","color.accent.secondary":"#8b5cf6","color.accent.secondaryBorder":"color-mix(in srgb, #8b5cf6 25%, transparent)","color.accent.secondaryHover":"#7c6b99","color.accent.secondarySurface":"color-mix(in srgb, #8b5cf6 9%, transparent)","color.accent.secondarySurfaceStrong":"color-mix(in srgb, #8b5cf6 15%, transparent)","color.accent.surface":"color-mix(in srgb, #60a5fa 9%, transparent)","color.accent.surfaceStrong":"color-mix(in srgb, #60a5fa 15%, transparent)","color.accent.surfaceSubtle":"color-mix(in srgb, #60a5fa 5%, transparent)","color.action.neutral.border":"#ffffff","color.action.neutral.content":"#ffffff","color.action.neutral.contentDisabled":"#d0d0d0","color.action.neutral.fillBorder":"#ffffff","color.action.neutral.surface":"#343434","color.action.neutral.surfaceHover":"#505050","color.action.neutral.surfacePressed":"#6b6b6b","color.action.primary.background":"#ffffff","color.action.primary.content":"#000000","color.action.primary.hover":"#e6e6e6","color.action.primary.pressed":"#ffffff","color.action.quiet.content":"#b0b0b0","color.action.quiet.hover":"rgba(255, 255, 255, 0.06)","color.action.quiet.pressed":"rgba(255, 255, 255, 0.1)","color.action.secondary.background":"rgba(255, 255, 255, 0.06)","color.action.secondary.content":"#e8e8e8","color.action.secondary.hover":"rgba(255, 255, 255, 0.1)","color.action.secondary.pressed":"rgba(255, 255, 255, 0.12)","color.border.default":"#b5b5b5","color.border.strong":"#ffffff","color.border.subtle":"#8a8a8a","color.content.disabled":"#555555","color.content.inverse":"#0e0e10","color.content.muted":"#d0d0d0","color.content.onDark":"#ffffff","color.content.onLight":"#000000","color.content.primary":"#ffffff","color.content.secondary":"#f0f0f0","color.control.switch.thumb":"#000000","color.control.switch.track":"#b5b5b5","color.control.switch.trackChecked":"#ffcc00","color.field.background":"#1c1c1f","color.field.backgroundHover":"rgba(255, 255, 255, 0.06)","color.field.border":"#b5b5b5","color.field.borderFocus":"#ffcc00","color.field.borderHover":"#ffffff","color.focus.ring":"#ffcc00","color.identity.assistant.border":"color-mix(in srgb, #ec4899 15%, transparent)","color.identity.assistant.content":"#ec4899","color.identity.assistant.contentHover":"#f472b6","color.identity.assistant.surface":"color-mix(in srgb, #ec4899 9%, transparent)","color.identity.assistant.surfaceSubtle":"color-mix(in srgb, #ec4899 5%, transparent)","color.keyHint.background":"#343434","color.link.default":"#60a5fa","color.link.hover":"#93c5fd","color.overlay.scrim":"rgba(0, 0, 0, 0.56)","color.scrollbar.thumb":"#505050","color.scrollbar.thumbHover":"#6b6b6b","color.status.danger.border":"rgba(239, 68, 68, 0.3)","color.status.danger.content":"#ef4444","color.status.danger.surface":"rgba(239, 68, 68, 0.1)","color.status.info.border":"rgba(255, 255, 255, 0.24)","color.status.info.content":"#a1a1aa","color.status.info.surface":"rgba(255, 255, 255, 0.08)","color.status.success.border":"rgba(52, 211, 153, 0.3)","color.status.success.content":"#34d399","color.status.success.surface":"rgba(52, 211, 153, 0.1)","color.status.warning.border":"rgba(245, 158, 11, 0.3)","color.status.warning.content":"#f59e0b","color.status.warning.surface":"rgba(245, 158, 11, 0.1)","color.surface.canvas":"#000000","color.surface.chrome":"#000000","color.surface.panel":"#090909","color.surface.raised":"#1c1c1f","color.surface.scene":"#090909","color.surface.subtle":"rgba(255, 255, 255, 0.06)","color.surface.tertiary":"#000000","color.surface.workbench":"#000000","effect.blur.base":"blur(8px) saturate(1.1)","effect.blur.medium":"blur(12px) saturate(1.2)","effect.blur.subtle":"blur(4px) saturate(1.05)","opacity.disabled":.6,"opacity.focus":.9,"opacity.hover":.8,"opacity.muted":.8,"shadow.accentGlow":"0 12px 32px color-mix(in srgb, #3b82f6 25%, transparent), 0 6px 16px color-mix(in srgb, #60a5fa 18%, transparent), 0 3px 8px rgba(0, 0, 0, 0.12)","shadow.base":"0 4px 8px rgba(0, 0, 0, 0.7)","shadow.composer":"0 2px 6px rgba(0, 0, 0, 0.32)","shadow.innerHighlight":"inset 0 1px 0 rgba(255, 255, 255, 0.08)","shadow.innerHighlightHover":"inset 0 1px 0 rgba(255, 255, 255, 0.24)","shadow.lg":"0 8px 16px rgba(0, 0, 0, 0.6)","shadow.menu":"0 4px 10px rgba(0, 0, 0, 0.48)","shadow.overlay":"0 4px 20px rgba(0, 0, 0, 0.48)","shadow.raised":"0 2px 4px rgba(0, 0, 0, 0.8)","shadow.sm":"0 2px 4px rgba(0, 0, 0, 0.8)","shadow.xl":"0 12px 24px rgba(0, 0, 0, 0.5)","shadow.xs":"0 1px 2px rgba(0, 0, 0, 0.9)"},highContrastLight:{"color.accent.border":"color-mix(in srgb, #059cb0 40%, transparent)","color.accent.borderSubtle":"color-mix(in srgb, #059cb0 25%, transparent)","color.accent.default":"#059cb0","color.accent.disabled":"rgba(5, 156, 176, 0.30)","color.accent.hover":"#059cb0","color.accent.secondary":"#7c6b99","color.accent.secondaryBorder":"color-mix(in srgb, #7c6b99 25%, transparent)","color.accent.secondaryHover":"#655680","color.accent.secondarySurface":"color-mix(in srgb, #7c6b99 9%, transparent)","color.accent.secondarySurfaceStrong":"color-mix(in srgb, #7c6b99 15%, transparent)","color.accent.surface":"color-mix(in srgb, #059cb0 9%, transparent)","color.accent.surfaceStrong":"color-mix(in srgb, #059cb0 15%, transparent)","color.accent.surfaceSubtle":"color-mix(in srgb, #059cb0 5%, transparent)","color.action.neutral.border":"#000000","color.action.neutral.content":"#000000","color.action.neutral.contentDisabled":"#343434","color.action.neutral.fillBorder":"#000000","color.action.neutral.surface":"#e6e6e6","color.action.neutral.surfaceHover":"#cccccc","color.action.neutral.surfacePressed":"#b3b3b3","color.action.primary.background":"#000000","color.action.primary.content":"#ffffff","color.action.primary.hover":"#262626","color.action.primary.pressed":"#000000","color.action.quiet.content":"#555555","color.action.quiet.hover":"#f3f3f5","color.action.quiet.pressed":"rgba(16, 26, 39, 0.09)","color.action.secondary.background":"#f3f3f5","color.action.secondary.content":"#1c1c1f","color.action.secondary.hover":"rgba(16, 26, 39, 0.09)","color.action.secondary.pressed":"rgba(16, 26, 39, 0.13)","color.border.default":"#3b3b3b","color.border.strong":"#000000","color.border.subtle":"#707070","color.content.disabled":"#9a9a9a","color.content.inverse":"#ffffff","color.content.muted":"#343434","color.content.onDark":"#ffffff","color.content.onLight":"#000000","color.content.primary":"#000000","color.content.secondary":"#161616","color.control.switch.thumb":"#ffffff","color.control.switch.track":"#3b3b3b","color.control.switch.trackChecked":"#005fcc","color.field.background":"#ffffff","color.field.backgroundHover":"#ffffff","color.field.border":"#3b3b3b","color.field.borderFocus":"#005fcc","color.field.borderHover":"#000000","color.focus.ring":"#005fcc","color.identity.assistant.border":"color-mix(in srgb, #db2777 15%, transparent)","color.identity.assistant.content":"#db2777","color.identity.assistant.contentHover":"#be185d","color.identity.assistant.surface":"color-mix(in srgb, #db2777 9%, transparent)","color.identity.assistant.surfaceSubtle":"color-mix(in srgb, #db2777 5%, transparent)","color.keyHint.background":"#e6e6e6","color.link.default":"#2563eb","color.link.hover":"#005fcc","color.overlay.scrim":"rgba(16, 26, 39, 0.20)","color.scrollbar.thumb":"#cccccc","color.scrollbar.thumbHover":"#b3b3b3","color.status.danger.border":"rgba(167, 67, 82, 0.36)","color.status.danger.content":"#a74352","color.status.danger.surface":"rgba(167, 67, 82, 0.12)","color.status.info.border":"rgba(16, 26, 39, 0.15)","color.status.info.content":"#555555","color.status.info.surface":"#f3f3f5","color.status.success.border":"#247344","color.status.success.content":"#247344","color.status.success.surface":"#e1fbe9","color.status.warning.border":"rgba(154, 101, 31, 0.25)","color.status.warning.content":"#75501d","color.status.warning.surface":"rgba(154, 101, 31, 0.04)","color.surface.canvas":"#ffffff","color.surface.chrome":"#ffffff","color.surface.panel":"#ffffff","color.surface.raised":"#ffffff","color.surface.scene":"#ffffff","color.surface.subtle":"rgba(16, 26, 39, 0.03)","color.surface.tertiary":"#f3f3f5","color.surface.workbench":"#f3f3f5","effect.blur.base":"blur(8px) saturate(1.05)","effect.blur.medium":"blur(12px) saturate(1.2)","effect.blur.subtle":"blur(4px) saturate(1.02)","opacity.disabled":.55,"opacity.focus":.9,"opacity.hover":.75,"opacity.muted":.75,"shadow.accentGlow":"0 12px 32px color-mix(in srgb, #059cb0 25%, transparent), 0 6px 16px color-mix(in srgb, #059cb0 18%, transparent), 0 3px 8px rgba(0, 0, 0, 0.12)","shadow.base":"0 4px 8px rgba(16, 26, 39, 0.07)","shadow.composer":"0 2px 6px rgba(0, 0, 0, 0.08)","shadow.innerHighlight":"inset 0 1px 0 rgba(255, 255, 255, 0.08)","shadow.innerHighlightHover":"inset 0 1px 0 rgba(255, 255, 255, 0.24)","shadow.lg":"0 8px 16px rgba(16, 26, 39, 0.09)","shadow.menu":"0 4px 10px rgba(0, 0, 0, 0.12)","shadow.overlay":"0 4px 20px rgba(0, 0, 0, 0.12)","shadow.raised":"0 2px 4px rgba(16, 26, 39, 0.055)","shadow.sm":"0 2px 4px rgba(16, 26, 39, 0.055)","shadow.xl":"0 12px 24px rgba(16, 26, 39, 0.11)","shadow.xs":"0 1px 2px rgba(16, 26, 39, 0.04)"},light:{"color.accent.border":"color-mix(in srgb, #059cb0 40%, transparent)","color.accent.borderSubtle":"color-mix(in srgb, #059cb0 25%, transparent)","color.accent.default":"#059cb0","color.accent.disabled":"rgba(5, 156, 176, 0.30)","color.accent.hover":"#059cb0","color.accent.secondary":"#7c6b99","color.accent.secondaryBorder":"color-mix(in srgb, #7c6b99 25%, transparent)","color.accent.secondaryHover":"#655680","color.accent.secondarySurface":"color-mix(in srgb, #7c6b99 9%, transparent)","color.accent.secondarySurfaceStrong":"color-mix(in srgb, #7c6b99 15%, transparent)","color.accent.surface":"color-mix(in srgb, #059cb0 9%, transparent)","color.accent.surfaceStrong":"color-mix(in srgb, #059cb0 15%, transparent)","color.accent.surfaceSubtle":"color-mix(in srgb, #059cb0 5%, transparent)","color.action.neutral.border":"rgba(0, 0, 0, 0.05)","color.action.neutral.content":"rgba(0, 0, 0, 0.80)","color.action.neutral.contentDisabled":"rgba(0, 0, 0, 0.30)","color.action.neutral.fillBorder":"rgba(0, 0, 0, 0.05)","color.action.neutral.surface":"rgba(0, 0, 0, 0.05)","color.action.neutral.surfaceHover":"rgba(0, 0, 0, 0.10)","color.action.neutral.surfacePressed":"rgba(0, 0, 0, 0.10)","color.action.primary.background":"#101a27","color.action.primary.content":"#ffffff","color.action.primary.hover":"#1c1c1f","color.action.primary.pressed":"#000000","color.action.quiet.content":"#555555","color.action.quiet.hover":"#f3f3f5","color.action.quiet.pressed":"rgba(16, 26, 39, 0.09)","color.action.secondary.background":"#f3f3f5","color.action.secondary.content":"#1c1c1f","color.action.secondary.hover":"rgba(16, 26, 39, 0.09)","color.action.secondary.pressed":"rgba(16, 26, 39, 0.13)","color.border.default":"rgba(16, 26, 39, 0.15)","color.border.strong":"rgba(16, 26, 39, 0.34)","color.border.subtle":"rgba(16, 26, 39, 0.08)","color.content.disabled":"#9a9a9a","color.content.inverse":"#ffffff","color.content.muted":"#6a6a6a","color.content.onDark":"#ffffff","color.content.onLight":"#000000","color.content.primary":"#1c1c1f","color.content.secondary":"#555555","color.control.switch.thumb":"#ffffff","color.control.switch.track":"#dddddd","color.control.switch.trackChecked":"#34c78c","color.field.background":"#ffffff","color.field.backgroundHover":"#ffffff","color.field.border":"rgba(16, 26, 39, 0.15)","color.field.borderFocus":"#101a27","color.field.borderHover":"rgba(16, 26, 39, 0.24)","color.focus.ring":"#6a6a6a","color.identity.assistant.border":"color-mix(in srgb, #db2777 15%, transparent)","color.identity.assistant.content":"#db2777","color.identity.assistant.contentHover":"#be185d","color.identity.assistant.surface":"color-mix(in srgb, #db2777 9%, transparent)","color.identity.assistant.surfaceSubtle":"color-mix(in srgb, #db2777 5%, transparent)","color.keyHint.background":"rgba(0, 0, 0, 0.05)","color.link.default":"#2563eb","color.link.hover":"#005fcc","color.overlay.scrim":"rgba(16, 26, 39, 0.20)","color.scrollbar.thumb":"rgba(0, 0, 0, 0.10)","color.scrollbar.thumbHover":"rgba(0, 0, 0, 0.10)","color.status.danger.border":"rgba(167, 67, 82, 0.36)","color.status.danger.content":"#a74352","color.status.danger.surface":"rgba(167, 67, 82, 0.12)","color.status.info.border":"rgba(16, 26, 39, 0.15)","color.status.info.content":"#555555","color.status.info.surface":"#f3f3f5","color.status.success.border":"#247344","color.status.success.content":"#247344","color.status.success.surface":"#e1fbe9","color.status.warning.border":"rgba(154, 101, 31, 0.25)","color.status.warning.content":"#75501d","color.status.warning.surface":"rgba(154, 101, 31, 0.08)","color.surface.canvas":"#fdfdfd","color.surface.chrome":"#fdfdfd","color.surface.panel":"#ffffff","color.surface.raised":"#ffffff","color.surface.scene":"#ffffff","color.surface.subtle":"rgba(16, 26, 39, 0.03)","color.surface.tertiary":"#f3f3f5","color.surface.workbench":"#f3f3f5","effect.blur.base":"blur(8px) saturate(1.05)","effect.blur.medium":"blur(12px) saturate(1.2)","effect.blur.subtle":"blur(4px) saturate(1.02)","opacity.disabled":.55,"opacity.focus":.9,"opacity.hover":.75,"opacity.muted":.75,"shadow.accentGlow":"0 12px 32px color-mix(in srgb, #059cb0 25%, transparent), 0 6px 16px color-mix(in srgb, #059cb0 18%, transparent), 0 3px 8px rgba(0, 0, 0, 0.12)","shadow.base":"0 4px 8px rgba(16, 26, 39, 0.07)","shadow.composer":"0 2px 6px rgba(0, 0, 0, 0.08)","shadow.innerHighlight":"inset 0 1px 0 rgba(255, 255, 255, 0.08)","shadow.innerHighlightHover":"inset 0 1px 0 rgba(255, 255, 255, 0.24)","shadow.lg":"0 8px 16px rgba(16, 26, 39, 0.09)","shadow.menu":"0 4px 10px rgba(0, 0, 0, 0.12)","shadow.overlay":"0 4px 20px rgba(0, 0, 0, 0.12)","shadow.raised":"0 2px 4px rgba(16, 26, 39, 0.055)","shadow.sm":"0 2px 4px rgba(16, 26, 39, 0.055)","shadow.xl":"0 12px 24px rgba(16, 26, 39, 0.11)","shadow.xs":"0 1px 2px rgba(16, 26, 39, 0.04)"}});let Ao="dark";try{const i=localStorage.getItem("bitfun-mobile-theme");(i==="dark"||i==="light")&&(Ao=i)}catch{window.matchMedia?.("(prefers-color-scheme: light)").matches&&(Ao="light")}const Mo=document.documentElement;Mo.setAttribute("data-bf-design-system-root","");Mo.setAttribute("data-color-scheme",Ao);Mo.setAttribute("data-contrast","standard");Mo.setAttribute("data-density","comfortable");Mo.style.colorScheme=Ao;const wp=document.querySelector('meta[name="theme-color"]');wp?.setAttribute("content",String(ad[Ao]["color.surface.canvas"]));var Nm=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function cd(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var Wl={exports:{}},Lo={},Hl={exports:{}},ve={};var Ru;function _p(){if(Ru)return ve;Ru=1;var i=Symbol.for("react.element"),l=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),d=Symbol.for("react.strict_mode"),f=Symbol.for("react.profiler"),m=Symbol.for("react.provider"),p=Symbol.for("react.context"),_=Symbol.for("react.forward_ref"),w=Symbol.for("react.suspense"),E=Symbol.for("react.memo"),T=Symbol.for("react.lazy"),N=Symbol.iterator;function L(y){return y===null||typeof y!="object"?null:(y=N&&y[N]||y["@@iterator"],typeof y=="function"?y:null)}var O={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},B=Object.assign,W={};function F(y,I,ne){this.props=y,this.context=I,this.refs=W,this.updater=ne||O}F.prototype.isReactComponent={},F.prototype.setState=function(y,I){if(typeof y!="object"&&typeof y!="function"&&y!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,y,I,"setState")},F.prototype.forceUpdate=function(y){this.updater.enqueueForceUpdate(this,y,"forceUpdate")};function ue(){}ue.prototype=F.prototype;function V(y,I,ne){this.props=y,this.context=I,this.refs=W,this.updater=ne||O}var $=V.prototype=new ue;$.constructor=V,B($,F.prototype),$.isPureReactComponent=!0;var re=Array.isArray,we=Object.prototype.hasOwnProperty,de={current:null},_e={key:!0,ref:!0,__self:!0,__source:!0};function ke(y,I,ne){var ae,fe={},ce=null,ee=null;if(I!=null)for(ae in I.ref!==void 0&&(ee=I.ref),I.key!==void 0&&(ce=""+I.key),I)we.call(I,ae)&&!_e.hasOwnProperty(ae)&&(fe[ae]=I[ae]);var me=arguments.length-2;if(me===1)fe.children=ne;else if(1>>1,I=P[y];if(0>>1;yf(fe,D))cef(ee,fe)?(P[y]=ee,P[ce]=D,y=ce):(P[y]=fe,P[ae]=D,y=ae);else if(cef(ee,D))P[y]=ee,P[ce]=D,y=ce;else break e}}return U}function f(P,U){var D=P.sortIndex-U.sortIndex;return D!==0?D:P.id-U.id}if(typeof performance=="object"&&typeof performance.now=="function"){var m=performance;i.unstable_now=function(){return m.now()}}else{var p=Date,_=p.now();i.unstable_now=function(){return p.now()-_}}var w=[],E=[],T=1,N=null,L=3,O=!1,B=!1,W=!1,F=typeof setTimeout=="function"?setTimeout:null,ue=typeof clearTimeout=="function"?clearTimeout:null,V=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function $(P){for(var U=a(E);U!==null;){if(U.callback===null)d(E);else if(U.startTime<=P)d(E),U.sortIndex=U.expirationTime,l(w,U);else break;U=a(E)}}function re(P){if(W=!1,$(P),!B)if(a(w)!==null)B=!0,le(we);else{var U=a(E);U!==null&&te(re,U.startTime-P)}}function we(P,U){B=!1,W&&(W=!1,ue(ke),ke=-1),O=!0;var D=L;try{for($(U),N=a(w);N!==null&&(!(N.expirationTime>U)||P&&!Se());){var y=N.callback;if(typeof y=="function"){N.callback=null,L=N.priorityLevel;var I=y(N.expirationTime<=U);U=i.unstable_now(),typeof I=="function"?N.callback=I:N===a(w)&&d(w),$(U)}else d(w);N=a(w)}if(N!==null)var ne=!0;else{var ae=a(E);ae!==null&&te(re,ae.startTime-U),ne=!1}return ne}finally{N=null,L=D,O=!1}}var de=!1,_e=null,ke=-1,Ne=5,be=-1;function Se(){return!(i.unstable_now()-beP||125y?(P.sortIndex=D,l(E,P),a(w)===null&&P===a(E)&&(W?(ue(ke),ke=-1):W=!0,te(re,D-y))):(P.sortIndex=I,l(w,P),B||O||(B=!0,le(we))),P},i.unstable_shouldYield=Se,i.unstable_wrapCallback=function(P){var U=L;return function(){var D=L;L=U;try{return P.apply(this,arguments)}finally{L=D}}}})(Kl)),Kl}var zu;function Cp(){return zu||(zu=1,$l.exports=Sp()),$l.exports}var Uu;function Ep(){if(Uu)return yt;Uu=1;var i=ra(),l=Cp();function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),w=Object.prototype.hasOwnProperty,E=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,T={},N={};function L(e){return w.call(N,e)?!0:w.call(T,e)?!1:E.test(e)?N[e]=!0:(T[e]=!0,!1)}function O(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function B(e,t,n,r){if(t===null||typeof t>"u"||O(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function W(e,t,n,r,o,s,u){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=o,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=s,this.removeEmptyString=u}var F={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){F[e]=new W(e,0,!1,e,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];F[t]=new W(t,1,!1,e[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(e){F[e]=new W(e,2,!1,e.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){F[e]=new W(e,2,!1,e,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){F[e]=new W(e,3,!1,e.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(e){F[e]=new W(e,3,!0,e,null,!1,!1)}),["capture","download"].forEach(function(e){F[e]=new W(e,4,!1,e,null,!1,!1)}),["cols","rows","size","span"].forEach(function(e){F[e]=new W(e,6,!1,e,null,!1,!1)}),["rowSpan","start"].forEach(function(e){F[e]=new W(e,5,!1,e.toLowerCase(),null,!1,!1)});var ue=/[\-:]([a-z])/g;function V(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(ue,V);F[t]=new W(t,1,!1,e,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(ue,V);F[t]=new W(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(ue,V);F[t]=new W(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(e){F[e]=new W(e,1,!1,e.toLowerCase(),null,!1,!1)}),F.xlinkHref=new W("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(e){F[e]=new W(e,1,!1,e.toLowerCase(),null,!0,!0)});function $(e,t,n,r){var o=F.hasOwnProperty(t)?F[t]:null;(o!==null?o.type!==0:r||!(2h||o[u]!==s[h]){var g=` +`+o[u].replace(" at new "," at ");return e.displayName&&g.includes("")&&(g=g.replace("",e.displayName)),g}while(1<=u&&0<=h);break}}}finally{ne=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?I(e):""}function fe(e){switch(e.tag){case 5:return I(e.type);case 16:return I("Lazy");case 13:return I("Suspense");case 19:return I("SuspenseList");case 0:case 2:case 15:return e=ae(e.type,!1),e;case 11:return e=ae(e.type.render,!1),e;case 1:return e=ae(e.type,!0),e;default:return""}}function ce(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case _e:return"Fragment";case de:return"Portal";case Ne:return"Profiler";case ke:return"StrictMode";case K:return"Suspense";case q:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Se:return(e.displayName||"Context")+".Consumer";case be:return(e._context.displayName||"Context")+".Provider";case he:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case J:return t=e.displayName||null,t!==null?t:ce(e.type)||"Memo";case le:t=e._payload,e=e._init;try{return ce(e(t))}catch{}}return null}function ee(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return ce(t);case 8:return t===ke?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function me(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function ye(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function Re(e){var t=ye(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var o=n.get,s=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return o.call(this)},set:function(u){r=""+u,s.call(this,u)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(u){r=""+u},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function ct(e){e._valueTracker||(e._valueTracker=Re(e))}function wt(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=ye(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function Ae(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Fe(e,t){var n=t.checked;return D({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function Ie(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=me(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function We(e,t){t=t.checked,t!=null&&$(e,"checked",t,!1)}function He(e,t){We(e,t);var n=me(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?Qe(e,t.type,n):t.hasOwnProperty("defaultValue")&&Qe(e,t.type,me(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function Et(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function Qe(e,t,n){(t!=="number"||Ae(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var tt=Array.isArray;function Ot(e,t,n,r){if(e=e.options,t){t={};for(var o=0;o"+t.valueOf().toString()+"",t=_t.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function jt(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var Ce={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},ie=["Webkit","ms","Moz","O"];Object.keys(Ce).forEach(function(e){ie.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),Ce[t]=Ce[e]})});function ur(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||Ce.hasOwnProperty(e)&&Ce[e]?(""+t).trim():t+"px"}function Kr(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,o=ur(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,o):e[n]=o}}var Qn=D({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function dr(e,t){if(t){if(Qn[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(a(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(a(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(a(61))}if(t.style!=null&&typeof t.style!="object")throw Error(a(62))}}function fr(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var En=null;function pr(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var sn=null,ln=null,an=null;function cn(e){if(e=mo(e)){if(typeof sn!="function")throw Error(a(280));var t=e.stateNode;t&&(t=as(t),sn(e.stateNode,e.type,t))}}function jn(e){ln?an?an.push(e):an=[e]:ln=e}function un(){if(ln){var e=ln,t=an;if(an=ln=null,cn(e),t)for(e=0;e>>=0,e===0?32:31-(bd(e)/Ad|0)|0}var Vo=64,$o=4194304;function Gr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function Ko(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,o=e.suspendedLanes,s=e.pingedLanes,u=n&268435455;if(u!==0){var h=u&~o;h!==0?r=Gr(h):(s&=u,s!==0&&(r=Gr(s)))}else u=n&~o,u!==0?r=Gr(u):s!==0&&(r=Gr(s));if(r===0)return 0;if(t!==0&&t!==r&&(t&o)===0&&(o=r&-r,s=t&-t,o>=s||o===16&&(s&4194240)!==0))return t;if((r&4)!==0&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Zr(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-Ht(t),e[t]=n}function Od(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=so),Ea=" ",ja=!1;function Na(e,t){switch(e){case"keyup":return hf.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Ia(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var xr=!1;function gf(e,t){switch(e){case"compositionend":return Ia(t);case"keypress":return t.which!==32?null:(ja=!0,Ea);case"textInput":return e=t.data,e===Ea&&ja?null:e;default:return null}}function yf(e,t){if(xr)return e==="compositionend"||!xi&&Na(e,t)?(e=wa(),Zo=gi=Dn=null,xr=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=Aa(n)}}function za(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?za(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ua(){for(var e=window,t=Ae();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=Ae(e.document)}return t}function Ei(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function jf(e){var t=Ua(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&za(n.ownerDocument.documentElement,n)){if(r!==null&&Ei(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var o=n.textContent.length,s=Math.min(r.start,o);r=r.end===void 0?s:Math.min(r.end,o),!e.extend&&s>r&&(o=r,r=s,s=o),o=Ma(n,s);var u=Ma(n,r);o&&u&&(e.rangeCount!==1||e.anchorNode!==o.node||e.anchorOffset!==o.offset||e.focusNode!==u.node||e.focusOffset!==u.offset)&&(t=t.createRange(),t.setStart(o.node,o.offset),e.removeAllRanges(),s>r?(e.addRange(t),e.extend(u.node,u.offset)):(t.setEnd(u.node,u.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,Sr=null,ji=null,co=null,Ni=!1;function Oa(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Ni||Sr==null||Sr!==Ae(r)||(r=Sr,"selectionStart"in r&&Ei(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),co&&ao(co,r)||(co=r,r=ss(ji,"onSelect"),0Ir||(e.current=Oi[Ir],Oi[Ir]=null,Ir--)}function Pe(e,t){Ir++,Oi[Ir]=e.current,e.current=t}var An={},st=bn(An),ft=bn(!1),Gn=An;function Tr(e,t){var n=e.type.contextTypes;if(!n)return An;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var o={},s;for(s in n)o[s]=t[s];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=o),o}function pt(e){return e=e.childContextTypes,e!=null}function cs(){ze(ft),ze(st)}function ec(e,t,n){if(st.current!==An)throw Error(a(168));Pe(st,t),Pe(ft,n)}function tc(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var o in r)if(!(o in t))throw Error(a(108,ee(e)||"Unknown",o));return D({},n,r)}function us(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||An,Gn=st.current,Pe(st,e),Pe(ft,ft.current),!0}function nc(e,t,n){var r=e.stateNode;if(!r)throw Error(a(169));n?(e=tc(e,t,Gn),r.__reactInternalMemoizedMergedChildContext=e,ze(ft),ze(st),Pe(st,e)):ze(ft),Pe(ft,n)}var pn=null,ds=!1,Bi=!1;function rc(e){pn===null?pn=[e]:pn.push(e)}function Uf(e){ds=!0,rc(e)}function Mn(){if(!Bi&&pn!==null){Bi=!0;var e=0,t=De;try{var n=pn;for(De=1;e>=u,o-=u,hn=1<<32-Ht(t)+o|n<pe?(et=se,se=null):et=se.sibling;var Te=R(k,se,S[pe],z);if(Te===null){se===null&&(se=et);break}e&&se&&Te.alternate===null&&t(k,se),v=s(Te,v,pe),oe===null?X=Te:oe.sibling=Te,oe=Te,se=et}if(pe===S.length)return n(k,se),Ue&&Xn(k,pe),X;if(se===null){for(;pepe?(et=se,se=null):et=se.sibling;var $n=R(k,se,Te.value,z);if($n===null){se===null&&(se=et);break}e&&se&&$n.alternate===null&&t(k,se),v=s($n,v,pe),oe===null?X=$n:oe.sibling=$n,oe=$n,se=et}if(Te.done)return n(k,se),Ue&&Xn(k,pe),X;if(se===null){for(;!Te.done;pe++,Te=S.next())Te=A(k,Te.value,z),Te!==null&&(v=s(Te,v,pe),oe===null?X=Te:oe.sibling=Te,oe=Te);return Ue&&Xn(k,pe),X}for(se=r(k,se);!Te.done;pe++,Te=S.next())Te=H(se,k,pe,Te.value,z),Te!==null&&(e&&Te.alternate!==null&&se.delete(Te.key===null?pe:Te.key),v=s(Te,v,pe),oe===null?X=Te:oe.sibling=Te,oe=Te);return e&&se.forEach(function(vp){return t(k,vp)}),Ue&&Xn(k,pe),X}function $e(k,v,S,z){if(typeof S=="object"&&S!==null&&S.type===_e&&S.key===null&&(S=S.props.children),typeof S=="object"&&S!==null){switch(S.$$typeof){case we:e:{for(var X=S.key,oe=v;oe!==null;){if(oe.key===X){if(X=S.type,X===_e){if(oe.tag===7){n(k,oe.sibling),v=o(oe,S.props.children),v.return=k,k=v;break e}}else if(oe.elementType===X||typeof X=="object"&&X!==null&&X.$$typeof===le&&cc(X)===oe.type){n(k,oe.sibling),v=o(oe,S.props),v.ref=go(k,oe,S),v.return=k,k=v;break e}n(k,oe);break}else t(k,oe);oe=oe.sibling}S.type===_e?(v=ir(S.props.children,k.mode,z,S.key),v.return=k,k=v):(z=Os(S.type,S.key,S.props,null,k.mode,z),z.ref=go(k,v,S),z.return=k,k=z)}return u(k);case de:e:{for(oe=S.key;v!==null;){if(v.key===oe)if(v.tag===4&&v.stateNode.containerInfo===S.containerInfo&&v.stateNode.implementation===S.implementation){n(k,v.sibling),v=o(v,S.children||[]),v.return=k,k=v;break e}else{n(k,v);break}else t(k,v);v=v.sibling}v=zl(S,k.mode,z),v.return=k,k=v}return u(k);case le:return oe=S._init,$e(k,v,oe(S._payload),z)}if(tt(S))return G(k,v,S,z);if(U(S))return Z(k,v,S,z);ms(k,S)}return typeof S=="string"&&S!==""||typeof S=="number"?(S=""+S,v!==null&&v.tag===6?(n(k,v.sibling),v=o(v,S),v.return=k,k=v):(n(k,v),v=Ml(S,k.mode,z),v.return=k,k=v),u(k)):n(k,v)}return $e}var Pr=uc(!0),dc=uc(!1),gs=bn(null),ys=null,br=null,Ki=null;function qi(){Ki=br=ys=null}function Qi(e){var t=gs.current;ze(gs),e._currentValue=t}function Yi(e,t,n){for(;e!==null;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,r!==null&&(r.childLanes|=t)):r!==null&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function Ar(e,t){ys=e,Ki=br=null,e=e.dependencies,e!==null&&e.firstContext!==null&&((e.lanes&t)!==0&&(ht=!0),e.firstContext=null)}function Rt(e){var t=e._currentValue;if(Ki!==e)if(e={context:e,memoizedValue:t,next:null},br===null){if(ys===null)throw Error(a(308));br=e,ys.dependencies={lanes:0,firstContext:e}}else br=br.next=e;return t}var Jn=null;function Gi(e){Jn===null?Jn=[e]:Jn.push(e)}function fc(e,t,n,r){var o=t.interleaved;return o===null?(n.next=n,Gi(t)):(n.next=o.next,o.next=n),t.interleaved=n,gn(e,r)}function gn(e,t){e.lanes|=t;var n=e.alternate;for(n!==null&&(n.lanes|=t),n=e,e=e.return;e!==null;)e.childLanes|=t,n=e.alternate,n!==null&&(n.childLanes|=t),n=e,e=e.return;return n.tag===3?n.stateNode:null}var zn=!1;function Zi(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function pc(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function yn(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Un(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,(je&2)!==0){var o=r.pending;return o===null?t.next=t:(t.next=o.next,o.next=t),r.pending=t,gn(e,n)}return o=r.interleaved,o===null?(t.next=t,Gi(r)):(t.next=o.next,o.next=t),r.interleaved=t,gn(e,n)}function vs(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194240)!==0)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,di(e,n)}}function hc(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var o=null,s=null;if(n=n.firstBaseUpdate,n!==null){do{var u={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};s===null?o=s=u:s=s.next=u,n=n.next}while(n!==null);s===null?o=s=t:s=s.next=t}else o=s=t;n={baseState:r.baseState,firstBaseUpdate:o,lastBaseUpdate:s,shared:r.shared,effects:r.effects},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function ws(e,t,n,r){var o=e.updateQueue;zn=!1;var s=o.firstBaseUpdate,u=o.lastBaseUpdate,h=o.shared.pending;if(h!==null){o.shared.pending=null;var g=h,j=g.next;g.next=null,u===null?s=j:u.next=j,u=g;var b=e.alternate;b!==null&&(b=b.updateQueue,h=b.lastBaseUpdate,h!==u&&(h===null?b.firstBaseUpdate=j:h.next=j,b.lastBaseUpdate=g))}if(s!==null){var A=o.baseState;u=0,b=j=g=null,h=s;do{var R=h.lane,H=h.eventTime;if((r&R)===R){b!==null&&(b=b.next={eventTime:H,lane:0,tag:h.tag,payload:h.payload,callback:h.callback,next:null});e:{var G=e,Z=h;switch(R=t,H=n,Z.tag){case 1:if(G=Z.payload,typeof G=="function"){A=G.call(H,A,R);break e}A=G;break e;case 3:G.flags=G.flags&-65537|128;case 0:if(G=Z.payload,R=typeof G=="function"?G.call(H,A,R):G,R==null)break e;A=D({},A,R);break e;case 2:zn=!0}}h.callback!==null&&h.lane!==0&&(e.flags|=64,R=o.effects,R===null?o.effects=[h]:R.push(h))}else H={eventTime:H,lane:R,tag:h.tag,payload:h.payload,callback:h.callback,next:null},b===null?(j=b=H,g=A):b=b.next=H,u|=R;if(h=h.next,h===null){if(h=o.shared.pending,h===null)break;R=h,h=R.next,R.next=null,o.lastBaseUpdate=R,o.shared.pending=null}}while(!0);if(b===null&&(g=A),o.baseState=g,o.firstBaseUpdate=j,o.lastBaseUpdate=b,t=o.shared.interleaved,t!==null){o=t;do u|=o.lane,o=o.next;while(o!==t)}else s===null&&(o.shared.lanes=0);nr|=u,e.lanes=u,e.memoizedState=A}}function mc(e,t,n){if(e=t.effects,t.effects=null,e!==null)for(t=0;tn?n:4,e(!0);var r=nl.transition;nl.transition={};try{e(!1),t()}finally{De=n,nl.transition=r}}function bc(){return Pt().memoizedState}function Wf(e,t,n){var r=Wn(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},Ac(e))Mc(t,n);else if(n=fc(e,t,n,r),n!==null){var o=dt();Yt(n,e,r,o),zc(n,t,r)}}function Hf(e,t,n){var r=Wn(e),o={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(Ac(e))Mc(t,o);else{var s=e.alternate;if(e.lanes===0&&(s===null||s.lanes===0)&&(s=t.lastRenderedReducer,s!==null))try{var u=t.lastRenderedState,h=s(u,n);if(o.hasEagerState=!0,o.eagerState=h,Vt(h,u)){var g=t.interleaved;g===null?(o.next=o,Gi(t)):(o.next=g.next,g.next=o),t.interleaved=o;return}}catch{}n=fc(e,t,o,r),n!==null&&(o=dt(),Yt(n,e,r,o),zc(n,t,r))}}function Ac(e){var t=e.alternate;return e===Be||t!==null&&t===Be}function Mc(e,t){_o=xs=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function zc(e,t,n){if((n&4194240)!==0){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,di(e,n)}}var Es={readContext:Rt,useCallback:it,useContext:it,useEffect:it,useImperativeHandle:it,useInsertionEffect:it,useLayoutEffect:it,useMemo:it,useReducer:it,useRef:it,useState:it,useDebugValue:it,useDeferredValue:it,useTransition:it,useMutableSource:it,useSyncExternalStore:it,useId:it,unstable_isNewReconciler:!1},Vf={readContext:Rt,useCallback:function(e,t){return en().memoizedState=[e,t===void 0?null:t],e},useContext:Rt,useEffect:jc,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,Ss(4194308,4,Tc.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Ss(4194308,4,e,t)},useInsertionEffect:function(e,t){return Ss(4,2,e,t)},useMemo:function(e,t){var n=en();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=en();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=Wf.bind(null,Be,e),[r.memoizedState,e]},useRef:function(e){var t=en();return e={current:e},t.memoizedState=e},useState:Cc,useDebugValue:cl,useDeferredValue:function(e){return en().memoizedState=e},useTransition:function(){var e=Cc(!1),t=e[0];return e=Ff.bind(null,e[1]),en().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=Be,o=en();if(Ue){if(n===void 0)throw Error(a(407));n=n()}else{if(n=t(),Je===null)throw Error(a(349));(tr&30)!==0||wc(r,t,n)}o.memoizedState=n;var s={value:n,getSnapshot:t};return o.queue=s,jc(kc.bind(null,r,s,e),[e]),r.flags|=2048,So(9,_c.bind(null,r,s,n,t),void 0,null),n},useId:function(){var e=en(),t=Je.identifierPrefix;if(Ue){var n=mn,r=hn;n=(r&~(1<<32-Ht(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=ko++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=u.createElement(n,{is:r.is}):(e=u.createElement(n),n==="select"&&(u=e,r.multiple?u.multiple=!0:r.size&&(u.size=r.size))):e=u.createElementNS(e,n),e[Xt]=t,e[ho]=r,ru(e,t,!1,!1),t.stateNode=e;e:{switch(u=fr(n,r),n){case"dialog":Me("cancel",e),Me("close",e),o=r;break;case"iframe":case"object":case"embed":Me("load",e),o=r;break;case"video":case"audio":for(o=0;oBr&&(t.flags|=128,r=!0,Co(s,!1),t.lanes=4194304)}else{if(!r)if(e=_s(u),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),Co(s,!0),s.tail===null&&s.tailMode==="hidden"&&!u.alternate&&!Ue)return lt(t),null}else 2*Le()-s.renderingStartTime>Br&&n!==1073741824&&(t.flags|=128,r=!0,Co(s,!1),t.lanes=4194304);s.isBackwards?(u.sibling=t.child,t.child=u):(n=s.last,n!==null?n.sibling=u:t.child=u,s.last=u)}return s.tail!==null?(t=s.tail,s.rendering=t,s.tail=t.sibling,s.renderingStartTime=Le(),t.sibling=null,n=Oe.current,Pe(Oe,r?n&1|2:n&1),t):(lt(t),null);case 22:case 23:return Pl(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&(t.mode&1)!==0?(Ct&1073741824)!==0&&(lt(t),t.subtreeFlags&6&&(t.flags|=8192)):lt(t),null;case 24:return null;case 25:return null}throw Error(a(156,t.tag))}function Xf(e,t){switch(Wi(t),t.tag){case 1:return pt(t.type)&&cs(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Mr(),ze(ft),ze(st),tl(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 5:return Ji(t),null;case 13:if(ze(Oe),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(a(340));Rr()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return ze(Oe),null;case 4:return Mr(),null;case 10:return Qi(t.type._context),null;case 22:case 23:return Pl(),null;case 24:return null;default:return null}}var Ts=!1,at=!1,Jf=typeof WeakSet=="function"?WeakSet:Set,Y=null;function Ur(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){Ve(e,t,r)}else n.current=null}function kl(e,t,n){try{n()}catch(r){Ve(e,t,r)}}var iu=!1;function ep(e,t){if(Pi=Yo,e=Ua(),Ei(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var o=r.anchorOffset,s=r.focusNode;r=r.focusOffset;try{n.nodeType,s.nodeType}catch{n=null;break e}var u=0,h=-1,g=-1,j=0,b=0,A=e,R=null;t:for(;;){for(var H;A!==n||o!==0&&A.nodeType!==3||(h=u+o),A!==s||r!==0&&A.nodeType!==3||(g=u+r),A.nodeType===3&&(u+=A.nodeValue.length),(H=A.firstChild)!==null;)R=A,A=H;for(;;){if(A===e)break t;if(R===n&&++j===o&&(h=u),R===s&&++b===r&&(g=u),(H=A.nextSibling)!==null)break;A=R,R=A.parentNode}A=H}n=h===-1||g===-1?null:{start:h,end:g}}else n=null}n=n||{start:0,end:0}}else n=null;for(bi={focusedElem:e,selectionRange:n},Yo=!1,Y=t;Y!==null;)if(t=Y,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,Y=e;else for(;Y!==null;){t=Y;try{var G=t.alternate;if((t.flags&1024)!==0)switch(t.tag){case 0:case 11:case 15:break;case 1:if(G!==null){var Z=G.memoizedProps,$e=G.memoizedState,k=t.stateNode,v=k.getSnapshotBeforeUpdate(t.elementType===t.type?Z:Kt(t.type,Z),$e);k.__reactInternalSnapshotBeforeUpdate=v}break;case 3:var S=t.stateNode.containerInfo;S.nodeType===1?S.textContent="":S.nodeType===9&&S.documentElement&&S.removeChild(S.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(a(163))}}catch(z){Ve(t,t.return,z)}if(e=t.sibling,e!==null){e.return=t.return,Y=e;break}Y=t.return}return G=iu,iu=!1,G}function Eo(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var o=r=r.next;do{if((o.tag&e)===e){var s=o.destroy;o.destroy=void 0,s!==void 0&&kl(t,n,s)}o=o.next}while(o!==r)}}function Ls(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function xl(e){var t=e.ref;if(t!==null){var n=e.stateNode;e.tag,e=n,typeof t=="function"?t(e):t.current=e}}function lu(e){var t=e.alternate;t!==null&&(e.alternate=null,lu(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[Xt],delete t[ho],delete t[Ui],delete t[Mf],delete t[zf])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function au(e){return e.tag===5||e.tag===3||e.tag===4}function cu(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||au(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Sl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ls));else if(r!==4&&(e=e.child,e!==null))for(Sl(e,t,n),e=e.sibling;e!==null;)Sl(e,t,n),e=e.sibling}function Cl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(Cl(e,t,n),e=e.sibling;e!==null;)Cl(e,t,n),e=e.sibling}var nt=null,qt=!1;function On(e,t,n){for(n=n.child;n!==null;)uu(e,t,n),n=n.sibling}function uu(e,t,n){if(Tt&&typeof Tt.onCommitFiberUnmount=="function")try{Tt.onCommitFiberUnmount(Zt,n)}catch{}switch(n.tag){case 5:at||Ur(n,t);case 6:var r=nt,o=qt;nt=null,On(e,t,n),nt=r,qt=o,nt!==null&&(qt?(e=nt,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):nt.removeChild(n.stateNode));break;case 18:nt!==null&&(qt?(e=nt,n=n.stateNode,e.nodeType===8?zi(e.parentNode,n):e.nodeType===1&&zi(e,n),no(e)):zi(nt,n.stateNode));break;case 4:r=nt,o=qt,nt=n.stateNode.containerInfo,qt=!0,On(e,t,n),nt=r,qt=o;break;case 0:case 11:case 14:case 15:if(!at&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){o=r=r.next;do{var s=o,u=s.destroy;s=s.tag,u!==void 0&&((s&2)!==0||(s&4)!==0)&&kl(n,t,u),o=o.next}while(o!==r)}On(e,t,n);break;case 1:if(!at&&(Ur(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(h){Ve(n,t,h)}On(e,t,n);break;case 21:On(e,t,n);break;case 22:n.mode&1?(at=(r=at)||n.memoizedState!==null,On(e,t,n),at=r):On(e,t,n);break;default:On(e,t,n)}}function du(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new Jf),t.forEach(function(r){var o=cp.bind(null,e,r);n.has(r)||(n.add(r),r.then(o,o))})}}function Qt(e,t){var n=t.deletions;if(n!==null)for(var r=0;ro&&(o=u),r&=~s}if(r=o,r=Le()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*np(r/1960))-r,10e?16:e,Fn===null)var r=!1;else{if(e=Fn,Fn=null,As=0,(je&6)!==0)throw Error(a(331));var o=je;for(je|=4,Y=e.current;Y!==null;){var s=Y,u=s.child;if((Y.flags&16)!==0){var h=s.deletions;if(h!==null){for(var g=0;gLe()-Nl?or(e,0):jl|=n),gt(e,t)}function Cu(e,t){t===0&&((e.mode&1)===0?t=1:(t=$o,$o<<=1,($o&130023424)===0&&($o=4194304)));var n=dt();e=gn(e,t),e!==null&&(Zr(e,t,n),gt(e,n))}function ap(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Cu(e,n)}function cp(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,o=e.memoizedState;o!==null&&(n=o.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(a(314))}r!==null&&r.delete(t),Cu(e,n)}var Eu;Eu=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||ft.current)ht=!0;else{if((e.lanes&n)===0&&(t.flags&128)===0)return ht=!1,Gf(e,t,n);ht=(e.flags&131072)!==0}else ht=!1,Ue&&(t.flags&1048576)!==0&&oc(t,ps,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;Is(e,t),e=t.pendingProps;var o=Tr(t,st.current);Ar(t,n),o=ol(null,t,r,e,o,n);var s=sl();return t.flags|=1,typeof o=="object"&&o!==null&&typeof o.render=="function"&&o.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,pt(r)?(s=!0,us(t)):s=!1,t.memoizedState=o.state!==null&&o.state!==void 0?o.state:null,Zi(t),o.updater=js,t.stateNode=o,o._reactInternals=t,dl(t,r,e,n),t=ml(null,t,r,!0,s,n)):(t.tag=0,Ue&&s&&Fi(t),ut(null,t,o,n),t=t.child),t;case 16:r=t.elementType;e:{switch(Is(e,t),e=t.pendingProps,o=r._init,r=o(r._payload),t.type=r,o=t.tag=dp(r),e=Kt(r,e),o){case 0:t=hl(null,t,r,e,n);break e;case 1:t=Zc(null,t,r,e,n);break e;case 11:t=Kc(null,t,r,e,n);break e;case 14:t=qc(null,t,r,Kt(r.type,e),n);break e}throw Error(a(306,r,""))}return t;case 0:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:Kt(r,o),hl(e,t,r,o,n);case 1:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:Kt(r,o),Zc(e,t,r,o,n);case 3:e:{if(Xc(t),e===null)throw Error(a(387));r=t.pendingProps,s=t.memoizedState,o=s.element,pc(e,t),ws(t,r,null,n);var u=t.memoizedState;if(r=u.element,s.isDehydrated)if(s={element:r,isDehydrated:!1,cache:u.cache,pendingSuspenseBoundaries:u.pendingSuspenseBoundaries,transitions:u.transitions},t.updateQueue.baseState=s,t.memoizedState=s,t.flags&256){o=zr(Error(a(423)),t),t=Jc(e,t,r,n,o);break e}else if(r!==o){o=zr(Error(a(424)),t),t=Jc(e,t,r,n,o);break e}else for(St=Pn(t.stateNode.containerInfo.firstChild),xt=t,Ue=!0,$t=null,n=dc(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(Rr(),r===o){t=vn(e,t,n);break e}ut(e,t,r,n)}t=t.child}return t;case 5:return gc(t),e===null&&Vi(t),r=t.type,o=t.pendingProps,s=e!==null?e.memoizedProps:null,u=o.children,Ai(r,o)?u=null:s!==null&&Ai(r,s)&&(t.flags|=32),Gc(e,t),ut(e,t,u,n),t.child;case 6:return e===null&&Vi(t),null;case 13:return eu(e,t,n);case 4:return Xi(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=Pr(t,null,r,n):ut(e,t,r,n),t.child;case 11:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:Kt(r,o),Kc(e,t,r,o,n);case 7:return ut(e,t,t.pendingProps,n),t.child;case 8:return ut(e,t,t.pendingProps.children,n),t.child;case 12:return ut(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,o=t.pendingProps,s=t.memoizedProps,u=o.value,Pe(gs,r._currentValue),r._currentValue=u,s!==null)if(Vt(s.value,u)){if(s.children===o.children&&!ft.current){t=vn(e,t,n);break e}}else for(s=t.child,s!==null&&(s.return=t);s!==null;){var h=s.dependencies;if(h!==null){u=s.child;for(var g=h.firstContext;g!==null;){if(g.context===r){if(s.tag===1){g=yn(-1,n&-n),g.tag=2;var j=s.updateQueue;if(j!==null){j=j.shared;var b=j.pending;b===null?g.next=g:(g.next=b.next,b.next=g),j.pending=g}}s.lanes|=n,g=s.alternate,g!==null&&(g.lanes|=n),Yi(s.return,n,t),h.lanes|=n;break}g=g.next}}else if(s.tag===10)u=s.type===t.type?null:s.child;else if(s.tag===18){if(u=s.return,u===null)throw Error(a(341));u.lanes|=n,h=u.alternate,h!==null&&(h.lanes|=n),Yi(u,n,t),u=s.sibling}else u=s.child;if(u!==null)u.return=s;else for(u=s;u!==null;){if(u===t){u=null;break}if(s=u.sibling,s!==null){s.return=u.return,u=s;break}u=u.return}s=u}ut(e,t,o.children,n),t=t.child}return t;case 9:return o=t.type,r=t.pendingProps.children,Ar(t,n),o=Rt(o),r=r(o),t.flags|=1,ut(e,t,r,n),t.child;case 14:return r=t.type,o=Kt(r,t.pendingProps),o=Kt(r.type,o),qc(e,t,r,o,n);case 15:return Qc(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,o=t.pendingProps,o=t.elementType===r?o:Kt(r,o),Is(e,t),t.tag=1,pt(r)?(e=!0,us(t)):e=!1,Ar(t,n),Oc(t,r,o),dl(t,r,o,n),ml(null,t,r,!0,e,n);case 19:return nu(e,t,n);case 22:return Yc(e,t,n)}throw Error(a(156,t.tag))};function ju(e,t){return Yr(e,t)}function up(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function At(e,t,n,r){return new up(e,t,n,r)}function Al(e){return e=e.prototype,!(!e||!e.isReactComponent)}function dp(e){if(typeof e=="function")return Al(e)?1:0;if(e!=null){if(e=e.$$typeof,e===he)return 11;if(e===J)return 14}return 2}function Vn(e,t){var n=e.alternate;return n===null?(n=At(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Os(e,t,n,r,o,s){var u=2;if(r=e,typeof e=="function")Al(e)&&(u=1);else if(typeof e=="string")u=5;else e:switch(e){case _e:return ir(n.children,o,s,t);case ke:u=8,o|=8;break;case Ne:return e=At(12,n,t,o|2),e.elementType=Ne,e.lanes=s,e;case K:return e=At(13,n,t,o),e.elementType=K,e.lanes=s,e;case q:return e=At(19,n,t,o),e.elementType=q,e.lanes=s,e;case te:return Bs(n,o,s,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case be:u=10;break e;case Se:u=9;break e;case he:u=11;break e;case J:u=14;break e;case le:u=16,r=null;break e}throw Error(a(130,e==null?e:typeof e,""))}return t=At(u,n,t,o),t.elementType=e,t.type=r,t.lanes=s,t}function ir(e,t,n,r){return e=At(7,e,r,t),e.lanes=n,e}function Bs(e,t,n,r){return e=At(22,e,r,t),e.elementType=te,e.lanes=n,e.stateNode={isHidden:!1},e}function Ml(e,t,n){return e=At(6,e,null,t),e.lanes=n,e}function zl(e,t,n){return t=At(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function fp(e,t,n,r,o){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=ui(0),this.expirationTimes=ui(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=ui(0),this.identifierPrefix=r,this.onRecoverableError=o,this.mutableSourceEagerHydrationData=null}function Ul(e,t,n,r,o,s,u,h,g){return e=new fp(e,t,n,h,g),t===1?(t=1,s===!0&&(t|=8)):t=0,s=At(3,null,null,t),e.current=s,s.stateNode=e,s.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Zi(s),e}function pp(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(i)}catch(l){console.error(l)}}return i(),Vl.exports=Ep(),Vl.exports}var Bu;function Np(){if(Bu)return qs;Bu=1;var i=jp();return qs.createRoot=i.createRoot,qs.hydrateRoot=i.hydrateRoot,qs}var Ip=Np();const Tp=cd(Ip),Lp="modulepreload",Dp=function(i,l){return new URL(i,l).href},Fu={},Rp=function(l,a,d){let f=Promise.resolve();if(a&&a.length>0){let E=function(T){return Promise.all(T.map(N=>Promise.resolve(N).then(L=>({status:"fulfilled",value:L}),L=>({status:"rejected",reason:L}))))};const p=document.getElementsByTagName("link"),_=document.querySelector("meta[property=csp-nonce]"),w=_?.nonce||_?.getAttribute("nonce");f=E(a.map(T=>{if(T=Dp(T,d),T in Fu)return;Fu[T]=!0;const N=T.endsWith(".css"),L=N?'[rel="stylesheet"]':"";if(d)for(let B=p.length-1;B>=0;B--){const W=p[B];if(W.href===T&&(!N||W.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${T}"]${L}`))return;const O=document.createElement("link");if(O.rel=N?"stylesheet":Lp,N||(O.as="script"),O.crossOrigin="",O.href=T,w&&O.setAttribute("nonce",w),document.head.appendChild(O),N)return new Promise((B,W)=>{O.addEventListener("load",B),O.addEventListener("error",()=>W(new Error(`Unable to preload CSS for ${T}`)))})}))}function m(p){const _=new Event("vite:preloadError",{cancelable:!0});if(_.payload=p,window.dispatchEvent(_),!_.defaultPrevented)throw p}return f.then(p=>{for(const _ of p||[])_.status==="rejected"&&m(_.reason);return l().catch(m)})},Kn=[{id:"zh-CN",shortName:"中",aliases:["zh","zh-Hans","zh-CN"],contentFallbacks:["en-US"]},{id:"zh-TW",shortName:"繁",aliases:["zh-TW","zh-Hant","zh-HK","zh-MO"],contentFallbacks:["zh-CN","en-US"]},{id:"en-US",shortName:"EN",aliases:["en","en-US"],contentFallbacks:["zh-CN"]}],Pp=["en-US","zh-CN"],bp=Kn.flatMap(i=>i.aliases.map(l=>({locale:i,alias:l.toLowerCase()}))).sort((i,l)=>l.alias.length-i.alias.length),ti="en-US",ql={"zh-CN":{product:{name:"BitFun",remote:"BitFun Remote"},features:{remoteControl:"远程控制",codeAgent:"代码助手",deepReview:"严格审查",settings:"设置",workspace:"工作区"},modes:{agentic:"代理模式",assistant:"助手模式",expert:"专家模式",review:"评审模式"},agents:{code:"代码会话",cowork:"协作会话",claw:"Claw",default:"默认助手"},tools:{explore:"探索",read:"读取",write:"写入",shell:"命令行",search:"搜索",edit:"编辑",todo:"待办"},connectionMethods:{lan:"局域网",ngrok:"Ngrok",bitfunServer:"BitFun Server",customServer:"自定义服务器",botFeishu:"飞书机器人",botTelegram:"Telegram Bot",botWeixin:"微信机器人"},statuses:{loading:"加载中",running:"运行中",done:"已完成",failed:"失败",cancelled:"已取消"}},"zh-TW":{product:{name:"BitFun",remote:"BitFun Remote"},features:{remoteControl:"遠端控制",codeAgent:"程式碼助手",deepReview:"嚴格審查",settings:"設定",workspace:"工作區"},modes:{agentic:"代理模式",assistant:"助手模式",expert:"專家模式",review:"審查模式"},agents:{code:"程式碼會話",cowork:"協作會話",claw:"Claw",default:"預設助手"},tools:{explore:"探索",read:"讀取",write:"寫入",shell:"命令列",search:"搜尋",edit:"編輯",todo:"待辦"},connectionMethods:{lan:"區域網路",ngrok:"Ngrok",bitfunServer:"BitFun Server",customServer:"自訂伺服器",botFeishu:"飛書機器人",botTelegram:"Telegram Bot",botWeixin:"微信機器人"},statuses:{loading:"載入中",running:"執行中",done:"已完成",failed:"失敗",cancelled:"已取消"}},"en-US":{product:{name:"BitFun",remote:"BitFun Remote"},features:{remoteControl:"Remote Control",codeAgent:"Code Agent",deepReview:"Review: Strict",settings:"Settings",workspace:"Workspace"},modes:{agentic:"Agentic Mode",assistant:"Assistant Mode",expert:"Expert Mode",review:"Review Mode"},agents:{code:"Code Session",cowork:"Cowork Session",claw:"Claw",default:"Default Assistant"},tools:{explore:"Explore",read:"Read",write:"Write",shell:"Shell",search:"Search",edit:"Edit",todo:"Todo"},connectionMethods:{lan:"LAN",ngrok:"Ngrok",bitfunServer:"BitFun Server",customServer:"Custom Server",botFeishu:"Feishu Bot",botTelegram:"Telegram Bot",botWeixin:"WeChat Bot"},statuses:{loading:"Loading",running:"Running",done:"Done",failed:"Failed",cancelled:"Cancelled"}}};function Ap(i){return Kn.some(l=>l.id===i)}function oa(i){const l=i?.trim().toLowerCase();if(!l)return null;const a=Kn.find(d=>d.id.toLowerCase()===l);return a?a.id:bp.find(({alias:d})=>l===d||l.startsWith(`${d}-`))?.locale.id??null}function Mp(i){const l=Kn.findIndex(a=>a.id===i);return Kn[(l+1)%Kn.length].id}function zp(i){return Kn.find(l=>l.id===i)?.shortName??i}function Up(i,l=!1){const a=oa(i),d=a?Kn.find(m=>m.id===a):null,f=d?[...l?[d.id]:[],...d.contentFallbacks]:[...Pp];return Array.from(new Set(f))}const Op={"en-US":{shared:ql["en-US"],common:{back:"Back",continue:"Continue",cancel:"Cancel",switch:"Switch",loading:"Loading...",switchLanguage:"Switch language",toggleTheme:"Toggle theme",attachImage:"Attach image",stop:"Stop",submit:"Submit",submitting:"Submitting...",submitted:"Submitted",other:"Other",customTextInput:"Custom text input",typeYourAnswer:"Type your answer...",itemCount:"{count} items",justNow:"just now",minutesAgo:"{count}m ago",hoursAgo:"{count}h ago",daysAgo:"{count}d ago"},pairing:{enterUserIdToContinue:"Enter your user ID to continue",enterAccountToContinue:"Enter your BitFun account to continue",connectingAndPairing:"Connecting and pairing...",pairedLoadingSessions:"Paired! Loading sessions...",connectionError:"Connection error",invalidQrCode:"Invalid QR code: missing room or public key",userIdRequired:"User ID is required",usernameRequired:"Username is required",passwordRequired:"Password is required",tooManyAttempts:"Too many failed attempts. Try again in {seconds}s.",pairingFailed:"Pairing failed",fieldsTooLong:"Username or password is too long.",requestTimedOut:"The relay did not respond in time. Check the network and try again.",qrExpired:"This QR code has expired or the desktop stopped sharing. Scan a new code.",rateLimited:"Too many pairing attempts. Wait one minute, then scan or try again.",relayUnavailable:"The relay or desktop is temporarily unavailable. Try again shortly.",credentialsRejected:"The username or password was not accepted.",fieldLabel:"User ID",usernameLabel:"Username",passwordLabel:"Password",placeholder:"Enter a user ID",usernamePlaceholder:"Enter your username",passwordPlaceholder:"Enter your password",note:"The first successful connection binds this URL to your user ID for the current remote session.",accountNote:"Use the same BitFun account currently logged in on the scanned desktop. Your password is not saved on this phone.",connecting:"Connecting...",retryIn:"Retry in {seconds}s",continue:"Continue"},sessions:{switchWorkspace:"Switch workspace",selectWorkspace:"Select Workspace",noWorkspaces:"No workspaces found",noWorkspaceSelected:"No workspace selected",assistant:"Assistant",switchAssistant:"Switch assistant",selectAssistant:"Select Assistant",launch:"Launch",startRemoteFlow:"Start a new remote flow",codeSessionDesc:"For coding anywhere, anytime.",coworkSessionDesc:"For assisting with everyday work.",clawSession:"Claw Session",clawSessionDesc:"Personal assistant for daily tasks.",recent:"Recent",sessionHistory:"Session history",loadingSessions:"Loading sessions...",noSessions:"No sessions yet. Create one to get started.",untitledSession:"Untitled Session",loadingMore:"Loading more...",remoteCodeSession:"Remote Code Session",remoteCoworkSession:"Remote Cowork Session",remoteClawSession:"Remote Claw Session",agentCode:"Code",agentCowork:"Cowork",agentDefault:"Default",searchSessions:"Search sessions...",renameSession:"Rename",deleteSession:"Delete",confirmDelete:"Delete session?",confirmDeleteDesc:"This action cannot be undone.",renameTitle:"Rename Session",sessionNamePlaceholder:"Session name",cancel:"Cancel",save:"Save",emptySearch:"No sessions match your search.",deleted:"Session deleted",deleteFailed:"Delete failed",renameFailed:"Rename failed",disconnect:"Disconnect",disconnectConfirm:"Disconnect from current desktop? You can re-pair later.",reconnecting:"Reconnecting...",repair:"Pair again",connectionUnpaired:"Not connected",connectionChecking:"Checking connection...",connectionConnected:"Connected",connectionUnreachable:"Connection lost",continueSession:"Continue where you left off"},workspace:{loadingInfo:"Loading workspace info...",currentWorkspace:"Current Workspace",unknownProject:"Unknown Project",noWorkspaceOpen:"No workspace is currently open on the desktop.",noWorkspaceHint:"Select a recent workspace below, or open one on the desktop first.",selectWorkspace:"Select Workspace",recentWorkspaces:"Recent Workspaces",noRecentWorkspaces:"No recent workspaces found. Please open a workspace on the desktop first.",failedToSetWorkspace:"Failed to set workspace",openingWorkspace:"Opening workspace..."},chat:{session:"Session",loadingOlderMessages:"Loading older messages...",showResponse:"Show response",hideResponse:"Hide response",analyzingImage:"Analyzing image with image understanding model...",inputPlaceholder:"How can I help you...",collapsedInputPlaceholder:"Ask BitFun...",collapsedStreamingPlaceholder:"Replying...",messageQueued:"Message queued; it will run after the current step",imageAnalyzingPlaceholder:"Analyzing image...",imageAttachmentFallback:"(see attached images)",modelSelection:"Select model",modelPrimary:"Primary Model",modelPrimaryDesc:"Uses the configured primary model",modelFast:"Fast Model",modelFastDesc:"Uses the configured fast model",reasoningSelection:"Select reasoning effort",reasoningAuto:"Auto",askQuestionCount:"{count} question{suffix}",waiting:"Waiting",thinking:"Thinking...",allTasksCompleted:"All tasks completed",task:"Task",toolCalls:"{count} tool call{suffix}",done:"{count} done",running:"{count} running",thoughtCharacters:"Thought {count} characters",textCharacters:"Text {count} characters",readToolsDone:"{summary}",readToolsRunning:"{summary} ({doneCount} done)",fileLoading:"Loading...",fileUnavailable:"File unavailable",fileDownloading:"Downloading...",fileDownloaded:"Downloaded",clickToDownload:"Click to download",scrollToBottom:"Scroll to bottom",copyMessage:"Copy text",resendMessage:"Resend",deleteMessage:"Delete",messageCopied:"Copied",messageDeleted:"Deleted",copyFailed:"Copy failed"},devices:{title:"Devices",noDelegatedIdentity:"The paired desktop is not logged into a BitFun account. Log in on the desktop to enable multi-device control, then retry.",loading:"Loading...",refresh:"Refresh",retry:"Retry",noDevices:"No devices found",online:"Online",offline:"Offline",lastSeen:"Last seen {time}",current:"Current",pairedDesktop:"Paired",switchFailed:"Failed to switch device",loadFailed:"Could not load devices. Check the connection and retry.",identityFailed:"Could not request account access from the paired desktop.",authorizationExpired:"Account authorization expired. Keep the paired desktop online and retry.",deviceUnavailable:"This device is offline or did not respond.",unknownDevice:"Unnamed device",controllingDevice:"Controlling {name}"},tools:{ls:"LS",glob:"Glob",grep:"Grep",delete:"Delete",task:"Task",web:"Web"}},"zh-CN":{shared:ql["zh-CN"],common:{back:"返回",continue:"继续",cancel:"取消",switch:"切换",loading:"加载中...",switchLanguage:"切换语言",toggleTheme:"切换主题",attachImage:"添加图片",stop:"停止",submit:"提交",submitting:"提交中...",submitted:"已提交",other:"其他",customTextInput:"自定义输入",typeYourAnswer:"请输入你的回答...",itemCount:"{count} 项",justNow:"刚刚",minutesAgo:"{count} 分钟前",hoursAgo:"{count} 小时前",daysAgo:"{count} 天前"},pairing:{enterUserIdToContinue:"请输入你的用户 ID 继续",enterAccountToContinue:"请输入你的 BitFun 账号继续",connectingAndPairing:"正在连接并配对...",pairedLoadingSessions:"配对成功,正在加载会话...",connectionError:"连接异常",invalidQrCode:"二维码无效:缺少 room 或 public key",userIdRequired:"用户 ID 不能为空",usernameRequired:"用户名不能为空",passwordRequired:"密码不能为空",tooManyAttempts:"失败次数过多,请在 {seconds} 秒后重试。",pairingFailed:"配对失败",fieldsTooLong:"用户名或密码过长。",requestTimedOut:"中继服务响应超时,请检查网络后重试。",qrExpired:"此二维码已过期,或桌面端已停止共享,请重新扫码。",rateLimited:"配对尝试过多,请等待一分钟后重新扫码或重试。",relayUnavailable:"中继服务或桌面端暂时不可用,请稍后重试。",credentialsRejected:"用户名或密码未通过验证。",fieldLabel:"用户 ID",usernameLabel:"用户名",passwordLabel:"密码",placeholder:"请输入用户 ID",usernamePlaceholder:"请输入用户名",passwordPlaceholder:"请输入密码",note:"首次成功连接后,本次远程会话会把该 URL 绑定到你的用户 ID。",accountNote:"请使用被扫码桌面端当前登录的 BitFun 账号。密码不会保存在本机。",connecting:"连接中...",retryIn:"{seconds} 秒后重试",continue:"继续"},sessions:{switchWorkspace:"切换工作区",selectWorkspace:"选择工作区",noWorkspaces:"暂无工作区",noWorkspaceSelected:"未选择工作区",assistant:"助理",switchAssistant:"切换助理",selectAssistant:"选择助理",launch:"启动",startRemoteFlow:"开始一个新的远程流程",codeSessionDesc:"随时随地进行编码。",coworkSessionDesc:"处理日常协作与办公任务。",clawSession:"助理会话",clawSessionDesc:"处理日常任务的个人助手。",recent:"最近",sessionHistory:"会话历史",loadingSessions:"正在加载会话...",noSessions:"还没有会话,先创建一个开始吧。",untitledSession:"未命名会话",loadingMore:"正在加载更多...",remoteCodeSession:"远程代码会话",remoteCoworkSession:"远程协作会话",remoteClawSession:"远程助理会话",agentCode:"Code",agentCowork:"Cowork",agentDefault:"默认",searchSessions:"搜索会话...",renameSession:"重命名",deleteSession:"删除",confirmDelete:"确定删除此会话?",confirmDeleteDesc:"此操作无法撤销。",renameTitle:"重命名会话",sessionNamePlaceholder:"会话名称",cancel:"取消",save:"保存",emptySearch:"没有匹配的会话。",deleted:"会话已删除",deleteFailed:"删除失败",renameFailed:"重命名失败",disconnect:"断开连接",disconnectConfirm:"断开当前桌面连接?之后可重新配对。",reconnecting:"正在重新连接...",repair:"重新配对",connectionUnpaired:"未连接",connectionChecking:"检测连接中...",connectionConnected:"已连接",connectionUnreachable:"连接断开",continueSession:"继续上次会话"},workspace:{loadingInfo:"正在加载工作区信息...",currentWorkspace:"当前工作区",unknownProject:"未知项目",noWorkspaceOpen:"桌面端当前没有打开工作区。",noWorkspaceHint:"你可以在下方选择最近工作区,或先在桌面端打开一个工作区。",selectWorkspace:"选择工作区",recentWorkspaces:"最近工作区",noRecentWorkspaces:"没有找到最近工作区,请先在桌面端打开一个工作区。",failedToSetWorkspace:"设置工作区失败",openingWorkspace:"正在打开工作区..."},chat:{session:"会话",loadingOlderMessages:"正在加载更早的消息...",showResponse:"Show response",hideResponse:"Hide response",analyzingImage:"正在使用图像理解模型分析图片...",inputPlaceholder:"有什么可以帮您...",collapsedInputPlaceholder:"发消息...",collapsedStreamingPlaceholder:"正在回复...",messageQueued:"已加入队列,将在当前步骤结束后处理",imageAnalyzingPlaceholder:"正在分析图片...",imageAttachmentFallback:"(见附带图片)",modelSelection:"选择模型",modelPrimary:"Primary 模型",modelPrimaryDesc:"使用已配置的主力模型",modelFast:"Fast 模型",modelFastDesc:"使用已配置的快速模型",reasoningSelection:"选择思考强度",reasoningAuto:"Auto",askQuestionCount:"{count} 个问题{suffix}",waiting:"等待中",thinking:"思考中...",allTasksCompleted:"所有任务已完成",task:"任务",toolCalls:"{count} 次工具调用{suffix}",done:"已完成 {count}",running:"运行中 {count}",thoughtCharacters:"思考 {count} 个字符",textCharacters:"文本 {count} 个字符",readToolsDone:"{summary}",readToolsRunning:"{summary}(已完成 {doneCount})",fileLoading:"加载中...",fileUnavailable:"文件不可用",fileDownloading:"下载中...",fileDownloaded:"已下载",clickToDownload:"点击下载",scrollToBottom:"滚动到底部",copyMessage:"复制文本",resendMessage:"重新发送",deleteMessage:"删除",messageCopied:"已复制",messageDeleted:"已删除",copyFailed:"复制失败"},devices:{title:"设备",noDelegatedIdentity:"所连接的桌面端未登录 BitFun 账号。请在桌面端登录以启用多设备控制,然后重试。",loading:"加载中...",refresh:"刷新",retry:"重试",noDevices:"未找到设备",online:"在线",offline:"离线",lastSeen:"上次在线:{time}",current:"当前",pairedDesktop:"已配对",switchFailed:"切换设备失败",loadFailed:"无法加载设备,请检查连接后重试。",identityFailed:"无法从已配对桌面端获取账号访问权限。",authorizationExpired:"账号授权已过期,请保持已配对桌面端在线并重试。",deviceUnavailable:"该设备离线或未响应。",unknownDevice:"未命名设备",controllingDevice:"正在控制 {name}"},tools:{ls:"列表",glob:"Glob",grep:"Grep",delete:"删除",task:"任务",web:"网络"}},"zh-TW":{shared:ql["zh-TW"],common:{back:"返回",continue:"繼續",cancel:"取消",switch:"切換",loading:"加載中...",switchLanguage:"切換語言",toggleTheme:"切換主題",attachImage:"添加圖片",stop:"停止",submit:"提交",submitting:"提交中...",submitted:"已提交",other:"其他",customTextInput:"自定義輸入",typeYourAnswer:"請輸入你的回答...",itemCount:"{count} 項",justNow:"剛剛",minutesAgo:"{count} 分鐘前",hoursAgo:"{count} 小時前",daysAgo:"{count} 天前"},pairing:{enterUserIdToContinue:"請輸入你的用戶 ID 繼續",enterAccountToContinue:"請輸入你的 BitFun 帳號繼續",connectingAndPairing:"正在連接並配對...",pairedLoadingSessions:"配對成功,正在加載會話...",connectionError:"連接異常",invalidQrCode:"二維碼無效:缺少 room 或 public key",userIdRequired:"用戶 ID 不能為空",usernameRequired:"用戶名不能為空",passwordRequired:"密碼不能為空",tooManyAttempts:"失敗次數過多,請在 {seconds} 秒後重試。",pairingFailed:"配對失敗",fieldsTooLong:"帳號或密碼過長。",requestTimedOut:"中繼服務回應逾時,請檢查網路後重試。",qrExpired:"此 QR Code 已過期,或桌面端已停止分享,請重新掃描。",rateLimited:"配對嘗試過多,請等待一分鐘後重新掃描或重試。",relayUnavailable:"中繼服務或桌面端暫時無法使用,請稍後重試。",credentialsRejected:"帳號或密碼未通過驗證。",fieldLabel:"用戶 ID",usernameLabel:"用戶名",passwordLabel:"密碼",placeholder:"請輸入用戶 ID",usernamePlaceholder:"請輸入用戶名",passwordPlaceholder:"請輸入密碼",note:"首次成功連接後,本次遠程會話會把該 URL 綁定到你的用戶 ID。",accountNote:"請使用被掃碼桌面端目前登入的 BitFun 帳號。密碼不會保存在本機。",connecting:"連接中...",retryIn:"{seconds} 秒後重試",continue:"繼續"},sessions:{switchWorkspace:"切換工作區",selectWorkspace:"選擇工作區",noWorkspaces:"暫無工作區",noWorkspaceSelected:"未選擇工作區",assistant:"助理",switchAssistant:"切換助理",selectAssistant:"選擇助理",launch:"啟動",startRemoteFlow:"開始一個新的遠程流程",codeSessionDesc:"隨時隨地進行編碼。",coworkSessionDesc:"處理日常協作與辦公任務。",clawSession:"助理會話",clawSessionDesc:"處理日常任務的個人助手。",recent:"最近",sessionHistory:"會話歷史",loadingSessions:"正在加載會話...",noSessions:"還沒有會話,先創建一個開始吧。",untitledSession:"未命名會話",loadingMore:"正在加載更多...",remoteCodeSession:"遠程代碼會話",remoteCoworkSession:"遠程協作會話",remoteClawSession:"遠程助理會話",agentCode:"Code",agentCowork:"Cowork",agentDefault:"默認",searchSessions:"搜尋會話...",renameSession:"重新命名",deleteSession:"刪除",confirmDelete:"確定刪除此會話?",confirmDeleteDesc:"此操作無法復原。",renameTitle:"重新命名會話",sessionNamePlaceholder:"會話名稱",cancel:"取消",save:"儲存",emptySearch:"沒有匹配的會話。",deleted:"會話已刪除",deleteFailed:"刪除失敗",renameFailed:"重新命名失敗",disconnect:"斷開連接",disconnectConfirm:"斷開當前桌面連接?之後可重新配對。",reconnecting:"正在重新連接...",repair:"重新配對",connectionUnpaired:"未連接",connectionChecking:"檢測連接中...",connectionConnected:"已連接",connectionUnreachable:"連接斷開",continueSession:"繼續上次會話"},workspace:{loadingInfo:"正在加載工作區信息...",currentWorkspace:"當前工作區",unknownProject:"未知項目",noWorkspaceOpen:"桌面端當前沒有打開工作區。",noWorkspaceHint:"你可以在下方選擇最近工作區,或先在桌面端打開一個工作區。",selectWorkspace:"選擇工作區",recentWorkspaces:"最近工作區",noRecentWorkspaces:"沒有找到最近工作區,請先在桌面端打開一個工作區。",failedToSetWorkspace:"設置工作區失敗",openingWorkspace:"正在打開工作區..."},chat:{session:"會話",loadingOlderMessages:"正在加載更早的消息...",showResponse:"Show response",hideResponse:"Hide response",analyzingImage:"正在使用圖像理解模型分析圖片...",inputPlaceholder:"有什麼可以幫您...",collapsedInputPlaceholder:"發消息...",collapsedStreamingPlaceholder:"正在回覆...",messageQueued:"已加入隊列,將在當前步驟結束後處理",imageAnalyzingPlaceholder:"正在分析圖片...",imageAttachmentFallback:"(見附帶圖片)",modelSelection:"選擇模型",modelPrimary:"Primary 模型",modelPrimaryDesc:"使用已設定的主力模型",modelFast:"Fast 模型",modelFastDesc:"使用已設定的快速模型",reasoningSelection:"選擇思考強度",reasoningAuto:"Auto",askQuestionCount:"{count} 個問題{suffix}",waiting:"等待中",thinking:"思考中...",allTasksCompleted:"所有任務已完成",task:"任務",toolCalls:"{count} 次工具調用{suffix}",done:"已完成 {count}",running:"運行中 {count}",thoughtCharacters:"思考 {count} 個字符",textCharacters:"文本 {count} 個字符",readToolsDone:"{summary}",readToolsRunning:"{summary}(已完成 {doneCount})",fileLoading:"加載中...",fileUnavailable:"檔案不可用",fileDownloading:"下載中...",fileDownloaded:"已下載",clickToDownload:"點擊下載",scrollToBottom:"捲動到底部",copyMessage:"複製文本",resendMessage:"重新傳送",deleteMessage:"刪除",messageCopied:"已複製",messageDeleted:"已刪除",copyFailed:"複製失敗"},devices:{title:"設備",noDelegatedIdentity:"所連接的桌面端未登入 BitFun 帳號。請在桌面端登入以啟用多設備控制,然後重試。",loading:"加載中...",refresh:"重新整理",retry:"重試",noDevices:"未找到設備",online:"在線",offline:"離線",lastSeen:"上次在線:{time}",current:"目前",pairedDesktop:"已配對",switchFailed:"切換設備失敗",loadFailed:"無法載入裝置,請檢查連線後重試。",identityFailed:"無法從已配對桌面端取得帳號存取權限。",authorizationExpired:"帳號授權已過期,請保持已配對桌面端在線並重試。",deviceUnavailable:"該裝置離線或未回應。",unknownDevice:"未命名裝置",controllingDevice:"正在控制 {name}"},tools:{ls:"列表",glob:"Glob",grep:"Grep",delete:"刪除",task:"任務",web:"網絡"}}},ud="bitfun-mobile-language";function Bp(i,l){const a=l.split(".");let d=i;for(const f of a){if(!d||typeof d!="object"||!(f in d))return null;d=d[f]}return typeof d=="string"?d:null}function Fp(i,l){return l?i.replace(/\{(\w+)\}/g,(a,d)=>{const f=l[d];return f==null?"":String(f)}):i}function Wp(i,l,a){const d=Up(i,!0).map(f=>Bp(Op[f],l)).find(f=>f!==null)??l;return Fp(d,a)}function Hp(){try{const l=localStorage.getItem(ud);if(Ap(l))return l}catch{}const i=Vp();return i||(oa(navigator.language)??ti)}function Vp(){const i=[];try{i.push(new URLSearchParams(window.location.search).get("lang"))}catch{}const l=window.location.hash||"",a=l.indexOf("?");if(a>=0)try{const d=l.slice(a+1);i.push(new URLSearchParams(d).get("lang"))}catch{}for(const d of i){const f=oa(d);if(f)return f}return null}const dd=C.createContext({language:ti,setLanguage:()=>{},toggleLanguage:()=>{},t:i=>i,formatDate:(i,l)=>new Intl.DateTimeFormat(ti,l).format(i),formatRelativeTime:i=>fd(ti,i)});function fd(i,l){const a=l instanceof Date?l.getTime():l,d=(a-Date.now())/1e3,f=Math.abs(d),m=new Intl.RelativeTimeFormat(i,{numeric:"auto"});return f<60?m.format(Math.round(d),"second"):f<3600?m.format(Math.round(d/60),"minute"):f<86400?m.format(Math.round(d/3600),"hour"):f<2592e3?m.format(Math.round(d/86400),"day"):new Intl.DateTimeFormat(i,{dateStyle:"medium",timeStyle:"short"}).format(a)}const $p=({children:i})=>{const[l,a]=C.useState(Hp);C.useLayoutEffect(()=>{document.documentElement.lang=l;try{localStorage.setItem(ud,l)}catch{}},[l]);const d=C.useCallback(p=>{a(p)},[]),f=C.useCallback(()=>{a(Mp)},[]),m=C.useMemo(()=>({language:l,setLanguage:d,toggleLanguage:f,t:(p,_)=>Wp(l,p,_),formatDate:(p,_)=>new Intl.DateTimeFormat(l,_).format(p),formatRelativeTime:p=>fd(l,p)}),[l,d,f]);return c.jsx(dd.Provider,{value:m,children:i})};function $r(){return C.useContext(dd)}const sa=({className:i})=>{const{language:l,toggleLanguage:a,t:d}=$r(),f=["mobile-lang-btn",i].filter(Boolean).join(" ");return c.jsx("button",{type:"button",className:f,onClick:a,"aria-label":d("common.switchLanguage"),title:d("common.switchLanguage"),children:zp(l)})};function Kp(i){return i instanceof Uint8Array||ArrayBuffer.isView(i)&&i.constructor.name==="Uint8Array"}function pd(i,l=""){if(!Number.isSafeInteger(i)||i<0){const a=l&&`"${l}" `;throw new Error(`${a}expected integer >= 0, got ${i}`)}}function bo(i,l,a=""){const d=Kp(i),f=i?.length,m=l!==void 0;if(!d||m&&f!==l){const p=a&&`"${a}" `,_=m?` of length ${l}`:"",w=d?`length=${f}`:`type=${typeof i}`;throw new Error(p+"expected Uint8Array"+_+", got "+w)}return i}const hd=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",qp=Array.from({length:256},(i,l)=>l.toString(16).padStart(2,"0"));function Qp(i){if(bo(i),hd)return i.toHex();let l="";for(let a=0;a=_n._0&&i<=_n._9)return i-_n._0;if(i>=_n.A&&i<=_n.F)return i-(_n.A-10);if(i>=_n.a&&i<=_n.f)return i-(_n.a-10)}function Yp(i){if(typeof i!="string")throw new Error("hex string expected, got "+typeof i);if(hd)return Uint8Array.fromHex(i);const l=i.length,a=l/2;if(l%2)throw new Error("hex string expected, got unpadded hex of length "+l);const d=new Uint8Array(a);for(let f=0,m=0;ftypeof i=="bigint"&&md<=i;function th(i,l,a){return ni(i)&&ni(l)&&ni(a)&&l<=i&&iObject.entries(m).forEach(([_,w])=>d(_,w,p));f(l,!1),f(a,!0)}const gd=BigInt(0);function yd(i,l){const a=i%l;return a>=gd?a:l+a}function Gt(i,l,a){let d=i;for(;l-- >gd;)d*=d,d%=a;return d}function rh(i,l){return function(d){const f=i(d);return{secretKey:f,publicKey:l(f)}}}const Do=BigInt(0),Wr=BigInt(1),Qs=BigInt(2);function oh(i){return nh(i,{adjustScalarBytes:"function",powPminus2:"function"}),Object.freeze({...i})}function sh(i){const l=oh(i),{P:a,type:d,adjustScalarBytes:f,powPminus2:m,randomBytes:p}=l,_=d==="x25519";if(!_&&d!=="x448")throw new Error("invalid type");const w=p||Gp,E=_?255:448,T=_?32:56,N=BigInt(_?9:5),L=BigInt(_?121665:39081),O=_?Qs**BigInt(254):Qs**BigInt(447),B=_?BigInt(8)*Qs**BigInt(251)-Wr:BigInt(4)*Qs**BigInt(445)-Wr,W=O+B+Wr,F=q=>yd(q,a),ue=V(N);function V(q){return eh(F(q),T)}function $(q){const J=Jl(bo(q,T,"uCoordinate"));return _&&(J[31]&=127),F(Hu(J))}function re(q){return Hu(f(Jl(bo(q,T,"scalar"))))}function we(q,J){const le=be($(J),re(q));if(le===Do)throw new Error("invalid private or public key received");return V(le)}function de(q){return we(q,ue)}const _e=de,ke=we;function Ne(q,J,le){const te=F(q*(J-le));return J=F(J-te),le=F(le+te),{x_2:J,x_3:le}}function be(q,J){Vu("u",q,Do,a),Vu("scalar",J,O,W);const le=J,te=q;let P=Wr,U=Do,D=q,y=Wr,I=Do;for(let ae=BigInt(E-1);ae>=Do;ae--){const fe=le>>ae&Wr;I^=fe,{x_2:P,x_3:D}=Ne(I,P,D),{x_2:U,x_3:y}=Ne(I,U,y),I=fe;const ce=P+U,ee=F(ce*ce),me=P-U,ye=F(me*me),Re=ee-ye,ct=D+y,wt=D-y,Ae=F(wt*ce),Fe=F(ct*me),Ie=Ae+Fe,We=Ae-Fe;D=F(Ie*Ie),y=F(te*F(We*We)),P=F(ee*ye),U=F(Re*(ee+F(L*Re)))}({x_2:P,x_3:D}=Ne(I,P,D)),{x_2:U,x_3:y}=Ne(I,U,y);const ne=m(U);return F(P*ne)}const Se={secretKey:T,publicKey:T,seed:T},he=(q=w(T))=>(bo(q,Se.seed,"seed"),q),K={randomSecretKey:he};return Object.freeze({keygen:rh(he,_e),getSharedSecret:ke,getPublicKey:_e,scalarMult:we,scalarMultBase:de,utils:K,GuBytes:ue.slice(),lengths:Se})}const ih=BigInt(1),$u=BigInt(2),lh=BigInt(3),ah=BigInt(5);BigInt(8);const vd=BigInt("0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed");function ch(i){const l=BigInt(10),a=BigInt(20),d=BigInt(40),f=BigInt(80),m=vd,_=i*i%m*i%m,w=Gt(_,$u,m)*_%m,E=Gt(w,ih,m)*i%m,T=Gt(E,ah,m)*E%m,N=Gt(T,l,m)*T%m,L=Gt(N,a,m)*N%m,O=Gt(L,d,m)*L%m,B=Gt(O,f,m)*O%m,W=Gt(B,f,m)*O%m,F=Gt(W,l,m)*T%m;return{pow_p_5_8:Gt(F,$u,m)*i%m,b2:_}}function uh(i){return i[0]&=248,i[31]&=127,i[31]|=64,i}const wd=(()=>{const i=vd;return sh({P:i,type:"x25519",powPminus2:l=>{const{pow_p_5_8:a,b2:d}=ch(l);return yd(Gt(a,lh,i)*d,i)},adjustScalarBytes:uh})})();function dh(i){return i instanceof Uint8Array||ArrayBuffer.isView(i)&&i.constructor.name==="Uint8Array"}function vt(i,l,a=""){const d=dh(i),f=i?.length,m=l!==void 0;if(!d||m&&f!==l){const p=a&&`"${a}" `,_=m?` of length ${l}`:"",w=d?`length=${f}`:`type=${typeof i}`;throw new Error(p+"expected Uint8Array"+_+", got "+w)}return i}function ri(i,l=!0){if(i.destroyed)throw new Error("Hash instance has been destroyed");if(l&&i.finished)throw new Error("Hash#digest() has already been called")}function _d(i,l){vt(i,void 0,"output");const a=l.outputLen;if(i.length{function a(d,...f){if(vt(d,void 0,"key"),!ph)throw new Error("Non little-endian hardware is not yet supported");if(i.nonceLength!==void 0){const T=f[0];vt(T,i.varSizeNonce?void 0:i.nonceLength,"nonce")}const m=i.tagLength;m&&f[1]!==void 0&&vt(f[1],void 0,"AAD");const p=l(d,...f),_=(T,N)=>{if(N!==void 0){if(T!==2)throw new Error("cipher output not supported");vt(N,void 0,"output")}};let w=!1;return{encrypt(T,N){if(w)throw new Error("cannot encrypt() twice with same key + nonce");return w=!0,vt(T),_(p.encrypt.length,N),p.encrypt(T,N)},decrypt(T,N){if(vt(T),m&&T.length{const f=d&1;return{s3:a<<31|d>>>1,s2:l<<31|a>>>1,s1:i<<31|l>>>1,s0:i>>>1^vh<<24&-(f&1)}},zt=i=>(i>>>0&255)<<24|(i>>>8&255)<<16|(i>>>16&255)<<8|i>>>24&255|0;function _h(i){i.reverse();const l=i[15]&1;let a=0;for(let d=0;d>>1|a,a=(f&1)<<7}return i[0]^=-l&225,i}const kh=i=>i>64*1024?8:i>1024?4:2;class kd{blockLen=kn;outputLen=kn;s0=0;s1=0;s2=0;s3=0;finished=!1;t;W;windowSize;constructor(l,a){vt(l,16,"key"),l=ar(l);const d=ii(l);let f=d.getUint32(0,!1),m=d.getUint32(4,!1),p=d.getUint32(8,!1),_=d.getUint32(12,!1);const w=[];for(let B=0;B<128;B++)w.push({s0:zt(f),s1:zt(m),s2:zt(p),s3:zt(_)}),{s0:f,s1:m,s2:p,s3:_}=wh(f,m,p,_);const E=kh(a||1024);if(![1,2,4,8].includes(E))throw new Error("ghash: invalid window size, expected 2, 4 or 8");this.W=E;const N=128/E,L=this.windowSize=2**E,O=[];for(let B=0;B>>E-re-1&1))continue;const{s0:de,s1:_e,s2:ke,s3:Ne}=w[E*B+re];F^=de,ue^=_e,V^=ke,$^=Ne}O.push({s0:F,s1:ue,s2:V,s3:$})}this.t=O}_updateBlock(l,a,d,f){l^=this.s0,a^=this.s1,d^=this.s2,f^=this.s3;const{W:m,t:p,windowSize:_}=this;let w=0,E=0,T=0,N=0;const L=(1<>>8*W&255;for(let ue=8/m-1;ue>=0;ue--){const V=F>>>m*ue&L,{s0:$,s1:re,s2:we,s3:de}=p[O*_+V];w^=$,E^=re,T^=we,N^=de,O+=1}}this.s0=w,this.s1=E,this.s2=T,this.s3=N}update(l){ri(this),vt(l),l=ar(l);const a=xn(l),d=Math.floor(l.length/kn),f=l.length%kn;for(let m=0;mi(f,d.length).update(d).digest(),a=i(new Uint8Array(16),0);return l.outputLen=a.outputLen,l.blockLen=a.blockLen,l.create=(d,f)=>i(d,f),l}const Ku=xd((i,l)=>new kd(i,l));xd((i,l)=>new xh(i,l));const ea=16,Sh=4,Ys=new Uint8Array(ea),Ch=283;function Eh(i){if(![16,24,32].includes(i.length))throw new Error('"aes key" expected Uint8Array of length 16/24/32, got length='+i.length)}function la(i){return i<<1^Ch&-(i>>7)}function qu(i,l){let a=0;for(;l>0;l>>=1)a^=i&-(l&1),i=la(i);return a}const jh=(()=>{const i=new Uint8Array(256);for(let a=0,d=1;a<256;a++,d^=la(d))i[a]=d;const l=new Uint8Array(256);l[0]=99;for(let a=0;a<255;a++){let d=i[255-a];d|=d<<8,l[i[a]]=(d^d>>4^d>>5^d>>6^d>>7^99)&255}return Sn(i),l})(),Nh=i=>i<<24|i>>>8,Ql=i=>i<<8|i>>>24;function Ih(i,l){if(i.length!==256)throw new Error("Wrong sbox length");const a=new Uint32Array(256).map((E,T)=>l(i[T])),d=a.map(Ql),f=d.map(Ql),m=f.map(Ql),p=new Uint32Array(256*256),_=new Uint32Array(256*256),w=new Uint16Array(256*256);for(let E=0;E<256;E++)for(let T=0;T<256;T++){const N=E*256+T;p[N]=a[E]^d[T],_[N]=f[E]^m[T],w[N]=i[E]<<8|i[T]}return{sbox:i,sbox2:w,T0:a,T1:d,T2:f,T3:m,T01:p,T23:_}}const Sd=Ih(jh,i=>qu(i,3)<<24|i<<16|i<<8|qu(i,2)),Th=(()=>{const i=new Uint8Array(16);for(let l=0,a=1;l<16;l++,a=la(a))i[l]=a;return i})();function Lh(i){vt(i);const l=i.length;Eh(i);const{sbox2:a}=Sd,d=[];oi(i)||d.push(i=ar(i));const f=xn(i),m=f.length,p=w=>Po(a,w,w,w,w),_=new Uint32Array(l+28);_.set(f);for(let w=m;w<_.length;w++){let E=_[w-1];w%m===0?E=p(Nh(E))^Th[w/m-1]:m>6&&w%m===4&&(E=p(E)),_[w]=_[w-m]^E}return Sn(...d),_}function Gs(i,l,a,d,f,m){return i[a<<8&65280|d>>>8&255]^l[f>>>8&65280|m>>>24&255]}function Po(i,l,a,d,f){return i[l&255|a&65280]|i[d>>>16&255|f>>>16&65280]<<16}function Qu(i,l,a,d,f){const{sbox2:m,T01:p,T23:_}=Sd;let w=0;l^=i[w++],a^=i[w++],d^=i[w++],f^=i[w++];const E=i.length/4-2;for(let B=0;B>>0,_.setUint32(T,L,l),{s0:O,s1:B,s2:W,s3:F}=Qu(i,p[0],p[1],p[2],p[3]);const ue=ea*Math.floor(w.length/Sh);if(uel+=String.fromCharCode(a)),btoa(l)}function si(i){const l=atob(i),a=new Uint8Array(l.length);for(let d=0;df.abort(),d);try{const p=await fetch(l,{...a,signal:f.signal}),_=await p.arrayBuffer();return new Response(_,{status:p.status,statusText:p.statusText,headers:p.headers})}catch(p){throw p?.name==="AbortError"?new Error("Request timed out"):p}finally{window.clearTimeout(m)}}async fetchWithRetry(l,a,d){let f=null;const m=Date.now()+Mh;for(let p=1;p<=Gl;p+=1){try{const w=m-Date.now();if(w<=0)throw f??new Error("Relay request retry budget exceeded");const E=await this.fetchWithTimeout(l,a,Math.min(d,w));if(zh.has(E.status)&&p=m)throw f??new Error("Relay request retry budget exceeded");await new Promise(w=>window.setTimeout(w,_))}throw f}async pair(l,a){this.keyPair=await Ph();const d=si(l);this.sharedKey=await bh(this.keyPair,d);const f=a.mobileInstallId,m=this.getMobileDeviceName(),p=a.userId.trim(),_=a.mobileInstallId.trim(),w=a.password&&a.password.length>0?a.password:void 0,E=await this.fetchWithRetry(`${this.relayUrl}/api/rooms/${encodeURIComponent(this.roomId)}/pair`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({public_key:ta(this.keyPair.publicKey),device_id:f,device_name:m})},35e3);if(!E.ok)throw new Error(`Pairing failed: HTTP ${E.status}`);const T=await E.json(),N=await Xs(this.sharedKey,T.encrypted_data,T.nonce),O={challenge_echo:JSON.parse(N).challenge,device_id:f,device_name:m,mobile_install_id:_,user_id:p};w&&(O.password=w);const{data:B,nonce:W}=await Yl(this.sharedKey,JSON.stringify(O)),F=await this.fetchWithTimeout(`${this.relayUrl}/api/rooms/${encodeURIComponent(this.roomId)}/command`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({encrypted_data:B,nonce:W})},65e3);if(!F.ok)throw new Error(`Pairing verification failed: HTTP ${F.status}`);const ue=await F.json(),V=await Xs(this.sharedKey,ue.encrypted_data,ue.nonce),$=JSON.parse(V);if($?.resp==="error")throw new Error($?.message||"Pairing rejected");return $}async requestDelegatedIdentity(l){if(!l?.force&&this.hasDelegatedIdentity)return!0;const a=++this.delegatedIdentityRequestEpoch;l?.force&&(this.delegatedIdentityRefreshOwner=a);try{const d=await this.sendCommand({cmd:"get_delegated_identity"},{retryable:!0});if(this.delegatedIdentityRequestEpoch!==a)return!1;if(d?.resp==="delegate_identity"&&d.token&&d.master_key){const f=d.device_id??null,m={token:d.token,masterKey:si(d.master_key),userId:d.user_id??null,homeDeviceId:f,generation:++this.delegatedIdentityGenerationValue};this.delegatedIdentity=m;const p={userId:m.userId,masterKey:m.masterKey.slice(),homeDeviceId:m.homeDeviceId},_=Oh(this.delegatedAccountIdentity,p),w=this.delegatedAccountIdentity!==null;_&&(this.delegatedAccountEpochValue+=1),this.delegatedAccountIdentity=p;const E=this.homeDeviceId,T=this.pairedDeviceIdValue===null||this.pairedDeviceIdValue===E;return this.homeDeviceId=f,_?this.setPairedDeviceId(f):T&&(this.pairedDeviceIdValue=f),_&&this.emitDelegatedAccountOwnerChange({kind:w?"replacement":"initial",epoch:this.delegatedAccountEpochValue,userId:m.userId,homeDeviceId:f}),!0}return this.commitDelegatedAccountUnavailable(),!1}finally{this.delegatedIdentityRefreshOwner===a&&(this.delegatedIdentityRefreshOwner=null)}}clearDelegatedIdentity(){this.delegatedIdentityRequestEpoch+=1,this.delegatedIdentityRefreshOwner=null,this.delegatedIdentity&&(this.delegatedIdentityGenerationValue+=1),this.delegatedIdentity=null}resetConnectionIdentity(){const l=this.controlTargetEpochValue;this.clearDelegatedIdentity(),this.commitDelegatedAccountUnavailable(),this.controlTargetEpochValue===l&&this.setPairedDeviceId(null)}onDelegatedAccountOwnerChange(l,a){return this.delegatedAccountOwnerListeners.add(l),a?.emitCurrent&&this.delegatedAccountIdentity&&l({kind:"initial",epoch:this.delegatedAccountEpochValue,userId:this.delegatedAccountIdentity.userId,homeDeviceId:this.delegatedAccountIdentity.homeDeviceId}),()=>this.delegatedAccountOwnerListeners.delete(l)}emitDelegatedAccountOwnerChange(l){for(const a of this.delegatedAccountOwnerListeners)a(l)}commitDelegatedAccountUnavailable(){if(this.delegatedIdentity&&(this.delegatedIdentityGenerationValue+=1),this.delegatedIdentity=null,!this.delegatedAccountIdentity){const l=this.pairedDeviceIdValue===null||this.pairedDeviceIdValue===this.homeDeviceId;this.homeDeviceId=null,l?this.pairedDeviceIdValue=null:this.setPairedDeviceId(null);return}this.delegatedAccountEpochValue+=1,this.delegatedAccountIdentity=null,this.homeDeviceId=null,this.setPairedDeviceId(null),this.emitDelegatedAccountOwnerChange({kind:"unavailable",epoch:this.delegatedAccountEpochValue,userId:null,homeDeviceId:null})}async sendCommand(l,a={}){if(!this.sharedKey)throw new Error("Not paired");const d=JSON.stringify(l),{data:f,nonce:m}=await Yl(this.sharedKey,d),p=JSON.stringify({encrypted_data:f,nonce:m}),_=await(a.retryable?this.fetchWithRetry:this.fetchWithTimeout).call(this,`${this.relayUrl}/api/rooms/${encodeURIComponent(this.roomId)}/command`,{method:"POST",headers:{"Content-Type":"application/json"},body:p},a.retryable?2e4:65e3);if(!_.ok)throw new Error(`Command failed: HTTP ${_.status}`);const w=await _.json(),E=await Xs(this.sharedKey,w.encrypted_data,w.nonce);return JSON.parse(E)}get isPaired(){return this.sharedKey!==null}get hasDelegatedIdentity(){return this.delegatedIdentity!==null}get pairedDeviceId(){return this.pairedDeviceIdValue}setPairedDeviceId(l){this.pairedDeviceIdValue=l,this.controlTargetEpochValue+=1;const a=this.getControlTargetSnapshot();for(const d of this.controlTargetListeners)d(a)}get controlTargetEpoch(){return this.controlTargetEpochValue}getControlTargetSnapshot(){return{deviceId:this.pairedDeviceIdValue,homeDeviceId:this.homeDeviceId,epoch:this.controlTargetEpochValue}}isControlTargetCurrent(l){return l.epoch===this.controlTargetEpochValue}onControlTargetChange(l){return this.controlTargetListeners.add(l),()=>this.controlTargetListeners.delete(l)}get delegatedIdentityGeneration(){return this.delegatedIdentityGenerationValue}get delegatedAccountEpoch(){return this.delegatedAccountEpochValue}get delegatedUserId(){return this.delegatedIdentity?.userId??null}requireDelegatedIdentity(){const l=this.delegatedIdentity;if(!l)throw new Error("No delegated identity");return l}isDelegatedIdentityCurrent(l){return this.delegatedIdentity?.generation===l.generation&&this.delegatedIdentityGenerationValue===l.generation&&this.delegatedIdentityRefreshOwner===null}ensureDelegatedIdentityCurrent(l,a){if(!this.isDelegatedIdentityCurrent(l))throw this.delegatedIdentityChangeError(a)}delegatedIdentityChangeError(l){return this.delegatedAccountEpochValue===l?new aa:new Yu}async refreshDelegatedIdentityAfterUnauthorized(l){if(!this.isDelegatedIdentityCurrent(l))return this.hasDelegatedIdentity;try{return await this.requestDelegatedIdentity({force:!0})}catch{return!1}}async listDevices(){return this.withDelegatedAuthRetry(async l=>{const a=await this.fetchWithRetry(`${this.relayUrl}/api/devices`,{headers:{Authorization:`Bearer ${l.token}`}},2e4);if(!a.ok){const d=new Error(`List devices failed: HTTP ${a.status}`);throw d.status=a.status,d}return a.json()},{allowAccountReplacementRetry:!0})}async sendDeviceRpc(l,a,d={}){return this.withDelegatedAuthRetry(async f=>{const m=JSON.stringify(a),{data:p,nonce:_}=await Yl(f.masterKey,m),w=await(d.retryable?this.fetchWithRetry:this.fetchWithTimeout).call(this,`${this.relayUrl}/api/devices/${encodeURIComponent(l)}/rpc`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${f.token}`},body:JSON.stringify({encrypted_data:p,nonce:_})},d.retryable?2e4:13e4);if(!w.ok){const L=new Error(`Device RPC failed: HTTP ${w.status}`);throw L.status=w.status,L}const E=await w.json(),T=await Xs(f.masterKey,E.encrypted_data,E.nonce),N=JSON.parse(T);if(N?.resp==="error")throw new Error(N.message||"Remote error");return N},{allowAccountReplacementRetry:!1})}async withDelegatedAuthRetry(l,a){let d=this.requireDelegatedIdentity();const f=this.delegatedAccountEpochValue;this.ensureDelegatedIdentityCurrent(d,f);try{const m=await l(d);return this.ensureDelegatedIdentityCurrent(d,f),m}catch(m){if(!this.isDelegatedIdentityCurrent(d))throw this.delegatedIdentityChangeError(f);const p=m?.status,_=String(m?.message||m);if(!(p===401||_.includes("HTTP 401")||_.includes("Unauthorized")))throw m;if(!await this.refreshDelegatedIdentityAfterUnauthorized(d))throw new Error("No delegated identity");if(!a.allowAccountReplacementRetry&&this.delegatedAccountEpochValue!==f)throw new Yu;d=this.requireDelegatedIdentity();const T=await l(d);return this.ensureDelegatedIdentityCurrent(d,this.delegatedAccountEpochValue),T}}getMobileDeviceName(){const l=navigator.userAgent;return/iPhone/i.test(l)?"iPhone":/iPad/i.test(l)?"iPad":/Android/i.test(l)?"Android":"Mobile Browser"}}class jd extends Error{constructor(){super("Remote control target changed"),this.name="RemoteControlTargetChangedError"}}function Mt(i){return i instanceof jd}const Fh=new Set(["get_workspace_info","list_recent_workspaces","list_assistants","list_sessions","get_session_messages","get_model_catalog","poll_session","ping","get_file_info","read_file_chunk"]);class Wh{client;constructor(l){this.client=l}get controlTargetEpoch(){return this.client.controlTargetEpoch}onControlTargetChange(l){return this.client.onControlTargetChange(l)}ensureControlTargetCurrent(l){if(!this.client.isControlTargetCurrent(l))throw new jd}async request(l,a=this.client.getControlTargetSnapshot()){this.ensureControlTargetCurrent(a);const d=`req_${Date.now()}_${Math.random().toString(36).slice(2,8)}`,f={...l,_request_id:d},m=l.cmd,p=typeof m=="string"&&Fh.has(m),_=a.deviceId,w=!!_&&_!==a.homeDeviceId;try{let E;w&&_?E=await this.client.sendDeviceRpc(_,f,{retryable:p}):E=await this.client.sendCommand(f,{retryable:p}),this.ensureControlTargetCurrent(a);const T=E;if(T.resp==="error")throw new Error(T.message||"Unknown error");return E}catch(E){throw this.ensureControlTargetCurrent(a),E}}async getWorkspaceInfo(){const l=await this.request({cmd:"get_workspace_info"});return{has_workspace:l.has_workspace,path:l.path,project_name:l.project_name,git_branch:l.git_branch,workspace_kind:l.workspace_kind,assistant_id:l.assistant_id,remote_connection_id:l.remote_connection_id,remote_ssh_host:l.remote_ssh_host}}async listRecentWorkspaces(){return(await this.request({cmd:"list_recent_workspaces"})).workspaces||[]}async setWorkspace(l,a){return this.request({cmd:"set_workspace",path:l,remote_connection_id:a?.remoteConnectionId,remote_ssh_host:a?.remoteSshHost})}async listAssistants(){return(await this.request({cmd:"list_assistants"})).assistants||[]}async setAssistant(l){return this.request({cmd:"set_assistant",path:l})}async listSessions(l,a=30,d=0,f,m){const p=await this.request({cmd:"list_sessions",workspace_path:l??null,remote_connection_id:m?.remoteConnectionId,remote_ssh_host:m?.remoteSshHost,limit:a,offset:d,query:f?.trim()||null});return{sessions:p.sessions||[],has_more:p.has_more??!1}}async createSession(l,a,d,f){return(await this.request({cmd:"create_session",agent_type:l||void 0,session_name:a||void 0,workspace_path:d??null,remote_connection_id:f?.remoteConnectionId,remote_ssh_host:f?.remoteSshHost})).session_id}async getSessionMessages(l,a,d){const f=await this.request({cmd:"get_session_messages",session_id:l,limit:a,before_message_id:d});return{messages:f.messages||[],has_more:f.has_more||!1}}async getModelCatalog(l){return(await this.request({cmd:"get_model_catalog",session_id:l??void 0})).catalog}async setSessionModel(l,a){return(await this.request({cmd:"set_session_model",session_id:l,model_id:a})).model_id}async setSessionModelSelection(l,a,d){const f=await this.request({cmd:"set_session_model",session_id:l,model_id:a,reasoning_preset:d});return{model_id:f.model_id,reasoning_preset:f.reasoning_preset??null}}async sendMessage(l,a,d,f){return(await this.request({cmd:"send_message",session_id:l,content:a,agent_type:d||void 0,image_contexts:f&&f.length>0?f:void 0})).turn_id}async cancelTask(l,a){await this.request({cmd:"cancel_task",session_id:l,turn_id:a??void 0})}async cancelTool(l,a){await this.request({cmd:"cancel_tool",tool_id:l,reason:a??void 0})}async deleteSession(l){await this.request({cmd:"delete_session",session_id:l})}async renameSession(l,a){await this.request({cmd:"update_session_title",session_id:l,title:a})}async answerQuestion(l,a){await this.request({cmd:"answer_question",tool_id:l,answers:a})}async pollSession(l,a,d,f=0){return this.request({cmd:"poll_session",session_id:l,since_version:a,known_msg_count:d,known_model_catalog_version:f})}async ping(){await this.request({cmd:"ping"})}async getFileInfo(l,a){const d=await this.request({cmd:"get_file_info",path:l,session_id:a??void 0});return{name:d.name,size:d.size,mimeType:d.mime_type}}async readFile(l,a,d){let m=0;const p=[];let _="",w="",E=0;const T=this.client.getControlTargetSnapshot();for(;;){const N=await this.request({cmd:"read_file_chunk",path:l,session_id:a??void 0,offset:m,limit:3145728},T);if(this.ensureControlTargetCurrent(T),p.push(N.chunk_base64),_=N.name,w=N.mime_type,E=N.total_size,m+=N.chunk_size,d?.(Math.min(m,E),E),m>=E||N.chunk_size===0)break}return this.ensureControlTargetCurrent(T),{name:_,contentBase64:p.join(""),mimeType:w,size:E}}}class Im{intervalId=null;sinceVersion=0;knownMsgCount=0;sessionId;sessionMgr;onUpdate;polling=!1;stopped=!1;hasActiveTurn=!1;knownModelCatalogVersion=0;turnJustEndedAt=null;TURN_JUST_ENDED_GRACE_PERIOD_MS=5e3;constructor(l,a,d,f=0){this.sessionMgr=l,this.sessionId=a,this.onUpdate=d,this.knownModelCatalogVersion=f}start(l=0){this.stopped=!1,this.knownMsgCount=l,this.tick(),document.addEventListener("visibilitychange",this.onVisibilityChange)}stop(){this.stopped=!0,this.intervalId!==null&&(clearTimeout(this.intervalId),this.intervalId=null),document.removeEventListener("visibilitychange",this.onVisibilityChange)}resetCursors(){this.sinceVersion=0,this.knownMsgCount=0}setKnownModelCatalogVersion(l){this.knownModelCatalogVersion=l}nudge(){this.hasActiveTurn=!0,this.intervalId!==null&&clearTimeout(this.intervalId),this.tick()}getInterval(){if(document.visibilityState!=="visible")return 5e3;const l=Date.now();return this.turnJustEndedAt!=null&&l-this.turnJustEndedAtthis.tick(),this.getInterval()))}onVisibilityChange=()=>{this.stopped||(document.visibilityState==="visible"?(this.intervalId!==null&&clearTimeout(this.intervalId),this.tick()):this.scheduleNext())};async tick(){if(this.stopped||this.polling){this.scheduleNext();return}this.polling=!0;try{const l=await this.sessionMgr.pollSession(this.sessionId,this.sinceVersion,this.knownMsgCount,this.knownModelCatalogVersion);if(l.changed){const a=this.hasActiveTurn,d=l.active_turn!=null&&l.active_turn.status==="active";this.hasActiveTurn=d,a&&!d&&(this.turnJustEndedAt=Date.now()),(l.new_messages&&l.new_messages.length>0||l.message_snapshot)&&(this.turnJustEndedAt=null),this.sinceVersion=l.version,l.total_msg_count!=null&&(this.knownMsgCount=l.total_msg_count),l.model_catalog?.version!=null&&(this.knownModelCatalogVersion=l.model_catalog.version),this.onUpdate(l)}}catch(l){console.error("[Poller] poll error",l)}finally{this.polling=!1,this.scheduleNext()}}}const Gu=i=>{let l;const a=new Set,d=(E,T)=>{const N=typeof E=="function"?E(l):E;if(!Object.is(N,l)){const L=l;l=T??(typeof N!="object"||N===null)?N:Object.assign({},l,N),a.forEach(O=>O(l,L))}},f=()=>l,_={setState:d,getState:f,getInitialState:()=>w,subscribe:E=>(a.add(E),()=>a.delete(E))},w=l=i(d,f,_);return _},Hh=(i=>i?Gu(i):Gu),Vh=i=>i;function $h(i,l=Vh){const a=Vr.useSyncExternalStore(i.subscribe,Vr.useCallback(()=>l(i.getState()),[i,l]),Vr.useCallback(()=>l(i.getInitialState()),[i,l]));return Vr.useDebugValue(a),a}const Zu=i=>{const l=Hh(i),a=d=>$h(l,d);return Object.assign(a,l),a},Kh=(i=>i?Zu(i):Zu),Ut=Kh((i,l)=>({connectionStatus:"idle",setConnectionStatus:a=>i({connectionStatus:a}),connectionHealth:"unpaired",setConnectionHealth:a=>i({connectionHealth:a}),currentWorkspace:null,setCurrentWorkspace:a=>i({currentWorkspace:a}),currentAssistant:null,setCurrentAssistant:a=>i({currentAssistant:a}),pairedDisplayMode:null,setPairedDisplayMode:a=>i({pairedDisplayMode:a}),authenticatedUserId:null,setAuthenticatedUserId:a=>i({authenticatedUserId:a}),authenticatedUserLabel:null,setAuthenticatedUserLabel:a=>i({authenticatedUserLabel:a}),controlTarget:null,setControlTarget:a=>i({controlTarget:a}),sessions:[],setSessions:a=>i({sessions:a}),appendSessions:a=>i(d=>({sessions:[...d.sessions,...a]})),updateSessionName:(a,d)=>i(f=>({sessions:f.sessions.map(m=>m.session_id===a?{...m,name:d}:m)})),removeSession:a=>i(d=>{const{[a]:f,...m}=d.messagesBySession;return{sessions:d.sessions.filter(p=>p.session_id!==a),messagesBySession:m}}),activeSessionId:null,setActiveSessionId:a=>i({activeSessionId:a}),messagesBySession:{},deletedMessageIds:{},getMessages:a=>{const d=l().messagesBySession[a]||[],f=l().deletedMessageIds[a];return f?d.filter(m=>!f.has(m.id)):d},setMessages:(a,d)=>i(f=>{const m=f.deletedMessageIds[a],p=m?d.filter(_=>!m.has(_.id)):d;return{messagesBySession:{...f.messagesBySession,[a]:p}}}),appendNewMessages:(a,d)=>i(f=>{if(d.length===0)return f;const m=f.messagesBySession[a]||[],p=new Set(m.map(E=>E.id)),_=f.deletedMessageIds[a],w=d.filter(E=>!p.has(E.id)&&!_?.has(E.id));return w.length===0?f:{messagesBySession:{...f.messagesBySession,[a]:[...m,...w]}}}),deleteMessage:(a,d)=>i(f=>{const m=f.messagesBySession[a],p=new Set(f.deletedMessageIds[a]||[]);return p.add(d),{deletedMessageIds:{...f.deletedMessageIds,[a]:p},messagesBySession:m?{...f.messagesBySession,[a]:m.filter(_=>_.id!==d)}:f.messagesBySession}}),activeTurn:null,setActiveTurn:a=>i({activeTurn:a}),error:null,setError:a=>i({error:a}),resetConnectionState:()=>i({connectionStatus:"idle",currentWorkspace:null,currentAssistant:null,pairedDisplayMode:null,authenticatedUserId:null,authenticatedUserLabel:null,controlTarget:null,sessions:[],activeSessionId:null,messagesBySession:{},deletedMessageIds:{},activeTurn:null,error:null}),resetForDeviceSwitch:()=>i({currentWorkspace:null,currentAssistant:null,pairedDisplayMode:null,sessions:[],activeSessionId:null,messagesBySession:{},deletedMessageIds:{},activeTurn:null,error:null})})),Nd="bitfun-mobile-theme";function qh(i){const l=document.documentElement;l.setAttribute("data-bf-design-system-root",""),l.setAttribute("data-color-scheme",i),l.setAttribute("data-contrast","standard"),l.setAttribute("data-density","comfortable"),l.style.colorScheme=i,document.querySelector('meta[name="theme-color"]')?.setAttribute("content",String(ad[i]["color.surface.canvas"]))}function Qh(){const i=document.documentElement.getAttribute("data-color-scheme");if(i==="dark"||i==="light")return i;try{const l=localStorage.getItem(Nd);if(l==="dark"||l==="light")return l}catch{}return window.matchMedia?.("(prefers-color-scheme: light)").matches?"light":"dark"}const Id=C.createContext({themeId:"dark",isDark:!0,setTheme:()=>{},toggleTheme:()=>{}}),Yh=280;let Xu;const Gh=({children:i})=>{const[l,a]=C.useState(Qh);C.useLayoutEffect(()=>{const m=document.documentElement,p=m.getAttribute("data-color-scheme"),_=p!=null&&p!==l;_&&(clearTimeout(Xu),m.classList.add("theme-switching"),m.offsetHeight),qh(l),_&&(Xu=setTimeout(()=>{m.classList.remove("theme-switching")},Yh+40));try{localStorage.setItem(Nd,l)}catch{}},[l]);const d=C.useCallback(m=>a(m),[]),f=C.useCallback(()=>a(m=>m==="dark"?"light":"dark"),[]);return c.jsx(Id.Provider,{value:{themeId:l,isDark:l==="dark",setTheme:d,toggleTheme:f},children:i})};function Td(){return C.useContext(Id)}const Ld=""+new URL("Logo-ICON-BOaKcXgO.png",import.meta.url).href,Zh=({isDark:i})=>c.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:i?c.jsx("path",{d:"M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM3 8a5 5 0 0 1 5-5v10a5 5 0 0 1-5-5Z",fill:"currentColor"}):c.jsx("path",{d:"M8 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 1Zm0 11a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 12Zm7-4a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 15 8ZM3 8a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 3 8Zm9.95-3.54a.5.5 0 0 1 0 .71l-.71.7a.5.5 0 1 1-.7-.7l.7-.71a.5.5 0 0 1 .71 0ZM5.46 11.24a.5.5 0 0 1 0 .71l-.7.71a.5.5 0 0 1-.71-.71l.7-.71a.5.5 0 0 1 .71 0Zm7.08 1.42a.5.5 0 0 1-.7 0l-.71-.71a.5.5 0 0 1 .7-.7l.71.7a.5.5 0 0 1 0 .71ZM5.46 4.76a.5.5 0 0 1-.71 0l-.71-.7a.5.5 0 0 1 .71-.71l.7.7a.5.5 0 0 1 0 .71ZM8 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z",fill:"currentColor"})}),Ju="bitfun.mobile.install_id",ed="bitfun.mobile.user_id",lr="bitfun.mobile.user_id_lock_until",Hr="bitfun.mobile.user_id_failure_count",Xh=3,td=6e4;function Jh(i){return i.includes("This remote URL is already protected")||i.includes("This mobile device must continue using the previously confirmed user ID")||i.includes("Invalid username or password")||i.includes("Missing password")||i.includes("Missing username")||i.includes("Too many pairing attempts")}function em(i){try{const l=i.replace(/^wss:\/\//,"https://").replace(/^ws:\/\//,"http://").replace(/\/ws\/?$/,"").replace(/\/$/,""),a=new URL(l);return!["http:","https:"].includes(a.protocol)||!a.hostname||a.username||a.password||a.search||a.hash?null:a.toString().replace(/\/$/,"")}catch{return null}}function tm(i,l){return!!i&&i.length<=128&&/^[A-Za-z0-9_-]+$/.test(i)&&!["_store","page-data","pages"].includes(i)&&!!l&&l.length<=512&&/^[A-Za-z0-9+/=_-]+$/.test(l)}function nm(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`mobile-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`}function nd(){const i=localStorage.getItem(Ju)?.trim();if(i)return i;const l=nm();return localStorage.setItem(Ju,l),l}function rm(){const i=window.location.hash,l=new URLSearchParams(i.replace(/^#\/pair\?/,"")),a=l.get("room"),d=l.get("pk"),f=l.get("relay"),m=l.get("auth")==="account",p=l.get("user")?.trim()||null;if(f)return{room:a,pk:d,httpBaseUrl:em(f)??"",accountAuth:m,accountUsername:p};const _=window.location.origin,w=window.location.pathname.replace(/\/[^/]*$/,"").replace(/\/r\/[^/]*$/,"");return{room:a,pk:d,httpBaseUrl:_+w,accountAuth:m,accountUsername:p}}const om=({onPaired:i})=>{const{t:l}=$r(),{isDark:a,toggleTheme:d}=Td(),{connectionStatus:f,setConnectionStatus:m,setError:p,error:_,setAuthenticatedUserId:w,setAuthenticatedUserLabel:E}=Ut(),[T,N]=C.useState(""),[L,O]=C.useState(""),[B,W]=C.useState(!1),[F,ue]=C.useState(0),[V,$]=C.useState(null),[re,we]=C.useState(()=>Date.now()),de=C.useRef(0),_e=C.useRef(null),ke=C.useRef(0),Ne=C.useRef(async()=>{}),be=C.useRef(i);be.current=i;const Se=C.useMemo(()=>rm(),[]),he=Se.accountAuth,K=!!V&&V>re,q=K?Math.max(1,Math.ceil((V-re)/1e3)):0,J=C.useCallback(async(D,y,I)=>{const ne=Se.room,ae=Se.pk,fe=D.trim(),ce=y,ee=I?.autoReconnect===!0,me=I?.installId||nd(),ye=_e.current,Re=!!ye&&ye>Date.now(),ct=Re?Math.max(1,Math.ceil((ye-Date.now())/1e3)):0,wt=++ke.current,Ae=()=>ke.current===wt;if(!ne||!ae||!tm(ne,ae)||!Se.httpBaseUrl){if(!Ae())return;p(l("pairing.invalidQrCode")),m("error");return}if(!fe){if(!Ae())return;p(l(he?"pairing.usernameRequired":"pairing.userIdRequired")),m("error");return}if(fe.length>128||ce.length>1024){if(!Ae())return;p(l("pairing.fieldsTooLong")),m("error");return}if(he&&!ce){if(!Ae())return;p(l("pairing.passwordRequired")),m("error");return}if(!ee&&Re){if(!Ae())return;p(l("pairing.tooManyAttempts",{seconds:ct})),m("error");return}W(!0),p(null),m("pairing");const Fe=new Bh(Se.httpBaseUrl,ne);try{const Ie=await Fe.pair(ae,{userId:fe,mobileInstallId:me,password:he?ce:void 0});if(!Ae())return;m("paired"),localStorage.setItem(ed,fe),localStorage.removeItem(Hr),localStorage.removeItem(lr),ue(0),$(null),O(""),w(Ie.authenticated_user_id??(he?null:fe)),E(fe);const We=new Wh(Fe),He=Ut.getState();Ie.has_workspace&&(Ie.workspace_kind==="assistant"&&Ie.path?(He.setPairedDisplayMode("assistant"),He.setCurrentAssistant({path:Ie.path,name:Ie.project_name??"Claw",assistant_id:Ie.assistant_id}),He.setCurrentWorkspace(null)):(He.setPairedDisplayMode("pro"),He.setCurrentWorkspace({has_workspace:!0,path:Ie.path,project_name:Ie.project_name,git_branch:Ie.git_branch,workspace_kind:Ie.workspace_kind,assistant_id:Ie.assistant_id,remote_connection_id:Ie.remote_connection_id,remote_ssh_host:Ie.remote_ssh_host}))),Ie.sessions&&He.setSessions(Ie.sessions);try{const Et=await Promise.race([Fe.requestDelegatedIdentity(),new Promise(tt=>{window.setTimeout(()=>tt(!1),1e4)})]);if(!Ae())return;const Qe=Fe.homeDeviceId;if(Et&&Qe){He.setControlTarget({deviceId:Qe,deviceName:null,isHome:!0});const tt=Fe.delegatedAccountEpoch,Ot=Fe.getControlTargetSnapshot();Fe.listDevices().then(rn=>{if(Fe.delegatedAccountEpoch!==tt||!Fe.isControlTargetCurrent(Ot)||Fe.pairedDeviceId!==Qe)return;const qn=rn.find(Bt=>Bt.device_id===Qe);qn&&Ut.getState().setControlTarget({deviceId:Qe,deviceName:qn.device_name,isHome:!0})}).catch(()=>{})}}catch{}if(!Ae())return;be.current(Fe,We)}catch(Ie){if(!Ae())return;const We=Ie?.message||"",He=We.includes("timed out")?l("pairing.requestTimedOut"):We.includes("HTTP 404")?l("pairing.qrExpired"):We.includes("HTTP 429")?l("pairing.rateLimited"):We.includes("HTTP 503")||We.includes("HTTP 504")?l("pairing.relayUnavailable"):We||l("pairing.pairingFailed");if(!ee&&Jh(He)){const Et=de.current+1,Qe=Et>=Xh,tt=Qe?Date.now()+td:null;localStorage.setItem(Hr,String(Et)),tt?localStorage.setItem(lr,String(tt)):localStorage.removeItem(lr),ue(Et),$(tt),p(Qe?l("pairing.tooManyAttempts",{seconds:Math.ceil(td/1e3)}):We.includes("Too many pairing attempts")?l("pairing.rateLimited"):l("pairing.credentialsRejected"))}else p(He);m("error")}finally{Ae()&&W(!1)}},[Se.httpBaseUrl,Se.pk,Se.room,he,w,E,m,p,l]);Ne.current=J,C.useEffect(()=>{const D=localStorage.getItem(ed)?.trim()??"",I=(Se.accountUsername?.trim()??"")||D,ne=nd(),ae=Number(localStorage.getItem(Hr)||"0"),fe=Number(localStorage.getItem(lr)||"0"),ce=fe>Date.now()?fe:null;fe&&!ce&&(localStorage.removeItem(lr),localStorage.removeItem(Hr));const ee=!he&&!!D&&!!ne&&!!Se.room&&!!Se.pk;return N(I),ue(ce?ae:0),$(ce),p(null),ee?(m("pairing"),Ne.current(D,"",{autoReconnect:!0,installId:ne})):m("idle"),()=>{ke.current+=1}},[]),C.useEffect(()=>{de.current=F,_e.current=V},[F,V]),C.useEffect(()=>{if(!V)return;if(V<=Date.now()){$(null),ue(0),localStorage.removeItem(lr),localStorage.removeItem(Hr);return}const D=window.setInterval(()=>{const y=Date.now();we(y),V<=y&&($(null),ue(0),localStorage.removeItem(lr),localStorage.removeItem(Hr))},1e3);return()=>window.clearInterval(D)},[V]);const le=async()=>{await J(T,L,{autoReconnect:!1})},te={idle:l(he?"pairing.enterAccountToContinue":"pairing.enterUserIdToContinue"),pairing:l("pairing.connectingAndPairing"),paired:l("pairing.pairedLoadingSessions"),error:l("pairing.connectionError")},P=f==="pairing",U=f==="idle"||f==="error";return c.jsxs("div",{className:"pairing-page",children:[c.jsxs("div",{className:"pairing-page__actions",children:[c.jsx(sa,{}),c.jsx("button",{className:"pairing-page__theme-btn",onClick:d,"aria-label":l("common.toggleTheme"),children:c.jsx(Zh,{isDark:a})})]}),c.jsx("img",{src:Ld,alt:"BitFun",className:"pairing-page__logo"}),c.jsx("div",{className:"pairing-page__brand",children:l("shared.product.remote")}),c.jsx("div",{className:"pairing-page__spinner-wrap",children:P&&c.jsx("div",{className:"spinner"})}),c.jsx("div",{className:"pairing-page__state",children:te[f]||f}),U&&c.jsxs("div",{className:"pairing-page__form",children:[c.jsxs("label",{className:"pairing-page__field",children:[c.jsx("span",{className:"pairing-page__field-label",children:l(he?"pairing.usernameLabel":"pairing.fieldLabel")}),c.jsx("input",{className:"pairing-page__input",type:"text",value:T,onChange:D=>N(D.target.value),placeholder:l(he?"pairing.usernamePlaceholder":"pairing.placeholder"),autoCapitalize:"off",autoCorrect:"off",autoComplete:"username",maxLength:128,disabled:B||K})]}),he&&c.jsxs("label",{className:"pairing-page__field",children:[c.jsx("span",{className:"pairing-page__field-label",children:l("pairing.passwordLabel")}),c.jsx("input",{className:"pairing-page__input",type:"password",value:L,onChange:D=>O(D.target.value),placeholder:l("pairing.passwordPlaceholder"),autoComplete:"current-password",maxLength:1024,disabled:B||K})]}),c.jsx("p",{className:"pairing-page__note",children:l(he?"pairing.accountNote":"pairing.note")}),c.jsx("button",{className:"pairing-page__retry",onClick:le,disabled:B||K,children:B?l("pairing.connecting"):K?l("pairing.retryIn",{seconds:q}):l("pairing.continue")})]}),_&&c.jsx("div",{className:"pairing-page__error",children:_})]})},sm=({sessionMgr:i,onReady:l})=>{const{t:a}=$r(),[d,f]=C.useState(null),[m,p]=C.useState([]),[_,w]=C.useState(!0),[E,T]=C.useState(!1),[N,L]=C.useState(null),[O,B]=C.useState(!1),W=C.useCallback(async()=>{try{const $=await i.getWorkspaceInfo();f($)}catch($){L($.message)}finally{w(!1)}},[i]),F=C.useCallback(async()=>{try{const $=await i.listRecentWorkspaces();p($)}catch($){L($.message)}},[i]);C.useEffect(()=>{W()},[W]);const ue=async()=>{B(!0),await F()},V=C.useCallback(async $=>{if(!E){T(!0),L(null);try{const re=await i.setWorkspace($.path,{remoteConnectionId:$.remote_connection_id,remoteSshHost:$.remote_ssh_host});re.success?(await W(),B(!1)):L(re.error||a("workspace.failedToSetWorkspace"))}catch(re){L(re.message)}finally{T(!1)}}},[W,i,E,a]);return _?c.jsx("div",{className:"workspace-page",children:c.jsxs("div",{className:"workspace-page__loading",children:[c.jsx("div",{className:"spinner"}),c.jsx("span",{children:a("workspace.loadingInfo")})]})}):c.jsxs("div",{className:"workspace-page",children:[c.jsxs("div",{className:"workspace-page__header",children:[c.jsx("h1",{children:a("shared.features.workspace")}),c.jsx(sa,{})]}),c.jsxs("div",{className:"workspace-page__content",children:[d?.has_workspace?c.jsxs("div",{className:"workspace-page__current",children:[c.jsx("div",{className:"workspace-page__current-label",children:a("workspace.currentWorkspace")}),c.jsxs("div",{className:"workspace-page__current-card",children:[c.jsx("div",{className:"workspace-page__project-name",children:d.project_name||a("workspace.unknownProject")}),c.jsx("div",{className:"workspace-page__project-path",children:d.path}),d.git_branch&&c.jsxs("div",{className:"workspace-page__git-branch",children:[c.jsxs("svg",{width:"12",height:"12",viewBox:"0 0 16 16",fill:"none",children:[c.jsx("circle",{cx:"5",cy:"4",r:"2",stroke:"currentColor",strokeWidth:"1.3"}),c.jsx("circle",{cx:"11",cy:"4",r:"2",stroke:"currentColor",strokeWidth:"1.3"}),c.jsx("circle",{cx:"5",cy:"12",r:"2",stroke:"currentColor",strokeWidth:"1.3"}),c.jsx("path",{d:"M5 6V10M11 6V8C11 9.1046 10.1046 10 9 10H5",stroke:"currentColor",strokeWidth:"1.3"})]}),d.git_branch]})]}),c.jsxs("div",{className:"workspace-page__actions",children:[c.jsx("button",{className:"workspace-page__btn workspace-page__btn--primary",onClick:l,children:a("common.continue")}),c.jsx("button",{className:"workspace-page__btn workspace-page__btn--secondary",onClick:ue,children:a("common.switch")})]})]}):c.jsxs("div",{className:"workspace-page__no-workspace",children:[c.jsx("div",{className:"workspace-page__no-workspace-icon",children:c.jsx("svg",{width:"40",height:"40",viewBox:"0 0 16 16",fill:"none",children:c.jsx("path",{d:"M2 4V12C2 12.5523 2.44772 13 3 13H13C13.5523 13 14 12.5523 14 12V6C14 5.44772 13.5523 5 13 5H8L6.5 3H3C2.44772 3 2 3.44772 2 4Z",stroke:"currentColor",strokeWidth:"1.3",strokeLinejoin:"round"})})}),c.jsx("div",{className:"workspace-page__no-workspace-text",children:a("workspace.noWorkspaceOpen")}),c.jsx("div",{className:"workspace-page__no-workspace-hint",children:a("workspace.noWorkspaceHint")}),!O&&c.jsx("button",{className:"workspace-page__btn workspace-page__btn--primary",onClick:ue,children:a("workspace.selectWorkspace")})]}),O&&c.jsxs("div",{className:"workspace-page__recent",children:[c.jsx("div",{className:"workspace-page__recent-label",children:a("workspace.recentWorkspaces")}),m.length===0?c.jsx("div",{className:"workspace-page__recent-empty",children:a("workspace.noRecentWorkspaces")}):c.jsx("div",{className:"workspace-page__recent-list",children:m.map($=>c.jsxs("button",{className:"workspace-page__recent-item",onClick:()=>V($),disabled:E,children:[c.jsx("div",{className:"workspace-page__recent-item-name",children:$.name}),c.jsx("div",{className:"workspace-page__recent-item-path",children:$.path})]},`${$.remote_connection_id??"local"}:${$.path}`))}),d?.has_workspace&&c.jsx("button",{className:"workspace-page__btn workspace-page__btn--secondary",onClick:()=>B(!1),children:a("common.cancel")})]}),E&&c.jsxs("div",{className:"workspace-page__switching",children:[c.jsx("div",{className:"spinner spinner--sm"}),c.jsx("span",{children:a("workspace.openingWorkspace")})]}),N&&c.jsx("div",{className:"workspace-page__error",children:N})]})]})};function im(i){const l=C.useCallback(d=>i.onControlTargetChange(d),[i]),a=C.useCallback(()=>i.controlTargetEpoch,[i]);return C.useSyncExternalStore(l,a,a)}const Js=30,lm=(i,l=!1)=>{const a=i.nativeEvent;return l||a.isComposing||a.keyCode===229};function am(i,l,a){return!i.active||i.sessionMgr!==l||i.epoch!==a||l.controlTargetEpoch!==a?null:a}function rd(i,l,a){const d=parseInt(i,10);if(!d||isNaN(d))return"";const f=new Date(d*1e3),p=new Date().getTime()-f.getTime(),_=Math.floor(p/6e4);if(_<1)return a("common.justNow");if(_<60)return a("common.minutesAgo",{count:_});const w=Math.floor(_/60);if(w<24)return a("common.hoursAgo",{count:w});const E=Math.floor(w/24);return E<7?a("common.daysAgo",{count:E}):l(f)}function od(i,l){switch(i){case"code":case"agentic":return l("sessions.agentCode");case"cowork":case"Cowork":return l("sessions.agentCowork");case"claw":case"Claw":return l("shared.agents.claw");default:return i||l("sessions.agentDefault")}}function Dd(i){return i==="cowork"||i==="Cowork"}function Rd(i){return i==="claw"||i==="Claw"}function cm(i){return i.length===0?void 0:i.some(a=>a.workspace_kind!=null)?i.find(a=>a.workspace_kind!=="assistant"):i[0]}function sd(i,l){if(!i||i.length<=l)return i;const a=l-3,d=Math.ceil(a*.6),f=a-d;return i.slice(0,d)+"..."+i.slice(-f)}function Ro({agentType:i}){return Dd(i)?c.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"}),c.jsx("circle",{cx:"9",cy:"7",r:"4"}),c.jsx("path",{d:"M22 21v-2a4 4 0 0 0-3-3.87"}),c.jsx("path",{d:"M16 3.13a4 4 0 0 1 0 7.75"})]}):Rd(i)?c.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("rect",{width:"20",height:"14",x:"2",y:"5",rx:"2"}),c.jsx("path",{d:"M2 10h20"})]}):c.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("path",{d:"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"})})}const um=()=>c.jsxs("svg",{width:"32",height:"32",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("polyline",{points:"4 17 10 11 4 5"}),c.jsx("line",{x1:"12",y1:"19",x2:"20",y2:"19"})]}),Zl=()=>c.jsxs("svg",{width:"32",height:"32",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("path",{d:"M12 8V4H8"}),c.jsx("rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}),c.jsx("path",{d:"M2 14h2"}),c.jsx("path",{d:"M20 14h2"}),c.jsx("path",{d:"M15 13v2"}),c.jsx("path",{d:"M9 13v2"})]}),id=()=>c.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("path",{d:"m6 14 1.5-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.54 6a2 2 0 0 1-1.95 1.5H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h3.93a2 2 0 0 1 1.66.9l.82 1.2a2 2 0 0 0 1.66.9H18a2 2 0 0 1 2 2v2"})}),dm=({isDark:i})=>c.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:i?c.jsx("path",{d:"M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM3 8a5 5 0 0 1 5-5v10a5 5 0 0 1-5-5Z",fill:"currentColor"}):c.jsx("path",{d:"M8 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 1Zm0 11a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 8 12Zm7-4a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 15 8ZM3 8a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1 0-1h1A.5.5 0 0 1 3 8Zm9.95-3.54a.5.5 0 0 1 0 .71l-.71.7a.5.5 0 1 1-.7-.7l.7-.71a.5.5 0 0 1 .71 0ZM5.46 11.24a.5.5 0 0 1 0 .71l-.7.71a.5.5 0 0 1-.71-.71l.7-.71a.5.5 0 0 1 .71 0Zm7.08 1.42a.5.5 0 0 1-.7 0l-.71-.71a.5.5 0 0 1 .7-.7l.71.7a.5.5 0 0 1 0 .71ZM5.46 4.76a.5.5 0 0 1-.71 0l-.71-.7a.5.5 0 0 1 .71-.71l.7.7a.5.5 0 0 1 0 .71ZM8 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6Z",fill:"currentColor"})}),fm=({sessionMgr:i,onSelectSession:l,onOpenWorkspace:a,onDisconnect:d,onOpenDevices:f})=>{const m=C.useRef(!1),{t:p,formatDate:_}=$r(),{sessions:w,setSessions:E,appendSessions:T,setError:N,currentWorkspace:L,setCurrentWorkspace:O,currentAssistant:B,setCurrentAssistant:W,setPairedDisplayMode:F,authenticatedUserLabel:ue,connectionHealth:V,controlTarget:$}=Ut(),{isDark:re,toggleTheme:we}=Td(),[de,_e]=C.useState(!1),[ke,Ne]=C.useState(!1),[be,Se]=C.useState(!1),[he,K]=C.useState(!0),q=C.useRef(!0),[J,le]=C.useState(!1),[te,P]=C.useState(()=>{const x=Ut.getState().pairedDisplayMode;return x==="assistant"||x==="pro"?x:"pro"}),[U,D]=C.useState([]),[y,I]=C.useState(!1),[ne,ae]=C.useState([]),[fe,ce]=C.useState(!1),[ee,me]=C.useState(""),[ye,Re]=C.useState(null),[ct,wt]=C.useState(null),[Ae,Fe]=C.useState(""),[Ie,We]=C.useState(null),[He,Et]=C.useState(!1),[Qe,tt]=C.useState(!1),[Ot,rn]=C.useState(null),[qn,Bt]=C.useState(!1),Cn=C.useRef(),cr=C.useRef({x:0,y:0}),on=C.useRef(!1),_t=C.useRef(),ot=im(i),jt=C.useRef({sessionMgr:i,epoch:ot,active:!0});(jt.current.sessionMgr!==i||jt.current.epoch!==ot)&&(jt.current={sessionMgr:i,epoch:ot,active:!0});const Ce=C.useCallback(()=>am(jt.current,i,ot),[ot,i]),ie=C.useCallback(x=>{const M=jt.current;return x!==null&&M.active&&M.sessionMgr===i&&M.epoch===x&&i.controlTargetEpoch===x},[ot,i]),ur=ee.trim().length>0,Kr=w.length>0&&!ur,Qn=()=>{Cn.current&&(clearTimeout(Cn.current),Cn.current=void 0)},dr=C.useCallback((x,M)=>{He||Qe||(Qn(),on.current=!1,cr.current={x:M.touches[0].clientX,y:M.touches[0].clientY},Cn.current=setTimeout(()=>{on.current=!0,Re(x),Cn.current=void 0},500))},[He,Qe]),fr=C.useCallback(x=>{const M=Math.abs(x.touches[0].clientX-cr.current.x),Q=Math.abs(x.touches[0].clientY-cr.current.y);(M>10||Q>10)&&Qn()},[]),En=C.useCallback(()=>{Qn()},[]),pr=C.useCallback((x,M)=>{if(on.current){M.preventDefault(),M.stopPropagation(),on.current=!1;return}l(x.session_id,x.name)},[l]),sn=C.useCallback(x=>{_t.current&&clearTimeout(_t.current),rn(x),_t.current=setTimeout(()=>rn(null),2500)},[]);C.useEffect(()=>()=>{Qn(),_t.current&&clearTimeout(_t.current)},[]);const ln=C.useCallback(async()=>{if(!ct||!Ae.trim())return;const x=Ce();if(x!==null){tt(!0);try{if(await i.renameSession(ct.session_id,Ae.trim()),!ie(x))return;Ut.getState().updateSessionName(ct.session_id,Ae.trim()),wt(null),Re(null)}catch(M){ie(x)&&!Mt(M)&&sn(M.message||p("sessions.renameFailed"))}finally{ie(x)&&tt(!1)}}},[Ce,ie,ct,Ae,i,sn,p]),an=C.useCallback(async()=>{if(!Ie)return;const x=Ce();if(x!==null){Et(!0);try{if(await i.deleteSession(Ie.session_id),!ie(x))return;Ut.getState().removeSession(Ie.session_id),We(null),Re(null),sn(p("sessions.deleted"))}catch(M){ie(x)&&!Mt(M)&&sn(M.message||p("sessions.deleteFailed"))}finally{ie(x)&&Et(!1)}}},[Ce,Ie,ie,i,sn,p]),[cn,jn]=C.useState(0),[un,hr]=C.useState(!1),Ft=C.useRef(0),mr=C.useRef(null),Ze=C.useRef(0),Wt=C.useRef(void 0),gr=C.useRef(0),Nt=C.useRef(!1),zo=C.useRef({sessionMgr:i,epoch:ot});C.useLayoutEffect(()=>{const x=zo.current,M=x.sessionMgr!==i||x.epoch!==ot,Q=jt.current;return Q.active=Q.sessionMgr===i&&Q.epoch===ot&&i.controlTargetEpoch===ot,M&&(q.current=!0,K(!0),Ze.current+=1,Ne(!1),Se(!1),hr(!1),Qn(),on.current=!1,Nt.current=!1,jn(0),_t.current&&(clearTimeout(_t.current),_t.current=void 0),_e(!1),tt(!1),Et(!1),D([]),ae([]),I(!1),ce(!1),Re(null),wt(null),Fe(""),We(null),rn(null),Bt(!1),me(""),P("pro"),le(!1),E([]),O(null),W(null),F(null),N(null),Ft.current=0,Wt.current=void 0),zo.current={sessionMgr:i,epoch:ot},()=>{Q.active=!1,Ze.current+=1}},[ot,i,W,O,N,F,E]);const dn=C.useCallback(async()=>{const x=Ce();if(x!==null)try{const M=await i.listAssistants();if(!ie(x))return;if(D(M),!B&&M.length>0){const Q=M.find(ge=>!ge.assistant_id)||M[0];return W(Q),Q.path}return B?.path}catch(M){ie(x)&&!Mt(M)&&N(M.message);return}},[Ce,B,ie,i,W,N]),Ke=C.useCallback(async(x,M="",Q)=>{const ge=Ce();if(ge===null)return;const xe=++Ze.current;Se(!1),Ne(!0),Ft.current=0;try{const Ee=await i.listSessions(x,Js,0,M,Q);if(xe!==Ze.current||!ie(ge))return;E(Ee.sessions),le(Ee.has_more),Ft.current=Ee.sessions.length}catch(Ee){if(xe!==Ze.current||!ie(ge))return;Mt(Ee)||N(Ee.message)}finally{xe===Ze.current&&ie(ge)&&Ne(!1)}},[Ce,ie,i,N,E]),yr=C.useCallback(async()=>{const x=Ce();if(x!==null)try{const M=await i.listRecentWorkspaces();if(!ie(x))return;ae(M)}catch(M){ie(x)&&!Mt(M)&&N(M.message)}},[Ce,ie,i,N]),qr=C.useCallback(async x=>{if(q.current)return;const M=Ce();if(M!==null)try{const Q=await i.setWorkspace(x.path,{remoteConnectionId:x.remote_connection_id,remoteSshHost:x.remote_ssh_host});if(!ie(M))return;if(Q.success){const ge=Q.path||x.path,xe=Q.remote_connection_id??x.remote_connection_id,Ee=Q.remote_ssh_host??x.remote_ssh_host,Zt={remoteConnectionId:xe,remoteSshHost:Ee};O({has_workspace:!0,path:ge,project_name:Q.project_name||x.name,workspace_kind:xe||Ee?"remote":void 0,remote_connection_id:xe,remote_ssh_host:Ee}),ce(!1),Ke(ge,ee,Zt)}else N(Q.error||"Failed to set workspace")}catch(Q){ie(M)&&!Mt(Q)&&N(Q.message)}},[Ce,ie,Ke,ee,i,O,N]),Qr=C.useCallback(async()=>{const x=Ce();if(x===null)return!1;try{const M=await i.listRecentWorkspaces();if(!ie(x))return!1;const Q=cm(M);if(!Q)return!1;const ge=await i.setWorkspace(Q.path,{remoteConnectionId:Q.remote_connection_id,remoteSshHost:Q.remote_ssh_host});if(!ie(x))return!1;if(ge.success){const xe=ge.path||Q.path,Ee=ge.remote_connection_id??Q.remote_connection_id,Zt=ge.remote_ssh_host??Q.remote_ssh_host,Tt={remoteConnectionId:Ee,remoteSshHost:Zt};return O({has_workspace:!0,path:xe,project_name:ge.project_name||Q.name,workspace_kind:Ee||Zt?"remote":Q.workspace_kind,remote_connection_id:Ee,remote_ssh_host:Zt}),await Ke(xe,ee,Tt),ie(x)}return N(ge.error||p("workspace.failedToSetWorkspace")),!1}catch(M){return ie(x)&&!Mt(M)&&N(M.message),!1}},[Ce,ie,Ke,ee,i,O,N,p]),Uo=C.useCallback(async(x,M="",Q)=>{if(ke||be||!J)return;const ge=Ce();if(ge===null)return;const xe=Ze.current;Se(!0);try{const Ee=await i.listSessions(x,Js,Ft.current,M,Q);if(xe!==Ze.current||!ie(ge))return;T(Ee.sessions),le(Ee.has_more),Ft.current+=Ee.sessions.length}catch(Ee){if(xe!==Ze.current||!ie(ge))return;Mt(Ee)||N(Ee.message)}finally{xe===Ze.current&&ie(ge)&&Se(!1)}},[T,Ce,J,ie,ke,be,i,N]);C.useEffect(()=>{let x=!1;const M=Ce();if(M===null)return;const Q=()=>!x&&ie(M);return(async()=>{try{const xe=await i.getWorkspaceInfo();if(!Q())return;if(xe.workspace_kind==="assistant"&&xe.path)W({path:xe.path,name:xe.project_name??"Claw",assistant_id:xe.assistant_id}),O(null),P("assistant"),Wt.current=xe.path,await Ke(xe.path);else{P("pro");const Ee=xe.has_workspace?xe:null;O(Ee),Ee?.path?(Wt.current=Ee.path,await Ke(Ee.path,"",{remoteConnectionId:Ee.remote_connection_id,remoteSshHost:Ee.remote_ssh_host})):await Qr()}}catch(xe){Q()&&!Mt(xe)&&N(xe.message)}finally{Q()&&(F(null),Ne(!1),q.current=!1,K(!1))}})(),()=>{x=!0}},[ot]);const vr=C.useCallback(async()=>{const x=Ce();if(x===null)return;const M=++Ze.current;Se(!1);try{if(te==="pro"){const Q=await i.getWorkspaceInfo();if(M!==Ze.current||!ie(x))return;if(Q.workspace_kind==="assistant"){O(null),E([]),le(!1),Ft.current=0;return}const ge=Q.has_workspace?Q:null;O(ge);const xe=await i.listSessions(ge?.path,Js,0,ee,{remoteConnectionId:ge?.remote_connection_id,remoteSshHost:ge?.remote_ssh_host});if(M!==Ze.current||!ie(x))return;E(xe.sessions),le(xe.has_more),Ft.current=xe.sessions.length}else{const Q=await i.listSessions(B?.path,Js,0,ee);if(M!==Ze.current||!ie(x))return;E(Q.sessions),le(Q.has_more),Ft.current=Q.sessions.length}}catch{}finally{M===Ze.current&&ie(x)&&(Ne(!1),Se(!1))}},[Ce,B?.path,te,ie,ee,i,O,E]);C.useEffect(()=>{const x=setInterval(vr,1e4);return()=>clearInterval(x)},[vr]),C.useEffect(()=>{const x=te==="assistant"?B?.path:L?.path;if(!x)return;if(Wt.current===x){Wt.current=void 0;return}const M=te==="assistant"?void 0:{remoteConnectionId:L?.remote_connection_id,remoteSshHost:L?.remote_ssh_host},Q=setTimeout(()=>{Ke(x,ee,M)},250);return()=>clearTimeout(Q)},[B?.path,L?.path,L?.remote_connection_id,L?.remote_ssh_host,te,Ke,ee]);const It=60,Oo=C.useCallback(x=>{const M=mr.current;!M||M.scrollTop>0||un||(gr.current=x.touches[0].clientY,Nt.current=!0)},[un]),Bo=C.useCallback(x=>{if(!Nt.current)return;const M=x.touches[0].clientY-gr.current;M>0?jn(Math.min(M*.5,80)):(Nt.current=!1,jn(0))},[]),li=C.useCallback(async()=>{if(!Nt.current)return;Nt.current=!1;const x=Ce();x!==null&&(cn>=It&&(hr(!0),jn(It),await vr(),ie(x)&&hr(!1)),ie(x)&&jn(0))},[Ce,ie,cn,vr]),Fo=C.useCallback(x=>{const M=x.currentTarget;if(M.scrollHeight-M.scrollTop-M.clientHeight<150){const Q=te==="assistant"?B?.path:L?.path,ge=te==="assistant"?void 0:{remoteConnectionId:L?.remote_connection_id,remoteSshHost:L?.remote_ssh_host};Uo(Q,ee,ge)}},[te,B?.path,L?.path,L?.remote_connection_id,L?.remote_ssh_host,Uo,ee]),wr=C.useCallback(async x=>{if(de||q.current)return;const M=Ce();if(M!==null){_e(!0);try{const Q=te==="assistant"?B?.path:L?.path,ge=te==="assistant"?void 0:{remoteConnectionId:L?.remote_connection_id,remoteSshHost:L?.remote_ssh_host},xe=await i.createSession(x,void 0,Q,ge);if(!ie(M)||(await Ke(Q,ee,ge),!ie(M)))return;const Ee=Rd(x)?p("sessions.remoteClawSession"):Dd(x)?p("sessions.remoteCoworkSession"):p("sessions.remoteCodeSession");l(xe,Ee,!0)}catch(Q){ie(M)&&!Mt(Q)&&N(Q.message)}finally{ie(M)&&_e(!1)}}},[de,Ce,L?.path,L?.remote_connection_id,L?.remote_ssh_host,B?.path,te,ie,Ke,l,ee,i,N,p]),Yr=C.useCallback(async x=>{if(q.current)return;const M=Ce();if(M!==null)if(P(x),I(!1),x==="assistant"){const Q=await dn();if(!ie(M))return;Ke(Q,ee)}else L?.path?await Ke(L.path,ee,{remoteConnectionId:L.remote_connection_id,remoteSshHost:L.remote_ssh_host}):await Qr()},[Ce,L?.path,ie,dn,Ke,ee,Qr]),Wo=C.useCallback(async x=>{if(q.current)return;const M=Ce();if(M!==null)try{if(await i.setAssistant(x.path),!ie(M))return;W(x),I(!1),Ke(x.path,ee)}catch(Q){ie(M)&&!Mt(Q)&&N(Q.message)}},[Ce,ie,Ke,ee,i,W,N]),Ho=L?.project_name||p("sessions.noWorkspaceSelected"),ai=B?.name||p("shared.agents.default"),Le=te==="pro";return c.jsxs("div",{className:"session-list",children:[c.jsxs("div",{className:"session-list__header",children:[c.jsxs("div",{className:"session-list__header-brand",children:[c.jsx("img",{src:Ld,alt:"BitFun",className:"session-list__logo"}),c.jsxs("div",{className:"session-list__header-copy",children:[c.jsx("h1",{children:p("shared.product.remote")}),ue&&c.jsxs("span",{className:"session-list__header-account-name",children:[c.jsx("span",{className:`session-list__health-dot session-list__health-dot--${V}`,title:(()=>{switch(V){case"connected":return p("sessions.connectionConnected");case"checking":return p("sessions.connectionChecking");case"unreachable":return p("sessions.connectionUnreachable");default:return p("sessions.connectionUnpaired")}})()}),ue,$&&!$.isHome&&$.deviceName&&c.jsx("span",{className:"session-list__header-target",title:p("devices.controllingDevice",{name:$.deviceName}),children:$.deviceName})]})]})]}),c.jsxs("div",{className:"session-list__header-actions",children:[f&&c.jsx("button",{className:`session-list__devices-btn ${$&&!$.isHome?"is-remote":""}`,onClick:f,title:p("devices.title"),"aria-label":p("devices.title"),children:c.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",ry:"2"}),c.jsx("line",{x1:"8",y1:"21",x2:"16",y2:"21"}),c.jsx("line",{x1:"12",y1:"17",x2:"12",y2:"21"})]})}),c.jsx(sa,{className:"session-list__language-btn"}),c.jsx("button",{className:"session-list__theme-btn",onClick:we,"aria-label":p("common.toggleTheme"),children:c.jsx(dm,{isDark:re})}),c.jsx("button",{className:"session-list__disconnect-btn",onClick:()=>Bt(!0),"aria-label":p("sessions.disconnect"),title:p("sessions.disconnect"),children:c.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"}),c.jsx("polyline",{points:"16 17 21 12 16 7"}),c.jsx("line",{x1:"21",y1:"12",x2:"9",y2:"12"})]})})]})]}),c.jsxs("div",{className:"session-list__items",ref:mr,onScroll:Fo,onTouchStart:Oo,onTouchMove:Bo,onTouchEnd:li,children:[(cn>0||un)&&c.jsx("div",{className:"session-list__pull-indicator",style:{height:un?It:cn},children:c.jsx("div",{className:`session-list__pull-spinner${un||cn>=It?" is-active":""}`,children:c.jsx("svg",{width:"18",height:"18",viewBox:"0 0 18 18",fill:"none",style:{transform:`rotate(${cn*4}deg)`,transition:un?"transform 0s":void 0},children:c.jsx("path",{d:"M9 2V5M9 13V16M2 9H5M13 9H16M4.22 4.22L6.34 6.34M11.66 11.66L13.78 13.78M13.78 4.22L11.66 6.34M6.34 11.66L4.22 13.78",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round"})})})}),Kr&&c.jsxs("button",{type:"button",className:"session-list__resume-card",onClick:x=>pr(w[0],x),onTouchStart:x=>dr(w[0],x),onTouchMove:fr,onTouchEnd:En,onTouchCancel:En,onContextMenu:x=>{x.preventDefault(),Re(w[0])},onKeyDown:x=>{(x.key==="Enter"||x.key===" ")&&(x.preventDefault(),l(w[0].session_id,w[0].name))},children:[c.jsx("div",{className:`session-list__item-icon session-list__resume-icon session-list__item-icon--${w[0].agent_type}`,children:c.jsx(Ro,{agentType:w[0].agent_type})}),c.jsxs("div",{className:"session-list__resume-body",children:[c.jsx("div",{className:"session-list__resume-label",children:p("sessions.continueSession")}),c.jsx("div",{className:"session-list__resume-name",children:w[0].name||p("sessions.untitledSession")}),c.jsxs("div",{className:"session-list__resume-meta",children:[c.jsx("span",{className:`session-list__agent-badge session-list__agent-badge--${w[0].agent_type}`,children:od(w[0].agent_type,p)}),c.jsx("span",{className:"session-list__resume-time",children:rd(w[0].updated_at,_,p)})]})]}),c.jsx("span",{className:"session-list__resume-arrow",children:c.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("path",{d:"m9 18 6-6-6-6"})})})]}),c.jsxs("div",{className:"session-list__mode-toggle",children:[c.jsxs("button",{className:`session-list__mode-toggle-btn ${Le?"is-active":""}`,onClick:()=>Yr("pro"),disabled:he,children:[c.jsx(um,{}),c.jsx("span",{children:p("shared.modes.expert")})]}),c.jsxs("button",{className:`session-list__mode-toggle-btn ${Le?"":"is-active"}`,onClick:()=>Yr("assistant"),disabled:he,children:[c.jsx(Zl,{}),c.jsx("span",{children:p("shared.modes.assistant")})]})]}),Le&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"session-list__workspace-bar",onClick:()=>{q.current||(yr(),ce(!0))},children:[c.jsx("span",{className:"session-list__workspace-icon",children:c.jsx(id,{})}),c.jsxs("div",{className:"session-list__workspace-copy",children:[c.jsx("span",{className:"session-list__workspace-label",children:p("shared.features.workspace")}),c.jsx("span",{className:"session-list__workspace-name",title:Ho,children:sd(Ho,24)})]}),L?.git_branch&&c.jsxs("span",{className:"session-list__workspace-branch",children:[c.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("line",{x1:"6",x2:"6",y1:"3",y2:"15"}),c.jsx("circle",{cx:"18",cy:"6",r:"3"}),c.jsx("circle",{cx:"6",cy:"18",r:"3"}),c.jsx("path",{d:"M18 9a9 9 0 0 1-9 9"})]}),sd(L.git_branch,20)]}),c.jsx("span",{className:"session-list__workspace-switch","aria-label":p("sessions.switchWorkspace"),children:c.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("path",{d:"m7 15 5 5 5-5"}),c.jsx("path",{d:"m7 9 5-5 5 5"})]})})]}),fe&&c.jsx("div",{className:"session-list__picker-overlay",onClick:()=>ce(!1),children:c.jsxs("div",{className:"session-list__picker-modal session-list__picker-modal--workspace",onClick:x=>x.stopPropagation(),children:[c.jsxs("div",{className:"session-list__picker-header",children:[c.jsx("h3",{children:p("sessions.selectWorkspace")}),c.jsx("button",{className:"session-list__picker-close",onClick:()=>ce(!1),children:c.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),c.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),c.jsx("div",{className:"session-list__picker-list",children:ne.length===0?c.jsx("div",{className:"session-list__picker-empty",children:p("sessions.noWorkspaces")}):ne.map((x,M)=>{const Q=L?.path===x.path&&(L?.remote_connection_id??void 0)===(x.remote_connection_id??void 0)&&(L?.remote_ssh_host??void 0)===(x.remote_ssh_host??void 0),ge=[x.remote_connection_id??"local",x.remote_ssh_host??"",x.path||String(M)].join(":");return c.jsxs("button",{className:`session-list__picker-item session-list__picker-item--workspace ${Q?"is-selected":""}`,onClick:()=>qr(x),children:[c.jsx("span",{className:"session-list__picker-item-icon",children:c.jsx(id,{})}),c.jsx("span",{className:"session-list__picker-item-name",children:x.name}),Q&&c.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("polyline",{points:"20 6 9 17 4 12"})})]},ge)})})]})})]}),!Le&&c.jsxs(c.Fragment,{children:[c.jsxs("div",{className:"session-list__assistant-bar",onClick:()=>{q.current||(dn(),I(!0))},children:[c.jsx("span",{className:"session-list__assistant-icon",children:c.jsx(Zl,{})}),c.jsxs("div",{className:"session-list__assistant-copy",children:[c.jsx("span",{className:"session-list__assistant-label",children:p("sessions.assistant")}),c.jsx("span",{className:"session-list__assistant-name",children:ai})]}),c.jsx("span",{className:"session-list__assistant-switch","aria-label":p("sessions.switchAssistant"),children:c.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("path",{d:"m7 15 5 5 5-5"}),c.jsx("path",{d:"m7 9 5-5 5 5"})]})})]}),y&&c.jsx("div",{className:"session-list__picker-overlay",onClick:()=>I(!1),children:c.jsxs("div",{className:"session-list__picker-modal",onClick:x=>x.stopPropagation(),children:[c.jsxs("div",{className:"session-list__picker-header",children:[c.jsx("h3",{children:p("sessions.selectAssistant")}),c.jsx("button",{className:"session-list__picker-close",onClick:()=>I(!1),children:c.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),c.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),c.jsx("div",{className:"session-list__picker-list",children:U.map((x,M)=>c.jsxs("button",{className:`session-list__picker-item ${B?.path===x.path?"is-selected":""}`,onClick:()=>Wo(x),children:[c.jsx("span",{className:"session-list__picker-item-icon",children:c.jsx(Zl,{})}),c.jsx("span",{className:"session-list__picker-item-name",children:x.name}),B?.path===x.path&&c.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("polyline",{points:"20 6 9 17 4 12"})})]},x.path||M))})]})})]}),c.jsxs("section",{className:`session-list__panel ${Le?"":"session-list__panel--assistant"}`,children:[c.jsx("div",{className:"session-list__section-head",children:c.jsxs("div",{children:[c.jsx("div",{className:"session-list__section-kicker",children:p("sessions.launch")}),c.jsx("div",{className:"session-list__section-title",children:p("sessions.startRemoteFlow")})]})}),Le?L?c.jsxs("div",{className:"session-list__create-row",children:[c.jsxs("button",{className:"session-list__create-btn session-list__create-btn--code",onClick:()=>wr("code"),disabled:de||he,children:[c.jsx("div",{className:"session-list__create-icon",children:c.jsx(Ro,{agentType:"code"})}),c.jsxs("div",{className:"session-list__create-copy",children:[c.jsx("span",{className:"session-list__create-title",children:p("shared.agents.code")}),c.jsx("span",{className:"session-list__create-desc",children:p("sessions.codeSessionDesc")})]}),c.jsx("span",{className:"session-list__create-arrow",children:c.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("path",{d:"m9 18 6-6-6-6"})})})]}),c.jsxs("button",{className:"session-list__create-btn session-list__create-btn--cowork",onClick:()=>wr("cowork"),disabled:de||he,children:[c.jsx("div",{className:"session-list__create-icon",children:c.jsx(Ro,{agentType:"cowork"})}),c.jsxs("div",{className:"session-list__create-copy",children:[c.jsx("span",{className:"session-list__create-title",children:p("shared.agents.cowork")}),c.jsx("span",{className:"session-list__create-desc",children:p("sessions.coworkSessionDesc")})]}),c.jsx("span",{className:"session-list__create-arrow",children:c.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("path",{d:"m9 18 6-6-6-6"})})})]})]}):null:c.jsx("div",{className:"session-list__create-row",children:c.jsxs("button",{className:"session-list__create-btn session-list__create-btn--claw",onClick:()=>wr("claw"),disabled:de||he,children:[c.jsx("div",{className:"session-list__create-icon",children:c.jsx(Ro,{agentType:"claw"})}),c.jsxs("div",{className:"session-list__create-copy",children:[c.jsx("span",{className:"session-list__create-title",children:p("sessions.clawSession")}),c.jsx("span",{className:"session-list__create-desc",children:p("sessions.clawSessionDesc")})]}),c.jsx("span",{className:"session-list__create-arrow",children:c.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("path",{d:"m9 18 6-6-6-6"})})})]})})]}),c.jsxs("section",{className:`session-list__panel session-list__panel--sessions ${Le?"":"session-list__panel--assistant"}`,children:[c.jsxs("div",{className:"session-list__section-head",children:[c.jsxs("div",{children:[c.jsx("div",{className:"session-list__section-kicker",children:p("sessions.recent")}),c.jsx("div",{className:"session-list__section-title",children:p("sessions.sessionHistory")})]}),c.jsx("div",{className:"session-list__section-meta",children:p("common.itemCount",{count:w.length})})]}),c.jsxs("div",{className:"session-list__search",children:[c.jsxs("svg",{className:"session-list__search-icon",width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("circle",{cx:"11",cy:"11",r:"8"}),c.jsx("line",{x1:"21",y1:"21",x2:"16.65",y2:"16.65"})]}),c.jsx("input",{className:"session-list__search-input",type:"search",placeholder:p("sessions.searchSessions"),value:ee,onChange:x=>me(x.target.value),disabled:he,enterKeyHint:"search"}),ee&&c.jsx("button",{className:"session-list__search-clear",onClick:()=>me(""),"aria-label":"Clear",disabled:he,children:c.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("line",{x1:"18",y1:"6",x2:"6",y2:"18"}),c.jsx("line",{x1:"6",y1:"6",x2:"18",y2:"18"})]})})]}),(ke||he)&&w.length===0&&c.jsx("div",{className:"session-list__empty",children:p("sessions.loadingSessions")}),!ke&&!he&&w.length===0&&!ur&&c.jsx("div",{className:"session-list__empty",children:p("sessions.noSessions")}),!ke&&!he&&w.length===0&&ur&&c.jsx("div",{className:"session-list__empty",children:p("sessions.emptySearch")}),c.jsx("div",{className:"session-list__cards",children:w.slice(Kr?1:0).map(x=>c.jsxs("div",{className:`session-list__item${ye?.session_id===x.session_id?" session-list__item--active":""}`,onClick:M=>pr(x,M),onTouchStart:M=>dr(x,M),onTouchMove:fr,onTouchEnd:En,onTouchCancel:En,onContextMenu:M=>{M.preventDefault(),Re(x)},children:[c.jsx("div",{className:`session-list__item-icon session-list__item-icon--${x.agent_type}`,children:c.jsx(Ro,{agentType:x.agent_type})}),c.jsxs("div",{className:"session-list__item-body",children:[c.jsxs("div",{className:"session-list__item-top",children:[c.jsx("div",{className:"session-list__item-name",children:x.name||p("sessions.untitledSession")}),c.jsx("span",{className:`session-list__agent-badge session-list__agent-badge--${x.agent_type}`,children:od(x.agent_type,p)})]}),c.jsx("div",{className:"session-list__item-time",children:rd(x.updated_at,_,p)})]})]},x.session_id))}),be&&c.jsx("div",{className:"session-list__load-more",children:p("sessions.loadingMore")})]})]}),ye&&!ct&&!Ie&&c.jsx("div",{className:"session-list__menu-overlay",onClick:()=>Re(null),children:c.jsxs("div",{className:"session-list__menu-sheet",onClick:x=>x.stopPropagation(),children:[c.jsx("div",{className:"session-list__menu-handle"}),c.jsx("div",{className:"session-list__menu-title",children:ye.name||p("sessions.untitledSession")}),c.jsxs("div",{className:"session-list__menu-actions",children:[c.jsxs("button",{className:"session-list__menu-btn",onClick:()=>{wt(ye),Fe(ye.name||"")},children:[c.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("path",{d:"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"}),c.jsx("path",{d:"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"})]}),c.jsx("span",{children:p("sessions.renameSession")})]}),c.jsxs("button",{className:"session-list__menu-btn session-list__menu-btn--danger",onClick:()=>We(ye),children:[c.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("polyline",{points:"3 6 5 6 21 6"}),c.jsx("path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"})]}),c.jsx("span",{children:p("sessions.deleteSession")})]})]}),c.jsx("button",{className:"session-list__menu-cancel",onClick:()=>Re(null),children:p("sessions.cancel")})]})}),ct&&c.jsx("div",{className:"session-list__picker-overlay",onClick:()=>!Qe&&wt(null),children:c.jsxs("div",{className:"session-list__rename-modal",onClick:x=>x.stopPropagation(),children:[c.jsx("h3",{className:"session-list__rename-title",children:p("sessions.renameTitle")}),c.jsx("input",{className:"session-list__rename-input",type:"text",value:Ae,onChange:x=>Fe(x.target.value),placeholder:p("sessions.sessionNamePlaceholder"),autoFocus:!0,onKeyDown:x=>{if((x.key==="Enter"||x.key==="Escape")&&lm(x,m.current)){x.stopPropagation();return}x.key==="Enter"&&ln(),x.key==="Escape"&&wt(null)},onCompositionStart:()=>{m.current=!0},onCompositionEnd:()=>{m.current=!1}}),c.jsxs("div",{className:"session-list__rename-actions",children:[c.jsx("button",{className:"session-list__rename-btn session-list__rename-btn--cancel",onClick:()=>wt(null),disabled:Qe,children:p("sessions.cancel")}),c.jsx("button",{className:"session-list__rename-btn session-list__rename-btn--save",onClick:ln,disabled:Qe||!Ae.trim(),children:Qe?"...":p("sessions.save")})]})]})}),Ie&&c.jsx("div",{className:"session-list__picker-overlay",onClick:()=>!He&&We(null),onKeyDown:x=>{x.key==="Escape"&&We(null),x.key==="Enter"&&!He&&an()},children:c.jsxs("div",{className:"session-list__confirm-modal",onClick:x=>x.stopPropagation(),children:[c.jsx("div",{className:"session-list__confirm-icon",children:c.jsxs("svg",{width:"28",height:"28",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("circle",{cx:"12",cy:"12",r:"10"}),c.jsx("line",{x1:"12",y1:"8",x2:"12",y2:"12"}),c.jsx("line",{x1:"12",y1:"16",x2:"12.01",y2:"16"})]})}),c.jsx("h3",{className:"session-list__confirm-title",children:p("sessions.confirmDelete")}),c.jsxs("p",{className:"session-list__confirm-desc",children:['"',Ie.name||p("sessions.untitledSession"),'"',c.jsx("br",{}),p("sessions.confirmDeleteDesc")]}),c.jsxs("div",{className:"session-list__confirm-actions",children:[c.jsx("button",{className:"session-list__confirm-btn session-list__confirm-btn--cancel",onClick:()=>We(null),disabled:He,children:p("sessions.cancel")}),c.jsx("button",{className:"session-list__confirm-btn session-list__confirm-btn--danger",onClick:an,disabled:He,children:He?"...":p("sessions.deleteSession")})]})]})}),qn&&c.jsx("div",{className:"session-list__picker-overlay",role:"alertdialog","aria-modal":"true","aria-labelledby":"disconnect-confirm-title","aria-describedby":"disconnect-confirm-desc",onClick:()=>Bt(!1),onKeyDown:x=>{x.key==="Escape"&&Bt(!1)},children:c.jsxs("div",{className:"session-list__confirm-modal",onClick:x=>x.stopPropagation(),children:[c.jsx("div",{className:"session-list__confirm-icon",children:c.jsxs("svg",{width:"28",height:"28",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("path",{d:"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"}),c.jsx("polyline",{points:"16 17 21 12 16 7"}),c.jsx("line",{x1:"21",y1:"12",x2:"9",y2:"12"})]})}),c.jsx("h3",{id:"disconnect-confirm-title",className:"session-list__confirm-title",children:p("sessions.disconnect")}),c.jsx("p",{id:"disconnect-confirm-desc",className:"session-list__confirm-desc",children:p("sessions.disconnectConfirm")}),c.jsxs("div",{className:"session-list__confirm-actions",children:[c.jsx("button",{className:"session-list__confirm-btn session-list__confirm-btn--cancel",onClick:()=>Bt(!1),autoFocus:!0,children:p("common.cancel")}),c.jsx("button",{className:"session-list__confirm-btn session-list__confirm-btn--danger",onClick:()=>{Bt(!1),d()},children:p("sessions.disconnect")})]})]})}),Ot&&c.jsx("div",{className:"session-list__toast",role:"alert","aria-live":"assertive",children:Ot})]})},pm=()=>c.jsx("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("path",{d:"m15 18-6-6 6-6"})}),hm=()=>c.jsxs("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}),c.jsx("path",{d:"M21 3v5h-5"}),c.jsx("path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}),c.jsx("path",{d:"M3 21v-5h5"})]}),mm=()=>c.jsxs("svg",{width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.7",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("rect",{x:"2",y:"3",width:"20",height:"14",rx:"2",ry:"2"}),c.jsx("line",{x1:"8",y1:"21",x2:"16",y2:"21"}),c.jsx("line",{x1:"12",y1:"17",x2:"12",y2:"21"})]}),gm=()=>c.jsxs("svg",{width:"40",height:"40",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.4",strokeLinecap:"round",strokeLinejoin:"round",children:[c.jsx("circle",{cx:"12",cy:"8",r:"4"}),c.jsx("path",{d:"M6 21v-1a6 6 0 0 1 9-5.2"}),c.jsx("circle",{cx:"18",cy:"18",r:"4"}),c.jsx("path",{d:"M18 16.5v1.8l1.2 1.2"})]}),ym=({client:i,onBack:l})=>{const{t:a,formatRelativeTime:d}=$r(),{setControlTarget:f,resetForDeviceSwitch:m}=Ut(),[p,_]=C.useState([]),[w,E]=C.useState(i.hasDelegatedIdentity),[T,N]=C.useState(!i.hasDelegatedIdentity),[L,O]=C.useState(!1),[B,W]=C.useState(null),[F,ue]=C.useState(null),V=C.useRef(!0),$=C.useRef(0),re=C.useRef(0),we=C.useRef(0),de=C.useMemo(()=>[...p].sort((K,q)=>{const J=K.device_id===i.pairedDeviceId,le=q.device_id===i.pairedDeviceId;return J!==le?J?-1:1:K.online!==q.online?K.online?-1:1:(K.device_name||K.device_id).localeCompare(q.device_name||q.device_id)}),[i.pairedDeviceId,p]),_e=C.useCallback((K,q)=>{const J=String(K?.message||K);return J.includes("HTTP 401")||J.includes("No delegated identity")?a("devices.authorizationExpired"):J.includes("HTTP 404")||J.includes("HTTP 503")||J.includes("HTTP 504")?a("devices.deviceUnavailable"):a(q)},[a]);C.useEffect(()=>(V.current=!0,()=>{V.current=!1,$.current+=1,re.current+=1,we.current+=1}),[]);const ke=C.useCallback(async()=>{if(!i.hasDelegatedIdentity)return;const K=++re.current,q=()=>V.current&&re.current===K;try{const J=await i.listDevices();if(!q())return;_(J),ue(null),E(!0)}catch(J){if(!q()||na(J))return;String(J?.message||J).includes("No delegated identity")?(E(!1),_([])):ue(_e(J,"devices.loadFailed"))}},[i,_e]),Ne=C.useCallback(async(K=!1)=>{const q=++$.current;N(!0),ue(null);let J=!1;try{J=await i.requestDelegatedIdentity({force:K||!i.hasDelegatedIdentity})}catch(le){J=!1,V.current&&$.current===q&&ue(_e(le,"devices.identityFailed"))}return V.current&&$.current===q?(E(J),N(!1),J):!1},[i,_e]);C.useEffect(()=>{let K;return(async()=>!await Ne(!1)||!V.current||(O(!0),await ke(),V.current&&O(!1),K=setInterval(ke,3e4)))(),()=>{K&&clearInterval(K)}},[Ne,ke]);const be=C.useCallback(async()=>{L||B||!await Ne(!0)||(O(!0),await ke(),V.current&&O(!1))},[Ne,L,ke,B]),Se=C.useCallback(async K=>{if(!K.online||B||i.pairedDeviceId===K.device_id)return;const q=++we.current,J=i.delegatedAccountEpoch;let le=i.controlTargetEpoch;const te=()=>V.current&&we.current===q&&i.delegatedAccountEpoch===J&&i.controlTargetEpoch===le;W(K.device_id),ue(null);try{const P=await i.sendDeviceRpc(K.device_id,{cmd:"host_invoke",command:"peer_mode_ping",args:{}},{retryable:!0});if(!te())return;if(P.resp==="host_invoke_result"&&P.ok===!1)throw new Error(P.error||a("devices.switchFailed"));i.setPairedDeviceId(K.device_id),le=i.controlTargetEpoch,m(),f({deviceId:K.device_id,deviceName:K.device_name,isHome:K.device_id===i.homeDeviceId}),l()}catch(P){if(!te()||na(P))return;String(P?.message||P).includes("No delegated identity")?(E(!1),_([])):ue(_e(P,"devices.switchFailed"))}finally{V.current&&we.current===q&&W(null)}},[i,_e,l,m,f,B,a]),he=()=>T?c.jsxs("div",{className:"devices-page__loading",children:[c.jsx("span",{className:"spinner"}),a("devices.loading")]}):w?L&&p.length===0?c.jsxs("div",{className:"devices-page__loading",children:[c.jsx("span",{className:"spinner"}),a("devices.loading")]}):p.length===0?c.jsx("div",{className:"devices-page__empty",children:a("devices.noDevices")}):c.jsx("div",{className:"devices-page__list",children:de.map(K=>{const q=i.pairedDeviceId===K.device_id,J=i.homeDeviceId===K.device_id,le=B===K.device_id,te=K.online&&!q&&!B;return c.jsxs("button",{type:"button",className:["devices-page__device",K.online?"is-online":"is-offline",q?"is-current":"",le?"is-switching":""].filter(Boolean).join(" "),disabled:!te,onClick:()=>te&&Se(K),children:[c.jsx("span",{className:"devices-page__device-icon",children:c.jsx(mm,{})}),c.jsxs("span",{className:"devices-page__device-copy",children:[c.jsxs("span",{className:"devices-page__device-name-row",children:[c.jsx("span",{className:"devices-page__device-name",children:K.device_name||a("devices.unknownDevice")}),q&&c.jsx("span",{className:"devices-page__badge devices-page__badge--current",children:a("devices.current")}),J&&!q&&c.jsx("span",{className:"devices-page__badge",children:a("devices.pairedDesktop")})]}),c.jsxs("span",{className:"devices-page__device-meta",children:[c.jsx("span",{className:`devices-page__status-dot ${K.online?"is-online":"is-offline"}`}),K.online?a("devices.online"):K.last_seen_at?a("devices.lastSeen",{time:d(K.last_seen_at*1e3)}):a("devices.offline"),c.jsx("span",{className:"devices-page__device-id",children:K.device_id.slice(0,8)})]})]}),le?c.jsx("span",{className:"devices-page__device-spinner spinner"}):te&&c.jsx("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:c.jsx("path",{d:"m9 18 6-6-6-6"})})]},K.device_id)})}):c.jsxs("div",{className:"devices-page__empty-card",children:[c.jsx("span",{className:"devices-page__empty-icon",children:c.jsx(gm,{})}),c.jsx("p",{className:"devices-page__empty-text",children:a("devices.noDelegatedIdentity")}),c.jsx("button",{type:"button",className:"devices-page__retry-btn",onClick:be,children:a("devices.retry")})]});return c.jsxs("div",{className:"devices-page",children:[c.jsxs("div",{className:"devices-page__header",children:[c.jsx("button",{type:"button",className:"devices-page__back-btn",onClick:l,"aria-label":a("common.back"),children:c.jsx(pm,{})}),c.jsx("h2",{className:"devices-page__title",children:a("devices.title")}),c.jsx("button",{type:"button",className:`devices-page__refresh-btn ${L||T?"is-loading":""}`,onClick:be,disabled:L||T||!!B,"aria-label":a("devices.refresh"),title:a("devices.refresh"),children:c.jsx(hm,{})})]}),F&&c.jsx("div",{className:"devices-page__error",children:F}),c.jsx("div",{className:"devices-page__body",children:he()})]})};class vm extends Vr.Component{constructor(l){super(l),this.state={hasError:!1,error:null}}static getDerivedStateFromError(l){return{hasError:!0,error:l}}componentDidCatch(l,a){console.error("[ErrorBoundary]",l.message,a.componentStack)}handleRetry=()=>{this.setState({hasError:!1,error:null})};render(){return this.state.hasError?c.jsxs("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",padding:"32px",textAlign:"center",background:"var(--bf-color-surface-canvas)",color:"var(--bf-color-content-primary)",fontFamily:"system-ui, sans-serif"},children:[c.jsx("div",{style:{fontSize:"48px",marginBottom:"16px"},children:"⚠"}),c.jsx("h2",{style:{fontSize:"18px",fontWeight:600,margin:"0 0 8px"},children:"Something went wrong"}),c.jsx("p",{style:{fontSize:"13px",color:"var(--bf-color-content-muted)",margin:"0 0 24px",maxWidth:"280px"},children:this.state.error?.message||"An unexpected error occurred."}),c.jsx("button",{onClick:this.handleRetry,style:{padding:"12px 32px",border:"none",borderRadius:"14px",background:"var(--bf-color-accent-default)",color:"var(--bf-color-action-primary-content)",fontSize:"15px",fontWeight:600,cursor:"pointer"},children:"Retry"})]}):this.props.children}}function wm(i){const l=Ut.getState(),a=i.kind==="initial"&&i.userId!==null&&l.authenticatedUserId!==null&&l.authenticatedUserId!==i.userId,d=i.kind==="replacement"||i.kind==="unavailable"||a;return d&&(l.resetForDeviceSwitch(),l.setAuthenticatedUserLabel(null)),i.kind==="unavailable"?(l.setAuthenticatedUserId(null),l.setControlTarget(null),!0):((i.userId!==null||i.kind==="replacement")&&l.setAuthenticatedUserId(i.userId),(d||l.controlTarget===null)&&l.setControlTarget(i.homeDeviceId?{deviceId:i.homeDeviceId,deviceName:null,isHome:!0}:null),d)}const ld=15e3,_m=1e4,km=250;function xm(i,l){let a;return Promise.race([i.ping(),new Promise((d,f)=>{a=setTimeout(()=>f(new Error("ping timeout")),l)})]).finally(()=>{a&&clearTimeout(a)})}function Sm(i){const l=Ut(d=>d.setConnectionHealth),a=C.useRef();C.useEffect(()=>{let d=!1,f=0;if(!i){l("unpaired");return}const m=(E,T)=>{d||E!==f||(a.current&&clearTimeout(a.current),a.current=setTimeout(()=>{p(E)},T))},p=async E=>{if(!(d||E!==f))try{if(await xm(i,_m),d||E!==f)return;l("connected"),m(E,ld)}catch(T){if(d||E!==f)return;if(Mt(T)||na(T)){l("checking"),m(E,km);return}l("unreachable"),m(E,ld)}},_=()=>{f+=1,a.current&&clearTimeout(a.current),l("checking"),p(f)},w=i.onControlTargetChange(_);return _(),()=>{d=!0,f+=1,w(),a.current&&clearTimeout(a.current)}},[i,l])}const Xl=300,Cm=C.lazy(()=>Rp(()=>import("./ChatPage-B79eLrUh.js"),[],import.meta.url));function ei(i,l,a,d){return d?l===i?a==="push"?"nav-push-enter":"nav-pop-enter":a==="push"?"nav-push-exit":"nav-pop-exit":""}const Em=()=>{const{t:i}=$r(),[l,a]=C.useState("pairing"),[d,f]=C.useState(null),[m,p]=C.useState("Session"),[_,w]=C.useState(!1),E=Ut(U=>U.connectionHealth),T=C.useRef(null),N=C.useRef(null),L=C.useRef(null),[O,B]=C.useState(null);Sm(O);const[W,F]=C.useState(null),[ue,V]=C.useState(null),$=C.useRef(),re=C.useRef(["pairing"]),we=C.useRef(!1),de=C.useCallback((U,D)=>{a(y=>(V(y),U)),F(D),clearTimeout($.current),$.current=setTimeout(()=>{V(null),F(null)},Xl),D==="push"?(re.current=[...re.current,U],we.current||history.pushState({page:U},"")):D==="pop"&&(re.current=re.current.slice(0,-1),we.current||history.back())},[]);C.useEffect(()=>()=>clearTimeout($.current),[]),C.useEffect(()=>{const U=D=>{const I=D.target.closest("a");if(I&&I.href){const ne=I.href;(ne.startsWith("http://")||ne.startsWith("https://"))&&(D.preventDefault(),D.stopPropagation(),window.open(ne,"_blank","noopener,noreferrer"))}};return document.addEventListener("click",U,!0),()=>{document.removeEventListener("click",U,!0)}},[]);const _e=C.useCallback((U,D)=>{N.current?.(),T.current=U,N.current=U.onDelegatedAccountOwnerChange(y=>{T.current!==U||!wm(y)||(clearTimeout($.current),f(null),p("Session"),w(!1),V(null),F(null),re.current=["pairing","sessions"],history.replaceState({page:"sessions"},""),a("sessions"))},{emitCurrent:!0}),L.current=D,B(D),re.current=["pairing","sessions"],history.pushState({page:"sessions"},""),a("sessions")},[]),ke=C.useCallback(()=>{de("sessions","pop"),setTimeout(()=>f(null),Xl)},[de]),Ne=C.useCallback(()=>{de("sessions","pop")},[de]),be=C.useCallback(()=>{de("sessions","pop")},[de]);C.useEffect(()=>{const U=()=>{const D=re.current,y=D[D.length-1];if(y==="pairing"||y==="sessions"){history.pushState({page:y},"");return}we.current=!0;try{y==="chat"?ke():y==="workspace"?Ne():y==="devices"&&be()}finally{we.current=!1}};return window.addEventListener("popstate",U),()=>window.removeEventListener("popstate",U)},[ke,Ne,be]);const Se=C.useCallback(()=>{de("workspace","push")},[de]),he=C.useCallback(()=>{de("sessions","pop")},[de]),K=C.useCallback((U,D,y)=>{f(U),p(D||"Session"),w(!!y),de("chat","push")},[de]),q=C.useCallback(()=>{de("sessions","pop"),setTimeout(()=>f(null),Xl)},[de]),J=C.useCallback(()=>{N.current?.(),N.current=null,T.current?.resetConnectionIdentity(),T.current=null,L.current=null,B(null),f(null),p("Session"),w(!1),V(null),F(null),clearTimeout($.current),localStorage.removeItem("bitfun.mobile.user_id"),Ut.getState().resetConnectionState(),re.current=["pairing"],a("pairing")},[]);C.useEffect(()=>()=>{N.current?.(),N.current=null},[]);const le=W!==null,te=l,P=U=>te===U||le&&ue===U;return c.jsxs("div",{className:"mobile-app",children:[E==="unreachable"&&l!=="pairing"&&c.jsxs("div",{className:"mobile-reconnect-banner",role:"alert",children:[c.jsx("span",{className:"mobile-reconnect-spinner"}),c.jsx("span",{children:i("sessions.reconnecting")}),c.jsx("button",{type:"button",onClick:J,children:i("sessions.repair")})]}),l==="pairing"&&c.jsx(om,{onPaired:_e}),P("workspace")&&L.current&&c.jsx("div",{className:`nav-page ${ei("workspace",te,W,le)}`,children:c.jsx(sm,{sessionMgr:L.current,onReady:he})}),P("devices")&&T.current&&c.jsx("div",{className:`nav-page ${ei("devices",te,W,le)}`,children:c.jsx(ym,{client:T.current,onBack:be})}),P("sessions")&&L.current&&c.jsx("div",{className:`nav-page ${ei("sessions",te,W,le)}`,children:c.jsx(fm,{sessionMgr:L.current,onSelectSession:K,onOpenWorkspace:Se,onDisconnect:J,onOpenDevices:()=>de("devices","push")})}),P("chat")&&L.current&&d&&c.jsx("div",{className:`nav-page ${ei("chat",te,W,le)}`,children:c.jsx(C.Suspense,{fallback:c.jsx("div",{className:"spinner","aria-hidden":"true"}),children:c.jsx(Cm,{sessionMgr:L.current,sessionId:d,sessionName:m,onBack:q,autoFocus:_})})})]})},jm=()=>c.jsx(Gh,{children:c.jsx(vm,{children:c.jsx($p,{children:c.jsx(Em,{})})})});Tp.createRoot(document.getElementById("root")).render(c.jsx(Vr.StrictMode,{children:c.jsx(jm,{})}));export{Vr as R,Im as S,Rp as _,Ut as a,Td as b,Nm as c,im as d,jd as e,cd as g,Mt as i,c as j,Op as m,C as r,$r as u}; diff --git a/src/apps/relay-server/static/assets/index-UKiPf1rJ.css b/src/apps/relay-server/static/assets/index-UKiPf1rJ.css deleted file mode 100644 index d815605ffd..0000000000 --- a/src/apps/relay-server/static/assets/index-UKiPf1rJ.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}html,body,#root{height:100%;height:100dvh;width:100%;overflow:hidden}body{font-family:var(--font-family-sans);font-size:var(--font-size-sm);line-height:var(--line-height-base);color:var(--color-text-primary);background:var(--color-bg-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mobile-app{height:100%;height:100dvh;width:100%;background:var(--color-bg-primary);color:var(--color-text-primary);display:flex;flex-direction:column;position:relative;overflow:hidden}::-webkit-scrollbar{width:4px;height:4px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--scrollbar-thumb);border-radius:var(--size-radius-full)}::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-thumb-hover)}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes slideUp{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes slideDown{0%{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:translateY(0)}}@keyframes typing-bounce{0%,60%,to{transform:translateY(0);opacity:.4}30%{transform:translateY(-4px);opacity:1}}@keyframes focusBorderFlow{0%{background-position:0% 50%}50%{background-position:100% 50%}to{background-position:0% 50%}}.page-transition{animation:fadeIn var(--motion-base) cubic-bezier(0,0,.2,1)}.nav-page{position:absolute;inset:0;background:var(--color-bg-primary);z-index:1}.nav-push-enter{z-index:2;animation:navPushIn .3s cubic-bezier(.2,.9,.3,1) both}.nav-push-exit{z-index:1;animation:navPushOut .3s cubic-bezier(.2,.9,.3,1) both}.nav-pop-enter{z-index:1;animation:navPopIn .3s cubic-bezier(.2,.9,.3,1) both}.nav-pop-exit{z-index:2;animation:navPopOut .3s cubic-bezier(.2,.9,.3,1) both}@keyframes navPushIn{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes navPushOut{0%{transform:translate(0)}to{transform:translate(-25%)}}@keyframes navPopIn{0%{transform:translate(-25%)}to{transform:translate(0)}}@keyframes navPopOut{0%{transform:translate(0)}to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.page-transition,.nav-push-enter,.nav-push-exit,.nav-pop-enter,.nav-pop-exit{animation:none}}.spinner{width:28px;height:28px;border:2.5px solid var(--border-subtle);border-top-color:var(--color-accent-500);border-radius:50%;animation:spin .8s linear infinite}.spinner--sm{width:14px;height:14px;border-width:2px}html.theme-switching,html.theme-switching *,html.theme-switching *:before,html.theme-switching *:after{transition:background-color .28s ease,color .28s ease,border-color .28s ease,box-shadow .28s ease,fill .28s ease,stroke .28s ease,background .28s ease!important}.mobile-reconnect-banner{position:fixed;top:env(safe-area-inset-top,0);left:0;right:0;z-index:100;display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--color-warning);color:var(--btn-primary-color);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);animation:slideDown var(--motion-fast) var(--easing-standard)}.mobile-reconnect-banner button{margin-left:4px;padding:3px 9px;border:1px solid currentColor;border-radius:var(--size-radius-full);background:transparent;color:inherit;font:inherit;cursor:pointer}.mobile-reconnect-spinner{display:inline-block;width:14px;height:14px;border:2px solid color-mix(in srgb,currentColor 30%,transparent);border-top-color:currentColor;border-radius:50%;animation:reconnect-spin .8s linear infinite}@keyframes reconnect-spin{to{transform:rotate(360deg)}}.pairing-page{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100%;min-height:100dvh;gap:var(--size-gap-6);padding:max(var(--size-gap-8),env(safe-area-inset-top,0px)) max(var(--size-gap-8),env(safe-area-inset-right,0px)) max(var(--size-gap-8),env(safe-area-inset-bottom,0px)) max(var(--size-gap-8),env(safe-area-inset-left,0px));animation:fadeIn var(--motion-slow) cubic-bezier(0,0,.2,1)}.pairing-page__actions{position:absolute;top:calc(var(--size-gap-4) + env(safe-area-inset-top,0px));right:calc(var(--size-gap-4) + env(safe-area-inset-right,0px));display:flex;align-items:center;gap:var(--size-gap-2)}.pairing-page__theme-btn{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:1px solid var(--border-subtle);border-radius:50%;background:var(--element-bg-subtle);color:var(--color-text-secondary);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.pairing-page__theme-btn:active{transform:scale(.96);color:var(--color-text-primary);background:var(--element-bg-base)}.pairing-page__logo{width:64px;height:64px;object-fit:contain;margin-bottom:var(--size-gap-2);animation:pairingLogoBreathe 3.2s var(--easing-standard) infinite}@keyframes pairingLogoBreathe{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.05);opacity:.88}}.pairing-page__brand{font-size:var(--font-size-2xl);font-weight:var(--font-weight-semibold);color:var(--color-accent-500);letter-spacing:.5px}.pairing-page__state{font-size:var(--font-size-sm);color:var(--color-text-muted);text-align:center}.pairing-page__form{width:min(100%,320px);display:flex;flex-direction:column;gap:var(--size-gap-3)}.pairing-page__field{display:flex;flex-direction:column;gap:8px}.pairing-page__field-label{font-size:var(--font-size-xs);color:var(--color-text-secondary);letter-spacing:.04em;text-transform:uppercase}.pairing-page__input{width:100%;min-height:44px;padding:0 14px;border:1px solid var(--border-base);border-radius:var(--size-radius-base);background:var(--color-bg-elevated);color:var(--color-text-primary);font-size:var(--font-size-base);outline:none}.pairing-page__input:focus{border-color:var(--color-accent-400);box-shadow:0 0 0 3px color-mix(in srgb,var(--color-accent-400) 18%,transparent)}.pairing-page__note{margin:0;font-size:var(--font-size-xs);line-height:1.5;color:var(--color-text-muted);text-align:left}.pairing-page__spinner-wrap{height:32px;display:flex;align-items:center;justify-content:center}.pairing-page__error{font-size:var(--font-size-xs);color:var(--color-error);text-align:center;max-width:280px;padding:var(--size-gap-2) var(--size-gap-3);background:var(--color-error-bg);border:1px solid var(--color-error-border);border-radius:var(--size-radius-base)}.pairing-page__retry{padding:var(--size-gap-3) var(--size-gap-8);background:var(--btn-default-bg);color:var(--color-text-primary);border:1px solid var(--border-base);border-radius:var(--size-radius-base);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.pairing-page__retry:active{background:var(--btn-hover-bg)}.pairing-page__retry:disabled{opacity:.6;cursor:not-allowed}@media(prefers-reduced-motion:reduce){.pairing-page,.pairing-page__logo{animation:none}}.session-list{position:relative;display:flex;flex-direction:column;height:100%;background:var(--color-bg-primary);overflow:hidden}.session-list__header{position:relative;z-index:1;display:flex;align-items:center;justify-content:space-between;padding:0 var(--size-gap-5);min-height:56px;border-bottom:1px solid var(--border-subtle);background:var(--color-bg-elevated);backdrop-filter:var(--blur-base);-webkit-backdrop-filter:var(--blur-base);flex-shrink:0}.session-list__header-brand{display:flex;align-items:center;gap:var(--size-gap-3);min-width:0}.session-list__header-copy{display:flex;flex-direction:column;gap:0;min-width:0}.session-list__header-copy h1{margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--color-text-primary);letter-spacing:.01em;width:fit-content}.session-list__header-account-name{font-size:11px;font-weight:var(--font-weight-medium);color:var(--color-text-muted);letter-spacing:.02em}.session-list__health-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:5px;vertical-align:middle}.session-list__health-dot--connected{background:var(--color-success)}.session-list__health-dot--checking{background:var(--color-warning)}.session-list__health-dot--unpaired{background:var(--color-text-muted)}.session-list__health-dot--unreachable{background:var(--color-error)}.session-list__header-kicker{font-size:10px;font-weight:var(--font-weight-semibold);letter-spacing:.16em;text-transform:uppercase;color:var(--color-accent-500);width:fit-content}.session-list__logo{width:26px;height:26px;object-fit:contain;flex-shrink:0}.session-list__header-actions{display:flex;align-items:center;gap:var(--size-gap-2)}.mobile-lang-btn.session-list__language-btn{width:32px;min-width:32px;height:32px;padding:0}.session-list__theme-btn,.session-list__devices-btn,.session-list__disconnect-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:1px solid var(--border-subtle);border-radius:50%;background:var(--element-bg-subtle);color:var(--color-text-secondary);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.session-list__theme-btn:active,.session-list__devices-btn:active,.session-list__disconnect-btn:active{transform:scale(.96);color:var(--color-text-primary);background:var(--element-bg-base)}.session-list__disconnect-btn:active{color:var(--color-error);background:var(--color-error-bg)}.session-list__devices-btn.is-remote{border-color:var(--color-accent-200);background:var(--color-accent-100);color:var(--color-accent-500)}.session-list__header-target{display:inline-block;max-width:120px;margin-left:6px;padding:0 7px;border:1px solid var(--color-accent-200);border-radius:var(--size-radius-full);background:var(--color-accent-100);color:var(--color-accent-500);font-size:10px;font-weight:var(--font-weight-semibold);line-height:16px;letter-spacing:.02em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.session-list__workspace-bar{position:relative;z-index:1;display:flex;align-items:center;gap:12px;padding:12px;border:1px solid var(--color-accent-200);border-radius:20px;corner-shape:squircle;background:var(--color-accent-50);cursor:pointer;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard)}.session-list__workspace-bar:active{transform:translateY(1px);background:var(--color-accent-100)}.session-list__resume-card{display:flex;align-items:center;gap:12px;width:100%;padding:14px 16px;border:1.5px solid var(--color-accent-200);border-radius:18px;corner-shape:squircle;background:var(--color-accent-50);color:var(--color-text-primary);font:inherit;text-align:left;cursor:pointer;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard);animation:sessionItemIn var(--motion-base) cubic-bezier(0,0,.2,1) both}.session-list__resume-card:active{transform:scale(.985);background:var(--color-accent-100)}.session-list__resume-card:focus-visible{outline:2px solid var(--color-accent-500);outline-offset:2px}.session-list__resume-icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:10px;corner-shape:squircle}.session-list__resume-body{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;gap:2px;text-align:left}.session-list__resume-label{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--color-accent-500)}.session-list__resume-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-list__resume-meta{display:flex;align-items:center;gap:8px;margin-top:2px;min-width:0;overflow:hidden}.session-list__resume-time{font-size:11px;color:var(--color-text-muted);white-space:nowrap;flex-shrink:0}.session-list__resume-arrow{flex-shrink:0;color:var(--color-text-muted);display:inline-flex;align-items:center}.session-list__mode-toggle{display:flex;gap:6px;padding:4px;border:1px solid var(--border-subtle);border-radius:16px;corner-shape:squircle;background:var(--color-bg-secondary)}.session-list__mode-toggle-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:8px;padding:10px 12px;border:none;border-radius:12px;corner-shape:squircle;background:transparent;color:var(--color-text-secondary);font-size:13px;font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.session-list__mode-toggle-btn svg{width:18px;height:18px;flex-shrink:0}.session-list__mode-toggle-btn.is-active{background:var(--color-bg-elevated);color:var(--color-text-primary);box-shadow:var(--shadow-sm)}.session-list__mode-toggle-btn.is-active.is-active:first-child{color:var(--color-accent-500)}.session-list__mode-toggle-btn.is-active.is-active:last-child{color:var(--color-pink-500)}.session-list__mode-toggle-btn:active:not(.is-active){background:var(--element-bg-subtle)}.session-list__workspace-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:10px;corner-shape:squircle;color:var(--color-accent-500);background:var(--color-accent-100)}.session-list__workspace-copy{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.session-list__workspace-label{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--color-accent-500)}.session-list__workspace-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-list__workspace-branch{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:999px;corner-shape:squircle;background:var(--color-accent-100);color:var(--color-accent-500);font-size:11px;flex-shrink:1;min-width:0;white-space:nowrap}.session-list__workspace-switch{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--color-text-muted)}.session-list__items{position:relative;z-index:1;flex:1;overflow-y:auto;padding:var(--size-gap-4);-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:var(--size-gap-4)}.session-list__panel{position:relative;padding:var(--size-gap-4);border:1px solid var(--border-subtle);border-radius:22px;corner-shape:squircle;background:var(--color-bg-elevated);box-shadow:var(--shadow-base);overflow:visible}.session-list__section-head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--size-gap-3);margin-bottom:var(--size-gap-4)}.session-list__section-kicker{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--color-accent-500)}.session-list__panel--assistant .session-list__section-kicker{color:var(--color-pink-500)}.session-list__section-title{margin-top:4px;font-size:var(--font-size-lg);line-height:1.1;font-weight:var(--font-weight-semibold);color:var(--color-text-primary);letter-spacing:-.02em}.session-list__section-meta{font-size:11px;color:var(--color-text-muted);flex-shrink:0}.session-list__hint{background:var(--color-pink-100);color:var(--color-pink-600);border:1px solid var(--color-pink-200)}.session-list__assistant-bar{position:relative;z-index:1;display:flex;align-items:center;gap:12px;margin:0;padding:12px;border:1px solid var(--color-pink-200);border-radius:20px;corner-shape:squircle;background:var(--color-pink-50);cursor:pointer;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard)}.session-list__assistant-bar:active{transform:translateY(1px);background:var(--color-pink-100)}.session-list__assistant-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:10px;corner-shape:squircle;color:var(--color-pink-500);background:var(--color-pink-100)}.session-list__assistant-icon svg{width:20px;height:20px}.session-list__assistant-copy{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.session-list__assistant-label{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--color-pink-500)}.session-list__assistant-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-list__assistant-switch{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--color-text-muted)}.session-list__create-row{display:flex;flex-direction:column;gap:10px}.session-list__create-btn{position:relative;display:flex;align-items:center;gap:12px;width:100%;padding:12px;border:1px solid var(--border-subtle);border-radius:18px;corner-shape:squircle;background:var(--color-bg-secondary);color:var(--color-text-primary);cursor:pointer;text-align:left;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard);animation:sessionItemIn var(--motion-base) cubic-bezier(0,0,.2,1) both;box-shadow:var(--shadow-sm)}.session-list__create-btn:active:not(:disabled){transform:translateY(1px);background:var(--element-bg-subtle)}.session-list__create-btn:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.session-list__create-btn--code{border-color:var(--color-accent-200)}.session-list__create-btn--cowork{border-color:var(--color-purple-200)}.session-list__create-btn--claw{border-color:var(--color-pink-200)}.session-list__create-icon{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:10px;corner-shape:squircle;flex-shrink:0;color:var(--color-accent-500);background:var(--color-accent-100)}.session-list__create-btn--cowork .session-list__create-icon{color:var(--color-purple-500);background:var(--color-purple-100)}.session-list__create-btn--claw .session-list__create-icon{color:var(--color-pink-500);background:var(--color-pink-100)}.session-list__create-copy{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}.session-list__create-title{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);letter-spacing:-.01em}.session-list__create-desc{font-size:11px;line-height:1.35;color:var(--color-text-secondary);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.session-list__create-arrow{display:inline-flex;align-items:center;justify-content:center;color:var(--color-text-muted);flex-shrink:0}.session-list__cards{display:flex;flex-direction:column;gap:10px}.session-list__item{display:flex;align-items:center;gap:12px;padding:12px;border:1px solid var(--border-subtle);border-radius:18px;corner-shape:squircle;background:var(--color-bg-secondary);box-shadow:var(--shadow-xs);cursor:pointer;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard);animation:sessionItemIn var(--motion-base) cubic-bezier(0,0,.2,1) both}.session-list__item:nth-child(1){animation-delay:35ms}.session-list__item:nth-child(2){animation-delay:70ms}.session-list__item:nth-child(3){animation-delay:105ms}.session-list__item:nth-child(4){animation-delay:.14s}.session-list__item:nth-child(5){animation-delay:175ms}.session-list__item:nth-child(6){animation-delay:.21s}.session-list__item:nth-child(7){animation-delay:245ms}.session-list__item:nth-child(8){animation-delay:.28s}.session-list__item:nth-child(9){animation-delay:315ms}.session-list__item:nth-child(10){animation-delay:.35s}.session-list__item:nth-child(11){animation-delay:385ms}.session-list__item:nth-child(12){animation-delay:.42s}.session-list__item:nth-child(13){animation-delay:455ms}.session-list__item:nth-child(14){animation-delay:.49s}.session-list__item:nth-child(15){animation-delay:525ms}.session-list__item:nth-child(16){animation-delay:.56s}.session-list__item:nth-child(17){animation-delay:595ms}.session-list__item:nth-child(18){animation-delay:.63s}.session-list__item:nth-child(19){animation-delay:665ms}.session-list__item:nth-child(20){animation-delay:.7s}.session-list__item:active{transform:translateY(1px);background:var(--element-bg-subtle)}.session-list__item-icon{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:10px;corner-shape:squircle;flex-shrink:0;color:var(--color-accent-500);background:var(--color-accent-100)}.session-list__item-icon--cowork,.session-list__item-icon--Cowork{color:var(--color-purple-500);background:var(--color-purple-100)}.session-list__item-icon--claw,.session-list__item-icon--Claw{color:var(--color-pink-500);background:var(--color-pink-100)}.session-list__item-body{min-width:0;flex:1;display:flex;flex-direction:column;justify-content:center}.session-list__item-top{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--size-gap-3)}.session-list__item-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);line-height:1.25;color:var(--color-text-primary);min-width:0;flex:1;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}.session-list__item-time{font-size:10px;color:var(--color-text-muted);margin-top:2px}.session-list__agent-badge{display:inline-flex;align-items:center;min-height:18px;padding:0 8px;border-radius:999px;corner-shape:squircle;font-size:10px;font-weight:var(--font-weight-semibold);border:1px solid var(--border-subtle);background:var(--element-bg-subtle);color:var(--color-text-secondary);flex-shrink:0}.session-list__agent-badge--code,.session-list__agent-badge--agentic{background:var(--color-accent-100);color:var(--color-accent-500);border-color:var(--color-accent-200)}.session-list__agent-badge--cowork,.session-list__agent-badge--Cowork{background:var(--color-purple-100);color:var(--color-purple-500);border-color:var(--color-purple-200)}.session-list__agent-badge--claw,.session-list__agent-badge--Claw{background:var(--color-pink-100);color:var(--color-pink-500);border-color:var(--color-pink-200)}.session-list__empty{padding:var(--size-gap-10) var(--size-gap-4);text-align:center;font-size:var(--font-size-sm);line-height:1.6;color:var(--color-text-muted);border:1px solid var(--border-subtle);border-radius:18px;corner-shape:squircle;background:var(--color-bg-secondary)}.session-list__pull-indicator{display:flex;align-items:center;justify-content:center;overflow:hidden;transition:height .2s cubic-bezier(0,0,.2,1)}.session-list__pull-spinner{color:var(--color-text-muted);transition:color var(--motion-fast)}.session-list__pull-spinner.is-active{color:var(--color-accent-500);animation:spin .8s linear infinite}.session-list__load-more{padding:var(--size-gap-3) 0 var(--size-gap-1);text-align:center;font-size:12px;color:var(--color-text-muted)}.session-list__picker-overlay{position:fixed;inset:0;background:var(--color-overlay);display:flex;align-items:flex-end;justify-content:center;z-index:1000;animation:fadeIn var(--motion-fast) var(--easing-standard)}.session-list__picker-modal{width:100%;max-height:60vh;background:var(--color-bg-elevated);border-radius:20px 20px 0 0;overflow:hidden;animation:slideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.session-list__picker-header{display:flex;align-items:center;justify-content:space-between;padding:var(--size-gap-4);border-bottom:1px solid var(--border-subtle)}.session-list__picker-header h3{margin:0;font-size:16px;font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.session-list__picker-close{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;color:var(--color-text-secondary);cursor:pointer;border-radius:50%}.session-list__picker-close:active{background:var(--element-bg-subtle)}.session-list__picker-list{padding:var(--size-gap-3);max-height:calc(60vh - 60px);overflow-y:auto}.session-list__picker-empty{padding:var(--size-gap-6);text-align:center;color:var(--color-text-muted);font-size:var(--font-size-sm)}.session-list__picker-item{display:flex;align-items:center;gap:12px;width:100%;padding:12px;border:1px solid var(--border-subtle);border-radius:16px;corner-shape:squircle;background:var(--color-bg-secondary);color:var(--color-text-primary);cursor:pointer;text-align:left;transition:all var(--motion-fast) var(--easing-standard);margin-bottom:8px}.session-list__picker-item:last-child{margin-bottom:0}.session-list__picker-item:active{transform:scale(.99);background:var(--element-bg-subtle)}.session-list__picker-item.is-selected{border-color:var(--color-pink-500);background:var(--color-pink-50)}.session-list__picker-item.is-selected svg{color:var(--color-pink-500)}.session-list__picker-item--workspace.is-selected{border-color:var(--color-accent-500);background:var(--color-accent-50)}.session-list__picker-item--workspace.is-selected svg{color:var(--color-accent-500)}.session-list__picker-item svg{color:var(--color-text-muted);flex-shrink:0}.session-list__picker-item-icon{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:10px;corner-shape:squircle;color:var(--color-pink-500);background:var(--color-pink-100);flex-shrink:0}.session-list__picker-item-icon svg{width:18px;height:18px;color:inherit}.session-list__picker-item--workspace .session-list__picker-item-icon{color:var(--color-accent-500);background:var(--color-accent-100)}.session-list__picker-item-name{flex:1;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-primary)}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes sessionItemIn{0%{opacity:0;transform:translateY(12px) scale(.985)}to{opacity:1;transform:translateY(0)}}.session-list__search{display:flex;align-items:center;gap:8px;padding:6px 10px;border:1px solid var(--border-subtle);border-radius:12px;corner-shape:squircle;background:var(--color-bg-secondary);margin-bottom:var(--size-gap-3)}.session-list__search-icon{flex-shrink:0;color:var(--color-text-muted)}.session-list__search-input{flex:1;border:none;background:none;font-size:var(--font-size-sm);color:var(--color-text-primary);outline:none;padding:0;min-width:0}.session-list__search-input::placeholder{color:var(--color-text-muted)}.session-list__search-input::-webkit-search-decoration,.session-list__search-input::-webkit-search-cancel-button{display:none}.session-list__search-clear{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:none;color:var(--color-text-muted);cursor:pointer;border-radius:50%;flex-shrink:0}.session-list__search-clear:active{background:var(--element-bg-subtle);color:var(--color-text-primary)}.session-list__menu-overlay{position:fixed;inset:0;background:var(--color-overlay);display:flex;align-items:flex-end;justify-content:center;z-index:1000;animation:fadeIn var(--motion-fast) var(--easing-standard)}.session-list__menu-sheet{width:100%;max-width:440px;background:var(--color-bg-elevated);border-radius:20px 20px 0 0;padding:var(--size-gap-2) var(--size-gap-4) var(--size-gap-6);display:flex;flex-direction:column;gap:var(--size-gap-3);animation:slideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.session-list__menu-handle{width:36px;height:4px;border-radius:999px;background:var(--border-subtle);margin:0 auto}.session-list__menu-title{text-align:center;font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);padding:var(--size-gap-1) 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-list__menu-actions{display:flex;flex-direction:column;gap:4px}.session-list__menu-btn{display:flex;align-items:center;gap:12px;width:100%;padding:14px 16px;border:none;border-radius:16px;corner-shape:squircle;background:var(--color-bg-secondary);color:var(--color-text-primary);font-size:var(--font-size-base);font-weight:var(--font-weight-medium);cursor:pointer;text-align:left}.session-list__menu-btn svg{flex-shrink:0}.session-list__menu-btn:active{background:var(--element-bg-subtle);transform:scale(.99)}.session-list__menu-btn--danger{color:var(--color-error);background:var(--color-error-bg)}.session-list__menu-btn--danger:active{background:color-mix(in srgb,var(--color-error) 12%,transparent)}.session-list__menu-cancel{width:100%;padding:14px;border:none;border-radius:14px;corner-shape:squircle;background:var(--color-bg-secondary);color:var(--color-text-secondary);font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);cursor:pointer}.session-list__menu-cancel:active{background:var(--element-bg-subtle)}.session-list__item--active{border-color:var(--color-accent-500)!important;background:var(--element-bg-subtle)!important}.session-list__rename-modal{width:calc(100% - 32px);max-width:400px;background:var(--color-bg-elevated);border-radius:20px;padding:var(--size-gap-5);display:flex;flex-direction:column;gap:var(--size-gap-4);animation:slideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.session-list__rename-title{margin:0;font-size:18px;font-weight:var(--font-weight-semibold);color:var(--color-text-primary);text-align:center}.session-list__rename-input{padding:12px 14px;border:1px solid var(--border-subtle);border-radius:12px;corner-shape:squircle;background:var(--color-bg-secondary);color:var(--color-text-primary);font-size:var(--font-size-base);outline:none}.session-list__rename-input:focus{border-color:var(--color-accent-500);box-shadow:0 0 0 3px var(--color-accent-100)}.session-list__rename-actions{display:flex;gap:10px}.session-list__rename-btn{flex:1;padding:12px;border:none;border-radius:14px;corner-shape:squircle;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.session-list__rename-btn:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.session-list__rename-btn--cancel{background:var(--color-bg-secondary);color:var(--color-text-secondary)}.session-list__rename-btn--cancel:active:not(:disabled){background:var(--element-bg-subtle)}.session-list__rename-btn--save{background:var(--color-accent-500);color:var(--btn-primary-color)}.session-list__rename-btn--save:active:not(:disabled){opacity:.85}.session-list__confirm-modal{width:calc(100% - 32px);max-width:340px;background:var(--color-bg-elevated);border-radius:20px;padding:var(--size-gap-6) var(--size-gap-5) var(--size-gap-5);display:flex;flex-direction:column;align-items:center;gap:var(--size-gap-3);text-align:center;animation:slideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.session-list__confirm-icon{color:var(--color-error);margin-bottom:var(--size-gap-1)}.session-list__confirm-title{margin:0;font-size:17px;font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.session-list__confirm-desc{margin:0;font-size:var(--font-size-sm);color:var(--color-text-secondary);line-height:1.5}.session-list__confirm-actions{display:flex;gap:10px;width:100%;margin-top:var(--size-gap-2)}.session-list__confirm-btn{flex:1;padding:12px;border:none;border-radius:14px;corner-shape:squircle;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.session-list__confirm-btn:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.session-list__confirm-btn--cancel{background:var(--color-bg-secondary);color:var(--color-text-secondary)}.session-list__confirm-btn--cancel:active:not(:disabled){background:var(--element-bg-subtle)}.session-list__confirm-btn--danger{background:var(--color-error);color:var(--btn-primary-color)}.session-list__confirm-btn--danger:active:not(:disabled){opacity:.85}.session-list__toast{position:fixed;bottom:40px;left:50%;transform:translate(-50%);padding:10px 20px;border-radius:999px;background:var(--color-text-primary);color:var(--color-bg-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);z-index:9999;box-shadow:var(--shadow-base);pointer-events:none;animation:toastIn .25s var(--easing-standard)}@keyframes toastIn{0%{opacity:0;transform:translate(-50%) translateY(10px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.session-list *,.session-list *:before,.session-list *:after{animation:none!important;transition:none!important}}.devices-page{position:relative;display:flex;flex-direction:column;height:100%;background:var(--color-bg-primary);overflow:hidden}.devices-page__header{position:relative;z-index:1;display:flex;align-items:center;gap:var(--size-gap-3);padding:0 var(--size-gap-4);min-height:56px;border-bottom:1px solid var(--border-subtle);background:var(--color-bg-elevated);backdrop-filter:var(--blur-base);-webkit-backdrop-filter:var(--blur-base);flex-shrink:0}.devices-page__back-btn,.devices-page__refresh-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:1px solid var(--border-subtle);border-radius:50%;background:var(--element-bg-subtle);color:var(--color-text-secondary);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard);flex-shrink:0}.devices-page__back-btn:active,.devices-page__refresh-btn:active{transform:scale(.96);color:var(--color-text-primary);background:var(--element-bg-base)}.devices-page__back-btn:disabled,.devices-page__refresh-btn:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.devices-page__back-btn.is-loading svg,.devices-page__refresh-btn.is-loading svg{animation:reconnect-spin .8s linear infinite}.devices-page__title{flex:1;margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--color-text-primary);letter-spacing:.01em}.devices-page__body{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:var(--size-gap-4)}.devices-page__list{display:flex;flex-direction:column;gap:var(--size-gap-3)}.devices-page__device{display:flex;align-items:center;gap:var(--size-gap-3);width:100%;padding:var(--size-gap-4);border:1px solid var(--border-subtle);border-radius:20px;corner-shape:squircle;background:var(--color-bg-elevated);color:var(--color-text-primary);text-align:left;cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.devices-page__device:active:not(:disabled){background:var(--element-bg-subtle);transform:scale(.99)}.devices-page__device.is-offline{opacity:var(--opacity-disabled);cursor:not-allowed}.devices-page__device.is-current{border-color:var(--color-accent-300);background:var(--color-accent-50);cursor:default}.devices-page__device.is-switching{border-color:var(--color-accent-300)}.devices-page__device>svg{flex-shrink:0;color:var(--color-text-muted)}.devices-page__device-icon{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border:1px solid var(--border-subtle);border-radius:var(--size-radius-lg);background:var(--element-bg-subtle);color:var(--color-text-secondary);flex-shrink:0}.is-current .devices-page__device-icon{background:var(--color-accent-100);border-color:var(--color-accent-200);color:var(--color-accent-500)}.devices-page__device-copy{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}.devices-page__device-name-row{display:flex;align-items:center;gap:var(--size-gap-2);min-width:0}.devices-page__device-name{font-size:var(--font-size-base);font-weight:var(--font-weight-medium);color:var(--color-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.devices-page__badge{flex-shrink:0;padding:1px 7px;border:1px solid var(--border-subtle);border-radius:var(--size-radius-full);background:var(--element-bg-subtle);color:var(--color-text-secondary);font-size:10px;font-weight:var(--font-weight-semibold);letter-spacing:.03em}.devices-page__badge--current{border-color:var(--color-accent-200);background:var(--color-accent-100);color:var(--color-accent-500)}.devices-page__device-meta{display:flex;align-items:center;gap:5px;font-size:var(--font-size-xs);color:var(--color-text-muted)}.devices-page__status-dot{display:inline-block;width:7px;height:7px;border-radius:50%;flex-shrink:0}.devices-page__status-dot.is-online{background:var(--color-success)}.devices-page__status-dot.is-offline{background:var(--color-text-muted)}.devices-page__device-id{margin-left:var(--size-gap-1);font-family:var(--font-family-mono);letter-spacing:.02em}.devices-page__device-spinner{flex-shrink:0;width:16px;height:16px;border-width:2px}.devices-page__loading{display:flex;flex-direction:column;align-items:center;gap:var(--size-gap-3);padding:var(--size-gap-10) 0;font-size:var(--font-size-sm);color:var(--color-text-muted)}.devices-page__empty{padding:var(--size-gap-10) 0;text-align:center;font-size:var(--font-size-sm);color:var(--color-text-muted)}.devices-page__empty-card{display:flex;flex-direction:column;align-items:center;gap:var(--size-gap-4);margin-top:var(--size-gap-8);padding:var(--size-gap-8) var(--size-gap-6);border:1px solid var(--border-subtle);border-radius:20px;corner-shape:squircle;background:var(--color-bg-elevated)}.devices-page__empty-icon{display:inline-flex;color:var(--color-text-muted)}.devices-page__empty-text{margin:0;font-size:var(--font-size-sm);line-height:var(--line-height-relaxed);color:var(--color-text-secondary);text-align:center}.devices-page__retry-btn{padding:var(--size-gap-2) var(--size-gap-6);border:1px solid var(--border-base);border-radius:var(--size-radius-full);background:var(--btn-default-bg);color:var(--color-text-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.devices-page__retry-btn:active{background:var(--btn-hover-bg)}.devices-page__error{margin:var(--size-gap-3) var(--size-gap-4) 0;padding:var(--size-gap-2) var(--size-gap-3);font-size:var(--font-size-xs);color:var(--color-error);background:var(--color-error-bg);border:1px solid var(--color-error-border);border-radius:var(--size-radius-base)}.workspace-page{display:flex;flex-direction:column;height:100%;background:var(--color-bg-primary)}.workspace-page__header{display:flex;align-items:center;justify-content:space-between;gap:var(--size-gap-3);padding:0 var(--size-gap-5);height:56px;min-height:56px;border-bottom:1px solid var(--border-subtle);background:var(--color-bg-elevated);backdrop-filter:var(--blur-base);-webkit-backdrop-filter:var(--blur-base);flex-shrink:0}.workspace-page__header h1{font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.workspace-page__content{flex:1;overflow-y:auto;padding:var(--size-gap-4);-webkit-overflow-scrolling:touch}.workspace-page__loading{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:var(--size-gap-4);color:var(--color-text-muted);font-size:var(--font-size-sm)}.workspace-page__current{display:flex;flex-direction:column;gap:var(--size-gap-4)}.workspace-page__current-label,.workspace-page__recent-label{font-size:9px;font-weight:var(--font-weight-semibold);color:var(--color-accent-500);text-transform:uppercase;letter-spacing:.14em}.workspace-page__current-card{border:1px solid var(--border-subtle);border-radius:18px;corner-shape:squircle;padding:var(--size-gap-4);background:var(--color-bg-elevated);box-shadow:var(--shadow-sm);transition:all var(--motion-fast) var(--easing-standard)}.workspace-page__project-name{font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);margin-bottom:var(--size-gap-1)}.workspace-page__project-path{font-size:var(--font-size-xs);color:var(--color-text-muted);word-break:break-all;margin-bottom:var(--size-gap-2);font-family:var(--font-family-mono)}.workspace-page__git-branch{display:inline-flex;align-items:center;gap:4px;font-size:var(--font-size-xs);color:var(--color-accent-500);background:var(--color-accent-100);padding:3px var(--size-gap-2);border-radius:8px;corner-shape:squircle;word-break:break-all}.workspace-page__actions{display:flex;gap:var(--size-gap-2)}.workspace-page__btn{flex:1;padding:var(--size-gap-3) var(--size-gap-4);border:none;border-radius:12px;corner-shape:squircle;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.workspace-page__btn--primary{background:var(--color-accent-500);color:var(--btn-primary-color)}.workspace-page__btn--primary:active{background:var(--color-accent-600)}.workspace-page__btn--secondary{background:var(--element-bg-subtle);color:var(--color-text-primary);border:1px solid var(--border-subtle)}.workspace-page__btn--secondary:active{background:var(--element-bg-base)}.workspace-page__btn:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.workspace-page__no-workspace{display:flex;flex-direction:column;align-items:center;text-align:center;padding:var(--size-gap-10) var(--size-gap-5);gap:var(--size-gap-3);border:1px solid var(--border-subtle);border-radius:22px;corner-shape:squircle;background:var(--color-bg-elevated);box-shadow:var(--shadow-base)}.workspace-page__no-workspace-icon{color:var(--color-text-muted);opacity:.5}.workspace-page__no-workspace-text{font-size:var(--font-size-base);font-weight:var(--font-weight-medium);color:var(--color-text-primary)}.workspace-page__no-workspace-hint{font-size:var(--font-size-xs);color:var(--color-text-muted);max-width:280px}.workspace-page__recent{margin-top:var(--size-gap-5);display:flex;flex-direction:column;gap:var(--size-gap-3);animation:slideUp .3s cubic-bezier(0,0,.2,1) both}.workspace-page__recent-empty{text-align:center;color:var(--color-text-muted);font-size:var(--font-size-xs);padding:var(--size-gap-6) 0}.workspace-page__recent-list{display:flex;flex-direction:column;gap:var(--size-gap-2)}.workspace-page__recent-item{display:flex;flex-direction:column;align-items:flex-start;background:var(--color-bg-secondary);border:1px solid var(--border-subtle);border-radius:14px;corner-shape:squircle;padding:12px;cursor:pointer;text-align:left;color:var(--color-text-primary);box-shadow:var(--shadow-xs);transition:all var(--motion-fast) var(--easing-standard);animation:slideUp .3s cubic-bezier(0,0,.2,1) both}.workspace-page__recent-item:nth-child(1){animation-delay:.04s}.workspace-page__recent-item:nth-child(2){animation-delay:.08s}.workspace-page__recent-item:nth-child(3){animation-delay:.12s}.workspace-page__recent-item:nth-child(4){animation-delay:.16s}.workspace-page__recent-item:nth-child(5){animation-delay:.2s}.workspace-page__recent-item:nth-child(6){animation-delay:.24s}.workspace-page__recent-item:nth-child(7){animation-delay:.28s}.workspace-page__recent-item:nth-child(8){animation-delay:.32s}.workspace-page__recent-item:nth-child(9){animation-delay:.36s}.workspace-page__recent-item:nth-child(10){animation-delay:.4s}.workspace-page__recent-item:nth-child(11){animation-delay:.44s}.workspace-page__recent-item:nth-child(12){animation-delay:.48s}.workspace-page__recent-item:nth-child(13){animation-delay:.52s}.workspace-page__recent-item:nth-child(14){animation-delay:.56s}.workspace-page__recent-item:nth-child(15){animation-delay:.6s}.workspace-page__recent-item:nth-child(16){animation-delay:.64s}.workspace-page__recent-item:nth-child(17){animation-delay:.68s}.workspace-page__recent-item:nth-child(18){animation-delay:.72s}.workspace-page__recent-item:nth-child(19){animation-delay:.76s}.workspace-page__recent-item:nth-child(20){animation-delay:.8s}.workspace-page__recent-item:active{transform:translateY(1px);background:var(--element-bg-subtle)}.workspace-page__recent-item:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.workspace-page__recent-item-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--color-text-primary);margin-bottom:2px}.workspace-page__recent-item-path{font-size:11px;color:var(--color-text-muted);word-break:break-all;font-family:var(--font-family-mono)}.workspace-page__switching{display:flex;align-items:center;justify-content:center;gap:var(--size-gap-2);padding:var(--size-gap-4);color:var(--color-text-muted);font-size:var(--font-size-xs)}.workspace-page__error{margin-top:var(--size-gap-3);font-size:var(--font-size-xs);color:var(--color-error);text-align:center;padding:var(--size-gap-2) var(--size-gap-3);background:var(--color-error-bg);border-radius:10px;corner-shape:squircle}@media(prefers-reduced-motion:reduce){.workspace-page__recent,.workspace-page__recent-item{animation:none}.workspace-page__recent-item{transition:none}}.chat-page{display:flex;flex-direction:column;height:100%;background:var(--color-bg-flowchat)}.chat-page__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:0 var(--size-gap-5);min-height:56px;border-bottom:1px solid var(--border-subtle);flex-shrink:0;background:var(--color-bg-elevated);backdrop-filter:var(--blur-base);-webkit-backdrop-filter:var(--blur-base);position:relative;z-index:10}.chat-page__header-row{display:flex;align-items:center;gap:var(--size-gap-2);flex:1;min-width:0}.chat-page__back{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;background:none;border:none;color:var(--color-text-muted);cursor:pointer;padding:0;flex-shrink:0;border-radius:50%;transition:all var(--motion-fast) var(--easing-standard)}.chat-page__back:active{background:var(--element-bg-subtle);color:var(--color-text-primary)}.chat-page__header-center{flex:1;min-width:0;overflow:hidden;text-align:center}.chat-page__title{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--color-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}.chat-page__header-right{display:flex;align-items:center;gap:var(--size-gap-1);flex-shrink:0}.chat-page__theme-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:none;border:none;color:var(--color-text-muted);cursor:pointer;border-radius:50%;transition:all var(--motion-fast) var(--easing-standard)}.chat-page__theme-btn:active{background:var(--element-bg-subtle)}.chat-page__header-workspace{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--color-text-muted);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;justify-content:center}.chat-page__workspace-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--color-accent-500);font-weight:var(--font-weight-medium);font-size:11px}.chat-page__workspace-branch{color:var(--color-text-muted);font-weight:var(--font-weight-normal);flex-shrink:0;font-size:11px;display:inline-flex;align-items:center;gap:3px}.chat-page__messages{flex:1;overflow-y:auto;padding:var(--size-gap-4) var(--size-gap-4) 100px;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:var(--size-gap-4);position:relative}.chat-page__load-more-indicator{text-align:center;font-size:var(--font-size-xs);color:var(--color-text-muted);padding:var(--size-gap-2) 0}.chat-page__scroll-to-bottom{position:fixed;bottom:110px;left:50%;transform:translate(-50%);width:40px;height:40px;border-radius:50%;border:1px solid var(--border-subtle);background:var(--color-bg-elevated);color:var(--color-text-primary);box-shadow:var(--shadow-base);cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:15;animation:scrollBtnIn .2s var(--easing-standard)}.chat-page__scroll-to-bottom:active{transform:translate(-50%) scale(.92);box-shadow:var(--shadow-sm)}.chat-page__scroll-to-bottom:focus-visible{outline:2px solid var(--color-accent-500);outline-offset:2px}@media(prefers-reduced-motion:reduce){.chat-page__scroll-to-bottom{animation:none}}@media(forced-colors:active){.chat-page__scroll-to-bottom{border:2px solid ButtonText;background:ButtonFace;color:ButtonText}}@keyframes scrollBtnIn{0%{opacity:0;transform:translate(-50%) scale(.7)}to{opacity:1;transform:translate(-50%) scale(1)}}.chat-msg{display:flex;flex-direction:column;width:100%}.chat-msg--user{align-items:flex-start}.chat-msg__user-card{display:flex;align-items:flex-start;width:100%}.chat-msg__user-avatar{display:none}.chat-msg__user-content{width:100%;font-size:var(--font-size-sm);line-height:var(--line-height-relaxed);color:var(--color-text-primary);word-break:break-word;white-space:pre-wrap;padding:8px 12px;background:var(--element-bg-subtle);border:1px solid var(--border-subtle);border-radius:var(--size-radius-base)}.chat-msg__user-images{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}.chat-msg__user-image{width:48px;height:48px;border-radius:6px;object-fit:cover;border:1px solid var(--border-subtle)}.chat-msg--assistant{align-items:flex-start;gap:var(--size-gap-1)}.chat-msg--collapsed{padding:0}.chat-msg__response-toggle{display:inline-flex;align-items:center;gap:6px;background:none;border:none;color:var(--color-text-muted);font-size:var(--font-size-xs);cursor:pointer;padding:3px 0;text-align:left}.chat-msg__response-toggle:active{opacity:.7}.chat-msg__response-chevron{display:inline-flex;align-items:center;transition:transform var(--motion-fast) var(--easing-standard)}.chat-msg__response-chevron.is-open{transform:rotate(90deg)}.chat-msg__response-label{color:var(--color-text-muted);font-style:italic;font-size:var(--font-size-xs)}.chat-msg__image-analyzing{display:flex;align-items:center;gap:8px;padding:10px 14px;font-size:var(--font-size-sm);color:var(--color-text-secondary);background:var(--element-bg-subtle);border-radius:10px;animation:analyzeGlow 2s ease-in-out infinite}.chat-msg__image-analyzing span{flex-shrink:0}.chat-msg__image-analyzing-icon{display:flex;align-items:center;color:var(--color-accent-500);animation:analyzeSpin 3s linear infinite}@keyframes analyzeSpin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes analyzeGlow{0%,to{opacity:1}50%{opacity:.7}}.chat-page__toast{position:fixed;top:48px;left:16px;right:16px;padding:12px 16px;border-radius:10px;background:var(--color-error);color:var(--btn-primary-color);font-size:13px;line-height:1.4;z-index:9999;white-space:pre-line;animation:toastSlideIn .25s ease-out;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.chat-page__toast--info{background:var(--color-success)}@keyframes toastSlideIn{0%{transform:translateY(-20px);opacity:0}to{transform:translateY(0);opacity:1}}.chat-msg--menu-active{opacity:.7}.chat-msg__menu-overlay{position:fixed;inset:0;background:var(--color-overlay);display:flex;align-items:flex-end;justify-content:center;z-index:1000;animation:menuFadeIn var(--motion-fast) var(--easing-standard)}.chat-msg__menu-sheet{width:100%;max-width:440px;background:var(--color-bg-elevated);border-radius:20px 20px 0 0;padding:var(--size-gap-2) var(--size-gap-4) var(--size-gap-6);display:flex;flex-direction:column;gap:var(--size-gap-3);animation:menuSlideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.chat-msg__menu-handle{width:36px;height:4px;border-radius:999px;background:var(--border-subtle);margin:0 auto}.chat-msg__menu-actions{display:flex;flex-direction:column;gap:4px}.chat-msg__menu-btn{display:flex;align-items:center;gap:12px;width:100%;padding:14px 16px;border:none;border-radius:16px;background:var(--color-bg-secondary);color:var(--color-text-primary);font-size:var(--font-size-base);font-weight:var(--font-weight-medium);cursor:pointer;text-align:left}.chat-msg__menu-btn svg{flex-shrink:0}.chat-msg__menu-btn:active:not(:disabled){background:var(--element-bg-subtle);transform:scale(.99)}.chat-msg__menu-btn:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.chat-msg__menu-btn--danger{color:var(--color-error);background:var(--color-error-bg)}.chat-msg__menu-btn--danger:active:not(:disabled){background:var(--color-error-border)}.chat-msg__menu-cancel{width:100%;padding:14px;border:none;border-radius:14px;background:var(--color-bg-secondary);color:var(--color-text-secondary);font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);cursor:pointer}.chat-msg__menu-cancel:active{background:var(--element-bg-subtle)}@keyframes menuFadeIn{0%{opacity:0}to{opacity:1}}@keyframes menuSlideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}@media(prefers-reduced-motion:reduce){.chat-msg__menu-sheet,.chat-msg__menu-overlay{animation:none}}.mobile-lang-btn{display:inline-flex;align-items:center;justify-content:center;min-width:44px;height:44px;padding:0 10px;border:1px solid var(--border-subtle);border-radius:999px;background:var(--element-bg-subtle);color:var(--color-text-secondary);font-size:11px;font-weight:var(--font-weight-semibold);letter-spacing:.04em;cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.mobile-lang-btn:active{transform:scale(.96);color:var(--color-text-primary);background:var(--element-bg-base)}.chat-tool-list{display:flex;flex-direction:column;gap:var(--size-gap-1);width:100%}.chat-tool-list--collapsed{border:1px solid var(--border-base);border-radius:var(--size-radius-lg);background:color-mix(in srgb,var(--color-bg-secondary) 60%,transparent);-webkit-backdrop-filter:var(--blur-base);backdrop-filter:var(--blur-base);overflow:hidden}.chat-tool-list__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);min-height:32px;cursor:pointer;transition:background var(--motion-fast) var(--easing-standard)}.chat-tool-list__header:active{background:var(--element-bg-subtle)}.chat-tool-list__chevron{display:flex;align-items:center;color:var(--color-text-muted);transition:transform var(--motion-fast) var(--easing-standard);flex-shrink:0}.chat-tool-list__chevron.is-expanded{transform:rotate(180deg)}.chat-tool-list__count{font-size:12px;font-weight:var(--font-weight-medium);color:var(--color-text-secondary)}.chat-tool-list__stats{display:flex;gap:var(--size-gap-2);margin-left:auto}.chat-tool-list__stat{font-size:11px;font-variant-numeric:tabular-nums}.chat-tool-list__stat--done{color:var(--color-success)}.chat-tool-list__stat--running{color:var(--color-warning)}.chat-tool-list__scroll{display:flex;flex-direction:column;gap:var(--size-gap-1);padding:var(--size-gap-2);max-height:140px;border-top:1px solid var(--border-subtle);overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scroll-behavior:smooth}.chat-tool-list__scroll .chat-tool-card{flex-shrink:0}.chat-tool-list__scroll{mask-image:linear-gradient(to bottom,transparent 0px,black 16px,black 100%);-webkit-mask-image:linear-gradient(to bottom,transparent 0px,black 16px,black 100%)}.chat-tool-list__scroll::-webkit-scrollbar{width:3px}.chat-tool-list__scroll::-webkit-scrollbar-track{background:transparent}.chat-tool-list__scroll::-webkit-scrollbar-thumb{background:var(--color-text-muted);border-radius:2px;opacity:.4}.chat-tool-card{border-radius:var(--size-radius-base);border:1px solid var(--border-base);background:var(--color-bg-flowchat);overflow:hidden;transition:all var(--motion-fast) var(--easing-standard)}.chat-tool-card--running{border-color:var(--color-warning-border)}.chat-tool-card--done{border-color:var(--color-success-border)}.chat-tool-card--error{border-color:var(--color-error-border)}.chat-tool-card--pending{border-color:var(--color-warning-border)}.chat-tool-card__row{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);cursor:pointer;min-height:36px}.chat-tool-card__icon{display:flex;align-items:center;justify-content:center;width:16px;height:16px;flex-shrink:0}.chat-tool-card__spinner{display:inline-block;width:14px;height:14px;border:2px solid var(--color-warning-border);border-top-color:var(--color-warning);border-radius:50%;animation:spin .7s linear infinite}.chat-tool-card__check{color:var(--color-success);display:flex;align-items:center}.chat-tool-card__error-icon{color:var(--color-error);display:flex;align-items:center}.chat-tool-card__pending-icon{color:var(--color-warning);display:flex;align-items:center}.chat-tool-card__name{flex:1;font-size:var(--font-size-xs);color:var(--color-text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:var(--font-weight-medium);min-width:0}.chat-tool-card__preview{font-weight:var(--font-weight-normal);color:var(--color-text-muted)}.chat-tool-card__type{display:inline-flex;align-items:center;padding:1px 6px;border-radius:var(--size-radius-sm);font-size:11px;font-weight:var(--font-weight-medium);background:var(--color-accent-100);color:var(--color-accent-500);flex-shrink:0}.chat-tool-card__duration{font-size:11px;color:var(--color-text-muted);flex-shrink:0;font-variant-numeric:tabular-nums;font-family:var(--font-family-mono)}.chat-tool-card__cancel{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:var(--size-radius-sm);border:none;background:var(--color-error);color:var(--btn-primary-color);cursor:pointer;flex-shrink:0;transition:all var(--motion-fast) var(--easing-standard);margin-left:auto;box-shadow:0 1px 4px var(--color-error-border)}.chat-tool-card__cancel:active{transform:scale(.9)}.chat-tool-card__cancel svg{flex-shrink:0}.chat-tool-card__expanded{border-top:1px solid var(--border-subtle);padding:var(--size-gap-2) var(--size-gap-3);font-size:var(--font-size-xs);color:var(--color-text-muted);max-height:200px;overflow-y:auto;font-family:var(--font-family-mono);line-height:var(--line-height-relaxed);white-space:pre-wrap;word-break:break-all}.chat-task-card{border-radius:var(--size-radius-lg);border:1px solid var(--border-base);background:color-mix(in srgb,var(--color-bg-secondary) 60%,transparent);-webkit-backdrop-filter:var(--blur-base);backdrop-filter:var(--blur-base);overflow:hidden;width:100%}.chat-task-card--running{border-color:var(--color-warning-border)}.chat-task-card--done{border-color:var(--color-success-border)}.chat-task-card--error{border-color:var(--color-error-border)}.chat-task-card--pending{border-color:var(--color-warning-border)}.chat-task-card__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);min-height:36px}.chat-task-card__summary{display:flex;align-items:center;gap:var(--size-gap-2);padding:4px var(--size-gap-3);border-top:1px solid var(--border-subtle);min-height:24px;cursor:pointer;transition:background var(--motion-fast) var(--easing-standard)}.chat-task-card__summary:active{background:var(--element-bg-subtle)}.chat-task-card__chevron{display:flex;align-items:center;color:var(--color-text-muted);transition:transform var(--motion-fast) var(--easing-standard);flex-shrink:0}.chat-task-card__chevron.is-expanded{transform:rotate(180deg)}.chat-task-card__stat{font-size:11px;font-weight:var(--font-weight-medium);color:var(--color-text-muted)}.chat-task-card__stat-right{display:flex;gap:var(--size-gap-2);margin-left:auto}.chat-task-card__stat--done{font-size:11px;color:var(--color-success);font-variant-numeric:tabular-nums}.chat-task-card__stat--running{font-size:11px;color:var(--color-warning);font-variant-numeric:tabular-nums}.chat-task-card__steps{border-top:1px solid var(--border-subtle);max-height:140px;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scroll-behavior:smooth;padding:var(--size-gap-1) var(--size-gap-3);mask-image:linear-gradient(to bottom,transparent 0px,black 8px,black 100%);-webkit-mask-image:linear-gradient(to bottom,transparent 0px,black 8px,black 100%)}.chat-task-card__steps::-webkit-scrollbar{width:3px}.chat-task-card__steps::-webkit-scrollbar-track{background:transparent}.chat-task-card__steps::-webkit-scrollbar-thumb{background:var(--color-text-muted);border-radius:2px;opacity:.4}.chat-task-card__step{display:flex;align-items:center;gap:var(--size-gap-2);padding:3px 0;font-size:11px;color:var(--color-text-muted);min-height:22px}.chat-task-card__step svg{flex-shrink:0}.chat-task-card__step--thinking{color:var(--color-text-muted);opacity:.7}.chat-task-card__step--thinking svg{transform:rotate(-90deg)}.chat-task-card__step-spinner{display:inline-block;width:10px;height:10px;border:1.5px solid var(--color-warning-border);border-top-color:var(--color-warning);border-radius:50%;animation:spin .7s linear infinite;flex-shrink:0}.chat-task-card__step-name{font-weight:var(--font-weight-medium);color:var(--color-text-secondary);flex-shrink:0}.chat-task-card__step-preview{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--color-text-muted)}.chat-task-card__step-duration{flex-shrink:0;font-variant-numeric:tabular-nums;font-family:var(--font-family-mono);color:var(--color-text-muted)}.chat-ask-card{border:1px solid var(--border-base);border-radius:var(--size-radius-lg);background:color-mix(in srgb,var(--color-bg-secondary) 80%,transparent);-webkit-backdrop-filter:var(--blur-base);backdrop-filter:var(--blur-base);overflow:hidden;width:100%}.chat-ask-card__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);border-bottom:1px solid var(--border-subtle)}.chat-ask-card__count{font-size:12px;font-weight:var(--font-weight-medium);color:var(--color-text-secondary);flex:1}.chat-ask-card__submit{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:var(--size-radius-base);border:1px solid var(--color-accent-500);background:transparent;color:var(--color-accent-500);font-size:12px;font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.chat-ask-card__submit:disabled{opacity:.4;cursor:not-allowed}.chat-ask-card__submit:not(:disabled):active{background:var(--color-accent-100)}.chat-ask-card__submit--bottom{width:100%;justify-content:center;padding:10px;margin-top:8px;font-size:13px}.chat-ask-card__waiting{display:inline-flex;align-items:center;gap:4px;font-size:11px;color:var(--color-warning)}.chat-ask-card__waiting:before{content:"";display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--color-warning);animation:pulse-dot 1.4s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.4}50%{opacity:1}}.chat-ask-card__question{padding:var(--size-gap-2) var(--size-gap-3)}.chat-ask-card__question+.chat-ask-card__question{border-top:1px solid var(--border-subtle)}.chat-ask-card__question-header{display:flex;align-items:baseline;gap:var(--size-gap-2);margin-bottom:var(--size-gap-2)}.chat-ask-card__tag{display:inline-flex;padding:1px 6px;border-radius:var(--size-radius-sm);font-size:11px;font-weight:var(--font-weight-medium);background:var(--color-accent-100);color:var(--color-accent-500);flex-shrink:0}.chat-ask-card__question-text{font-size:13px;color:var(--color-text-primary);font-weight:var(--font-weight-medium)}.chat-ask-card__options{display:flex;flex-direction:column;gap:var(--size-gap-1)}.chat-ask-card__option{display:flex;align-items:center;gap:var(--size-gap-2);padding:8px 10px;border-radius:var(--size-radius-base);border:1px solid var(--border-base);background:var(--color-bg-flowchat);cursor:pointer;text-align:left;width:100%;transition:all var(--motion-fast) var(--easing-standard)}.chat-ask-card__option:active:not(:disabled){background:var(--color-bg-secondary)}.chat-ask-card__option.is-selected{border-color:var(--color-accent-500);background:color-mix(in srgb,var(--color-accent-100) 40%,transparent)}.chat-ask-card__option:disabled{opacity:.6;cursor:not-allowed}.chat-ask-card__radio{display:flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:50%;border:1.5px solid var(--color-text-muted);flex-shrink:0;color:var(--color-accent-500);transition:all var(--motion-fast) var(--easing-standard)}.is-selected .chat-ask-card__radio{border-color:var(--color-accent-500);background:var(--color-accent-500);color:var(--btn-primary-color)}.chat-ask-card__radio--multi{border-radius:3px}.chat-ask-card__option-label{font-size:13px;color:var(--color-text-primary);font-weight:var(--font-weight-medium);flex-shrink:0}.chat-ask-card__option-desc{font-size:11px;color:var(--color-text-muted);flex:1;text-align:right}.chat-ask-card__custom-input{width:100%;padding:6px 10px;border-radius:var(--size-radius-base);border:1px solid var(--border-base);background:var(--color-bg-flowchat);color:var(--color-text-primary);font-size:13px;outline:none}.chat-ask-card__custom-input:focus{border-color:var(--color-accent-500)}.chat-ask-card__custom-input:disabled{opacity:.5}.chat-todo-card{border-radius:var(--size-radius-base);border:1px solid var(--border-base);background:var(--color-bg-flowchat);overflow:hidden;width:100%}.chat-todo-card__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);cursor:pointer;min-height:36px;transition:background var(--motion-fast) var(--easing-standard)}.chat-todo-card__header:active{background:var(--element-bg-subtle)}.chat-todo-card__icon{display:flex;align-items:center;color:var(--color-accent-500);flex-shrink:0}.chat-todo-card__current{flex:1;min-width:0;font-size:var(--font-size-xs);color:var(--color-text-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-todo-card__current--done{color:var(--color-success);font-weight:var(--font-weight-medium)}.chat-todo-card__right{display:flex;align-items:center;gap:var(--size-gap-2);flex-shrink:0;margin-left:auto}.chat-todo-card__dots{display:flex;align-items:center;gap:3px;flex-shrink:0}.chat-todo-card__dot{width:6px;height:6px;border-radius:50%;transition:all var(--motion-fast) var(--easing-standard)}.chat-todo-card__dot--completed{background:var(--color-success)}.chat-todo-card__dot--in_progress{background:var(--color-accent-500);animation:todoPulse 1.4s ease-in-out infinite}.chat-todo-card__dot--pending{background:var(--color-text-muted);opacity:.3}.chat-todo-card__dot--cancelled{background:var(--color-error);opacity:.5}@keyframes todoPulse{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.chat-todo-card__stats{font-size:11px;font-weight:var(--font-weight-medium);color:var(--color-text-muted);font-variant-numeric:tabular-nums;flex-shrink:0}.chat-todo-card__chevron{display:flex;align-items:center;color:var(--color-text-muted);transition:transform var(--motion-fast) var(--easing-standard);flex-shrink:0}.chat-todo-card__chevron.is-expanded{transform:rotate(180deg)}.chat-todo-card__list{border-top:1px solid var(--border-subtle);padding:var(--size-gap-2) var(--size-gap-3);display:flex;flex-direction:column;gap:var(--size-gap-1)}.chat-todo-card__item{display:flex;align-items:flex-start;gap:var(--size-gap-2);padding:4px 0}.chat-todo-card__item svg{flex-shrink:0;margin-top:1px}.chat-todo-card__item--completed{opacity:.6}.chat-todo-card__item--cancelled{opacity:.4}.chat-todo-card__item-text{font-size:var(--font-size-xs);color:var(--color-text-primary);line-height:var(--line-height-base)}.chat-todo-card__item--in_progress .chat-todo-card__item-text{color:var(--color-accent-500);font-weight:var(--font-weight-medium)}.chat-thinking{display:flex;flex-direction:column;width:100%}.chat-thinking__toggle{display:inline-flex;align-items:center;gap:6px;background:none;border:none;color:var(--color-text-muted);font-size:var(--font-size-xs);cursor:pointer;padding:3px 0;text-align:left}.chat-thinking__toggle:active{opacity:.7}.chat-thinking__chevron{display:inline-flex;align-items:center;transition:transform var(--motion-fast) var(--easing-standard)}.chat-thinking__chevron.is-open{transform:rotate(90deg)}.chat-thinking__label{color:var(--color-text-muted);font-style:italic;font-size:var(--font-size-xs)}.chat-thinking__expand-container{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--motion-base) var(--easing-standard)}.chat-thinking__expand-container.is-expanded{grid-template-rows:1fr}.chat-thinking__expand-inner{overflow:hidden}.chat-thinking__content-wrapper{position:relative;max-height:300px;overflow-y:auto;-webkit-overflow-scrolling:touch}.chat-thinking__content-wrapper:before,.chat-thinking__content-wrapper:after{content:"";position:sticky;left:0;right:0;height:24px;z-index:1;pointer-events:none;display:block}.chat-thinking__content-wrapper:before{top:0;background:linear-gradient(to bottom,var(--color-bg-flowchat),transparent)}.chat-thinking__content-wrapper:after{bottom:0;background:linear-gradient(to top,var(--color-bg-flowchat),transparent)}.chat-thinking__content-wrapper.at-top:before{display:none}.chat-thinking__content-wrapper.at-bottom:after{display:none}.chat-thinking__content{padding:var(--size-gap-2) 0;font-size:var(--font-size-xs);color:var(--color-text-muted);line-height:var(--line-height-relaxed)}.chat-thinking__content p{margin-bottom:6px}.chat-thinking__content p:last-child{margin-bottom:0}.chat-thinking__content code{background:var(--element-bg-base);padding:1px 4px;border-radius:3px;font-size:11px;font-family:var(--font-family-mono)}.chat-thinking--streaming .chat-thinking__label:after{content:"";display:inline-block;width:4px;height:12px;background:var(--color-text-muted);margin-left:4px;animation:pulse 1s ease-in-out infinite;vertical-align:middle;border-radius:1px}.chat-page__input-wrap{position:fixed;bottom:16px;left:50%;transform:translate(-50%);width:100%;max-width:700px;z-index:20;display:flex;justify-content:center;padding:0 8px;transition:max-width .3s cubic-bezier(.4,0,.2,1),padding .3s cubic-bezier(.4,0,.2,1)}.chat-page__input-wrap:not(.is-expanded){max-width:480px}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-box{min-height:42px;max-height:42px;padding:0 8px 0 20px;border-radius:21px;border:1px solid var(--border-subtle);flex-direction:row;align-items:center;gap:8px;cursor:pointer;box-shadow:var(--shadow-lg)}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-box:active{background:var(--color-bg-elevated);box-shadow:var(--shadow-xl);transform:translateY(-1px)}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-area{flex:1 1 auto;min-height:auto;min-width:0}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-actions-left{display:none}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-actions{flex-shrink:0;padding:0;height:auto}.chat-page__input-wrap:not(.is-expanded) .chat-page__action-btn{display:none}.chat-page__input-wrap:not(.is-expanded) .chat-page__send-btn{width:24px;height:24px;opacity:.35}.chat-page__input-wrap.is-expanded .chat-page__input-box{border-radius:12px;padding:12px 8px 0;border:1px solid var(--border-base);flex-direction:column;gap:0}.chat-page__input-box{position:relative;width:100%;display:flex;pointer-events:auto;background:var(--color-bg-tertiary);backdrop-filter:blur(16px) saturate(1.2);-webkit-backdrop-filter:blur(16px) saturate(1.2);transition:border-radius .3s cubic-bezier(.4,0,.2,1),padding .3s cubic-bezier(.4,0,.2,1),min-height .3s cubic-bezier(.4,0,.2,1),max-height .3s cubic-bezier(.4,0,.2,1),box-shadow .3s cubic-bezier(.4,0,.2,1),border-color .3s cubic-bezier(.4,0,.2,1),background .3s cubic-bezier(.4,0,.2,1);box-shadow:var(--shadow-xl)}.chat-page__input-area{position:relative;display:flex;align-items:flex-start;flex:1 1 auto;min-width:0;width:100%;min-height:40px}.chat-page__input{width:100%;background:transparent;border:none;color:var(--color-text-primary);font-size:14px;padding:0 28px 0 0;resize:none;min-height:36px;max-height:120px;outline:none;font-family:var(--font-family-sans);line-height:1.5}.chat-page__input::placeholder{color:var(--color-text-primary);opacity:.6}.chat-page__input:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.chat-page__input-placeholder{display:block;width:100%;min-width:0;font-size:14px;color:var(--color-text-primary);opacity:.6;line-height:24px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-page__input-actions{display:flex;align-items:flex-end;justify-content:space-between;gap:8px;min-width:0;min-height:24px;padding:0 0 7px}.chat-page__input-actions-left{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.chat-page__input-actions-right{display:flex;align-items:flex-end;gap:6px;margin-left:auto;flex-shrink:0}.chat-model-selector{position:relative;flex-shrink:0}.chat-model-selector__trigger{display:inline-flex;align-items:center;gap:4px;min-width:0;height:24px;padding:0 8px;border:none;border-radius:12px;background:var(--element-bg-subtle);color:var(--color-text-secondary);cursor:pointer;transition:all .2s ease}.chat-model-selector__trigger:active:not(:disabled),.chat-model-selector__trigger--open{background:var(--color-accent-100);color:var(--color-text-primary)}.chat-model-selector__trigger:disabled{opacity:var(--opacity-disabled);cursor:not-allowed}.chat-model-selector__icon,.chat-model-selector__thinking,.chat-model-selector__chevron{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.chat-model-selector__icon,.chat-model-selector__chevron{color:var(--color-text-muted)}.chat-model-selector__thinking{color:var(--color-purple-500)}.chat-model-selector__name{max-width:96px;display:inline-flex;align-items:center;gap:4px;min-width:0}.chat-model-selector__name-text{min-width:0;flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:9px;letter-spacing:.3px}.chat-model-selector__effort{display:inline-flex;align-items:center;justify-content:center;padding:1px 4px;border-radius:4px;background:var(--color-success-bg);color:var(--color-success);font-size:7px;font-weight:600;line-height:1;text-transform:uppercase}.chat-model-selector__dropdown{position:absolute;bottom:calc(100% + 8px);left:0;width:180px;max-width:180px;max-height:min(345px,100vh - 160px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--border-subtle);border-radius:10px;background:var(--color-bg-elevated);box-shadow:var(--shadow-xl);backdrop-filter:blur(18px) saturate(1.15);-webkit-backdrop-filter:blur(18px) saturate(1.15);z-index:30}.chat-model-selector__header{padding:10px 12px 8px;font-size:10px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--color-text-muted);border-bottom:1px solid var(--border-subtle)}.chat-model-selector__divider{height:1px;margin:4px 12px;background:var(--border-subtle)}.chat-model-selector__list{flex:1 1 auto;min-height:0;max-height:none;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}.chat-model-selector__option{width:100%;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 12px;border:none;background:transparent;color:inherit;text-align:left;cursor:pointer;transition:background .15s ease}.chat-model-selector__option:active,.chat-model-selector__option.is-selected{background:var(--element-bg-subtle)}.chat-model-selector__option-main{display:flex;flex-direction:column;gap:2px;min-width:0;width:100%;flex:1;overflow:hidden}.chat-model-selector__option-name{display:flex;align-items:center;gap:.5em;min-width:0;max-width:100%;width:100%;font-size:11px;font-weight:500;color:var(--color-text-primary)}.chat-model-selector__option-name-text{flex:0 1 auto;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-model-selector__option-thinking{color:var(--color-purple-500);font-size:9px;flex-shrink:0}.chat-model-selector__option-meta{display:block;min-width:0;max-width:100%;font-size:9px;color:var(--color-text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-model-selector__option-meta--stacked{display:flex;flex-direction:column;gap:1px;white-space:normal}.chat-model-selector__option-meta-line{display:block;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-reasoning-selector__trigger{max-width:112px}.chat-reasoning-selector__name{max-width:68px}.chat-reasoning-selector__dropdown{width:160px;max-width:min(160px,100vw - 32px)}.chat-page__action-btn{flex-shrink:0;width:24px;height:24px;border-radius:50%;border:none;background:transparent;color:var(--color-text-secondary);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.chat-page__action-btn:active:not(:disabled){background:var(--element-bg-soft);color:var(--color-text-primary)}.chat-page__action-btn:disabled{opacity:.4;cursor:not-allowed}.chat-page__send-btn{position:relative;width:24px;height:24px;border-radius:50%;border:1px solid var(--color-accent-300);background:var(--color-accent-200);color:var(--color-accent-300);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;flex-shrink:0}.chat-page__send-btn:not(:disabled){background:var(--color-accent-500);border:1px solid var(--color-accent-600);color:var(--btn-primary-color);box-shadow:var(--shadow-sm)}.chat-page__send-btn:active:not(:disabled){transform:scale(.92)}.chat-page__send-btn:disabled{background:var(--color-accent-100);border-color:var(--color-accent-200);color:var(--color-accent-400);opacity:.35;cursor:default;box-shadow:none}.chat-page__send-btn.is-stop{background:var(--color-error)!important;border-color:var(--color-error)!important;color:var(--btn-primary-color)!important;opacity:1!important;box-shadow:var(--shadow-sm)}.chat-page__send-btn.is-stop:active{transform:scale(.92)}.chat-page__stream-actions{display:inline-flex;align-items:center;gap:6px;flex-shrink:0}.chat-page__image-preview-row{display:flex;gap:8px;padding:0;min-width:0;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.chat-page__image-thumb{position:relative;width:46px;height:46px;border-radius:6px;overflow:hidden;flex-shrink:0;border:1px solid var(--border-subtle)}.chat-page__image-thumb img{width:100%;height:100%;object-fit:cover}.chat-page__image-remove{position:absolute;top:2px;right:2px;width:16px;height:16px;border-radius:50%;background:var(--color-overlay);color:var(--color-static-white);border:none;font-size:11px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}.chat-msg__typing{display:inline-flex;gap:4px;align-items:center;padding:4px 0}.chat-msg__typing span{display:inline-block;width:5px;height:5px;background:var(--color-text-muted);border-radius:50%;animation:typing-bounce 1.2s ease-in-out infinite}.chat-msg__typing span:nth-child(2){animation-delay:.15s}.chat-msg__typing span:nth-child(3){animation-delay:.3s}.chat-msg__assistant-content{color:var(--color-text-primary);line-height:var(--line-height-relaxed);font-family:var(--font-family-sans);font-size:var(--font-size-sm);word-wrap:break-word;overflow-wrap:break-word;max-width:100%;width:100%;margin:0;padding:0;text-align:left}.chat-msg__assistant-content>*:first-child{margin-top:0!important}.chat-msg__assistant-content>*:last-child{margin-bottom:0!important}.chat-msg__assistant-content>*+*{margin-top:.25rem}.chat-msg__assistant-content ul+*,.chat-msg__assistant-content ol+*{margin-top:.5rem}.chat-msg__assistant-content p+ul,.chat-msg__assistant-content p+ol{margin-top:.25rem}.chat-msg__assistant-content p+p{margin-top:.25rem}.chat-msg__assistant-content li+li{margin-top:.05rem}.chat-msg__assistant-content li>*{margin-top:0;margin-bottom:.05rem}.chat-msg__assistant-content li>*:last-child{margin-bottom:0}.chat-msg__assistant-content p{margin-top:0;margin-bottom:.5rem;display:block;line-height:1.5;font-size:var(--font-size-sm);color:var(--color-text-primary)}.chat-msg__assistant-content p:last-child{margin-bottom:0}.chat-msg__assistant-content p code{display:inline!important}.chat-msg__assistant-content h1,.chat-msg__assistant-content h2,.chat-msg__assistant-content h3,.chat-msg__assistant-content h4,.chat-msg__assistant-content h5,.chat-msg__assistant-content h6{font-family:var(--font-family-sans);color:var(--color-text-primary);margin-top:1.25rem;margin-bottom:.6rem;font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);letter-spacing:.015em}.chat-msg__assistant-content h1:first-child,.chat-msg__assistant-content h2:first-child,.chat-msg__assistant-content h3:first-child,.chat-msg__assistant-content h4:first-child,.chat-msg__assistant-content h5:first-child,.chat-msg__assistant-content h6:first-child{margin-top:0}.chat-msg__assistant-content h1{font-size:var(--font-size-xl);margin:1.25rem 0 .75rem;padding-bottom:.5rem;border-bottom:1px solid var(--border-subtle)}.chat-msg__assistant-content h2{font-size:var(--font-size-lg);margin:1rem 0 .6rem;padding-bottom:.35rem;border-bottom:1px solid var(--border-subtle)}.chat-msg__assistant-content h3{font-size:var(--font-size-base);margin:.85rem 0 .5rem}.chat-msg__assistant-content h4{font-size:var(--font-size-sm);margin:.7rem 0 .4rem;color:var(--color-text-secondary)}.chat-msg__assistant-content h5{font-size:var(--font-size-sm);margin:.6rem 0 .4rem;color:var(--color-text-secondary)}.chat-msg__assistant-content h6{font-size:var(--font-size-xs);margin:.5rem 0 .35rem;color:var(--color-text-muted);opacity:.85}.chat-msg__assistant-content ul,.chat-msg__assistant-content ol{margin-top:0;margin-bottom:.5rem;padding-left:1.5rem;line-height:1.5;font-size:var(--font-size-sm)}.chat-msg__assistant-content li{word-wrap:break-word;margin-bottom:.1rem;position:relative;line-height:1.5;color:var(--color-text-primary)}.chat-msg__assistant-content li:last-child{margin-bottom:0}.chat-msg__assistant-content li p{margin-top:0;margin-bottom:.1rem}.chat-msg__assistant-content li p:last-child{margin-bottom:0}.chat-msg__assistant-content ul>li::marker{color:var(--color-text-muted);font-size:1.2em;font-weight:700}.chat-msg__assistant-content ol>li::marker{color:var(--color-text-muted);font-weight:700}.chat-msg__assistant-content ul ul,.chat-msg__assistant-content ol ol,.chat-msg__assistant-content ul ol,.chat-msg__assistant-content ol ul{margin-top:.1rem;margin-bottom:0;padding-left:1.2rem}.chat-msg__assistant-content ul:has(>li>.file-card){list-style:none;padding-left:0}.chat-msg__assistant-content ul:has(>li>.file-card)>li{margin-bottom:var(--size-gap-2)}.chat-msg__assistant-content ul:has(>li>.file-card)>li:last-child{margin-bottom:0}.chat-msg__assistant-content .inline-code{padding:.15em .35em;margin:0 .05em;font-size:.85em;background:var(--element-bg-base);border:1px solid var(--border-subtle);border-radius:4px;font-family:var(--font-family-mono);white-space:nowrap;vertical-align:baseline;line-height:1.4;color:var(--color-text-primary);font-weight:500}.chat-msg__assistant-content pre code,.chat-msg__assistant-content pre>.inline-code{padding:0;margin:0;background:transparent;border:none;border-radius:0;font-size:inherit;font-weight:inherit;white-space:pre;display:block;color:inherit}.chat-msg__assistant-content .code-block-wrapper{margin:.5rem 0;border-radius:var(--size-radius-base);background:var(--color-bg-primary);border:1px dashed var(--border-subtle);box-shadow:var(--shadow-sm);overflow:hidden;position:relative}.chat-msg__assistant-content .code-block-wrapper pre[class*=language-]{margin:0!important;border:none!important;border-radius:var(--size-radius-base)!important;padding:1rem!important;background:var(--color-bg-primary)!important;box-shadow:none!important;font-size:.75rem!important}.chat-msg__assistant-content .code-block-wrapper pre code{font-family:var(--font-family-mono)!important;background:var(--color-bg-primary)!important;font-size:.75rem!important}.chat-msg__assistant-content .code-block-wrapper pre[style]{background:var(--color-bg-primary)!important;border:none!important;box-shadow:none!important}.chat-msg__assistant-content .code-block-wrapper code[style]{background:var(--color-bg-primary)!important;border:none!important}.chat-msg__assistant-content .copy-button{position:absolute;top:.5rem;right:.5rem;padding:.4rem;background:transparent;border:none;border-radius:6px;color:var(--color-text-muted);cursor:pointer;display:flex;align-items:center;justify-content:center;width:28px;height:28px;opacity:.6;z-index:10;transition:all .2s ease}.chat-msg__assistant-content .copy-button:active{opacity:1;background:var(--element-bg-soft)}.chat-msg__assistant-content .copy-button.copy-success{color:var(--color-success);opacity:1}.chat-msg__assistant-content pre{padding:1rem;overflow-x:auto;-webkit-overflow-scrolling:touch;font-size:.75rem;line-height:1.5;background:var(--color-bg-primary);border:1px dashed var(--border-subtle);border-radius:var(--size-radius-base);margin:.5rem 0;box-shadow:var(--shadow-sm);position:relative}.chat-msg__assistant-content pre code{background:none;padding:0;font-size:var(--font-size-xs)}.chat-msg__assistant-content pre:has(.code-block-wrapper){padding:0!important;background:transparent!important;border:none!important;border-radius:0!important;margin:.5rem 0!important;box-shadow:none!important;position:static!important}.chat-msg__assistant-content blockquote,.chat-msg__assistant-content .custom-blockquote{font-style:italic;margin:1rem 0;padding:.75rem 1rem;position:relative;background:var(--color-accent-50);border-left:3px solid var(--color-accent-400);border-radius:0 var(--size-radius-sm) var(--size-radius-sm) 0;color:var(--color-text-muted)}.chat-msg__assistant-content blockquote>:first-child,.chat-msg__assistant-content .custom-blockquote>:first-child{margin-top:0}.chat-msg__assistant-content blockquote>:last-child,.chat-msg__assistant-content .custom-blockquote>:last-child{margin-bottom:0}.chat-msg__assistant-content blockquote p,.chat-msg__assistant-content .custom-blockquote p{margin:.3rem 0}.chat-msg__assistant-content .table-wrapper{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:1rem 0;border-radius:var(--size-radius-base);border:1px solid var(--border-subtle);box-shadow:var(--shadow-sm);background:var(--color-bg-primary)}.chat-msg__assistant-content .table-wrapper table{border-spacing:0;border-collapse:collapse;width:100%;font-size:var(--font-size-xs)}.chat-msg__assistant-content .table-wrapper th,.chat-msg__assistant-content .table-wrapper td{padding:8px 12px;border-bottom:1px solid var(--border-subtle);text-align:left}.chat-msg__assistant-content .table-wrapper th{font-weight:var(--font-weight-semibold);background:var(--element-bg-subtle);color:var(--color-text-primary);white-space:nowrap}.chat-msg__assistant-content .table-wrapper td{color:var(--color-text-primary)}.chat-msg__assistant-content .table-wrapper th:first-child{border-radius:var(--size-radius-base) 0 0 0}.chat-msg__assistant-content .table-wrapper th:last-child{border-radius:0 var(--size-radius-base) 0 0}.chat-msg__assistant-content .table-wrapper tr:last-child td:first-child{border-radius:0 0 0 var(--size-radius-base)}.chat-msg__assistant-content .table-wrapper tr:last-child td:last-child{border-radius:0 0 var(--size-radius-base) 0}.chat-msg__assistant-content .table-wrapper tr:last-child td{border-bottom:none}.chat-msg__assistant-content .table-wrapper tbody tr:nth-child(2n){background:var(--element-bg-subtle)}.chat-msg__assistant-content a{color:var(--color-accent-500);text-decoration:none;word-break:break-all}.chat-msg__assistant-content a:active{text-decoration:underline}.chat-msg__assistant-content hr{height:1px;padding:0;margin:1.5rem 0;background:var(--border-subtle);border:0;border-radius:1px}.chat-msg__assistant-content strong{font-weight:var(--font-weight-semibold);color:var(--color-text-primary)}.chat-msg__assistant-content em{font-style:italic;color:var(--color-text-secondary)}.chat-msg__assistant-content del{text-decoration:line-through;color:var(--color-text-muted)}.chat-msg__assistant-content input[type=checkbox]{margin-right:6px;accent-color:var(--color-accent-500)} diff --git a/src/apps/relay-server/static/assets/index-_bexjgCT.css b/src/apps/relay-server/static/assets/index-_bexjgCT.css new file mode 100644 index 0000000000..8c5aea7068 --- /dev/null +++ b/src/apps/relay-server/static/assets/index-_bexjgCT.css @@ -0,0 +1 @@ +@charset "UTF-8";@layer bf.tokens.system,bf.tokens.theme,bf.reset,bf.base,bf.components,bf.overrides;@layer bf.tokens.system{:where([data-bf-design-system-root]){--bf-border-width-default: 1px;--bf-border-width-strong: 2px;--bf-control-action-card-actions-gap: 0px;--bf-control-action-card-actions-padding-inline-end: var(--bf-space-2);--bf-control-action-card-content-gap: var(--bf-space-1);--bf-control-action-card-gap: var(--bf-space-2);--bf-control-action-card-icon-size: 16px;--bf-control-action-card-leading-size: 30px;--bf-control-action-card-md-min-block-size: 62px;--bf-control-action-card-padding-block: var(--bf-space-2);--bf-control-action-card-padding-inline: var(--bf-space-3);--bf-control-action-card-radius: var(--bf-radius-base);--bf-control-action-card-sm-min-block-size: 54px;--bf-control-activity-item-content-gap: var(--bf-space-1);--bf-control-activity-item-divider-block-size: 16px;--bf-control-activity-item-inline-gap: var(--bf-space-1);--bf-control-activity-item-inline-icon-size: 12px;--bf-control-activity-item-surface-gap: var(--bf-space-2);--bf-control-activity-item-surface-height: 30px;--bf-control-activity-item-surface-icon-size: 14px;--bf-control-activity-item-surface-padding-block: var(--bf-space-1);--bf-control-activity-item-surface-padding-inline-end: 3px;--bf-control-activity-item-surface-padding-inline-start: var(--bf-space-2);--bf-control-activity-item-surface-radius: var(--bf-radius-base);--bf-control-ask-user-body-gap: var(--bf-space-3);--bf-control-ask-user-body-padding: var(--bf-space-4);--bf-control-ask-user-description-max-width: 500px;--bf-control-ask-user-header-height: 30px;--bf-control-ask-user-icon-size: 14px;--bf-control-ask-user-option-content-gap: var(--bf-space-2);--bf-control-ask-user-option-gap: var(--bf-space-1);--bf-control-ask-user-option-padding-block: 7px;--bf-control-ask-user-option-padding-inline: var(--bf-space-2);--bf-control-ask-user-question-options-gap: var(--bf-space-3);--bf-control-ask-user-question-padding-inline: var(--bf-space-1);--bf-control-ask-user-summary-action-size: 22px;--bf-control-ask-user-summary-padding-block: var(--bf-space-1);--bf-control-ask-user-summary-padding-inline-end: var(--bf-space-1);--bf-control-ask-user-summary-padding-inline-start: var(--bf-space-2);--bf-control-button-xs-height: 24px;--bf-control-button-xs-leading-icon-size: 12px;--bf-control-button-xs-padding-inline: 6px;--bf-control-button-xs-trailing-icon-size: 10px;--bf-control-change-count-gap: var(--bf-space-1);--bf-control-change-count-padding-block: 2px;--bf-control-change-count-padding-inline: var(--bf-space-1);--bf-control-change-count-radius: var(--bf-radius-xs);--bf-control-chat-composer-compact-gap: 9px;--bf-control-chat-composer-compact-height: 45px;--bf-control-chat-composer-compact-padding-block: 9px;--bf-control-chat-composer-compact-padding-inline: 9px;--bf-control-chat-composer-compact-track-height: 25px;--bf-control-chat-composer-control-height: 25px;--bf-control-composer-context-gap: var(--bf-space-2);--bf-control-composer-context-offset: 32px;--bf-control-composer-context-padding-block: 6px;--bf-control-composer-context-padding-inline: var(--bf-space-2);--bf-control-composer-divider-block-size: 16px;--bf-control-composer-editor-padding: var(--bf-space-1);--bf-control-composer-min-block-size: 120px;--bf-control-composer-surface-gap: var(--bf-space-3);--bf-control-composer-surface-padding: var(--bf-space-2);--bf-control-composer-surface-radius: var(--bf-radius-xl);--bf-control-composer-toolbar-gap: var(--bf-space-2);--bf-control-flow-chat-card-expanded-padding-block: .5rem;--bf-control-flow-chat-card-expanded-padding-inline: .625rem;--bf-control-flow-chat-card-gap: .42rem;--bf-control-flow-chat-card-padding-block: .625rem;--bf-control-flow-chat-card-padding-inline: .75rem;--bf-control-flow-chat-card-radius: var(--bf-radius-base);--bf-control-flow-chat-code-block-padding-block: .55rem;--bf-control-flow-chat-code-block-padding-inline: .75rem;--bf-control-flow-chat-content-padding-inline: 3rem;--bf-control-flow-chat-content-padding-inline-mobile: 1.5rem;--bf-control-flow-chat-control-gap: .5rem;--bf-control-flow-chat-control-padding-block: .35rem;--bf-control-flow-chat-control-padding-inline: .75rem;--bf-control-flow-chat-flow-item-gap: .42rem;--bf-control-flow-chat-inline-gap: .35rem;--bf-control-flow-chat-turn-gap: .46rem;--bf-control-height-lg: 48px;--bf-control-height-md: 40px;--bf-control-height-sm: 32px;--bf-control-hit-target: 40px;--bf-control-icon-size2xs: 8px;--bf-control-icon-size-lg: 24px;--bf-control-icon-size-md: 16px;--bf-control-icon-size-sm: 14px;--bf-control-icon-size-xs: 12px;--bf-control-icon-button-xs-icon-size: 14px;--bf-control-icon-button-xs-size: 22px;--bf-control-segmented-control-gap: 2px;--bf-control-segmented-control-icon-size: 12px;--bf-control-segmented-control-padding: 2px;--bf-control-segmented-control-radius: var(--bf-radius-pill);--bf-control-segmented-control-segment-gap: var(--bf-space-1);--bf-control-segmented-control-segment-height: 22px;--bf-control-segmented-control-segment-padding-inline: var(--bf-space-2);--bf-control-segmented-control-segment-radius: var(--bf-radius-pill);--bf-control-select-content-gap: var(--bf-space-2);--bf-control-select-indicator-size: 14px;--bf-control-select-leading-inset: var(--bf-space-3);--bf-control-select-padding-inline: var(--bf-space-3);--bf-control-select-radius: var(--bf-radius-base);--bf-control-select-trailing-inset: var(--bf-space-3);--bf-control-status-pill-gap: 2px;--bf-control-status-pill-icon-size: 14px;--bf-control-status-pill-padding-block: 3px;--bf-control-status-pill-padding-inline: 6px;--bf-control-status-pill-radius: var(--bf-radius-pill);--bf-control-switch-thumb-inset: 2px;--bf-control-switch-thumb-size: 12px;--bf-control-switch-thumb-travel: 12px;--bf-control-switch-thumb-travel-reverse: -12px;--bf-control-switch-track-height: 16px;--bf-control-switch-track-width: 28px;--bf-control-tab-group-gap: var(--bf-space-2);--bf-control-tab-group-item-action-inset: var(--bf-space-2);--bf-control-tab-group-item-action-size: var(--bf-space-5);--bf-control-tab-group-item-gap: 6px;--bf-control-tab-group-item-height: var(--bf-control-height-md);--bf-control-tab-group-item-icon-size: 16px;--bf-control-tab-group-item-padding-inline: var(--bf-space-4);--bf-control-tab-group-item-radius: var(--bf-radius-pill);--bf-control-tool-card-expanded-padding-inline: .625rem;--bf-control-tool-card-header-icon-slot: 34px;--bf-control-tool-card-header-padding-block: .44rem;--bf-control-tool-card-header-padding-inline-end: .625rem;--bf-focus-offset: 2px;--bf-focus-width: 2px;--bf-font-family-control: "SF Pro Text", -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", "Microsoft YaHei UI", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;--bf-font-family-mono: "JetBrains Mono", "FiraCode", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, "Cascadia Mono", "Cascadia Code", Consolas, "Liberation Mono", "Courier New", monospace;--bf-font-family-sans: "Noto Sans SC", -apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei UI", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif;--bf-font-size-2xl: 18px;--bf-font-size-2xs: 9px;--bf-font-size-3xl: 22px;--bf-font-size-3xs: 8px;--bf-font-size-4xl: 26px;--bf-font-size-4xs: 7px;--bf-font-size-5xl: 32px;--bf-font-size-6xl: 40px;--bf-font-size-7xl: 48px;--bf-font-size-8xl: 56px;--bf-font-size-9xl: 64px;--bf-font-size-base: 14px;--bf-font-size-lg: 15px;--bf-font-size-meta: 11px;--bf-font-size-micro: 10px;--bf-font-size-sm: 13px;--bf-font-size-xl: 16px;--bf-font-size-xs: 12px;--bf-font-weight-bold: 700;--bf-font-weight-medium: 500;--bf-font-weight-regular: 400;--bf-font-weight-semibold: 600;--bf-layer-base: 0;--bf-layer-content: 2;--bf-layer-context-menu: 500;--bf-layer-decoration: 1;--bf-layer-dropdown: 60;--bf-layer-floating: 50;--bf-layer-fullscreen: 280;--bf-layer-modal: 200;--bf-layer-modal-active: 250;--bf-layer-notification: 400;--bf-layer-overlay: 100;--bf-layer-overlay-host: 300;--bf-layer-popover: 360;--bf-layer-sticky: 15;--bf-layer-toast: 400;--bf-layer-tooltip: 350;--bf-layout-card-footer-gap: var(--bf-space-2);--bf-layout-card-gap-lg: 30px;--bf-layout-card-gap-md: var(--bf-space-3);--bf-layout-card-gap-sm: var(--bf-space-2);--bf-layout-card-header-gap: var(--bf-space-2);--bf-layout-card-media-min-block-size: 120px;--bf-layout-card-padding-md: var(--bf-space-5);--bf-layout-card-padding-sm: var(--bf-space-3);--bf-layout-card-radius-lg: 28px;--bf-layout-card-radius-md: var(--bf-radius-lg);--bf-layout-card-radius-sm: var(--bf-radius-base);--bf-layout-card-title-description-gap: var(--bf-space-1);--bf-layout-confirm-dialog-content-gap: var(--bf-space-4);--bf-layout-confirm-dialog-icon-glyph-size: 18px;--bf-layout-confirm-dialog-icon-size: 32px;--bf-layout-confirm-dialog-message-gap: var(--bf-space-3);--bf-layout-confirm-dialog-preview-padding-block: var(--bf-space-3);--bf-layout-confirm-dialog-preview-padding-inline: var(--bf-space-4);--bf-layout-confirm-dialog-preview-radius: var(--bf-radius-base);--bf-layout-disclosure-actions-gap: var(--bf-space-1);--bf-layout-disclosure-content-padding-block: var(--bf-space-3);--bf-layout-disclosure-content-padding-inline: var(--bf-space-8);--bf-layout-disclosure-indicator-size: 14px;--bf-layout-disclosure-trigger-gap: var(--bf-space-2);--bf-layout-disclosure-trigger-min-block-size: 30px;--bf-layout-disclosure-trigger-padding-block: var(--bf-space-1);--bf-layout-disclosure-trigger-padding-inline: var(--bf-space-2);--bf-layout-disclosure-trigger-radius: var(--bf-radius-base);--bf-layout-field-content-gap: var(--bf-space-1);--bf-layout-field-control-gap: var(--bf-space-2);--bf-layout-field-horizontal-gap: var(--bf-space-5);--bf-layout-field-horizontal-gap-wide: var(--bf-space-10);--bf-layout-field-label-action-gap: var(--bf-space-2);--bf-layout-field-label-gap: 2px;--bf-layout-field-label-width-lg: 400px;--bf-layout-field-label-width-md: 200px;--bf-layout-field-label-width-sm: 150px;--bf-layout-field-root-gap: var(--bf-space-2);--bf-layout-field-group-radius: var(--bf-radius-lg);--bf-layout-field-group-row-padding-block: var(--bf-space-4);--bf-layout-field-group-row-padding-inline: var(--bf-space-5);--bf-layout-form-section-gap: var(--bf-space-4);--bf-layout-form-section-header-gap: var(--bf-space-5);--bf-layout-form-section-title-description-gap: var(--bf-space-1);--bf-layout-navigation-panel-content-gap: var(--bf-space-4);--bf-layout-navigation-panel-footer-height: 40px;--bf-layout-navigation-panel-footer-padding: var(--bf-space-2);--bf-layout-navigation-panel-heading-action-size: 22px;--bf-layout-navigation-panel-heading-gap: var(--bf-space-5);--bf-layout-navigation-panel-heading-height: 22px;--bf-layout-navigation-panel-heading-padding-inline: var(--bf-space-2);--bf-layout-navigation-panel-inline-size: 216px;--bf-layout-navigation-panel-item-gap: var(--bf-space-2);--bf-layout-navigation-panel-item-height: 30px;--bf-layout-navigation-panel-item-icon-size: 14px;--bf-layout-navigation-panel-item-padding-inline: var(--bf-space-2);--bf-layout-navigation-panel-item-radius: var(--bf-radius-base);--bf-layout-navigation-panel-scrollbar-gap: 2px;--bf-layout-navigation-panel-section-gap: var(--bf-space-1);--bf-layout-navigation-panel-surface-padding: var(--bf-space-2);--bf-layout-split-view-content-panel-radius: var(--bf-radius-3xl);--bf-layout-toolbar-badge-size: 24px;--bf-layout-toolbar-content-gap: 40px;--bf-layout-toolbar-group-gap-md: var(--bf-space-2);--bf-layout-toolbar-group-gap-sm: var(--bf-space-1);--bf-layout-toolbar-md-height: 45px;--bf-layout-toolbar-md-padding-block-end: 6px;--bf-layout-toolbar-md-padding-block-start: var(--bf-space-2);--bf-layout-toolbar-md-padding-inline-end: 11px;--bf-layout-toolbar-md-padding-inline-start: var(--bf-space-2);--bf-layout-toolbar-overflow-fade-extent: 16px;--bf-layout-toolbar-separator-block-size: 16px;--bf-layout-toolbar-sm-height: 33px;--bf-layout-toolbar-sm-padding-block: var(--bf-space-1);--bf-layout-toolbar-sm-padding-inline: var(--bf-space-2);--bf-letter-spacing-caps: .1em;--bf-letter-spacing-expanded: .26em;--bf-letter-spacing-normal: 0em;--bf-letter-spacing-snug: -.01em;--bf-letter-spacing-subtle: .01em;--bf-letter-spacing-tight: -.02em;--bf-letter-spacing-tighter: -.04em;--bf-letter-spacing-wide: .02em;--bf-letter-spacing-wider: .04em;--bf-letter-spacing-widest: .08em;--bf-line-height-base: 1.5;--bf-line-height-code: 1.52;--bf-line-height-comfortable: 1.55;--bf-line-height-compact: 1.32;--bf-line-height-dense: 1.25;--bf-line-height-display: 1.1;--bf-line-height-loose: 1.8;--bf-line-height-none: 1;--bf-line-height-reading: 1.58;--bf-line-height-relaxed: 1.6;--bf-line-height-snug: 1.3;--bf-line-height-spacious: 1.7;--bf-line-height-support: 1.45;--bf-line-height-tight: 1.2;--bf-line-height-ui: 1.4;--bf-motion-duration-base: .22s;--bf-motion-duration-fast: .14s;--bf-motion-duration-instant: 80ms;--bf-motion-duration-lazy: 1s;--bf-motion-duration-loop: .72s;--bf-motion-duration-normal: var(--bf-motion-duration-base);--bf-motion-duration-slow: .42s;--bf-motion-easing-accelerate: cubic-bezier(.4, 0, 1, 1);--bf-motion-easing-decelerate: var(--bf-motion-easing-standard);--bf-motion-easing-enter: var(--bf-motion-easing-standard);--bf-motion-easing-exit: cubic-bezier(.3, 0, 1, 1);--bf-motion-easing-smooth: cubic-bezier(.77, 0, .175, 1);--bf-motion-easing-standard: cubic-bezier(.23, 1, .32, 1);--bf-overlay-menu-heading-action-size: 22px;--bf-overlay-menu-heading-gap: var(--bf-space-5);--bf-overlay-menu-heading-height: 24px;--bf-overlay-menu-heading-padding-inline: var(--bf-space-2);--bf-overlay-menu-inline-size: 220px;--bf-overlay-menu-item-gap: var(--bf-space-2);--bf-overlay-menu-item-height: 30px;--bf-overlay-menu-item-icon-size: 14px;--bf-overlay-menu-item-padding-inline: var(--bf-space-2);--bf-overlay-menu-item-radius: var(--bf-radius-base);--bf-overlay-menu-max-block-size: 480px;--bf-overlay-menu-scrollbar-gap: 2px;--bf-overlay-menu-section-gap: var(--bf-space-2);--bf-overlay-menu-surface-padding: var(--bf-space-2);--bf-overlay-menu-surface-radius: var(--bf-radius-xl);--bf-overlay-modal-backdrop-blur: blur(20px);--bf-overlay-modal-content-padding-lg: var(--bf-space-6);--bf-overlay-modal-content-padding-md: var(--bf-space-4);--bf-overlay-modal-content-padding-sm: var(--bf-space-3);--bf-overlay-modal-content-padding-xl: var(--bf-space-8);--bf-overlay-modal-description-gap: var(--bf-space-2);--bf-overlay-modal-edge-gutter: 8px;--bf-overlay-modal-footer-action-min-width: 100px;--bf-overlay-modal-footer-blur: blur(10px);--bf-overlay-modal-footer-content-inset: 104px;--bf-overlay-modal-footer-fade-extent: var(--bf-space-6);--bf-overlay-modal-footer-gap: var(--bf-space-2);--bf-overlay-modal-footer-height: 68px;--bf-overlay-modal-footer-padding-block-end: var(--bf-space-5);--bf-overlay-modal-footer-padding-block-start: var(--bf-space-2);--bf-overlay-modal-footer-padding-inline: var(--bf-space-6);--bf-overlay-modal-header-actions-gap: var(--bf-space-2);--bf-overlay-modal-header-gap: var(--bf-space-5);--bf-overlay-modal-header-padding-block-end: var(--bf-space-5);--bf-overlay-modal-header-padding-block-start: var(--bf-space-6);--bf-overlay-modal-header-padding-inline: var(--bf-space-6);--bf-overlay-modal-max-inline-size-large: 600px;--bf-overlay-modal-max-inline-size-medium: 560px;--bf-overlay-modal-max-inline-size-small: 420px;--bf-overlay-modal-max-inline-size-wide: 1200px;--bf-overlay-modal-max-inline-size-xlarge: 720px;--bf-overlay-modal-max-inline-size-xxlarge: 960px;--bf-overlay-modal-scrollbar-width: var(--bf-scrollbar-width);--bf-overlay-modal-surface-radius: 28px;--bf-overlay-modal-viewport-gutter: 24px;--bf-overlay-tooltip-arrow-size: 8px;--bf-overlay-tooltip-gap: var(--bf-space-2);--bf-overlay-tooltip-max-block-size: 320px;--bf-overlay-tooltip-max-inline-size: 280px;--bf-overlay-tooltip-padding-block: 6px;--bf-overlay-tooltip-padding-inline: 10px;--bf-overlay-tooltip-surface-radius: var(--bf-radius-sm);--bf-radius-2xl: 20px;--bf-radius-3xl: 24px;--bf-radius-4xl: 32px;--bf-radius-base: 8px;--bf-radius-lg: 12px;--bf-radius-md: var(--bf-radius-base);--bf-radius-pill: 9999px;--bf-radius-sm: 6px;--bf-radius-xl: 16px;--bf-radius-xs: 4px;--bf-scrollbar-radius: var(--bf-radius-pill);--bf-scrollbar-width: 6px;--bf-space-0: 0px;--bf-space-1: 4px;--bf-space-10: 40px;--bf-space-12: 48px;--bf-space-16: 64px;--bf-space-2: 8px;--bf-space-3: 12px;--bf-space-4: 16px;--bf-space-5: 20px;--bf-space-6: 24px;--bf-space-8: 32px;--bf-space-component-block: 8px;--bf-space-component-inline: 12px;--bf-type-body-lg-font-family: var(--bf-font-family-sans);--bf-type-body-lg-font-size: var(--bf-font-size-xl);--bf-type-body-lg-font-weight: var(--bf-font-weight-regular);--bf-type-body-lg-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-body-lg-line-height: var(--bf-line-height-relaxed);--bf-type-body-md-font-family: var(--bf-font-family-sans);--bf-type-body-md-font-size: var(--bf-font-size-base);--bf-type-body-md-font-weight: var(--bf-font-weight-regular);--bf-type-body-md-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-body-md-line-height: var(--bf-line-height-base);--bf-type-body-sm-font-family: var(--bf-font-family-sans);--bf-type-body-sm-font-size: var(--bf-font-size-sm);--bf-type-body-sm-font-weight: var(--bf-font-weight-regular);--bf-type-body-sm-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-body-sm-line-height: var(--bf-line-height-base);--bf-type-body-xs-font-family: var(--bf-font-family-sans);--bf-type-body-xs-font-size: var(--bf-font-size-xs);--bf-type-body-xs-font-weight: var(--bf-font-weight-regular);--bf-type-body-xs-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-body-xs-line-height: var(--bf-line-height-base);--bf-type-code-md-font-family: var(--bf-font-family-mono);--bf-type-code-md-font-size: var(--bf-font-size-sm);--bf-type-code-md-font-weight: var(--bf-font-weight-regular);--bf-type-code-md-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-code-md-line-height: var(--bf-line-height-code);--bf-type-code-sm-font-family: var(--bf-font-family-mono);--bf-type-code-sm-font-size: var(--bf-font-size-xs);--bf-type-code-sm-font-weight: var(--bf-font-weight-regular);--bf-type-code-sm-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-code-sm-line-height: var(--bf-line-height-code);--bf-type-display-fluid-hero-font-family: var(--bf-font-family-sans);--bf-type-display-fluid-hero-font-size: clamp(var(--bf-font-size-6xl), 4vw, var(--bf-font-size-8xl));--bf-type-display-fluid-hero-font-weight: var(--bf-font-weight-semibold);--bf-type-display-fluid-hero-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-display-fluid-hero-line-height: var(--bf-line-height-display);--bf-type-display-fluid-title-font-family: var(--bf-font-family-sans);--bf-type-display-fluid-title-font-size: clamp(var(--bf-font-size-5xl), 3.2vw, var(--bf-font-size-7xl));--bf-type-display-fluid-title-font-weight: var(--bf-font-weight-semibold);--bf-type-display-fluid-title-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-display-fluid-title-line-height: var(--bf-line-height-display);--bf-type-display-lg-font-family: var(--bf-font-family-sans);--bf-type-display-lg-font-size: var(--bf-font-size-7xl);--bf-type-display-lg-font-weight: var(--bf-font-weight-semibold);--bf-type-display-lg-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-display-lg-line-height: var(--bf-line-height-display);--bf-type-display-md-font-family: var(--bf-font-family-sans);--bf-type-display-md-font-size: var(--bf-font-size-6xl);--bf-type-display-md-font-weight: var(--bf-font-weight-semibold);--bf-type-display-md-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-display-md-line-height: var(--bf-line-height-display);--bf-type-display-sm-font-family: var(--bf-font-family-sans);--bf-type-display-sm-font-size: var(--bf-font-size-5xl);--bf-type-display-sm-font-weight: var(--bf-font-weight-semibold);--bf-type-display-sm-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-display-sm-line-height: var(--bf-line-height-display);--bf-type-display-xl-font-family: var(--bf-font-family-sans);--bf-type-display-xl-font-size: var(--bf-font-size-8xl);--bf-type-display-xl-font-weight: var(--bf-font-weight-semibold);--bf-type-display-xl-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-display-xl-line-height: var(--bf-line-height-display);--bf-type-flow-body-font-family: var(--bf-font-family-sans);--bf-type-flow-body-font-size: var(--bf-font-size-base);--bf-type-flow-body-font-weight: var(--bf-font-weight-regular);--bf-type-flow-body-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-flow-body-line-height: var(--bf-line-height-reading);--bf-type-flow-code-font-family: var(--bf-font-family-mono);--bf-type-flow-code-font-size: var(--bf-font-size-sm);--bf-type-flow-code-font-weight: var(--bf-font-weight-regular);--bf-type-flow-code-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-flow-code-line-height: var(--bf-line-height-code);--bf-type-flow-control-font-family: var(--bf-font-family-control);--bf-type-flow-control-font-size: var(--bf-font-size-sm);--bf-type-flow-control-font-weight: var(--bf-font-weight-regular);--bf-type-flow-control-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-flow-control-line-height: var(--bf-line-height-support);--bf-type-flow-lead-font-family: var(--bf-font-family-sans);--bf-type-flow-lead-font-size: var(--bf-font-size-lg);--bf-type-flow-lead-font-weight: var(--bf-font-weight-regular);--bf-type-flow-lead-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-flow-lead-line-height: var(--bf-line-height-relaxed);--bf-type-flow-meta-font-family: var(--bf-font-family-control);--bf-type-flow-meta-font-size: var(--bf-font-size-meta);--bf-type-flow-meta-font-weight: var(--bf-font-weight-regular);--bf-type-flow-meta-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-flow-meta-line-height: var(--bf-line-height-compact);--bf-type-flow-micro-font-family: var(--bf-font-family-control);--bf-type-flow-micro-font-size: var(--bf-font-size-micro);--bf-type-flow-micro-font-weight: var(--bf-font-weight-regular);--bf-type-flow-micro-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-flow-micro-line-height: var(--bf-line-height-compact);--bf-type-flow-page-title-font-family: var(--bf-font-family-sans);--bf-type-flow-page-title-font-size: var(--bf-font-size-3xl);--bf-type-flow-page-title-font-weight: var(--bf-font-weight-semibold);--bf-type-flow-page-title-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-flow-page-title-line-height: var(--bf-line-height-tight);--bf-type-flow-section-title-font-family: var(--bf-font-family-sans);--bf-type-flow-section-title-font-size: var(--bf-font-size-2xl);--bf-type-flow-section-title-font-weight: var(--bf-font-weight-semibold);--bf-type-flow-section-title-letter-spacing: var(--bf-letter-spacing-snug);--bf-type-flow-section-title-line-height: var(--bf-line-height-tight);--bf-type-flow-support-font-family: var(--bf-font-family-control);--bf-type-flow-support-font-size: var(--bf-font-size-xs);--bf-type-flow-support-font-weight: var(--bf-font-weight-regular);--bf-type-flow-support-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-flow-support-line-height: var(--bf-line-height-support);--bf-type-flow-title-font-family: var(--bf-font-family-sans);--bf-type-flow-title-font-size: var(--bf-font-size-xl);--bf-type-flow-title-font-weight: var(--bf-font-weight-semibold);--bf-type-flow-title-letter-spacing: var(--bf-letter-spacing-snug);--bf-type-flow-title-line-height: var(--bf-line-height-tight);--bf-type-heading-card-font-family: var(--bf-font-family-sans);--bf-type-heading-card-font-size: var(--bf-font-size-xl);--bf-type-heading-card-font-weight: var(--bf-font-weight-semibold);--bf-type-heading-card-letter-spacing: var(--bf-letter-spacing-snug);--bf-type-heading-card-line-height: var(--bf-line-height-tight);--bf-type-heading-dialog-font-family: var(--bf-font-family-sans);--bf-type-heading-dialog-font-size: var(--bf-font-size-3xl);--bf-type-heading-dialog-font-weight: var(--bf-font-weight-semibold);--bf-type-heading-dialog-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-heading-dialog-line-height: var(--bf-line-height-tight);--bf-type-heading-display-font-family: var(--bf-font-family-sans);--bf-type-heading-display-font-size: var(--bf-font-size-4xl);--bf-type-heading-display-font-weight: var(--bf-font-weight-semibold);--bf-type-heading-display-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-heading-display-line-height: var(--bf-line-height-display);--bf-type-heading-page-font-family: var(--bf-font-family-sans);--bf-type-heading-page-font-size: var(--bf-font-size-2xl);--bf-type-heading-page-font-weight: var(--bf-font-weight-semibold);--bf-type-heading-page-letter-spacing: var(--bf-letter-spacing-tight);--bf-type-heading-page-line-height: var(--bf-line-height-tight);--bf-type-heading-section-font-family: var(--bf-font-family-sans);--bf-type-heading-section-font-size: var(--bf-font-size-lg);--bf-type-heading-section-font-weight: var(--bf-font-weight-semibold);--bf-type-heading-section-letter-spacing: var(--bf-letter-spacing-snug);--bf-type-heading-section-line-height: var(--bf-line-height-tight);--bf-type-label-lg-font-family: var(--bf-font-family-control);--bf-type-label-lg-font-size: var(--bf-font-size-base);--bf-type-label-lg-font-weight: var(--bf-font-weight-medium);--bf-type-label-lg-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-label-lg-line-height: var(--bf-line-height-tight);--bf-type-label-md-font-family: var(--bf-font-family-control);--bf-type-label-md-font-size: var(--bf-font-size-sm);--bf-type-label-md-font-weight: var(--bf-font-weight-medium);--bf-type-label-md-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-label-md-line-height: var(--bf-line-height-tight);--bf-type-label-selected-font-family: var(--bf-font-family-control);--bf-type-label-selected-font-size: var(--bf-font-size-sm);--bf-type-label-selected-font-weight: var(--bf-font-weight-semibold);--bf-type-label-selected-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-label-selected-line-height: var(--bf-line-height-tight);--bf-type-label-sm-font-family: var(--bf-font-family-control);--bf-type-label-sm-font-size: var(--bf-font-size-xs);--bf-type-label-sm-font-weight: var(--bf-font-weight-medium);--bf-type-label-sm-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-label-sm-line-height: var(--bf-line-height-tight);--bf-type-label-xs-font-family: var(--bf-font-family-control);--bf-type-label-xs-font-size: var(--bf-font-size-meta);--bf-type-label-xs-font-weight: var(--bf-font-weight-medium);--bf-type-label-xs-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-label-xs-line-height: var(--bf-line-height-tight);--bf-type-meta-font-family: var(--bf-font-family-control);--bf-type-meta-font-size: var(--bf-font-size-meta);--bf-type-meta-font-weight: var(--bf-font-weight-regular);--bf-type-meta-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-meta-line-height: var(--bf-line-height-compact);--bf-type-micro-font-family: var(--bf-font-family-control);--bf-type-micro-font-size: var(--bf-font-size-micro);--bf-type-micro-font-weight: var(--bf-font-weight-regular);--bf-type-micro-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-micro-line-height: var(--bf-line-height-compact);--bf-type-support-font-family: var(--bf-font-family-control);--bf-type-support-font-size: var(--bf-font-size-xs);--bf-type-support-font-weight: var(--bf-font-weight-regular);--bf-type-support-letter-spacing: var(--bf-letter-spacing-normal);--bf-type-support-line-height: var(--bf-line-height-support)}}@layer bf.tokens.system{:where([data-bf-design-system-root][data-density=compact]){--bf-control-height-lg: 44px;--bf-control-height-md: 36px;--bf-control-height-sm: 28px;--bf-control-hit-target: 36px;--bf-control-tab-group-item-height: var(--bf-control-height-md);--bf-space-component-block: 6px;--bf-space-component-inline: 10px}}@layer bf.tokens.system{:where([data-bf-design-system-root][data-density=touch]){--bf-control-height-lg: 56px;--bf-control-height-md: 48px;--bf-control-height-sm: 40px;--bf-control-hit-target: 48px;--bf-control-tab-group-item-height: var(--bf-control-height-md);--bf-space-component-block: 12px;--bf-space-component-inline: 16px}}@media(prefers-reduced-motion:reduce){:where([data-bf-design-system-root]){--bf-motion-duration-fast: 0ms;--bf-motion-duration-normal: 0ms;--bf-motion-duration-slow: 0ms;--bf-motion-duration-loop: 0ms}}@layer bf.tokens.theme{:where([data-bf-design-system-root]),:where([data-bf-design-system-root][data-color-scheme=light]){--bf-color-accent-border: color-mix(in srgb, #059cb0 40%, transparent);--bf-color-accent-border-subtle: color-mix(in srgb, #059cb0 25%, transparent);--bf-color-accent-default: #059cb0;--bf-color-accent-disabled: rgba(5, 156, 176, .3);--bf-color-accent-hover: #059cb0;--bf-color-accent-secondary: #7c6b99;--bf-color-accent-secondary-border: color-mix(in srgb, #7c6b99 25%, transparent);--bf-color-accent-secondary-hover: #655680;--bf-color-accent-secondary-surface: color-mix(in srgb, #7c6b99 9%, transparent);--bf-color-accent-secondary-surface-strong: color-mix(in srgb, #7c6b99 15%, transparent);--bf-color-accent-surface: color-mix(in srgb, #059cb0 9%, transparent);--bf-color-accent-surface-strong: color-mix(in srgb, #059cb0 15%, transparent);--bf-color-accent-surface-subtle: color-mix(in srgb, #059cb0 5%, transparent);--bf-color-action-neutral-border: rgba(0, 0, 0, .05);--bf-color-action-neutral-content: rgba(0, 0, 0, .8);--bf-color-action-neutral-content-disabled: rgba(0, 0, 0, .3);--bf-color-action-neutral-fill-border: rgba(0, 0, 0, .05);--bf-color-action-neutral-surface: rgba(0, 0, 0, .05);--bf-color-action-neutral-surface-hover: rgba(0, 0, 0, .1);--bf-color-action-neutral-surface-pressed: rgba(0, 0, 0, .1);--bf-color-action-primary-background: #101a27;--bf-color-action-primary-content: #ffffff;--bf-color-action-primary-hover: #1c1c1f;--bf-color-action-primary-pressed: #000000;--bf-color-action-quiet-content: #555555;--bf-color-action-quiet-hover: #f3f3f5;--bf-color-action-quiet-pressed: rgba(16, 26, 39, .09);--bf-color-action-secondary-background: #f3f3f5;--bf-color-action-secondary-content: #1c1c1f;--bf-color-action-secondary-hover: rgba(16, 26, 39, .09);--bf-color-action-secondary-pressed: rgba(16, 26, 39, .13);--bf-color-border-default: rgba(16, 26, 39, .15);--bf-color-border-strong: rgba(16, 26, 39, .34);--bf-color-border-subtle: rgba(16, 26, 39, .08);--bf-color-content-disabled: #9a9a9a;--bf-color-content-inverse: #ffffff;--bf-color-content-muted: #6a6a6a;--bf-color-content-on-dark: #ffffff;--bf-color-content-on-light: #000000;--bf-color-content-primary: #1c1c1f;--bf-color-content-secondary: #555555;--bf-color-control-switch-thumb: #ffffff;--bf-color-control-switch-track: #dddddd;--bf-color-control-switch-track-checked: #34c78c;--bf-color-field-background: #ffffff;--bf-color-field-background-hover: #ffffff;--bf-color-field-border: rgba(16, 26, 39, .15);--bf-color-field-border-focus: #101a27;--bf-color-field-border-hover: rgba(16, 26, 39, .24);--bf-color-focus-ring: #6a6a6a;--bf-color-identity-assistant-border: color-mix(in srgb, #db2777 15%, transparent);--bf-color-identity-assistant-content: #db2777;--bf-color-identity-assistant-content-hover: #be185d;--bf-color-identity-assistant-surface: color-mix(in srgb, #db2777 9%, transparent);--bf-color-identity-assistant-surface-subtle: color-mix(in srgb, #db2777 5%, transparent);--bf-color-key-hint-background: rgba(0, 0, 0, .05);--bf-color-link-default: #2563eb;--bf-color-link-hover: #005fcc;--bf-color-overlay-scrim: rgba(16, 26, 39, .2);--bf-color-scrollbar-thumb: rgba(0, 0, 0, .1);--bf-color-scrollbar-thumb-hover: rgba(0, 0, 0, .1);--bf-color-status-danger-border: rgba(167, 67, 82, .36);--bf-color-status-danger-content: #a74352;--bf-color-status-danger-surface: rgba(167, 67, 82, .12);--bf-color-status-info-border: rgba(16, 26, 39, .15);--bf-color-status-info-content: #555555;--bf-color-status-info-surface: #f3f3f5;--bf-color-status-success-border: #247344;--bf-color-status-success-content: #247344;--bf-color-status-success-surface: #e1fbe9;--bf-color-status-warning-border: rgba(154, 101, 31, .25);--bf-color-status-warning-content: #75501d;--bf-color-status-warning-surface: rgba(154, 101, 31, .08);--bf-color-surface-canvas: #fdfdfd;--bf-color-surface-chrome: #fdfdfd;--bf-color-surface-panel: #ffffff;--bf-color-surface-raised: #ffffff;--bf-color-surface-scene: #ffffff;--bf-color-surface-subtle: rgba(16, 26, 39, .03);--bf-color-surface-tertiary: #f3f3f5;--bf-color-surface-workbench: #f3f3f5;--bf-effect-blur-base: blur(8px) saturate(1.05);--bf-effect-blur-medium: blur(12px) saturate(1.2);--bf-effect-blur-subtle: blur(4px) saturate(1.02);--bf-opacity-disabled: .55;--bf-opacity-focus: .9;--bf-opacity-hover: .75;--bf-opacity-muted: .75;--bf-shadow-accent-glow: 0 12px 32px color-mix(in srgb, #059cb0 25%, transparent), 0 6px 16px color-mix(in srgb, #059cb0 18%, transparent), 0 3px 8px rgba(0, 0, 0, .12);--bf-shadow-base: 0 4px 8px rgba(16, 26, 39, .07);--bf-shadow-composer: 0 2px 6px rgba(0, 0, 0, .08);--bf-shadow-inner-highlight: inset 0 1px 0 rgba(255, 255, 255, .08);--bf-shadow-inner-highlight-hover: inset 0 1px 0 rgba(255, 255, 255, .24);--bf-shadow-lg: 0 8px 16px rgba(16, 26, 39, .09);--bf-shadow-menu: 0 4px 10px rgba(0, 0, 0, .12);--bf-shadow-overlay: 0 4px 20px rgba(0, 0, 0, .12);--bf-shadow-raised: 0 2px 4px rgba(16, 26, 39, .055);--bf-shadow-sm: 0 2px 4px rgba(16, 26, 39, .055);--bf-shadow-xl: 0 12px 24px rgba(16, 26, 39, .11);--bf-shadow-xs: 0 1px 2px rgba(16, 26, 39, .04)}}@layer bf.tokens.theme{:where([data-bf-design-system-root][data-color-scheme=dark]){--bf-color-accent-border: color-mix(in srgb, #60a5fa 40%, transparent);--bf-color-accent-border-subtle: color-mix(in srgb, #60a5fa 25%, transparent);--bf-color-accent-default: #60a5fa;--bf-color-accent-disabled: rgba(96, 165, 250, .3);--bf-color-accent-hover: #3b82f6;--bf-color-accent-secondary: #8b5cf6;--bf-color-accent-secondary-border: color-mix(in srgb, #8b5cf6 25%, transparent);--bf-color-accent-secondary-hover: #7c6b99;--bf-color-accent-secondary-surface: color-mix(in srgb, #8b5cf6 9%, transparent);--bf-color-accent-secondary-surface-strong: color-mix(in srgb, #8b5cf6 15%, transparent);--bf-color-accent-surface: color-mix(in srgb, #60a5fa 9%, transparent);--bf-color-accent-surface-strong: color-mix(in srgb, #60a5fa 15%, transparent);--bf-color-accent-surface-subtle: color-mix(in srgb, #60a5fa 5%, transparent);--bf-color-action-neutral-border: rgba(255, 255, 255, .18);--bf-color-action-neutral-content: #b0b0b0;--bf-color-action-neutral-content-disabled: #555555;--bf-color-action-neutral-fill-border: rgba(255, 255, 255, .1);--bf-color-action-neutral-surface: rgba(255, 255, 255, .1);--bf-color-action-neutral-surface-hover: rgba(255, 255, 255, .12);--bf-color-action-neutral-surface-pressed: rgba(255, 255, 255, .15);--bf-color-action-primary-background: rgba(255, 255, 255, .16);--bf-color-action-primary-content: #f3f3f5;--bf-color-action-primary-hover: rgba(255, 255, 255, .24);--bf-color-action-primary-pressed: rgba(255, 255, 255, .2);--bf-color-action-quiet-content: #b0b0b0;--bf-color-action-quiet-hover: rgba(255, 255, 255, .06);--bf-color-action-quiet-pressed: rgba(255, 255, 255, .1);--bf-color-action-secondary-background: rgba(255, 255, 255, .06);--bf-color-action-secondary-content: #e8e8e8;--bf-color-action-secondary-hover: rgba(255, 255, 255, .1);--bf-color-action-secondary-pressed: rgba(255, 255, 255, .12);--bf-color-border-default: rgba(255, 255, 255, .18);--bf-color-border-strong: rgba(255, 255, 255, .3);--bf-color-border-subtle: rgba(255, 255, 255, .12);--bf-color-content-disabled: #555555;--bf-color-content-inverse: #0e0e10;--bf-color-content-muted: #858585;--bf-color-content-on-dark: #ffffff;--bf-color-content-on-light: #000000;--bf-color-content-primary: #e8e8e8;--bf-color-content-secondary: #b0b0b0;--bf-color-control-switch-thumb: #ffffff;--bf-color-control-switch-track: #555555;--bf-color-control-switch-track-checked: #34c78c;--bf-color-field-background: #1c1c1f;--bf-color-field-background-hover: rgba(255, 255, 255, .06);--bf-color-field-border: rgba(255, 255, 255, .18);--bf-color-field-border-focus: #60a5fa;--bf-color-field-border-hover: rgba(255, 255, 255, .24);--bf-color-focus-ring: #60a5fa;--bf-color-identity-assistant-border: color-mix(in srgb, #ec4899 15%, transparent);--bf-color-identity-assistant-content: #ec4899;--bf-color-identity-assistant-content-hover: #f472b6;--bf-color-identity-assistant-surface: color-mix(in srgb, #ec4899 9%, transparent);--bf-color-identity-assistant-surface-subtle: color-mix(in srgb, #ec4899 5%, transparent);--bf-color-key-hint-background: rgba(255, 255, 255, .1);--bf-color-link-default: #60a5fa;--bf-color-link-hover: #93c5fd;--bf-color-overlay-scrim: rgba(0, 0, 0, .56);--bf-color-scrollbar-thumb: rgba(255, 255, 255, .12);--bf-color-scrollbar-thumb-hover: rgba(255, 255, 255, .15);--bf-color-status-danger-border: rgba(239, 68, 68, .3);--bf-color-status-danger-content: #ef4444;--bf-color-status-danger-surface: rgba(239, 68, 68, .1);--bf-color-status-info-border: rgba(255, 255, 255, .24);--bf-color-status-info-content: #a1a1aa;--bf-color-status-info-surface: rgba(255, 255, 255, .08);--bf-color-status-success-border: rgba(52, 211, 153, .3);--bf-color-status-success-content: #34d399;--bf-color-status-success-surface: rgba(52, 211, 153, .1);--bf-color-status-warning-border: rgba(245, 158, 11, .3);--bf-color-status-warning-content: #f59e0b;--bf-color-status-warning-surface: rgba(245, 158, 11, .1);--bf-color-surface-canvas: #0e0e10;--bf-color-surface-chrome: #0e0e10;--bf-color-surface-panel: #1c1c1f;--bf-color-surface-raised: #1c1c1f;--bf-color-surface-scene: #1c1c1f;--bf-color-surface-subtle: rgba(255, 255, 255, .06);--bf-color-surface-tertiary: #0e0e10;--bf-color-surface-workbench: #0e0e10;--bf-effect-blur-base: blur(8px) saturate(1.1);--bf-effect-blur-medium: blur(12px) saturate(1.2);--bf-effect-blur-subtle: blur(4px) saturate(1.05);--bf-opacity-disabled: .6;--bf-opacity-focus: .9;--bf-opacity-hover: .8;--bf-opacity-muted: .8;--bf-shadow-accent-glow: 0 12px 32px color-mix(in srgb, #3b82f6 25%, transparent), 0 6px 16px color-mix(in srgb, #60a5fa 18%, transparent), 0 3px 8px rgba(0, 0, 0, .12);--bf-shadow-base: 0 4px 8px rgba(0, 0, 0, .7);--bf-shadow-composer: 0 2px 6px rgba(0, 0, 0, .32);--bf-shadow-inner-highlight: inset 0 1px 0 rgba(255, 255, 255, .08);--bf-shadow-inner-highlight-hover: inset 0 1px 0 rgba(255, 255, 255, .24);--bf-shadow-lg: 0 8px 16px rgba(0, 0, 0, .6);--bf-shadow-menu: 0 4px 10px rgba(0, 0, 0, .48);--bf-shadow-overlay: 0 4px 20px rgba(0, 0, 0, .48);--bf-shadow-raised: 0 2px 4px rgba(0, 0, 0, .8);--bf-shadow-sm: 0 2px 4px rgba(0, 0, 0, .8);--bf-shadow-xl: 0 12px 24px rgba(0, 0, 0, .5);--bf-shadow-xs: 0 1px 2px rgba(0, 0, 0, .9)}}@layer bf.tokens.theme{:where([data-bf-design-system-root][data-color-scheme=light][data-contrast=high]){--bf-color-action-neutral-border: #000000;--bf-color-action-neutral-content: #000000;--bf-color-action-neutral-content-disabled: #343434;--bf-color-action-neutral-fill-border: #000000;--bf-color-action-neutral-surface: #e6e6e6;--bf-color-action-neutral-surface-hover: #cccccc;--bf-color-action-neutral-surface-pressed: #b3b3b3;--bf-color-action-primary-background: #000000;--bf-color-action-primary-hover: #262626;--bf-color-border-default: #3b3b3b;--bf-color-border-strong: #000000;--bf-color-border-subtle: #707070;--bf-color-content-muted: #343434;--bf-color-content-primary: #000000;--bf-color-content-secondary: #161616;--bf-color-control-switch-track: #3b3b3b;--bf-color-control-switch-track-checked: #005fcc;--bf-color-field-border: #3b3b3b;--bf-color-field-border-focus: #005fcc;--bf-color-field-border-hover: #000000;--bf-color-focus-ring: #005fcc;--bf-color-key-hint-background: #e6e6e6;--bf-color-scrollbar-thumb: #cccccc;--bf-color-scrollbar-thumb-hover: #b3b3b3;--bf-color-status-warning-surface: rgba(154, 101, 31, .04);--bf-color-surface-canvas: #ffffff;--bf-color-surface-chrome: #ffffff}}@layer bf.tokens.theme{:where([data-bf-design-system-root][data-color-scheme=dark][data-contrast=high]){--bf-color-action-neutral-border: #ffffff;--bf-color-action-neutral-content: #ffffff;--bf-color-action-neutral-content-disabled: #d0d0d0;--bf-color-action-neutral-fill-border: #ffffff;--bf-color-action-neutral-surface: #343434;--bf-color-action-neutral-surface-hover: #505050;--bf-color-action-neutral-surface-pressed: #6b6b6b;--bf-color-action-primary-background: #ffffff;--bf-color-action-primary-content: #000000;--bf-color-action-primary-hover: #e6e6e6;--bf-color-action-primary-pressed: #ffffff;--bf-color-border-default: #b5b5b5;--bf-color-border-strong: #ffffff;--bf-color-border-subtle: #8a8a8a;--bf-color-content-muted: #d0d0d0;--bf-color-content-primary: #ffffff;--bf-color-content-secondary: #f0f0f0;--bf-color-control-switch-thumb: #000000;--bf-color-control-switch-track: #b5b5b5;--bf-color-control-switch-track-checked: #ffcc00;--bf-color-field-border: #b5b5b5;--bf-color-field-border-focus: #ffcc00;--bf-color-field-border-hover: #ffffff;--bf-color-focus-ring: #ffcc00;--bf-color-key-hint-background: #343434;--bf-color-scrollbar-thumb: #505050;--bf-color-scrollbar-thumb-hover: #6b6b6b;--bf-color-surface-canvas: #000000;--bf-color-surface-chrome: #000000;--bf-color-surface-panel: #090909;--bf-color-surface-scene: #090909;--bf-color-surface-tertiary: #000000;--bf-color-surface-workbench: #000000}}:root{--size-radius-sm: 6px;--size-radius-base: 8px;--size-radius-lg: 12px;--size-radius-xl: 16px;--size-radius-2xl: 20px;--size-radius-full: 9999px;--size-gap-1: 4px;--size-gap-2: 8px;--size-gap-3: 12px;--size-gap-4: 16px;--size-gap-5: 20px;--size-gap-6: 24px;--size-gap-8: 32px;--size-gap-10: 40px;--size-gap-12: 48px;--size-gap-16: 64px;--motion-fast: .15s;--motion-base: .3s;--motion-slow: .6s;--easing-standard: cubic-bezier(.4, 0, .2, 1);--font-family-sans: "Noto Sans SC", -apple-system, BlinkMacSystemFont, "Segoe UI", "SF Pro Display", Roboto, sans-serif;--font-family-mono: "Menlo", "SF Mono", "Cascadia Code", "Consolas", "Liberation Mono", "Courier New", "Noto Sans Mono CJK SC", "Noto Sans Mono", monospace;--font-weight-normal: 400;--font-weight-medium: 500;--font-weight-semibold: 600;--font-weight-bold: 700;--font-size-xs: 12px;--font-size-sm: 14px;--font-size-base: 15px;--font-size-lg: 16px;--font-size-xl: 18px;--font-size-2xl: 20px;--font-size-3xl: 24px;--line-height-tight: 1.2;--line-height-base: 1.5;--line-height-relaxed: 1.6}*{margin:0;padding:0;box-sizing:border-box;-webkit-tap-highlight-color:transparent}html,body,#root{height:100%;height:100dvh;width:100%;overflow:hidden}body{font-family:var(--font-family-sans);font-size:var(--font-size-sm);line-height:var(--line-height-base);color:var(--bf-color-content-primary);background:var(--bf-color-surface-canvas);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mobile-app{height:100%;height:100dvh;width:100%;background:var(--bf-color-surface-canvas);color:var(--bf-color-content-primary);display:flex;flex-direction:column;position:relative;overflow:hidden}::-webkit-scrollbar{width:4px;height:4px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:var(--bf-color-scrollbar-thumb);border-radius:var(--size-radius-full)}::-webkit-scrollbar-thumb:hover{background:var(--bf-color-scrollbar-thumb-hover)}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes slideUp{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}@keyframes slideDown{0%{opacity:0;transform:translateY(-12px)}to{opacity:1;transform:translateY(0)}}@keyframes typing-bounce{0%,60%,to{transform:translateY(0);opacity:.4}30%{transform:translateY(-4px);opacity:1}}@keyframes focusBorderFlow{0%{background-position:0% 50%}50%{background-position:100% 50%}to{background-position:0% 50%}}.page-transition{animation:fadeIn var(--motion-base) cubic-bezier(0,0,.2,1)}.nav-page{position:absolute;inset:0;background:var(--bf-color-surface-canvas);z-index:1}.nav-push-enter{z-index:2;animation:navPushIn .3s cubic-bezier(.2,.9,.3,1) both}.nav-push-exit{z-index:1;animation:navPushOut .3s cubic-bezier(.2,.9,.3,1) both}.nav-pop-enter{z-index:1;animation:navPopIn .3s cubic-bezier(.2,.9,.3,1) both}.nav-pop-exit{z-index:2;animation:navPopOut .3s cubic-bezier(.2,.9,.3,1) both}@keyframes navPushIn{0%{transform:translate(100%)}to{transform:translate(0)}}@keyframes navPushOut{0%{transform:translate(0)}to{transform:translate(-25%)}}@keyframes navPopIn{0%{transform:translate(-25%)}to{transform:translate(0)}}@keyframes navPopOut{0%{transform:translate(0)}to{transform:translate(100%)}}@media(prefers-reduced-motion:reduce){.page-transition,.nav-push-enter,.nav-push-exit,.nav-pop-enter,.nav-pop-exit{animation:none}}.spinner{width:28px;height:28px;border:2.5px solid var(--bf-color-border-subtle);border-top-color:var(--bf-color-accent-default);border-radius:50%;animation:spin .8s linear infinite}.spinner--sm{width:14px;height:14px;border-width:2px}html.theme-switching,html.theme-switching *,html.theme-switching *:before,html.theme-switching *:after{transition:background-color .28s ease,color .28s ease,border-color .28s ease,box-shadow .28s ease,fill .28s ease,stroke .28s ease,background .28s ease!important}.mobile-reconnect-banner{position:fixed;top:env(safe-area-inset-top,0);left:0;right:0;z-index:100;display:flex;align-items:center;justify-content:center;gap:8px;padding:8px 16px;background:var(--bf-color-status-warning-content);color:var(--bf-color-action-primary-content);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);animation:slideDown var(--motion-fast) var(--easing-standard)}.mobile-reconnect-banner button{margin-left:4px;padding:3px 9px;border:1px solid currentColor;border-radius:var(--size-radius-full);background:transparent;color:inherit;font:inherit;cursor:pointer}.mobile-reconnect-spinner{display:inline-block;width:14px;height:14px;border:2px solid color-mix(in srgb,currentColor 30%,transparent);border-top-color:currentColor;border-radius:50%;animation:reconnect-spin .8s linear infinite}@keyframes reconnect-spin{to{transform:rotate(360deg)}}.pairing-page{position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100%;min-height:100dvh;gap:var(--size-gap-6);padding:max(var(--size-gap-8),env(safe-area-inset-top,0px)) max(var(--size-gap-8),env(safe-area-inset-right,0px)) max(var(--size-gap-8),env(safe-area-inset-bottom,0px)) max(var(--size-gap-8),env(safe-area-inset-left,0px));animation:fadeIn var(--motion-slow) cubic-bezier(0,0,.2,1)}.pairing-page__actions{position:absolute;top:calc(var(--size-gap-4) + env(safe-area-inset-top,0px));right:calc(var(--size-gap-4) + env(safe-area-inset-right,0px));display:flex;align-items:center;gap:var(--size-gap-2)}.pairing-page__theme-btn{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:1px solid var(--bf-color-border-subtle);border-radius:50%;background:var(--bf-color-surface-subtle);color:var(--bf-color-content-secondary);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.pairing-page__theme-btn:active{transform:scale(.96);color:var(--bf-color-content-primary);background:var(--bf-color-action-neutral-surface-hover)}.pairing-page__logo{width:64px;height:64px;object-fit:contain;margin-bottom:var(--size-gap-2);animation:pairingLogoBreathe 3.2s var(--easing-standard) infinite}@keyframes pairingLogoBreathe{0%,to{transform:scale(1);opacity:1}50%{transform:scale(1.05);opacity:.88}}.pairing-page__brand{font-size:var(--font-size-2xl);font-weight:var(--font-weight-semibold);color:var(--bf-color-accent-default);letter-spacing:.5px}.pairing-page__state{font-size:var(--font-size-sm);color:var(--bf-color-content-muted);text-align:center}.pairing-page__form{width:min(100%,320px);display:flex;flex-direction:column;gap:var(--size-gap-3)}.pairing-page__field{display:flex;flex-direction:column;gap:8px}.pairing-page__field-label{font-size:var(--font-size-xs);color:var(--bf-color-content-secondary);letter-spacing:.04em;text-transform:uppercase}.pairing-page__input{width:100%;min-height:44px;padding:0 14px;border:1px solid var(--bf-color-border-default);border-radius:var(--size-radius-base);background:var(--bf-color-surface-raised);color:var(--bf-color-content-primary);font-size:var(--font-size-base);outline:none}.pairing-page__input:focus{border-color:var(--bf-color-accent-border);box-shadow:0 0 0 3px color-mix(in srgb,var(--bf-color-accent-border) 18%,transparent)}.pairing-page__note{margin:0;font-size:var(--font-size-xs);line-height:1.5;color:var(--bf-color-content-muted);text-align:left}.pairing-page__spinner-wrap{height:32px;display:flex;align-items:center;justify-content:center}.pairing-page__error{font-size:var(--font-size-xs);color:var(--bf-color-status-danger-content);text-align:center;max-width:280px;padding:var(--size-gap-2) var(--size-gap-3);background:var(--bf-color-status-danger-surface);border:1px solid var(--bf-color-status-danger-border);border-radius:var(--size-radius-base)}.pairing-page__retry{padding:var(--size-gap-3) var(--size-gap-8);background:var(--bf-color-action-secondary-background);color:var(--bf-color-content-primary);border:1px solid var(--bf-color-border-default);border-radius:var(--size-radius-base);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.pairing-page__retry:active{background:var(--bf-color-action-secondary-hover)}.pairing-page__retry:disabled{opacity:.6;cursor:not-allowed}@media(prefers-reduced-motion:reduce){.pairing-page,.pairing-page__logo{animation:none}}.session-list{position:relative;display:flex;flex-direction:column;height:100%;background:var(--bf-color-surface-canvas);overflow:hidden}.session-list__header{position:relative;z-index:1;display:flex;align-items:center;justify-content:space-between;padding:0 var(--size-gap-5);min-height:56px;border-bottom:1px solid var(--bf-color-border-subtle);background:var(--bf-color-surface-raised);backdrop-filter:var(--bf-effect-blur-base);-webkit-backdrop-filter:var(--bf-effect-blur-base);flex-shrink:0}.session-list__header-brand{display:flex;align-items:center;gap:var(--size-gap-3);min-width:0}.session-list__header-copy{display:flex;flex-direction:column;gap:0;min-width:0}.session-list__header-copy h1{margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--bf-color-content-primary);letter-spacing:.01em;width:fit-content}.session-list__header-account-name{font-size:11px;font-weight:var(--font-weight-medium);color:var(--bf-color-content-muted);letter-spacing:.02em}.session-list__health-dot{display:inline-block;width:7px;height:7px;border-radius:50%;margin-right:5px;vertical-align:middle}.session-list__health-dot--connected{background:var(--bf-color-status-success-content)}.session-list__health-dot--checking{background:var(--bf-color-status-warning-content)}.session-list__health-dot--unpaired{background:var(--bf-color-content-muted)}.session-list__health-dot--unreachable{background:var(--bf-color-status-danger-content)}.session-list__header-kicker{font-size:10px;font-weight:var(--font-weight-semibold);letter-spacing:.16em;text-transform:uppercase;color:var(--bf-color-accent-default);width:fit-content}.session-list__logo{width:26px;height:26px;object-fit:contain;flex-shrink:0}.session-list__header-actions{display:flex;align-items:center;gap:var(--size-gap-2)}.mobile-lang-btn.session-list__language-btn{width:32px;min-width:32px;height:32px;padding:0}.session-list__theme-btn,.session-list__devices-btn,.session-list__disconnect-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:1px solid var(--bf-color-border-subtle);border-radius:50%;background:var(--bf-color-surface-subtle);color:var(--bf-color-content-secondary);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.session-list__theme-btn:active,.session-list__devices-btn:active,.session-list__disconnect-btn:active{transform:scale(.96);color:var(--bf-color-content-primary);background:var(--bf-color-action-neutral-surface-hover)}.session-list__disconnect-btn:active{color:var(--bf-color-status-danger-content);background:var(--bf-color-status-danger-surface)}.session-list__devices-btn.is-remote{border-color:var(--bf-color-accent-surface-strong);background:var(--bf-color-accent-surface);color:var(--bf-color-accent-default)}.session-list__header-target{display:inline-block;max-width:120px;margin-left:6px;padding:0 7px;border:1px solid var(--bf-color-accent-surface-strong);border-radius:var(--size-radius-full);background:var(--bf-color-accent-surface);color:var(--bf-color-accent-default);font-size:10px;font-weight:var(--font-weight-semibold);line-height:16px;letter-spacing:.02em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle}.session-list__workspace-bar{position:relative;z-index:1;display:flex;align-items:center;gap:12px;padding:12px;border:1px solid var(--bf-color-accent-surface-strong);border-radius:20px;corner-shape:squircle;background:var(--bf-color-accent-surface-subtle);cursor:pointer;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard)}.session-list__workspace-bar:active{transform:translateY(1px);background:var(--bf-color-accent-surface)}.session-list__resume-card{display:flex;align-items:center;gap:12px;width:100%;padding:14px 16px;border:1.5px solid var(--bf-color-accent-surface-strong);border-radius:18px;corner-shape:squircle;background:var(--bf-color-accent-surface-subtle);color:var(--bf-color-content-primary);font:inherit;text-align:left;cursor:pointer;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard);animation:sessionItemIn var(--motion-base) cubic-bezier(0,0,.2,1) both}.session-list__resume-card:active{transform:scale(.985);background:var(--bf-color-accent-surface)}.session-list__resume-card:focus-visible{outline:2px solid var(--bf-color-accent-default);outline-offset:2px}.session-list__resume-icon{flex-shrink:0;display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:10px;corner-shape:squircle}.session-list__resume-body{flex:1;min-width:0;display:flex;flex-direction:column;justify-content:center;gap:2px;text-align:left}.session-list__resume-label{font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--bf-color-accent-default)}.session-list__resume-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-list__resume-meta{display:flex;align-items:center;gap:8px;margin-top:2px;min-width:0;overflow:hidden}.session-list__resume-time{font-size:11px;color:var(--bf-color-content-muted);white-space:nowrap;flex-shrink:0}.session-list__resume-arrow{flex-shrink:0;color:var(--bf-color-content-muted);display:inline-flex;align-items:center}.session-list__mode-toggle{display:flex;gap:6px;padding:4px;border:1px solid var(--bf-color-border-subtle);border-radius:16px;corner-shape:squircle;background:var(--bf-color-surface-panel)}.session-list__mode-toggle-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:8px;padding:10px 12px;border:none;border-radius:12px;corner-shape:squircle;background:transparent;color:var(--bf-color-content-secondary);font-size:13px;font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.session-list__mode-toggle-btn svg{width:18px;height:18px;flex-shrink:0}.session-list__mode-toggle-btn.is-active{background:var(--bf-color-surface-raised);color:var(--bf-color-content-primary);box-shadow:var(--bf-shadow-sm)}.session-list__mode-toggle-btn.is-active.is-active:first-child{color:var(--bf-color-accent-default)}.session-list__mode-toggle-btn.is-active.is-active:last-child{color:var(--bf-color-identity-assistant-content)}.session-list__mode-toggle-btn:active:not(.is-active){background:var(--bf-color-surface-subtle)}.session-list__workspace-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:10px;corner-shape:squircle;color:var(--bf-color-accent-default);background:var(--bf-color-accent-surface)}.session-list__workspace-copy{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.session-list__workspace-label{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--bf-color-accent-default)}.session-list__workspace-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-list__workspace-branch{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:999px;corner-shape:squircle;background:var(--bf-color-accent-surface);color:var(--bf-color-accent-default);font-size:11px;flex-shrink:1;min-width:0;white-space:nowrap}.session-list__workspace-switch{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--bf-color-content-muted)}.session-list__items{position:relative;z-index:1;flex:1;overflow-y:auto;padding:var(--size-gap-4);-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:var(--size-gap-4)}.session-list__panel{position:relative;padding:var(--size-gap-4);border:1px solid var(--bf-color-border-subtle);border-radius:22px;corner-shape:squircle;background:var(--bf-color-surface-raised);box-shadow:var(--bf-shadow-base);overflow:visible}.session-list__section-head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--size-gap-3);margin-bottom:var(--size-gap-4)}.session-list__section-kicker{font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--bf-color-accent-default)}.session-list__panel--assistant .session-list__section-kicker{color:var(--bf-color-identity-assistant-content)}.session-list__section-title{margin-top:4px;font-size:var(--font-size-lg);line-height:1.1;font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary);letter-spacing:-.02em}.session-list__section-meta{font-size:11px;color:var(--bf-color-content-muted);flex-shrink:0}.session-list__hint{background:var(--bf-color-identity-assistant-surface);color:var(--bf-color-identity-assistant-content-hover);border:1px solid var(--bf-color-identity-assistant-border)}.session-list__assistant-bar{position:relative;z-index:1;display:flex;align-items:center;gap:12px;margin:0;padding:12px;border:1px solid var(--bf-color-identity-assistant-border);border-radius:20px;corner-shape:squircle;background:var(--bf-color-identity-assistant-surface-subtle);cursor:pointer;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard)}.session-list__assistant-bar:active{transform:translateY(1px);background:var(--bf-color-identity-assistant-surface)}.session-list__assistant-icon{flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:10px;corner-shape:squircle;color:var(--bf-color-identity-assistant-content);background:var(--bf-color-identity-assistant-surface)}.session-list__assistant-icon svg{width:20px;height:20px}.session-list__assistant-copy{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.session-list__assistant-label{font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--bf-color-identity-assistant-content)}.session-list__assistant-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-list__assistant-switch{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--bf-color-content-muted)}.session-list__create-row{display:flex;flex-direction:column;gap:10px}.session-list__create-btn{position:relative;display:flex;align-items:center;gap:12px;width:100%;padding:12px;border:1px solid var(--bf-color-border-subtle);border-radius:18px;corner-shape:squircle;background:var(--bf-color-surface-panel);color:var(--bf-color-content-primary);cursor:pointer;text-align:left;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard);animation:sessionItemIn var(--motion-base) cubic-bezier(0,0,.2,1) both;box-shadow:var(--bf-shadow-sm)}.session-list__create-btn:active:not(:disabled){transform:translateY(1px);background:var(--bf-color-surface-subtle)}.session-list__create-btn:disabled{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.session-list__create-btn--code{border-color:var(--bf-color-accent-surface-strong)}.session-list__create-btn--cowork{border-color:var(--bf-color-accent-secondary-border)}.session-list__create-btn--claw{border-color:var(--bf-color-identity-assistant-border)}.session-list__create-icon{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:10px;corner-shape:squircle;flex-shrink:0;color:var(--bf-color-accent-default);background:var(--bf-color-accent-surface)}.session-list__create-btn--cowork .session-list__create-icon{color:var(--bf-color-accent-secondary);background:var(--bf-color-accent-secondary-surface)}.session-list__create-btn--claw .session-list__create-icon{color:var(--bf-color-identity-assistant-content);background:var(--bf-color-identity-assistant-surface)}.session-list__create-copy{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}.session-list__create-title{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary);letter-spacing:-.01em}.session-list__create-desc{font-size:11px;line-height:1.35;color:var(--bf-color-content-secondary);display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.session-list__create-arrow{display:inline-flex;align-items:center;justify-content:center;color:var(--bf-color-content-muted);flex-shrink:0}.session-list__cards{display:flex;flex-direction:column;gap:10px}.session-list__item{display:flex;align-items:center;gap:12px;padding:12px;border:1px solid var(--bf-color-border-subtle);border-radius:18px;corner-shape:squircle;background:var(--bf-color-surface-panel);box-shadow:var(--bf-shadow-xs);cursor:pointer;transition:transform var(--motion-fast) var(--easing-standard),background var(--motion-fast) var(--easing-standard);animation:sessionItemIn var(--motion-base) cubic-bezier(0,0,.2,1) both}.session-list__item:nth-child(1){animation-delay:35ms}.session-list__item:nth-child(2){animation-delay:70ms}.session-list__item:nth-child(3){animation-delay:105ms}.session-list__item:nth-child(4){animation-delay:.14s}.session-list__item:nth-child(5){animation-delay:175ms}.session-list__item:nth-child(6){animation-delay:.21s}.session-list__item:nth-child(7){animation-delay:245ms}.session-list__item:nth-child(8){animation-delay:.28s}.session-list__item:nth-child(9){animation-delay:315ms}.session-list__item:nth-child(10){animation-delay:.35s}.session-list__item:nth-child(11){animation-delay:385ms}.session-list__item:nth-child(12){animation-delay:.42s}.session-list__item:nth-child(13){animation-delay:455ms}.session-list__item:nth-child(14){animation-delay:.49s}.session-list__item:nth-child(15){animation-delay:525ms}.session-list__item:nth-child(16){animation-delay:.56s}.session-list__item:nth-child(17){animation-delay:595ms}.session-list__item:nth-child(18){animation-delay:.63s}.session-list__item:nth-child(19){animation-delay:665ms}.session-list__item:nth-child(20){animation-delay:.7s}.session-list__item:active{transform:translateY(1px);background:var(--bf-color-surface-subtle)}.session-list__item-icon{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:10px;corner-shape:squircle;flex-shrink:0;color:var(--bf-color-accent-default);background:var(--bf-color-accent-surface)}.session-list__item-icon--cowork,.session-list__item-icon--Cowork{color:var(--bf-color-accent-secondary);background:var(--bf-color-accent-secondary-surface)}.session-list__item-icon--claw,.session-list__item-icon--Claw{color:var(--bf-color-identity-assistant-content);background:var(--bf-color-identity-assistant-surface)}.session-list__item-body{min-width:0;flex:1;display:flex;flex-direction:column;justify-content:center}.session-list__item-top{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--size-gap-3)}.session-list__item-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);line-height:1.25;color:var(--bf-color-content-primary);min-width:0;flex:1;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}.session-list__item-time{font-size:10px;color:var(--bf-color-content-muted);margin-top:2px}.session-list__agent-badge{display:inline-flex;align-items:center;min-height:18px;padding:0 8px;border-radius:999px;corner-shape:squircle;font-size:10px;font-weight:var(--font-weight-semibold);border:1px solid var(--bf-color-border-subtle);background:var(--bf-color-surface-subtle);color:var(--bf-color-content-secondary);flex-shrink:0}.session-list__agent-badge--code,.session-list__agent-badge--agentic{background:var(--bf-color-accent-surface);color:var(--bf-color-accent-default);border-color:var(--bf-color-accent-surface-strong)}.session-list__agent-badge--cowork,.session-list__agent-badge--Cowork{background:var(--bf-color-accent-secondary-surface);color:var(--bf-color-accent-secondary);border-color:var(--bf-color-accent-secondary-border)}.session-list__agent-badge--claw,.session-list__agent-badge--Claw{background:var(--bf-color-identity-assistant-surface);color:var(--bf-color-identity-assistant-content);border-color:var(--bf-color-identity-assistant-border)}.session-list__empty{padding:var(--size-gap-10) var(--size-gap-4);text-align:center;font-size:var(--font-size-sm);line-height:1.6;color:var(--bf-color-content-muted);border:1px solid var(--bf-color-border-subtle);border-radius:18px;corner-shape:squircle;background:var(--bf-color-surface-panel)}.session-list__pull-indicator{display:flex;align-items:center;justify-content:center;overflow:hidden;transition:height .2s cubic-bezier(0,0,.2,1)}.session-list__pull-spinner{color:var(--bf-color-content-muted);transition:color var(--motion-fast)}.session-list__pull-spinner.is-active{color:var(--bf-color-accent-default);animation:spin .8s linear infinite}.session-list__load-more{padding:var(--size-gap-3) 0 var(--size-gap-1);text-align:center;font-size:12px;color:var(--bf-color-content-muted)}.session-list__picker-overlay{position:fixed;inset:0;background:var(--bf-color-overlay-scrim);display:flex;align-items:flex-end;justify-content:center;z-index:1000;animation:fadeIn var(--motion-fast) var(--easing-standard)}.session-list__picker-modal{width:100%;max-height:60vh;background:var(--bf-color-surface-raised);border-radius:20px 20px 0 0;overflow:hidden;animation:slideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.session-list__picker-header{display:flex;align-items:center;justify-content:space-between;padding:var(--size-gap-4);border-bottom:1px solid var(--bf-color-border-subtle)}.session-list__picker-header h3{margin:0;font-size:16px;font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary)}.session-list__picker-close{display:flex;align-items:center;justify-content:center;width:32px;height:32px;border:none;background:transparent;color:var(--bf-color-content-secondary);cursor:pointer;border-radius:50%}.session-list__picker-close:active{background:var(--bf-color-surface-subtle)}.session-list__picker-list{padding:var(--size-gap-3);max-height:calc(60vh - 60px);overflow-y:auto}.session-list__picker-empty{padding:var(--size-gap-6);text-align:center;color:var(--bf-color-content-muted);font-size:var(--font-size-sm)}.session-list__picker-item{display:flex;align-items:center;gap:12px;width:100%;padding:12px;border:1px solid var(--bf-color-border-subtle);border-radius:16px;corner-shape:squircle;background:var(--bf-color-surface-panel);color:var(--bf-color-content-primary);cursor:pointer;text-align:left;transition:all var(--motion-fast) var(--easing-standard);margin-bottom:8px}.session-list__picker-item:last-child{margin-bottom:0}.session-list__picker-item:active{transform:scale(.99);background:var(--bf-color-surface-subtle)}.session-list__picker-item.is-selected{border-color:var(--bf-color-identity-assistant-content);background:var(--bf-color-identity-assistant-surface-subtle)}.session-list__picker-item.is-selected svg{color:var(--bf-color-identity-assistant-content)}.session-list__picker-item--workspace.is-selected{border-color:var(--bf-color-accent-default);background:var(--bf-color-accent-surface-subtle)}.session-list__picker-item--workspace.is-selected svg{color:var(--bf-color-accent-default)}.session-list__picker-item svg{color:var(--bf-color-content-muted);flex-shrink:0}.session-list__picker-item-icon{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:10px;corner-shape:squircle;color:var(--bf-color-identity-assistant-content);background:var(--bf-color-identity-assistant-surface);flex-shrink:0}.session-list__picker-item-icon svg{width:18px;height:18px;color:inherit}.session-list__picker-item--workspace .session-list__picker-item-icon{color:var(--bf-color-accent-default);background:var(--bf-color-accent-surface)}.session-list__picker-item-name{flex:1;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--bf-color-content-primary)}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}@keyframes sessionItemIn{0%{opacity:0;transform:translateY(12px) scale(.985)}to{opacity:1;transform:translateY(0)}}.session-list__search{display:flex;align-items:center;gap:8px;padding:6px 10px;border:1px solid var(--bf-color-border-subtle);border-radius:12px;corner-shape:squircle;background:var(--bf-color-surface-panel);margin-bottom:var(--size-gap-3)}.session-list__search-icon{flex-shrink:0;color:var(--bf-color-content-muted)}.session-list__search-input{flex:1;border:none;background:none;font-size:var(--font-size-sm);color:var(--bf-color-content-primary);outline:none;padding:0;min-width:0}.session-list__search-input::placeholder{color:var(--bf-color-content-muted)}.session-list__search-input::-webkit-search-decoration,.session-list__search-input::-webkit-search-cancel-button{display:none}.session-list__search-clear{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border:none;background:none;color:var(--bf-color-content-muted);cursor:pointer;border-radius:50%;flex-shrink:0}.session-list__search-clear:active{background:var(--bf-color-surface-subtle);color:var(--bf-color-content-primary)}.session-list__menu-overlay{position:fixed;inset:0;background:var(--bf-color-overlay-scrim);display:flex;align-items:flex-end;justify-content:center;z-index:1000;animation:fadeIn var(--motion-fast) var(--easing-standard)}.session-list__menu-sheet{width:100%;max-width:440px;background:var(--bf-color-surface-raised);border-radius:20px 20px 0 0;padding:var(--size-gap-2) var(--size-gap-4) var(--size-gap-6);display:flex;flex-direction:column;gap:var(--size-gap-3);animation:slideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.session-list__menu-handle{width:36px;height:4px;border-radius:999px;background:var(--bf-color-border-subtle);margin:0 auto}.session-list__menu-title{text-align:center;font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary);padding:var(--size-gap-1) 0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.session-list__menu-actions{display:flex;flex-direction:column;gap:4px}.session-list__menu-btn{display:flex;align-items:center;gap:12px;width:100%;padding:14px 16px;border:none;border-radius:16px;corner-shape:squircle;background:var(--bf-color-surface-panel);color:var(--bf-color-content-primary);font-size:var(--font-size-base);font-weight:var(--font-weight-medium);cursor:pointer;text-align:left}.session-list__menu-btn svg{flex-shrink:0}.session-list__menu-btn:active{background:var(--bf-color-surface-subtle);transform:scale(.99)}.session-list__menu-btn--danger{color:var(--bf-color-status-danger-content);background:var(--bf-color-status-danger-surface)}.session-list__menu-btn--danger:active{background:color-mix(in srgb,var(--bf-color-status-danger-content) 12%,transparent)}.session-list__menu-cancel{width:100%;padding:14px;border:none;border-radius:14px;corner-shape:squircle;background:var(--bf-color-surface-panel);color:var(--bf-color-content-secondary);font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);cursor:pointer}.session-list__menu-cancel:active{background:var(--bf-color-surface-subtle)}.session-list__item--active{border-color:var(--bf-color-accent-default)!important;background:var(--bf-color-surface-subtle)!important}.session-list__rename-modal{width:calc(100% - 32px);max-width:400px;background:var(--bf-color-surface-raised);border-radius:20px;padding:var(--size-gap-5);display:flex;flex-direction:column;gap:var(--size-gap-4);animation:slideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.session-list__rename-title{margin:0;font-size:18px;font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary);text-align:center}.session-list__rename-input{padding:12px 14px;border:1px solid var(--bf-color-border-subtle);border-radius:12px;corner-shape:squircle;background:var(--bf-color-surface-panel);color:var(--bf-color-content-primary);font-size:var(--font-size-base);outline:none}.session-list__rename-input:focus{border-color:var(--bf-color-accent-default);box-shadow:0 0 0 3px var(--bf-color-accent-surface)}.session-list__rename-actions{display:flex;gap:10px}.session-list__rename-btn{flex:1;padding:12px;border:none;border-radius:14px;corner-shape:squircle;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.session-list__rename-btn:disabled{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.session-list__rename-btn--cancel{background:var(--bf-color-surface-panel);color:var(--bf-color-content-secondary)}.session-list__rename-btn--cancel:active:not(:disabled){background:var(--bf-color-surface-subtle)}.session-list__rename-btn--save{background:var(--bf-color-accent-default);color:var(--bf-color-action-primary-content)}.session-list__rename-btn--save:active:not(:disabled){opacity:.85}.session-list__confirm-modal{width:calc(100% - 32px);max-width:340px;background:var(--bf-color-surface-raised);border-radius:20px;padding:var(--size-gap-6) var(--size-gap-5) var(--size-gap-5);display:flex;flex-direction:column;align-items:center;gap:var(--size-gap-3);text-align:center;animation:slideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.session-list__confirm-icon{color:var(--bf-color-status-danger-content);margin-bottom:var(--size-gap-1)}.session-list__confirm-title{margin:0;font-size:17px;font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary)}.session-list__confirm-desc{margin:0;font-size:var(--font-size-sm);color:var(--bf-color-content-secondary);line-height:1.5}.session-list__confirm-actions{display:flex;gap:10px;width:100%;margin-top:var(--size-gap-2)}.session-list__confirm-btn{flex:1;padding:12px;border:none;border-radius:14px;corner-shape:squircle;font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.session-list__confirm-btn:disabled{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.session-list__confirm-btn--cancel{background:var(--bf-color-surface-panel);color:var(--bf-color-content-secondary)}.session-list__confirm-btn--cancel:active:not(:disabled){background:var(--bf-color-surface-subtle)}.session-list__confirm-btn--danger{background:var(--bf-color-status-danger-content);color:var(--bf-color-action-primary-content)}.session-list__confirm-btn--danger:active:not(:disabled){opacity:.85}.session-list__toast{position:fixed;bottom:40px;left:50%;transform:translate(-50%);padding:10px 20px;border-radius:999px;background:var(--bf-color-content-primary);color:var(--bf-color-surface-canvas);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);z-index:9999;box-shadow:var(--bf-shadow-base);pointer-events:none;animation:toastIn .25s var(--easing-standard)}@keyframes toastIn{0%{opacity:0;transform:translate(-50%) translateY(10px)}to{opacity:1;transform:translate(-50%) translateY(0)}}@media(prefers-reduced-motion:reduce){.session-list *,.session-list *:before,.session-list *:after{animation:none!important;transition:none!important}}.devices-page{position:relative;display:flex;flex-direction:column;height:100%;background:var(--bf-color-surface-canvas);overflow:hidden}.devices-page__header{position:relative;z-index:1;display:flex;align-items:center;gap:var(--size-gap-3);padding:0 var(--size-gap-4);min-height:56px;border-bottom:1px solid var(--bf-color-border-subtle);background:var(--bf-color-surface-raised);backdrop-filter:var(--bf-effect-blur-base);-webkit-backdrop-filter:var(--bf-effect-blur-base);flex-shrink:0}.devices-page__back-btn,.devices-page__refresh-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;border:1px solid var(--bf-color-border-subtle);border-radius:50%;background:var(--bf-color-surface-subtle);color:var(--bf-color-content-secondary);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard);flex-shrink:0}.devices-page__back-btn:active,.devices-page__refresh-btn:active{transform:scale(.96);color:var(--bf-color-content-primary);background:var(--bf-color-action-neutral-surface-hover)}.devices-page__back-btn:disabled,.devices-page__refresh-btn:disabled{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.devices-page__back-btn.is-loading svg,.devices-page__refresh-btn.is-loading svg{animation:reconnect-spin .8s linear infinite}.devices-page__title{flex:1;margin:0;font-size:var(--font-size-lg);font-weight:var(--font-weight-bold);color:var(--bf-color-content-primary);letter-spacing:.01em}.devices-page__body{flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;padding:var(--size-gap-4)}.devices-page__list{display:flex;flex-direction:column;gap:var(--size-gap-3)}.devices-page__device{display:flex;align-items:center;gap:var(--size-gap-3);width:100%;padding:var(--size-gap-4);border:1px solid var(--bf-color-border-subtle);border-radius:20px;corner-shape:squircle;background:var(--bf-color-surface-raised);color:var(--bf-color-content-primary);text-align:left;cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.devices-page__device:active:not(:disabled){background:var(--bf-color-surface-subtle);transform:scale(.99)}.devices-page__device.is-offline{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.devices-page__device.is-current{border-color:var(--bf-color-accent-border-subtle);background:var(--bf-color-accent-surface-subtle);cursor:default}.devices-page__device.is-switching{border-color:var(--bf-color-accent-border-subtle)}.devices-page__device>svg{flex-shrink:0;color:var(--bf-color-content-muted)}.devices-page__device-icon{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border:1px solid var(--bf-color-border-subtle);border-radius:var(--size-radius-lg);background:var(--bf-color-surface-subtle);color:var(--bf-color-content-secondary);flex-shrink:0}.is-current .devices-page__device-icon{background:var(--bf-color-accent-surface);border-color:var(--bf-color-accent-surface-strong);color:var(--bf-color-accent-default)}.devices-page__device-copy{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}.devices-page__device-name-row{display:flex;align-items:center;gap:var(--size-gap-2);min-width:0}.devices-page__device-name{font-size:var(--font-size-base);font-weight:var(--font-weight-medium);color:var(--bf-color-content-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.devices-page__badge{flex-shrink:0;padding:1px 7px;border:1px solid var(--bf-color-border-subtle);border-radius:var(--size-radius-full);background:var(--bf-color-surface-subtle);color:var(--bf-color-content-secondary);font-size:10px;font-weight:var(--font-weight-semibold);letter-spacing:.03em}.devices-page__badge--current{border-color:var(--bf-color-accent-surface-strong);background:var(--bf-color-accent-surface);color:var(--bf-color-accent-default)}.devices-page__device-meta{display:flex;align-items:center;gap:5px;font-size:var(--font-size-xs);color:var(--bf-color-content-muted)}.devices-page__status-dot{display:inline-block;width:7px;height:7px;border-radius:50%;flex-shrink:0}.devices-page__status-dot.is-online{background:var(--bf-color-status-success-content)}.devices-page__status-dot.is-offline{background:var(--bf-color-content-muted)}.devices-page__device-id{margin-left:var(--size-gap-1);font-family:var(--font-family-mono);letter-spacing:.02em}.devices-page__device-spinner{flex-shrink:0;width:16px;height:16px;border-width:2px}.devices-page__loading{display:flex;flex-direction:column;align-items:center;gap:var(--size-gap-3);padding:var(--size-gap-10) 0;font-size:var(--font-size-sm);color:var(--bf-color-content-muted)}.devices-page__empty{padding:var(--size-gap-10) 0;text-align:center;font-size:var(--font-size-sm);color:var(--bf-color-content-muted)}.devices-page__empty-card{display:flex;flex-direction:column;align-items:center;gap:var(--size-gap-4);margin-top:var(--size-gap-8);padding:var(--size-gap-8) var(--size-gap-6);border:1px solid var(--bf-color-border-subtle);border-radius:20px;corner-shape:squircle;background:var(--bf-color-surface-raised)}.devices-page__empty-icon{display:inline-flex;color:var(--bf-color-content-muted)}.devices-page__empty-text{margin:0;font-size:var(--font-size-sm);line-height:var(--line-height-relaxed);color:var(--bf-color-content-secondary);text-align:center}.devices-page__retry-btn{padding:var(--size-gap-2) var(--size-gap-6);border:1px solid var(--bf-color-border-default);border-radius:var(--size-radius-full);background:var(--bf-color-action-secondary-background);color:var(--bf-color-content-primary);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.devices-page__retry-btn:active{background:var(--bf-color-action-secondary-hover)}.devices-page__error{margin:var(--size-gap-3) var(--size-gap-4) 0;padding:var(--size-gap-2) var(--size-gap-3);font-size:var(--font-size-xs);color:var(--bf-color-status-danger-content);background:var(--bf-color-status-danger-surface);border:1px solid var(--bf-color-status-danger-border);border-radius:var(--size-radius-base)}.workspace-page{display:flex;flex-direction:column;height:100%;background:var(--bf-color-surface-canvas)}.workspace-page__header{display:flex;align-items:center;justify-content:space-between;gap:var(--size-gap-3);padding:0 var(--size-gap-5);height:56px;min-height:56px;border-bottom:1px solid var(--bf-color-border-subtle);background:var(--bf-color-surface-raised);backdrop-filter:var(--bf-effect-blur-base);-webkit-backdrop-filter:var(--bf-effect-blur-base);flex-shrink:0}.workspace-page__header h1{font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary)}.workspace-page__content{flex:1;overflow-y:auto;padding:var(--size-gap-4);-webkit-overflow-scrolling:touch}.workspace-page__loading{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:var(--size-gap-4);color:var(--bf-color-content-muted);font-size:var(--font-size-sm)}.workspace-page__current{display:flex;flex-direction:column;gap:var(--size-gap-4)}.workspace-page__current-label,.workspace-page__recent-label{font-size:9px;font-weight:var(--font-weight-semibold);color:var(--bf-color-accent-default);text-transform:uppercase;letter-spacing:.14em}.workspace-page__current-card{border:1px solid var(--bf-color-border-subtle);border-radius:18px;corner-shape:squircle;padding:var(--size-gap-4);background:var(--bf-color-surface-raised);box-shadow:var(--bf-shadow-sm);transition:all var(--motion-fast) var(--easing-standard)}.workspace-page__project-name{font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary);margin-bottom:var(--size-gap-1)}.workspace-page__project-path{font-size:var(--font-size-xs);color:var(--bf-color-content-muted);word-break:break-all;margin-bottom:var(--size-gap-2);font-family:var(--font-family-mono)}.workspace-page__git-branch{display:inline-flex;align-items:center;gap:4px;font-size:var(--font-size-xs);color:var(--bf-color-accent-default);background:var(--bf-color-accent-surface);padding:3px var(--size-gap-2);border-radius:8px;corner-shape:squircle;word-break:break-all}.workspace-page__actions{display:flex;gap:var(--size-gap-2)}.workspace-page__btn{flex:1;padding:var(--size-gap-3) var(--size-gap-4);border:none;border-radius:12px;corner-shape:squircle;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.workspace-page__btn--primary{background:var(--bf-color-accent-default);color:var(--bf-color-action-primary-content)}.workspace-page__btn--primary:active{background:var(--bf-color-accent-hover)}.workspace-page__btn--secondary{background:var(--bf-color-surface-subtle);color:var(--bf-color-content-primary);border:1px solid var(--bf-color-border-subtle)}.workspace-page__btn--secondary:active{background:var(--bf-color-action-neutral-surface-hover)}.workspace-page__btn:disabled{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.workspace-page__no-workspace{display:flex;flex-direction:column;align-items:center;text-align:center;padding:var(--size-gap-10) var(--size-gap-5);gap:var(--size-gap-3);border:1px solid var(--bf-color-border-subtle);border-radius:22px;corner-shape:squircle;background:var(--bf-color-surface-raised);box-shadow:var(--bf-shadow-base)}.workspace-page__no-workspace-icon{color:var(--bf-color-content-muted);opacity:.5}.workspace-page__no-workspace-text{font-size:var(--font-size-base);font-weight:var(--font-weight-medium);color:var(--bf-color-content-primary)}.workspace-page__no-workspace-hint{font-size:var(--font-size-xs);color:var(--bf-color-content-muted);max-width:280px}.workspace-page__recent{margin-top:var(--size-gap-5);display:flex;flex-direction:column;gap:var(--size-gap-3);animation:slideUp .3s cubic-bezier(0,0,.2,1) both}.workspace-page__recent-empty{text-align:center;color:var(--bf-color-content-muted);font-size:var(--font-size-xs);padding:var(--size-gap-6) 0}.workspace-page__recent-list{display:flex;flex-direction:column;gap:var(--size-gap-2)}.workspace-page__recent-item{display:flex;flex-direction:column;align-items:flex-start;background:var(--bf-color-surface-panel);border:1px solid var(--bf-color-border-subtle);border-radius:14px;corner-shape:squircle;padding:12px;cursor:pointer;text-align:left;color:var(--bf-color-content-primary);box-shadow:var(--bf-shadow-xs);transition:all var(--motion-fast) var(--easing-standard);animation:slideUp .3s cubic-bezier(0,0,.2,1) both}.workspace-page__recent-item:nth-child(1){animation-delay:.04s}.workspace-page__recent-item:nth-child(2){animation-delay:.08s}.workspace-page__recent-item:nth-child(3){animation-delay:.12s}.workspace-page__recent-item:nth-child(4){animation-delay:.16s}.workspace-page__recent-item:nth-child(5){animation-delay:.2s}.workspace-page__recent-item:nth-child(6){animation-delay:.24s}.workspace-page__recent-item:nth-child(7){animation-delay:.28s}.workspace-page__recent-item:nth-child(8){animation-delay:.32s}.workspace-page__recent-item:nth-child(9){animation-delay:.36s}.workspace-page__recent-item:nth-child(10){animation-delay:.4s}.workspace-page__recent-item:nth-child(11){animation-delay:.44s}.workspace-page__recent-item:nth-child(12){animation-delay:.48s}.workspace-page__recent-item:nth-child(13){animation-delay:.52s}.workspace-page__recent-item:nth-child(14){animation-delay:.56s}.workspace-page__recent-item:nth-child(15){animation-delay:.6s}.workspace-page__recent-item:nth-child(16){animation-delay:.64s}.workspace-page__recent-item:nth-child(17){animation-delay:.68s}.workspace-page__recent-item:nth-child(18){animation-delay:.72s}.workspace-page__recent-item:nth-child(19){animation-delay:.76s}.workspace-page__recent-item:nth-child(20){animation-delay:.8s}.workspace-page__recent-item:active{transform:translateY(1px);background:var(--bf-color-surface-subtle)}.workspace-page__recent-item:disabled{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.workspace-page__recent-item-name{font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);color:var(--bf-color-content-primary);margin-bottom:2px}.workspace-page__recent-item-path{font-size:11px;color:var(--bf-color-content-muted);word-break:break-all;font-family:var(--font-family-mono)}.workspace-page__switching{display:flex;align-items:center;justify-content:center;gap:var(--size-gap-2);padding:var(--size-gap-4);color:var(--bf-color-content-muted);font-size:var(--font-size-xs)}.workspace-page__error{margin-top:var(--size-gap-3);font-size:var(--font-size-xs);color:var(--bf-color-status-danger-content);text-align:center;padding:var(--size-gap-2) var(--size-gap-3);background:var(--bf-color-status-danger-surface);border-radius:10px;corner-shape:squircle}@media(prefers-reduced-motion:reduce){.workspace-page__recent,.workspace-page__recent-item{animation:none}.workspace-page__recent-item{transition:none}}.chat-page{display:flex;flex-direction:column;height:100%;background:var(--bf-color-surface-scene)}.chat-page__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:0 var(--size-gap-5);min-height:56px;border-bottom:1px solid var(--bf-color-border-subtle);flex-shrink:0;background:var(--bf-color-surface-raised);backdrop-filter:var(--bf-effect-blur-base);-webkit-backdrop-filter:var(--bf-effect-blur-base);position:relative;z-index:10}.chat-page__header-row{display:flex;align-items:center;gap:var(--size-gap-2);flex:1;min-width:0}.chat-page__back{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;background:none;border:none;color:var(--bf-color-content-muted);cursor:pointer;padding:0;flex-shrink:0;border-radius:50%;transition:all var(--motion-fast) var(--easing-standard)}.chat-page__back:active{background:var(--bf-color-surface-subtle);color:var(--bf-color-content-primary)}.chat-page__header-center{flex:1;min-width:0;overflow:hidden;text-align:center}.chat-page__title{font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:block}.chat-page__header-right{display:flex;align-items:center;gap:var(--size-gap-1);flex-shrink:0}.chat-page__theme-btn{display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;padding:0;background:none;border:none;color:var(--bf-color-content-muted);cursor:pointer;border-radius:50%;transition:all var(--motion-fast) var(--easing-standard)}.chat-page__theme-btn:active{background:var(--bf-color-surface-subtle)}.chat-page__header-workspace{display:flex;align-items:center;gap:4px;font-size:11px;color:var(--bf-color-content-muted);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;justify-content:center}.chat-page__workspace-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--bf-color-accent-default);font-weight:var(--font-weight-medium);font-size:11px}.chat-page__workspace-branch{color:var(--bf-color-content-muted);font-weight:var(--font-weight-normal);flex-shrink:0;font-size:11px;display:inline-flex;align-items:center;gap:3px}.chat-page__messages{flex:1;overflow-y:auto;padding:var(--size-gap-4) var(--size-gap-4) 100px;-webkit-overflow-scrolling:touch;display:flex;flex-direction:column;gap:var(--size-gap-4);position:relative}.chat-page__load-more-indicator{text-align:center;font-size:var(--font-size-xs);color:var(--bf-color-content-muted);padding:var(--size-gap-2) 0}.chat-page__scroll-to-bottom{position:fixed;bottom:110px;left:50%;transform:translate(-50%);width:40px;height:40px;border-radius:50%;border:1px solid var(--bf-color-border-subtle);background:var(--bf-color-surface-raised);color:var(--bf-color-content-primary);box-shadow:var(--bf-shadow-base);cursor:pointer;display:flex;align-items:center;justify-content:center;z-index:15;animation:scrollBtnIn .2s var(--easing-standard)}.chat-page__scroll-to-bottom:active{transform:translate(-50%) scale(.92);box-shadow:var(--bf-shadow-sm)}.chat-page__scroll-to-bottom:focus-visible{outline:2px solid var(--bf-color-accent-default);outline-offset:2px}@media(prefers-reduced-motion:reduce){.chat-page__scroll-to-bottom{animation:none}}@media(forced-colors:active){.chat-page__scroll-to-bottom{border:2px solid ButtonText;background:ButtonFace;color:ButtonText}}@keyframes scrollBtnIn{0%{opacity:0;transform:translate(-50%) scale(.7)}to{opacity:1;transform:translate(-50%) scale(1)}}.chat-msg{display:flex;flex-direction:column;width:100%}.chat-msg--user{align-items:flex-start}.chat-msg__user-card{display:flex;align-items:flex-start;width:100%}.chat-msg__user-avatar{display:none}.chat-msg__user-content{width:100%;font-size:var(--font-size-sm);line-height:var(--line-height-relaxed);color:var(--bf-color-content-primary);word-break:break-word;white-space:pre-wrap;padding:8px 12px;background:var(--bf-color-surface-subtle);border:1px solid var(--bf-color-border-subtle);border-radius:var(--size-radius-base)}.chat-msg__user-images{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}.chat-msg__user-image{width:48px;height:48px;border-radius:6px;object-fit:cover;border:1px solid var(--bf-color-border-subtle)}.chat-msg--assistant{align-items:flex-start;gap:var(--size-gap-1)}.chat-msg--collapsed{padding:0}.chat-msg__response-toggle{display:inline-flex;align-items:center;gap:6px;background:none;border:none;color:var(--bf-color-content-muted);font-size:var(--font-size-xs);cursor:pointer;padding:3px 0;text-align:left}.chat-msg__response-toggle:active{opacity:.7}.chat-msg__response-chevron{display:inline-flex;align-items:center;transition:transform var(--motion-fast) var(--easing-standard)}.chat-msg__response-chevron.is-open{transform:rotate(90deg)}.chat-msg__response-label{color:var(--bf-color-content-muted);font-style:italic;font-size:var(--font-size-xs)}.chat-msg__image-analyzing{display:flex;align-items:center;gap:8px;padding:10px 14px;font-size:var(--font-size-sm);color:var(--bf-color-content-secondary);background:var(--bf-color-surface-subtle);border-radius:10px;animation:analyzeGlow 2s ease-in-out infinite}.chat-msg__image-analyzing span{flex-shrink:0}.chat-msg__image-analyzing-icon{display:flex;align-items:center;color:var(--bf-color-accent-default);animation:analyzeSpin 3s linear infinite}@keyframes analyzeSpin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes analyzeGlow{0%,to{opacity:1}50%{opacity:.7}}.chat-page__toast{position:fixed;top:48px;left:16px;right:16px;padding:12px 16px;border-radius:10px;background:var(--bf-color-status-danger-content);color:var(--bf-color-action-primary-content);font-size:13px;line-height:1.4;z-index:9999;white-space:pre-line;animation:toastSlideIn .25s ease-out;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.chat-page__toast--info{background:var(--bf-color-status-success-content)}@keyframes toastSlideIn{0%{transform:translateY(-20px);opacity:0}to{transform:translateY(0);opacity:1}}.chat-msg--menu-active{opacity:.7}.chat-msg__menu-overlay{position:fixed;inset:0;background:var(--bf-color-overlay-scrim);display:flex;align-items:flex-end;justify-content:center;z-index:1000;animation:menuFadeIn var(--motion-fast) var(--easing-standard)}.chat-msg__menu-sheet{width:100%;max-width:440px;background:var(--bf-color-surface-raised);border-radius:20px 20px 0 0;padding:var(--size-gap-2) var(--size-gap-4) var(--size-gap-6);display:flex;flex-direction:column;gap:var(--size-gap-3);animation:menuSlideUp var(--motion-base) cubic-bezier(0,0,.2,1)}.chat-msg__menu-handle{width:36px;height:4px;border-radius:999px;background:var(--bf-color-border-subtle);margin:0 auto}.chat-msg__menu-actions{display:flex;flex-direction:column;gap:4px}.chat-msg__menu-btn{display:flex;align-items:center;gap:12px;width:100%;padding:14px 16px;border:none;border-radius:16px;background:var(--bf-color-surface-panel);color:var(--bf-color-content-primary);font-size:var(--font-size-base);font-weight:var(--font-weight-medium);cursor:pointer;text-align:left}.chat-msg__menu-btn svg{flex-shrink:0}.chat-msg__menu-btn:active:not(:disabled){background:var(--bf-color-surface-subtle);transform:scale(.99)}.chat-msg__menu-btn:disabled{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.chat-msg__menu-btn--danger{color:var(--bf-color-status-danger-content);background:var(--bf-color-status-danger-surface)}.chat-msg__menu-btn--danger:active:not(:disabled){background:var(--bf-color-status-danger-border)}.chat-msg__menu-cancel{width:100%;padding:14px;border:none;border-radius:14px;background:var(--bf-color-surface-panel);color:var(--bf-color-content-secondary);font-size:var(--font-size-base);font-weight:var(--font-weight-semibold);cursor:pointer}.chat-msg__menu-cancel:active{background:var(--bf-color-surface-subtle)}@keyframes menuFadeIn{0%{opacity:0}to{opacity:1}}@keyframes menuSlideUp{0%{transform:translateY(100%)}to{transform:translateY(0)}}@media(prefers-reduced-motion:reduce){.chat-msg__menu-sheet,.chat-msg__menu-overlay{animation:none}}.mobile-lang-btn{display:inline-flex;align-items:center;justify-content:center;min-width:44px;height:44px;padding:0 10px;border:1px solid var(--bf-color-border-subtle);border-radius:999px;background:var(--bf-color-surface-subtle);color:var(--bf-color-content-secondary);font-size:11px;font-weight:var(--font-weight-semibold);letter-spacing:.04em;cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.mobile-lang-btn:active{transform:scale(.96);color:var(--bf-color-content-primary);background:var(--bf-color-action-neutral-surface-hover)}.chat-tool-list{display:flex;flex-direction:column;gap:var(--size-gap-1);width:100%}.chat-tool-list--collapsed{border:1px solid var(--bf-color-border-default);border-radius:var(--size-radius-lg);background:color-mix(in srgb,var(--bf-color-surface-panel) 60%,transparent);-webkit-backdrop-filter:var(--bf-effect-blur-base);backdrop-filter:var(--bf-effect-blur-base);overflow:hidden}.chat-tool-list__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);min-height:32px;cursor:pointer;transition:background var(--motion-fast) var(--easing-standard)}.chat-tool-list__header:active{background:var(--bf-color-surface-subtle)}.chat-tool-list__chevron{display:flex;align-items:center;color:var(--bf-color-content-muted);transition:transform var(--motion-fast) var(--easing-standard);flex-shrink:0}.chat-tool-list__chevron.is-expanded{transform:rotate(180deg)}.chat-tool-list__count{font-size:12px;font-weight:var(--font-weight-medium);color:var(--bf-color-content-secondary)}.chat-tool-list__stats{display:flex;gap:var(--size-gap-2);margin-left:auto}.chat-tool-list__stat{font-size:11px;font-variant-numeric:tabular-nums}.chat-tool-list__stat--done{color:var(--bf-color-status-success-content)}.chat-tool-list__stat--running{color:var(--bf-color-status-warning-content)}.chat-tool-list__scroll{display:flex;flex-direction:column;gap:var(--size-gap-1);padding:var(--size-gap-2);max-height:140px;border-top:1px solid var(--bf-color-border-subtle);overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scroll-behavior:smooth}.chat-tool-list__scroll .chat-tool-card{flex-shrink:0}.chat-tool-list__scroll{mask-image:linear-gradient(to bottom,transparent 0px,black 16px,black 100%);-webkit-mask-image:linear-gradient(to bottom,transparent 0px,black 16px,black 100%)}.chat-tool-list__scroll::-webkit-scrollbar{width:3px}.chat-tool-list__scroll::-webkit-scrollbar-track{background:transparent}.chat-tool-list__scroll::-webkit-scrollbar-thumb{background:var(--bf-color-content-muted);border-radius:2px;opacity:.4}.chat-tool-card{border-radius:var(--size-radius-base);border:1px solid var(--bf-color-border-default);background:var(--bf-color-surface-scene);overflow:hidden;transition:all var(--motion-fast) var(--easing-standard)}.chat-tool-card--running{border-color:var(--bf-color-status-warning-border)}.chat-tool-card--done{border-color:var(--bf-color-status-success-border)}.chat-tool-card--error{border-color:var(--bf-color-status-danger-border)}.chat-tool-card--pending{border-color:var(--bf-color-status-warning-border)}.chat-tool-card__row{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);cursor:pointer;min-height:36px}.chat-tool-card__icon{display:flex;align-items:center;justify-content:center;width:16px;height:16px;flex-shrink:0}.chat-tool-card__spinner{display:inline-block;width:14px;height:14px;border:2px solid var(--bf-color-status-warning-border);border-top-color:var(--bf-color-status-warning-content);border-radius:50%;animation:spin .7s linear infinite}.chat-tool-card__check{color:var(--bf-color-status-success-content);display:flex;align-items:center}.chat-tool-card__error-icon{color:var(--bf-color-status-danger-content);display:flex;align-items:center}.chat-tool-card__pending-icon{color:var(--bf-color-status-warning-content);display:flex;align-items:center}.chat-tool-card__name{flex:1;font-size:var(--font-size-xs);color:var(--bf-color-content-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:var(--font-weight-medium);min-width:0}.chat-tool-card__preview{font-weight:var(--font-weight-normal);color:var(--bf-color-content-muted)}.chat-tool-card__type{display:inline-flex;align-items:center;padding:1px 6px;border-radius:var(--size-radius-sm);font-size:11px;font-weight:var(--font-weight-medium);background:var(--bf-color-accent-surface);color:var(--bf-color-accent-default);flex-shrink:0}.chat-tool-card__duration{font-size:11px;color:var(--bf-color-content-muted);flex-shrink:0;font-variant-numeric:tabular-nums;font-family:var(--font-family-mono)}.chat-tool-card__cancel{display:inline-flex;align-items:center;justify-content:center;width:20px;height:20px;padding:0;border-radius:var(--size-radius-sm);border:none;background:var(--bf-color-status-danger-content);color:var(--bf-color-action-primary-content);cursor:pointer;flex-shrink:0;transition:all var(--motion-fast) var(--easing-standard);margin-left:auto;box-shadow:0 1px 4px var(--bf-color-status-danger-border)}.chat-tool-card__cancel:active{transform:scale(.9)}.chat-tool-card__cancel svg{flex-shrink:0}.chat-tool-card__expanded{border-top:1px solid var(--bf-color-border-subtle);padding:var(--size-gap-2) var(--size-gap-3);font-size:var(--font-size-xs);color:var(--bf-color-content-muted);max-height:200px;overflow-y:auto;font-family:var(--font-family-mono);line-height:var(--line-height-relaxed);white-space:pre-wrap;word-break:break-all}.chat-task-card{border-radius:var(--size-radius-lg);border:1px solid var(--bf-color-border-default);background:color-mix(in srgb,var(--bf-color-surface-panel) 60%,transparent);-webkit-backdrop-filter:var(--bf-effect-blur-base);backdrop-filter:var(--bf-effect-blur-base);overflow:hidden;width:100%}.chat-task-card--running{border-color:var(--bf-color-status-warning-border)}.chat-task-card--done{border-color:var(--bf-color-status-success-border)}.chat-task-card--error{border-color:var(--bf-color-status-danger-border)}.chat-task-card--pending{border-color:var(--bf-color-status-warning-border)}.chat-task-card__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);min-height:36px}.chat-task-card__summary{display:flex;align-items:center;gap:var(--size-gap-2);padding:4px var(--size-gap-3);border-top:1px solid var(--bf-color-border-subtle);min-height:24px;cursor:pointer;transition:background var(--motion-fast) var(--easing-standard)}.chat-task-card__summary:active{background:var(--bf-color-surface-subtle)}.chat-task-card__chevron{display:flex;align-items:center;color:var(--bf-color-content-muted);transition:transform var(--motion-fast) var(--easing-standard);flex-shrink:0}.chat-task-card__chevron.is-expanded{transform:rotate(180deg)}.chat-task-card__stat{font-size:11px;font-weight:var(--font-weight-medium);color:var(--bf-color-content-muted)}.chat-task-card__stat-right{display:flex;gap:var(--size-gap-2);margin-left:auto}.chat-task-card__stat--done{font-size:11px;color:var(--bf-color-status-success-content);font-variant-numeric:tabular-nums}.chat-task-card__stat--running{font-size:11px;color:var(--bf-color-status-warning-content);font-variant-numeric:tabular-nums}.chat-task-card__steps{border-top:1px solid var(--bf-color-border-subtle);max-height:140px;overflow-y:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scroll-behavior:smooth;padding:var(--size-gap-1) var(--size-gap-3);mask-image:linear-gradient(to bottom,transparent 0px,black 8px,black 100%);-webkit-mask-image:linear-gradient(to bottom,transparent 0px,black 8px,black 100%)}.chat-task-card__steps::-webkit-scrollbar{width:3px}.chat-task-card__steps::-webkit-scrollbar-track{background:transparent}.chat-task-card__steps::-webkit-scrollbar-thumb{background:var(--bf-color-content-muted);border-radius:2px;opacity:.4}.chat-task-card__step{display:flex;align-items:center;gap:var(--size-gap-2);padding:3px 0;font-size:11px;color:var(--bf-color-content-muted);min-height:22px}.chat-task-card__step svg{flex-shrink:0}.chat-task-card__step--thinking{color:var(--bf-color-content-muted);opacity:.7}.chat-task-card__step--thinking svg{transform:rotate(-90deg)}.chat-task-card__step-spinner{display:inline-block;width:10px;height:10px;border:1.5px solid var(--bf-color-status-warning-border);border-top-color:var(--bf-color-status-warning-content);border-radius:50%;animation:spin .7s linear infinite;flex-shrink:0}.chat-task-card__step-name{font-weight:var(--font-weight-medium);color:var(--bf-color-content-secondary);flex-shrink:0}.chat-task-card__step-preview{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--bf-color-content-muted)}.chat-task-card__step-duration{flex-shrink:0;font-variant-numeric:tabular-nums;font-family:var(--font-family-mono);color:var(--bf-color-content-muted)}.chat-ask-card{border:1px solid var(--bf-color-border-default);border-radius:var(--size-radius-lg);background:color-mix(in srgb,var(--bf-color-surface-panel) 80%,transparent);-webkit-backdrop-filter:var(--bf-effect-blur-base);backdrop-filter:var(--bf-effect-blur-base);overflow:hidden;width:100%}.chat-ask-card__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);border-bottom:1px solid var(--bf-color-border-subtle)}.chat-ask-card__count{font-size:12px;font-weight:var(--font-weight-medium);color:var(--bf-color-content-secondary);flex:1}.chat-ask-card__submit{display:inline-flex;align-items:center;gap:4px;padding:4px 10px;border-radius:var(--size-radius-base);border:1px solid var(--bf-color-accent-default);background:transparent;color:var(--bf-color-accent-default);font-size:12px;font-weight:var(--font-weight-medium);cursor:pointer;transition:all var(--motion-fast) var(--easing-standard)}.chat-ask-card__submit:disabled{opacity:.4;cursor:not-allowed}.chat-ask-card__submit:not(:disabled):active{background:var(--bf-color-accent-surface)}.chat-ask-card__submit--bottom{width:100%;justify-content:center;padding:10px;margin-top:8px;font-size:13px}.chat-ask-card__waiting{display:inline-flex;align-items:center;gap:4px;font-size:11px;color:var(--bf-color-status-warning-content)}.chat-ask-card__waiting:before{content:"";display:inline-block;width:6px;height:6px;border-radius:50%;background:var(--bf-color-status-warning-content);animation:pulse-dot 1.4s ease-in-out infinite}@keyframes pulse-dot{0%,to{opacity:.4}50%{opacity:1}}.chat-ask-card__question{padding:var(--size-gap-2) var(--size-gap-3)}.chat-ask-card__question+.chat-ask-card__question{border-top:1px solid var(--bf-color-border-subtle)}.chat-ask-card__question-header{display:flex;align-items:baseline;gap:var(--size-gap-2);margin-bottom:var(--size-gap-2)}.chat-ask-card__tag{display:inline-flex;padding:1px 6px;border-radius:var(--size-radius-sm);font-size:11px;font-weight:var(--font-weight-medium);background:var(--bf-color-accent-surface);color:var(--bf-color-accent-default);flex-shrink:0}.chat-ask-card__question-text{font-size:13px;color:var(--bf-color-content-primary);font-weight:var(--font-weight-medium)}.chat-ask-card__options{display:flex;flex-direction:column;gap:var(--size-gap-1)}.chat-ask-card__option{display:flex;align-items:center;gap:var(--size-gap-2);padding:8px 10px;border-radius:var(--size-radius-base);border:1px solid var(--bf-color-border-default);background:var(--bf-color-surface-scene);cursor:pointer;text-align:left;width:100%;transition:all var(--motion-fast) var(--easing-standard)}.chat-ask-card__option:active:not(:disabled){background:var(--bf-color-surface-panel)}.chat-ask-card__option.is-selected{border-color:var(--bf-color-accent-default);background:color-mix(in srgb,var(--bf-color-accent-surface) 40%,transparent)}.chat-ask-card__option:disabled{opacity:.6;cursor:not-allowed}.chat-ask-card__radio{display:flex;align-items:center;justify-content:center;width:16px;height:16px;border-radius:50%;border:1.5px solid var(--bf-color-content-muted);flex-shrink:0;color:var(--bf-color-accent-default);transition:all var(--motion-fast) var(--easing-standard)}.is-selected .chat-ask-card__radio{border-color:var(--bf-color-accent-default);background:var(--bf-color-accent-default);color:var(--bf-color-action-primary-content)}.chat-ask-card__radio--multi{border-radius:3px}.chat-ask-card__option-label{font-size:13px;color:var(--bf-color-content-primary);font-weight:var(--font-weight-medium);flex-shrink:0}.chat-ask-card__option-desc{font-size:11px;color:var(--bf-color-content-muted);flex:1;text-align:right}.chat-ask-card__custom-input{width:100%;padding:6px 10px;border-radius:var(--size-radius-base);border:1px solid var(--bf-color-border-default);background:var(--bf-color-surface-scene);color:var(--bf-color-content-primary);font-size:13px;outline:none}.chat-ask-card__custom-input:focus{border-color:var(--bf-color-accent-default)}.chat-ask-card__custom-input:disabled{opacity:.5}.chat-todo-card{border-radius:var(--size-radius-base);border:1px solid var(--bf-color-border-default);background:var(--bf-color-surface-scene);overflow:hidden;width:100%}.chat-todo-card__header{display:flex;align-items:center;gap:var(--size-gap-2);padding:var(--size-gap-2) var(--size-gap-3);cursor:pointer;min-height:36px;transition:background var(--motion-fast) var(--easing-standard)}.chat-todo-card__header:active{background:var(--bf-color-surface-subtle)}.chat-todo-card__icon{display:flex;align-items:center;color:var(--bf-color-accent-default);flex-shrink:0}.chat-todo-card__current{flex:1;min-width:0;font-size:var(--font-size-xs);color:var(--bf-color-content-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-todo-card__current--done{color:var(--bf-color-status-success-content);font-weight:var(--font-weight-medium)}.chat-todo-card__right{display:flex;align-items:center;gap:var(--size-gap-2);flex-shrink:0;margin-left:auto}.chat-todo-card__dots{display:flex;align-items:center;gap:3px;flex-shrink:0}.chat-todo-card__dot{width:6px;height:6px;border-radius:50%;transition:all var(--motion-fast) var(--easing-standard)}.chat-todo-card__dot--completed{background:var(--bf-color-status-success-content)}.chat-todo-card__dot--in_progress{background:var(--bf-color-accent-default);animation:todoPulse 1.4s ease-in-out infinite}.chat-todo-card__dot--pending{background:var(--bf-color-content-muted);opacity:.3}.chat-todo-card__dot--cancelled{background:var(--bf-color-status-danger-content);opacity:.5}@keyframes todoPulse{0%,to{opacity:.5;transform:scale(1)}50%{opacity:1;transform:scale(1.3)}}.chat-todo-card__stats{font-size:11px;font-weight:var(--font-weight-medium);color:var(--bf-color-content-muted);font-variant-numeric:tabular-nums;flex-shrink:0}.chat-todo-card__chevron{display:flex;align-items:center;color:var(--bf-color-content-muted);transition:transform var(--motion-fast) var(--easing-standard);flex-shrink:0}.chat-todo-card__chevron.is-expanded{transform:rotate(180deg)}.chat-todo-card__list{border-top:1px solid var(--bf-color-border-subtle);padding:var(--size-gap-2) var(--size-gap-3);display:flex;flex-direction:column;gap:var(--size-gap-1)}.chat-todo-card__item{display:flex;align-items:flex-start;gap:var(--size-gap-2);padding:4px 0}.chat-todo-card__item svg{flex-shrink:0;margin-top:1px}.chat-todo-card__item--completed{opacity:.6}.chat-todo-card__item--cancelled{opacity:.4}.chat-todo-card__item-text{font-size:var(--font-size-xs);color:var(--bf-color-content-primary);line-height:var(--line-height-base)}.chat-todo-card__item--in_progress .chat-todo-card__item-text{color:var(--bf-color-accent-default);font-weight:var(--font-weight-medium)}.chat-thinking{display:flex;flex-direction:column;width:100%}.chat-thinking__toggle{display:inline-flex;align-items:center;gap:6px;background:none;border:none;color:var(--bf-color-content-muted);font-size:var(--font-size-xs);cursor:pointer;padding:3px 0;text-align:left}.chat-thinking__toggle:active{opacity:.7}.chat-thinking__chevron{display:inline-flex;align-items:center;transition:transform var(--motion-fast) var(--easing-standard)}.chat-thinking__chevron.is-open{transform:rotate(90deg)}.chat-thinking__label{color:var(--bf-color-content-muted);font-style:italic;font-size:var(--font-size-xs)}.chat-thinking__expand-container{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--motion-base) var(--easing-standard)}.chat-thinking__expand-container.is-expanded{grid-template-rows:1fr}.chat-thinking__expand-inner{overflow:hidden}.chat-thinking__content-wrapper{position:relative;max-height:300px;overflow-y:auto;-webkit-overflow-scrolling:touch}.chat-thinking__content-wrapper:before,.chat-thinking__content-wrapper:after{content:"";position:sticky;left:0;right:0;height:24px;z-index:1;pointer-events:none;display:block}.chat-thinking__content-wrapper:before{top:0;background:linear-gradient(to bottom,var(--bf-color-surface-scene),transparent)}.chat-thinking__content-wrapper:after{bottom:0;background:linear-gradient(to top,var(--bf-color-surface-scene),transparent)}.chat-thinking__content-wrapper.at-top:before{display:none}.chat-thinking__content-wrapper.at-bottom:after{display:none}.chat-thinking__content{padding:var(--size-gap-2) 0;font-size:var(--font-size-xs);color:var(--bf-color-content-muted);line-height:var(--line-height-relaxed)}.chat-thinking__content p{margin-bottom:6px}.chat-thinking__content p:last-child{margin-bottom:0}.chat-thinking__content code{background:var(--bf-color-action-neutral-surface-hover);padding:1px 4px;border-radius:3px;font-size:11px;font-family:var(--font-family-mono)}.chat-thinking--streaming .chat-thinking__label:after{content:"";display:inline-block;width:4px;height:12px;background:var(--bf-color-content-muted);margin-left:4px;animation:pulse 1s ease-in-out infinite;vertical-align:middle;border-radius:1px}.chat-page__input-wrap{position:fixed;bottom:16px;left:50%;transform:translate(-50%);width:100%;max-width:700px;z-index:20;display:flex;justify-content:center;padding:0 8px;transition:max-width .3s cubic-bezier(.4,0,.2,1),padding .3s cubic-bezier(.4,0,.2,1)}.chat-page__input-wrap:not(.is-expanded){max-width:480px}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-box{min-height:42px;max-height:42px;padding:0 8px 0 20px;border-radius:21px;border:1px solid var(--bf-color-border-subtle);flex-direction:row;align-items:center;gap:8px;cursor:pointer;box-shadow:var(--bf-shadow-lg)}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-box:active{background:var(--bf-color-surface-raised);box-shadow:var(--bf-shadow-xl);transform:translateY(-1px)}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-area{flex:1 1 auto;min-height:auto;min-width:0}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-actions-left{display:none}.chat-page__input-wrap:not(.is-expanded) .chat-page__input-actions{flex-shrink:0;padding:0;height:auto}.chat-page__input-wrap:not(.is-expanded) .chat-page__action-btn{display:none}.chat-page__input-wrap:not(.is-expanded) .chat-page__send-btn{width:24px;height:24px;opacity:.35}.chat-page__input-wrap.is-expanded .chat-page__input-box{border-radius:12px;padding:12px 8px 0;border:1px solid var(--bf-color-border-default);flex-direction:column;gap:0}.chat-page__input-box{position:relative;width:100%;display:flex;pointer-events:auto;background:var(--bf-color-surface-tertiary);backdrop-filter:blur(16px) saturate(1.2);-webkit-backdrop-filter:blur(16px) saturate(1.2);transition:border-radius .3s cubic-bezier(.4,0,.2,1),padding .3s cubic-bezier(.4,0,.2,1),min-height .3s cubic-bezier(.4,0,.2,1),max-height .3s cubic-bezier(.4,0,.2,1),box-shadow .3s cubic-bezier(.4,0,.2,1),border-color .3s cubic-bezier(.4,0,.2,1),background .3s cubic-bezier(.4,0,.2,1);box-shadow:var(--bf-shadow-xl)}.chat-page__input-area{position:relative;display:flex;align-items:flex-start;flex:1 1 auto;min-width:0;width:100%;min-height:40px}.chat-page__input{width:100%;background:transparent;border:none;color:var(--bf-color-content-primary);font-size:14px;padding:0 28px 0 0;resize:none;min-height:36px;max-height:120px;outline:none;font-family:var(--font-family-sans);line-height:1.5}.chat-page__input::placeholder{color:var(--bf-color-content-primary);opacity:.6}.chat-page__input:disabled{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.chat-page__input-placeholder{display:block;width:100%;min-width:0;font-size:14px;color:var(--bf-color-content-primary);opacity:.6;line-height:24px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-page__input-actions{display:flex;align-items:flex-end;justify-content:space-between;gap:8px;min-width:0;min-height:24px;padding:0 0 7px}.chat-page__input-actions-left{display:flex;align-items:center;gap:8px;flex:1;min-width:0}.chat-page__input-actions-right{display:flex;align-items:flex-end;gap:6px;margin-left:auto;flex-shrink:0}.chat-model-selector{position:relative;flex-shrink:0}.chat-model-selector__trigger{display:inline-flex;align-items:center;gap:4px;min-width:0;height:24px;padding:0 8px;border:none;border-radius:12px;background:var(--bf-color-surface-subtle);color:var(--bf-color-content-secondary);cursor:pointer;transition:all .2s ease}.chat-model-selector__trigger:active:not(:disabled),.chat-model-selector__trigger--open{background:var(--bf-color-accent-surface);color:var(--bf-color-content-primary)}.chat-model-selector__trigger:disabled{opacity:var(--bf-opacity-disabled);cursor:not-allowed}.chat-model-selector__icon,.chat-model-selector__thinking,.chat-model-selector__chevron{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0}.chat-model-selector__icon,.chat-model-selector__chevron{color:var(--bf-color-content-muted)}.chat-model-selector__thinking{color:var(--bf-color-accent-secondary)}.chat-model-selector__name{max-width:96px;display:inline-flex;align-items:center;gap:4px;min-width:0}.chat-model-selector__name-text{min-width:0;flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:9px;letter-spacing:.3px}.chat-model-selector__effort{display:inline-flex;align-items:center;justify-content:center;padding:1px 4px;border-radius:4px;background:var(--bf-color-status-success-surface);color:var(--bf-color-status-success-content);font-size:7px;font-weight:600;line-height:1;text-transform:uppercase}.chat-model-selector__dropdown{position:absolute;bottom:calc(100% + 8px);left:0;width:180px;max-width:180px;max-height:min(345px,100vh - 160px);display:flex;flex-direction:column;overflow:hidden;border:1px solid var(--bf-color-border-subtle);border-radius:10px;background:var(--bf-color-surface-raised);box-shadow:var(--bf-shadow-xl);backdrop-filter:blur(18px) saturate(1.15);-webkit-backdrop-filter:blur(18px) saturate(1.15);z-index:30}.chat-model-selector__header{padding:10px 12px 8px;font-size:10px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--bf-color-content-muted);border-bottom:1px solid var(--bf-color-border-subtle)}.chat-model-selector__divider{height:1px;margin:4px 12px;background:var(--bf-color-border-subtle)}.chat-model-selector__list{flex:1 1 auto;min-height:0;max-height:none;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;-webkit-overflow-scrolling:touch}.chat-model-selector__option{width:100%;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 12px;border:none;background:transparent;color:inherit;text-align:left;cursor:pointer;transition:background .15s ease}.chat-model-selector__option:active,.chat-model-selector__option.is-selected{background:var(--bf-color-surface-subtle)}.chat-model-selector__option-main{display:flex;flex-direction:column;gap:2px;min-width:0;width:100%;flex:1;overflow:hidden}.chat-model-selector__option-name{display:flex;align-items:center;gap:.5em;min-width:0;max-width:100%;width:100%;font-size:11px;font-weight:500;color:var(--bf-color-content-primary)}.chat-model-selector__option-name-text{flex:0 1 auto;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-model-selector__option-thinking{color:var(--bf-color-accent-secondary);font-size:9px;flex-shrink:0}.chat-model-selector__option-meta{display:block;min-width:0;max-width:100%;font-size:9px;color:var(--bf-color-content-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-model-selector__option-meta--stacked{display:flex;flex-direction:column;gap:1px;white-space:normal}.chat-model-selector__option-meta-line{display:block;min-width:0;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.chat-reasoning-selector__trigger{max-width:112px}.chat-reasoning-selector__name{max-width:68px}.chat-reasoning-selector__dropdown{width:160px;max-width:min(160px,100vw - 32px)}.chat-page__action-btn{flex-shrink:0;width:24px;height:24px;border-radius:50%;border:none;background:transparent;color:var(--bf-color-content-secondary);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;padding:0}.chat-page__action-btn:active:not(:disabled){background:var(--bf-color-action-neutral-surface);color:var(--bf-color-content-primary)}.chat-page__action-btn:disabled{opacity:.4;cursor:not-allowed}.chat-page__send-btn{position:relative;width:24px;height:24px;border-radius:50%;border:1px solid var(--bf-color-accent-border-subtle);background:var(--bf-color-accent-surface-strong);color:var(--bf-color-accent-border-subtle);display:inline-flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;flex-shrink:0}.chat-page__send-btn:not(:disabled){background:var(--bf-color-accent-default);border:1px solid var(--bf-color-accent-hover);color:var(--bf-color-action-primary-content);box-shadow:var(--bf-shadow-sm)}.chat-page__send-btn:active:not(:disabled){transform:scale(.92)}.chat-page__send-btn:disabled{background:var(--bf-color-accent-surface);border-color:var(--bf-color-accent-surface-strong);color:var(--bf-color-accent-border);opacity:.35;cursor:default;box-shadow:none}.chat-page__send-btn.is-stop{background:var(--bf-color-status-danger-content)!important;border-color:var(--bf-color-status-danger-content)!important;color:var(--bf-color-action-primary-content)!important;opacity:1!important;box-shadow:var(--bf-shadow-sm)}.chat-page__send-btn.is-stop:active{transform:scale(.92)}.chat-page__stream-actions{display:inline-flex;align-items:center;gap:6px;flex-shrink:0}.chat-page__image-preview-row{display:flex;gap:8px;padding:0;min-width:0;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}.chat-page__image-thumb{position:relative;width:46px;height:46px;border-radius:6px;overflow:hidden;flex-shrink:0;border:1px solid var(--bf-color-border-subtle)}.chat-page__image-thumb img{width:100%;height:100%;object-fit:cover}.chat-page__image-remove{position:absolute;top:2px;right:2px;width:16px;height:16px;border-radius:50%;background:var(--bf-color-overlay-scrim);color:var(--bf-color-content-on-dark);border:none;font-size:11px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0}.chat-msg__typing{display:inline-flex;gap:4px;align-items:center;padding:4px 0}.chat-msg__typing span{display:inline-block;width:5px;height:5px;background:var(--bf-color-content-muted);border-radius:50%;animation:typing-bounce 1.2s ease-in-out infinite}.chat-msg__typing span:nth-child(2){animation-delay:.15s}.chat-msg__typing span:nth-child(3){animation-delay:.3s}.chat-msg__assistant-content{color:var(--bf-color-content-primary);line-height:var(--line-height-relaxed);font-family:var(--font-family-sans);font-size:var(--font-size-sm);word-wrap:break-word;overflow-wrap:break-word;max-width:100%;width:100%;margin:0;padding:0;text-align:left}.chat-msg__assistant-content>*:first-child{margin-top:0!important}.chat-msg__assistant-content>*:last-child{margin-bottom:0!important}.chat-msg__assistant-content>*+*{margin-top:.25rem}.chat-msg__assistant-content ul+*,.chat-msg__assistant-content ol+*{margin-top:.5rem}.chat-msg__assistant-content p+ul,.chat-msg__assistant-content p+ol{margin-top:.25rem}.chat-msg__assistant-content p+p{margin-top:.25rem}.chat-msg__assistant-content li+li{margin-top:.05rem}.chat-msg__assistant-content li>*{margin-top:0;margin-bottom:.05rem}.chat-msg__assistant-content li>*:last-child{margin-bottom:0}.chat-msg__assistant-content p{margin-top:0;margin-bottom:.5rem;display:block;line-height:1.5;font-size:var(--font-size-sm);color:var(--bf-color-content-primary)}.chat-msg__assistant-content p:last-child{margin-bottom:0}.chat-msg__assistant-content p code{display:inline!important}.chat-msg__assistant-content h1,.chat-msg__assistant-content h2,.chat-msg__assistant-content h3,.chat-msg__assistant-content h4,.chat-msg__assistant-content h5,.chat-msg__assistant-content h6{font-family:var(--font-family-sans);color:var(--bf-color-content-primary);margin-top:1.25rem;margin-bottom:.6rem;font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);letter-spacing:.015em}.chat-msg__assistant-content h1:first-child,.chat-msg__assistant-content h2:first-child,.chat-msg__assistant-content h3:first-child,.chat-msg__assistant-content h4:first-child,.chat-msg__assistant-content h5:first-child,.chat-msg__assistant-content h6:first-child{margin-top:0}.chat-msg__assistant-content h1{font-size:var(--font-size-xl);margin:1.25rem 0 .75rem;padding-bottom:.5rem;border-bottom:1px solid var(--bf-color-border-subtle)}.chat-msg__assistant-content h2{font-size:var(--font-size-lg);margin:1rem 0 .6rem;padding-bottom:.35rem;border-bottom:1px solid var(--bf-color-border-subtle)}.chat-msg__assistant-content h3{font-size:var(--font-size-base);margin:.85rem 0 .5rem}.chat-msg__assistant-content h4{font-size:var(--font-size-sm);margin:.7rem 0 .4rem;color:var(--bf-color-content-secondary)}.chat-msg__assistant-content h5{font-size:var(--font-size-sm);margin:.6rem 0 .4rem;color:var(--bf-color-content-secondary)}.chat-msg__assistant-content h6{font-size:var(--font-size-xs);margin:.5rem 0 .35rem;color:var(--bf-color-content-muted);opacity:.85}.chat-msg__assistant-content ul,.chat-msg__assistant-content ol{margin-top:0;margin-bottom:.5rem;padding-left:1.5rem;line-height:1.5;font-size:var(--font-size-sm)}.chat-msg__assistant-content li{word-wrap:break-word;margin-bottom:.1rem;position:relative;line-height:1.5;color:var(--bf-color-content-primary)}.chat-msg__assistant-content li:last-child{margin-bottom:0}.chat-msg__assistant-content li p{margin-top:0;margin-bottom:.1rem}.chat-msg__assistant-content li p:last-child{margin-bottom:0}.chat-msg__assistant-content ul>li::marker{color:var(--bf-color-content-muted);font-size:1.2em;font-weight:700}.chat-msg__assistant-content ol>li::marker{color:var(--bf-color-content-muted);font-weight:700}.chat-msg__assistant-content ul ul,.chat-msg__assistant-content ol ol,.chat-msg__assistant-content ul ol,.chat-msg__assistant-content ol ul{margin-top:.1rem;margin-bottom:0;padding-left:1.2rem}.chat-msg__assistant-content ul:has(>li>.file-card){list-style:none;padding-left:0}.chat-msg__assistant-content ul:has(>li>.file-card)>li{margin-bottom:var(--size-gap-2)}.chat-msg__assistant-content ul:has(>li>.file-card)>li:last-child{margin-bottom:0}.chat-msg__assistant-content .inline-code{padding:.15em .35em;margin:0 .05em;font-size:.85em;background:var(--bf-color-action-neutral-surface-hover);border:1px solid var(--bf-color-border-subtle);border-radius:4px;font-family:var(--font-family-mono);white-space:nowrap;vertical-align:baseline;line-height:1.4;color:var(--bf-color-content-primary);font-weight:500}.chat-msg__assistant-content pre code,.chat-msg__assistant-content pre>.inline-code{padding:0;margin:0;background:transparent;border:none;border-radius:0;font-size:inherit;font-weight:inherit;white-space:pre;display:block;color:inherit}.chat-msg__assistant-content .code-block-wrapper{margin:.5rem 0;border-radius:var(--size-radius-base);background:var(--bf-color-surface-canvas);border:1px dashed var(--bf-color-border-subtle);box-shadow:var(--bf-shadow-sm);overflow:hidden;position:relative}.chat-msg__assistant-content .code-block-wrapper pre[class*=language-]{margin:0!important;border:none!important;border-radius:var(--size-radius-base)!important;padding:1rem!important;background:var(--bf-color-surface-canvas)!important;box-shadow:none!important;font-size:.75rem!important}.chat-msg__assistant-content .code-block-wrapper pre code{font-family:var(--font-family-mono)!important;background:var(--bf-color-surface-canvas)!important;font-size:.75rem!important}.chat-msg__assistant-content .code-block-wrapper pre[style]{background:var(--bf-color-surface-canvas)!important;border:none!important;box-shadow:none!important}.chat-msg__assistant-content .code-block-wrapper code[style]{background:var(--bf-color-surface-canvas)!important;border:none!important}.chat-msg__assistant-content .copy-button{position:absolute;top:.5rem;right:.5rem;padding:.4rem;background:transparent;border:none;border-radius:6px;color:var(--bf-color-content-muted);cursor:pointer;display:flex;align-items:center;justify-content:center;width:28px;height:28px;opacity:.6;z-index:10;transition:all .2s ease}.chat-msg__assistant-content .copy-button:active{opacity:1;background:var(--bf-color-action-neutral-surface)}.chat-msg__assistant-content .copy-button.copy-success{color:var(--bf-color-status-success-content);opacity:1}.chat-msg__assistant-content pre{padding:1rem;overflow-x:auto;-webkit-overflow-scrolling:touch;font-size:.75rem;line-height:1.5;background:var(--bf-color-surface-canvas);border:1px dashed var(--bf-color-border-subtle);border-radius:var(--size-radius-base);margin:.5rem 0;box-shadow:var(--bf-shadow-sm);position:relative}.chat-msg__assistant-content pre code{background:none;padding:0;font-size:var(--font-size-xs)}.chat-msg__assistant-content pre:has(.code-block-wrapper){padding:0!important;background:transparent!important;border:none!important;border-radius:0!important;margin:.5rem 0!important;box-shadow:none!important;position:static!important}.chat-msg__assistant-content blockquote,.chat-msg__assistant-content .custom-blockquote{font-style:italic;margin:1rem 0;padding:.75rem 1rem;position:relative;background:var(--bf-color-accent-surface-subtle);border-left:3px solid var(--bf-color-accent-border);border-radius:0 var(--size-radius-sm) var(--size-radius-sm) 0;color:var(--bf-color-content-muted)}.chat-msg__assistant-content blockquote>:first-child,.chat-msg__assistant-content .custom-blockquote>:first-child{margin-top:0}.chat-msg__assistant-content blockquote>:last-child,.chat-msg__assistant-content .custom-blockquote>:last-child{margin-bottom:0}.chat-msg__assistant-content blockquote p,.chat-msg__assistant-content .custom-blockquote p{margin:.3rem 0}.chat-msg__assistant-content .table-wrapper{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:1rem 0;border-radius:var(--size-radius-base);border:1px solid var(--bf-color-border-subtle);box-shadow:var(--bf-shadow-sm);background:var(--bf-color-surface-canvas)}.chat-msg__assistant-content .table-wrapper table{border-spacing:0;border-collapse:collapse;width:100%;font-size:var(--font-size-xs)}.chat-msg__assistant-content .table-wrapper th,.chat-msg__assistant-content .table-wrapper td{padding:8px 12px;border-bottom:1px solid var(--bf-color-border-subtle);text-align:left}.chat-msg__assistant-content .table-wrapper th{font-weight:var(--font-weight-semibold);background:var(--bf-color-surface-subtle);color:var(--bf-color-content-primary);white-space:nowrap}.chat-msg__assistant-content .table-wrapper td{color:var(--bf-color-content-primary)}.chat-msg__assistant-content .table-wrapper th:first-child{border-radius:var(--size-radius-base) 0 0 0}.chat-msg__assistant-content .table-wrapper th:last-child{border-radius:0 var(--size-radius-base) 0 0}.chat-msg__assistant-content .table-wrapper tr:last-child td:first-child{border-radius:0 0 0 var(--size-radius-base)}.chat-msg__assistant-content .table-wrapper tr:last-child td:last-child{border-radius:0 0 var(--size-radius-base) 0}.chat-msg__assistant-content .table-wrapper tr:last-child td{border-bottom:none}.chat-msg__assistant-content .table-wrapper tbody tr:nth-child(2n){background:var(--bf-color-surface-subtle)}.chat-msg__assistant-content a{color:var(--bf-color-accent-default);text-decoration:none;word-break:break-all}.chat-msg__assistant-content a:active{text-decoration:underline}.chat-msg__assistant-content hr{height:1px;padding:0;margin:1.5rem 0;background:var(--bf-color-border-subtle);border:0;border-radius:1px}.chat-msg__assistant-content strong{font-weight:var(--font-weight-semibold);color:var(--bf-color-content-primary)}.chat-msg__assistant-content em{font-style:italic;color:var(--bf-color-content-secondary)}.chat-msg__assistant-content del{text-decoration:line-through;color:var(--bf-color-content-muted)}.chat-msg__assistant-content input[type=checkbox]{margin-right:6px;accent-color:var(--bf-color-accent-default)} diff --git a/src/apps/relay-server/static/index.html b/src/apps/relay-server/static/index.html index b647e9d781..17a4f7eb81 100644 --- a/src/apps/relay-server/static/index.html +++ b/src/apps/relay-server/static/index.html @@ -3,7 +3,7 @@ - + @@ -12,11 +12,9 @@ - - + +
diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/SKILL.md b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/SKILL.md index 12c7e68790..05f3dd981d 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/SKILL.md +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/SKILL.md @@ -29,7 +29,7 @@ python scripts/bitfun_appearance.py contract list renderers python scripts/bitfun_appearance.py contract show components python scripts/bitfun_appearance.py contract show scenes python scripts/bitfun_appearance.py contract properties -python scripts/bitfun_appearance.py contract tokens css +python scripts/bitfun_appearance.py contract tokens theme python scripts/bitfun_appearance.py contract tokens widget ``` diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/references/style-playbook.md b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/references/style-playbook.md index 846fe16587..9b9e3335f0 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/references/style-playbook.md +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/references/style-playbook.md @@ -97,21 +97,21 @@ For the default cold cinematic fallback, representative generated values are: ```json { - "--bf-appearance-token-color-bg-scene": "rgba(8, 17, 31, 0.08)", - "--bf-appearance-token-color-bg-elevated": "rgba(24, 43, 60, 0.72)", - "--bf-appearance-token-element-bg-subtle": "rgba(11, 25, 40, 0.52)", - "--bf-appearance-token-element-bg-soft": "rgba(16, 34, 53, 0.60)", - "--bf-appearance-token-element-bg-base": "rgba(22, 43, 61, 0.66)", - "--bf-appearance-token-element-bg-hover": "rgba(23, 54, 74, 0.74)", - "--bf-appearance-token-border-subtle": "rgba(82, 229, 245, 0.08)", - "--bf-appearance-token-border-base": "rgba(82, 229, 245, 0.12)", - "--bf-appearance-token-border-medium": "rgba(82, 229, 245, 0.18)" + "--bf-color-surface-scene": "rgba(8, 17, 31, 0.08)", + "--bf-color-surface-raised": "rgba(24, 43, 60, 0.72)", + "--bf-color-surface-subtle": "rgba(11, 25, 40, 0.52)", + "--bf-color-action-quiet-hover": "rgba(16, 34, 53, 0.60)", + "--bf-color-action-neutral-surface": "rgba(22, 43, 61, 0.66)", + "--bf-color-action-neutral-surface-pressed": "rgba(23, 54, 74, 0.74)", + "--bf-color-border-subtle": "rgba(82, 229, 245, 0.08)", + "--bf-color-border-default": "rgba(82, 229, 245, 0.12)", + "--bf-color-border-strong": "rgba(82, 229, 245, 0.18)" } ``` Tune the RGB values to the source palette while preserving the alpha hierarchy. -Insights report cards currently derive their local surfaces from `color-bg-elevated` and element/border tokens. They do not expose individual registered Parts. Keep `insights.content` transparent and use these tokens for glass-card behavior. +Insights report cards currently derive their local surfaces from `--bf-color-surface-raised` and canonical action/border tokens. They do not expose individual registered Parts. Keep `insights.content` transparent and use these tokens for glass-card behavior. ## Runtime failure diagnosis @@ -121,7 +121,7 @@ Insights report cards currently derive their local surfaces from `color-bg-eleva | in-app floating mini-chat has no artwork | host `background` shorthand reset the asset | add override to the panel and transparent inner chat owners | | main video is hidden | `workbench.workspace` or another scene owner still paints an opaque background | make the registered workspace and structural scene owners transparent; keep the video only in top-level `backgroundMedia` | | main video shows a still image | reduced motion is enabled or video playback/codec validation failed | confirm OS/browser motion preference, inspect import errors, and use WebM VP9 with `preview.webp` as poster | -| collapsed navigation has an opaque 80x40 block | child `nav-bar.root` paints `color-bg-primary` | force the base root transparent and use a low-alpha collapsed-state glass material | +| collapsed navigation has an opaque 80x40 block | child `nav-bar.root` paints `--bf-color-surface-canvas` | force the base root transparent and use a low-alpha collapsed-state glass material | | collapsed navigation looks like a pasted image tile | `sidebar.webp` was applied to the small `workbench.collapsedNav` owner | remove the image, keep the scene owner transparent, and let the collapsed `nav-bar.root` provide quiet glass contrast | | whole Insights history has an image | artwork was applied to `insights.content` | make content transparent; style cards through tokens | | archived sessions or shortcuts are opaque | specialized ConfigPage root replaced the generic `config.root` attribute | override the specialized root Part directly | diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/references/surface-plan.json b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/references/surface-plan.json index 6bc99bc3ed..348ae83ccc 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/references/surface-plan.json +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/references/surface-plan.json @@ -3,7 +3,7 @@ "schemaVersion": 1, "scope": "example-style-selection", "styleId": "cinematic-animated-wallpaper", - "validatedAgainstRegistryRevision": "19b5c2f96bb9f9eb7b83f6c9c7df0568dae4b153", + "validatedAgainstRegistryRevision": "68a853e10a3e2c18d85a3f5fca29bc09b4e8313d", "scenes": { "workbench": { "parts": { diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/scripts/cinematic_recipe.py b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/scripts/cinematic_recipe.py index 91cb65c591..231fea87a8 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/scripts/cinematic_recipe.py +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/examples/cinematic-animated-wallpaper/scripts/cinematic_recipe.py @@ -96,11 +96,6 @@ def rgba(value: str, alpha: float, spaced: bool = True) -> str: return f"rgba({red}{separator}{green}{separator}{blue}{separator}{alpha:.2f})" -def rgb_triplet(value: str, spaced: bool = True) -> str: - separator = ", " if spaced else "," - return separator.join(str(channel) for channel in hex_rgb(value)) - - def resolve_palette_values(value: Any, colors: Mapping[str, str]) -> Any: if isinstance(value, dict): if value.get("kind") == "palette": @@ -216,49 +211,63 @@ def build_renderers(colors: Mapping[str, str], appearance_id: str) -> dict[str, surface = colors["surface"] elevated = colors["surfaceElevated"] accent = colors["accent"] + theme_tokens = { + "--bf-color-surface-canvas": rgba(background, 0.78), + "--bf-color-surface-panel": rgba(surface, 0.72), + "--bf-color-surface-tertiary": rgba(elevated, 0.76), + "--bf-color-surface-raised": rgba(elevated, 0.74), + "--bf-color-surface-scene": rgba(background, 0.08), + "--bf-color-surface-workbench": rgba(background, 0.08), + "--bf-color-surface-chrome": rgba(background, 0.18), + "--bf-color-surface-subtle": rgba(surface, 0.50), + "--bf-color-action-quiet-hover": rgba(surface, 0.58), + "--bf-color-action-neutral-surface": rgba(elevated, 0.66), + "--bf-color-action-neutral-surface-hover": rgba(elevated, 0.70), + "--bf-color-action-neutral-surface-pressed": rgba(elevated, 0.78), + "--bf-color-content-primary": colors["text"], + "--bf-color-content-secondary": colors["textSecondary"], + "--bf-color-content-muted": colors["textMuted"], + "--bf-color-content-disabled": colors["textDisabled"], + "--bf-color-accent-default": accent, + "--bf-color-accent-hover": colors["accentStrong"], + "--bf-color-border-subtle": rgba(accent, 0.08), + "--bf-color-border-default": rgba(accent, 0.12), + "--bf-color-border-strong": rgba(accent, 0.28), + "--bf-color-status-danger-content": colors["danger"], + "--bf-color-status-danger-surface": rgba(colors["danger"], 0.28), + "--bf-color-status-danger-border": rgba(colors["danger"], 0.38), + "--bf-color-status-warning-content": colors["warning"], + "--bf-color-status-success-content": colors["success"], + "--bf-color-status-info-content": colors["info"], + "--bf-color-scrollbar-thumb": rgba(accent, 0.22), + "--bf-color-scrollbar-thumb-hover": rgba(accent, 0.38), + } + widget_tokens = { + "--bf-color-surface-canvas": background, + "--bf-color-surface-panel": surface, + "--bf-color-surface-tertiary": elevated, + "--bf-color-surface-raised": elevated, + "--bf-color-surface-scene": background, + "--bf-color-content-primary": colors["text"], + "--bf-color-content-secondary": colors["textSecondary"], + "--bf-color-content-muted": colors["textMuted"], + "--bf-color-content-disabled": colors["textDisabled"], + "--bf-color-accent-default": accent, + "--bf-color-accent-hover": colors["accentStrong"], + "--bf-color-border-subtle": rgba(accent, 0.08, spaced=False), + "--bf-color-border-default": rgba(accent, 0.12, spaced=False), + "--bf-color-border-strong": rgba(accent, 0.28, spaced=False), + "--bf-color-surface-subtle": rgba(surface, 0.50, spaced=False), + "--bf-color-action-quiet-hover": rgba(surface, 0.58, spaced=False), + "--bf-color-action-neutral-surface": rgba(elevated, 0.66, spaced=False), + "--bf-color-action-neutral-surface-hover": rgba(elevated, 0.70, spaced=False), + "--bf-color-action-neutral-surface-pressed": rgba(elevated, 0.78, spaced=False), + } return { - "css-tokens": { + "theme-tokens": { "version": 1, "settings": { - "background": rgba(background, 0.18), - "tokens": { - "--bf-appearance-token-color-bg-primary": rgba(background, 0.78), - "--bf-appearance-token-color-bg-secondary": rgba(surface, 0.72), - "--bf-appearance-token-color-bg-tertiary": rgba(elevated, 0.76), - "--bf-appearance-token-color-bg-elevated": rgba(elevated, 0.74), - "--bf-appearance-token-color-bg-scene": rgba(background, 0.08), - "--bf-appearance-token-color-bg-workbench": rgba(background, 0.08), - "--bf-appearance-token-element-bg-subtle": rgba(surface, 0.50), - "--bf-appearance-token-element-bg-soft": rgba(surface, 0.58), - "--bf-appearance-token-element-bg-base": rgba(elevated, 0.66), - "--bf-appearance-token-element-bg-medium": rgba(elevated, 0.70), - "--bf-appearance-token-element-bg-hover": rgba(elevated, 0.78), - "--bf-appearance-token-color-text-primary": colors["text"], - "--bf-appearance-token-color-text-secondary": colors["textSecondary"], - "--bf-appearance-token-color-text-muted": colors["textMuted"], - "--bf-appearance-token-color-text-disabled": colors["textDisabled"], - "--bf-appearance-token-color-accent-500": accent, - "--bf-appearance-token-color-accent-500-rgb": rgb_triplet(accent), - "--bf-appearance-token-color-accent-600": colors["accentStrong"], - "--bf-appearance-token-color-cyan-500": colors["info"], - "--bf-appearance-token-border-subtle": rgba(accent, 0.08), - "--bf-appearance-token-border-base": rgba(accent, 0.12), - "--bf-appearance-token-border-medium": rgba(accent, 0.18), - "--bf-appearance-token-border-strong": rgba(accent, 0.28), - "--bf-appearance-token-glass-bg-base": rgba(surface, 0.58), - "--bf-appearance-token-glass-bg-hover": rgba(elevated, 0.68), - "--bf-appearance-token-glass-bg-active": rgba(elevated, 0.76), - "--bf-appearance-token-glass-border-base": rgba(accent, 0.12), - "--bf-appearance-token-glass-border-hover": rgba(accent, 0.22), - "--bf-appearance-token-color-error": colors["danger"], - "--bf-appearance-token-color-error-bg": rgba(colors["danger"], 0.28), - "--bf-appearance-token-color-error-border": rgba(colors["danger"], 0.38), - "--bf-appearance-token-color-warning": colors["warning"], - "--bf-appearance-token-color-success": colors["success"], - "--bf-appearance-token-color-info": colors["info"], - "--bf-appearance-token-scrollbar-thumb": rgba(accent, 0.22), - "--bf-appearance-token-scrollbar-thumb-hover": rgba(accent, 0.38), - }, + "tokens": theme_tokens, }, }, "monaco": { @@ -345,28 +354,7 @@ def build_renderers(colors: Mapping[str, str], appearance_id: str) -> dict[str, "settings": { "id": appearance_id, "mode": "dark", - "vars": { - "--bf-appearance-token-color-bg-primary": background, - "--bf-appearance-token-color-bg-secondary": surface, - "--bf-appearance-token-color-bg-tertiary": elevated, - "--bf-appearance-token-color-bg-elevated": elevated, - "--bf-appearance-token-color-bg-scene": background, - "--bf-appearance-token-color-text-primary": colors["text"], - "--bf-appearance-token-color-text-secondary": colors["textSecondary"], - "--bf-appearance-token-color-text-muted": colors["textMuted"], - "--bf-appearance-token-color-text-disabled": colors["textDisabled"], - "--bf-appearance-token-color-accent-500": accent, - "--bf-appearance-token-color-accent-500-rgb": rgb_triplet(accent, spaced=False), - "--bf-appearance-token-color-accent-600": colors["accentStrong"], - "--bf-appearance-token-border-subtle": rgba(accent, 0.08, spaced=False), - "--bf-appearance-token-border-base": rgba(accent, 0.12, spaced=False), - "--bf-appearance-token-border-medium": rgba(accent, 0.18, spaced=False), - "--bf-appearance-token-element-bg-subtle": rgba(surface, 0.50, spaced=False), - "--bf-appearance-token-element-bg-soft": rgba(surface, 0.58, spaced=False), - "--bf-appearance-token-element-bg-base": rgba(elevated, 0.66, spaced=False), - "--bf-appearance-token-element-bg-medium": rgba(elevated, 0.70, spaced=False), - "--bf-appearance-token-element-bg-hover": rgba(elevated, 0.78, spaced=False), - }, + "vars": widget_tokens, }, }, "bitfun-canvas": { @@ -423,7 +411,7 @@ def build_manifest( colors = palette["colors"] manifest: dict[str, Any] = { "schema": "bitfun.appearance", - "schemaVersion": 1, + "schemaVersion": 2, "id": appearance_id, "name": name, "version": version, diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/appearance-registry.json b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/appearance-registry.json index ec0f014d1b..2ef71a2daf 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/appearance-registry.json +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/appearance-registry.json @@ -1,11 +1,11 @@ { "schema": "bitfun.appearance.registry", - "schemaVersion": 1, - "generatedFrom": "19b5c2f96bb9f9eb7b83f6c9c7df0568dae4b153", - "generatedAt": "2026-08-30T08:27:29.571207+00:00", - "sourceRevision": "19b5c2f96bb9f9eb7b83f6c9c7df0568dae4b153", - "sourceDirty": true, - "sourceTreeHash": "36781423bb7063ddcd5a6e21ef0244599d39955b45e79d0c183dee3e41fdb3ac", + "schemaVersion": 2, + "generatedFrom": "68a853e10a3e2c18d85a3f5fca29bc09b4e8313d", + "generatedAt": "2026-08-30T22:40:41.595382+00:00", + "sourceRevision": "68a853e10a3e2c18d85a3f5fca29bc09b4e8313d", + "sourceDirty": false, + "sourceTreeHash": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b", "components": [ { "id": "card", @@ -229,196 +229,6 @@ } ] }, - { - "id": "select", - "parts": [ - { - "id": "root", - "propertyProfile": "control", - "visualRole": "control" - }, - { - "id": "label", - "propertyProfile": "paint", - "visualRole": "content" - }, - { - "id": "trigger", - "propertyProfile": "control", - "visualRole": "control" - }, - { - "id": "value", - "propertyProfile": "paint", - "visualRole": "content" - }, - { - "id": "suffix", - "propertyProfile": "paint", - "visualRole": "decoration" - }, - { - "id": "loading", - "propertyProfile": "paint", - "visualRole": "decoration" - }, - { - "id": "clear", - "propertyProfile": "control", - "visualRole": "control" - }, - { - "id": "arrow", - "propertyProfile": "paint", - "visualRole": "decoration" - }, - { - "id": "dropdown", - "propertyProfile": "overlay", - "visualRole": "popup" - }, - { - "id": "search", - "propertyProfile": "control", - "visualRole": "control" - }, - { - "id": "searchInput", - "propertyProfile": "control", - "visualRole": "control" - }, - { - "id": "options", - "propertyProfile": "container", - "visualRole": "content" - }, - { - "id": "option", - "propertyProfile": "control", - "visualRole": "control" - }, - { - "id": "optionIcon", - "propertyProfile": "paint", - "visualRole": "decoration" - }, - { - "id": "optionLabel", - "propertyProfile": "paint", - "visualRole": "content" - }, - { - "id": "optionDescription", - "propertyProfile": "paint", - "visualRole": "content" - }, - { - "id": "group", - "propertyProfile": "container", - "visualRole": "content" - }, - { - "id": "groupLabel", - "propertyProfile": "paint", - "visualRole": "content" - }, - { - "id": "empty", - "propertyProfile": "container", - "visualRole": "content" - }, - { - "id": "message", - "propertyProfile": "paint", - "visualRole": "content" - } - ], - "facets": [ - { - "id": "size", - "attribute": "data-bf-size", - "values": [ - "small", - "medium", - "large" - ] - }, - { - "id": "placement", - "attribute": "data-bf-placement", - "values": [ - "top", - "bottom" - ] - }, - { - "id": "multiple", - "attribute": "data-bf-multiple", - "values": [ - "true", - "false" - ] - } - ], - "states": [ - { - "id": "hover", - "selector": { - "kind": "self", - "suffix": ":hover" - } - }, - { - "id": "focusWithin", - "selector": { - "kind": "self", - "suffix": ":focus-within" - } - }, - { - "id": "open", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"open\"]" - } - }, - { - "id": "selected", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"selected\"]" - } - }, - { - "id": "highlighted", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"highlighted\"]" - } - }, - { - "id": "disabled", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"disabled\"]" - } - }, - { - "id": "error", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"error\"]" - } - }, - { - "id": "loading", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"loading\"]" - } - } - ] - }, { "id": "code-editor", "parts": [ @@ -10313,38 +10123,10 @@ "id": "header", "propertyProfile": "container" }, - { - "id": "back", - "propertyProfile": "container" - }, { "id": "content", "propertyProfile": "container" }, - { - "id": "loading", - "propertyProfile": "container" - }, - { - "id": "empty", - "propertyProfile": "container" - }, - { - "id": "list", - "propertyProfile": "container" - }, - { - "id": "item", - "propertyProfile": "container" - }, - { - "id": "itemName", - "propertyProfile": "container" - }, - { - "id": "itemDetail", - "propertyProfile": "container" - }, { "id": "currentDirectoryName", "propertyProfile": "container" @@ -10360,13 +10142,6 @@ ], "facets": [], "states": [ - { - "id": "selected", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"selected\"]" - } - }, { "id": "loading", "selector": { @@ -10650,18 +10425,6 @@ "id": "menu", "propertyProfile": "container" }, - { - "id": "menuHeader", - "propertyProfile": "container" - }, - { - "id": "menuBack", - "propertyProfile": "container" - }, - { - "id": "menuTitle", - "propertyProfile": "container" - }, { "id": "loading", "propertyProfile": "container" @@ -10669,14 +10432,6 @@ { "id": "empty", "propertyProfile": "container" - }, - { - "id": "list", - "propertyProfile": "container" - }, - { - "id": "listItem", - "propertyProfile": "container" } ], "facets": [], @@ -10687,13 +10442,6 @@ "kind": "self", "suffix": "[data-bf-state~=\"active\"]" } - }, - { - "id": "selected", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"selected\"]" - } } ] }, @@ -11041,18 +10789,6 @@ { "id": "input", "propertyProfile": "container" - }, - { - "id": "list", - "propertyProfile": "container" - }, - { - "id": "item", - "propertyProfile": "container" - }, - { - "id": "itemIcon", - "propertyProfile": "container" } ], "facets": [ @@ -11067,15 +10803,7 @@ ] } ], - "states": [ - { - "id": "selected", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"selected\"]" - } - } - ] + "states": [] }, { "id": "m-editor", @@ -12834,33 +12562,10 @@ { "id": "empty", "propertyProfile": "container" - }, - { - "id": "item", - "propertyProfile": "container" - }, - { - "id": "itemName", - "propertyProfile": "container" } ], "facets": [], - "states": [ - { - "id": "selected", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"selected\"]" - } - }, - { - "id": "current", - "selector": { - "kind": "self", - "suffix": "[data-bf-state~=\"current\"]" - } - } - ] + "states": [] }, { "id": "workspace-list-section", @@ -13246,29 +12951,9 @@ "id": "badge", "propertyProfile": "container" }, - { - "id": "menu", - "propertyProfile": "container" - }, - { - "id": "missionControl", - "propertyProfile": "container" - }, - { - "id": "divider", - "propertyProfile": "container" - }, - { - "id": "item", - "propertyProfile": "container" - }, { "id": "itemTitle", "propertyProfile": "container" - }, - { - "id": "itemClose", - "propertyProfile": "container" } ], "facets": [], @@ -16071,7 +15756,7 @@ } ], "renderers": [ - "css-tokens", + "theme-tokens", "monaco", "xterm", "mermaid", @@ -16134,354 +15819,402 @@ "mixBlendMode", "isolation" ], - "cssTokenNames": [ - "--bf-appearance-token-badge-padding-y", - "--bf-appearance-token-blur-base", - "--bf-appearance-token-blur-medium", - "--bf-appearance-token-blur-subtle", - "--bf-appearance-token-border-accent", - "--bf-appearance-token-border-accent-soft", - "--bf-appearance-token-border-accent-strong", - "--bf-appearance-token-border-accent-subtle", - "--bf-appearance-token-border-base", - "--bf-appearance-token-border-medium", - "--bf-appearance-token-border-prominent", - "--bf-appearance-token-border-strong", - "--bf-appearance-token-border-subtle", - "--bf-appearance-token-btn-ghost-color", - "--bf-appearance-token-btn-ghost-hover-bg", - "--bf-appearance-token-btn-ghost-hover-border", - "--bf-appearance-token-btn-ghost-hover-color", - "--bf-appearance-token-btn-primary-active-bg", - "--bf-appearance-token-btn-primary-active-border", - "--bf-appearance-token-btn-primary-active-color", - "--bf-appearance-token-btn-primary-active-shadow", - "--bf-appearance-token-btn-primary-active-transform", - "--bf-appearance-token-btn-primary-bg", - "--bf-appearance-token-btn-primary-border", - "--bf-appearance-token-btn-primary-color", - "--bf-appearance-token-btn-primary-hover-bg", - "--bf-appearance-token-btn-primary-hover-border", - "--bf-appearance-token-btn-primary-hover-color", - "--bf-appearance-token-btn-primary-hover-shadow", - "--bf-appearance-token-btn-primary-hover-transform", - "--bf-appearance-token-btn-primary-shadow", - "--bf-appearance-token-chrome-accent-100", - "--bf-appearance-token-chrome-accent-200", - "--bf-appearance-token-chrome-accent-300", - "--bf-appearance-token-chrome-accent-400", - "--bf-appearance-token-chrome-accent-50", - "--bf-appearance-token-chrome-accent-500", - "--bf-appearance-token-chrome-accent-600", - "--bf-appearance-token-chrome-accent-700", - "--bf-appearance-token-chrome-bg-elevated", - "--bf-appearance-token-chrome-bg-primary", - "--bf-appearance-token-chrome-bg-scene", - "--bf-appearance-token-chrome-bg-secondary", - "--bf-appearance-token-chrome-bg-tertiary", - "--bf-appearance-token-chrome-bg-workbench", - "--bf-appearance-token-chrome-border-accent", - "--bf-appearance-token-chrome-border-accent-soft", - "--bf-appearance-token-chrome-border-accent-strong", - "--bf-appearance-token-chrome-border-accent-subtle", - "--bf-appearance-token-chrome-border-base", - "--bf-appearance-token-chrome-border-medium", - "--bf-appearance-token-chrome-border-prominent", - "--bf-appearance-token-chrome-border-strong", - "--bf-appearance-token-chrome-border-subtle", - "--bf-appearance-token-chrome-element-bg-base", - "--bf-appearance-token-chrome-element-bg-medium", - "--bf-appearance-token-chrome-element-bg-soft", - "--bf-appearance-token-chrome-element-bg-strong", - "--bf-appearance-token-chrome-element-bg-subtle", - "--bf-appearance-token-chrome-scrollbar-thumb", - "--bf-appearance-token-chrome-scrollbar-thumb-hover", - "--bf-appearance-token-chrome-text-disabled", - "--bf-appearance-token-chrome-text-muted", - "--bf-appearance-token-chrome-text-primary", - "--bf-appearance-token-chrome-text-secondary", - "--bf-appearance-token-color-accent-100", - "--bf-appearance-token-color-accent-200", - "--bf-appearance-token-color-accent-300", - "--bf-appearance-token-color-accent-400", - "--bf-appearance-token-color-accent-50", - "--bf-appearance-token-color-accent-500", - "--bf-appearance-token-color-accent-500-rgb", - "--bf-appearance-token-color-accent-600", - "--bf-appearance-token-color-accent-700", - "--bf-appearance-token-color-bg-elevated", - "--bf-appearance-token-color-bg-primary", - "--bf-appearance-token-color-bg-scene", - "--bf-appearance-token-color-bg-secondary", - "--bf-appearance-token-color-bg-tertiary", - "--bf-appearance-token-color-bg-workbench", - "--bf-appearance-token-color-cyan-500", - "--bf-appearance-token-color-error", - "--bf-appearance-token-color-error-bg", - "--bf-appearance-token-color-error-border", - "--bf-appearance-token-color-indigo-500", - "--bf-appearance-token-color-info", - "--bf-appearance-token-color-info-bg", - "--bf-appearance-token-color-info-border", - "--bf-appearance-token-color-overlay-black-08", - "--bf-appearance-token-color-overlay-black-12", - "--bf-appearance-token-color-overlay-black-15", - "--bf-appearance-token-color-overlay-black-20", - "--bf-appearance-token-color-overlay-black-30", - "--bf-appearance-token-color-overlay-black-40", - "--bf-appearance-token-color-overlay-black-50", - "--bf-appearance-token-color-overlay-black-80", - "--bf-appearance-token-color-overlay-slate-04", - "--bf-appearance-token-color-overlay-slate-08", - "--bf-appearance-token-color-overlay-slate-12", - "--bf-appearance-token-color-overlay-slate-rgb", - "--bf-appearance-token-color-overlay-white-04", - "--bf-appearance-token-color-overlay-white-08", - "--bf-appearance-token-color-overlay-white-12", - "--bf-appearance-token-color-overlay-white-15", - "--bf-appearance-token-color-overlay-white-20", - "--bf-appearance-token-color-overlay-white-24", - "--bf-appearance-token-color-overlay-white-60", - "--bf-appearance-token-color-overlay-white-70", - "--bf-appearance-token-color-overlay-white-80", - "--bf-appearance-token-color-overlay-white-90", - "--bf-appearance-token-color-overlay-white-95", - "--bf-appearance-token-color-purple-100", - "--bf-appearance-token-color-purple-200", - "--bf-appearance-token-color-purple-500", - "--bf-appearance-token-color-purple-600", - "--bf-appearance-token-color-static-black", - "--bf-appearance-token-color-static-black-rgb", - "--bf-appearance-token-color-static-white", - "--bf-appearance-token-color-static-white-rgb", - "--bf-appearance-token-color-success", - "--bf-appearance-token-color-success-bg", - "--bf-appearance-token-color-success-border", - "--bf-appearance-token-color-text-disabled", - "--bf-appearance-token-color-text-muted", - "--bf-appearance-token-color-text-primary", - "--bf-appearance-token-color-text-secondary", - "--bf-appearance-token-color-warning", - "--bf-appearance-token-color-warning-bg", - "--bf-appearance-token-color-warning-border", - "--bf-appearance-token-config-page-divider", - "--bf-appearance-token-config-page-row-hover-bg", - "--bf-appearance-token-config-page-section-bg", - "--bf-appearance-token-config-page-section-border", - "--bf-appearance-token-config-page-section-border-width", - "--bf-appearance-token-config-page-section-shadow", - "--bf-appearance-token-domain-capability-creative", - "--bf-appearance-token-domain-capability-docs", - "--bf-appearance-token-domain-capability-ops", - "--bf-appearance-token-domain-capability-testing", - "--bf-appearance-token-domain-context-compression", - "--bf-appearance-token-domain-generative-ui", - "--bf-appearance-token-domain-git-lane-0", - "--bf-appearance-token-domain-git-lane-1", - "--bf-appearance-token-domain-git-lane-2", - "--bf-appearance-token-domain-git-lane-3", - "--bf-appearance-token-domain-git-lane-4", - "--bf-appearance-token-domain-git-lane-5", - "--bf-appearance-token-domain-git-lane-6", - "--bf-appearance-token-domain-git-lane-7", - "--bf-appearance-token-domain-insights-issue", - "--bf-appearance-token-domain-insights-neutral", - "--bf-appearance-token-domain-insights-positive", - "--bf-appearance-token-domain-insights-time", - "--bf-appearance-token-domain-inspector-active-background", - "--bf-appearance-token-domain-inspector-active-border", - "--bf-appearance-token-domain-inspector-active-border-subtle", - "--bf-appearance-token-domain-inspector-browser-tooltip-background", - "--bf-appearance-token-domain-inspector-main-tooltip-background", - "--bf-appearance-token-domain-inspector-selected-background", - "--bf-appearance-token-domain-inspector-selected-border", - "--bf-appearance-token-domain-inspector-tooltip-shadow", - "--bf-appearance-token-domain-inspector-tooltip-text", - "--bf-appearance-token-domain-mermaid-diagram", - "--bf-appearance-token-domain-mini-app", - "--bf-appearance-token-domain-progress-compacting", - "--bf-appearance-token-domain-review-judge", - "--bf-appearance-token-domain-review-member-default", - "--bf-appearance-token-domain-review-worker", - "--bf-appearance-token-domain-teal-action", - "--bf-appearance-token-domain-template-memories", - "--bf-appearance-token-domain-text-stroke-0", - "--bf-appearance-token-domain-text-stroke-1", - "--bf-appearance-token-domain-text-stroke-2", - "--bf-appearance-token-domain-text-stroke-3", - "--bf-appearance-token-domain-text-stroke-4", - "--bf-appearance-token-domain-todo", - "--bf-appearance-token-domain-tool-assistant-action", - "--bf-appearance-token-domain-tool-git", - "--bf-appearance-token-domain-tool-mcp", - "--bf-appearance-token-domain-tool-review-summary", - "--bf-appearance-token-domain-tool-search", - "--bf-appearance-token-domain-tool-terminal", - "--bf-appearance-token-domain-tool-web-search", - "--bf-appearance-token-easing-accelerate", - "--bf-appearance-token-easing-decelerate", - "--bf-appearance-token-easing-smooth", - "--bf-appearance-token-easing-standard", - "--bf-appearance-token-element-bg-base", - "--bf-appearance-token-element-bg-hover", - "--bf-appearance-token-element-bg-medium", - "--bf-appearance-token-element-bg-soft", - "--bf-appearance-token-element-bg-strong", - "--bf-appearance-token-element-bg-subtle", - "--bf-appearance-token-flowchat-card-expanded-pad-x", - "--bf-appearance-token-flowchat-card-expanded-pad-y", - "--bf-appearance-token-flowchat-card-gap", - "--bf-appearance-token-flowchat-card-pad-x", - "--bf-appearance-token-flowchat-card-pad-y", - "--bf-appearance-token-flowchat-card-radius", - "--bf-appearance-token-flowchat-code-block-pad-x", - "--bf-appearance-token-flowchat-code-block-pad-y", - "--bf-appearance-token-flowchat-content-inline-pad", - "--bf-appearance-token-flowchat-content-inline-pad-mobile", - "--bf-appearance-token-flowchat-control-gap", - "--bf-appearance-token-flowchat-control-pad-x", - "--bf-appearance-token-flowchat-control-pad-y", - "--bf-appearance-token-flowchat-flow-item-gap", - "--bf-appearance-token-flowchat-inline-gap", - "--bf-appearance-token-flowchat-link-color", - "--bf-appearance-token-flowchat-link-hover-color", - "--bf-appearance-token-flowchat-turn-gap", - "--bf-appearance-token-git-color-added", - "--bf-appearance-token-git-color-branch", - "--bf-appearance-token-git-color-branch-bg", - "--bf-appearance-token-git-color-branch-bg-hover", - "--bf-appearance-token-git-color-changes", - "--bf-appearance-token-git-color-deleted", - "--bf-appearance-token-git-color-staged", - "--bf-appearance-token-glass-bg-active", - "--bf-appearance-token-glass-bg-base", - "--bf-appearance-token-glass-bg-hover", - "--bf-appearance-token-glass-blue-subtle", - "--bf-appearance-token-glass-border-base", - "--bf-appearance-token-glass-border-hover", - "--bf-appearance-token-glass-red-base", - "--bf-appearance-token-glass-red-hover", - "--bf-appearance-token-glass-red-subtle", - "--bf-appearance-token-glow-shadow-blue", - "--bf-appearance-token-inner-glow-top", - "--bf-appearance-token-inner-glow-top-hover", - "--bf-appearance-token-language-blue", - "--bf-appearance-token-language-cyan", - "--bf-appearance-token-language-green", - "--bf-appearance-token-language-orange", - "--bf-appearance-token-language-purple", - "--bf-appearance-token-language-red", - "--bf-appearance-token-language-slate", - "--bf-appearance-token-language-yellow", - "--bf-appearance-token-motion-base", - "--bf-appearance-token-motion-fast", - "--bf-appearance-token-motion-instant", - "--bf-appearance-token-motion-lazy", - "--bf-appearance-token-motion-slow", - "--bf-appearance-token-opacity-disabled", - "--bf-appearance-token-opacity-hover", - "--bf-appearance-token-prism-dark-comment", - "--bf-appearance-token-prism-dark-foreground", - "--bf-appearance-token-prism-dark-function", - "--bf-appearance-token-prism-dark-keyword", - "--bf-appearance-token-prism-dark-number", - "--bf-appearance-token-prism-dark-property", - "--bf-appearance-token-prism-dark-punctuation", - "--bf-appearance-token-prism-dark-string", - "--bf-appearance-token-prism-dark-tag", - "--bf-appearance-token-prism-light-comment", - "--bf-appearance-token-prism-light-foreground", - "--bf-appearance-token-prism-light-function", - "--bf-appearance-token-prism-light-keyword", - "--bf-appearance-token-prism-light-number", - "--bf-appearance-token-prism-light-property", - "--bf-appearance-token-prism-light-punctuation", - "--bf-appearance-token-prism-light-string", - "--bf-appearance-token-prism-light-tag", - "--bf-appearance-token-scene-viewport-border-width", - "--bf-appearance-token-scrollbar-thumb", - "--bf-appearance-token-scrollbar-thumb-hover", - "--bf-appearance-token-shadow-base", - "--bf-appearance-token-shadow-lg", - "--bf-appearance-token-shadow-sm", - "--bf-appearance-token-shadow-xl", - "--bf-appearance-token-shadow-xs", - "--bf-appearance-token-size-gap-1", - "--bf-appearance-token-size-gap-10", - "--bf-appearance-token-size-gap-12", - "--bf-appearance-token-size-gap-16", - "--bf-appearance-token-size-gap-2", - "--bf-appearance-token-size-gap-3", - "--bf-appearance-token-size-gap-4", - "--bf-appearance-token-size-gap-5", - "--bf-appearance-token-size-gap-6", - "--bf-appearance-token-size-gap-8", - "--bf-appearance-token-size-radius-2xl", - "--bf-appearance-token-size-radius-base", - "--bf-appearance-token-size-radius-full", - "--bf-appearance-token-size-radius-lg", - "--bf-appearance-token-size-radius-md", - "--bf-appearance-token-size-radius-sm", - "--bf-appearance-token-size-radius-xl", - "--bf-appearance-token-tool-card-expanded-pad-x", - "--bf-appearance-token-tool-card-header-icon-slot", - "--bf-appearance-token-tool-card-header-pad-right", - "--bf-appearance-token-tool-card-header-pad-y" + "themeTokenNames": [ + "--bf-color-accent-border", + "--bf-color-accent-border-subtle", + "--bf-color-accent-default", + "--bf-color-accent-disabled", + "--bf-color-accent-hover", + "--bf-color-accent-secondary", + "--bf-color-accent-secondary-border", + "--bf-color-accent-secondary-hover", + "--bf-color-accent-secondary-surface", + "--bf-color-accent-secondary-surface-strong", + "--bf-color-accent-surface", + "--bf-color-accent-surface-strong", + "--bf-color-accent-surface-subtle", + "--bf-color-action-neutral-border", + "--bf-color-action-neutral-content", + "--bf-color-action-neutral-content-disabled", + "--bf-color-action-neutral-fill-border", + "--bf-color-action-neutral-surface", + "--bf-color-action-neutral-surface-hover", + "--bf-color-action-neutral-surface-pressed", + "--bf-color-action-primary-background", + "--bf-color-action-primary-content", + "--bf-color-action-primary-hover", + "--bf-color-action-primary-pressed", + "--bf-color-action-quiet-content", + "--bf-color-action-quiet-hover", + "--bf-color-action-quiet-pressed", + "--bf-color-action-secondary-background", + "--bf-color-action-secondary-content", + "--bf-color-action-secondary-hover", + "--bf-color-action-secondary-pressed", + "--bf-color-border-default", + "--bf-color-border-strong", + "--bf-color-border-subtle", + "--bf-color-content-disabled", + "--bf-color-content-inverse", + "--bf-color-content-muted", + "--bf-color-content-on-dark", + "--bf-color-content-on-light", + "--bf-color-content-primary", + "--bf-color-content-secondary", + "--bf-color-control-switch-thumb", + "--bf-color-control-switch-track", + "--bf-color-control-switch-track-checked", + "--bf-color-field-background", + "--bf-color-field-background-hover", + "--bf-color-field-border", + "--bf-color-field-border-focus", + "--bf-color-field-border-hover", + "--bf-color-focus-ring", + "--bf-color-identity-assistant-border", + "--bf-color-identity-assistant-content", + "--bf-color-identity-assistant-content-hover", + "--bf-color-identity-assistant-surface", + "--bf-color-identity-assistant-surface-subtle", + "--bf-color-key-hint-background", + "--bf-color-link-default", + "--bf-color-link-hover", + "--bf-color-overlay-scrim", + "--bf-color-scrollbar-thumb", + "--bf-color-scrollbar-thumb-hover", + "--bf-color-status-danger-border", + "--bf-color-status-danger-content", + "--bf-color-status-danger-surface", + "--bf-color-status-info-border", + "--bf-color-status-info-content", + "--bf-color-status-info-surface", + "--bf-color-status-success-border", + "--bf-color-status-success-content", + "--bf-color-status-success-surface", + "--bf-color-status-warning-border", + "--bf-color-status-warning-content", + "--bf-color-status-warning-surface", + "--bf-color-surface-canvas", + "--bf-color-surface-chrome", + "--bf-color-surface-panel", + "--bf-color-surface-raised", + "--bf-color-surface-scene", + "--bf-color-surface-subtle", + "--bf-color-surface-tertiary", + "--bf-color-surface-workbench", + "--bf-effect-blur-base", + "--bf-effect-blur-medium", + "--bf-effect-blur-subtle", + "--bf-opacity-disabled", + "--bf-opacity-focus", + "--bf-opacity-hover", + "--bf-opacity-muted", + "--bf-shadow-accent-glow", + "--bf-shadow-base", + "--bf-shadow-composer", + "--bf-shadow-inner-highlight", + "--bf-shadow-inner-highlight-hover", + "--bf-shadow-lg", + "--bf-shadow-menu", + "--bf-shadow-overlay", + "--bf-shadow-raised", + "--bf-shadow-sm", + "--bf-shadow-xl", + "--bf-shadow-xs", + "--bf-domain-context-compression", + "--bf-domain-generative-ui", + "--bf-domain-mini-app", + "--bf-domain-mermaid-diagram", + "--bf-domain-tool-search", + "--bf-domain-tool-web-search", + "--bf-domain-tool-git", + "--bf-domain-tool-terminal", + "--bf-domain-tool-mcp", + "--bf-domain-tool-assistant-action", + "--bf-domain-tool-review-summary", + "--bf-domain-capability-docs", + "--bf-domain-capability-testing", + "--bf-domain-capability-creative", + "--bf-domain-capability-ops", + "--bf-domain-insights-positive", + "--bf-domain-insights-time", + "--bf-domain-insights-neutral", + "--bf-domain-insights-issue", + "--bf-domain-progress-compacting", + "--bf-domain-template-memories", + "--bf-domain-review-member-default", + "--bf-domain-review-worker", + "--bf-domain-review-judge", + "--bf-domain-teal-action", + "--bf-domain-todo", + "--bf-domain-git-branch", + "--bf-domain-git-branch-background", + "--bf-domain-git-branch-background-hover", + "--bf-domain-git-changes", + "--bf-domain-git-added", + "--bf-domain-git-deleted", + "--bf-domain-git-staged", + "--bf-domain-git-lane-0", + "--bf-domain-git-lane-1", + "--bf-domain-git-lane-2", + "--bf-domain-git-lane-3", + "--bf-domain-git-lane-4", + "--bf-domain-git-lane-5", + "--bf-domain-git-lane-6", + "--bf-domain-git-lane-7", + "--bf-domain-text-stroke-0", + "--bf-domain-text-stroke-1", + "--bf-domain-text-stroke-2", + "--bf-domain-text-stroke-3", + "--bf-domain-text-stroke-4", + "--bf-domain-inspector-active-border", + "--bf-domain-inspector-active-background", + "--bf-domain-inspector-active-border-subtle", + "--bf-domain-inspector-selected-border", + "--bf-domain-inspector-selected-background", + "--bf-domain-inspector-browser-tooltip-background", + "--bf-domain-inspector-main-tooltip-background", + "--bf-domain-inspector-tooltip-text", + "--bf-domain-inspector-tooltip-shadow", + "--bf-domain-language-blue", + "--bf-domain-language-cyan", + "--bf-domain-language-yellow", + "--bf-domain-language-orange", + "--bf-domain-language-red", + "--bf-domain-language-green", + "--bf-domain-language-purple", + "--bf-domain-language-slate", + "--bf-domain-prism-light-foreground", + "--bf-domain-prism-light-comment", + "--bf-domain-prism-light-keyword", + "--bf-domain-prism-light-string", + "--bf-domain-prism-light-function", + "--bf-domain-prism-light-number", + "--bf-domain-prism-light-tag", + "--bf-domain-prism-light-punctuation", + "--bf-domain-prism-light-property", + "--bf-domain-prism-dark-foreground", + "--bf-domain-prism-dark-comment", + "--bf-domain-prism-dark-keyword", + "--bf-domain-prism-dark-string", + "--bf-domain-prism-dark-function", + "--bf-domain-prism-dark-number", + "--bf-domain-prism-dark-tag", + "--bf-domain-prism-dark-punctuation", + "--bf-domain-prism-dark-property", + "--bf-component-config-page-section-background", + "--bf-component-config-page-section-border", + "--bf-component-config-page-section-border-width", + "--bf-component-config-page-section-shadow", + "--bf-component-config-page-divider", + "--bf-component-config-page-row-hover-background", + "--bf-component-scene-viewport-border-width", + "--bf-component-badge-padding-block" + ], + "scopedThemeTokenNames": [ + "--bf-color-accent-border", + "--bf-color-accent-border-subtle", + "--bf-color-accent-default", + "--bf-color-accent-disabled", + "--bf-color-accent-hover", + "--bf-color-accent-secondary", + "--bf-color-accent-secondary-border", + "--bf-color-accent-secondary-hover", + "--bf-color-accent-secondary-surface", + "--bf-color-accent-secondary-surface-strong", + "--bf-color-accent-surface", + "--bf-color-accent-surface-strong", + "--bf-color-accent-surface-subtle", + "--bf-color-action-neutral-border", + "--bf-color-action-neutral-content", + "--bf-color-action-neutral-content-disabled", + "--bf-color-action-neutral-fill-border", + "--bf-color-action-neutral-surface", + "--bf-color-action-neutral-surface-hover", + "--bf-color-action-neutral-surface-pressed", + "--bf-color-action-primary-background", + "--bf-color-action-primary-content", + "--bf-color-action-primary-hover", + "--bf-color-action-primary-pressed", + "--bf-color-action-quiet-content", + "--bf-color-action-quiet-hover", + "--bf-color-action-quiet-pressed", + "--bf-color-action-secondary-background", + "--bf-color-action-secondary-content", + "--bf-color-action-secondary-hover", + "--bf-color-action-secondary-pressed", + "--bf-color-border-default", + "--bf-color-border-strong", + "--bf-color-border-subtle", + "--bf-color-content-disabled", + "--bf-color-content-inverse", + "--bf-color-content-muted", + "--bf-color-content-on-dark", + "--bf-color-content-on-light", + "--bf-color-content-primary", + "--bf-color-content-secondary", + "--bf-color-control-switch-thumb", + "--bf-color-control-switch-track", + "--bf-color-control-switch-track-checked", + "--bf-color-field-background", + "--bf-color-field-background-hover", + "--bf-color-field-border", + "--bf-color-field-border-focus", + "--bf-color-field-border-hover", + "--bf-color-focus-ring", + "--bf-color-identity-assistant-border", + "--bf-color-identity-assistant-content", + "--bf-color-identity-assistant-content-hover", + "--bf-color-identity-assistant-surface", + "--bf-color-identity-assistant-surface-subtle", + "--bf-color-key-hint-background", + "--bf-color-link-default", + "--bf-color-link-hover", + "--bf-color-overlay-scrim", + "--bf-color-scrollbar-thumb", + "--bf-color-scrollbar-thumb-hover", + "--bf-color-status-danger-border", + "--bf-color-status-danger-content", + "--bf-color-status-danger-surface", + "--bf-color-status-info-border", + "--bf-color-status-info-content", + "--bf-color-status-info-surface", + "--bf-color-status-success-border", + "--bf-color-status-success-content", + "--bf-color-status-success-surface", + "--bf-color-status-warning-border", + "--bf-color-status-warning-content", + "--bf-color-status-warning-surface", + "--bf-color-surface-canvas", + "--bf-color-surface-chrome", + "--bf-color-surface-panel", + "--bf-color-surface-raised", + "--bf-color-surface-scene", + "--bf-color-surface-subtle", + "--bf-color-surface-tertiary", + "--bf-color-surface-workbench", + "--bf-effect-blur-base", + "--bf-effect-blur-medium", + "--bf-effect-blur-subtle", + "--bf-opacity-disabled", + "--bf-opacity-focus", + "--bf-opacity-hover", + "--bf-opacity-muted", + "--bf-shadow-accent-glow", + "--bf-shadow-base", + "--bf-shadow-composer", + "--bf-shadow-inner-highlight", + "--bf-shadow-inner-highlight-hover", + "--bf-shadow-lg", + "--bf-shadow-menu", + "--bf-shadow-overlay", + "--bf-shadow-raised", + "--bf-shadow-sm", + "--bf-shadow-xl", + "--bf-shadow-xs" + ], + "themeScopeIds": [ + "chrome" ], "widgetVariableNames": [ - "--bf-appearance-token-color-bg-primary", - "--bf-appearance-token-color-static-white", - "--bf-appearance-token-color-static-black", - "--bf-appearance-token-color-bg-secondary", - "--bf-appearance-token-color-bg-tertiary", - "--bf-appearance-token-color-bg-elevated", - "--bf-appearance-token-color-bg-scene", - "--bf-appearance-token-color-text-primary", - "--bf-appearance-token-color-text-secondary", - "--bf-appearance-token-color-text-muted", - "--bf-appearance-token-color-text-disabled", - "--bf-appearance-token-color-accent-500", - "--bf-appearance-token-color-accent-500-rgb", - "--bf-appearance-token-color-accent-600", - "--bf-appearance-token-color-success", - "--bf-appearance-token-color-success-bg", - "--bf-appearance-token-color-warning", - "--bf-appearance-token-color-warning-bg", - "--bf-appearance-token-color-error", - "--bf-appearance-token-color-error-bg", - "--bf-appearance-token-color-info", - "--bf-appearance-token-color-info-bg", - "--bf-appearance-token-color-info-border", - "--bf-appearance-token-border-subtle", - "--bf-appearance-token-border-base", - "--bf-appearance-token-border-medium", - "--bf-appearance-token-element-bg-subtle", - "--bf-appearance-token-element-bg-soft", - "--bf-appearance-token-element-bg-base", - "--bf-appearance-token-element-bg-medium", - "--bf-appearance-token-element-bg-hover", - "--bf-appearance-token-shadow-xs", - "--bf-appearance-token-shadow-sm", - "--bf-appearance-token-motion-fast", - "--bf-appearance-token-motion-base", - "--bf-appearance-token-easing-standard", - "--bf-appearance-token-btn-primary-bg", - "--bf-appearance-token-btn-primary-color", - "--bf-appearance-token-btn-primary-border", - "--bf-appearance-token-btn-primary-shadow", - "--bf-appearance-token-btn-primary-hover-bg", - "--bf-appearance-token-btn-primary-hover-color", - "--bf-appearance-token-btn-primary-hover-border", - "--bf-appearance-token-btn-primary-hover-shadow", - "--bf-appearance-token-btn-primary-hover-transform", - "--bf-appearance-token-btn-primary-active-bg", - "--bf-appearance-token-btn-primary-active-color", - "--bf-appearance-token-btn-primary-active-border", - "--bf-appearance-token-btn-primary-active-shadow", - "--bf-appearance-token-btn-primary-active-transform", - "--bf-appearance-token-btn-ghost-color", - "--bf-appearance-token-btn-ghost-hover-bg", - "--bf-appearance-token-btn-ghost-hover-color", - "--bf-appearance-token-btn-ghost-hover-border" + "--bf-color-accent-border", + "--bf-color-accent-border-subtle", + "--bf-color-accent-default", + "--bf-color-accent-disabled", + "--bf-color-accent-hover", + "--bf-color-accent-secondary", + "--bf-color-accent-secondary-border", + "--bf-color-accent-secondary-hover", + "--bf-color-accent-secondary-surface", + "--bf-color-accent-secondary-surface-strong", + "--bf-color-accent-surface", + "--bf-color-accent-surface-strong", + "--bf-color-accent-surface-subtle", + "--bf-color-action-neutral-border", + "--bf-color-action-neutral-content", + "--bf-color-action-neutral-content-disabled", + "--bf-color-action-neutral-fill-border", + "--bf-color-action-neutral-surface", + "--bf-color-action-neutral-surface-hover", + "--bf-color-action-neutral-surface-pressed", + "--bf-color-action-primary-background", + "--bf-color-action-primary-content", + "--bf-color-action-primary-hover", + "--bf-color-action-primary-pressed", + "--bf-color-action-quiet-content", + "--bf-color-action-quiet-hover", + "--bf-color-action-quiet-pressed", + "--bf-color-action-secondary-background", + "--bf-color-action-secondary-content", + "--bf-color-action-secondary-hover", + "--bf-color-action-secondary-pressed", + "--bf-color-border-default", + "--bf-color-border-strong", + "--bf-color-border-subtle", + "--bf-color-content-disabled", + "--bf-color-content-inverse", + "--bf-color-content-muted", + "--bf-color-content-on-dark", + "--bf-color-content-on-light", + "--bf-color-content-primary", + "--bf-color-content-secondary", + "--bf-color-control-switch-thumb", + "--bf-color-control-switch-track", + "--bf-color-control-switch-track-checked", + "--bf-color-field-background", + "--bf-color-field-background-hover", + "--bf-color-field-border", + "--bf-color-field-border-focus", + "--bf-color-field-border-hover", + "--bf-color-focus-ring", + "--bf-color-identity-assistant-border", + "--bf-color-identity-assistant-content", + "--bf-color-identity-assistant-content-hover", + "--bf-color-identity-assistant-surface", + "--bf-color-identity-assistant-surface-subtle", + "--bf-color-key-hint-background", + "--bf-color-link-default", + "--bf-color-link-hover", + "--bf-color-overlay-scrim", + "--bf-color-scrollbar-thumb", + "--bf-color-scrollbar-thumb-hover", + "--bf-color-status-danger-border", + "--bf-color-status-danger-content", + "--bf-color-status-danger-surface", + "--bf-color-status-info-border", + "--bf-color-status-info-content", + "--bf-color-status-info-surface", + "--bf-color-status-success-border", + "--bf-color-status-success-content", + "--bf-color-status-success-surface", + "--bf-color-status-warning-border", + "--bf-color-status-warning-content", + "--bf-color-status-warning-surface", + "--bf-color-surface-canvas", + "--bf-color-surface-chrome", + "--bf-color-surface-panel", + "--bf-color-surface-raised", + "--bf-color-surface-scene", + "--bf-color-surface-subtle", + "--bf-color-surface-tertiary", + "--bf-color-surface-workbench", + "--bf-effect-blur-base", + "--bf-effect-blur-medium", + "--bf-effect-blur-subtle", + "--bf-opacity-disabled", + "--bf-opacity-focus", + "--bf-opacity-hover", + "--bf-opacity-muted", + "--bf-shadow-accent-glow", + "--bf-shadow-base", + "--bf-shadow-composer", + "--bf-shadow-inner-highlight", + "--bf-shadow-inner-highlight-hover", + "--bf-shadow-lg", + "--bf-shadow-menu", + "--bf-shadow-overlay", + "--bf-shadow-raised", + "--bf-shadow-sm", + "--bf-shadow-xl", + "--bf-shadow-xs" ] } diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/package-contract.md b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/package-contract.md index dde51c8f2d..523f2612c2 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/package-contract.md +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/package-contract.md @@ -6,7 +6,7 @@ - Archive format: ZIP - Root manifest: `appearance.json` - `schema`: `bitfun.appearance` -- `schemaVersion`: `1` +- `schemaVersion`: `2` - Image formats: PNG, JPEG, WebP, or GIF - Background video formats: MP4 or WebM - Imported packages are sparse overlays merged with the built-in light or dark Appearance package. diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/renderer-contracts.md b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/renderer-contracts.md index 2ec6af45e5..cdf21f89c6 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/renderer-contracts.md +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/references/renderer-contracts.md @@ -19,12 +19,14 @@ Renderer entries use this shape: } ``` -## css-tokens +## theme-tokens -`settings` contains `tokens` and `background`. Query accepted token names with: +`settings.tokens` contains only canonical `--bf-*` theme, component, and registered domain tokens. Optional +`settings.scopes` contains a registered scope such as `chrome`, whose values are limited to the scoped canonical +theme-token set. Query accepted root token names with: ```powershell -python scripts/bitfun_appearance.py contract tokens css +python scripts/bitfun_appearance.py contract tokens theme ``` ## monaco diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/bitfun_appearance.py b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/bitfun_appearance.py index f0cd431e87..bc2e9d3077 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/bitfun_appearance.py +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/bitfun_appearance.py @@ -14,7 +14,7 @@ SCHEMA = "bitfun.appearance" -SCHEMA_VERSION = 1 +SCHEMA_VERSION = 2 REGISTRY_PATH = Path(__file__).resolve().parent.parent / "references" / "appearance-registry.json" MANIFEST_NAME = "appearance.json" MAX_ARCHIVE_BYTES = 96 * 1024 * 1024 @@ -225,7 +225,7 @@ def load_registry() -> dict[str, Any]: registry = json.loads(REGISTRY_PATH.read_text(encoding="utf-8")) except (OSError, json.JSONDecodeError) as error: raise AppearanceError(f"Could not load bundled Appearance registry: {error}") from error - if registry.get("schema") != "bitfun.appearance.registry" or registry.get("schemaVersion") != 1: + if registry.get("schema") != "bitfun.appearance.registry" or registry.get("schemaVersion") != 2: raise AppearanceError("Bundled Appearance registry has an unsupported schema") return registry @@ -243,7 +243,9 @@ def __init__(self, registry: Mapping[str, Any]): self.components = {item["id"]: item for item in registry.get("components", [])} self.scenes = {item["id"]: item for item in registry.get("scenes", [])} self.renderers = set(registry.get("renderers", [])) - self.css_tokens = set(registry.get("cssTokenNames", [])) + self.theme_tokens = set(registry.get("themeTokenNames", [])) + self.scoped_theme_tokens = set(registry.get("scopedThemeTokenNames", [])) + self.theme_scope_ids = set(registry.get("themeScopeIds", [])) self.widget_vars = set(registry.get("widgetVariableNames", [])) self.errors: list[dict[str, str]] = [] self.warnings: list[dict[str, str]] = [] @@ -798,8 +800,8 @@ def scan_renderer_text(self, value: Any, path: str) -> None: self.scan_renderer_text(item, f"{path}.{key}") def validate_renderer_settings(self, renderer_id: str, settings: Mapping[str, Any]) -> list[str]: - if renderer_id == "css-tokens": - return self.validate_css_tokens(settings) + if renderer_id == "theme-tokens": + return self.validate_theme_tokens(settings) if renderer_id == "monaco": return self.validate_monaco(settings) if renderer_id == "xterm": @@ -812,21 +814,45 @@ def validate_renderer_settings(self, renderer_id: str, settings: Mapping[str, An return self.validate_canvas(settings) return [f"Unsupported renderer: {renderer_id}"] - def validate_css_tokens(self, settings: Mapping[str, Any]) -> list[str]: + def validate_theme_token_map( + self, + tokens: Any, + allowed_names: set[str], + path: str, + ) -> list[str]: errors: list[str] = [] - tokens = settings.get("tokens") - background = settings.get("background") - if not is_record(tokens) or not isinstance(background, str): - return ["css-tokens settings must contain tokens and background"] + if not is_record(tokens): + return [f"{path} must be an object"] for name, value in tokens.items(): - if name not in self.css_tokens: - errors.append(f"Unsupported CSS token name: {name}") + if name not in allowed_names: + errors.append(f"Unsupported {path} token name: {name}") if not isinstance(value, str) or not value or len(value) > 512: - errors.append(f"CSS token {name} must be a non-empty string of at most 512 characters") + errors.append(f"{path} token {name} must be a non-empty string of at most 512 characters") elif CSS_TOKEN_FORBIDDEN.search(value): - errors.append(f"CSS token {name} contains a forbidden value") - if CSS_TOKEN_FORBIDDEN.search(background): - errors.append("css-tokens background contains a forbidden value") + errors.append(f"{path} token {name} contains a forbidden value") + return errors + + def validate_theme_tokens(self, settings: Mapping[str, Any]) -> list[str]: + errors: list[str] = [] + for key in settings: + if key not in ("tokens", "scopes"): + errors.append(f"Unknown setting: {key}") + errors.extend(self.validate_theme_token_map(settings.get("tokens"), self.theme_tokens, "root")) + scopes = settings.get("scopes") + if scopes is None: + return errors + if not is_record(scopes): + errors.append("scopes must be an object") + return errors + for scope_id, tokens in scopes.items(): + if scope_id not in self.theme_scope_ids: + errors.append(f"Unknown theme token scope: {scope_id}") + continue + errors.extend(self.validate_theme_token_map( + tokens, + self.scoped_theme_tokens, + f"scope {scope_id}", + )) return errors def validate_monaco(self, settings: Mapping[str, Any]) -> list[str]: @@ -1680,7 +1706,7 @@ def command_contract(args: argparse.Namespace, registry: Mapping[str, Any]) -> N print(json.dumps(sorted(STYLE_PROPERTIES), indent=2)) return if args.action == "tokens": - key = "cssTokenNames" if args.token_kind == "css" else "widgetVariableNames" + key = "themeTokenNames" if args.token_kind == "theme" else "widgetVariableNames" print("\n".join(registry.get(key, []))) return if args.kind == "renderers": @@ -1733,7 +1759,7 @@ def create_parser() -> argparse.ArgumentParser: contract_show.add_argument("kind", choices=("components", "scenes")) contract_show.add_argument("id") contract_tokens = contract_sub.add_parser("tokens") - contract_tokens.add_argument("token_kind", choices=("css", "widget")) + contract_tokens.add_argument("token_kind", choices=("theme", "widget")) contract_sub.add_parser("properties") return parser diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/sync_registry.py b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/sync_registry.py index 943808c313..048a86633a 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/sync_registry.py +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/sync_registry.py @@ -19,7 +19,9 @@ "scenes", "renderers", "defaultForceableProperties", - "cssTokenNames", + "themeTokenNames", + "scopedThemeTokenNames", + "themeScopeIds", "widgetVariableNames", ) EXPORT_MARKER = "__BITFUN_APPEARANCE_REGISTRY__" @@ -53,7 +55,7 @@ def export_registry(repo: Path) -> dict[str, Any]: const server = await createServer({ root: process.cwd(), logLevel: 'silent', appType: 'custom', server: { middlewareMode: true } }); try { const registryModule = await server.ssrLoadModule('/src/infrastructure/appearance/registry/defaultAppearanceRegistry.ts'); - const catalog = await server.ssrLoadModule('/src/infrastructure/appearance/builtins/catalog.ts'); + const tokenContract = await server.ssrLoadModule('/src/infrastructure/appearance/appearanceTokenContract.ts'); const widget = await server.ssrLoadModule('/src/infrastructure/appearance/adapters/widgetAppearanceVariables.ts'); const profiles = await server.ssrLoadModule('/src/infrastructure/appearance/appearancePropertyProfiles.ts'); const registry = registryModule.createDefaultAppearanceRegistry(); @@ -79,7 +81,9 @@ def export_registry(repo: Path) -> dict[str, Any]: scenes: registry.getScenes().map(descriptor), renderers: registry.getRendererAdapters().map(adapter => adapter.id), defaultForceableProperties, - cssTokenNames: [...catalog.APPEARANCE_CSS_TOKEN_NAMES], + themeTokenNames: [...tokenContract.APPEARANCE_ROOT_TOKEN_NAMES], + scopedThemeTokenNames: [...tokenContract.APPEARANCE_SCOPED_TOKEN_NAMES], + themeScopeIds: Object.keys(tokenContract.APPEARANCE_THEME_SCOPE_SELECTORS), widgetVariableNames: [...widget.WIDGET_APPEARANCE_VARIABLE_NAMES], })); } finally { @@ -119,7 +123,7 @@ def main() -> int: snapshot = export_registry(repo) output_value = { "schema": "bitfun.appearance.registry", - "schemaVersion": 1, + "schemaVersion": 2, "generatedFrom": revision, "generatedAt": dt.datetime.now(dt.timezone.utc).isoformat(), "sourceRevision": revision, diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/test_bitfun_appearance.py b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/test_bitfun_appearance.py index 16437343b9..5e9ce6f19c 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/test_bitfun_appearance.py +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/test_bitfun_appearance.py @@ -11,7 +11,7 @@ def base_manifest() -> dict[str, object]: return { "schema": "bitfun.appearance", - "schemaVersion": 1, + "schemaVersion": 2, "id": "validator-test", "name": "Validator Test", "version": "1.0.0", @@ -101,6 +101,21 @@ def test_xterm_typography_settings_are_rejected(self) -> None: self.assertIn("Unknown setting: fontWeight", errors) self.assertIn("Unknown setting: fontWeightBold", errors) + def test_theme_token_renderer_accepts_only_canonical_root_and_scope_tokens(self) -> None: + validator = appearance.ManifestValidator(self.registry) + self.assertEqual([], validator.validate_theme_tokens({ + "tokens": {"--bf-color-surface-canvas": "#101820"}, + "scopes": {"chrome": {"--bf-color-content-primary": "#f5f7fa"}}, + })) + + errors = validator.validate_theme_tokens({ + "tokens": {"--bf-appearance-token-color-bg-primary": "#101820"}, + }) + self.assertIn( + "Unsupported root token name: --bf-appearance-token-color-bg-primary", + errors, + ) + def test_normalization_and_visual_semantic_warnings_are_reported(self) -> None: manifest = base_manifest() manifest["components"] = { @@ -156,7 +171,7 @@ def test_contract_output_preserves_authoring_metadata(self) -> None: def test_registry_contract_comparison_ignores_provenance_only_changes(self) -> None: current = { "schema": "bitfun.appearance.registry", - "schemaVersion": 1, + "schemaVersion": 2, "sourceRevision": "old-revision", "generatedAt": "old-time", **{key: [] for key in registry_sync.CONTRACT_KEYS}, diff --git a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/test_cinematic_tools.py b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/test_cinematic_tools.py index 7b58391fd3..7ae1b5fd08 100644 --- a/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/test_cinematic_tools.py +++ b/src/crates/assembly/core/builtin_skills/create-bitfun-skin/scripts/test_cinematic_tools.py @@ -37,6 +37,11 @@ def test_default_manifest_is_current_and_warning_free(self) -> None: surface_plan=plan, ) self.assertEqual([], contract.validate_manifest(manifest)) + self.assertEqual(2, manifest["schemaVersion"]) + self.assertIn("theme-tokens", manifest["renderers"]) + self.assertNotIn("css-tokens", manifest["renderers"]) + serialized_renderers = json.dumps(manifest["renderers"]) + self.assertNotIn("--bf-appearance-token-", serialized_renderers) self.assertIn("flow-chat-turn-rail", manifest["components"]) self.assertIn("copyable-text-preview", manifest["components"]) self.assertNotIn("input", manifest["components"]["toolbar-mode"]["parts"]) diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-coding-selfie/style.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-coding-selfie/style.css index afc19f95eb..e4546a9fed 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-coding-selfie/style.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-coding-selfie/style.css @@ -3,8 +3,7 @@ * palette ─ Inherits BitFun host theme (--bitfun-* tokens). Surfaces, * text and borders all proxy through host vars so the dashboard * reads as a native BitFun panel under both bitfun-dark and - * bitfun-light. Standalone fallbacks mirror the default dark - * theme (#0e0e10 / #e8e8e8 / #60a5fa). + * bitfun-light. The host contract owns first-paint defaults. * accent ─ host primary (cool blue / slate) for hero/streak/heatmap * accents. Diff stats keep semantic green/red so additions and * deletions stay glanceable. @@ -13,58 +12,45 @@ :root { color-scheme: dark; - --cs-bg: var(--bitfun-bg, #0e0e10); - --cs-card: var(--bitfun-bg-secondary, #1c1c1f); - --cs-card-2: var(--bitfun-bg-tertiary, #121214); + --cs-bg: var(--bitfun-bg); + --cs-card: var(--bitfun-bg-secondary); + --cs-card-2: var(--bitfun-bg-tertiary); - --cs-border: var(--bitfun-border-subtle, rgba(255, 255, 255, 0.10)); - --cs-border-strong: var(--bitfun-border, rgba(255, 255, 255, 0.18)); + --cs-border: var(--bitfun-border-subtle); + --cs-border-strong: var(--bitfun-border); - --cs-text: var(--bitfun-text, #e8e8e8); - --cs-text-2: var(--bitfun-text-secondary, #b0b0b0); - --cs-text-muted: var(--bitfun-text-muted, #858585); + --cs-text: var(--bitfun-text); + --cs-text-2: var(--bitfun-text-secondary); + --cs-text-muted: var(--bitfun-text-muted); /* Primary accent now follows the host (cool blue in dark, slate in light) * so the dashboard stops fighting BitFun's neutral palette. The previous * "run green" is preserved as a secondary semantic color (--cs-add). */ - --cs-accent: var(--bitfun-accent, #60a5fa); - --cs-accent-2: var(--bitfun-accent-hover, #3b82f6); - --cs-accent-soft: rgba(96, 165, 250, 0.14); - --cs-accent-glow: 0 0 20px rgba(96, 165, 250, 0.20); + --cs-accent: var(--bitfun-accent); + --cs-accent-2: var(--bitfun-accent-hover); + --cs-accent-soft: color-mix(in srgb, var(--cs-accent) 14%, transparent); + --cs-accent-glow: 0 0 20px color-mix(in srgb, var(--cs-accent) 20%, transparent); /* Diff / activity semantics — kept on green/red regardless of host accent * because additions and deletions must stay universally readable. */ - --cs-add: var(--bitfun-success, #34d399); - --cs-del: var(--bitfun-error, #f87171); - --cs-warn: var(--bitfun-warning, #f59e0b); - - /* RGB triplet of the host accent — used by .cs-heat-* gradients to mix - * tinted alpha steps without hardcoding the brand color. Updated by the - * light-theme block below. */ - --cs-accent-rgb: 96, 165, 250; - --cs-add-rgb: 52, 211, 153; + --cs-add: var(--bitfun-success); + --cs-del: var(--bitfun-error); + --cs-warn: var(--bitfun-warning); --cs-bg-grad: - radial-gradient(ellipse at top, rgba(var(--cs-accent-rgb), 0.05), transparent 60%), - radial-gradient(ellipse at bottom right, rgba(139,92,246, 0.04), transparent 50%), + radial-gradient(ellipse at top, color-mix(in srgb, var(--cs-accent) 5%, transparent), transparent 60%), + radial-gradient(ellipse at bottom right, color-mix(in srgb, var(--bitfun-accent-secondary) 4%, transparent), transparent 50%), var(--cs-bg); - --cs-radius: var(--bitfun-radius-lg, 12px); - --cs-radius-sm: var(--bitfun-radius, 8px); - --cs-mono: var(--bitfun-font-mono, 'JetBrains Mono', 'FiraCode', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, 'Cascadia Mono', 'Cascadia Code', Consolas, 'Liberation Mono', 'Courier New', monospace); - --cs-sans: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', 'Segoe UI', 'Microsoft YaHei UI', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif); + --cs-radius: var(--bitfun-radius-lg); + --cs-radius-sm: var(--bitfun-radius); + --cs-mono: var(--bitfun-font-mono); + --cs-sans: var(--bitfun-font-sans); } [data-bf-appearance-mode="light"] { color-scheme: light; - /* Sturdier alpha & a slightly muted glow on near-white surfaces. */ - --cs-accent-soft: rgba(71, 85, 105, 0.10); - --cs-accent-glow: 0 0 0 transparent; - --cs-accent-rgb: 71, 85, 105; - --cs-add-rgb: 91, 154, 111; - --cs-bg-grad: - radial-gradient(ellipse at top, rgba(var(--cs-accent-rgb), 0.06), transparent 60%), - var(--cs-bg); + --cs-accent-glow: none; } * { box-sizing: border-box; } @@ -175,8 +161,8 @@ html, body { grid-column: span 9; padding: clamp(10px, 1.5vh, 16px) clamp(14px, 1.8vw, 20px); background: - radial-gradient(circle at 80% 0%, rgba(var(--cs-accent-rgb), 0.10), transparent 55%), - radial-gradient(circle at 0% 100%, rgba(139, 92, 246, 0.05), transparent 50%), + radial-gradient(circle at 80% 0%, color-mix(in srgb, var(--cs-accent) 10%, transparent), transparent 55%), + radial-gradient(circle at 0% 100%, color-mix(in srgb, var(--bitfun-accent-secondary) 5%, transparent), transparent 50%), var(--cs-card); justify-content: center; } @@ -186,7 +172,7 @@ html, body { right: -20%; width: 60%; height: 180%; - background: radial-gradient(ellipse, rgba(var(--cs-accent-rgb), 0.10), transparent 60%); + background: radial-gradient(ellipse, color-mix(in srgb, var(--cs-accent) 10%, transparent), transparent 60%); pointer-events: none; filter: blur(10px); } @@ -253,7 +239,7 @@ html, body { .cs-range-chip.is-active { background: var(--cs-accent-soft); color: var(--cs-accent); - border-color: rgba(var(--cs-accent-rgb), 0.45); + border-color: color-mix(in srgb, var(--cs-accent) 45%, transparent); } .cs-range-custom { display: inline-flex; @@ -275,7 +261,7 @@ html, body { } .cs-range-date:focus { outline: none; - border-color: rgba(var(--cs-accent-rgb), 0.55); + border-color: color-mix(in srgb, var(--cs-accent) 55%, transparent); } .cs-range-sep { color: var(--cs-text-muted); font-size: 12px; } @@ -318,9 +304,9 @@ html, body { .cs-tile-streak { grid-column: span 3; background: - linear-gradient(140deg, rgba(var(--cs-accent-rgb), 0.10), transparent 70%), + linear-gradient(140deg, color-mix(in srgb, var(--cs-accent) 10%, transparent), transparent 70%), var(--cs-card); - border-color: rgba(var(--cs-accent-rgb), 0.22); + border-color: color-mix(in srgb, var(--cs-accent) 22%, transparent); display: grid; grid-template-columns: auto auto 1fr; grid-template-rows: auto 1fr auto; @@ -528,7 +514,7 @@ html, body { border-radius: 2px; opacity: 0.85; } -.cs-hour-bar.peak::after { box-shadow: 0 0 12px rgba(var(--cs-accent-rgb), 0.45); opacity: 1; } +.cs-hour-bar.peak::after { box-shadow: 0 0 12px color-mix(in srgb, var(--cs-accent) 45%, transparent); opacity: 1; } .cs-hour-bar:hover { filter: brightness(1.2); } .cs-hours-axis { display: flex; @@ -603,12 +589,12 @@ html, body { .cs-heat-cell:hover { outline-color: var(--cs-accent); } .cs-heat-empty { background: transparent; pointer-events: none; } .cs-heat-0 { background: var(--cs-card-2); } -.cs-heat-1 { background: rgba(var(--cs-accent-rgb), 0.25); } -.cs-heat-2 { background: rgba(var(--cs-accent-rgb), 0.45); } -.cs-heat-3 { background: rgba(var(--cs-accent-rgb), 0.70); } +.cs-heat-1 { background: color-mix(in srgb, var(--cs-accent) 25%, transparent); } +.cs-heat-2 { background: color-mix(in srgb, var(--cs-accent) 45%, transparent); } +.cs-heat-3 { background: color-mix(in srgb, var(--cs-accent) 70%, transparent); } .cs-heat-4 { background: var(--cs-accent); - box-shadow: 0 0 10px rgba(var(--cs-accent-rgb), 0.35); + box-shadow: 0 0 10px color-mix(in srgb, var(--cs-accent) 35%, transparent); } /* Custom hover tooltip for heatmap cells (replaces native title delay). */ @@ -625,7 +611,7 @@ html, body { font-size: 12.5px; line-height: 1.35; white-space: nowrap; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); + box-shadow: var(--bitfun-shadow-overlay); } .cs-heatmap-legend { diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-coding-selfie/ui.js b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-coding-selfie/ui.js index faf400ba96..7a748d1f92 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-coding-selfie/ui.js +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-coding-selfie/ui.js @@ -417,7 +417,7 @@ function renderDonut(langs) { svg.innerHTML = ''; const total = langs.reduce((acc, l) => acc + l.weight, 0); if (total <= 0) { - svg.innerHTML = ''; + svg.innerHTML = ''; $('lang-legend').innerHTML = `
  • ${t('noCommitsThisRange')}
  • `; return; } @@ -444,7 +444,7 @@ function renderDonut(langs) { const s = slices[i]; const frac = s.weight / total; const dash = c * frac; - const color = s.isOther ? 'rgba(148,163,184,0.35)' : LANG_COLORS[i % LANG_COLORS.length]; + const color = s.isOther ? 'var(--cs-text-muted)' : LANG_COLORS[i % LANG_COLORS.length]; const arc = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); arc.setAttribute('cx', '60'); arc.setAttribute('cy', '60'); @@ -469,7 +469,7 @@ function renderDonut(langs) { slices.forEach((s, i) => { const li = document.createElement('li'); li.className = 'cs-legend-row'; - const color = s.isOther ? 'rgba(148,163,184,0.35)' : LANG_COLORS[i % LANG_COLORS.length]; + const color = s.isOther ? 'var(--cs-text-muted)' : LANG_COLORS[i % LANG_COLORS.length]; const pct = (s.weight / total) * 100; const barPct = (s.weight / maxWeight) * 100; const safeName = escapeHtml(s.name); diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-daily-divination/style.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-daily-divination/style.css index 0c4161d69f..7340d70061 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-daily-divination/style.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-daily-divination/style.css @@ -29,9 +29,7 @@ body, html { margin: 0; padding: 0; height: 100%; } --d-serif: ui-serif, "Cormorant Garamond", "Cormorant", "EB Garamond", "Noto Serif SC", "Source Han Serif SC", "Songti SC", STSong, "STZhongsong", SimSun, "宋体", Georgia, "Times New Roman", serif; - --d-sans: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "PingFang SC", - "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei UI", "Microsoft YaHei", - "Helvetica Neue", Helvetica, Arial, sans-serif); + --d-sans: var(--bitfun-font-sans); } body { diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-gomoku/style.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-gomoku/style.css index f3ef0a415a..a78b18a318 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-gomoku/style.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-gomoku/style.css @@ -18,23 +18,23 @@ body, html { margin: 0; padding: 0; height: 100%; } [hidden] { display: none !important; } :root { - --g-bg: var(--bitfun-bg, #121214); - --g-bg-secondary: var(--bitfun-bg-secondary, #18181a); - --g-bg-elevated: var(--bitfun-bg-elevated, #1f1f22); + --g-bg: var(--bitfun-bg); + --g-bg-secondary: var(--bitfun-bg-secondary); + --g-bg-elevated: var(--bitfun-bg-elevated); - --g-text: var(--bitfun-text, #e8e8e8); - --g-text-soft: var(--bitfun-text-secondary, #b0b0b0); - --g-text-mute: var(--bitfun-text-muted, #858585); + --g-text: var(--bitfun-text); + --g-text-soft: var(--bitfun-text-secondary); + --g-text-mute: var(--bitfun-text-muted); - --g-border: var(--bitfun-border, #2e2e32); - --g-border-subtle: var(--bitfun-border-subtle, #27272a); + --g-border: var(--bitfun-border); + --g-border-subtle: var(--bitfun-border-subtle); - --g-element: var(--bitfun-element-bg, #27272a); - --g-element-hover: var(--bitfun-element-hover, #3f3f46); + --g-element: var(--bitfun-element-bg); + --g-element-hover: var(--bitfun-element-hover); - --g-accent: var(--bitfun-accent, #60a5fa); - --g-accent-hover: var(--bitfun-accent-hover, #3b82f6); - --g-accent-soft: color-mix(in srgb, var(--bitfun-accent, #60a5fa) 16%, transparent); + --g-accent: var(--bitfun-accent); + --g-accent-hover: var(--bitfun-accent-hover); + --g-accent-soft: color-mix(in srgb, var(--bitfun-accent) 16%, transparent); /* Stones — dark theme defaults. * Black stones use a lighter rim so they read against the dark board surface; @@ -44,12 +44,10 @@ body, html { margin: 0; padding: 0; height: 100%; } --g-stone-white: #f1f1f3; --g-stone-white-stroke: rgba(0, 0, 0, 0.35); - --g-radius: var(--bitfun-radius-lg, 8px); - --g-radius-sm: var(--bitfun-radius, 6px); + --g-radius: var(--bitfun-radius-lg); + --g-radius-sm: var(--bitfun-radius); - --g-sans: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "PingFang SC", - "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei UI", "Microsoft YaHei", - "Helvetica Neue", Helvetica, Arial, sans-serif); + --g-sans: var(--bitfun-font-sans); --g-dur: 160ms; --g-ease: cubic-bezier(.2, .8, .2, 1); @@ -422,7 +420,7 @@ button { font-family: inherit; cursor: pointer; } .btn--primary { background: var(--g-accent); - color: #fff; + color: var(--bitfun-text-on-accent); border-color: var(--g-accent); flex: initial; padding: 8px 18px; @@ -503,7 +501,7 @@ button { font-family: inherit; cursor: pointer; } ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { - background: var(--bitfun-scrollbar-thumb, rgba(255, 255, 255, 0.12)); + background: var(--bitfun-scrollbar-thumb); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-regex-playground/style.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-regex-playground/style.css index e56c4d171b..cc03d52a70 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-regex-playground/style.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/builtin-regex-playground/style.css @@ -2,11 +2,11 @@ * Design system reference: * palette ─ Inherits BitFun host theme (--bitfun-* tokens) so it reads * as a native panel under both bitfun-dark and bitfun-light. - * Local --rx-* tokens are derived from the host vars with - * standalone-safe fallbacks matching the default dark theme. + * Local --rx-* tokens are derived from the required host vars; + * the host contract owns first-paint defaults. * accent ─ host primary (cool blue / slate) for focus & active states; * warning amber as the secondary "match" highlight. - * type ─ system mono (code) + system sans (UI), follows --bitfun-font-* + * type ─ system mono (code) + system sans (UI), follows the two registered host font variables * pattern ─ bento-style cards on calm host surfaces * motion ─ 150-300ms color-shift micro-interactions, no scale jumps */ @@ -20,67 +20,52 @@ body, html { margin: 0; padding: 0; height: 100%; } [hidden] { display: none !important; } :root { + color-scheme: dark; /* Surfaces — drive everything off host bg tokens so the playground tracks * BitFun light/dark automatically. Fallbacks mirror the default dark theme. */ - --rx-bg: var(--bitfun-bg, #0e0e10); - --rx-bg-2: var(--bitfun-bg-tertiary, #121214); - --rx-surface: var(--bitfun-bg-secondary, #1c1c1f); - --rx-surface-2: var(--bitfun-element-bg, rgba(255,255,255,0.06)); - --rx-surface-3: var(--bitfun-element-hover, rgba(255,255,255,0.10)); + --rx-bg: var(--bitfun-bg); + --rx-bg-2: var(--bitfun-bg-tertiary); + --rx-surface: var(--bitfun-bg-secondary); + --rx-surface-2: var(--bitfun-element-bg); + --rx-surface-3: var(--bitfun-element-hover); - --rx-border: var(--bitfun-border-subtle, rgba(255,255,255,0.10)); - --rx-border-strong: var(--bitfun-border, rgba(255,255,255,0.18)); - --rx-border-bright: var(--bitfun-border, rgba(255,255,255,0.28)); + --rx-border: var(--bitfun-border-subtle); + --rx-border-strong: var(--bitfun-border); + --rx-border-bright: var(--bitfun-border); - --rx-text: var(--bitfun-text, #e8e8e8); - --rx-text-soft: var(--bitfun-text-secondary, #b0b0b0); - --rx-text-mute: var(--bitfun-text-muted, #858585); - --rx-text-dim: var(--bitfun-text-muted, #6a6a6a); + --rx-text: var(--bitfun-text); + --rx-text-soft: var(--bitfun-text-secondary); + --rx-text-mute: var(--bitfun-text-muted); + --rx-text-dim: var(--bitfun-text-muted); /* Accent — follows host primary (blue in dark, slate in light) instead of * the previous saturated "run green" which clashed with BitFun's neutral palette. */ - --rx-accent: var(--bitfun-accent, #60a5fa); - --rx-accent-strong: var(--bitfun-accent-hover, #3b82f6); - --rx-accent-soft: rgba(96,165,250,0.14); + --rx-accent: var(--bitfun-accent); + --rx-accent-strong: var(--bitfun-accent-hover); + --rx-accent-soft: color-mix(in srgb, var(--rx-accent) 14%, transparent); /* Semantic colors — pulled from host so they harmonize with the rest of BitFun. */ - --rx-match: var(--bitfun-warning, #f59e0b); /* warm match highlight */ - --rx-match-soft: rgba(245,158,11,0.18); - --rx-error: var(--bitfun-error, #ef4444); - --rx-info: var(--bitfun-info, #E1AB80); - --rx-group: #b39dff; /* capture-group accent */ - --rx-string: var(--bitfun-success, #34d399); + --rx-match: var(--bitfun-warning); /* warm match highlight */ + --rx-match-soft: color-mix(in srgb, var(--rx-match) 18%, transparent); + --rx-error: var(--bitfun-error); + --rx-info: var(--bitfun-info); + --rx-group: var(--bitfun-accent-secondary); /* capture-group accent */ + --rx-string: var(--bitfun-success); - --rx-radius: var(--bitfun-radius, 8px); + --rx-radius: var(--bitfun-radius); --rx-radius-sm: 6px; - --rx-shadow-card: 0 1px 0 rgba(255,255,255,0.025) inset, 0 4px 14px -8px rgba(0,0,0,0.55); - --rx-shadow-elevated: 0 1px 0 rgba(255,255,255,0.035) inset, 0 16px 32px -18px rgba(0,0,0,0.7); + --rx-shadow-card: var(--bitfun-shadow-card); + --rx-shadow-elevated: var(--bitfun-shadow-overlay); - --rx-mono: var(--bitfun-font-mono, "JetBrains Mono", "FiraCode", ui-monospace, "SFMono-Regular", - "SF Mono", Menlo, Monaco, "Cascadia Mono", "Cascadia Code", Consolas, - "Liberation Mono", "Courier New", monospace); - --rx-sans: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "SF Pro Text", - "PingFang SC", "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei UI", - "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif); + --rx-mono: var(--bitfun-font-mono); + --rx-sans: var(--bitfun-font-sans); --rx-dur: 200ms; --rx-ease: cubic-bezier(.2,.8,.2,1); } -/* Light-theme local overrides — host already swaps --bitfun-* tokens, but a - * few decorative pieces (rgba accent washes, capture-group badge, code chips) - * benefit from sturdier alpha / hue picks against a near-white surface. */ [data-bf-appearance-mode="light"] { - --rx-accent-soft: rgba(71,85,105,0.10); - --rx-match-soft: rgba(192,140,66,0.18); - --rx-group: #6b5a89; - --rx-shadow-card: - 0 1px 0 rgba(255,255,255,0.6) inset, - 0 1px 2px rgba(15,23,42,0.06), - 0 4px 14px -8px rgba(15,23,42,0.10); - --rx-shadow-elevated: - 0 1px 0 rgba(255,255,255,0.6) inset, - 0 12px 32px -18px rgba(15,23,42,0.20); + color-scheme: light; } body { @@ -98,8 +83,8 @@ button, input, textarea, select { font-family: inherit; color: inherit; } /* Page wash: very faint accent halos on the host background — keeps the * surface feeling alive without introducing a competing hue. */ background: - radial-gradient(1000px 500px at 90% -10%, rgba(96,165,250,0.05), transparent 60%), - radial-gradient(900px 500px at -10% 110%, rgba(139,92,246,0.035), transparent 55%), + radial-gradient(1000px 500px at 90% -10%, color-mix(in srgb, var(--rx-accent) 5%, transparent), transparent 60%), + radial-gradient(900px 500px at -10% 110%, color-mix(in srgb, var(--rx-group) 4%, transparent), transparent 55%), var(--rx-bg); } @@ -666,11 +651,11 @@ button, input, textarea, select { font-family: inherit; color: inherit; } ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { - background: var(--bitfun-scrollbar-thumb, rgba(255,255,255,0.14)); + background: var(--bitfun-scrollbar-thumb); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { - background: var(--bitfun-scrollbar-thumb-hover, rgba(255,255,255,0.26)); + background: var(--bitfun-scrollbar-thumb-hover); } /* ── Reduced motion ─────────────────────────────────── */ @@ -710,22 +695,10 @@ button, input, textarea, select { font-family: inherit; color: inherit; } .match__groups { margin-left: 40px; } } -/* ── Light theme adaptation ───────────────────────────────────────────── - * The host (see bridge_builder.rs) writes [data-bf-appearance-mode="light"] on - * AND repaints all --bitfun-* CSS variables. Because every --rx-* token above - * already proxies through var(--bitfun-…), most of the playground re-tints - * automatically. Only a handful of decorative pieces — page wash, frosted - * topbar tint — need an explicit ivory pass. */ -[data-bf-appearance-mode="light"] .rx { - background: - radial-gradient(1000px 500px at 90% -10%, rgba(71,85,105,0.05), transparent 60%), - radial-gradient(900px 500px at -10% 110%, rgba(124,58,237,0.04), transparent 55%), - var(--rx-bg); -} [data-bf-appearance-mode="light"] .topbar { background: color-mix(in srgb, var(--rx-bg) 85%, transparent); border-bottom-color: var(--rx-border); } [data-bf-appearance-mode="light"] .pattern-error { - color: #b91c1c; + color: var(--rx-error); } diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/style.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/style.css index 611feace90..623fe7d462 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/style.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/style.css @@ -1,32 +1,32 @@ /* styles/tokens.css */ /* Git Graph MiniApp — theme tokens (host --bitfun-* when running in BitFun) */ :root { - --bg: var(--bitfun-bg, #0d1117); - --bg-surface: var(--bitfun-bg-secondary, #161b22); - --bg-hover: var(--bitfun-element-hover, #1c2333); - --bg-active: var(--bitfun-element-bg, #1f2a3d); - --border: var(--bitfun-border, #30363d); - --border-light: var(--bitfun-border-subtle, #21262d); - --text: var(--bitfun-text, #e6edf3); - --text-sec: var(--bitfun-text-secondary, #8b949e); - --text-dim: var(--bitfun-text-muted, #484f58); - --accent: var(--bitfun-accent, #58a6ff); - --accent-dim: var(--bitfun-accent-hover, #1f6feb); - --green: var(--bitfun-success, #3fb950); - --red: var(--bitfun-error, #f85149); - --orange: var(--bitfun-warning, #d29922); - --purple: var(--bitfun-info, #bc8cff); - --branch-1: var(--bitfun-accent, #58a6ff); - --branch-2: var(--bitfun-success, #3fb950); - --branch-3: var(--bitfun-info, #bc8cff); - --branch-4: var(--bitfun-warning, #f0883e); + --bg: var(--bitfun-bg); + --bg-surface: var(--bitfun-bg-secondary); + --bg-hover: var(--bitfun-element-hover); + --bg-active: var(--bitfun-element-bg); + --border: var(--bitfun-border); + --border-light: var(--bitfun-border-subtle); + --text: var(--bitfun-text); + --text-sec: var(--bitfun-text-secondary); + --text-dim: var(--bitfun-text-muted); + --accent: var(--bitfun-accent); + --accent-dim: var(--bitfun-accent-hover); + --green: var(--bitfun-success); + --red: var(--bitfun-error); + --orange: var(--bitfun-warning); + --purple: var(--bitfun-accent-secondary); + --branch-1: var(--bitfun-accent); + --branch-2: var(--bitfun-success); + --branch-3: var(--bitfun-accent-secondary); + --branch-4: var(--bitfun-warning); --branch-5: #f778ba; --branch-6: #79c0ff; --branch-7: #56d364; - --radius: var(--bitfun-radius, 6px); - --radius-lg: var(--bitfun-radius-lg, 10px); - --graph-node-stroke: var(--bitfun-bg, #0d1117); - --graph-uncommitted: var(--text-dim, #808080); + --radius: var(--bitfun-radius); + --radius-lg: var(--bitfun-radius-lg); + --graph-node-stroke: var(--bitfun-bg); + --graph-uncommitted: var(--text-dim); --graph-lane-width: 18px; --graph-row-height: 28px; } @@ -34,7 +34,7 @@ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } body { - font-family: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif); + font-family: var(--bitfun-font-sans); font-size: 13px; color: var(--text); background: var(--bg); @@ -70,7 +70,7 @@ body { text-overflow: ellipsis; white-space: nowrap; max-width: 280px; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); } .toolbar__branch-filter { position: relative; } .toolbar__branch-filter .chevron { margin-left: 4px; opacity: .8; } @@ -85,7 +85,7 @@ body { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 8px 24px rgba(0,0,0,.25); + box-shadow: var(--bitfun-shadow-overlay); z-index: 200; padding: 4px 0; } @@ -121,8 +121,8 @@ body { } .btn--primary { background: var(--accent-dim); - color: #fff; - border-color: rgba(88,166,255,.4); + color: var(--bitfun-text-on-accent); + border-color: color-mix(in srgb, var(--accent) 40%, transparent); } .btn--primary:hover { background: var(--accent); } .btn--primary:active { background: var(--accent-dim); } @@ -177,19 +177,19 @@ body { line-height: 1.4; } .badge--branch { - background: rgba(88,166,255,.15); + background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); - border: 1px solid rgba(88,166,255,.25); + border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent); } .badge--status { - background: rgba(63,185,80,.12); + background: color-mix(in srgb, var(--green) 12%, transparent); color: var(--green); - border: 1px solid rgba(63,185,80,.2); + border: 1px solid color-mix(in srgb, var(--green) 20%, transparent); } .badge--status.has-changes { - background: rgba(210,153,34,.12); + background: color-mix(in srgb, var(--orange) 12%, transparent); color: var(--orange); - border-color: rgba(210,153,34,.2); + border-color: color-mix(in srgb, var(--orange) 20%, transparent); } /* ── Empty state ─────────────────── */ @@ -260,7 +260,7 @@ body { } .commit-row:hover { background: var(--bg-hover); } .commit-row.selected { background: var(--bg-active); } -.commit-row.find-highlight { background: rgba(88,166,255,.15); } +.commit-row.find-highlight { background: color-mix(in srgb, var(--accent) 15%, transparent); } .commit-row.compare-selected { box-shadow: inset 0 0 0 2px var(--accent); } .commit-row.commit-row--stash .graph-node--stash-outer { fill: none; @@ -289,7 +289,7 @@ body { } .commit-row__hash { flex-shrink: 0; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-family: var(--bitfun-font-mono); font-size: 11px; color: var(--accent); width: 56px; @@ -318,19 +318,19 @@ body { white-space: nowrap; } .ref-tag--head { - background: rgba(88,166,255,.18); + background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); } .ref-tag--branch { - background: rgba(63,185,80,.14); + background: color-mix(in srgb, var(--green) 14%, transparent); color: var(--green); } .ref-tag--tag { - background: rgba(210,153,34,.14); + background: color-mix(in srgb, var(--orange) 14%, transparent); color: var(--orange); } .ref-tag--remote { - background: rgba(188,140,255,.14); + background: color-mix(in srgb, var(--purple) 14%, transparent); color: var(--purple); } @@ -350,7 +350,7 @@ body { font-size: 11px; color: var(--text-dim); text-align: right; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-family: var(--bitfun-font-mono); } /* styles/graph.css */ @@ -392,7 +392,7 @@ body { display: flex; flex-direction: column; overflow: hidden; - box-shadow: -4px 0 12px rgba(0,0,0,.08); + box-shadow: var(--bitfun-shadow-card); } .detail-panel-resizer { width: 6px; @@ -485,7 +485,7 @@ body { flex-shrink: 0; } .detail-code-preview__filename { - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 12px; color: var(--text); overflow: hidden; @@ -513,7 +513,7 @@ body { .detail-code-preview__error { color: var(--red); } .detail-code-preview__diff { margin: 0; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 11px; line-height: 1.6; white-space: pre; @@ -522,8 +522,8 @@ body { color: var(--text); } .detail-code-preview__diff .diff-line { display: block; } -.detail-code-preview__diff .diff-line.diff-add { color: var(--green); background: rgba(63,185,80,.08); } -.detail-code-preview__diff .diff-line.diff-del { color: var(--red); background: rgba(248,81,73,.08); } +.detail-code-preview__diff .diff-line.diff-add { color: var(--green); background: color-mix(in srgb, var(--green) 8%, transparent); } +.detail-code-preview__diff .diff-line.diff-del { color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); } .detail-code-preview__diff .diff-line.diff-hunk { color: var(--text-dim); } .detail-section { @@ -541,7 +541,7 @@ body { margin-bottom: 8px; } .detail-hash { - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 12px; color: var(--accent); word-break: break-all; @@ -588,7 +588,7 @@ body { background: var(--bg); border-radius: var(--radius); border: 1px solid var(--border-light); - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 11px; line-height: 1.5; white-space: pre-wrap; @@ -597,8 +597,8 @@ body { overflow: auto; } .diff-line { display: block; } -.diff-line.diff-add { color: var(--green); background: rgba(63,185,80,.08); } -.diff-line.diff-del { color: var(--red); background: rgba(248,81,73,.08); } +.diff-line.diff-add { color: var(--green); background: color-mix(in srgb, var(--green) 8%, transparent); } +.diff-line.diff-del { color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); } .diff-line.diff-hunk { color: var(--text-dim); } .detail-file__name { flex: 1; @@ -606,7 +606,7 @@ body { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); color: var(--text-sec); } .detail-file__stat { display: flex; gap: 6px; flex-shrink: 0; font-size: 11px; } @@ -651,7 +651,7 @@ body { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 4px 16px rgba(0,0,0,.2); + box-shadow: var(--bitfun-shadow-overlay); } .find-widget__input { width: 220px; @@ -680,7 +680,7 @@ body { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 8px 24px rgba(0,0,0,.3); + box-shadow: var(--bitfun-shadow-overlay); font-size: 12px; } .context-menu[aria-hidden="true"] { display: none; } @@ -722,7 +722,7 @@ body { background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0,0,0,.35); + box-shadow: var(--bitfun-shadow-overlay); } .modal-dialog__header { display: flex; diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/detail-panel.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/detail-panel.css index 818d96290a..13e37e4edc 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/detail-panel.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/detail-panel.css @@ -11,7 +11,7 @@ display: flex; flex-direction: column; overflow: hidden; - box-shadow: -4px 0 12px rgba(0,0,0,.08); + box-shadow: var(--bitfun-shadow-card); } .detail-panel-resizer { width: 6px; @@ -104,7 +104,7 @@ flex-shrink: 0; } .detail-code-preview__filename { - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 12px; color: var(--text); overflow: hidden; @@ -132,7 +132,7 @@ .detail-code-preview__error { color: var(--red); } .detail-code-preview__diff { margin: 0; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 11px; line-height: 1.6; white-space: pre; @@ -141,8 +141,8 @@ color: var(--text); } .detail-code-preview__diff .diff-line { display: block; } -.detail-code-preview__diff .diff-line.diff-add { color: var(--green); background: rgba(63,185,80,.08); } -.detail-code-preview__diff .diff-line.diff-del { color: var(--red); background: rgba(248,81,73,.08); } +.detail-code-preview__diff .diff-line.diff-add { color: var(--green); background: color-mix(in srgb, var(--green) 8%, transparent); } +.detail-code-preview__diff .diff-line.diff-del { color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); } .detail-code-preview__diff .diff-line.diff-hunk { color: var(--text-dim); } .detail-section { @@ -160,7 +160,7 @@ margin-bottom: 8px; } .detail-hash { - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 12px; color: var(--accent); word-break: break-all; @@ -207,7 +207,7 @@ background: var(--bg); border-radius: var(--radius); border: 1px solid var(--border-light); - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); font-size: 11px; line-height: 1.5; white-space: pre-wrap; @@ -216,8 +216,8 @@ overflow: auto; } .diff-line { display: block; } -.diff-line.diff-add { color: var(--green); background: rgba(63,185,80,.08); } -.diff-line.diff-del { color: var(--red); background: rgba(248,81,73,.08); } +.diff-line.diff-add { color: var(--green); background: color-mix(in srgb, var(--green) 8%, transparent); } +.diff-line.diff-del { color: var(--red); background: color-mix(in srgb, var(--red) 8%, transparent); } .diff-line.diff-hunk { color: var(--text-dim); } .detail-file__name { flex: 1; @@ -225,7 +225,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); color: var(--text-sec); } .detail-file__stat { display: flex; gap: 6px; flex-shrink: 0; font-size: 11px; } diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/layout.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/layout.css index 866044d095..491ae7c98e 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/layout.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/layout.css @@ -23,7 +23,7 @@ text-overflow: ellipsis; white-space: nowrap; max-width: 280px; - font-family: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace); + font-family: var(--bitfun-font-mono); } .toolbar__branch-filter { position: relative; } .toolbar__branch-filter .chevron { margin-left: 4px; opacity: .8; } @@ -38,7 +38,7 @@ background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 8px 24px rgba(0,0,0,.25); + box-shadow: var(--bitfun-shadow-overlay); z-index: 200; padding: 4px 0; } @@ -74,8 +74,8 @@ } .btn--primary { background: var(--accent-dim); - color: #fff; - border-color: rgba(88,166,255,.4); + color: var(--bitfun-text-on-accent); + border-color: color-mix(in srgb, var(--accent) 40%, transparent); } .btn--primary:hover { background: var(--accent); } .btn--primary:active { background: var(--accent-dim); } @@ -130,19 +130,19 @@ line-height: 1.4; } .badge--branch { - background: rgba(88,166,255,.15); + background: color-mix(in srgb, var(--accent) 15%, transparent); color: var(--accent); - border: 1px solid rgba(88,166,255,.25); + border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent); } .badge--status { - background: rgba(63,185,80,.12); + background: color-mix(in srgb, var(--green) 12%, transparent); color: var(--green); - border: 1px solid rgba(63,185,80,.2); + border: 1px solid color-mix(in srgb, var(--green) 20%, transparent); } .badge--status.has-changes { - background: rgba(210,153,34,.12); + background: color-mix(in srgb, var(--orange) 12%, transparent); color: var(--orange); - border-color: rgba(210,153,34,.2); + border-color: color-mix(in srgb, var(--orange) 20%, transparent); } /* ── Empty state ─────────────────── */ @@ -213,7 +213,7 @@ } .commit-row:hover { background: var(--bg-hover); } .commit-row.selected { background: var(--bg-active); } -.commit-row.find-highlight { background: rgba(88,166,255,.15); } +.commit-row.find-highlight { background: color-mix(in srgb, var(--accent) 15%, transparent); } .commit-row.compare-selected { box-shadow: inset 0 0 0 2px var(--accent); } .commit-row.commit-row--stash .graph-node--stash-outer { fill: none; @@ -242,7 +242,7 @@ } .commit-row__hash { flex-shrink: 0; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-family: var(--bitfun-font-mono); font-size: 11px; color: var(--accent); width: 56px; @@ -271,19 +271,19 @@ white-space: nowrap; } .ref-tag--head { - background: rgba(88,166,255,.18); + background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); } .ref-tag--branch { - background: rgba(63,185,80,.14); + background: color-mix(in srgb, var(--green) 14%, transparent); color: var(--green); } .ref-tag--tag { - background: rgba(210,153,34,.14); + background: color-mix(in srgb, var(--orange) 14%, transparent); color: var(--orange); } .ref-tag--remote { - background: rgba(188,140,255,.14); + background: color-mix(in srgb, var(--purple) 14%, transparent); color: var(--purple); } @@ -303,5 +303,5 @@ font-size: 11px; color: var(--text-dim); text-align: right; - font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; + font-family: var(--bitfun-font-mono); } diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/overlay.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/overlay.css index 20694046e2..b4960d1674 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/overlay.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/overlay.css @@ -35,7 +35,7 @@ background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 4px 16px rgba(0,0,0,.2); + box-shadow: var(--bitfun-shadow-overlay); } .find-widget__input { width: 220px; @@ -64,7 +64,7 @@ background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius); - box-shadow: 0 8px 24px rgba(0,0,0,.3); + box-shadow: var(--bitfun-shadow-overlay); font-size: 12px; } .context-menu[aria-hidden="true"] { display: none; } @@ -106,7 +106,7 @@ background: var(--bg-surface); border: 1px solid var(--border); border-radius: var(--radius-lg); - box-shadow: 0 16px 48px rgba(0,0,0,.35); + box-shadow: var(--bitfun-shadow-overlay); } .modal-dialog__header { display: flex; diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/tokens.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/tokens.css index 0f1649176e..6f00ce692b 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/tokens.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/styles/tokens.css @@ -1,31 +1,31 @@ /* Git Graph MiniApp — theme tokens (host --bitfun-* when running in BitFun) */ :root { - --bg: var(--bitfun-bg, #0d1117); - --bg-surface: var(--bitfun-bg-secondary, #161b22); - --bg-hover: var(--bitfun-element-hover, #1c2333); - --bg-active: var(--bitfun-element-bg, #1f2a3d); - --border: var(--bitfun-border, #30363d); - --border-light: var(--bitfun-border-subtle, #21262d); - --text: var(--bitfun-text, #e6edf3); - --text-sec: var(--bitfun-text-secondary, #8b949e); - --text-dim: var(--bitfun-text-muted, #484f58); - --accent: var(--bitfun-accent, #58a6ff); - --accent-dim: var(--bitfun-accent-hover, #1f6feb); - --green: var(--bitfun-success, #3fb950); - --red: var(--bitfun-error, #f85149); - --orange: var(--bitfun-warning, #d29922); - --purple: var(--bitfun-info, #bc8cff); - --branch-1: var(--bitfun-accent, #58a6ff); - --branch-2: var(--bitfun-success, #3fb950); - --branch-3: var(--bitfun-info, #bc8cff); - --branch-4: var(--bitfun-warning, #f0883e); + --bg: var(--bitfun-bg); + --bg-surface: var(--bitfun-bg-secondary); + --bg-hover: var(--bitfun-element-hover); + --bg-active: var(--bitfun-element-bg); + --border: var(--bitfun-border); + --border-light: var(--bitfun-border-subtle); + --text: var(--bitfun-text); + --text-sec: var(--bitfun-text-secondary); + --text-dim: var(--bitfun-text-muted); + --accent: var(--bitfun-accent); + --accent-dim: var(--bitfun-accent-hover); + --green: var(--bitfun-success); + --red: var(--bitfun-error); + --orange: var(--bitfun-warning); + --purple: var(--bitfun-accent-secondary); + --branch-1: var(--bitfun-accent); + --branch-2: var(--bitfun-success); + --branch-3: var(--bitfun-accent-secondary); + --branch-4: var(--bitfun-warning); --branch-5: #f778ba; --branch-6: #79c0ff; --branch-7: #56d364; - --radius: var(--bitfun-radius, 6px); - --radius-lg: var(--bitfun-radius-lg, 10px); - --graph-node-stroke: var(--bitfun-bg, #0d1117); - --graph-uncommitted: var(--text-dim, #808080); + --radius: var(--bitfun-radius); + --radius-lg: var(--bitfun-radius-lg); + --graph-node-stroke: var(--bitfun-bg); + --graph-uncommitted: var(--text-dim); --graph-lane-width: 18px; --graph-row-height: 28px; } @@ -33,7 +33,7 @@ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } body { - font-family: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif); + font-family: var(--bitfun-font-sans); font-size: 13px; color: var(--text); background: var(--bg); diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/ui.js b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/ui.js index cf7c1802b5..86718662a9 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/ui.js +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/ui.js @@ -122,27 +122,34 @@ const root = document.documentElement; function getComputed(name) { - return getComputedStyle(root).getPropertyValue(name).trim() || null; + return getComputedStyle(root).getPropertyValue(name).trim(); + } + + function requireComputed(name) { + const value = getComputed(name); + if (!value) { + throw new Error('Git Graph requires the MiniApp appearance contract variable ' + name + '.'); + } + return value; } /** Returns array of 7 branch/lane colors from CSS variables (appearance-aware). */ window.__GG.getGraphColors = function () { const colors = []; for (let i = 1; i <= 7; i++) { - const v = getComputed('--branch-' + i); - colors.push(v || '#58a6ff'); + colors.push(requireComputed('--branch-' + i)); } return colors; }; /** Node stroke color (contrast with background). */ window.__GG.getNodeStroke = function () { - return getComputed('--graph-node-stroke') || getComputed('--bitfun-bg') || getComputed('--bg') || '#0d1117'; + return requireComputed('--graph-node-stroke'); }; /** Uncommitted / WIP line and node color. */ window.__GG.getUncommittedColor = function () { - return getComputed('--graph-uncommitted') || getComputed('--text-dim') || '#808080'; + return requireComputed('--graph-uncommitted'); }; })(); diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/ui/appearance.js b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/ui/appearance.js index 239ee2e055..b6d9a05f49 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/ui/appearance.js +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-git-graph/source/ui/appearance.js @@ -6,26 +6,33 @@ const root = document.documentElement; function getComputed(name) { - return getComputedStyle(root).getPropertyValue(name).trim() || null; + return getComputedStyle(root).getPropertyValue(name).trim(); + } + + function requireComputed(name) { + const value = getComputed(name); + if (!value) { + throw new Error('Git Graph requires the MiniApp appearance contract variable ' + name + '.'); + } + return value; } /** Returns array of 7 branch/lane colors from CSS variables (appearance-aware). */ window.__GG.getGraphColors = function () { const colors = []; for (let i = 1; i <= 7; i++) { - const v = getComputed('--branch-' + i); - colors.push(v || '#58a6ff'); + colors.push(requireComputed('--branch-' + i)); } return colors; }; /** Node stroke color (contrast with background). */ window.__GG.getNodeStroke = function () { - return getComputed('--graph-node-stroke') || getComputed('--bitfun-bg') || getComputed('--bg') || '#0d1117'; + return requireComputed('--graph-node-stroke'); }; /** Uncommitted / WIP line and node color. */ window.__GG.getUncommittedColor = function () { - return getComputed('--graph-uncommitted') || getComputed('--text-dim') || '#808080'; + return requireComputed('--graph-uncommitted'); }; })(); diff --git a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-icon-design-system/source/style.css b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-icon-design-system/source/style.css index b6d3bf2408..b9023ad997 100644 --- a/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-icon-design-system/source/style.css +++ b/src/crates/assembly/core/builtin_skills/miniapp-dev/references/examples/demo-icon-design-system/source/style.css @@ -1,36 +1,35 @@ /* ── Theme token aliases ────────────────────────────────────────────────────── */ /* Map --bitfun-* host variables to local names so every rule auto-adapts. */ :root { - --bg: var(--bitfun-bg, #121214); - --bg2: var(--bitfun-bg-secondary, #18181a); - --bg3: var(--bitfun-bg-tertiary, #0e0e10); - --bg-el: var(--bitfun-element-bg, #27272a); - --bg-hover: var(--bitfun-element-hover, #3f3f46); - --text: var(--bitfun-text, #e8e8e8); - --text2: var(--bitfun-text-secondary, #b0b0b0); - --text3: var(--bitfun-text-muted, #858585); - --accent: var(--bitfun-accent, #60a5fa); - --accent2: var(--bitfun-accent-hover, #3b82f6); - --success: var(--bitfun-success, #34d399); - --warning: var(--bitfun-warning, #f59e0b); - --danger: var(--bitfun-error, #ef4444); - --info: var(--bitfun-info, #60a5fa); - --border: var(--bitfun-border, #2e2e32); - --border2: var(--bitfun-border-subtle, #27272a); - --radius: var(--bitfun-radius, 6px); - --radius-lg: var(--bitfun-radius-lg, 10px); - --font: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif); - --font-mono: var(--bitfun-font-mono, ui-monospace, monospace); - --scrollbar: var(--bitfun-scrollbar-thumb, rgba(128,128,128,0.25)); + --bg: var(--bitfun-bg); + --bg2: var(--bitfun-bg-secondary); + --bg3: var(--bitfun-bg-tertiary); + --bg-el: var(--bitfun-element-bg); + --bg-hover: var(--bitfun-element-hover); + --text: var(--bitfun-text); + --text2: var(--bitfun-text-secondary); + --text3: var(--bitfun-text-muted); + --accent: var(--bitfun-accent); + --accent2: var(--bitfun-accent-hover); + --success: var(--bitfun-success); + --warning: var(--bitfun-warning); + --danger: var(--bitfun-error); + --info: var(--bitfun-info); + --border: var(--bitfun-border); + --border2: var(--bitfun-border-subtle); + --radius: var(--bitfun-radius); + --radius-lg: var(--bitfun-radius-lg); + --font: var(--bitfun-font-sans); + --font-mono: var(--bitfun-font-mono); + --scrollbar: var(--bitfun-scrollbar-thumb); /* Derived semantic tokens */ - --on-accent: #fff; /* text on accent-coloured surface */ - --on-danger: #fff; /* text on danger-coloured surface */ - --on-success: #fff; /* text on success-coloured surface */ + --on-accent: var(--bitfun-text-on-accent); + --on-danger: var(--bitfun-text-on-accent); + --on-success: var(--bitfun-text-on-accent); } -/* In light theme the on-accent/danger text must be white only if the accent is - dark enough; hosts should override via --bitfun-on-accent if needed. */ +/* On-accent and danger text use the registered --bitfun-text-on-accent projection. */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } diff --git a/src/crates/assembly/core/src/agentic/tools/implementations/generative_ui_tool.rs b/src/crates/assembly/core/src/agentic/tools/implementations/generative_ui_tool.rs index 97e311fb1c..f7dba56478 100644 --- a/src/crates/assembly/core/src/agentic/tools/implementations/generative_ui_tool.rs +++ b/src/crates/assembly/core/src/agentic/tools/implementations/generative_ui_tool.rs @@ -55,7 +55,7 @@ impl GenerativeUITool { } fn bitfun_design_system_reminder() -> &'static str { - "BitFun design-system reminder: when the widget should feel native to the host BitFun app, compose the provided `bf-*` scaffold classes first and use host-projected appearance tokens instead of hard-coded design values. Prefer CSS variables such as `var(--color-bg-primary)`, `var(--color-bg-secondary)`, `var(--color-bg-scene)`, `var(--color-bg-elevated)`, `var(--color-text-primary)`, `var(--color-text-secondary)`, `var(--color-text-muted)`, `var(--color-accent-500)`, `var(--color-accent-600)`, `var(--border-subtle)`, `var(--border-base)`, `var(--border-medium)`, `var(--element-bg-subtle)`, `var(--element-bg-soft)`, `var(--element-bg-base)`, `var(--element-bg-medium)`, `var(--shadow-*)`, `var(--motion-*)`, `var(--easing-*)`, `var(--font-sans)`, and `var(--font-mono)`. Radius, spacing, font-size, and font-weight variables are iframe-local scaffold values rather than host appearance extension points. Support both `bitfun-dark` and `bitfun-light`; do not assume dark-only, purple-only, or landing-page styling. Favor compact desktop workbench layouts, panel/card surfaces, strong information hierarchy, and reusable BitFun component patterns. Avoid hard-coded colors, arbitrary spacing, giant hero sections, fake mobile chrome, and full marketing-page shells; prefer understated, premium UI with layered surfaces, restrained contrast, subtle borders, and do not use thick left-accent emphasis blocks." + "BitFun design-system reminder: when the widget should feel native to the host BitFun app, compose the provided `bf-*` scaffold classes first and use host-projected canonical tokens instead of hard-coded design values. Prefer CSS variables such as `var(--bf-color-surface-canvas)`, `var(--bf-color-surface-panel)`, `var(--bf-color-surface-scene)`, `var(--bf-color-surface-raised)`, `var(--bf-color-content-primary)`, `var(--bf-color-content-secondary)`, `var(--bf-color-content-muted)`, `var(--bf-color-accent-default)`, `var(--bf-color-accent-hover)`, `var(--bf-color-border-subtle)`, `var(--bf-color-border-default)`, `var(--bf-color-border-strong)`, `var(--bf-color-action-neutral-surface)`, `var(--bf-color-action-neutral-surface-hover)`, `var(--bf-color-action-quiet-hover)`, `var(--bf-shadow-*)`, `var(--bf-motion-duration-*)`, `var(--bf-motion-easing-*)`, `var(--bf-font-family-sans)`, and `var(--bf-font-family-mono)`. Radius, spacing, font-size, and font-weight variables are iframe-local scaffold values rather than host appearance extension points. Support both `bitfun-dark` and `bitfun-light`; do not assume dark-only, purple-only, or landing-page styling. Favor compact desktop workbench layouts, panel/card surfaces, strong information hierarchy, and reusable BitFun component patterns. Avoid hard-coded colors, arbitrary spacing, giant hero sections, fake mobile chrome, and full marketing-page shells; prefer understated, premium UI with layered surfaces, restrained contrast, subtle borders, and do not use thick left-accent emphasis blocks." } fn bitfun_widget_scaffold_reminder() -> &'static str { diff --git a/src/crates/contracts/product-domains/src/miniapp/bridge_builder.rs b/src/crates/contracts/product-domains/src/miniapp/bridge_builder.rs index 2974e3c702..c7b76ca4b3 100644 --- a/src/crates/contracts/product-domains/src/miniapp/bridge_builder.rs +++ b/src/crates/contracts/product-domains/src/miniapp/bridge_builder.rs @@ -347,5 +347,5 @@ pub fn scroll_boundary_script() -> &'static str { /// Minimal MiniApp iframe first-paint contract before the host sends Appearance variables. pub fn build_miniapp_default_appearance_css() -> &'static str { - r#""# + include_str!("generated/default_appearance_style.html") } diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/coding-selfie/style.css b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/coding-selfie/style.css index afc19f95eb..e4546a9fed 100644 --- a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/coding-selfie/style.css +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/coding-selfie/style.css @@ -3,8 +3,7 @@ * palette ─ Inherits BitFun host theme (--bitfun-* tokens). Surfaces, * text and borders all proxy through host vars so the dashboard * reads as a native BitFun panel under both bitfun-dark and - * bitfun-light. Standalone fallbacks mirror the default dark - * theme (#0e0e10 / #e8e8e8 / #60a5fa). + * bitfun-light. The host contract owns first-paint defaults. * accent ─ host primary (cool blue / slate) for hero/streak/heatmap * accents. Diff stats keep semantic green/red so additions and * deletions stay glanceable. @@ -13,58 +12,45 @@ :root { color-scheme: dark; - --cs-bg: var(--bitfun-bg, #0e0e10); - --cs-card: var(--bitfun-bg-secondary, #1c1c1f); - --cs-card-2: var(--bitfun-bg-tertiary, #121214); + --cs-bg: var(--bitfun-bg); + --cs-card: var(--bitfun-bg-secondary); + --cs-card-2: var(--bitfun-bg-tertiary); - --cs-border: var(--bitfun-border-subtle, rgba(255, 255, 255, 0.10)); - --cs-border-strong: var(--bitfun-border, rgba(255, 255, 255, 0.18)); + --cs-border: var(--bitfun-border-subtle); + --cs-border-strong: var(--bitfun-border); - --cs-text: var(--bitfun-text, #e8e8e8); - --cs-text-2: var(--bitfun-text-secondary, #b0b0b0); - --cs-text-muted: var(--bitfun-text-muted, #858585); + --cs-text: var(--bitfun-text); + --cs-text-2: var(--bitfun-text-secondary); + --cs-text-muted: var(--bitfun-text-muted); /* Primary accent now follows the host (cool blue in dark, slate in light) * so the dashboard stops fighting BitFun's neutral palette. The previous * "run green" is preserved as a secondary semantic color (--cs-add). */ - --cs-accent: var(--bitfun-accent, #60a5fa); - --cs-accent-2: var(--bitfun-accent-hover, #3b82f6); - --cs-accent-soft: rgba(96, 165, 250, 0.14); - --cs-accent-glow: 0 0 20px rgba(96, 165, 250, 0.20); + --cs-accent: var(--bitfun-accent); + --cs-accent-2: var(--bitfun-accent-hover); + --cs-accent-soft: color-mix(in srgb, var(--cs-accent) 14%, transparent); + --cs-accent-glow: 0 0 20px color-mix(in srgb, var(--cs-accent) 20%, transparent); /* Diff / activity semantics — kept on green/red regardless of host accent * because additions and deletions must stay universally readable. */ - --cs-add: var(--bitfun-success, #34d399); - --cs-del: var(--bitfun-error, #f87171); - --cs-warn: var(--bitfun-warning, #f59e0b); - - /* RGB triplet of the host accent — used by .cs-heat-* gradients to mix - * tinted alpha steps without hardcoding the brand color. Updated by the - * light-theme block below. */ - --cs-accent-rgb: 96, 165, 250; - --cs-add-rgb: 52, 211, 153; + --cs-add: var(--bitfun-success); + --cs-del: var(--bitfun-error); + --cs-warn: var(--bitfun-warning); --cs-bg-grad: - radial-gradient(ellipse at top, rgba(var(--cs-accent-rgb), 0.05), transparent 60%), - radial-gradient(ellipse at bottom right, rgba(139,92,246, 0.04), transparent 50%), + radial-gradient(ellipse at top, color-mix(in srgb, var(--cs-accent) 5%, transparent), transparent 60%), + radial-gradient(ellipse at bottom right, color-mix(in srgb, var(--bitfun-accent-secondary) 4%, transparent), transparent 50%), var(--cs-bg); - --cs-radius: var(--bitfun-radius-lg, 12px); - --cs-radius-sm: var(--bitfun-radius, 8px); - --cs-mono: var(--bitfun-font-mono, 'JetBrains Mono', 'FiraCode', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Monaco, 'Cascadia Mono', 'Cascadia Code', Consolas, 'Liberation Mono', 'Courier New', monospace); - --cs-sans: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Hiragino Sans GB', 'Segoe UI', 'Microsoft YaHei UI', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif); + --cs-radius: var(--bitfun-radius-lg); + --cs-radius-sm: var(--bitfun-radius); + --cs-mono: var(--bitfun-font-mono); + --cs-sans: var(--bitfun-font-sans); } [data-bf-appearance-mode="light"] { color-scheme: light; - /* Sturdier alpha & a slightly muted glow on near-white surfaces. */ - --cs-accent-soft: rgba(71, 85, 105, 0.10); - --cs-accent-glow: 0 0 0 transparent; - --cs-accent-rgb: 71, 85, 105; - --cs-add-rgb: 91, 154, 111; - --cs-bg-grad: - radial-gradient(ellipse at top, rgba(var(--cs-accent-rgb), 0.06), transparent 60%), - var(--cs-bg); + --cs-accent-glow: none; } * { box-sizing: border-box; } @@ -175,8 +161,8 @@ html, body { grid-column: span 9; padding: clamp(10px, 1.5vh, 16px) clamp(14px, 1.8vw, 20px); background: - radial-gradient(circle at 80% 0%, rgba(var(--cs-accent-rgb), 0.10), transparent 55%), - radial-gradient(circle at 0% 100%, rgba(139, 92, 246, 0.05), transparent 50%), + radial-gradient(circle at 80% 0%, color-mix(in srgb, var(--cs-accent) 10%, transparent), transparent 55%), + radial-gradient(circle at 0% 100%, color-mix(in srgb, var(--bitfun-accent-secondary) 5%, transparent), transparent 50%), var(--cs-card); justify-content: center; } @@ -186,7 +172,7 @@ html, body { right: -20%; width: 60%; height: 180%; - background: radial-gradient(ellipse, rgba(var(--cs-accent-rgb), 0.10), transparent 60%); + background: radial-gradient(ellipse, color-mix(in srgb, var(--cs-accent) 10%, transparent), transparent 60%); pointer-events: none; filter: blur(10px); } @@ -253,7 +239,7 @@ html, body { .cs-range-chip.is-active { background: var(--cs-accent-soft); color: var(--cs-accent); - border-color: rgba(var(--cs-accent-rgb), 0.45); + border-color: color-mix(in srgb, var(--cs-accent) 45%, transparent); } .cs-range-custom { display: inline-flex; @@ -275,7 +261,7 @@ html, body { } .cs-range-date:focus { outline: none; - border-color: rgba(var(--cs-accent-rgb), 0.55); + border-color: color-mix(in srgb, var(--cs-accent) 55%, transparent); } .cs-range-sep { color: var(--cs-text-muted); font-size: 12px; } @@ -318,9 +304,9 @@ html, body { .cs-tile-streak { grid-column: span 3; background: - linear-gradient(140deg, rgba(var(--cs-accent-rgb), 0.10), transparent 70%), + linear-gradient(140deg, color-mix(in srgb, var(--cs-accent) 10%, transparent), transparent 70%), var(--cs-card); - border-color: rgba(var(--cs-accent-rgb), 0.22); + border-color: color-mix(in srgb, var(--cs-accent) 22%, transparent); display: grid; grid-template-columns: auto auto 1fr; grid-template-rows: auto 1fr auto; @@ -528,7 +514,7 @@ html, body { border-radius: 2px; opacity: 0.85; } -.cs-hour-bar.peak::after { box-shadow: 0 0 12px rgba(var(--cs-accent-rgb), 0.45); opacity: 1; } +.cs-hour-bar.peak::after { box-shadow: 0 0 12px color-mix(in srgb, var(--cs-accent) 45%, transparent); opacity: 1; } .cs-hour-bar:hover { filter: brightness(1.2); } .cs-hours-axis { display: flex; @@ -603,12 +589,12 @@ html, body { .cs-heat-cell:hover { outline-color: var(--cs-accent); } .cs-heat-empty { background: transparent; pointer-events: none; } .cs-heat-0 { background: var(--cs-card-2); } -.cs-heat-1 { background: rgba(var(--cs-accent-rgb), 0.25); } -.cs-heat-2 { background: rgba(var(--cs-accent-rgb), 0.45); } -.cs-heat-3 { background: rgba(var(--cs-accent-rgb), 0.70); } +.cs-heat-1 { background: color-mix(in srgb, var(--cs-accent) 25%, transparent); } +.cs-heat-2 { background: color-mix(in srgb, var(--cs-accent) 45%, transparent); } +.cs-heat-3 { background: color-mix(in srgb, var(--cs-accent) 70%, transparent); } .cs-heat-4 { background: var(--cs-accent); - box-shadow: 0 0 10px rgba(var(--cs-accent-rgb), 0.35); + box-shadow: 0 0 10px color-mix(in srgb, var(--cs-accent) 35%, transparent); } /* Custom hover tooltip for heatmap cells (replaces native title delay). */ @@ -625,7 +611,7 @@ html, body { font-size: 12.5px; line-height: 1.35; white-space: nowrap; - box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); + box-shadow: var(--bitfun-shadow-overlay); } .cs-heatmap-legend { diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/coding-selfie/ui.js b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/coding-selfie/ui.js index faf400ba96..7a748d1f92 100644 --- a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/coding-selfie/ui.js +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/coding-selfie/ui.js @@ -417,7 +417,7 @@ function renderDonut(langs) { svg.innerHTML = ''; const total = langs.reduce((acc, l) => acc + l.weight, 0); if (total <= 0) { - svg.innerHTML = ''; + svg.innerHTML = ''; $('lang-legend').innerHTML = `
  • ${t('noCommitsThisRange')}
  • `; return; } @@ -444,7 +444,7 @@ function renderDonut(langs) { const s = slices[i]; const frac = s.weight / total; const dash = c * frac; - const color = s.isOther ? 'rgba(148,163,184,0.35)' : LANG_COLORS[i % LANG_COLORS.length]; + const color = s.isOther ? 'var(--cs-text-muted)' : LANG_COLORS[i % LANG_COLORS.length]; const arc = document.createElementNS('http://www.w3.org/2000/svg', 'circle'); arc.setAttribute('cx', '60'); arc.setAttribute('cy', '60'); @@ -469,7 +469,7 @@ function renderDonut(langs) { slices.forEach((s, i) => { const li = document.createElement('li'); li.className = 'cs-legend-row'; - const color = s.isOther ? 'rgba(148,163,184,0.35)' : LANG_COLORS[i % LANG_COLORS.length]; + const color = s.isOther ? 'var(--cs-text-muted)' : LANG_COLORS[i % LANG_COLORS.length]; const pct = (s.weight / total) * 100; const barPct = (s.weight / maxWeight) * 100; const safeName = escapeHtml(s.name); diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/divination/style.css b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/divination/style.css index 0c4161d69f..7340d70061 100644 --- a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/divination/style.css +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/divination/style.css @@ -29,9 +29,7 @@ body, html { margin: 0; padding: 0; height: 100%; } --d-serif: ui-serif, "Cormorant Garamond", "Cormorant", "EB Garamond", "Noto Serif SC", "Source Han Serif SC", "Songti SC", STSong, "STZhongsong", SimSun, "宋体", Georgia, "Times New Roman", serif; - --d-sans: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "PingFang SC", - "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei UI", "Microsoft YaHei", - "Helvetica Neue", Helvetica, Arial, sans-serif); + --d-sans: var(--bitfun-font-sans); } body { diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/gomoku/style.css b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/gomoku/style.css index f3ef0a415a..a78b18a318 100644 --- a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/gomoku/style.css +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/gomoku/style.css @@ -18,23 +18,23 @@ body, html { margin: 0; padding: 0; height: 100%; } [hidden] { display: none !important; } :root { - --g-bg: var(--bitfun-bg, #121214); - --g-bg-secondary: var(--bitfun-bg-secondary, #18181a); - --g-bg-elevated: var(--bitfun-bg-elevated, #1f1f22); + --g-bg: var(--bitfun-bg); + --g-bg-secondary: var(--bitfun-bg-secondary); + --g-bg-elevated: var(--bitfun-bg-elevated); - --g-text: var(--bitfun-text, #e8e8e8); - --g-text-soft: var(--bitfun-text-secondary, #b0b0b0); - --g-text-mute: var(--bitfun-text-muted, #858585); + --g-text: var(--bitfun-text); + --g-text-soft: var(--bitfun-text-secondary); + --g-text-mute: var(--bitfun-text-muted); - --g-border: var(--bitfun-border, #2e2e32); - --g-border-subtle: var(--bitfun-border-subtle, #27272a); + --g-border: var(--bitfun-border); + --g-border-subtle: var(--bitfun-border-subtle); - --g-element: var(--bitfun-element-bg, #27272a); - --g-element-hover: var(--bitfun-element-hover, #3f3f46); + --g-element: var(--bitfun-element-bg); + --g-element-hover: var(--bitfun-element-hover); - --g-accent: var(--bitfun-accent, #60a5fa); - --g-accent-hover: var(--bitfun-accent-hover, #3b82f6); - --g-accent-soft: color-mix(in srgb, var(--bitfun-accent, #60a5fa) 16%, transparent); + --g-accent: var(--bitfun-accent); + --g-accent-hover: var(--bitfun-accent-hover); + --g-accent-soft: color-mix(in srgb, var(--bitfun-accent) 16%, transparent); /* Stones — dark theme defaults. * Black stones use a lighter rim so they read against the dark board surface; @@ -44,12 +44,10 @@ body, html { margin: 0; padding: 0; height: 100%; } --g-stone-white: #f1f1f3; --g-stone-white-stroke: rgba(0, 0, 0, 0.35); - --g-radius: var(--bitfun-radius-lg, 8px); - --g-radius-sm: var(--bitfun-radius, 6px); + --g-radius: var(--bitfun-radius-lg); + --g-radius-sm: var(--bitfun-radius); - --g-sans: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "PingFang SC", - "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei UI", "Microsoft YaHei", - "Helvetica Neue", Helvetica, Arial, sans-serif); + --g-sans: var(--bitfun-font-sans); --g-dur: 160ms; --g-ease: cubic-bezier(.2, .8, .2, 1); @@ -422,7 +420,7 @@ button { font-family: inherit; cursor: pointer; } .btn--primary { background: var(--g-accent); - color: #fff; + color: var(--bitfun-text-on-accent); border-color: var(--g-accent); flex: initial; padding: 8px 18px; @@ -503,7 +501,7 @@ button { font-family: inherit; cursor: pointer; } ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { - background: var(--bitfun-scrollbar-thumb, rgba(255, 255, 255, 0.12)); + background: var(--bitfun-scrollbar-thumb); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/style.css b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/style.css index 711c8fe7f1..974c666812 100644 --- a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/style.css +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/ppt-live/style.css @@ -49,11 +49,11 @@ --radius-full: 9999px; /* Shadows / Elevation */ - --shadow-xs: 0 1px 2px 0 rgba(0,0,0,0.05); - --shadow-sm: 0 1px 3px 0 rgba(0,0,0,0.08), 0 1px 2px -1px rgba(0,0,0,0.04); - --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.08), 0 2px 4px -2px rgba(0,0,0,0.04); - --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.08), 0 4px 6px -4px rgba(0,0,0,0.04); - --shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.08), 0 8px 10px -6px rgba(0,0,0,0.04); + --shadow-xs: var(--bitfun-shadow-xs); + --shadow-sm: var(--bitfun-shadow-sm); + --shadow-md: var(--bitfun-shadow-card); + --shadow-lg: var(--bitfun-shadow-lg); + --shadow-xl: var(--bitfun-shadow-xl); --shadow-glow: 0 0 20px color-mix(in srgb, var(--studio-primary) 30%, transparent); /* Z-Index hierarchy */ @@ -86,28 +86,28 @@ --canvas-zoom-max: 2.0; --app-font-sans-stack: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans CJK SC", "Noto Sans SC", sans-serif; - --app-font: var(--bitfun-font-sans, var(--app-font-sans-stack)); - --app-mono: var(--bitfun-font-mono, ui-monospace, SFMono-Regular, monospace); - - --studio-bg: var(--bitfun-bg, Canvas); - --studio-surface: var(--bitfun-bg-elevated, Canvas); - --studio-panel: var(--bitfun-bg-secondary, Canvas); - --studio-line: var(--bitfun-border-subtle, GrayText); - --studio-border: var(--bitfun-border, GrayText); - --studio-text: var(--bitfun-text, CanvasText); - --studio-muted: var(--bitfun-text-muted, GrayText); - --studio-soft: var(--bitfun-text-secondary, CanvasText); - --studio-primary: var(--bitfun-accent, Highlight); - --studio-primary-2: color-mix(in srgb, var(--studio-primary) 72%, white 28%); - --studio-accent: var(--bitfun-info, var(--studio-primary)); - --studio-focus: color-mix(in srgb, var(--bitfun-accent, var(--studio-accent)) 55%, transparent); - --studio-success: var(--bitfun-success, #15835b); - --studio-danger: var(--bitfun-error, #d33f49); - --studio-warning: var(--bitfun-warning, #b7791f); - --studio-accent-text: var(--bitfun-accent-text, var(--bitfun-bg, #fff)); - --studio-overlay: var(--bitfun-overlay, color-mix(in srgb, var(--studio-text) 18%, transparent)); - --studio-control-bg: var(--bitfun-element-bg, Field); - --studio-control-hover: var(--bitfun-element-hover, Field); + --app-font: var(--bitfun-font-sans); + --app-mono: var(--bitfun-font-mono); + + --studio-bg: var(--bitfun-bg); + --studio-surface: var(--bitfun-bg-elevated); + --studio-panel: var(--bitfun-bg-secondary); + --studio-line: var(--bitfun-border-subtle); + --studio-border: var(--bitfun-border); + --studio-text: var(--bitfun-text); + --studio-muted: var(--bitfun-text-muted); + --studio-soft: var(--bitfun-text-secondary); + --studio-primary: var(--bitfun-accent); + --studio-primary-2: color-mix(in srgb, var(--studio-primary) 72%, var(--bitfun-text-on-accent) 28%); + --studio-accent: var(--bitfun-accent-secondary); + --studio-focus: color-mix(in srgb, var(--bitfun-accent) 55%, transparent); + --studio-success: var(--bitfun-success); + --studio-danger: var(--bitfun-error); + --studio-warning: var(--bitfun-warning); + --studio-accent-text: var(--bitfun-text-on-accent); + --studio-overlay: var(--bitfun-overlay-scrim); + --studio-control-bg: var(--bitfun-element-bg); + --studio-control-hover: var(--bitfun-element-hover); --studio-control-muted: color-mix(in srgb, var(--studio-text) 6%, transparent); --studio-control-subtle: color-mix(in srgb, var(--studio-text) 8%, transparent); --studio-topbar-bg: color-mix(in srgb, var(--studio-panel) 94%, transparent); @@ -116,7 +116,7 @@ --studio-canvas-grid: color-mix(in srgb, var(--studio-text) 4%, transparent); --studio-input-bg: var(--studio-control-bg); --studio-log-bg: color-mix(in srgb, var(--studio-text) 4%, var(--studio-bg)); - --studio-shadow: var(--bitfun-shadow, 0 24px 80px color-mix(in srgb, var(--studio-text) 22%, transparent)); + --studio-shadow: var(--bitfun-shadow-overlay); --studio-chip-active-border: color-mix(in srgb, var(--studio-accent) 42%, transparent); --studio-chip-active-bg: color-mix(in srgb, var(--studio-accent) 10%, transparent); --studio-chip-done-border: color-mix(in srgb, var(--studio-success) 32%, transparent); @@ -124,139 +124,12 @@ --studio-history-active-border: color-mix(in srgb, var(--studio-primary) 52%, transparent); --studio-history-active-bg: color-mix(in srgb, var(--studio-primary) 10%, transparent); --studio-resizer-hover: color-mix(in srgb, var(--studio-accent) 55%, transparent); - --studio-slide-chrome: #ffffff; - --studio-slide-empty-bg: #f8fafc; - --studio-slide-empty-text: #1f2937; - --studio-slide-empty-muted: #64748b; - --studio-slide-tip-border: #e2e8f0; - --studio-slide-tip-text: #475569; -} - -[data-bf-appearance-mode="light"] { - color-scheme: light; - --studio-bg: var(--bitfun-bg, #f6f7fb); - --studio-surface: var(--bitfun-bg-elevated, #ffffff); - --studio-panel: var(--bitfun-bg-secondary, #ffffff); - --studio-line: var(--bitfun-border-subtle, #d8dee9); - --studio-border: var(--bitfun-border, #c8d0dc); - --studio-text: var(--bitfun-text, #151a23); - --studio-muted: var(--bitfun-text-muted, #718096); - --studio-soft: var(--bitfun-text-secondary, #4f5b6b); - --studio-primary: var(--bitfun-accent, #2f6feb); - --studio-primary-2: color-mix(in srgb, var(--studio-primary) 72%, white 28%); - --studio-accent: var(--bitfun-info, var(--studio-primary)); - --studio-control-bg: var(--bitfun-element-bg, #ffffff); - --studio-control-hover: var(--bitfun-element-hover, #f1f4f9); - --studio-control-muted: color-mix(in srgb, var(--studio-text) 6%, transparent); - --studio-control-subtle: color-mix(in srgb, var(--studio-text) 8%, transparent); - --studio-topbar-bg: color-mix(in srgb, var(--studio-panel) 94%, transparent); - --studio-sidebar-bg: var(--studio-panel); - --studio-canvas-bg: color-mix(in srgb, var(--studio-bg) 82%, var(--studio-text) 18%); - --studio-canvas-grid: color-mix(in srgb, var(--studio-text) 4%, transparent); - --studio-input-bg: var(--studio-control-bg); - --studio-log-bg: color-mix(in srgb, var(--studio-text) 4%, var(--studio-bg)); - --studio-slide-chrome: #ffffff; - --studio-slide-empty-bg: #f8fafc; - --studio-slide-empty-text: #1f2937; - --studio-slide-empty-muted: #64748b; - --studio-slide-tip-border: #e2e8f0; - --studio-slide-tip-text: #475569; -} - -/* ============================================ - 2. DARK THEME OVERRIDE - ============================================ */ - -[data-bf-appearance-mode="dark"] { - color-scheme: dark; - --studio-bg: #0a0a0a; - --studio-surface: #141414; - --studio-panel: #1a1a1a; - --studio-line: #2a2a2a; - --studio-border: #333333; - --studio-text: var(--bitfun-text, #ececec); - --studio-muted: var(--bitfun-text-muted, #8a8a8a); - --studio-soft: var(--bitfun-text-secondary, #b3b3b3); - --studio-primary: #e5e5e5; - --studio-primary-2: #f5f5f5; - --studio-accent: #c9c9c9; - --studio-focus: color-mix(in srgb, #ffffff 35%, transparent); - --studio-success: #4ade80; - --studio-danger: #f87171; - --studio-warning: #fbbf24; - --studio-accent-text: #0a0a0a; - --studio-overlay: rgba(0, 0, 0, 0.72); - --studio-control-bg: #242424; - --studio-control-hover: #2e2e2e; - --studio-control-muted: color-mix(in srgb, #ffffff 5%, transparent); - --studio-control-subtle: color-mix(in srgb, #ffffff 7%, transparent); - --studio-topbar-bg: #121212; - --studio-sidebar-bg: #121212; - --studio-canvas-bg: #080808; - --studio-canvas-grid: color-mix(in srgb, #ffffff 3%, transparent); - --studio-input-bg: #1f1f1f; - --studio-log-bg: #0e0e0e; - --studio-shadow: 0 24px 80px rgba(0, 0, 0, 0.55); - --studio-chip-active-border: color-mix(in srgb, #ffffff 28%, transparent); - --studio-chip-active-bg: color-mix(in srgb, #ffffff 6%, transparent); - --studio-chip-done-border: color-mix(in srgb, #4ade80 32%, transparent); - --studio-chip-error-border: color-mix(in srgb, #f87171 52%, transparent); - --studio-history-active-border: color-mix(in srgb, #ffffff 24%, transparent); - --studio-history-active-bg: color-mix(in srgb, #ffffff 5%, transparent); - --studio-resizer-hover: color-mix(in srgb, #ffffff 40%, transparent); - --studio-slide-chrome: #111111; - --studio-slide-empty-bg: #141414; - --studio-slide-empty-text: #ececec; - --studio-slide-empty-muted: #8a8a8a; - --studio-slide-tip-border: #2a2a2a; - --studio-slide-tip-text: #8a8a8a; -} - -@media (prefers-color-scheme: dark) { - :root:not([data-bf-appearance-mode]) { - color-scheme: dark; - --studio-bg: #0a0a0a; - --studio-surface: #141414; - --studio-panel: #1a1a1a; - --studio-line: #2a2a2a; - --studio-border: #333333; - --studio-text: var(--bitfun-text, #ececec); - --studio-muted: var(--bitfun-text-muted, #8a8a8a); - --studio-soft: var(--bitfun-text-secondary, #b3b3b3); - --studio-primary: #e5e5e5; - --studio-primary-2: #f5f5f5; - --studio-accent: #c9c9c9; - --studio-focus: color-mix(in srgb, #ffffff 35%, transparent); - --studio-success: #4ade80; - --studio-danger: #f87171; - --studio-warning: #fbbf24; - --studio-accent-text: #0a0a0a; - --studio-overlay: rgba(0, 0, 0, 0.72); - --studio-control-bg: #242424; - --studio-control-hover: #2e2e2e; - --studio-control-muted: color-mix(in srgb, #ffffff 5%, transparent); - --studio-control-subtle: color-mix(in srgb, #ffffff 7%, transparent); - --studio-topbar-bg: #121212; - --studio-sidebar-bg: #121212; - --studio-canvas-bg: #080808; - --studio-canvas-grid: color-mix(in srgb, #ffffff 3%, transparent); - --studio-input-bg: #1f1f1f; - --studio-log-bg: #0e0e0e; - --studio-shadow: 0 24px 80px rgba(0, 0, 0, 0.55); - --studio-chip-active-border: color-mix(in srgb, #ffffff 28%, transparent); - --studio-chip-active-bg: color-mix(in srgb, #ffffff 6%, transparent); - --studio-chip-done-border: color-mix(in srgb, #4ade80 32%, transparent); - --studio-chip-error-border: color-mix(in srgb, #f87171 52%, transparent); - --studio-history-active-border: color-mix(in srgb, #ffffff 24%, transparent); - --studio-history-active-bg: color-mix(in srgb, #ffffff 5%, transparent); - --studio-resizer-hover: color-mix(in srgb, #ffffff 40%, transparent); - --studio-slide-chrome: #111111; - --studio-slide-empty-bg: #141414; - --studio-slide-empty-text: #ececec; - --studio-slide-empty-muted: #8a8a8a; - --studio-slide-tip-border: #2a2a2a; - --studio-slide-tip-text: #8a8a8a; - } + --studio-slide-chrome: var(--bitfun-bg-elevated); + --studio-slide-empty-bg: var(--bitfun-bg-secondary); + --studio-slide-empty-text: var(--bitfun-text); + --studio-slide-empty-muted: var(--bitfun-text-muted); + --studio-slide-tip-border: var(--bitfun-border); + --studio-slide-tip-text: var(--bitfun-text-secondary); } /* Smooth theme transition */ @@ -363,7 +236,7 @@ button, input, select, textarea { font-size: inherit; line-height: inherit; } padding: 0 12px 0 14px; border-bottom: 1px solid color-mix(in srgb, var(--studio-line) 72%, transparent); background: color-mix(in srgb, var(--studio-topbar-bg) 96%, transparent); - box-shadow: 0 1px 0 color-mix(in srgb, white 4%, transparent) inset; + box-shadow: 0 1px 0 color-mix(in srgb, var(--studio-text) 4%, transparent) inset; line-height: 1.15; } @@ -412,7 +285,7 @@ button, input, select, textarea { font-size: inherit; line-height: inherit; } border-radius: 8px; color: var(--studio-text); background: linear-gradient(180deg, color-mix(in srgb, var(--studio-text) 9%, transparent), color-mix(in srgb, var(--studio-text) 4%, transparent)); - box-shadow: 0 1px 0 color-mix(in srgb, white 8%, transparent) inset; + box-shadow: 0 1px 0 color-mix(in srgb, var(--studio-text) 8%, transparent) inset; font-size: 9px; font-weight: 800; } @@ -556,7 +429,7 @@ button, input, select, textarea { font-size: inherit; line-height: inherit; } border-radius: 10px; box-shadow: 0 8px 18px color-mix(in srgb, var(--studio-primary) 13%, transparent), - 0 1px 0 color-mix(in srgb, white 24%, transparent) inset; + 0 1px 0 color-mix(in srgb, var(--studio-accent-text) 24%, transparent) inset; } button:disabled { opacity: 0.5; cursor: not-allowed; } @@ -1409,7 +1282,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } .generation-phase.is-error { border-color: var(--studio-chip-error-border); - color: var(--studio-error, #c84b31); + color: var(--studio-danger); } .generation-steps, .outline-list { @@ -1437,7 +1310,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } } .generation-steps ::selection { - background: var(--bitfun-accent, color-mix(in srgb, var(--studio-accent) 32%, transparent)); + background: var(--bitfun-accent); color: var(--studio-text); } @@ -1522,7 +1395,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } } .generation-event.is-stream-tool-done { opacity: 0.75; } .generation-event.is-stream-tool-error { - background: color-mix(in srgb, var(--studio-error, #c84b31) 8%, transparent); + background: color-mix(in srgb, var(--studio-danger) 8%, transparent); } .generation-event.is-stream-system { border-style: dashed; @@ -1550,8 +1423,8 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } background: color-mix(in srgb, var(--studio-accent) 14%, transparent); } .generation-event.is-stream-tool-error .generation-index--label { - color: var(--studio-error, #c84b31); - background: color-mix(in srgb, var(--studio-error, #c84b31) 14%, transparent); + color: var(--studio-danger); + background: color-mix(in srgb, var(--studio-danger) 14%, transparent); } .generation-index--dot { background: transparent; @@ -1574,7 +1447,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } width: 8px; height: 8px; border-radius: 50%; - background: #fff; + background: var(--bitfun-text-on-accent); animation: live-pulse 1.2s ease-in-out infinite; } @keyframes live-pulse { @@ -1899,7 +1772,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } .outline-list, .history-list { scrollbar-width: thin; - scrollbar-color: var(--bitfun-scrollbar-thumb, color-mix(in srgb, var(--studio-text) 12%, transparent)) transparent; + scrollbar-color: var(--bitfun-scrollbar-thumb) transparent; } .generation-events::-webkit-scrollbar, @@ -1913,13 +1786,13 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } .outline-list::-webkit-scrollbar-thumb, .history-list::-webkit-scrollbar-thumb { border-radius: 999px; - background: var(--bitfun-scrollbar-thumb, color-mix(in srgb, var(--studio-text) 12%, transparent)); + background: var(--bitfun-scrollbar-thumb); } .generation-events::-webkit-scrollbar-thumb:hover, .outline-list::-webkit-scrollbar-thumb:hover, .history-list::-webkit-scrollbar-thumb:hover { - background: var(--bitfun-scrollbar-thumb-hover, color-mix(in srgb, var(--studio-text) 22%, transparent)); + background: var(--bitfun-scrollbar-thumb-hover); } /* ============================================ @@ -2412,7 +2285,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } } .export-modal__feedback.is-error { - color: color-mix(in srgb, var(--studio-danger, #dc2626) 82%, var(--studio-text)); + color: color-mix(in srgb, var(--studio-danger) 82%, var(--studio-text)); } .export-modal__spinner { @@ -2620,7 +2493,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } height: 18px; border-radius: 50%; background: var(--studio-primary); - color: #fff; + color: var(--bitfun-text-on-accent); display: flex; align-items: center; justify-content: center; @@ -2694,7 +2567,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } .template-card__preview { aspect-ratio: 4/3; - background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + background: linear-gradient(135deg, var(--studio-primary) 0%, var(--studio-accent) 100%); position: relative; overflow: hidden; } @@ -2703,7 +2576,7 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } content: ''; position: absolute; inset: 0; - background: linear-gradient(to bottom, transparent 60%, rgba(0,0,0,0.4)); + background: linear-gradient(to bottom, transparent 60%, var(--studio-overlay)); } .template-card__badge { @@ -2718,13 +2591,13 @@ button:disabled { opacity: 0.5; cursor: not-allowed; } } .template-card__badge--new { - background: rgba(16, 185, 129, 0.9); - color: #fff; + background: color-mix(in srgb, var(--studio-success) 90%, transparent); + color: var(--bitfun-text-on-accent); } .template-card__badge--hot { - background: rgba(245, 158, 11, 0.9); - color: #fff; + background: color-mix(in srgb, var(--studio-warning) 90%, transparent); + color: var(--bitfun-text-on-accent); } .template-card__info { diff --git a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/regex-playground/style.css b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/regex-playground/style.css index e56c4d171b..cc03d52a70 100644 --- a/src/crates/contracts/product-domains/src/miniapp/builtin/assets/regex-playground/style.css +++ b/src/crates/contracts/product-domains/src/miniapp/builtin/assets/regex-playground/style.css @@ -2,11 +2,11 @@ * Design system reference: * palette ─ Inherits BitFun host theme (--bitfun-* tokens) so it reads * as a native panel under both bitfun-dark and bitfun-light. - * Local --rx-* tokens are derived from the host vars with - * standalone-safe fallbacks matching the default dark theme. + * Local --rx-* tokens are derived from the required host vars; + * the host contract owns first-paint defaults. * accent ─ host primary (cool blue / slate) for focus & active states; * warning amber as the secondary "match" highlight. - * type ─ system mono (code) + system sans (UI), follows --bitfun-font-* + * type ─ system mono (code) + system sans (UI), follows the two registered host font variables * pattern ─ bento-style cards on calm host surfaces * motion ─ 150-300ms color-shift micro-interactions, no scale jumps */ @@ -20,67 +20,52 @@ body, html { margin: 0; padding: 0; height: 100%; } [hidden] { display: none !important; } :root { + color-scheme: dark; /* Surfaces — drive everything off host bg tokens so the playground tracks * BitFun light/dark automatically. Fallbacks mirror the default dark theme. */ - --rx-bg: var(--bitfun-bg, #0e0e10); - --rx-bg-2: var(--bitfun-bg-tertiary, #121214); - --rx-surface: var(--bitfun-bg-secondary, #1c1c1f); - --rx-surface-2: var(--bitfun-element-bg, rgba(255,255,255,0.06)); - --rx-surface-3: var(--bitfun-element-hover, rgba(255,255,255,0.10)); + --rx-bg: var(--bitfun-bg); + --rx-bg-2: var(--bitfun-bg-tertiary); + --rx-surface: var(--bitfun-bg-secondary); + --rx-surface-2: var(--bitfun-element-bg); + --rx-surface-3: var(--bitfun-element-hover); - --rx-border: var(--bitfun-border-subtle, rgba(255,255,255,0.10)); - --rx-border-strong: var(--bitfun-border, rgba(255,255,255,0.18)); - --rx-border-bright: var(--bitfun-border, rgba(255,255,255,0.28)); + --rx-border: var(--bitfun-border-subtle); + --rx-border-strong: var(--bitfun-border); + --rx-border-bright: var(--bitfun-border); - --rx-text: var(--bitfun-text, #e8e8e8); - --rx-text-soft: var(--bitfun-text-secondary, #b0b0b0); - --rx-text-mute: var(--bitfun-text-muted, #858585); - --rx-text-dim: var(--bitfun-text-muted, #6a6a6a); + --rx-text: var(--bitfun-text); + --rx-text-soft: var(--bitfun-text-secondary); + --rx-text-mute: var(--bitfun-text-muted); + --rx-text-dim: var(--bitfun-text-muted); /* Accent — follows host primary (blue in dark, slate in light) instead of * the previous saturated "run green" which clashed with BitFun's neutral palette. */ - --rx-accent: var(--bitfun-accent, #60a5fa); - --rx-accent-strong: var(--bitfun-accent-hover, #3b82f6); - --rx-accent-soft: rgba(96,165,250,0.14); + --rx-accent: var(--bitfun-accent); + --rx-accent-strong: var(--bitfun-accent-hover); + --rx-accent-soft: color-mix(in srgb, var(--rx-accent) 14%, transparent); /* Semantic colors — pulled from host so they harmonize with the rest of BitFun. */ - --rx-match: var(--bitfun-warning, #f59e0b); /* warm match highlight */ - --rx-match-soft: rgba(245,158,11,0.18); - --rx-error: var(--bitfun-error, #ef4444); - --rx-info: var(--bitfun-info, #E1AB80); - --rx-group: #b39dff; /* capture-group accent */ - --rx-string: var(--bitfun-success, #34d399); + --rx-match: var(--bitfun-warning); /* warm match highlight */ + --rx-match-soft: color-mix(in srgb, var(--rx-match) 18%, transparent); + --rx-error: var(--bitfun-error); + --rx-info: var(--bitfun-info); + --rx-group: var(--bitfun-accent-secondary); /* capture-group accent */ + --rx-string: var(--bitfun-success); - --rx-radius: var(--bitfun-radius, 8px); + --rx-radius: var(--bitfun-radius); --rx-radius-sm: 6px; - --rx-shadow-card: 0 1px 0 rgba(255,255,255,0.025) inset, 0 4px 14px -8px rgba(0,0,0,0.55); - --rx-shadow-elevated: 0 1px 0 rgba(255,255,255,0.035) inset, 0 16px 32px -18px rgba(0,0,0,0.7); + --rx-shadow-card: var(--bitfun-shadow-card); + --rx-shadow-elevated: var(--bitfun-shadow-overlay); - --rx-mono: var(--bitfun-font-mono, "JetBrains Mono", "FiraCode", ui-monospace, "SFMono-Regular", - "SF Mono", Menlo, Monaco, "Cascadia Mono", "Cascadia Code", Consolas, - "Liberation Mono", "Courier New", monospace); - --rx-sans: var(--bitfun-font-sans, -apple-system, BlinkMacSystemFont, "SF Pro Text", - "PingFang SC", "Hiragino Sans GB", "Segoe UI", "Microsoft YaHei UI", - "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif); + --rx-mono: var(--bitfun-font-mono); + --rx-sans: var(--bitfun-font-sans); --rx-dur: 200ms; --rx-ease: cubic-bezier(.2,.8,.2,1); } -/* Light-theme local overrides — host already swaps --bitfun-* tokens, but a - * few decorative pieces (rgba accent washes, capture-group badge, code chips) - * benefit from sturdier alpha / hue picks against a near-white surface. */ [data-bf-appearance-mode="light"] { - --rx-accent-soft: rgba(71,85,105,0.10); - --rx-match-soft: rgba(192,140,66,0.18); - --rx-group: #6b5a89; - --rx-shadow-card: - 0 1px 0 rgba(255,255,255,0.6) inset, - 0 1px 2px rgba(15,23,42,0.06), - 0 4px 14px -8px rgba(15,23,42,0.10); - --rx-shadow-elevated: - 0 1px 0 rgba(255,255,255,0.6) inset, - 0 12px 32px -18px rgba(15,23,42,0.20); + color-scheme: light; } body { @@ -98,8 +83,8 @@ button, input, textarea, select { font-family: inherit; color: inherit; } /* Page wash: very faint accent halos on the host background — keeps the * surface feeling alive without introducing a competing hue. */ background: - radial-gradient(1000px 500px at 90% -10%, rgba(96,165,250,0.05), transparent 60%), - radial-gradient(900px 500px at -10% 110%, rgba(139,92,246,0.035), transparent 55%), + radial-gradient(1000px 500px at 90% -10%, color-mix(in srgb, var(--rx-accent) 5%, transparent), transparent 60%), + radial-gradient(900px 500px at -10% 110%, color-mix(in srgb, var(--rx-group) 4%, transparent), transparent 55%), var(--rx-bg); } @@ -666,11 +651,11 @@ button, input, textarea, select { font-family: inherit; color: inherit; } ::-webkit-scrollbar { width: 8px; height: 8px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { - background: var(--bitfun-scrollbar-thumb, rgba(255,255,255,0.14)); + background: var(--bitfun-scrollbar-thumb); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { - background: var(--bitfun-scrollbar-thumb-hover, rgba(255,255,255,0.26)); + background: var(--bitfun-scrollbar-thumb-hover); } /* ── Reduced motion ─────────────────────────────────── */ @@ -710,22 +695,10 @@ button, input, textarea, select { font-family: inherit; color: inherit; } .match__groups { margin-left: 40px; } } -/* ── Light theme adaptation ───────────────────────────────────────────── - * The host (see bridge_builder.rs) writes [data-bf-appearance-mode="light"] on - * AND repaints all --bitfun-* CSS variables. Because every --rx-* token above - * already proxies through var(--bitfun-…), most of the playground re-tints - * automatically. Only a handful of decorative pieces — page wash, frosted - * topbar tint — need an explicit ivory pass. */ -[data-bf-appearance-mode="light"] .rx { - background: - radial-gradient(1000px 500px at 90% -10%, rgba(71,85,105,0.05), transparent 60%), - radial-gradient(900px 500px at -10% 110%, rgba(124,58,237,0.04), transparent 55%), - var(--rx-bg); -} [data-bf-appearance-mode="light"] .topbar { background: color-mix(in srgb, var(--rx-bg) 85%, transparent); border-bottom-color: var(--rx-border); } [data-bf-appearance-mode="light"] .pattern-error { - color: #b91c1c; + color: var(--rx-error); } diff --git a/src/crates/contracts/product-domains/src/miniapp/generated/default_appearance_style.html b/src/crates/contracts/product-domains/src/miniapp/generated/default_appearance_style.html new file mode 100644 index 0000000000..f8777d96e4 --- /dev/null +++ b/src/crates/contracts/product-domains/src/miniapp/generated/default_appearance_style.html @@ -0,0 +1,80 @@ + diff --git a/src/miniapp-market-web/index.html b/src/miniapp-market-web/index.html index 2b2f2c572e..074ab0bc35 100644 --- a/src/miniapp-market-web/index.html +++ b/src/miniapp-market-web/index.html @@ -18,7 +18,7 @@ /> - + BitFun MiniApp Market diff --git a/src/miniapp-market-web/package.json b/src/miniapp-market-web/package.json index cb17f15b81..996b0a130c 100644 --- a/src/miniapp-market-web/package.json +++ b/src/miniapp-market-web/package.json @@ -11,6 +11,7 @@ "preview": "vite preview" }, "dependencies": { + "@bitfun/theme-bitfun": "workspace:^", "@phosphor-icons/react": "^2.1.10", "lucide-react": "^0.541.0", "react": "^18.3.1", diff --git a/src/miniapp-market-web/public/theme-init.js b/src/miniapp-market-web/public/theme-init.js index c81f15abe6..788c14b8af 100644 --- a/src/miniapp-market-web/public/theme-init.js +++ b/src/miniapp-market-web/public/theme-init.js @@ -15,9 +15,11 @@ ? 'dark' : 'light'; - document.documentElement.dataset.theme = theme; - document.documentElement.style.colorScheme = theme; - document - .querySelector('meta[name="theme-color"]') - ?.setAttribute('content', theme === 'dark' ? '#0e0e10' : '#f7f8fa'); + var root = document.documentElement; + root.setAttribute('data-bf-design-system-root', ''); + root.dataset.colorScheme = theme; + root.dataset.contrast = 'standard'; + root.dataset.density = 'comfortable'; + root.dataset.theme = theme; + root.style.colorScheme = theme; })(); diff --git a/src/miniapp-market-web/src/main.tsx b/src/miniapp-market-web/src/main.tsx index 8f7da6f6e3..9ab800a827 100644 --- a/src/miniapp-market-web/src/main.tsx +++ b/src/miniapp-market-web/src/main.tsx @@ -1,5 +1,6 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; +import '@bitfun/theme-bitfun/default.css'; import App from './App'; import './styles.css'; diff --git a/src/miniapp-market-web/src/styles.css b/src/miniapp-market-web/src/styles.css index 99f80cbf00..04e6fca5b2 100644 --- a/src/miniapp-market-web/src/styles.css +++ b/src/miniapp-market-web/src/styles.css @@ -1,44 +1,5 @@ :root { color-scheme: light dark; - --background: light-dark(#f7f8fa, #0e0e10); - --background-grid: light-dark(rgb(100 116 139 / 3.2%), rgb(148 163 184 / 3%)); - --surface: light-dark(rgb(251 252 254 / 88%), rgb(28 28 31 / 88%)); - --surface-solid: light-dark(#fbfcfe, #1c1c1f); - --surface-subtle: light-dark(#f0f2f5, #242429); - --surface-hover: light-dark(#eaf0f8, #292d34); - --text-primary: light-dark(#1e293b, #e8e8ea); - --text-strong: light-dark(#0f172a, #f2f3f5); - --text-secondary: light-dark(#3d4f66, #b0b0b5); - --text-muted: light-dark(#64748b, #85858d); - --text-disabled: light-dark(#94a3b8, #5b5b63); - --border-subtle: light-dark(rgb(100 116 139 / 16%), rgb(226 232 240 / 12%)); - --border-base: light-dark(rgb(100 116 139 / 24%), rgb(226 232 240 / 20%)); - --border-strong: light-dark(rgb(71 85 105 / 38%), rgb(226 232 240 / 32%)); - --accent: light-dark(#2563eb, #60a5fa); - --accent-hover: light-dark(#1d4ed8, #7db7fb); - --accent-soft: light-dark(rgb(37 99 235 / 9%), rgb(96 165 250 / 12%)); - --accent-border: light-dark(rgb(37 99 235 / 24%), rgb(96 165 250 / 28%)); - --on-accent: light-dark(#f8fafc, #101318); - --primary-bg: light-dark(#111827, #e8e8ea); - --primary-hover: light-dark(#202a3a, #f2f3f5); - --primary-text: light-dark(#f8fafc, #151518); - --success: light-dark(#4d8a63, #66b780); - --success-soft: light-dark(rgb(77 138 99 / 10%), rgb(102 183 128 / 12%)); - --success-border: light-dark(rgb(77 138 99 / 28%), rgb(102 183 128 / 30%)); - --warning: light-dark(#a86f20, #d8a454); - --warning-soft: light-dark(rgb(168 111 32 / 10%), rgb(216 164 84 / 12%)); - --danger: light-dark(#b44d58, #db747d); - --danger-soft: light-dark(rgb(180 77 88 / 9%), rgb(219 116 125 / 11%)); - --danger-border: light-dark(rgb(180 77 88 / 28%), rgb(219 116 125 / 30%)); - --shadow-sm: - 0 1px 2px light-dark(rgb(71 85 105 / 6%), rgb(5 5 8 / 28%)), - 0 1px 1px light-dark(rgb(71 85 105 / 4%), rgb(5 5 8 / 20%)); - --shadow-md: - 0 4px 10px light-dark(rgb(71 85 105 / 8%), rgb(5 5 8 / 34%)), - 0 1px 3px light-dark(rgb(71 85 105 / 6%), rgb(5 5 8 / 26%)); - --shadow-lg: - 0 12px 28px light-dark(rgb(71 85 105 / 10%), rgb(5 5 8 / 42%)), - 0 2px 6px light-dark(rgb(71 85 105 / 7%), rgb(5 5 8 / 30%)); --radius-sm: 6px; --radius-md: 9px; --radius-lg: 12px; @@ -74,17 +35,17 @@ body { min-width: 300px; min-height: 100dvh; margin: 0; - background-color: var(--background); + background-color: var(--bf-color-surface-canvas); background-image: radial-gradient( circle at 76% 0%, - light-dark(rgb(37 99 235 / 5%), rgb(96 165 250 / 6%)), + color-mix(in srgb, var(--bf-color-accent-default) 6%, transparent), transparent 34rem ), - linear-gradient(var(--background-grid) 1px, transparent 1px), - linear-gradient(90deg, var(--background-grid) 1px, transparent 1px); + linear-gradient(color-mix(in srgb, var(--bf-color-content-primary) 3%, transparent) 1px, transparent 1px), + linear-gradient(90deg, color-mix(in srgb, var(--bf-color-content-primary) 3%, transparent) 1px, transparent 1px); background-size: auto, 44px 44px, 44px 44px; - color: var(--text-primary); + color: var(--bf-color-content-primary); font-size: 14px; line-height: 1.55; } @@ -114,7 +75,7 @@ a:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible { - outline: 2px solid var(--accent); + outline: 2px solid var(--bf-color-accent-default); outline-offset: 2px; } @@ -129,8 +90,8 @@ textarea:focus-visible { position: sticky; top: 0; z-index: 40; - border-bottom: 1px solid var(--border-subtle); - background: color-mix(in srgb, var(--background) 80%, transparent); + border-bottom: 1px solid var(--bf-color-border-subtle); + background: color-mix(in srgb, var(--bf-color-surface-canvas) 80%, transparent); backdrop-filter: blur(16px) saturate(130%); -webkit-backdrop-filter: blur(16px) saturate(130%); } @@ -163,11 +124,11 @@ textarea:focus-visible { flex: 0 0 auto; display: grid; place-items: center; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-sm); - background: var(--surface-solid); - color: var(--text-strong); - box-shadow: var(--shadow-sm); + background: var(--bf-color-surface-panel); + color: var(--bf-color-content-primary); + box-shadow: var(--bf-shadow-sm); } .brand-mark svg { @@ -183,7 +144,7 @@ textarea:focus-visible { } .brand-copy strong { - color: var(--text-strong); + color: var(--bf-color-content-primary); font-size: 13px; font-weight: 650; letter-spacing: -0.012em; @@ -191,7 +152,7 @@ textarea:focus-visible { } .brand-copy > span { - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 10.5px; line-height: 1.2; } @@ -216,7 +177,7 @@ textarea:focus-visible { min-height: 29px; padding-inline: 10px; border-radius: var(--radius-sm); - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 12.5px; transition: background 160ms ease, @@ -224,13 +185,13 @@ textarea:focus-visible { } .topbar nav button:hover { - background: var(--surface-subtle); - color: var(--text-primary); + background: var(--bf-color-surface-tertiary); + color: var(--bf-color-content-primary); } .topbar nav button.active { - background: var(--accent-soft); - color: var(--accent); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); + color: var(--bf-color-accent-default); font-weight: 600; } @@ -256,10 +217,10 @@ textarea:focus-visible { align-items: center; justify-content: center; gap: 7px; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-sm); - background: var(--surface); - color: var(--text-muted); + background: color-mix(in srgb, var(--bf-color-surface-raised) 88%, transparent); + color: var(--bf-color-content-muted); transition: border-color 160ms ease, background 160ms ease, @@ -269,9 +230,9 @@ textarea:focus-visible { .header-control:hover, .header-control[aria-expanded='true'] { - border-color: var(--border-base); - background: var(--surface-solid); - color: var(--text-primary); + border-color: var(--bf-color-border-default); + background: var(--bf-color-surface-panel); + color: var(--bf-color-content-primary); } .header-control:active { @@ -284,14 +245,14 @@ textarea:focus-visible { } .language-trigger .control-label { - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 12px; font-weight: 600; line-height: 1; } .language-caret { - color: var(--text-disabled); + color: var(--bf-color-content-disabled); transition: transform 160ms ease; } @@ -324,17 +285,17 @@ textarea:focus-visible { z-index: 60; display: grid; gap: 2px; - border: 1px solid var(--border-base); + border: 1px solid var(--bf-color-border-default); border-radius: var(--radius-md); - background: var(--surface-solid); - box-shadow: var(--shadow-md); + background: var(--bf-color-surface-panel); + box-shadow: var(--bf-shadow-menu); transform-origin: top right; animation: language-menu-in 140ms cubic-bezier(0.16, 1, 0.3, 1) both; } .language-menu-label { padding: 6px 9px 5px; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 11px; font-weight: 600; letter-spacing: 0.04em; @@ -351,33 +312,33 @@ textarea:focus-visible { border: 0; border-radius: 7px; background: transparent; - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 13px; text-align: left; } .language-menu button:hover { - background: var(--surface-subtle); - color: var(--text-primary); + background: var(--bf-color-surface-tertiary); + color: var(--bf-color-content-primary); } .language-menu button.selected { - background: var(--accent-soft); - color: var(--accent); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); + color: var(--bf-color-accent-default); font-weight: 600; } .profile { min-width: 0; gap: 8px; - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 12px; } .profile img { width: 24px; height: 24px; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-pill); } @@ -394,7 +355,7 @@ textarea:focus-visible { display: grid; place-items: center; border-radius: var(--radius-sm); - color: var(--text-muted); + color: var(--bf-color-content-muted); } .icon-button svg { @@ -404,8 +365,8 @@ textarea:focus-visible { .icon-button:hover, .text-action:hover { - background: var(--surface-subtle); - color: var(--text-primary); + background: var(--bf-color-surface-tertiary); + color: var(--bf-color-content-primary); } main { @@ -442,7 +403,7 @@ main { display: inline-flex; align-items: center; gap: 6px; - color: var(--accent); + color: var(--bf-color-accent-default); font-size: 11.5px; font-weight: 600; letter-spacing: 0.006em; @@ -458,7 +419,7 @@ main { .hero h1 { max-width: 520px; margin: 14px 0 12px; - color: var(--text-strong); + color: var(--bf-color-content-primary); font-size: clamp(31px, 3.5vw, 45px); font-weight: 660; line-height: 1.1; @@ -470,7 +431,7 @@ main { .hero-copy > p { max-width: 500px; margin: 0; - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 14.5px; line-height: 1.62; text-wrap: pretty; @@ -480,10 +441,10 @@ main { min-width: 0; overflow: hidden; position: relative; - border: 1px solid var(--border-base); + border: 1px solid var(--bf-color-border-default); border-radius: var(--radius-xl); - background: #111b2c; - box-shadow: var(--shadow-lg); + background: var(--bf-color-surface-canvas); + box-shadow: var(--bf-shadow-lg); animation: rise-in 540ms 80ms cubic-bezier(0.16, 1, 0.3, 1) both; } @@ -491,7 +452,7 @@ main { content: ""; position: absolute; inset: 0; - border: 1px solid rgb(248 250 252 / 10%); + border: 1px solid color-mix(in srgb, var(--bf-color-content-on-dark) 10%, transparent); border-radius: inherit; pointer-events: none; } @@ -507,8 +468,8 @@ main { .trust-row { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); - border-top: 1px solid var(--border-subtle); - border-bottom: 1px solid var(--border-subtle); + border-top: 1px solid var(--bf-color-border-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); } .trust-row > div { @@ -518,20 +479,20 @@ main { align-items: center; justify-content: center; gap: 9px; - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 12.5px; text-align: center; } .trust-row > div + div { - border-left: 1px solid var(--border-subtle); + border-left: 1px solid var(--bf-color-border-subtle); } .trust-row svg { width: 17px; height: 17px; flex: 0 0 auto; - color: var(--accent); + color: var(--bf-color-accent-default); } /* A .bfminiapp package only runs inside the desktop client, so the catalog and @@ -543,9 +504,9 @@ main { display: grid; grid-template-columns: auto 1fr; gap: 12px; - border: 1px solid var(--accent-border); + border: 1px solid color-mix(in srgb, var(--bf-color-accent-default) 28%, transparent); border-radius: var(--radius-lg); - background: var(--accent-soft); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); text-decoration: none; transition: border-color 150ms ease, @@ -557,8 +518,8 @@ main { } .get-bitfun:hover { - border-color: var(--accent); - box-shadow: var(--shadow-sm); + border-color: var(--bf-color-accent-default); + box-shadow: var(--bf-shadow-sm); } .get-bitfun-icon { @@ -567,8 +528,8 @@ main { display: grid; place-items: center; border-radius: var(--radius-sm); - background: var(--accent); - color: var(--on-accent); + background: var(--bf-color-accent-default); + color: var(--bf-color-content-inverse); } .get-bitfun-icon svg { @@ -583,13 +544,13 @@ main { } .get-bitfun-copy strong { - color: var(--text-strong); + color: var(--bf-color-content-primary); font-size: 13px; font-weight: 640; } .get-bitfun-copy > span { - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 12px; line-height: 1.5; text-wrap: pretty; @@ -601,7 +562,7 @@ main { display: inline-flex; align-items: center; gap: 5px; - color: var(--accent); + color: var(--bf-color-accent-default); font-size: 12.5px; font-weight: 620; white-space: nowrap; @@ -631,7 +592,7 @@ main { .catalog-heading h2 { margin: 0; - color: var(--text-strong); + color: var(--bf-color-content-primary); font-size: clamp(20px, 2vw, 25px); font-weight: 660; letter-spacing: -0.022em; @@ -640,14 +601,14 @@ main { .catalog-heading p { max-width: 500px; margin: 5px 0 0; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 12.5px; line-height: 1.58; } .result-count { flex: 0 0 auto; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 11.5px; font-variant-numeric: tabular-nums; } @@ -663,10 +624,10 @@ main { min-height: 36px; display: flex; align-items: center; - border: 1px solid var(--border-base); + border: 1px solid var(--bf-color-border-default); border-radius: var(--radius-sm); - background: var(--surface); - box-shadow: var(--shadow-sm); + background: color-mix(in srgb, var(--bf-color-surface-raised) 88%, transparent); + box-shadow: var(--bf-shadow-sm); font-size: 13px; } @@ -680,13 +641,13 @@ main { width: 15px; height: 15px; flex: 0 0 auto; - color: var(--text-muted); + color: var(--bf-color-content-muted); } .search-field:focus-within, .sort-field:focus-within { - border-color: var(--accent); - box-shadow: 0 0 0 3px var(--accent-soft); + border-color: var(--bf-color-accent-default); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); } .search-field input { @@ -695,14 +656,14 @@ main { border: 0; outline: 0; background: transparent; - color: var(--text-primary); + color: var(--bf-color-content-primary); } .search-field input::placeholder, .review-actions input::placeholder, .field input::placeholder, .field textarea::placeholder { - color: var(--text-muted); + color: var(--bf-color-content-muted); opacity: 1; } @@ -717,7 +678,7 @@ main { border: 0; outline: 0; background: transparent; - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 13px; cursor: pointer; } @@ -738,7 +699,7 @@ main { border: 1px solid transparent; border-radius: var(--radius-pill); background: transparent; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 11.5px; cursor: pointer; transition: @@ -749,15 +710,15 @@ main { } .category-tabs button:hover { - border-color: var(--border-base); - background: var(--surface); - color: var(--text-primary); + border-color: var(--bf-color-border-default); + background: color-mix(in srgb, var(--bf-color-surface-raised) 88%, transparent); + color: var(--bf-color-content-primary); } .category-tabs button.active { - border-color: var(--accent); - background: var(--accent); - color: var(--on-accent); + border-color: var(--bf-color-accent-default); + background: var(--bf-color-accent-default); + color: var(--bf-color-content-inverse); } .category-tabs svg { @@ -783,13 +744,13 @@ main { overflow: hidden; display: flex; flex-direction: column; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-lg); - background: var(--surface-solid); + background: var(--bf-color-surface-panel); color: inherit; text-decoration: none; text-align: left; - box-shadow: var(--shadow-sm); + box-shadow: var(--bf-shadow-sm); cursor: pointer; transition: transform 180ms cubic-bezier(0.16, 1, 0.3, 1), @@ -800,8 +761,8 @@ main { .app-card:hover { transform: translateY(-2px); - border-color: var(--border-base); - box-shadow: var(--shadow-md); + border-color: var(--bf-color-border-default); + box-shadow: var(--bf-shadow-menu); } /* 16:9 matches the MiniApp market card inside the BitFun desktop client, so a @@ -812,9 +773,9 @@ main { display: grid; place-items: center; overflow: hidden; - border-bottom: 1px solid var(--border-subtle); - background-color: var(--surface-subtle); - background-image: radial-gradient(circle at 68% 22%, var(--accent-soft), transparent 55%); + border-bottom: 1px solid var(--bf-color-border-subtle); + background-color: var(--bf-color-surface-tertiary); + background-image: radial-gradient(circle at 68% 22%, color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent), transparent 55%); } .card-visual img { @@ -834,11 +795,11 @@ main { height: 52px; display: grid; place-items: center; - border: 1px solid var(--accent-border); + border: 1px solid color-mix(in srgb, var(--bf-color-accent-default) 28%, transparent); border-radius: var(--radius-md); - background: var(--surface-solid); - color: var(--accent); - box-shadow: var(--shadow-sm); + background: var(--bf-color-surface-panel); + color: var(--bf-color-accent-default); + box-shadow: var(--bf-shadow-sm); } .app-icon-large svg { @@ -860,7 +821,7 @@ main { align-items: center; justify-content: space-between; gap: 10px; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 10px; } @@ -870,10 +831,10 @@ main { padding-inline: 7px; display: inline-flex; align-items: center; - border: 1px solid var(--accent-border); + border: 1px solid color-mix(in srgb, var(--bf-color-accent-default) 28%, transparent); border-radius: var(--radius-pill); - background: var(--accent-soft); - color: var(--accent); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); + color: var(--bf-color-accent-default); font-size: 10px; font-weight: 600; letter-spacing: 0.008em; @@ -894,10 +855,10 @@ main { flex: 0 0 auto; display: grid; place-items: center; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-sm); - background: var(--surface-subtle); - color: var(--text-secondary); + background: var(--bf-color-surface-tertiary); + color: var(--bf-color-content-secondary); } .app-icon svg { @@ -914,7 +875,7 @@ main { .submission-row h2 { margin: 0; overflow: hidden; - color: var(--text-strong); + color: var(--bf-color-content-primary); font-size: 14px; font-weight: 640; letter-spacing: -0.012em; @@ -926,7 +887,7 @@ main { .owner, .submission-row p { margin: 2px 0 0; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 10.5px; } @@ -934,7 +895,7 @@ main { margin: 10px 0 13px; overflow: hidden; display: -webkit-box; - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 12.5px; line-height: 1.52; -webkit-box-orient: vertical; @@ -947,8 +908,8 @@ main { display: flex; align-items: center; gap: 11px; - border-top: 1px solid var(--border-subtle); - color: var(--text-muted); + border-top: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-muted); font-size: 11px; font-variant-numeric: tabular-nums; } @@ -965,23 +926,23 @@ main { } .card-meta .ph-fill { - color: var(--warning); + color: var(--bf-color-status-warning-content); } .card-favorites.active svg { - color: var(--danger); + color: var(--bf-color-status-danger-content); } .card-meta small { - color: var(--text-disabled); + color: var(--bf-color-content-disabled); font-size: 10px; } .card-version { padding: 1px 5px; border-radius: 4px; - background: var(--surface-subtle); - color: var(--text-muted); + background: var(--bf-color-surface-tertiary); + color: var(--bf-color-content-muted); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 10px; font-variant-numeric: tabular-nums; @@ -989,7 +950,7 @@ main { .card-arrow { margin-left: auto; - color: var(--text-disabled); + color: var(--bf-color-content-disabled); transition: color 150ms ease, transform 150ms ease; @@ -997,7 +958,7 @@ main { .app-card:hover .card-arrow { transform: translateX(2px); - color: var(--accent); + color: var(--bf-color-accent-default); } .app-card-skeleton { @@ -1007,8 +968,8 @@ main { .app-card-skeleton:hover { transform: none; - border-color: var(--border-subtle); - box-shadow: var(--shadow-sm); + border-color: var(--bf-color-border-subtle); + box-shadow: var(--bf-shadow-sm); } .skeleton-block, @@ -1016,9 +977,9 @@ main { background: linear-gradient( 105deg, - var(--surface-subtle) 8%, - var(--surface-hover) 18%, - var(--surface-subtle) 33% + var(--bf-color-surface-tertiary) 8%, + var(--bf-color-action-neutral-surface-hover) 18%, + var(--bf-color-surface-tertiary) 33% ); background-size: 220% 100%; animation: shimmer 1.35s linear infinite; @@ -1027,7 +988,7 @@ main { .skeleton-visual { width: 100%; aspect-ratio: 16 / 9; - border-bottom: 1px solid var(--border-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); } .skeleton-line { @@ -1072,10 +1033,10 @@ main { place-items: center; align-content: center; gap: 12px; - border: 1px dashed var(--border-base); + border: 1px dashed var(--bf-color-border-default); border-radius: var(--radius-lg); - background: color-mix(in srgb, var(--surface) 72%, transparent); - color: var(--text-secondary); + background: color-mix(in srgb, color-mix(in srgb, var(--bf-color-surface-raised) 88%, transparent) 72%, transparent); + color: var(--bf-color-content-secondary); text-align: center; } @@ -1088,7 +1049,7 @@ main { .empty-state-hint { max-width: 460px; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 11.5px; line-height: 1.6; } @@ -1098,9 +1059,9 @@ main { .loading-mark { display: grid; place-items: center; - border: 1px solid var(--accent-border); - background: var(--accent-soft); - color: var(--accent); + border: 1px solid color-mix(in srgb, var(--bf-color-accent-default) 28%, transparent); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); + color: var(--bf-color-accent-default); } .empty-state-icon { @@ -1126,16 +1087,16 @@ main { align-items: center; justify-content: center; gap: 7px; - border: 1px solid var(--primary-bg); + border: 1px solid var(--bf-color-action-primary-background); border-radius: var(--radius-sm); - background: var(--primary-bg); - color: var(--primary-text); + background: var(--bf-color-action-primary-background); + color: var(--bf-color-action-primary-content); font-size: 12.5px; font-weight: 600; line-height: 1; text-decoration: none; white-space: nowrap; - box-shadow: var(--shadow-sm); + box-shadow: var(--bf-shadow-sm); cursor: pointer; transition: transform 150ms ease, @@ -1158,8 +1119,8 @@ main { } .button:hover:not(:disabled):not(.disabled) { - background: var(--primary-hover); - box-shadow: var(--shadow-md); + background: var(--bf-color-action-primary-hover); + box-shadow: var(--bf-shadow-menu); } .button-small { @@ -1170,35 +1131,35 @@ main { .button-secondary, .button-ghost { - border-color: var(--border-base); - background: var(--surface-solid); - color: var(--text-primary); + border-color: var(--bf-color-border-default); + background: var(--bf-color-surface-panel); + color: var(--bf-color-content-primary); box-shadow: none; } .button-secondary:hover:not(:disabled), .button-ghost:hover:not(:disabled) { - border-color: var(--border-strong); - background: var(--surface-hover); + border-color: var(--bf-color-border-strong); + background: var(--bf-color-action-neutral-surface-hover); box-shadow: none; } .button-secondary.active, .button-ghost.active { - border-color: var(--accent-border); - background: var(--accent-soft); - color: var(--accent); + border-color: color-mix(in srgb, var(--bf-color-accent-default) 28%, transparent); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); + color: var(--bf-color-accent-default); } .button-danger { - border-color: var(--danger); - background: var(--danger); - color: #f9fafb; + border-color: var(--bf-color-status-danger-content); + background: var(--bf-color-status-danger-content); + color: var(--bf-color-content-on-dark); } .button-danger:hover:not(:disabled) { - border-color: var(--danger); - background: color-mix(in srgb, var(--danger) 88%, var(--text-strong)); + border-color: var(--bf-color-status-danger-content); + background: color-mix(in srgb, var(--bf-color-status-danger-content) 88%, var(--bf-color-content-primary)); } .button.disabled, @@ -1225,7 +1186,7 @@ main { border: 0; border-radius: var(--radius-sm); background: transparent; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 11.5px; cursor: pointer; } @@ -1236,8 +1197,8 @@ main { } .back-link:hover { - background: var(--surface-subtle); - color: var(--text-primary); + background: var(--bf-color-surface-tertiary); + color: var(--bf-color-content-primary); } .detail-hero { @@ -1257,7 +1218,7 @@ main { .detail-title-row h1 { margin: 0; - color: var(--text-strong); + color: var(--bf-color-content-primary); font-size: clamp(25px, 3vw, 34px); font-weight: 660; line-height: 1.14; @@ -1269,7 +1230,7 @@ main { display: flex; flex-wrap: wrap; gap: 6px; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 11.5px; } @@ -1278,7 +1239,7 @@ main { .review-list small span + span::before { content: "/"; margin-right: 7px; - color: var(--text-disabled); + color: var(--bf-color-content-disabled); } .detail-icon { @@ -1287,11 +1248,11 @@ main { flex: 0 0 auto; display: grid; place-items: center; - border: 1px solid var(--accent-border); + border: 1px solid color-mix(in srgb, var(--bf-color-accent-default) 28%, transparent); border-radius: var(--radius-md); - background: var(--accent-soft); - color: var(--accent); - box-shadow: var(--shadow-sm); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); + color: var(--bf-color-accent-default); + box-shadow: var(--bf-shadow-sm); } .detail-icon svg { @@ -1302,7 +1263,7 @@ main { .detail-description { max-width: 560px; margin: 0; - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 14px; line-height: 1.68; text-wrap: pretty; @@ -1331,7 +1292,7 @@ main { border: 0; border-radius: 5px; background: transparent; - color: var(--text-disabled); + color: var(--bf-color-content-disabled); cursor: pointer; } @@ -1341,17 +1302,17 @@ main { } .rating-control button:hover { - background: var(--warning-soft); - color: var(--warning); + background: var(--bf-color-status-warning-surface); + color: var(--bf-color-status-warning-content); } .rating-control button.selected { - color: var(--warning); + color: var(--bf-color-status-warning-content); } .rating-control span { margin-left: 7px; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 11.5px; font-variant-numeric: tabular-nums; } @@ -1364,12 +1325,12 @@ main { overflow: hidden; display: grid; place-items: center; - border: 1px solid var(--border-base); + border: 1px solid var(--bf-color-border-default); border-radius: var(--radius-lg); - background-color: var(--surface-subtle); - background-image: radial-gradient(circle at 68% 22%, var(--accent-soft), transparent 55%); - color: var(--accent); - box-shadow: var(--shadow-md); + background-color: var(--bf-color-surface-tertiary); + background-image: radial-gradient(circle at 68% 22%, color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent), transparent 55%); + color: var(--bf-color-accent-default); + box-shadow: var(--bf-shadow-menu); } .detail-gallery-track { @@ -1406,7 +1367,7 @@ main { .detail-columns h2, .release-section h2 { margin: 0 0 12px; - color: var(--text-strong); + color: var(--bf-color-content-primary); font-size: 16px; font-weight: 650; letter-spacing: -0.015em; @@ -1431,10 +1392,10 @@ main { display: flex; align-items: flex-start; gap: 8px; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-sm); - background: var(--surface); - color: var(--text-secondary); + background: color-mix(in srgb, var(--bf-color-surface-raised) 88%, transparent); + color: var(--bf-color-content-secondary); font-size: 11.5px; line-height: 1.5; } @@ -1446,8 +1407,8 @@ main { display: grid; place-items: center; border-radius: 5px; - background: var(--success-soft); - color: var(--success); + background: var(--bf-color-status-success-surface); + color: var(--bf-color-status-success-content); } .permission-list li > span svg { @@ -1456,12 +1417,12 @@ main { } .permission-list .node-denied > span { - background: var(--danger-soft); - color: var(--danger); + background: var(--bf-color-status-danger-surface); + color: var(--bf-color-status-danger-content); } .prose { - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 13px; line-height: 1.72; white-space: pre-wrap; @@ -1472,10 +1433,10 @@ main { padding: 16px; display: grid; gap: 0; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-md); - background: var(--surface); - box-shadow: var(--shadow-sm); + background: color-mix(in srgb, var(--bf-color-surface-raised) 88%, transparent); + box-shadow: var(--bf-shadow-sm); } .fact { @@ -1483,7 +1444,7 @@ main { padding: 9px 0; display: grid; gap: 4px; - border-bottom: 1px solid var(--border-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); } .fact:first-child { @@ -1496,14 +1457,14 @@ main { } .fact span { - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 10px; letter-spacing: 0.012em; } .fact strong { overflow-wrap: anywhere; - color: var(--text-primary); + color: var(--bf-color-content-primary); font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums; @@ -1515,7 +1476,7 @@ main { display: inline-flex; align-items: center; gap: 5px; - color: var(--accent); + color: var(--bf-color-accent-default); font-size: 11.5px; text-decoration: none; } @@ -1534,7 +1495,7 @@ main { .release-section { margin-top: 52px; padding-top: 28px; - border-top: 1px solid var(--border-subtle); + border-top: 1px solid var(--bf-color-border-subtle); } .release-row { @@ -1544,13 +1505,13 @@ main { grid-template-columns: 56px 118px 100px minmax(0, 1fr) auto; align-items: center; gap: 14px; - border-bottom: 1px solid var(--border-subtle); - color: var(--text-secondary); + border-bottom: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-secondary); font-size: 11.5px; } .release-row strong { - color: var(--text-primary); + color: var(--bf-color-content-primary); } .release-row.yanked { @@ -1560,7 +1521,7 @@ main { .hash { overflow: hidden; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 10px; text-overflow: ellipsis; @@ -1575,7 +1536,7 @@ main { .page-intro h1, .auth-gate h1 { margin: 10px 0 8px; - color: var(--text-strong); + color: var(--bf-color-content-primary); font-size: clamp(22px, 2.6vw, 30px); font-weight: 660; line-height: 1.16; @@ -1584,7 +1545,7 @@ main { .page-intro p, .auth-gate p { - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 13.5px; line-height: 1.62; } @@ -1602,15 +1563,15 @@ main { min-width: 0; margin: 0; padding: 17px; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-md); - background: var(--surface); - box-shadow: var(--shadow-sm); + background: color-mix(in srgb, var(--bf-color-surface-raised) 88%, transparent); + box-shadow: var(--bf-shadow-sm); } .submission-form legend { padding: 0 7px; - color: var(--text-primary); + color: var(--bf-color-content-primary); font-size: 12px; font-weight: 650; } @@ -1630,7 +1591,7 @@ main { } .field > span { - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 10.5px; font-weight: 600; } @@ -1643,10 +1604,10 @@ main { width: 100%; min-height: 34px; padding: 7px 9px; - border: 1px solid var(--border-base); + border: 1px solid var(--bf-color-border-default); border-radius: var(--radius-sm); - background: var(--surface-solid); - color: var(--text-primary); + background: var(--bf-color-surface-panel); + color: var(--bf-color-content-primary); font-size: 13px; outline: 0; } @@ -1658,17 +1619,17 @@ main { .field input[type="file"] { min-height: 44px; padding: 7px; - color: var(--text-muted); + color: var(--bf-color-content-muted); } .field input[type="file"]::file-selector-button { min-height: 28px; margin-right: 9px; padding-inline: 10px; - border: 1px solid var(--border-base); + border: 1px solid var(--bf-color-border-default); border-radius: 5px; - background: var(--surface-subtle); - color: var(--text-primary); + background: var(--bf-color-surface-tertiary); + color: var(--bf-color-content-primary); cursor: pointer; } @@ -1677,13 +1638,13 @@ main { .field textarea:focus, .review-actions input:focus, .moderation-panel input:focus { - border-color: var(--accent); - box-shadow: 0 0 0 3px var(--accent-soft); + border-color: var(--bf-color-accent-default); + box-shadow: 0 0 0 3px color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); } .field input[readonly] { - background: var(--surface-subtle); - color: var(--text-muted); + background: var(--bf-color-surface-tertiary); + color: var(--bf-color-content-muted); } .safety-note { @@ -1691,10 +1652,10 @@ main { display: flex; align-items: flex-start; gap: 9px; - border: 1px solid var(--accent-border); + border: 1px solid color-mix(in srgb, var(--bf-color-accent-default) 28%, transparent); border-radius: var(--radius-sm); - background: var(--accent-soft); - color: var(--accent); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); + color: var(--bf-color-accent-default); font-size: 11.5px; } @@ -1710,7 +1671,7 @@ main { } .safety-note span { - color: var(--text-secondary); + color: var(--bf-color-content-secondary); line-height: 1.5; } @@ -1742,15 +1703,15 @@ main { } .notice.error { - border: 1px solid var(--danger-border); - background: var(--danger-soft); - color: var(--danger); + border: 1px solid var(--bf-color-status-danger-border); + background: var(--bf-color-status-danger-surface); + color: var(--bf-color-status-danger-content); } .notice.success { - border: 1px solid var(--success-border); - background: var(--success-soft); - color: var(--success); + border: 1px solid var(--bf-color-status-success-border); + background: var(--bf-color-status-success-surface); + color: var(--bf-color-status-success-content); } .auth-gate { @@ -1775,9 +1736,9 @@ main { } .gate-icon.success { - border-color: var(--success-border); - background: var(--success-soft); - color: var(--success); + border-color: var(--bf-color-status-success-border); + background: var(--bf-color-status-success-surface); + color: var(--bf-color-status-success-content); } .submission-list { @@ -1792,9 +1753,9 @@ main { grid-template-columns: auto minmax(0, 1fr) auto auto auto; align-items: center; gap: 11px; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-md); - background: var(--surface); + background: color-mix(in srgb, var(--bf-color-surface-raised) 88%, transparent); } .submission-meta { @@ -1804,7 +1765,7 @@ main { } .submission-row .rejection { - color: var(--danger); + color: var(--bf-color-status-danger-content); } .status-badge { @@ -1813,22 +1774,22 @@ main { display: inline-flex; align-items: center; border-radius: var(--radius-pill); - background: var(--accent-soft); - color: var(--accent); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); + color: var(--bf-color-accent-default); font-size: 9px; font-weight: 700; letter-spacing: 0.02em; } .status-badge.approved { - background: var(--success-soft); - color: var(--success); + background: var(--bf-color-status-success-surface); + color: var(--bf-color-status-success-content); } .status-badge.rejected, .status-badge.withdrawn { - background: var(--danger-soft); - color: var(--danger); + background: var(--bf-color-status-danger-surface); + color: var(--bf-color-status-danger-content); } .admin-page { @@ -1840,16 +1801,16 @@ main { display: grid; grid-template-columns: 288px minmax(0, 1fr); overflow: hidden; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-md); - background: var(--surface-solid); - box-shadow: var(--shadow-sm); + background: var(--bf-color-surface-panel); + box-shadow: var(--bf-shadow-sm); } .review-list { padding: 8px; - border-right: 1px solid var(--border-subtle); - background: var(--surface-subtle); + border-right: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-tertiary); } .review-list > button { @@ -1863,18 +1824,18 @@ main { border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent; - color: var(--text-primary); + color: var(--bf-color-content-primary); text-align: left; cursor: pointer; } .review-list > button:hover { - background: var(--surface); + background: color-mix(in srgb, var(--bf-color-surface-raised) 88%, transparent); } .review-list > button.selected { - border-color: var(--accent-border); - background: var(--accent-soft); + border-color: color-mix(in srgb, var(--bf-color-accent-default) 28%, transparent); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, transparent); } .review-list strong { @@ -1890,12 +1851,12 @@ main { display: flex; flex-wrap: wrap; gap: 5px; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 10px; } .review-list .review-submission-meta { - color: var(--text-secondary); + color: var(--bf-color-content-secondary); } .review-detail { @@ -1909,7 +1870,7 @@ main { place-items: center; align-content: center; gap: 10px; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 12.5px; text-align: center; } @@ -1917,7 +1878,7 @@ main { .review-placeholder svg { width: 28px; height: 28px; - color: var(--accent); + color: var(--bf-color-accent-default); } .review-summary { @@ -1926,7 +1887,7 @@ main { .review-summary h2 { margin: 0; - color: var(--text-strong); + color: var(--bf-color-content-primary); font-size: 17px; font-weight: 650; letter-spacing: -0.015em; @@ -1934,7 +1895,7 @@ main { .review-summary p { margin: 4px 0 0; - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 11.5px; line-height: 1.6; } @@ -1948,7 +1909,7 @@ main { .review-evidence-grid .fact { padding: 11px; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-sm); } @@ -1963,9 +1924,9 @@ main { min-width: 0; margin: 0; overflow: hidden; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-md); - background: var(--surface-subtle); + background: var(--bf-color-surface-tertiary); } .review-screenshots img { @@ -1973,7 +1934,7 @@ main { aspect-ratio: 16 / 9; display: block; object-fit: contain; - background: #15171c; + background: var(--bf-color-surface-canvas); } .review-screenshots figcaption { @@ -1981,7 +1942,7 @@ main { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 7px; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 9px; } @@ -1996,11 +1957,11 @@ main { display: grid; gap: 5px; border-radius: var(--radius-sm); - background: var(--surface-subtle); + background: var(--bf-color-surface-tertiary); } .hash-block span { - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 10px; } @@ -2011,23 +1972,23 @@ main { .source-browser { overflow: hidden; - border: 1px solid var(--border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: var(--radius-md); } .source-tabs { display: flex; overflow-x: auto; - border-bottom: 1px solid var(--border-subtle); - background: var(--surface-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-tertiary); } .source-mode { padding: 7px; display: flex; gap: 5px; - border-bottom: 1px solid var(--border-subtle); - background: var(--surface-solid); + border-bottom: 1px solid var(--bf-color-border-subtle); + background: var(--bf-color-surface-panel); } .source-mode button, @@ -2041,30 +2002,30 @@ main { border: 1px solid transparent; border-radius: 6px; background: transparent; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 11px; } .source-mode button.active { - border-color: var(--border-base); - background: var(--surface-subtle); - color: var(--text-primary); + border-color: var(--bf-color-border-default); + background: var(--bf-color-surface-tertiary); + color: var(--bf-color-content-primary); } .source-tabs button { min-height: 34px; padding-inline: 10px; border: 0; - border-right: 1px solid var(--border-subtle); + border-right: 1px solid var(--bf-color-border-subtle); background: transparent; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 10px; white-space: nowrap; } .source-tabs button.active { - background: var(--surface-solid); - color: var(--accent); + background: var(--bf-color-surface-panel); + color: var(--bf-color-accent-default); } .source-browser pre { @@ -2072,15 +2033,15 @@ main { margin: 0; padding: 16px; overflow: auto; - background: #14161b; - color: #e4e7ec; + background: var(--bf-color-content-on-light); + color: var(--bf-color-content-on-dark); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: 11px; line-height: 1.6; } .source-browser pre.diff-view { - color: #eef0f4; + color: var(--bf-color-content-on-dark); } .moderation-panel { @@ -2089,9 +2050,9 @@ main { display: flex; align-items: end; gap: 10px; - border: 1px solid var(--danger-border); + border: 1px solid var(--bf-color-status-danger-border); border-radius: var(--radius-md); - background: var(--danger-soft); + background: var(--bf-color-status-danger-surface); } .moderation-panel label { @@ -2099,12 +2060,12 @@ main { flex: 1; display: grid; gap: 6px; - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-size: 11px; } .danger-action { - color: var(--danger); + color: var(--bf-color-status-danger-content); } .review-actions { @@ -2127,7 +2088,7 @@ main { place-items: center; align-content: center; gap: 10px; - color: var(--text-muted); + color: var(--bf-color-content-muted); font-size: 11.5px; } @@ -2144,7 +2105,7 @@ main { } .muted { - color: var(--text-muted); + color: var(--bf-color-content-muted); } footer { @@ -2155,8 +2116,8 @@ footer { grid-template-columns: 1fr auto 1fr; align-items: center; gap: 20px; - border-top: 1px solid var(--border-subtle); - color: var(--text-muted); + border-top: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-muted); font-size: 10.5px; } @@ -2168,7 +2129,7 @@ footer a { } .footer-brand { - color: var(--text-secondary); + color: var(--bf-color-content-secondary); font-weight: 600; } @@ -2184,7 +2145,7 @@ footer a { } footer a:hover { - color: var(--accent); + color: var(--bf-color-accent-default); } .sr-only { @@ -2278,7 +2239,7 @@ footer a:hover { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 6px; border-right: 0; - border-bottom: 1px solid var(--border-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); } } @@ -2344,7 +2305,7 @@ footer a:hover { } .trust-row > div + div { - border-top: 1px solid var(--border-subtle); + border-top: 1px solid var(--bf-color-border-subtle); border-left: 0; } @@ -2565,7 +2526,7 @@ footer a:hover { @media (prefers-reduced-transparency: reduce) { .topbar, .surface { - background: var(--surface-solid); + background: var(--bf-color-surface-panel); backdrop-filter: none; -webkit-backdrop-filter: none; } diff --git a/src/miniapp-market-web/src/theme.ts b/src/miniapp-market-web/src/theme.ts index f1990dbe0e..20b55f9e7a 100644 --- a/src/miniapp-market-web/src/theme.ts +++ b/src/miniapp-market-web/src/theme.ts @@ -1,4 +1,5 @@ import { useCallback, useEffect, useState } from 'react'; +import { themes } from '@bitfun/theme-bitfun'; export type Theme = 'light' | 'dark'; @@ -21,11 +22,16 @@ function readStoredTheme(): string | null { } function applyTheme(theme: Theme) { - document.documentElement.dataset.theme = theme; - document.documentElement.style.colorScheme = theme; + const root = document.documentElement; + root.setAttribute('data-bf-design-system-root', ''); + root.dataset.colorScheme = theme; + root.dataset.contrast = 'standard'; + root.dataset.density = 'comfortable'; + root.dataset.theme = theme; + root.style.colorScheme = theme; document .querySelector('meta[name="theme-color"]') - ?.setAttribute('content', theme === 'dark' ? '#0e0e10' : '#f7f8fa'); + ?.setAttribute('content', String(themes[theme]['color.surface.canvas'])); } function initialTheme(): Theme { diff --git a/src/mobile-web/index.html b/src/mobile-web/index.html index 5e7a8fc874..51f141647a 100644 --- a/src/mobile-web/index.html +++ b/src/mobile-web/index.html @@ -3,7 +3,7 @@ - + @@ -13,8 +13,6 @@ diff --git a/src/mobile-web/package.json b/src/mobile-web/package.json index a477e8f1bc..790ced43a8 100644 --- a/src/mobile-web/package.json +++ b/src/mobile-web/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "@bitfun/theme-bitfun": "workspace:^", "@noble/ciphers": "^2.1.1", "@noble/curves": "^2.0.1", "react": "^18.3.1", diff --git a/src/mobile-web/src/components/ErrorBoundary.tsx b/src/mobile-web/src/components/ErrorBoundary.tsx index 73bf398175..822fe3a770 100644 --- a/src/mobile-web/src/components/ErrorBoundary.tsx +++ b/src/mobile-web/src/components/ErrorBoundary.tsx @@ -39,8 +39,8 @@ export class ErrorBoundary extends React.Component @@ -48,7 +48,7 @@ export class ErrorBoundary extends React.Component Something went wrong -

    +

    {this.state.error?.message || 'An unexpected error occurred.'}

    diff --git a/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/diagrams.test.tsx b/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/diagrams.test.tsx index 1516ca293e..9a0cfa7996 100644 --- a/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/diagrams.test.tsx +++ b/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/diagrams.test.tsx @@ -131,7 +131,7 @@ describe('Canvas diagram helpers', () => { expect(markup).toContain('bf-diagram'); expect(markup).toContain('aria-label="Runtime"'); - expect(markup).toContain('var(--bf-appearance-token-element-bg-subtle)'); + expect(markup).toContain('var(--bf-color-surface-subtle)'); expect(markup).toContain(' {title ? ( -
    +
    {title}
    ) : null} @@ -83,7 +83,7 @@ function renderGraphSvg({ width={rank.width + 16} height={rank.height + 16} rx={8} - fill={index % 2 === 0 ? 'var(--bf-appearance-token-element-bg-subtle)' : 'var(--bf-appearance-token-color-bg-chrome)'} + fill={index % 2 === 0 ? 'var(--bf-color-surface-subtle)' : 'var(--bf-color-surface-chrome)'} opacity={index % 2 === 0 ? 0.72 : 0.46} /> ))} @@ -106,7 +106,7 @@ function renderGraphSvg({ x={(edge.sourceX + edge.targetX) / 2} y={(edge.sourceY + edge.targetY) / 2 - 4} textAnchor="middle" - fill="var(--bf-appearance-token-color-text-muted)" + fill="var(--bf-color-content-muted)" fontSize="var(--bf-type-micro-font-size)" > {String(meta.label).slice(0, 18)} @@ -127,8 +127,8 @@ function renderGraphSvg({ width={layoutNode.width} height={layoutNode.height} rx={6} - fill="var(--bf-appearance-token-color-bg-elevated)" - stroke="var(--bf-appearance-token-border-subtle)" + fill="var(--bf-color-surface-raised)" + stroke="var(--bf-color-border-subtle)" strokeWidth={1} /> - + {String(label).slice(0, 22)} {description ? ( - + {String(description).slice(0, 26)} ) : null} @@ -177,7 +177,7 @@ export function DependencyGraph({ {nodes.length ? ( renderGraphSvg({ layout, nodes, edges: resolvedEdges, title: String(title || 'Dependency graph') }) ) : ( -
    No graph nodes
    +
    No graph nodes
    )} ); @@ -238,7 +238,7 @@ export function FlowDiagram({ {resolvedNodes.length ? ( renderGraphSvg({ layout, nodes: resolvedNodes, edges: resolvedEdges, title: String(title || 'Flow diagram') }) ) : ( -
    No flow steps
    +
    No flow steps
    )} ); diff --git a/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/layout.tsx b/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/layout.tsx index d1c9b23bd2..a3f4ca956d 100644 --- a/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/layout.tsx +++ b/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/layout.tsx @@ -93,7 +93,7 @@ export function Divider({ style, ...props }: CanvasDividerProps) { {...props} style={{ border: 0, - borderTop: '1px solid var(--bf-appearance-token-border-subtle)', + borderTop: '1px solid var(--bf-color-border-subtle)', width: '100%', margin: '4px 0', ...style, diff --git a/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/style.ts b/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/style.ts index beb27fc002..38b5024ffe 100644 --- a/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/style.ts +++ b/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/style.ts @@ -12,31 +12,31 @@ export const usageColorSequence = [ ] as const satisfies readonly CanvasColor[]; export const categoryPaletteLight: Record = { - gray: 'var(--bf-appearance-token-color-text-muted)', - purple: 'var(--bf-appearance-token-color-accent-500)', - green: 'var(--bf-appearance-token-color-success)', - yellow: 'var(--bf-appearance-token-color-warning)', - cyan: 'var(--bf-appearance-token-color-info)', + gray: 'var(--bf-color-content-muted)', + purple: 'var(--bf-color-accent-default)', + green: 'var(--bf-color-status-success-content)', + yellow: 'var(--bf-color-status-warning-content)', + cyan: 'var(--bf-color-status-info-content)', pink: 'var(--bitfun-canvas-danger)', - blue: 'var(--bf-appearance-token-color-accent-500)', - orange: 'var(--bf-appearance-token-color-warning)', + blue: 'var(--bf-color-accent-default)', + orange: 'var(--bf-color-status-warning-content)', }; export const categoryPaletteDark = categoryPaletteLight; export const canvasTokensLight = { - bg: 'var(--bf-appearance-token-color-bg-primary)', - panel: 'var(--bf-appearance-token-color-bg-secondary)', - elevated: 'var(--bf-appearance-token-color-bg-elevated)', - chrome: 'var(--bf-appearance-token-color-bg-chrome)', - text: 'var(--bf-appearance-token-color-text-primary)', - textSecondary: 'var(--bf-appearance-token-color-text-secondary)', - textMuted: 'var(--bf-appearance-token-color-text-muted)', - border: 'var(--bf-appearance-token-border-subtle)', - accent: 'var(--bf-appearance-token-color-accent-500)', - success: 'var(--bf-appearance-token-color-success)', - warning: 'var(--bf-appearance-token-color-warning)', - danger: 'var(--bf-appearance-token-color-error)', + bg: 'var(--bf-color-surface-canvas)', + panel: 'var(--bf-color-surface-panel)', + elevated: 'var(--bf-color-surface-raised)', + chrome: 'var(--bf-color-surface-chrome)', + text: 'var(--bf-color-content-primary)', + textSecondary: 'var(--bf-color-content-secondary)', + textMuted: 'var(--bf-color-content-muted)', + border: 'var(--bf-color-border-subtle)', + accent: 'var(--bf-color-accent-default)', + success: 'var(--bf-color-status-success-content)', + warning: 'var(--bf-color-status-warning-content)', + danger: 'var(--bf-color-status-danger-content)', info: 'var(--bitfun-canvas-info)', }; @@ -156,7 +156,7 @@ export function toneColor(tone: CanvasTone | undefined): string { tone === 'muted' || tone === 'neutral' ) { - return 'var(--bf-appearance-token-color-text-muted)'; + return 'var(--bf-color-content-muted)'; } - return 'var(--bf-appearance-token-color-text-primary)'; + return 'var(--bf-color-content-primary)'; } diff --git a/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/typography.tsx b/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/typography.tsx index a1f8d04aac..c80064fda5 100644 --- a/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/typography.tsx +++ b/src/web-ui/src/tools/bitfun-canvas/runtime/sdk/typography.tsx @@ -17,7 +17,7 @@ export function H1({ children, style, ...props }: CanvasHeadingProps) { margin: 0, fontWeight: 'var(--bf-type-heading-display-font-weight)', letterSpacing: 'var(--bf-type-heading-display-letter-spacing)', - color: 'var(--bf-appearance-token-color-text-primary)', + color: 'var(--bf-color-content-primary)', ...style, }} > @@ -37,7 +37,7 @@ export function H2({ children, style, ...props }: CanvasHeadingProps) { margin: 0, fontWeight: 'var(--bf-type-heading-page-font-weight)', letterSpacing: 'var(--bf-type-heading-page-letter-spacing)', - color: 'var(--bf-appearance-token-color-text-primary)', + color: 'var(--bf-color-content-primary)', ...style, }} > @@ -57,7 +57,7 @@ export function H3({ children, style, ...props }: CanvasHeadingProps) { margin: 0, fontWeight: 'var(--bf-type-heading-section-font-weight)', letterSpacing: 'var(--bf-type-heading-section-letter-spacing)', - color: 'var(--bf-appearance-token-color-text-primary)', + color: 'var(--bf-color-content-primary)', ...style, }} > @@ -115,7 +115,7 @@ export function Link({ children, style, ...props }: CanvasLinkProps) { target={props.target ?? '_blank'} rel={props.rel ?? 'noreferrer'} style={{ - color: 'var(--bf-appearance-token-color-accent-500)', + color: 'var(--bf-color-accent-default)', textDecoration: 'none', ...style, }} diff --git a/src/web-ui/src/tools/bitfun-canvas/runtime/styles/canvas-runtime.scss b/src/web-ui/src/tools/bitfun-canvas/runtime/styles/canvas-runtime.scss index f0bb9e3a15..21384d6495 100644 --- a/src/web-ui/src/tools/bitfun-canvas/runtime/styles/canvas-runtime.scss +++ b/src/web-ui/src/tools/bitfun-canvas/runtime/styles/canvas-runtime.scss @@ -10,43 +10,43 @@ --bitfun-canvas-warning: CanvasText; --bitfun-canvas-danger: Mark; --bitfun-canvas-info: LinkText; - --bf-appearance-token-color-static-white: Canvas; - --bf-appearance-token-color-bg-primary: var(--bitfun-canvas-bg); - --bf-appearance-token-color-bg-secondary: var(--bitfun-canvas-panel); - --bf-appearance-token-color-bg-elevated: color-mix(in srgb, var(--bitfun-canvas-bg) 86%, var(--bitfun-canvas-panel) 14%); - --bf-appearance-token-color-bg-chrome: color-mix(in srgb, var(--bitfun-canvas-panel) 92%, var(--bitfun-canvas-bg) 8%); - --bf-appearance-token-color-bg-scene: var(--bf-appearance-token-color-bg-secondary); - --bf-appearance-token-color-text-primary: var(--bitfun-canvas-fg); - --bf-appearance-token-color-text-secondary: color-mix(in srgb, var(--bitfun-canvas-fg) 76%, transparent); - --bf-appearance-token-color-text-muted: var(--bitfun-canvas-muted); - --bf-appearance-token-color-accent-500: var(--bitfun-canvas-accent); - --bf-appearance-token-color-accent-200: color-mix(in srgb, var(--bitfun-canvas-accent) 18%, transparent); - --bf-appearance-token-color-success: var(--bitfun-canvas-success); - --bf-appearance-token-color-warning: var(--bitfun-canvas-warning); - --bf-appearance-token-color-error: var(--bitfun-canvas-danger); - --bf-appearance-token-border-subtle: color-mix(in srgb, var(--bitfun-canvas-border) 70%, transparent); - --bf-appearance-token-border-base: var(--bitfun-canvas-border); - --bf-appearance-token-element-bg-subtle: color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 5%, transparent); - --bf-appearance-token-element-bg-soft: color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 8%, transparent); - --bf-appearance-token-element-bg-base: color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 12%, transparent); - --bf-appearance-token-element-bg-medium: color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 16%, transparent); - --bf-appearance-token-size-radius-sm: 6px; - --bf-appearance-token-size-radius-base: 8px; - --bf-appearance-token-size-radius-md: var(--bf-appearance-token-size-radius-base); - --bf-appearance-token-size-radius-lg: 12px; - --bf-appearance-token-size-radius-xl: 16px; - --bf-appearance-token-size-radius-2xl: 20px; - --bf-appearance-token-size-radius-full: 9999px; - --bf-appearance-token-size-gap-1: 4px; - --bf-appearance-token-size-gap-2: 8px; - --bf-appearance-token-size-gap-3: 12px; - --bf-appearance-token-size-gap-4: 16px; - --bf-appearance-token-size-gap-5: 20px; - --bf-appearance-token-size-gap-6: 24px; - --bf-appearance-token-size-gap-8: 32px; - --bf-appearance-token-size-gap-10: 40px; - --bf-appearance-token-size-gap-12: 48px; - --bf-appearance-token-size-gap-16: 64px; + --bf-color-content-on-dark: Canvas; + --bf-color-surface-canvas: var(--bitfun-canvas-bg); + --bf-color-surface-panel: var(--bitfun-canvas-panel); + --bf-color-surface-raised: color-mix(in srgb, var(--bitfun-canvas-bg) 86%, var(--bitfun-canvas-panel) 14%); + --bf-color-surface-chrome: color-mix(in srgb, var(--bitfun-canvas-panel) 92%, var(--bitfun-canvas-bg) 8%); + --bf-color-surface-scene: var(--bf-color-surface-panel); + --bf-color-content-primary: var(--bitfun-canvas-fg); + --bf-color-content-secondary: color-mix(in srgb, var(--bitfun-canvas-fg) 76%, transparent); + --bf-color-content-muted: var(--bitfun-canvas-muted); + --bf-color-accent-default: var(--bitfun-canvas-accent); + --bf-color-action-secondary-hover: color-mix(in srgb, var(--bitfun-canvas-accent) 18%, transparent); + --bf-color-status-success-content: var(--bitfun-canvas-success); + --bf-color-status-warning-content: var(--bitfun-canvas-warning); + --bf-color-status-danger-content: var(--bitfun-canvas-danger); + --bf-color-border-subtle: color-mix(in srgb, var(--bitfun-canvas-border) 70%, transparent); + --bf-color-border-default: var(--bitfun-canvas-border); + --bf-color-surface-subtle: color-mix(in srgb, var(--bf-color-content-primary) 5%, transparent); + --bf-color-action-quiet-hover: color-mix(in srgb, var(--bf-color-content-primary) 8%, transparent); + --bf-color-action-neutral-surface: color-mix(in srgb, var(--bf-color-content-primary) 12%, transparent); + --bf-color-action-neutral-surface-hover: color-mix(in srgb, var(--bf-color-content-primary) 16%, transparent); + --bf-radius-sm: 6px; + --bf-radius-base: 8px; + --bf-radius-md: var(--bf-radius-base); + --bf-radius-lg: 12px; + --bf-radius-xl: 16px; + --bf-radius-2xl: 20px; + --bf-radius-pill: 9999px; + --bf-space-1: 4px; + --bf-space-2: 8px; + --bf-space-3: 12px; + --bf-space-4: 16px; + --bf-space-5: 20px; + --bf-space-6: 24px; + --bf-space-8: 32px; + --bf-space-10: 40px; + --bf-space-12: 48px; + --bf-space-16: 64px; } * { box-sizing: border-box; } @@ -65,8 +65,8 @@ html { body { margin: 0; - background: var(--bf-appearance-token-color-bg-scene); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-scene); + color: var(--bf-color-content-primary); font-family: var(--bf-font-family-sans); font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-regular); @@ -95,10 +95,10 @@ button { max-width: 860px; margin: 0 auto; padding: 12px; - border: 1px solid var(--bf-appearance-token-border-base); + border: 1px solid var(--bf-color-border-default); border-radius: 8px; - color: var(--bf-appearance-token-color-text-muted); - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-secondary) 72%, transparent); + color: var(--bf-color-content-muted); + background: color-mix(in srgb, var(--bf-color-surface-panel) 72%, transparent); } .bf-canvas-stack { @@ -120,14 +120,14 @@ html[data-bitfun-canvas-design-mode] body { } [data-bitfun-canvas-hovered='true'] { - outline: 2px solid var(--bf-appearance-token-color-accent-500) !important; + outline: 2px solid var(--bf-color-accent-default) !important; outline-offset: 2px !important; } .bf-card { - border: 1px solid var(--bf-appearance-token-border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; - background: var(--bf-appearance-token-color-bg-elevated); + background: var(--bf-color-surface-raised); overflow: hidden; } @@ -138,8 +138,8 @@ html[data-bitfun-canvas-design-mode] body { justify-content: space-between; gap: 10px; padding: 9px 12px; - border-bottom: 1px solid var(--bf-appearance-token-border-subtle); - color: var(--bf-appearance-token-color-text-primary); + border-bottom: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-semibold); line-height: var(--bf-line-height-dense); @@ -150,14 +150,14 @@ html[data-bitfun-canvas-design-mode] body { } .bf-callout { - --bf-callout-accent: var(--bf-appearance-token-color-accent-500); + --bf-callout-accent: var(--bf-color-accent-default); position: relative; border-radius: 8px; padding: 12px 14px 12px 16px; - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-border-subtle) 76%, transparent); - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-elevated) 58%, transparent); - color: var(--bf-appearance-token-color-text-primary); + border: 1px solid color-mix(in srgb, var(--bf-color-border-subtle) 76%, transparent); + background: color-mix(in srgb, var(--bf-color-surface-raised) 58%, transparent); + color: var(--bf-color-content-primary); } .bf-callout::before { @@ -174,14 +174,14 @@ html[data-bitfun-canvas-design-mode] body { .bf-callout-title { margin-bottom: 6px; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-semibold); line-height: var(--bf-line-height-compact); } .bf-callout-body { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-comfortable); } @@ -201,16 +201,16 @@ html[data-bitfun-canvas-design-mode] body { border: 0; border-radius: 999px; padding: 3px 9px; - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-secondary); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); line-height: var(--bf-line-height-base); white-space: nowrap; } .bf-pill--active { - background: var(--bf-appearance-token-color-accent-200); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-secondary-hover); + color: var(--bf-color-content-primary); } .bf-button { @@ -221,35 +221,35 @@ html[data-bitfun-canvas-design-mode] body { padding: 0 11px; border: 0; border-radius: 6px; - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-secondary); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-secondary); cursor: pointer; } .bf-button:hover { - background: var(--bf-appearance-token-element-bg-medium); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface-hover); + color: var(--bf-color-content-primary); } .bf-button--primary { - background: var(--bf-appearance-token-color-accent-500); - color: var(--bf-appearance-token-color-static-white); + background: var(--bf-color-accent-default); + color: var(--bf-color-content-on-dark); } .bf-code { border-radius: 5px; padding: 1px 5px; - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-primary); font-family:var(--bf-font-family-mono); font-size: var(--bf-font-size-sm); } .bf-table-wrap { overflow: auto; - border: 1px solid var(--bf-appearance-token-border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; - background: var(--bf-appearance-token-color-bg-elevated); + background: var(--bf-color-surface-raised); } .bf-table { @@ -261,24 +261,24 @@ html[data-bitfun-canvas-design-mode] body { .bf-table th, .bf-table td { padding: 8px 10px; - border-bottom: 1px solid var(--bf-appearance-token-border-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); text-align: left; vertical-align: top; } .bf-table th { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-semibold); - background: var(--bf-appearance-token-color-bg-chrome); + background: var(--bf-color-surface-chrome); } .bf-table td { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } .bf-diff { overflow: auto; - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-primary) 54%, transparent); + background: color-mix(in srgb, var(--bf-color-surface-canvas) 54%, transparent); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-regular); @@ -286,9 +286,9 @@ html[data-bitfun-canvas-design-mode] body { } .bf-chart { - border: 1px solid var(--bf-appearance-token-border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: 8px; - background: var(--bf-appearance-token-color-bg-elevated); + background: var(--bf-color-surface-raised); padding: 12px; min-width: 0; } @@ -305,7 +305,7 @@ html[data-bitfun-canvas-design-mode] body { .bf-chart__title { min-width: 0; overflow: hidden; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-semibold); line-height: var(--bf-line-height-dense); @@ -317,7 +317,7 @@ html[data-bitfun-canvas-design-mode] body { display: flex; flex-wrap: wrap; gap: 6px 10px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-meta); } @@ -355,30 +355,30 @@ html[data-bitfun-canvas-design-mode] body { } .bf-canvas-toggle__label { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-sm); } .bf-canvas-toggle__description, .bf-canvas-toggle__status { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); } .bf-input, .bf-textarea { width: 100%; - border: 1px solid var(--bf-appearance-token-border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: 6px; - background: var(--bf-appearance-token-element-bg-subtle); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-subtle); + color: var(--bf-color-content-primary); padding: 7px 9px; outline: none; } .bf-input:focus, .bf-textarea:focus { - border-color: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 55%, var(--bf-appearance-token-border-base)); + border-color: color-mix(in srgb, var(--bf-color-accent-default) 55%, var(--bf-color-border-default)); } .bf-select { diff --git a/src/web-ui/src/tools/editor/components/CodeEditor.scss b/src/web-ui/src/tools/editor/components/CodeEditor.scss index 1f978231e4..8c071ae593 100644 --- a/src/web-ui/src/tools/editor/components/CodeEditor.scss +++ b/src/web-ui/src/tools/editor/components/CodeEditor.scss @@ -22,7 +22,7 @@ $_editor-padding-desktop: 32px; height: 100%; width: 100%; position: relative; - background: var(--bf-appearance-token-color-bg-scene); + background: var(--bf-color-surface-scene); > .editor-status-bar { @@ -37,27 +37,27 @@ $_editor-padding-desktop: 32px; align-items: center; justify-content: center; height: 100%; - background: var(--bf-appearance-token-color-bg-scene); - color: var(--bf-appearance-token-color-text-muted); + background: var(--bf-color-surface-scene); + color: var(--bf-color-content-muted); } &__loading-spinner { width: $_editor-loading-spinner-size; height: $_editor-loading-spinner-size; - border: $_editor-loading-spinner-border solid var(--bf-appearance-token-color-accent-200); - border-top-color: var(--bf-appearance-token-color-accent-500); + border: $_editor-loading-spinner-border solid var(--bf-color-action-secondary-hover); + border-top-color: var(--bf-color-accent-default); border-radius: $size-radius-full; animation: code-editor-spin $motion-lazy $easing-standard infinite; margin-bottom: $size-gap-4; box-shadow: - 0 0 20px color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 30%, transparent), - 0 0 40px var(--bf-appearance-token-color-accent-200); + 0 0 20px color-mix(in srgb, var(--bf-color-accent-default) 30%, transparent), + 0 0 40px var(--bf-color-action-secondary-hover); } &__loading-text { margin: 0; font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-family: var(--bf-font-family-mono); animation: code-editor-pulse $motion-slow ease-in-out infinite; } @@ -70,7 +70,7 @@ $_editor-padding-desktop: 32px; align-items: center; justify-content: center; height: 100%; - background: var(--bf-appearance-token-color-bg-scene); + background: var(--bf-color-surface-scene); text-align: center; padding: $_editor-padding-desktop; } @@ -78,7 +78,7 @@ $_editor-padding-desktop: 32px; &__error-icon { width: 32px; height: 32px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); margin-bottom: $size-gap-3; opacity: 0.5; } @@ -86,7 +86,7 @@ $_editor-padding-desktop: 32px; &__error-message { margin: 0 0 $size-gap-3 0; font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-family: var(--bf-font-family-mono); } @@ -113,7 +113,7 @@ $_editor-padding-desktop: 32px; flex-direction: column; align-items: center; justify-content: center; - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-scene) 85%, transparent); + background: color-mix(in srgb, var(--bf-color-surface-scene) 85%, transparent); backdrop-filter: blur(4px); z-index: 100; animation: code-editor-fade-in 0.2s ease-out; @@ -133,8 +133,8 @@ $_editor-padding-desktop: 32px; position: absolute; top: $size-gap-4; right: $size-gap-4; - background: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 90%, transparent); - color: var(--bf-appearance-token-color-bg-primary); + background: color-mix(in srgb, var(--bf-color-accent-default) 90%, transparent); + color: var(--bf-color-surface-canvas); padding: $size-gap-2 $size-gap-4; border-radius: $size-radius-base; font-size: var(--bf-font-size-xs); @@ -160,14 +160,14 @@ $_editor-padding-desktop: 32px; .monaco-editor { .ctrl-hover-underline { text-decoration: underline; - text-decoration-color: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 80%, transparent); + text-decoration-color: color-mix(in srgb, var(--bf-color-accent-default) 80%, transparent); text-underline-offset: 2px; cursor: pointer !important; } .monaco-cross-file-link { text-decoration: underline; - text-decoration-color: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 80%, transparent); + text-decoration-color: color-mix(in srgb, var(--bf-color-accent-default) 80%, transparent); text-decoration-thickness: 1px; text-underline-offset: 2px; cursor: pointer !important; @@ -181,17 +181,17 @@ $_editor-padding-desktop: 32px; .hover-row, .hover-contents { font-size: var(--bf-font-size-xs) !important; - color: var(--bf-appearance-token-color-static-black) !important; + color: var(--bf-color-content-on-light) !important; } p, span, div { font-size: var(--bf-font-size-xs) !important; - color: var(--bf-appearance-token-color-static-black) !important; + color: var(--bf-color-content-on-light) !important; } .markdown-string { font-size: var(--bf-font-size-xs) !important; - color: var(--bf-appearance-token-color-static-black) !important; + color: var(--bf-color-content-on-light) !important; } } } @@ -279,8 +279,8 @@ $_editor-padding-desktop: 32px; @media (prefers-contrast: high) { .code-editor-tool { &__loading-spinner { - border-color: var(--bf-appearance-token-color-text-muted); - border-top-color: var(--bf-appearance-token-color-text-primary); + border-color: var(--bf-color-content-muted); + border-top-color: var(--bf-color-content-primary); } &__error-icon { @@ -299,7 +299,7 @@ $_editor-padding-desktop: 32px; * { font-size: var(--bf-font-size-xs) !important; - color: var(--bf-appearance-token-color-static-black) !important; + color: var(--bf-color-content-on-light) !important; } } } diff --git a/src/web-ui/src/tools/editor/components/DiffEditor.scss b/src/web-ui/src/tools/editor/components/DiffEditor.scss index d3ef07902e..2328cb1dd0 100644 --- a/src/web-ui/src/tools/editor/components/DiffEditor.scss +++ b/src/web-ui/src/tools/editor/components/DiffEditor.scss @@ -12,25 +12,22 @@ $_diff-error-max-width: 400px; // Main Container .diff-editor-container { - --diff-editor-added-rgb: 63, 185, 80; - --diff-editor-deleted-rgb: 248, 81, 73; - --diff-editor-added-soft-bg: rgba(var(--diff-editor-added-rgb), 0.15); - --diff-editor-deleted-soft-bg: rgba(var(--diff-editor-deleted-rgb), 0.15); - --diff-editor-added-line-bg: rgba(var(--diff-editor-added-rgb), 0.18); - --diff-editor-deleted-line-bg: rgba(var(--diff-editor-deleted-rgb), 0.18); - --diff-editor-added-emphasis-bg: rgba(var(--diff-editor-added-rgb), 0.2); - --diff-editor-deleted-emphasis-bg: rgba(var(--diff-editor-deleted-rgb), 0.2); - --diff-editor-added-border: rgba(var(--diff-editor-added-rgb), 0.3); - --diff-editor-deleted-border: rgba(var(--diff-editor-deleted-rgb), 0.3); - --diff-editor-added-char-bg: rgba(var(--diff-editor-added-rgb), 0.38); - --diff-editor-deleted-char-bg: rgba(var(--diff-editor-deleted-rgb), 0.38); - --diff-editor-modified-char-rgb: 136, 182, 255; + --diff-editor-added-soft-bg: color-mix(in srgb, var(--bf-domain-git-added) 15%, transparent); + --diff-editor-deleted-soft-bg: color-mix(in srgb, var(--bf-domain-git-deleted) 15%, transparent); + --diff-editor-added-line-bg: color-mix(in srgb, var(--bf-domain-git-added) 18%, transparent); + --diff-editor-deleted-line-bg: color-mix(in srgb, var(--bf-domain-git-deleted) 18%, transparent); + --diff-editor-added-emphasis-bg: color-mix(in srgb, var(--bf-domain-git-added) 20%, transparent); + --diff-editor-deleted-emphasis-bg: color-mix(in srgb, var(--bf-domain-git-deleted) 20%, transparent); + --diff-editor-added-border: color-mix(in srgb, var(--bf-domain-git-added) 30%, transparent); + --diff-editor-deleted-border: color-mix(in srgb, var(--bf-domain-git-deleted) 30%, transparent); + --diff-editor-added-char-bg: color-mix(in srgb, var(--bf-domain-git-added) 38%, transparent); + --diff-editor-deleted-char-bg: color-mix(in srgb, var(--bf-domain-git-deleted) 38%, transparent); display: flex; flex-direction: column; width: 100%; height: 100%; - background: var(--bf-appearance-token-color-bg-primary); + background: var(--bf-color-surface-canvas); position: relative; overflow: hidden; } @@ -41,8 +38,8 @@ $_diff-error-max-width: 400px; justify-content: space-between; align-items: center; padding: 0 $size-gap-3; - background: var(--bf-appearance-token-color-bg-primary); - border-bottom: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-canvas); + border-bottom: 1px solid var(--bf-color-border-default); flex-shrink: 0; height: $_diff-toolbar-height; min-height: $_diff-toolbar-height; @@ -54,7 +51,7 @@ $_diff-error-max-width: 400px; display: flex; align-items: center; gap: $size-gap-4; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); font-family: var(--bf-font-family-mono); } @@ -72,13 +69,13 @@ $_diff-error-max-width: 400px; font-size: var(--bf-font-size-xs); &--add { - color: var(--bf-appearance-token-git-color-staged); + color: var(--bf-domain-git-staged); background: var(--diff-editor-added-soft-bg); border: 1px solid var(--diff-editor-added-border); } &--del { - color: var(--bf-appearance-token-git-color-deleted); + color: var(--bf-domain-git-deleted); background: var(--diff-editor-deleted-soft-bg); border: 1px solid var(--diff-editor-deleted-border); } @@ -86,12 +83,12 @@ $_diff-error-max-width: 400px; &__changes-count { font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); } &__file-path { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-xs); } @@ -108,10 +105,10 @@ $_diff-error-max-width: 400px; min-width: 32px; height: 32px; padding: 0 $size-gap-3; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-base; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-lg); line-height: var(--bf-line-height-none); cursor: pointer; @@ -123,13 +120,13 @@ $_diff-error-max-width: 400px; box-shadow $motion-fast $easing-standard; &:hover:not(:disabled) { - background: var(--bf-appearance-token-element-bg-medium); - border-color: var(--bf-appearance-token-color-accent-500); - color: var(--bf-appearance-token-color-accent-500); + background: var(--bf-color-action-neutral-surface-hover); + border-color: var(--bf-color-accent-default); + color: var(--bf-color-accent-default); transform: translateY(-1px); box-shadow: - 0 2px 8px color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 20%, transparent), - 0 0 20px var(--bf-appearance-token-color-accent-100); + 0 2px 8px color-mix(in srgb, var(--bf-color-accent-default) 20%, transparent), + 0 0 20px var(--bf-color-action-secondary-background); } &:active:not(:disabled) { @@ -144,7 +141,7 @@ $_diff-error-max-width: 400px; } &:focus-visible { - outline: 2px solid var(--bf-appearance-token-color-accent-500); + outline: 2px solid var(--bf-color-accent-default); outline-offset: 2px; } } @@ -174,7 +171,7 @@ $_diff-error-max-width: 400px; flex-direction: column; align-items: center; justify-content: center; - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-primary) 85%, transparent); + background: color-mix(in srgb, var(--bf-color-surface-canvas) 85%, transparent); backdrop-filter: blur(4px); z-index: 100; animation: diff-editor-fade-in 0.2s ease-out; @@ -198,8 +195,8 @@ $_diff-error-max-width: 400px; transform: translate(-50%, -50%); text-align: center; padding: $size-gap-6; - background: var(--bf-appearance-token-color-bg-primary); - border: 1px solid var(--bf-appearance-token-border-subtle); + background: var(--bf-color-surface-canvas); + border: 1px solid var(--bf-color-border-subtle); border-radius: $size-radius-lg; max-width: $_diff-error-max-width; z-index: 100; @@ -209,12 +206,12 @@ $_diff-error-max-width: 400px; gap: $size-gap-3; &__icon { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); opacity: 0.6; } &__message { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-medium); margin: 0; @@ -222,7 +219,7 @@ $_diff-error-max-width: 400px; } &__path { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); font-family: var(--bf-font-family-mono); margin: 0; @@ -237,20 +234,20 @@ $_diff-error-max-width: 400px; .diff-editor-container { :global { .monaco-diff-editor { - background-color: var(--bf-appearance-token-color-bg-primary) !important; + background-color: var(--bf-color-surface-canvas) !important; } .monaco-diff-editor .editor.original, .monaco-diff-editor .editor.modified { - background-color: var(--bf-appearance-token-color-bg-primary) !important; + background-color: var(--bf-color-surface-canvas) !important; } .monaco-diff-editor .monaco-editor { - background-color: var(--bf-appearance-token-color-bg-primary) !important; + background-color: var(--bf-color-surface-canvas) !important; } .monaco-diff-editor .monaco-editor-background { - background-color: var(--bf-appearance-token-color-bg-primary) !important; + background-color: var(--bf-color-surface-canvas) !important; } .monaco-diff-editor .monaco-editor .view-overlays { @@ -260,17 +257,17 @@ $_diff-error-max-width: 400px; .monaco-diff-editor .monaco-editor .margin, .monaco-diff-editor .editor.original .margin, .monaco-diff-editor .editor.modified .margin { - background-color: var(--bf-appearance-token-color-bg-primary) !important; + background-color: var(--bf-color-surface-canvas) !important; } .monaco-diff-editor .monaco-editor .margin-view-overlays, .monaco-diff-editor .editor.original .margin-view-overlays, .monaco-diff-editor .editor.modified .margin-view-overlays { - background-color: var(--bf-appearance-token-color-bg-primary) !important; + background-color: var(--bf-color-surface-canvas) !important; } .monaco-diff-editor .monaco-editor .gutter-background { - background-color: var(--bf-appearance-token-color-bg-primary) !important; + background-color: var(--bf-color-surface-canvas) !important; } // Gutter Styles @@ -289,10 +286,10 @@ $_diff-error-max-width: 400px; border: none !important; box-shadow: none !important; background: transparent !important; - color: var(--bf-appearance-token-color-text-muted) !important; + color: var(--bf-color-content-muted) !important; &:hover { - color: var(--bf-appearance-token-color-text-secondary) !important; + color: var(--bf-color-content-secondary) !important; } &:focus { @@ -322,23 +319,23 @@ $_diff-error-max-width: 400px; } .monaco-diff-editor.side-by-side .editor.original { - border-right: 1px dashed var(--bf-appearance-token-border-medium) !important; + border-right: 1px dashed var(--bf-color-field-border-hover) !important; transition: border-color 0.2s ease; } .monaco-diff-editor.side-by-side .editor.modified { - border-left: 1px dashed var(--bf-appearance-token-border-medium) !important; + border-left: 1px dashed var(--bf-color-field-border-hover) !important; transition: border-color 0.2s ease; } .monaco-diff-editor.side-by-side:hover .editor.original { border-right-style: solid !important; - border-right-color: var(--bf-appearance-token-color-overlay-white-15) !important; + border-right-color: color-mix(in srgb, var(--bf-color-content-on-dark) 15%, transparent) !important; } .monaco-diff-editor.side-by-side:hover .editor.modified { border-left-style: solid !important; - border-left-color: var(--bf-appearance-token-color-overlay-white-15) !important; + border-left-color: color-mix(in srgb, var(--bf-color-content-on-dark) 15%, transparent) !important; } .monaco-diff-editor .monaco-editor .view-lines { @@ -351,7 +348,7 @@ $_diff-error-max-width: 400px; .monaco-diff-editor .monaco-editor .line-numbers { background-color: transparent !important; - color: var(--bf-appearance-token-color-text-muted) !important; + color: var(--bf-color-content-muted) !important; } .monaco-diff-editor .monaco-editor .view-line { @@ -363,26 +360,26 @@ $_diff-error-max-width: 400px; } .monaco-diff-editor .diffViewport { - background-color: var(--bf-appearance-token-color-overlay-white-04) !important; - border-left: 1px dashed var(--bf-appearance-token-border-medium) !important; - border-right: 1px dashed var(--bf-appearance-token-border-medium) !important; + background-color: color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent) !important; + border-left: 1px dashed var(--bf-color-field-border-hover) !important; + border-right: 1px dashed var(--bf-color-field-border-hover) !important; transition: background-color 0.2s ease; &:hover { - background-color: var(--bf-appearance-token-color-overlay-white-08) !important; + background-color: color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent) !important; border-left-style: solid !important; border-right-style: solid !important; } } .monaco-diff-editor .diagonal-fill { - background-color: var(--bf-appearance-token-color-bg-secondary) !important; + background-color: var(--bf-color-surface-panel) !important; background-image: repeating-linear-gradient( 45deg, transparent, transparent 4px, - var(--bf-appearance-token-color-overlay-white-04) 4px, - var(--bf-appearance-token-color-overlay-white-04) 8px + color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent) 4px, + color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent) 8px ) !important; } @@ -408,7 +405,7 @@ $_diff-error-max-width: 400px; } .monaco-diff-editor .char-modified { - background-color: rgba(var(--diff-editor-modified-char-rgb), 0.32) !important; + background-color: color-mix(in srgb, var(--bf-color-accent-default) 32%, transparent) !important; border-radius: 2px; border: none !important; } @@ -417,15 +414,15 @@ $_diff-error-max-width: 400px; width: 8px !important; .insert { - background: var(--bf-appearance-token-color-success); + background: var(--bf-color-status-success-content); } .delete { - background: var(--bf-appearance-token-color-error); + background: var(--bf-color-status-danger-content); } .modified { - background: var(--bf-appearance-token-color-warning); + background: var(--bf-color-status-warning-content); } } @@ -465,16 +462,16 @@ $_diff-error-max-width: 400px; background: transparent; .slider { - background: var(--bf-appearance-token-color-overlay-white-08); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); border-radius: 4px; transition: background $motion-base $easing-standard; &:hover { - background: var(--bf-appearance-token-color-overlay-white-15); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 15%, transparent); } &.active { - background: rgba(var(--bf-appearance-token-color-static-white-rgb), 0.25); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 25%, transparent); } } } @@ -536,7 +533,7 @@ $_diff-error-max-width: 400px; // High Contrast Mode @media (prefers-contrast: high) { .diff-editor-container { - border: 2px solid var(--bf-appearance-token-border-base); + border: 2px solid var(--bf-color-border-default); } .diff-editor-toolbar { @@ -546,7 +543,7 @@ $_diff-error-max-width: 400px; border-width: 2px; &:hover:not(:disabled) { - border-color: var(--bf-appearance-token-color-accent-500); + border-color: var(--bf-color-accent-default); } } @@ -568,12 +565,12 @@ $_diff-error-max-width: 400px; .monaco-diff-editor { .line-insert { background-color: var(--diff-editor-added-emphasis-bg) !important; - border-left: 3px solid var(--bf-appearance-token-git-color-staged); + border-left: 3px solid var(--bf-domain-git-staged); } .line-delete { background-color: var(--diff-editor-deleted-emphasis-bg) !important; - border-left: 3px solid var(--bf-appearance-token-git-color-deleted); + border-left: 3px solid var(--bf-domain-git-deleted); } } } @@ -584,12 +581,12 @@ $_diff-error-max-width: 400px; :global { .diff-editor-container .monaco-diff-editor .monaco-editor-background, .diff-editor-container .monaco-diff-editor .monaco-editor .monaco-editor-background { - background-color: var(--bf-appearance-token-color-bg-primary) !important; + background-color: var(--bf-color-surface-canvas) !important; } .diff-editor-container .monaco-diff-editor .editor.original .monaco-editor, .diff-editor-container .monaco-diff-editor .editor.modified .monaco-editor { - background-color: var(--bf-appearance-token-color-bg-primary) !important; + background-color: var(--bf-color-surface-canvas) !important; } .monaco-diff-editor .gutter { diff --git a/src/web-ui/src/tools/editor/components/DiffEditor.tsx b/src/web-ui/src/tools/editor/components/DiffEditor.tsx index 853e562cc5..5f56ac27ae 100644 --- a/src/web-ui/src/tools/editor/components/DiffEditor.tsx +++ b/src/web-ui/src/tools/editor/components/DiffEditor.tsx @@ -295,7 +295,7 @@ export const DiffEditor: React.FC = ({ const elements = container.querySelectorAll(selector); elements.forEach((element) => { const htmlElement = element as HTMLElement; - htmlElement.style.backgroundColor = 'var(--bf-appearance-token-color-bg-primary)'; + htmlElement.style.backgroundColor = 'var(--bf-color-surface-canvas)'; }); }); diff --git a/src/web-ui/src/tools/editor/components/EditorBreadcrumb.scss b/src/web-ui/src/tools/editor/components/EditorBreadcrumb.scss index 887e8a0aad..32aa82b230 100644 --- a/src/web-ui/src/tools/editor/components/EditorBreadcrumb.scss +++ b/src/web-ui/src/tools/editor/components/EditorBreadcrumb.scss @@ -12,21 +12,19 @@ $_dropdown-width: 220px; // Breadcrumb Navigation .editor-breadcrumb { - --editor-breadcrumb-folder-rgb: 232, 181, 65; - display: flex; align-items: center; height: $_breadcrumb-height; padding: 0 $size-gap-3; - background: var(--bf-appearance-token-color-bg-scene); - border-bottom: 1px solid var(--bf-appearance-token-border-subtle); + background: var(--bf-color-surface-scene); + border-bottom: 1px solid var(--bf-color-border-subtle); overflow: hidden; flex-shrink: 0; gap: 2px; &__separator { flex-shrink: 0; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); opacity: 0.5; } @@ -36,7 +34,7 @@ $_dropdown-width: 220px; gap: 3px; font-size: var(--bf-font-size-xs); font-family: var(--bf-font-family-mono); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); white-space: nowrap; border-radius: 3px; padding: 2px 4px; @@ -45,7 +43,7 @@ $_dropdown-width: 220px; &-icon { display: flex; align-items: center; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); svg { width: 12px; height: 12px; } } @@ -57,28 +55,28 @@ $_dropdown-width: 220px; } &--ellipsis { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); cursor: default; } &--folder .editor-breadcrumb__item-icon { - color: rgb(var(--editor-breadcrumb-folder-rgb)); + color: var(--bf-color-content-muted); } &--file .editor-breadcrumb__item-icon { - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); } &--clickable { cursor: pointer; &:hover { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } } &--active { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } } } @@ -96,7 +94,7 @@ $_dropdown-width: 220px; justify-content: center; gap: $size-gap-2; padding: 16px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); } @@ -107,7 +105,7 @@ $_dropdown-width: 220px; &__empty { padding: 16px; text-align: center; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); } diff --git a/src/web-ui/src/tools/editor/components/EditorStatusBar.scss b/src/web-ui/src/tools/editor/components/EditorStatusBar.scss index ee0ed07731..4e8e4189ee 100644 --- a/src/web-ui/src/tools/editor/components/EditorStatusBar.scss +++ b/src/web-ui/src/tools/editor/components/EditorStatusBar.scss @@ -18,11 +18,11 @@ $_section-gap: 12px; justify-content: space-between; height: $_statusbar-height; padding: $_statusbar-padding; - background: var(--bf-appearance-token-color-bg-scene); - border-top: 1px solid var(--bf-appearance-token-border-subtle); + background: var(--bf-color-surface-scene); + border-top: 1px solid var(--bf-color-border-subtle); font-size: var(--bf-font-size-meta); font-family: var(--bf-font-family-mono); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); user-select: none; flex-shrink: 0; @@ -51,12 +51,12 @@ $_section-gap: 12px; cursor: pointer; &:hover { - background: var(--bf-appearance-token-element-bg-subtle); - color: var(--bf-appearance-token-color-text-secondary); + background: var(--bf-color-surface-subtle); + color: var(--bf-color-content-secondary); } &:active { - background: var(--bf-appearance-token-element-bg-medium); + background: var(--bf-color-action-neutral-surface-hover); } } } @@ -65,21 +65,21 @@ $_section-gap: 12px; &__separator { width: 1px; height: 12px; - background: var(--bf-appearance-token-border-subtle); + background: var(--bf-color-border-subtle); flex-shrink: 0; } // Selection Info &__selection { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); opacity: 0.7; margin-left: 4px; } // Read-only Badge &__readonly { - background: color-mix(in srgb, var(--bf-appearance-token-color-warning) 15%, transparent); - color: var(--bf-appearance-token-color-warning); + background: color-mix(in srgb, var(--bf-color-status-warning-content) 15%, transparent); + color: var(--bf-color-status-warning-content); padding: 1px 6px; border-radius: 3px; font-size: var(--bf-font-size-micro); @@ -113,12 +113,12 @@ $_section-gap: 12px; border-top-width: 2px; &__indicator--modified { - fill: var(--bf-appearance-token-color-warning); - color: var(--bf-appearance-token-color-warning); + fill: var(--bf-color-status-warning-content); + color: var(--bf-color-status-warning-content); } &__indicator--saved { - color: var(--bf-appearance-token-color-success); + color: var(--bf-color-status-success-content); } } } diff --git a/src/web-ui/src/tools/editor/components/ImageViewer.scss b/src/web-ui/src/tools/editor/components/ImageViewer.scss index daf0ef2540..64cbec18f7 100644 --- a/src/web-ui/src/tools/editor/components/ImageViewer.scss +++ b/src/web-ui/src/tools/editor/components/ImageViewer.scss @@ -9,8 +9,8 @@ display: flex; flex-direction: column; height: 100%; - background: var(--bf-appearance-token-color-bg-primary); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-canvas); + color: var(--bf-color-content-primary); overflow: hidden; font-family: var(--bf-font-family-sans); @@ -21,7 +21,7 @@ right: 0; bottom: 0; z-index: $z-fullscreen; - background: var(--bf-appearance-token-color-bg-primary); + background: var(--bf-color-surface-canvas); } // Toolbar layout comes from the design-system Toolbar; keep it pinned to the top. @@ -40,7 +40,7 @@ &__filename { font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -49,7 +49,7 @@ &__dimensions, &__filesize { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); white-space: nowrap; } @@ -67,12 +67,12 @@ position: relative; // Checkerboard pattern for transparent images // Uses theme CSS variables to adapt to any theme - background-color: var(--bf-appearance-token-color-bg-primary); + background-color: var(--bf-color-surface-canvas); background-image: - linear-gradient(45deg, var(--bf-appearance-token-element-bg-soft) 25%, transparent 25%), - linear-gradient(-45deg, var(--bf-appearance-token-element-bg-soft) 25%, transparent 25%), - linear-gradient(45deg, transparent 75%, var(--bf-appearance-token-element-bg-soft) 75%), - linear-gradient(-45deg, transparent 75%, var(--bf-appearance-token-element-bg-soft) 75%); + linear-gradient(45deg, var(--bf-color-action-quiet-hover) 25%, transparent 25%), + linear-gradient(-45deg, var(--bf-color-action-quiet-hover) 25%, transparent 25%), + linear-gradient(45deg, transparent 75%, var(--bf-color-action-quiet-hover) 75%), + linear-gradient(-45deg, transparent 75%, var(--bf-color-action-quiet-hover) 75%); background-size: 20px 20px; background-position: 0 0, 0 10px, 10px -10px, -10px 0px; } @@ -93,7 +93,7 @@ max-height: 100%; object-fit: contain; transition: transform 0.2s ease-out; - box-shadow: 0 4px 20px var(--bf-appearance-token-color-overlay-black-80); + box-shadow: 0 4px 20px color-mix(in srgb, var(--bf-color-content-on-light) 80%, transparent); } // Loading State @@ -103,7 +103,7 @@ align-items: center; justify-content: center; gap: 16px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); p { margin: 0; @@ -114,8 +114,8 @@ &__spinner { width: 40px; height: 40px; - border: 3px solid var(--bf-appearance-token-border-medium); - border-top-color: var(--bf-appearance-token-color-accent-500); + border: 3px solid var(--bf-color-field-border-hover); + border-top-color: var(--bf-color-accent-default); border-radius: 50%; animation: bitfun-image-viewer-spin 0.8s linear infinite; } @@ -144,14 +144,14 @@ p { margin: 0; - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); font-size: var(--bf-font-size-base); } } &__error-path { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); word-break: break-all; max-width: 600px; } diff --git a/src/web-ui/src/tools/editor/components/MarkdownEditor.scss b/src/web-ui/src/tools/editor/components/MarkdownEditor.scss index 2a9a5e9d38..f919df6b5b 100644 --- a/src/web-ui/src/tools/editor/components/MarkdownEditor.scss +++ b/src/web-ui/src/tools/editor/components/MarkdownEditor.scss @@ -8,8 +8,8 @@ flex-direction: column; width: 100%; height: 100%; - background: var(--bf-appearance-token-color-bg-scene); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-scene); + color: var(--bf-color-content-primary); overflow: hidden; } @@ -20,8 +20,8 @@ gap: $size-gap-3; min-height: 34px; padding: 4px $size-gap-3; - border-bottom: 1px solid var(--bf-appearance-token-border-subtle); - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-scene) 92%, var(--bf-appearance-token-color-bg-elevated)); + border-bottom: 1px solid var(--bf-color-border-subtle); + background: color-mix(in srgb, var(--bf-color-surface-scene) 92%, var(--bf-color-surface-raised)); flex-shrink: 0; } @@ -48,8 +48,8 @@ justify-content: center; width: 100%; height: 100%; - background: var(--bf-appearance-token-color-bg-scene); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-scene); + color: var(--bf-color-content-primary); } .bitfun-markdown-editor-error { @@ -58,8 +58,8 @@ justify-content: center; width: 100%; height: 100%; - background: var(--bf-appearance-token-color-bg-scene); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-scene); + color: var(--bf-color-content-primary); .error-content { display: flex; @@ -68,21 +68,21 @@ gap: $size-gap-4; padding: $size-gap-8; text-align: center; - background: var(--bf-appearance-token-element-bg-base); + background: var(--bf-color-action-neutral-surface); border-radius: $size-radius-lg; - border: 1px solid var(--bf-appearance-token-border-base); + border: 1px solid var(--bf-color-border-default); backdrop-filter: blur(8px); .error-icon { width: 48px; height: 48px; - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); } p { margin: 0; font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } } @@ -90,7 +90,7 @@ // Markdown preview inside m-editor only (align with flow-chat markdown chrome via shared Sass values). .m-editor .markdown-body { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-family: var(--bf-font-family-sans); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-relaxed); @@ -100,18 +100,18 @@ margin-bottom: $size-gap-4; font-weight: var(--bf-font-weight-semibold); line-height: var(--bf-line-height-tight); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } strong, b { font-weight: var(--bf-font-weight-bold); - color: var(--bf-appearance-token-color-warning); + color: var(--bf-color-status-warning-content); } h1 { font-size: var(--bf-font-size-3xl); - color: var(--bf-appearance-token-color-text-primary); - border-bottom: 1px solid var(--bf-appearance-token-border-subtle); + color: var(--bf-color-content-primary); + border-bottom: 1px solid var(--bf-color-border-subtle); padding-bottom: $size-gap-3; text-align: center; letter-spacing: var(--bf-letter-spacing-wider); @@ -119,7 +119,7 @@ h2 { font-size: var(--bf-font-size-2xl); - border-bottom: 1px solid var(--bf-appearance-token-border-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); padding-bottom: $size-gap-2; } @@ -134,12 +134,12 @@ } a { - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); text-decoration: none; transition: color $motion-fast $easing-standard; &:hover { - color: var(--bf-appearance-token-color-accent-600); + color: var(--bf-color-accent-hover); text-decoration: underline; } } @@ -182,7 +182,7 @@ color: markdownCode.$pre-code-fg; background: markdownCode.$pre-bg; border: 1px dashed markdownCode.$pre-border; - border-radius: var(--bf-appearance-token-flowchat-card-radius); + border-radius: var(--bf-control-flow-chat-card-radius); box-shadow: markdownCode.$pre-shadow; transition: border-color 0.3s ease, @@ -263,7 +263,7 @@ left: 0; top: 0; width: markdownLayout.$list-marker-width; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-medium); } @@ -314,7 +314,7 @@ margin-bottom: $size-gap-4; font-size: var(--bf-font-size-base); border: 1px solid markdownTable.$border; - border-radius: var(--bf-appearance-token-flowchat-card-radius); + border-radius: var(--bf-control-flow-chat-card-radius); background: markdownTable.$surface; box-shadow: markdownTable.$shadow; overflow: hidden; @@ -340,7 +340,7 @@ } table td { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } table th + th, @@ -378,30 +378,30 @@ table tbody tr:first-child th:first-child, table thead th:first-child { - border-top-left-radius: var(--bf-appearance-token-flowchat-card-radius); + border-top-left-radius: var(--bf-control-flow-chat-card-radius); } table tbody tr:first-child th:last-child, table thead th:last-child { - border-top-right-radius: var(--bf-appearance-token-flowchat-card-radius); + border-top-right-radius: var(--bf-control-flow-chat-card-radius); } table tbody tr:last-child td:first-child, table tbody tr:last-child th:first-child { - border-bottom-left-radius: var(--bf-appearance-token-flowchat-card-radius); + border-bottom-left-radius: var(--bf-control-flow-chat-card-radius); } table tbody tr:last-child td:last-child, table tbody tr:last-child th:last-child { - border-bottom-right-radius: var(--bf-appearance-token-flowchat-card-radius); + border-bottom-right-radius: var(--bf-control-flow-chat-card-radius); } table tbody tr:first-child th:only-child { - border-radius: var(--bf-appearance-token-flowchat-card-radius) var(--bf-appearance-token-flowchat-card-radius) 0 0; + border-radius: var(--bf-control-flow-chat-card-radius) var(--bf-control-flow-chat-card-radius) 0 0; } table tbody tr:last-child td:only-child { - border-radius: 0 0 var(--bf-appearance-token-flowchat-card-radius) var(--bf-appearance-token-flowchat-card-radius); + border-radius: 0 0 var(--bf-control-flow-chat-card-radius) var(--bf-control-flow-chat-card-radius); } table th code, @@ -429,8 +429,8 @@ details { margin: 0 0 $size-gap-4; padding: $size-gap-3 $size-gap-4; - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-secondary) 86%, transparent); - border: 1px solid var(--bf-appearance-token-border-subtle); + background: color-mix(in srgb, var(--bf-color-surface-panel) 86%, transparent); + border: 1px solid var(--bf-color-border-subtle); border-radius: $size-radius-lg; > :last-child { @@ -441,11 +441,11 @@ summary { cursor: pointer; font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); list-style-position: outside; &::marker { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } } @@ -458,7 +458,7 @@ padding: 0; margin: $size-gap-5 0; border: 0; - border-top: 1px solid var(--bf-appearance-token-border-subtle); + border-top: 1px solid var(--bf-color-border-subtle); background: none; overflow: visible; } diff --git a/src/web-ui/src/tools/editor/components/PlanViewer.scss b/src/web-ui/src/tools/editor/components/PlanViewer.scss index 459e8837d7..a25efb7b7c 100644 --- a/src/web-ui/src/tools/editor/components/PlanViewer.scss +++ b/src/web-ui/src/tools/editor/components/PlanViewer.scss @@ -7,8 +7,8 @@ display: flex; flex-direction: column; height: 100%; - background: var(--bf-appearance-token-color-bg-primary); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-canvas); + color: var(--bf-color-content-primary); overflow: hidden; // Loading and error states @@ -31,11 +31,11 @@ .error-icon { width: 48px; height: 48px; - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); } p { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-base); margin: 0; } @@ -49,19 +49,19 @@ align-items: center; justify-content: space-between; padding: 8px 12px; - background: var(--bf-appearance-token-color-bg-secondary); - border-bottom: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-panel); + border-bottom: 1px solid var(--bf-color-border-default); flex-shrink: 0; &--collapsible { cursor: pointer; &:hover { - background: var(--bf-appearance-token-color-bg-tertiary); + background: var(--bf-color-surface-tertiary); .header-expand-indicator { - color: var(--bf-appearance-token-color-text-primary); - background: var(--bf-appearance-token-color-overlay-white-08); + color: var(--bf-color-content-primary); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); } } } @@ -78,9 +78,9 @@ justify-content: center; width: 18px; height: 18px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); border-radius: 4px; - background: var(--bf-appearance-token-color-overlay-white-04); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent); transition: background-color 0.15s ease, color 0.15s ease, @@ -101,13 +101,13 @@ .file-icon { flex-shrink: 0; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } .file-name { font-size: var(--bf-font-size-base); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-family:var(--bf-font-family-mono); overflow: hidden; text-overflow: ellipsis; @@ -116,9 +116,9 @@ .unsaved-indicator { font-size: var(--bf-font-size-meta); - color: var(--bf-appearance-token-color-warning); + color: var(--bf-color-status-warning-content); padding: 2px 6px; - background: var(--bf-appearance-token-color-warning-bg); + background: var(--bf-color-status-warning-surface); border-radius: 4px; margin-left: 4px; } @@ -133,11 +133,11 @@ .todos-count { font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); padding: 2px 8px; border-radius: 999px; - border: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-color-bg-primary); + border: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-canvas); letter-spacing: var(--bf-letter-spacing-subtle); } @@ -147,8 +147,8 @@ // Todo Section .plan-viewer-todos { padding: 8px 12px; - background: var(--bf-appearance-token-color-bg-secondary); - border-bottom: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-panel); + border-bottom: 1px solid var(--bf-color-border-default); flex-shrink: 0; .todo-inline-toolbar, @@ -196,7 +196,7 @@ &--trailing { border: none; - border-top: 1px dashed var(--bf-appearance-token-border-base); + border-top: 1px dashed var(--bf-color-border-default); background: transparent; padding: 6px 16px 10px; @@ -223,20 +223,20 @@ margin-top: 2px; &--pending { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); opacity: 0.5; } &--in-progress { - color: var(--bf-appearance-token-color-info); + color: var(--bf-color-status-info-content); } &--completed { - color: var(--bf-appearance-token-color-success); + color: var(--bf-color-status-success-content); } &--cancelled { - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); opacity: 0.6; } } @@ -244,7 +244,7 @@ .todo-content { font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-base); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); flex: 1; min-width: 0; } @@ -254,15 +254,15 @@ min-width: 0; font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-base); - color: var(--bf-appearance-token-color-text-primary); - background: var(--bf-appearance-token-color-bg-primary); - border: 1px solid var(--bf-appearance-token-border-base); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-canvas); + border: 1px solid var(--bf-color-border-default); border-radius: 4px; padding: 4px 8px; outline: none; &:focus { - border-color: var(--bf-appearance-token-color-info); + border-color: var(--bf-color-status-info-content); } } @@ -274,15 +274,15 @@ // Status styles &.status-pending { .todo-content { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } } &.status-in_progress { - background: var(--bf-appearance-token-glass-blue-subtle); + background: color-mix(in srgb, var(--bf-color-accent-hover) 8%, transparent); .todo-content { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-medium); } } @@ -290,7 +290,7 @@ &.status-completed { .todo-content { text-decoration: line-through; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); opacity: 0.6; } } @@ -300,7 +300,7 @@ .todo-content { text-decoration: line-through; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } } } diff --git a/src/web-ui/src/tools/editor/components/ReadOnlyCodeBlock/ReadOnlyCodeBlock.scss b/src/web-ui/src/tools/editor/components/ReadOnlyCodeBlock/ReadOnlyCodeBlock.scss index a8350649d9..2933b2e8f9 100644 --- a/src/web-ui/src/tools/editor/components/ReadOnlyCodeBlock/ReadOnlyCodeBlock.scss +++ b/src/web-ui/src/tools/editor/components/ReadOnlyCodeBlock/ReadOnlyCodeBlock.scss @@ -3,14 +3,13 @@ */ .readonly-code-block { - --readonly-code-selection-rgb: 30, 136, 229; - --readonly-code-selection-bg: rgba(var(--readonly-code-selection-rgb), 0.3); + --readonly-code-selection-bg: color-mix(in srgb, var(--bf-color-accent-default) 30%, transparent); position: relative; width: 100%; overflow: hidden; border-radius: 6px; - background: var(--bf-appearance-token-color-bg-secondary); + background: var(--bf-color-surface-panel); // Monaco editor container .monaco-editor-core { @@ -71,7 +70,7 @@ // Bordered mode .readonly-code-block--bordered { - border: 1px solid var(--bf-appearance-token-border-base); + border: 1px solid var(--bf-color-border-default); } // Inline mode (for inline code) diff --git a/src/web-ui/src/tools/editor/components/StatusBarPopovers/StatusBarPopovers.scss b/src/web-ui/src/tools/editor/components/StatusBarPopovers/StatusBarPopovers.scss index fc1b14f89a..3a9f02f0f0 100644 --- a/src/web-ui/src/tools/editor/components/StatusBarPopovers/StatusBarPopovers.scss +++ b/src/web-ui/src/tools/editor/components/StatusBarPopovers/StatusBarPopovers.scss @@ -17,7 +17,7 @@ max-width: 320px; font-size: var(--bf-font-size-xs); font-family: var(--bf-font-family-sans); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); transform: translateY(-100%); animation: status-bar-popover-enter 0.15s $easing-decelerate forwards; @@ -45,8 +45,8 @@ &__hint { padding: 6px 12px; font-size: var(--bf-font-size-meta); - color: var(--bf-appearance-token-color-text-muted); - border-bottom: 1px solid var(--bf-appearance-token-border-subtle); + color: var(--bf-color-content-muted); + border-bottom: 1px solid var(--bf-color-border-subtle); } } diff --git a/src/web-ui/src/tools/editor/meditor/components/MEditor.scss b/src/web-ui/src/tools/editor/meditor/components/MEditor.scss index e5697f489a..8370cc9403 100644 --- a/src/web-ui/src/tools/editor/meditor/components/MEditor.scss +++ b/src/web-ui/src/tools/editor/meditor/components/MEditor.scss @@ -8,8 +8,8 @@ &-toolbar { padding: $size-gap-2; - border-bottom: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-element-bg-soft); + border-bottom: 1px solid var(--bf-color-border-default); + background: var(--bf-color-action-quiet-hover); backdrop-filter: blur(8px); } @@ -18,9 +18,9 @@ align-items: flex-start; gap: $size-gap-2; padding: $size-gap-2 $size-gap-3; - border-bottom: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-warning) 30%, transparent); - background: color-mix(in srgb, var(--bf-appearance-token-color-warning) 8%, transparent); - color: var(--bf-appearance-token-color-text-secondary); + border-bottom: 1px solid color-mix(in srgb, var(--bf-color-status-warning-content) 30%, transparent); + background: color-mix(in srgb, var(--bf-color-status-warning-content) 8%, transparent); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-support); @@ -29,7 +29,7 @@ width: 16px; height: 16px; margin-top: 2px; - color: var(--bf-appearance-token-color-warning); + color: var(--bf-color-status-warning-content); } } @@ -53,8 +53,8 @@ outline: 0; padding: $size-gap-3; box-sizing: border-box; - background: var(--bf-appearance-token-color-bg-scene); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-scene); + color: var(--bf-color-content-primary); font: inherit; font-family:var(--bf-font-family-mono); line-height: var(--bf-line-height-relaxed); @@ -73,45 +73,45 @@ &-mode-split { .m-editor-content { > .m-editor-edit-panel { - border-right: 1px solid var(--bf-appearance-token-border-base); + border-right: 1px solid var(--bf-color-border-default); } } } &-dark { - background: var(--bf-appearance-token-color-bg-scene); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-scene); + color: var(--bf-color-content-primary); .m-editor-textarea { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } .m-editor-toolbar { - background: var(--bf-appearance-token-element-bg-soft); - border-bottom-color: var(--bf-appearance-token-border-base); + background: var(--bf-color-action-quiet-hover); + border-bottom-color: var(--bf-color-border-default); } .m-editor-edit-panel { - border-right-color: var(--bf-appearance-token-border-base) !important; + border-right-color: var(--bf-color-border-default) !important; } } &-light { - background: var(--bf-appearance-token-color-bg-scene); - color: var(--bf-appearance-token-color-text-primary); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-scene); + color: var(--bf-color-content-primary); + border: 1px solid var(--bf-color-border-default); .m-editor-textarea { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } .m-editor-toolbar { - background: var(--bf-appearance-token-element-bg-soft); - border-bottom-color: var(--bf-appearance-token-border-base); + background: var(--bf-color-action-quiet-hover); + border-bottom-color: var(--bf-color-border-default); } .m-editor-edit-panel { - border-right-color: var(--bf-appearance-token-border-base) !important; + border-right-color: var(--bf-color-border-default) !important; } } diff --git a/src/web-ui/src/tools/editor/meditor/components/Preview.scss b/src/web-ui/src/tools/editor/meditor/components/Preview.scss index baa989991d..ecb0b79aff 100644 --- a/src/web-ui/src/tools/editor/meditor/components/Preview.scss +++ b/src/web-ui/src/tools/editor/meditor/components/Preview.scss @@ -13,19 +13,19 @@ &-frontmatter { margin: 0 0 $size-gap-4; overflow: hidden; - border: 1px solid var(--bf-appearance-token-border-base); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-base; - background: var(--bf-appearance-token-element-bg-soft); + background: var(--bf-color-action-quiet-hover); &__header { display: flex; align-items: center; padding: $size-gap-2 $size-gap-3; - border-bottom: 1px solid var(--bf-appearance-token-border-base); + border-bottom: 1px solid var(--bf-color-border-default); } &__label { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-semibold); } @@ -34,7 +34,7 @@ margin: 0; padding: $size-gap-3; overflow-x: auto; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-family:var(--bf-font-family-mono); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-comfortable); diff --git a/src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss b/src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss index bd657b4a5b..b36e6a0bde 100644 --- a/src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss +++ b/src/web-ui/src/tools/editor/meditor/components/TiptapEditor.scss @@ -5,9 +5,6 @@ @use '../../styles/markdown-editor-layout' as markdownLayout; .m-editor-tiptap { - --private-markdown-editor-highlight-rgb: 255, 213, 79; - --private-markdown-editor-highlight-border-rgb: 255, 193, 7; - position: relative; width: 100%; height: 100%; @@ -26,7 +23,7 @@ .ProseMirror { min-height: 100%; outline: none; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-relaxed); @@ -38,11 +35,11 @@ transition: background $motion-base $easing-standard; &:hover { - background: var(--bf-appearance-token-element-bg-subtle); + background: var(--bf-color-surface-subtle); } &.m-editor-tiptap-block-highlighted { - background: rgba(var(--private-markdown-editor-highlight-rgb), 0.15); + background: color-mix(in srgb, var(--bf-color-status-warning-content) 15%, transparent); } } @@ -53,7 +50,7 @@ > p.is-empty::before { content: attr(data-placeholder); - color: var(--bf-appearance-token-color-text-disabled); + color: var(--bf-color-content-disabled); float: left; height: 0; font-size: var(--bf-font-size-sm); @@ -91,13 +88,13 @@ h5, h6 { margin: 0; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-semibold); } h1 { font-size: var(--bf-font-size-3xl); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); text-align: center; } @@ -143,7 +140,7 @@ color: markdownCode.$pre-code-fg; background: markdownCode.$pre-bg; border: 1px dashed markdownCode.$pre-border; - border-radius: var(--bf-appearance-token-flowchat-card-radius); + border-radius: var(--bf-control-flow-chat-card-radius); box-shadow: markdownCode.$pre-shadow; transition: border-color 0.3s ease, @@ -210,7 +207,7 @@ margin: $size-gap-4 0; padding: 0; border: 0; - border-top: 1px solid var(--bf-appearance-token-border-subtle); + border-top: 1px solid var(--bf-color-border-subtle); background: none; background-color: transparent; overflow: visible; @@ -222,7 +219,7 @@ } &[data-block-id].m-editor-tiptap-block-highlighted { - border-top-color: rgba(var(--private-markdown-editor-highlight-border-rgb), 0.55); + border-top-color: color-mix(in srgb, var(--bf-color-status-warning-content) 55%, transparent); } } @@ -235,7 +232,7 @@ table-layout: fixed; font-size: var(--bf-font-size-base); border: 1px solid markdownTable.$border; - border-radius: var(--bf-appearance-token-flowchat-card-radius); + border-radius: var(--bf-control-flow-chat-card-radius); background: markdownTable.$surface; box-shadow: markdownTable.$shadow; overflow: hidden; @@ -262,7 +259,7 @@ } td { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } th + th, @@ -300,30 +297,30 @@ tbody tr:first-child th:first-child, thead th:first-child { - border-top-left-radius: var(--bf-appearance-token-flowchat-card-radius); + border-top-left-radius: var(--bf-control-flow-chat-card-radius); } tbody tr:first-child th:last-child, thead th:last-child { - border-top-right-radius: var(--bf-appearance-token-flowchat-card-radius); + border-top-right-radius: var(--bf-control-flow-chat-card-radius); } tbody tr:last-child td:first-child, tbody tr:last-child th:first-child { - border-bottom-left-radius: var(--bf-appearance-token-flowchat-card-radius); + border-bottom-left-radius: var(--bf-control-flow-chat-card-radius); } tbody tr:last-child td:last-child, tbody tr:last-child th:last-child { - border-bottom-right-radius: var(--bf-appearance-token-flowchat-card-radius); + border-bottom-right-radius: var(--bf-control-flow-chat-card-radius); } tbody tr:first-child th:only-child { - border-radius: var(--bf-appearance-token-flowchat-card-radius) var(--bf-appearance-token-flowchat-card-radius) 0 0; + border-radius: var(--bf-control-flow-chat-card-radius) var(--bf-control-flow-chat-card-radius) 0 0; } tbody tr:last-child td:only-child { - border-radius: 0 0 var(--bf-appearance-token-flowchat-card-radius) var(--bf-appearance-token-flowchat-card-radius); + border-radius: 0 0 var(--bf-control-flow-chat-card-radius) var(--bf-control-flow-chat-card-radius); } th code, @@ -361,7 +358,7 @@ left: 0; top: 0; width: markdownLayout.$list-marker-width; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-medium); } @@ -444,7 +441,7 @@ } a { - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); text-decoration: none; &:hover { @@ -466,7 +463,7 @@ z-index: 20; width: auto; max-width: calc(100% - #{$size-gap-8}); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } .m-editor-inline-ai__surface { @@ -488,8 +485,8 @@ height: 36px; padding: 0 12px 0 14px; border-radius: 999px; - background: color-mix(in srgb, var(--bf-appearance-token-color-text-muted) 8%, transparent); - border: 1px solid var(--bf-appearance-token-color-overlay-white-08); + background: color-mix(in srgb, var(--bf-color-content-muted) 8%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); input { font-size: var(--bf-font-size-sm); @@ -501,8 +498,8 @@ :root[data-bf-appearance-mode='light'] &, .light & { .m-editor-inline-ai__composer-input[data-bf-component='input'] { - background: var(--bf-appearance-token-color-overlay-slate-04); - border-color: var(--bf-appearance-token-color-overlay-slate-12); + background: color-mix(in srgb, var(--bf-color-content-muted) 4%, transparent); + border-color: color-mix(in srgb, var(--bf-color-content-muted) 12%, transparent); } } @@ -518,8 +515,8 @@ padding: 2px 8px; min-height: 0; border-radius: 999px; - background: color-mix(in srgb, var(--bf-appearance-token-color-text-muted) 14%, transparent); - color: var(--bf-appearance-token-color-text-muted); + background: color-mix(in srgb, var(--bf-color-content-muted) 14%, transparent); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-medium); letter-spacing: var(--bf-letter-spacing-wide); @@ -528,7 +525,7 @@ .m-editor-inline-ai__section-title { margin: $size-gap-2 0 6px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-micro); font-weight: var(--bf-font-weight-medium); letter-spacing: var(--bf-letter-spacing-wide); @@ -561,7 +558,7 @@ .m-editor-inline-ai-preview { margin: $size-gap-2 0 $size-gap-3; padding: 0; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } .m-editor-inline-ai-preview--inline { @@ -579,13 +576,13 @@ .m-editor-inline-ai-preview__title { font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); letter-spacing: var(--bf-letter-spacing-wide); } .m-editor-inline-ai-preview__status { font-size: var(--bf-font-size-meta); - color: var(--bf-appearance-token-color-text-disabled); + color: var(--bf-color-content-disabled); white-space: nowrap; } @@ -606,25 +603,25 @@ bottom: 6px; width: 2px; border-radius: 999px; - background: var(--bf-appearance-token-color-accent-400); + background: color-mix(in srgb, var(--bf-color-accent-default) 40%, transparent); } .m-editor-inline-ai-preview--streaming, .m-editor-inline-ai-preview--submitting, .m-editor-inline-ai-preview--ready { .m-editor-inline-ai-preview__body { - color: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 68%, var(--bf-appearance-token-color-text-secondary)); + color: color-mix(in srgb, var(--bf-color-accent-default) 68%, var(--bf-color-content-secondary)); } } .m-editor-inline-ai-preview--error { .m-editor-inline-ai-preview__title, .m-editor-inline-ai-preview__body { - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); } .m-editor-inline-ai-preview__body::before { - background: var(--bf-appearance-token-color-error-border); + background: var(--bf-color-status-danger-border); } } @@ -634,7 +631,7 @@ .m-editor-inline-ai-rendered__loading { margin-bottom: $size-gap-2; - color: var(--bf-appearance-token-color-text-disabled); + color: var(--bf-color-content-disabled); font-size: var(--bf-font-size-xs); } @@ -703,7 +700,7 @@ color: markdownCode.$pre-code-fg; background: markdownCode.$pre-bg; border: 1px dashed markdownCode.$pre-border; - border-radius: var(--bf-appearance-token-flowchat-card-radius); + border-radius: var(--bf-control-flow-chat-card-radius); box-shadow: markdownCode.$pre-shadow; overflow-x: auto; transition: @@ -783,7 +780,7 @@ .m-editor-inline-ai__error { margin-top: $size-gap-2; - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); font-size: var(--bf-font-size-xs); } @@ -792,30 +789,30 @@ .m-editor-frontmatter { margin: $size-gap-3 0; overflow: hidden; - border: 1px solid var(--bf-appearance-token-border-base); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-base; - background: var(--bf-appearance-token-element-bg-soft); - color: var(--bf-appearance-token-color-text-secondary); + background: var(--bf-color-action-quiet-hover); + color: var(--bf-color-content-secondary); } .m-editor-frontmatter__header { display: flex; align-items: center; padding: $size-gap-2 $size-gap-3; - border-bottom: 1px solid var(--bf-appearance-token-border-base); + border-bottom: 1px solid var(--bf-color-border-default); user-select: none; } .m-editor-frontmatter__label { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-semibold); } .m-editor-raw-html-inline { - color: var(--bf-appearance-token-color-text-secondary); - background: color-mix(in srgb, var(--bf-appearance-token-color-warning) 8%, transparent); - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-warning) 28%, transparent); + color: var(--bf-color-content-secondary); + background: color-mix(in srgb, var(--bf-color-status-warning-content) 8%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-status-warning-content) 28%, transparent); display: inline-flex; align-items: center; gap: 6px; @@ -830,7 +827,7 @@ font-weight: var(--bf-font-weight-semibold); letter-spacing: var(--bf-letter-spacing-wide); text-transform: uppercase; - color: var(--bf-appearance-token-color-warning); + color: var(--bf-color-status-warning-content); } .m-editor-raw-html-inline__source { @@ -885,10 +882,10 @@ width: 100%; min-height: 180px; resize: vertical; - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 12%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-content-primary) 12%, transparent); border-radius: $size-radius-base; - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-scene) 94%, black); - color: var(--bf-appearance-token-color-text-primary); + background: color-mix(in srgb, var(--bf-color-surface-scene) 94%, var(--bf-color-content-on-light)); + color: var(--bf-color-content-primary); padding: $size-gap-3; line-height: var(--bf-line-height-comfortable); word-break: break-word; @@ -898,8 +895,8 @@ -webkit-user-drag: none; &:focus { - border-color: color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 20%, transparent); - box-shadow: 0 0 0 1px color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 10%, transparent); + border-color: color-mix(in srgb, var(--bf-color-content-primary) 20%, transparent); + box-shadow: 0 0 0 1px color-mix(in srgb, var(--bf-color-content-primary) 10%, transparent); } } @@ -924,7 +921,7 @@ &:focus { border-color: transparent; - box-shadow: inset 0 0 0 1px var(--bf-appearance-token-border-base); + box-shadow: inset 0 0 0 1px var(--bf-color-border-default); } } @@ -940,7 +937,7 @@ border-radius: 0; background: transparent; box-shadow: none; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-family:var(--bf-font-family-mono); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-comfortable); @@ -955,7 +952,7 @@ .m-editor-render-only-block__preview .m-editor-render-only-block__markdown, .m-editor-raw-html-block__preview .m-editor-raw-html-block__markdown { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } .m-editor-render-only-block__preview .m-editor-render-only-block__markdown > :first-child, @@ -987,10 +984,10 @@ font-size: var(--bf-font-size-sm); white-space: pre-wrap; word-break: break-word; - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 12%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-content-primary) 12%, transparent); border-radius: $size-radius-base; - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-scene) 94%, black); - color: var(--bf-appearance-token-color-text-primary); + background: color-mix(in srgb, var(--bf-color-surface-scene) 94%, var(--bf-color-content-on-light)); + color: var(--bf-color-content-primary); padding: $size-gap-3; line-height: var(--bf-line-height-comfortable); } @@ -1014,7 +1011,7 @@ .m-editor-raw-html-block__details-summary { cursor: pointer; font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); list-style-position: outside; } @@ -1045,15 +1042,15 @@ gap: $size-gap-2; margin: $size-gap-3 0; padding: $size-gap-2 $size-gap-3; - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 10%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-content-primary) 10%, transparent); border-radius: $size-radius-base; - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-scene) 88%, white); + background: color-mix(in srgb, var(--bf-color-surface-scene) 88%, var(--bf-color-content-on-dark)); } [data-type='details'] > button { border: none; background: transparent; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); cursor: pointer; padding: 0; width: 20px; @@ -1078,7 +1075,7 @@ [data-type='details'] summary { display: block; list-style: none; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-medium); outline: none; @@ -1103,9 +1100,9 @@ .m-editor-details-block { margin: $size-gap-3 0; - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 10%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-content-primary) 10%, transparent); border-radius: $size-radius-base; - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-scene) 88%, white); + background: color-mix(in srgb, var(--bf-color-surface-scene) 88%, var(--bf-color-content-on-dark)); overflow: hidden; } @@ -1114,14 +1111,14 @@ align-items: center; gap: $size-gap-2; padding: $size-gap-2 $size-gap-3; - background: color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 4%, transparent); - border-bottom: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 8%, transparent); + background: color-mix(in srgb, var(--bf-color-content-primary) 4%, transparent); + border-bottom: 1px solid color-mix(in srgb, var(--bf-color-content-primary) 8%, transparent); } .m-editor-details-block__toggle { border: none; background: transparent; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); cursor: pointer; padding: 0; width: 20px; @@ -1135,14 +1132,14 @@ min-width: 0; border: none; background: transparent; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-medium); outline: none; } .m-editor-details-block__summary::placeholder { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } .m-editor-details-block__body { diff --git a/src/web-ui/src/tools/file-system/components/FileSearchResults.scss b/src/web-ui/src/tools/file-system/components/FileSearchResults.scss index 74164782db..b56b6f7842 100644 --- a/src/web-ui/src/tools/file-system/components/FileSearchResults.scss +++ b/src/web-ui/src/tools/file-system/components/FileSearchResults.scss @@ -12,7 +12,7 @@ $_icon-size: 16px; height: 100%; min-height: 0; overflow: hidden; - background: var(--bf-appearance-token-color-bg-primary); + background: var(--bf-color-surface-canvas); &--empty { justify-content: center; @@ -22,7 +22,7 @@ $_icon-size: 16px; .bitfun-search-results__empty { text-align: center; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); padding: $size-gap-8; &-icon { @@ -39,14 +39,14 @@ $_icon-size: 16px; .bitfun-search-results__header { padding: $size-gap-2 $size-gap-3; - border-bottom: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-color-bg-primary); + border-bottom: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-canvas); flex-shrink: 0; } .bitfun-search-results__count { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-weight: var(--bf-font-weight-medium); } @@ -86,18 +86,18 @@ $_icon-size: 16px; transition: background-color $motion-base $easing-standard, color $motion-base $easing-standard; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); text-align: left; font: inherit; appearance: none; &:hover { - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-primary); } &:focus-visible { - outline: 1px solid var(--bf-appearance-token-color-accent-500); + outline: 1px solid var(--bf-color-accent-default); outline-offset: 1px; } } @@ -109,11 +109,11 @@ $_icon-size: 16px; width: 20px; height: 20px; border-radius: $size-radius-sm; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); &--directory { - background: var(--bf-appearance-token-color-warning-bg); - color: var(--bf-appearance-token-color-warning); + background: var(--bf-color-status-warning-surface); + color: var(--bf-color-status-warning-content); } } @@ -133,7 +133,7 @@ $_icon-size: 16px; &-path { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); opacity: 0.6; @include mixins.text-ellipsis; width: 100%; @@ -146,8 +146,8 @@ $_icon-size: 16px; min-height: 20px; border: none; border-radius: 10px; - background: var(--bf-appearance-token-git-color-branch-bg); - color: var(--bf-appearance-token-git-color-branch); + background: var(--bf-domain-git-branch-background); + color: var(--bf-domain-git-branch); cursor: pointer; transition: transform $motion-fast $easing-standard, @@ -157,7 +157,7 @@ $_icon-size: 16px; appearance: none; &:hover { - background: var(--bf-appearance-token-git-color-branch-bg-hover); + background: var(--bf-domain-git-branch-background-hover); } &:active { @@ -165,7 +165,7 @@ $_icon-size: 16px; } &:focus-visible { - outline: 1px solid var(--bf-appearance-token-color-accent-500); + outline: 1px solid var(--bf-color-accent-default); outline-offset: 1px; } @@ -208,15 +208,15 @@ $_icon-size: 16px; appearance: none; &:hover { - background: var(--bf-appearance-token-element-bg-base); + background: var(--bf-color-action-neutral-surface); } &:active { - background: var(--bf-appearance-token-element-bg-soft); + background: var(--bf-color-action-quiet-hover); } &:focus-visible { - outline: 1px solid var(--bf-appearance-token-color-accent-500); + outline: 1px solid var(--bf-color-accent-default); outline-offset: 1px; } &-content { @@ -227,7 +227,7 @@ $_icon-size: 16px; display: block; font-size: var(--bf-font-size-xs); font-family: var(--bf-font-family-mono); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -237,15 +237,15 @@ $_icon-size: 16px; } .bitfun-search-results__highlight { - background: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 25%, transparent); - color: var(--bf-appearance-token-color-accent-500); + background: color-mix(in srgb, var(--bf-color-accent-default) 25%, transparent); + color: var(--bf-color-accent-default); padding: 1px 2px; border-radius: 2px; font-weight: var(--bf-font-weight-medium); } .bitfun-search-results__showing { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-weight: var(--bf-font-weight-regular); opacity: 0.7; } @@ -254,9 +254,9 @@ $_icon-size: 16px; @include mixins.flex-layout(row, center, center, $size-gap-1); padding: $size-gap-1 $size-gap-2; flex-shrink: 0; - border-top: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-element-bg-subtle); - color: var(--bf-appearance-token-color-text-muted); + border-top: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-subtle); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); cursor: pointer; transition: @@ -266,12 +266,12 @@ $_icon-size: 16px; user-select: none; &:hover { - background: var(--bf-appearance-token-element-bg-soft); - color: var(--bf-appearance-token-color-accent-600); + background: var(--bf-color-action-quiet-hover); + color: var(--bf-color-accent-hover); } &:active { - background: var(--bf-appearance-token-element-bg-medium); + background: var(--bf-color-action-neutral-surface-hover); } svg { diff --git a/src/web-ui/src/tools/file-system/components/FileTreeItem.tsx b/src/web-ui/src/tools/file-system/components/FileTreeItem.tsx index b1a4deef75..4d4a5935b0 100644 --- a/src/web-ui/src/tools/file-system/components/FileTreeItem.tsx +++ b/src/web-ui/src/tools/file-system/components/FileTreeItem.tsx @@ -157,8 +157,8 @@ export const FileTreeItem: React.FC = ({ dragImage.style.position = 'absolute'; dragImage.style.top = '-1000px'; dragImage.style.padding = '8px'; - dragImage.style.background = 'var(--bf-appearance-token-color-overlay-black-80)'; - dragImage.style.color = 'var(--bf-appearance-token-color-static-white)'; + dragImage.style.background = 'color-mix(in srgb, var(--bf-color-content-on-light) 80%, transparent)'; + dragImage.style.color = 'var(--bf-color-content-on-dark)'; dragImage.style.borderRadius = '4px'; document.body.appendChild(dragImage); dragImageRef.current = dragImage; diff --git a/src/web-ui/src/tools/file-system/styles/FileExplorer.scss b/src/web-ui/src/tools/file-system/styles/FileExplorer.scss index 9700c0d23c..8717da8c19 100644 --- a/src/web-ui/src/tools/file-system/styles/FileExplorer.scss +++ b/src/web-ui/src/tools/file-system/styles/FileExplorer.scss @@ -11,7 +11,7 @@ $_indent-width: 8px; height: 100%; overflow: hidden; @include mixins.flex-layout(column, stretch, start, 0); - background: var(--bf-appearance-token-color-bg-secondary); + background: var(--bf-color-surface-panel); border-radius: $size-radius-sm; position: relative; @@ -45,7 +45,7 @@ $_indent-width: 8px; .bitfun-file-explorer__empty { text-align: center; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); padding: $size-gap-8; } @@ -61,11 +61,11 @@ $_indent-width: 8px; padding: 4px 8px; height: 24px; font-size: var(--bf-font-size-meta); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); background: linear-gradient( 180deg, - rgba(var(--bf-appearance-token-color-static-white-rgb), 0.025) 0%, - rgba(var(--bf-appearance-token-color-static-white-rgb), 0.015) 100% + color-mix(in srgb, var(--bf-color-content-on-dark) 2.5%, transparent) 0%, + color-mix(in srgb, var(--bf-color-content-on-dark) 1.5%, transparent) 100% ); overflow: hidden; @@ -75,7 +75,7 @@ $_indent-width: 8px; } .bitfun-file-explorer__breadcrumb-separator { - color: var(--bf-appearance-token-color-text-disabled); + color: var(--bf-color-content-disabled); flex-shrink: 0; opacity: 0.4; margin: 0 1px; @@ -96,14 +96,14 @@ $_indent-width: 8px; cursor: pointer; &:hover { - color: var(--bf-appearance-token-color-text-primary); - background: var(--bf-appearance-token-color-overlay-white-08); + color: var(--bf-color-content-primary); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); } } &:last-child { - color: var(--bf-appearance-token-color-text-secondary); - background: var(--bf-appearance-token-color-overlay-white-04); + color: var(--bf-color-content-secondary); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent); } } @@ -137,36 +137,36 @@ $_indent-width: 8px; transition: background-color $motion-base $easing-standard, color $motion-base $easing-standard; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); &:focus { outline: none; - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-primary); } &:focus-visible { - outline: 1px solid var(--bf-appearance-token-color-accent-500); + outline: 1px solid var(--bf-color-accent-default); outline-offset: -1px; } &:hover { - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-primary); } &--selected { - background: var(--bf-appearance-token-git-color-branch-bg); - color: var(--bf-appearance-token-git-color-branch); + background: var(--bf-domain-git-branch-background); + color: var(--bf-domain-git-branch); .bitfun-file-explorer__node-name { - color: var(--bf-appearance-token-git-color-branch); + color: var(--bf-domain-git-branch); font-weight: var(--bf-font-weight-medium); } &:hover { - background: var(--bf-appearance-token-git-color-branch-bg-hover); - color: var(--bf-appearance-token-git-color-branch); + background: var(--bf-domain-git-branch-background-hover); + color: var(--bf-domain-git-branch); } } @@ -174,7 +174,7 @@ $_indent-width: 8px; font-style: italic; &:hover { - background: var(--bf-appearance-token-element-bg-base); + background: var(--bf-color-action-neutral-surface); } } @@ -185,7 +185,7 @@ $_indent-width: 8px; inset: 0; z-index: 0; border-radius: inherit; - background: var(--bf-appearance-token-git-color-branch-bg); + background: var(--bf-domain-git-branch-background); pointer-events: none; animation: file-node-highlight-fade 240ms cubic-bezier(0.23, 1, 0.32, 1) forwards; } @@ -196,7 +196,7 @@ $_indent-width: 8px; } .bitfun-file-explorer__node-name { - color: var(--bf-appearance-token-git-color-branch); + color: var(--bf-domain-git-branch); font-weight: var(--bf-font-weight-medium); } } @@ -210,7 +210,7 @@ $_indent-width: 8px; .bitfun-file-explorer__expand-icon { @include mixins.flex-layout(row, center, center, 0); @include mixins.size($_icon-size); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); flex-shrink: 0; min-width: $_icon-size; @@ -243,15 +243,15 @@ $_indent-width: 8px; min-width: $_icon-size; &--folder { - color: var(--bf-appearance-token-git-color-branch); + color: var(--bf-domain-git-branch); } &--folder-open { - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); } &--file { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } &--code, @@ -265,32 +265,32 @@ $_indent-width: 8px; &--java, &--c-cpp, &--font { - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); } &--html, &--css, &--sass, &--markdown { - color: var(--bf-appearance-token-color-purple-500); + color: var(--bf-color-accent-secondary); } &--image, &--audio, &--video { - color: var(--bf-appearance-token-color-success); + color: var(--bf-color-status-success-content); } &--config, &--json, &--database, &--archive { - color: var(--bf-appearance-token-color-warning); + color: var(--bf-color-status-warning-content); } &--text, &--binary { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } } @@ -319,38 +319,38 @@ $_indent-width: 8px; width: 100%; height: 26px; padding: 0 8px; - background: var(--bf-appearance-token-color-bg-elevated); + background: var(--bf-color-surface-raised); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: none !important; box-shadow: - 0 0 0 1px color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 80%, transparent), - 0 2px 8px color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 10%, transparent); + 0 0 0 1px color-mix(in srgb, var(--bf-color-accent-default) 80%, transparent), + 0 2px 8px color-mix(in srgb, var(--bf-color-content-primary) 10%, transparent); &:hover { - background: var(--bf-appearance-token-element-bg-soft); + background: var(--bf-color-action-quiet-hover); box-shadow: - 0 0 0 1px color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 90%, transparent), - 0 2px 8px color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 12%, transparent); + 0 0 0 1px color-mix(in srgb, var(--bf-color-accent-default) 90%, transparent), + 0 2px 8px color-mix(in srgb, var(--bf-color-content-primary) 12%, transparent); } &:focus-within { - background: var(--bf-appearance-token-color-bg-elevated); + background: var(--bf-color-surface-raised); box-shadow: - 0 0 0 1px var(--bf-appearance-token-color-accent-500), - 0 4px 12px color-mix(in srgb, var(--bf-appearance-token-color-text-primary) 16%, transparent); + 0 0 0 1px var(--bf-color-accent-default), + 0 4px 12px color-mix(in srgb, var(--bf-color-content-primary) 16%, transparent); } input { font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-medium); border: none !important; outline: none !important; } [data-bf-part='leading'] { - color: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 85%, transparent); + color: color-mix(in srgb, var(--bf-color-accent-default) 85%, transparent); } } } @@ -358,12 +358,12 @@ $_indent-width: 8px; .bitfun-file-explorer__compressed-path { font-style: italic; opacity: 0.85; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } .bitfun-file-explorer__node-size { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); opacity: 0.7; flex-shrink: 0; position: relative; @@ -372,7 +372,7 @@ $_indent-width: 8px; .bitfun-file-explorer__node-modified { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); opacity: 0.7; flex-shrink: 0; position: relative; @@ -405,7 +405,7 @@ $_indent-width: 8px; border: none; border-radius: $size-radius-sm; background: transparent; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); cursor: pointer; text-align: left; transition: @@ -414,8 +414,8 @@ $_indent-width: 8px; color $motion-fast $easing-standard; &:hover:not(:disabled) { - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-primary); } &:disabled { @@ -427,7 +427,7 @@ $_indent-width: 8px; .bitfun-file-explorer__empty-message { @include mixins.flex-layout(row, center, center, 0); padding: $size-gap-8; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-style: italic; } diff --git a/src/web-ui/src/tools/generative-widget/GenerativeWidgetFrame.scss b/src/web-ui/src/tools/generative-widget/GenerativeWidgetFrame.scss index 968c864127..4e64814a49 100644 --- a/src/web-ui/src/tools/generative-widget/GenerativeWidgetFrame.scss +++ b/src/web-ui/src/tools/generative-widget/GenerativeWidgetFrame.scss @@ -4,8 +4,8 @@ overflow-x: auto; overflow-y: hidden; border-radius: 10px; - background: var(--bf-appearance-token-color-overlay-white-04); - border: 1px solid var(--bf-appearance-token-color-overlay-white-08); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); } .bitfun-generative-widget-frame__iframe { diff --git a/src/web-ui/src/tools/generative-widget/GenerativeWidgetFrame.tsx b/src/web-ui/src/tools/generative-widget/GenerativeWidgetFrame.tsx index 68bf427d45..c795338bc7 100644 --- a/src/web-ui/src/tools/generative-widget/GenerativeWidgetFrame.tsx +++ b/src/web-ui/src/tools/generative-widget/GenerativeWidgetFrame.tsx @@ -4,7 +4,6 @@ import { widgetAppearanceAdapter } from '@/infrastructure/appearance/adapters/Wi import { fontPreferenceService } from '@/infrastructure/font-preference'; import { createWidgetAppearanceFallbackCss, - createWidgetAppearanceStaticShellCss, readWidgetAppearancePayload, type WidgetAppearancePayload, } from './appearancePayload'; @@ -94,9 +93,6 @@ export const GENERATIVE_WIDGET_SHELL_HTML = ` * { box-sizing: border-box; } :root { ${createWidgetAppearanceFallbackCss()} -${createWidgetAppearanceStaticShellCss()} - --bf-appearance-token-motion-fast: 0.15s; - --bf-appearance-token-easing-standard: ease; } html, body { margin: 0; @@ -104,7 +100,7 @@ ${createWidgetAppearanceStaticShellCss()} width: 100%; min-height: 0; background: transparent; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-family: var(--bf-font-family-sans); overflow-x: hidden; overflow-y: hidden; @@ -143,11 +139,11 @@ ${createWidgetAppearanceStaticShellCss()} font: inherit; } a { - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); text-decoration: none; } a:hover { - color: var(--bf-appearance-token-color-accent-600); + color: var(--bf-color-accent-hover); } [data-file-path], [data-bitfun-open-file] { @@ -168,25 +164,25 @@ ${createWidgetAppearanceStaticShellCss()} max-width: 100%; display: flex; flex-direction: column; - gap: var(--bf-appearance-token-size-gap-4); - color: var(--bf-appearance-token-color-text-primary); + gap: var(--bf-space-4); + color: var(--bf-color-content-primary); } .bf-stack { display: flex; flex-direction: column; - gap: var(--bf-appearance-token-size-gap-3); + gap: var(--bf-space-3); } .bf-row { display: flex; align-items: center; - gap: var(--bf-appearance-token-size-gap-3); + gap: var(--bf-space-3); min-width: 0; } .bf-row-wrap { display: flex; flex-wrap: wrap; align-items: center; - gap: var(--bf-appearance-token-size-gap-3); + gap: var(--bf-space-3); min-width: 0; } .bf-toolbar { @@ -194,37 +190,37 @@ ${createWidgetAppearanceStaticShellCss()} flex-wrap: wrap; align-items: center; justify-content: space-between; - gap: var(--bf-appearance-token-size-gap-3); - padding: var(--bf-appearance-token-size-gap-3) var(--bf-appearance-token-size-gap-4); - border-radius: var(--bf-appearance-token-size-radius-lg); - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-secondary) 82%, transparent); - border: 1px solid var(--bf-appearance-token-border-subtle); - box-shadow: var(--bf-appearance-token-shadow-xs); + gap: var(--bf-space-3); + padding: var(--bf-space-3) var(--bf-space-4); + border-radius: var(--bf-radius-lg); + background: color-mix(in srgb, var(--bf-color-surface-panel) 82%, transparent); + border: 1px solid var(--bf-color-border-subtle); + box-shadow: var(--bf-shadow-xs); } .bf-section { display: flex; flex-direction: column; - gap: var(--bf-appearance-token-size-gap-3); + gap: var(--bf-space-3); } .bf-section-header { display: flex; flex-wrap: wrap; align-items: flex-start; justify-content: space-between; - gap: var(--bf-appearance-token-size-gap-3); + gap: var(--bf-space-3); } .bf-title { margin: 0; font-size: var(--bf-font-size-lg); font-weight: var(--bf-font-weight-semibold); line-height: var(--bf-line-height-tight); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); letter-spacing: var(--bf-letter-spacing-snug); } .bf-subtitle { margin: 0; font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); line-height: var(--bf-line-height-base); } .bf-eyebrow { @@ -233,45 +229,45 @@ ${createWidgetAppearanceStaticShellCss()} font-weight: var(--bf-font-weight-medium); letter-spacing: var(--bf-letter-spacing-widest); text-transform: uppercase; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } .bf-card, .bf-panel { position: relative; display: flex; flex-direction: column; - gap: var(--bf-appearance-token-size-gap-3); + gap: var(--bf-space-3); width: 100%; - padding: var(--bf-appearance-token-size-gap-4); - border-radius: var(--bf-appearance-token-size-radius-lg); - background: var(--bf-appearance-token-color-bg-secondary); - border: 1px solid var(--bf-appearance-token-border-subtle); - box-shadow: var(--bf-appearance-token-shadow-sm); + padding: var(--bf-space-4); + border-radius: var(--bf-radius-lg); + background: var(--bf-color-surface-panel); + border: 1px solid var(--bf-color-border-subtle); + box-shadow: var(--bf-shadow-sm); overflow: hidden; } .bf-panel { - background: color-mix(in srgb, var(--bf-appearance-token-color-bg-secondary) 74%, var(--bf-appearance-token-element-bg-subtle)); + background: color-mix(in srgb, var(--bf-color-surface-panel) 74%, var(--bf-color-surface-subtle)); } [data-bitfun-prompt-selected="true"], [data-bitfun-context-selected="true"] { position: relative; - outline: 2px solid var(--bf-appearance-token-color-accent-500); + outline: 2px solid var(--bf-color-accent-default); outline-offset: 2px; box-shadow: - 0 0 0 4px color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 18%, transparent), - 0 10px 24px color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 14%, transparent); - border-radius: min(var(--bf-appearance-token-size-radius-base), 12px); + 0 0 0 4px color-mix(in srgb, var(--bf-color-accent-default) 18%, transparent), + 0 10px 24px color-mix(in srgb, var(--bf-color-accent-default) 14%, transparent); + border-radius: min(var(--bf-radius-base), 12px); transition: outline-color 120ms ease, box-shadow 120ms ease, transform 120ms ease; transform: translateY(-1px); } .bf-card-accent { - background: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 10%, var(--bf-appearance-token-color-bg-secondary)); - border-color: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 30%, var(--bf-appearance-token-border-subtle)); + background: color-mix(in srgb, var(--bf-color-accent-default) 10%, var(--bf-color-surface-panel)); + border-color: color-mix(in srgb, var(--bf-color-accent-default) 30%, var(--bf-color-border-subtle)); } .bf-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr)); - gap: var(--bf-appearance-token-size-gap-3); + gap: var(--bf-space-3); width: 100%; min-width: 0; } @@ -280,27 +276,27 @@ ${createWidgetAppearanceStaticShellCss()} flex-direction: column; gap: 6px; min-width: 0; - padding: var(--bf-appearance-token-size-gap-3); - border-radius: var(--bf-appearance-token-size-radius-base); - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-subtle); + padding: var(--bf-space-3); + border-radius: var(--bf-radius-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-subtle); } .bf-kpi-label { font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-medium); text-transform: uppercase; letter-spacing: var(--bf-letter-spacing-widest); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } .bf-kpi-value { font-size: var(--bf-font-size-2xl); font-weight: var(--bf-font-weight-semibold); line-height: var(--bf-line-height-display); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } .bf-kpi-meta { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } .bf-badge { display: inline-flex; @@ -310,32 +306,32 @@ ${createWidgetAppearanceStaticShellCss()} min-height: 24px; padding: 0 10px; border-radius: 999px; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-subtle); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-subtle); font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); white-space: nowrap; } .bf-badge-accent { - background: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 14%, transparent); - border-color: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 28%, var(--bf-appearance-token-border-subtle)); - color: var(--bf-appearance-token-color-accent-500); + background: color-mix(in srgb, var(--bf-color-accent-default) 14%, transparent); + border-color: color-mix(in srgb, var(--bf-color-accent-default) 28%, var(--bf-color-border-subtle)); + color: var(--bf-color-accent-default); } .bf-badge-success { - background: color-mix(in srgb, var(--bf-appearance-token-color-success) 14%, transparent); - border-color: color-mix(in srgb, var(--bf-appearance-token-color-success) 28%, var(--bf-appearance-token-border-subtle)); - color: var(--bf-appearance-token-color-success); + background: color-mix(in srgb, var(--bf-color-status-success-content) 14%, transparent); + border-color: color-mix(in srgb, var(--bf-color-status-success-content) 28%, var(--bf-color-border-subtle)); + color: var(--bf-color-status-success-content); } .bf-badge-warning { - background: color-mix(in srgb, var(--bf-appearance-token-color-warning) 14%, transparent); - border-color: color-mix(in srgb, var(--bf-appearance-token-color-warning) 28%, var(--bf-appearance-token-border-subtle)); - color: var(--bf-appearance-token-color-warning); + background: color-mix(in srgb, var(--bf-color-status-warning-content) 14%, transparent); + border-color: color-mix(in srgb, var(--bf-color-status-warning-content) 28%, var(--bf-color-border-subtle)); + color: var(--bf-color-status-warning-content); } .bf-badge-error { - background: color-mix(in srgb, var(--bf-appearance-token-color-error) 14%, transparent); - border-color: color-mix(in srgb, var(--bf-appearance-token-color-error) 28%, var(--bf-appearance-token-border-subtle)); - color: var(--bf-appearance-token-color-error); + background: color-mix(in srgb, var(--bf-color-status-danger-content) 14%, transparent); + border-color: color-mix(in srgb, var(--bf-color-status-danger-content) 28%, var(--bf-color-border-subtle)); + color: var(--bf-color-status-danger-content); } .bf-button { display: inline-flex; @@ -345,33 +341,33 @@ ${createWidgetAppearanceStaticShellCss()} min-height: 32px; max-width: 100%; padding: 0 12px; - border: 1px solid var(--bf-appearance-token-border-base); - border-radius: var(--bf-appearance-token-size-radius-sm); - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-secondary); + border: 1px solid var(--bf-color-border-default); + border-radius: var(--bf-radius-sm); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-secondary); text-decoration: none; white-space: nowrap; transition: transform 120ms cubic-bezier(0.23, 1, 0.32, 1), - background-color var(--bf-appearance-token-motion-fast) var(--bf-appearance-token-easing-standard), - border-color var(--bf-appearance-token-motion-fast) var(--bf-appearance-token-easing-standard), - color var(--bf-appearance-token-motion-fast) var(--bf-appearance-token-easing-standard), - box-shadow var(--bf-appearance-token-motion-fast) var(--bf-appearance-token-easing-standard); + background-color var(--bf-motion-duration-fast) var(--bf-motion-easing-standard), + border-color var(--bf-motion-duration-fast) var(--bf-motion-easing-standard), + color var(--bf-motion-duration-fast) var(--bf-motion-easing-standard), + box-shadow var(--bf-motion-duration-fast) var(--bf-motion-easing-standard); } .bf-button:hover { - background: var(--bf-appearance-token-element-bg-medium); - color: var(--bf-appearance-token-color-text-primary); - border-color: var(--bf-appearance-token-border-medium); + background: var(--bf-color-action-neutral-surface-hover); + color: var(--bf-color-content-primary); + border-color: var(--bf-color-field-border-hover); } .bf-button-primary { - background: var(--bf-appearance-token-color-accent-500); - color: var(--bf-appearance-token-color-static-white); + background: var(--bf-color-accent-default); + color: var(--bf-color-content-on-dark); border-color: transparent; - box-shadow: var(--bf-appearance-token-shadow-xs); + box-shadow: var(--bf-shadow-xs); } .bf-button-primary:hover { - background: var(--bf-appearance-token-color-accent-600); - color: var(--bf-appearance-token-color-static-white); + background: var(--bf-color-accent-hover); + color: var(--bf-color-content-on-dark); border-color: transparent; } .bf-input, @@ -381,15 +377,15 @@ ${createWidgetAppearanceStaticShellCss()} max-width: 100%; min-width: 0; padding: 0 12px; - border-radius: var(--bf-appearance-token-size-radius-sm); - border: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-element-bg-subtle); - color: var(--bf-appearance-token-color-text-primary); + border-radius: var(--bf-radius-sm); + border: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-subtle); + color: var(--bf-color-content-primary); transition: - background-color var(--bf-appearance-token-motion-fast) var(--bf-appearance-token-easing-standard), - border-color var(--bf-appearance-token-motion-fast) var(--bf-appearance-token-easing-standard), - color var(--bf-appearance-token-motion-fast) var(--bf-appearance-token-easing-standard), - box-shadow var(--bf-appearance-token-motion-fast) var(--bf-appearance-token-easing-standard); + background-color var(--bf-motion-duration-fast) var(--bf-motion-easing-standard), + border-color var(--bf-motion-duration-fast) var(--bf-motion-easing-standard), + color var(--bf-motion-duration-fast) var(--bf-motion-easing-standard), + box-shadow var(--bf-motion-duration-fast) var(--bf-motion-easing-standard); } .bf-input, .bf-select { @@ -403,14 +399,14 @@ ${createWidgetAppearanceStaticShellCss()} } .bf-input::placeholder, .bf-textarea::placeholder { - color: color-mix(in srgb, var(--bf-appearance-token-color-text-muted) 55%, transparent); + color: color-mix(in srgb, var(--bf-color-content-muted) 55%, transparent); } .bf-input:focus, .bf-textarea:focus, .bf-select:focus { outline: none; - border-color: var(--bf-appearance-token-color-accent-500); - background: var(--bf-appearance-token-element-bg-soft); + border-color: var(--bf-color-accent-default); + background: var(--bf-color-action-quiet-hover); } .bf-list { display: flex; @@ -422,25 +418,25 @@ ${createWidgetAppearanceStaticShellCss()} display: flex; align-items: flex-start; justify-content: space-between; - gap: var(--bf-appearance-token-size-gap-3); - padding: var(--bf-appearance-token-size-gap-3); - border-radius: var(--bf-appearance-token-size-radius-base); - background: var(--bf-appearance-token-element-bg-subtle); + gap: var(--bf-space-3); + padding: var(--bf-space-3); + border-radius: var(--bf-radius-base); + background: var(--bf-color-surface-subtle); border: 1px solid transparent; } .bf-list-item[data-file-path]:hover, .bf-list-item[data-bitfun-open-file]:hover, .bf-card[data-file-path]:hover, .bf-panel[data-file-path]:hover { - border-color: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 35%, var(--bf-appearance-token-border-subtle)); - background: color-mix(in srgb, var(--bf-appearance-token-element-bg-base) 76%, var(--bf-appearance-token-color-accent-500)); + border-color: color-mix(in srgb, var(--bf-color-accent-default) 35%, var(--bf-color-border-subtle)); + background: color-mix(in srgb, var(--bf-color-action-neutral-surface) 76%, var(--bf-color-accent-default)); } .bf-table-wrap { width: 100%; overflow-x: auto; - border: 1px solid var(--bf-appearance-token-border-subtle); - border-radius: var(--bf-appearance-token-size-radius-base); - background: var(--bf-appearance-token-color-bg-secondary); + border: 1px solid var(--bf-color-border-subtle); + border-radius: var(--bf-radius-base); + background: var(--bf-color-surface-panel); } .bf-table { width: 100%; @@ -452,15 +448,15 @@ ${createWidgetAppearanceStaticShellCss()} padding: 10px 12px; text-align: left; vertical-align: top; - border-bottom: 1px solid var(--bf-appearance-token-border-subtle); - color: var(--bf-appearance-token-color-text-secondary); + border-bottom: 1px solid var(--bf-color-border-subtle); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); word-break: break-word; } .bf-table th { font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); text-transform: uppercase; letter-spacing: var(--bf-letter-spacing-wider); } @@ -471,25 +467,25 @@ ${createWidgetAppearanceStaticShellCss()} justify-content: center; gap: 8px; min-height: 140px; - padding: var(--bf-appearance-token-size-gap-5); - border-radius: var(--bf-appearance-token-size-radius-lg); - border: 1px dashed var(--bf-appearance-token-border-base); - background: color-mix(in srgb, var(--bf-appearance-token-element-bg-subtle) 80%, transparent); - color: var(--bf-appearance-token-color-text-muted); + padding: var(--bf-space-5); + border-radius: var(--bf-radius-lg); + border: 1px dashed var(--bf-color-border-default); + background: color-mix(in srgb, var(--bf-color-surface-subtle) 80%, transparent); + color: var(--bf-color-content-muted); text-align: center; } .bf-divider { width: 100%; height: 1px; - background: var(--bf-appearance-token-border-subtle); + background: var(--bf-color-border-subtle); border: 0; margin: 0; } .bf-code { padding: 2px 6px; border-radius: 6px; - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-primary); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-xs); } @@ -500,7 +496,7 @@ ${createWidgetAppearanceStaticShellCss()} .bf-card, .bf-panel, .bf-toolbar { - padding: var(--bf-appearance-token-size-gap-3); + padding: var(--bf-space-3); } .bf-grid { grid-template-columns: 1fr; @@ -742,10 +738,10 @@ ${createWidgetAppearanceStaticShellCss()} }); var body = document.body; if (body) { - body.style.background = vars['--bf-appearance-token-color-bg-primary'] || 'transparent'; + body.style.background = vars['--bf-color-surface-canvas'] || 'transparent'; body.style.color = - vars['--bf-appearance-token-color-text-primary'] || - getComputedStyle(root).getPropertyValue('--bf-appearance-token-color-text-primary') || + vars['--bf-color-content-primary'] || + getComputedStyle(root).getPropertyValue('--bf-color-content-primary') || body.style.color; body.style.fontFamily = vars['--bf-font-family-sans'] || diff --git a/src/web-ui/src/tools/generative-widget/GenerativeWidgetPanel.scss b/src/web-ui/src/tools/generative-widget/GenerativeWidgetPanel.scss index 614785fa99..100412e574 100644 --- a/src/web-ui/src/tools/generative-widget/GenerativeWidgetPanel.scss +++ b/src/web-ui/src/tools/generative-widget/GenerativeWidgetPanel.scss @@ -15,7 +15,7 @@ } .bitfun-generative-widget-panel__empty-copy { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); } @@ -25,9 +25,9 @@ justify-content: space-between; gap: 12px; padding: 10px 12px; - border: 1px solid var(--bf-appearance-token-color-overlay-white-12); + border: 1px solid color-mix(in srgb, var(--bf-color-content-on-dark) 12%, transparent); border-radius: 10px; - background: var(--bf-appearance-token-color-bg-secondary); + background: var(--bf-color-surface-panel); } .bitfun-generative-widget-panel__toolbar-meta, @@ -39,20 +39,20 @@ .bitfun-generative-widget-panel__save-state { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } .bitfun-generative-widget-panel__save-state--saved { - color: var(--bf-appearance-token-color-success); + color: var(--bf-color-status-success-content); } .bitfun-generative-widget-panel__save-state--saving, .bitfun-generative-widget-panel__save-state--unsaved { - color: var(--bf-appearance-token-color-warning); + color: var(--bf-color-status-warning-content); } .bitfun-generative-widget-panel__save-state--error { - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); } .bitfun-generative-widget-panel__workspace { @@ -67,10 +67,10 @@ min-height: 0; display: flex; flex-direction: column; - border: 1px solid var(--bf-appearance-token-color-overlay-white-12); + border: 1px solid color-mix(in srgb, var(--bf-color-content-on-dark) 12%, transparent); border-radius: 12px; overflow: hidden; - background: var(--bf-appearance-token-color-bg-secondary); + background: var(--bf-color-surface-panel); } .bitfun-generative-widget-panel__pane-header { @@ -79,7 +79,7 @@ justify-content: space-between; gap: 8px; padding: 10px 12px; - border-bottom: 1px solid var(--bf-appearance-token-color-overlay-white-08); + border-bottom: 1px solid color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); } .bitfun-generative-widget-panel__pane-title { @@ -88,7 +88,7 @@ gap: 6px; font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } .bitfun-generative-widget-panel__editor-field { @@ -104,7 +104,7 @@ outline: none; padding: 14px 16px; background: transparent; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-regular); @@ -114,8 +114,8 @@ .bitfun-generative-widget-panel__error { padding: 10px 12px; border-radius: 10px; - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-error) 50%, transparent); - background: color-mix(in srgb, var(--bf-appearance-token-color-error) 10%, transparent); - color: var(--bf-appearance-token-color-error); + border: 1px solid color-mix(in srgb, var(--bf-color-status-danger-content) 50%, transparent); + background: color-mix(in srgb, var(--bf-color-status-danger-content) 10%, transparent); + color: var(--bf-color-status-danger-content); font-size: var(--bf-font-size-xs); } diff --git a/src/web-ui/src/tools/generative-widget/GenerativeWidgetStaticRenderer.tsx b/src/web-ui/src/tools/generative-widget/GenerativeWidgetStaticRenderer.tsx index 30cb129210..e611668308 100644 --- a/src/web-ui/src/tools/generative-widget/GenerativeWidgetStaticRenderer.tsx +++ b/src/web-ui/src/tools/generative-widget/GenerativeWidgetStaticRenderer.tsx @@ -77,7 +77,7 @@ export const GenerativeWidgetStaticRenderer: React.FC { const style: React.CSSProperties & Record = { background: 'transparent', - color: 'var(--bf-appearance-token-color-text-primary)', + color: 'var(--bf-color-content-primary)', width: '100%', }; diff --git a/src/web-ui/src/tools/generative-widget/appearancePayload.test.ts b/src/web-ui/src/tools/generative-widget/appearancePayload.test.ts index 42e2415244..825c338f1e 100644 --- a/src/web-ui/src/tools/generative-widget/appearancePayload.test.ts +++ b/src/web-ui/src/tools/generative-widget/appearancePayload.test.ts @@ -1,198 +1,39 @@ import { createHash } from 'node:crypto'; +import { + cssVariables as systemCssVariables, + tokens as systemTokens, +} from '@bitfun/design-tokens'; +import { themeCssVariables } from '@bitfun/theme-bitfun'; import { afterEach, describe, expect, it, vi } from 'vitest'; +import { widgetAppearanceAdapter } from '@/infrastructure/appearance/adapters/WidgetAppearanceAdapter'; import { - WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES, - WIDGET_TYPOGRAPHY_VARIABLE_NAMES, - WIDGET_APPEARANCE_VAR_NAMES, WIDGET_APPEARANCE_FALLBACK_VARS, + WIDGET_APPEARANCE_VAR_NAMES, + WIDGET_TYPOGRAPHY_VARIABLE_NAMES, createWidgetAppearanceFallbackCss, - createWidgetAppearanceStaticShellCss, readWidgetAppearancePayload, } from './appearancePayload'; -import { widgetAppearanceAdapter } from '@/infrastructure/appearance/adapters/WidgetAppearanceAdapter'; -const WIDGET_APPEARANCE_VAR_NAMES_HASH = '1f51a4826457c2a97d91d3e15845482b8e1dea3b350c9de6d423498d7cba5bdf'; -const WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES_HASH = 'ccdda56565fec7e2491b6c8d4645267f7a972bf9f54a79cde9637fc450bfd025'; -const RETIRED_WIDGET_APPEARANCE_COMPAT_KEYS = [ +const CANONICAL_THEME_VARIABLE_NAMES = Object.values(themeCssVariables); +const CANONICAL_THEME_VARIABLE_NAMES_HASH = '8d2fa88bd263ebe01778f9df1a717d8be3126aad34879f2bf530b8842f9d4678'; +const RETIRED_WIDGET_VARIABLE_NAMES = [ '--background-primary', - '--background-secondary', - '--background-tertiary', - '--bf-appearance-token-border-muted', - '--bf-appearance-token-border-primary', - '--bf-appearance-token-border-color', - '--bf-appearance-token-border-hover', - '--bg-elevated', - '--bg-hover', '--bg-primary', - '--bg-secondary', - '--bg-tertiary', - '--bf-appearance-token-color-background-secondary', - '--bf-appearance-token-color-background-tertiary', - '--bf-appearance-token-color-bg-base', - '--bf-appearance-token-color-bg-elevated-hover', - '--bf-appearance-token-color-bg-flowchat', - '--bf-appearance-token-color-bg-hover', - '--bf-appearance-token-color-bg-subtle', - '--bf-appearance-token-color-bg-surface', - '--bf-appearance-token-color-border', - '--bf-appearance-token-color-border-primary', - '--bf-appearance-token-color-border-subtle', - '--bf-appearance-token-color-hover', - '--bf-appearance-token-color-semantic-error', - '--bf-appearance-token-color-success-100', - '--bf-appearance-token-color-success-500', - '--bf-appearance-token-color-surface-elevated', - '--bf-appearance-token-color-surface-hover', - '--bf-appearance-token-color-text-tertiary', - '--bf-appearance-token-color-warning-100', - '--bf-appearance-token-color-warning-500', - '--bf-appearance-token-color-warning-700', - '--bf-appearance-token-color-overlay-white-02', - '--bf-appearance-token-color-overlay-white-03', - '--bf-appearance-token-color-overlay-white-05', - '--bf-appearance-token-color-overlay-white-06', - '--bf-appearance-token-color-overlay-white-10', - '--bf-appearance-token-color-overlay-black-06', - '--bf-appearance-token-color-overlay-black-10', - '--bf-appearance-token-color-overlay-black-25', - '--bf-appearance-token-color-accent', - '--bf-appearance-token-color-accent-primary', - '--bf-appearance-token-color-accent-alpha', - '--bf-appearance-token-color-primary', - '--bf-appearance-token-color-primary-rgb', - '--bf-appearance-token-color-primary-400', - '--bf-appearance-token-color-primary-hover', - '--bf-appearance-token-color-primary-500', - '--bf-appearance-token-color-primary-alpha', - '--bf-appearance-token-color-primary-bg', - '--bf-appearance-token-color-primary-bg-subtle', - '--accent-primary', - '--accent-primary-hover', - '--bf-appearance-token-color-danger', - '--bf-appearance-token-color-danger-500', - '--bf-appearance-token-color-danger-text', - '--bf-appearance-token-color-danger-bg', - '--bf-appearance-token-color-danger-border', - '--bf-appearance-token-color-danger-hover', - '--bf-appearance-token-element-bg', - '--bf-appearance-token-element-bg-elevated', - // typography-audit: negative-test-start -- retained only to verify legacy widget font aliases stay retired - '--bf-appearance-token-font-mono', - '--bf-appearance-token-font-sans', - // typography-audit: negative-test-end - '--markdown-font-mono', - '--bf-appearance-token-motion-normal', - '--smooth-height-collapse-duration', - '--radius-2xl', - '--radius-base', - '--radius-full', - '--radius-lg', - '--radius-md', - '--radius-sm', - '--radius-xl', - '--secondary-bg', - '--spacing-1', - '--spacing-10', - '--spacing-12', - '--spacing-16', - '--spacing-2', - '--spacing-3', - '--spacing-4', - '--spacing-5', - '--spacing-6', - '--spacing-8', - '--text-disabled', - '--text-muted', '--text-primary', - '--text-secondary', - '--text-tertiary', - '--bf-appearance-token-tool-card-bg-primary', - '--bf-appearance-token-tool-card-bg-secondary', - '--bf-appearance-token-tool-card-bg-hover', - '--bf-appearance-token-tool-card-bg-elevated', - '--bf-appearance-token-tool-card-border', - '--bf-appearance-token-tool-card-border-subtle', - '--bf-appearance-token-tool-card-text-primary', - '--bf-appearance-token-tool-card-text-secondary', - '--bf-appearance-token-tool-card-text-muted', - '--tool-compact-summary-font', -] as const; -const RETIRED_WIDGET_APPEARANCE_INTERNAL_KEYS = [ - '--bf-appearance-token-btn-ghost-bg', - '--bf-appearance-token-btn-ghost-border', - '--bf-appearance-token-btn-ghost-shadow', - '--bf-appearance-token-btn-ghost-hover-shadow', - '--bf-appearance-token-btn-ghost-hover-transform', - '--bf-appearance-token-btn-ghost-active-bg', - '--bf-appearance-token-btn-ghost-active-color', - '--bf-appearance-token-btn-ghost-active-border', - '--bf-appearance-token-btn-ghost-active-shadow', - '--bf-appearance-token-btn-ghost-active-transform', -] as const; -const DERIVED_WIDGET_APPEARANCE_PAYLOAD_KEYS = [ - '--bf-appearance-token-color-accent-50', - '--bf-appearance-token-color-accent-100', - '--bf-appearance-token-color-accent-200', - '--bf-appearance-token-color-accent-300', - '--bf-appearance-token-color-accent-400', - '--bf-appearance-token-color-accent-700', - '--bf-appearance-token-color-accent-800', - '--bf-appearance-token-color-success-border', - '--bf-appearance-token-color-warning-border', - '--bf-appearance-token-color-error-border', - '--bf-appearance-token-border-strong', - '--bf-appearance-token-border-prominent', - '--bf-appearance-token-element-bg-strong', - '--bf-appearance-token-size-radius-sm', - '--bf-appearance-token-size-radius-base', - '--bf-appearance-token-size-radius-md', - '--bf-appearance-token-size-radius-lg', - '--bf-appearance-token-size-radius-xl', - '--bf-appearance-token-size-radius-2xl', - '--bf-appearance-token-size-radius-full', - '--bf-appearance-token-size-gap-1', - '--bf-appearance-token-size-gap-2', - '--bf-appearance-token-size-gap-3', - '--bf-appearance-token-size-gap-4', - '--bf-appearance-token-size-gap-5', - '--bf-appearance-token-size-gap-6', - '--bf-appearance-token-size-gap-8', - '--bf-appearance-token-size-gap-10', - '--bf-appearance-token-size-gap-12', - '--bf-appearance-token-size-gap-16', - '--bf-font-size-xs', - '--bf-font-size-sm', - '--bf-font-size-base', - '--bf-font-size-lg', - '--bf-font-size-2xl', - '--bf-font-weight-medium', - '--bf-font-weight-semibold', -] as const; -const STATIC_WIDGET_SHELL_APPEARANCE_VARS = new Set([ - ...WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES, - '--bf-font-family-mono', - '--bf-font-family-sans', -]); -const LOCAL_ONLY_WIDGET_SHELL_KEYS = [ - '--bf-appearance-token-color-bg-workbench', - '--bf-appearance-token-color-overlay-white-08', - '--bf-appearance-token-color-overlay-black-12', - '--bf-appearance-token-tool-card-header-pad-y', - '--bf-type-flow-control-line-height', -] as const; -const IFRAME_ROOT_BASE_KEYS = [ - '--bf-font-family-sans', - '--bf-font-family-mono', - '--bf-font-size-xs', - '--bf-font-size-sm', - '--bf-font-size-base', - '--bf-font-size-lg', - '--bf-font-size-2xl', - '--bf-font-weight-medium', - '--bf-font-weight-semibold', + '--accent-primary', + '--bf-appearance-token-color-bg-primary', + '--bf-appearance-token-color-text-primary', + '--bf-appearance-token-color-accent-500', + '--bf-appearance-token-btn-primary-bg', + '--bf-color-accent-default-rgb', + '--bf-color-status-success-content-bg', + '--bf-color-status-success-content-border', + '--bf-color-status-warning-content-bg', + '--bf-color-status-warning-content-border', + '--bf-color-status-danger-content-bg', + '--bf-color-status-danger-content-border', ] as const; -const IFRAME_ROOT_BASE_APPEARANCE_VARS = new Set(IFRAME_ROOT_BASE_KEYS); function readPayloadWithHostValues(hostValues: Record = {}) { widgetAppearanceAdapter.apply({ @@ -201,13 +42,10 @@ function readPayloadWithHostValues(hostValues: Record = {}) { vars: hostValues, }, undefined, { revision: 1, mode: 'dark', assets: {} }); - return { - payload: readWidgetAppearancePayload(), - requestedNames: [...WIDGET_APPEARANCE_VAR_NAMES], - }; + return readWidgetAppearancePayload(); } -function hashNames(names: string[]): string { +function hashNames(names: readonly string[]): string { return createHash('sha256') .update(names.join('\n')) .digest('hex'); @@ -218,139 +56,79 @@ describe('generated widget appearance payload contract', () => { vi.unstubAllGlobals(); }); - it('keeps the host payload allowlist stable without exposing it as API', () => { - const { requestedNames } = readPayloadWithHostValues(); - - expect(new Set(requestedNames).size).toBe(requestedNames.length); + it('derives its complete host payload allowlist from the canonical theme package', () => { + expect(WIDGET_APPEARANCE_VAR_NAMES).toEqual(CANONICAL_THEME_VARIABLE_NAMES); + expect(new Set(WIDGET_APPEARANCE_VAR_NAMES).size).toBe(WIDGET_APPEARANCE_VAR_NAMES.length); expect({ - count: requestedNames.length, - hash: hashNames(requestedNames), - first: requestedNames[0], - last: requestedNames[requestedNames.length - 1], + count: WIDGET_APPEARANCE_VAR_NAMES.length, + hash: hashNames(WIDGET_APPEARANCE_VAR_NAMES), + first: WIDGET_APPEARANCE_VAR_NAMES[0], + last: WIDGET_APPEARANCE_VAR_NAMES[WIDGET_APPEARANCE_VAR_NAMES.length - 1], }).toEqual({ - count: 54, - hash: WIDGET_APPEARANCE_VAR_NAMES_HASH, - first: '--bf-appearance-token-color-bg-primary', - last: '--bf-appearance-token-btn-ghost-hover-border', + count: 100, + hash: CANONICAL_THEME_VARIABLE_NAMES_HASH, + first: '--bf-color-accent-border', + last: '--bf-shadow-xs', }); }); - it('uses reviewed iframe fallback values for requested host payload keys', () => { - const { payload, requestedNames } = readPayloadWithHostValues(); - const requestedFallbackVars = Object.fromEntries( - Object.entries(WIDGET_APPEARANCE_FALLBACK_VARS).filter(([name]) => requestedNames.includes(name)), - ); - - const payloadVars = payload?.vars ?? {}; - const requestedPayloadVars = Object.fromEntries( - Object.entries(payloadVars).filter(([name]) => requestedNames.includes(name)), - ); + it('uses the builtin canonical theme as the payload fallback', () => { + const payload = readPayloadWithHostValues(); - expect(requestedPayloadVars).toEqual(requestedFallbackVars); - expect(Object.keys(payloadVars).sort()).toEqual([ - ...Object.keys(requestedFallbackVars), + expect(payload?.vars).toMatchObject(WIDGET_APPEARANCE_FALLBACK_VARS); + expect(Object.keys(WIDGET_APPEARANCE_FALLBACK_VARS)).toEqual(WIDGET_APPEARANCE_VAR_NAMES); + expect(Object.keys(payload?.vars ?? {}).sort()).toEqual([ + ...WIDGET_APPEARANCE_VAR_NAMES, ...WIDGET_TYPOGRAPHY_VARIABLE_NAMES, ].sort()); + expect(WIDGET_APPEARANCE_FALLBACK_VARS['--bf-color-surface-canvas']).toBe('transparent'); }); - it('does not export retired low-risk compatibility keys', () => { - const { requestedNames } = readPayloadWithHostValues(); - - expect(requestedNames).not.toEqual(expect.arrayContaining(RETIRED_WIDGET_APPEARANCE_COMPAT_KEYS)); - expect(requestedNames).not.toEqual(expect.arrayContaining(RETIRED_WIDGET_APPEARANCE_INTERNAL_KEYS)); - expect(requestedNames).not.toEqual(expect.arrayContaining(DERIVED_WIDGET_APPEARANCE_PAYLOAD_KEYS)); - expect(requestedNames).toEqual( - expect.arrayContaining([ - '--bf-appearance-token-color-accent-500', - '--bf-appearance-token-color-accent-500-rgb', - '--bf-appearance-token-color-accent-600', - '--bf-appearance-token-color-error', - '--bf-appearance-token-color-error-bg', - '--bf-appearance-token-color-info', - '--bf-appearance-token-color-info-bg', - '--bf-appearance-token-color-info-border', - '--bf-appearance-token-btn-primary-bg', - '--bf-appearance-token-btn-primary-hover-bg', - '--bf-appearance-token-btn-primary-hover-transform', - '--bf-appearance-token-btn-ghost-hover-bg', - ]) + it('exports canonical state and status semantics without legacy aliases', () => { + expect(WIDGET_APPEARANCE_VAR_NAMES).toEqual(expect.arrayContaining([ + '--bf-color-action-primary-background', + '--bf-color-action-primary-hover', + '--bf-color-action-primary-pressed', + '--bf-color-status-success-content', + '--bf-color-status-success-surface', + '--bf-color-status-success-border', + '--bf-color-status-warning-surface', + '--bf-color-status-danger-surface', + '--bf-color-status-info-surface', + ])); + expect(WIDGET_APPEARANCE_VAR_NAMES).not.toEqual( + expect.arrayContaining(RETIRED_WIDGET_VARIABLE_NAMES), ); + expect(WIDGET_APPEARANCE_VAR_NAMES.some(name => name.startsWith('--bf-appearance-token-'))) + .toBe(false); }); - it('exports button component tokens from the host Appearance payload', () => { + it('passes canonical host overrides through unchanged', () => { const hostValues = { - '--bf-appearance-token-btn-primary-bg': 'linear-gradient(test-primary)', - '--bf-appearance-token-btn-primary-color': '#101010', - '--bf-appearance-token-btn-primary-border': '1px solid #202020', - '--bf-appearance-token-btn-primary-shadow': '0 1px 2px #303030', - '--bf-appearance-token-btn-primary-hover-bg': 'linear-gradient(test-hover)', - '--bf-appearance-token-btn-primary-hover-color': '#404040', - '--bf-appearance-token-btn-primary-hover-border': '1px solid #505050', - '--bf-appearance-token-btn-primary-hover-shadow': '0 2px 4px #606060', - '--bf-appearance-token-btn-primary-hover-transform': 'translateY(-1px)', - '--bf-appearance-token-btn-primary-active-bg': 'linear-gradient(test-active)', - '--bf-appearance-token-btn-primary-active-color': '#707070', - '--bf-appearance-token-btn-primary-active-border': '1px solid #808080', - '--bf-appearance-token-btn-primary-active-shadow': 'none', - '--bf-appearance-token-btn-primary-active-transform': 'none', - '--bf-appearance-token-btn-ghost-color': '#909090', - '--bf-appearance-token-btn-ghost-hover-bg': 'rgba(144, 144, 144, 0.1)', - '--bf-appearance-token-btn-ghost-hover-color': '#a0a0a0', - '--bf-appearance-token-btn-ghost-hover-border': '1px solid #b0b0b0', + '--bf-color-action-primary-background': 'linear-gradient(test-primary)', + '--bf-color-action-primary-content': '#101010', + '--bf-color-action-primary-hover': 'linear-gradient(test-hover)', + '--bf-color-action-primary-pressed': '#202020', + '--bf-color-status-danger-surface': 'rgba(200, 0, 0, 0.12)', + '--bf-color-status-danger-border': '#303030', + '--bf-shadow-raised': '0 1px 2px #404040', }; - const { payload } = readPayloadWithHostValues(hostValues); - - expect(payload?.vars).toMatchObject(hostValues); - }); - - it('keeps derived widget keys resolvable without host payload reads', () => { - const { requestedNames } = readPayloadWithHostValues(); - for (const name of DERIVED_WIDGET_APPEARANCE_PAYLOAD_KEYS) { - expect(requestedNames).not.toContain(name); - expect( - name in WIDGET_APPEARANCE_FALLBACK_VARS - || STATIC_WIDGET_SHELL_APPEARANCE_VARS.has(name) - || IFRAME_ROOT_BASE_APPEARANCE_VARS.has(name), - ).toBe(true); - } + expect(readPayloadWithHostValues(hostValues)?.vars).toMatchObject(hostValues); }); - it('renders fallback CSS from the same reviewed fallback map', () => { + it('renders one self-contained fallback scope from canonical theme and system tokens', () => { const css = createWidgetAppearanceFallbackCss(); for (const [name, value] of Object.entries(WIDGET_APPEARANCE_FALLBACK_VARS)) { expect(css).toContain(` ${name}: ${value};`); } - }); - - it('keeps host-internal shell vars available without exporting them from the host payload', () => { - const { requestedNames } = readPayloadWithHostValues(); - const css = createWidgetAppearanceStaticShellCss(); - const resolvableVars = new Set([ - ...Object.keys(WIDGET_APPEARANCE_FALLBACK_VARS), - ...requestedNames, - ...WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES, - ...IFRAME_ROOT_BASE_KEYS, - ...WIDGET_TYPOGRAPHY_VARIABLE_NAMES, - ]); - - for (const name of WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES) { - expect(css).toContain(` ${name}: `); + for (const [tokenName, value] of Object.entries(systemTokens)) { + const variableName = systemCssVariables[tokenName as keyof typeof systemCssVariables]; + expect(css).toContain(` ${variableName}: ${String(value)};`); + } + for (const retiredName of RETIRED_WIDGET_VARIABLE_NAMES) { + expect(css).not.toContain(`${retiredName}:`); } - expect({ - count: WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES.length, - hash: hashNames(WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES), - first: WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES[0], - last: WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES[WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES.length - 1], - }).toEqual({ - count: 62, - hash: WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES_HASH, - first: '--bf-appearance-token-color-bg-quaternary', - last: '--bf-appearance-token-tool-card-expanded-pad-x', - }); - const referencedVars = [...css.matchAll(/var\((--[a-zA-Z0-9_-]+)/g)].map((match) => match[1]); - expect(referencedVars.filter((name) => !resolvableVars.has(name))).toEqual([]); - expect(requestedNames).not.toEqual(expect.arrayContaining(LOCAL_ONLY_WIDGET_SHELL_KEYS)); }); }); diff --git a/src/web-ui/src/tools/generative-widget/appearancePayload.ts b/src/web-ui/src/tools/generative-widget/appearancePayload.ts index 5e10135565..37cc30f336 100644 --- a/src/web-ui/src/tools/generative-widget/appearancePayload.ts +++ b/src/web-ui/src/tools/generative-widget/appearancePayload.ts @@ -1,163 +1,43 @@ -import { widgetAppearanceAdapter } from '@/infrastructure/appearance/adapters/WidgetAppearanceAdapter'; -import { WIDGET_APPEARANCE_VARIABLE_NAMES } from '@/infrastructure/appearance/adapters/widgetAppearanceVariables'; -import { getBuiltinAppearanceCssToken } from '@/infrastructure/appearance/builtins/catalog'; import { cssVariables as systemCssVariables, tokens as systemTokens, type TokenName as SystemTokenName, } from '@bitfun/design-tokens'; +import { widgetAppearanceAdapter } from '@/infrastructure/appearance/adapters/WidgetAppearanceAdapter'; +import { WIDGET_APPEARANCE_VARIABLE_NAMES } from '@/infrastructure/appearance/adapters/widgetAppearanceVariables'; +import { getBuiltinAppearanceThemeTokens } from '@/infrastructure/appearance/builtins/catalog'; + export type WidgetAppearancePayload = { id: string; mode: string; vars: Record; }; -const FALLBACK_VAR = { - bgPrimary: '--bf-appearance-token-color-bg-primary', - bgElevated: '--bf-appearance-token-color-bg-elevated', - bgTertiary: '--bf-appearance-token-color-bg-tertiary', - bgScene: '--bf-appearance-token-color-bg-scene', - textPrimary: '--bf-appearance-token-color-text-primary', - textSecondary: '--bf-appearance-token-color-text-secondary', - textMuted: '--bf-appearance-token-color-text-muted', - textDisabled: '--bf-appearance-token-color-text-disabled', - accent50: '--bf-appearance-token-color-accent-50', - accent100: '--bf-appearance-token-color-accent-100', - accent400: '--bf-appearance-token-color-accent-400', - accent500: '--bf-appearance-token-color-accent-500', - accent500Rgb: '--bf-appearance-token-color-accent-500-rgb', - accent600: '--bf-appearance-token-color-accent-600', - bgSecondary: '--bf-appearance-token-color-bg-secondary', - success: '--bf-appearance-token-color-success', - successBg: '--bf-appearance-token-color-success-bg', - warning: '--bf-appearance-token-color-warning', - warningBg: '--bf-appearance-token-color-warning-bg', - error: '--bf-appearance-token-color-error', - errorBg: '--bf-appearance-token-color-error-bg', - errorBorder: '--bf-appearance-token-color-error-border', - staticWhite: '--bf-appearance-token-color-static-white', - staticBlack: '--bf-appearance-token-color-static-black', - overlayWhite04: '--bf-appearance-token-color-overlay-white-04', - overlayBlack08: '--bf-appearance-token-color-overlay-black-08', - overlayBlack30: '--bf-appearance-token-color-overlay-black-30', - borderSubtle: '--bf-appearance-token-border-subtle', - borderBase: '--bf-appearance-token-border-base', - borderMedium: '--bf-appearance-token-border-medium', - elementBgSubtle: '--bf-appearance-token-element-bg-subtle', - elementBgBase: '--bf-appearance-token-element-bg-base', - elementBgMedium: '--bf-appearance-token-element-bg-medium', - elementBgSoft: '--bf-appearance-token-element-bg-soft', - elementBgHover: '--bf-appearance-token-element-bg-hover', - motionBase: '--bf-appearance-token-motion-base', - shadowXs: '--bf-appearance-token-shadow-xs', - shadowSm: '--bf-appearance-token-shadow-sm', - sizeRadiusSm: '--bf-appearance-token-size-radius-sm', - sizeRadiusBase: '--bf-appearance-token-size-radius-base', - sizeRadiusMd: '--bf-appearance-token-size-radius-md', - sizeRadiusLg: '--bf-appearance-token-size-radius-lg', - sizeRadiusXl: '--bf-appearance-token-size-radius-xl', - sizeRadius2xl: '--bf-appearance-token-size-radius-2xl', - sizeRadiusFull: '--bf-appearance-token-size-radius-full', - sizeGap1: '--bf-appearance-token-size-gap-1', - sizeGap2: '--bf-appearance-token-size-gap-2', - sizeGap3: '--bf-appearance-token-size-gap-3', - sizeGap4: '--bf-appearance-token-size-gap-4', - sizeGap5: '--bf-appearance-token-size-gap-5', - sizeGap6: '--bf-appearance-token-size-gap-6', - sizeGap8: '--bf-appearance-token-size-gap-8', - sizeGap10: '--bf-appearance-token-size-gap-10', - sizeGap12: '--bf-appearance-token-size-gap-12', - sizeGap16: '--bf-appearance-token-size-gap-16', -} as const; +const builtinThemeTokens = getBuiltinAppearanceThemeTokens(); -type WidgetAppearanceFallbackVarName = typeof FALLBACK_VAR[keyof typeof FALLBACK_VAR]; -const widgetVar = (name: string): string => `var(${name})`; -const builtinToken = (name: WidgetAppearanceFallbackVarName): string => getBuiltinAppearanceCssToken(name); +function requireBuiltinThemeToken(name: string): string { + const value = builtinThemeTokens[name as keyof typeof builtinThemeTokens]; + if (typeof value !== 'string') { + throw new Error(`Default Appearance does not define widget theme token ${name}`); + } + return value; +} -const WIDGET_APPEARANCE_FALLBACK_COLOR = { - textPrimary: builtinToken(FALLBACK_VAR.textPrimary), - textSecondary: builtinToken(FALLBACK_VAR.textSecondary), - textMuted: builtinToken(FALLBACK_VAR.textMuted), - accent500: builtinToken(FALLBACK_VAR.accent500), - accent600: builtinToken(FALLBACK_VAR.accent600), - bgSecondary: builtinToken(FALLBACK_VAR.bgSecondary), - success: builtinToken(FALLBACK_VAR.success), - warning: builtinToken(FALLBACK_VAR.warning), - error: builtinToken(FALLBACK_VAR.error), - staticWhite: builtinToken(FALLBACK_VAR.staticWhite), - staticBlack: builtinToken(FALLBACK_VAR.staticBlack), - borderSubtle: builtinToken(FALLBACK_VAR.borderSubtle), - borderBase: builtinToken(FALLBACK_VAR.borderBase), - borderMedium: builtinToken(FALLBACK_VAR.borderMedium), - elementBgSubtle: builtinToken(FALLBACK_VAR.elementBgSubtle), - elementBgBase: builtinToken(FALLBACK_VAR.elementBgBase), - elementBgMedium: builtinToken(FALLBACK_VAR.elementBgMedium), - shadowBase: builtinToken(FALLBACK_VAR.overlayBlack30), -} as const; +export const WIDGET_APPEARANCE_FALLBACK_VARS = Object.freeze(Object.fromEntries( + WIDGET_APPEARANCE_VARIABLE_NAMES.map(name => [ + name, + name === '--bf-color-surface-canvas' ? 'transparent' : requireBuiltinThemeToken(name), + ]), +)); -// Keep this fallback map small and self-contained. It is the last-resort iframe -// contract for static widget rendering before the host Appearance payload arrives. -export const WIDGET_APPEARANCE_FALLBACK_VARS = { - [FALLBACK_VAR.bgPrimary]: 'transparent', - [FALLBACK_VAR.bgElevated]: WIDGET_APPEARANCE_FALLBACK_COLOR.bgSecondary, - [FALLBACK_VAR.bgTertiary]: WIDGET_APPEARANCE_FALLBACK_COLOR.bgSecondary, - [FALLBACK_VAR.bgScene]: WIDGET_APPEARANCE_FALLBACK_COLOR.bgSecondary, - [FALLBACK_VAR.textPrimary]: WIDGET_APPEARANCE_FALLBACK_COLOR.textPrimary, - [FALLBACK_VAR.textSecondary]: WIDGET_APPEARANCE_FALLBACK_COLOR.textSecondary, - [FALLBACK_VAR.textMuted]: WIDGET_APPEARANCE_FALLBACK_COLOR.textMuted, - [FALLBACK_VAR.textDisabled]: WIDGET_APPEARANCE_FALLBACK_COLOR.textMuted, - [FALLBACK_VAR.accent50]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.accent500)} 10%, transparent)`, - [FALLBACK_VAR.accent100]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.accent500)} 16%, transparent)`, - [FALLBACK_VAR.accent400]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.accent500)} 78%, ${widgetVar(FALLBACK_VAR.staticWhite)})`, - [FALLBACK_VAR.accent500]: WIDGET_APPEARANCE_FALLBACK_COLOR.accent500, - [FALLBACK_VAR.accent500Rgb]: '96 165 250', - [FALLBACK_VAR.accent600]: WIDGET_APPEARANCE_FALLBACK_COLOR.accent600, - [FALLBACK_VAR.bgSecondary]: WIDGET_APPEARANCE_FALLBACK_COLOR.bgSecondary, - [FALLBACK_VAR.success]: WIDGET_APPEARANCE_FALLBACK_COLOR.success, - [FALLBACK_VAR.successBg]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.success)} 16%, transparent)`, - [FALLBACK_VAR.warning]: WIDGET_APPEARANCE_FALLBACK_COLOR.warning, - [FALLBACK_VAR.warningBg]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.warning)} 16%, transparent)`, - [FALLBACK_VAR.error]: WIDGET_APPEARANCE_FALLBACK_COLOR.error, - [FALLBACK_VAR.errorBg]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.error)} 16%, transparent)`, - [FALLBACK_VAR.errorBorder]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.error)} 34%, transparent)`, - [FALLBACK_VAR.staticWhite]: WIDGET_APPEARANCE_FALLBACK_COLOR.staticWhite, - [FALLBACK_VAR.staticBlack]: WIDGET_APPEARANCE_FALLBACK_COLOR.staticBlack, - [FALLBACK_VAR.overlayWhite04]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticWhite)} 4%, transparent)`, - [FALLBACK_VAR.overlayBlack08]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticBlack)} 8%, transparent)`, - [FALLBACK_VAR.overlayBlack30]: `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticBlack)} 30%, transparent)`, - [FALLBACK_VAR.borderSubtle]: WIDGET_APPEARANCE_FALLBACK_COLOR.borderSubtle, - [FALLBACK_VAR.borderBase]: WIDGET_APPEARANCE_FALLBACK_COLOR.borderBase, - [FALLBACK_VAR.borderMedium]: WIDGET_APPEARANCE_FALLBACK_COLOR.borderMedium, - [FALLBACK_VAR.elementBgSubtle]: WIDGET_APPEARANCE_FALLBACK_COLOR.elementBgSubtle, - [FALLBACK_VAR.elementBgBase]: WIDGET_APPEARANCE_FALLBACK_COLOR.elementBgBase, - [FALLBACK_VAR.elementBgMedium]: WIDGET_APPEARANCE_FALLBACK_COLOR.elementBgMedium, - [FALLBACK_VAR.elementBgSoft]: WIDGET_APPEARANCE_FALLBACK_COLOR.elementBgBase, - [FALLBACK_VAR.elementBgHover]: WIDGET_APPEARANCE_FALLBACK_COLOR.elementBgMedium, - [FALLBACK_VAR.motionBase]: '0.2s', - [FALLBACK_VAR.shadowXs]: `0 1px 2px ${WIDGET_APPEARANCE_FALLBACK_COLOR.shadowBase}`, - [FALLBACK_VAR.shadowSm]: `0 2px 4px ${WIDGET_APPEARANCE_FALLBACK_COLOR.shadowBase}`, - [FALLBACK_VAR.sizeRadiusSm]: '6px', - [FALLBACK_VAR.sizeRadiusBase]: '8px', - [FALLBACK_VAR.sizeRadiusMd]: widgetVar(FALLBACK_VAR.sizeRadiusBase), - [FALLBACK_VAR.sizeRadiusLg]: '12px', - [FALLBACK_VAR.sizeRadiusXl]: '16px', - [FALLBACK_VAR.sizeRadius2xl]: '20px', - [FALLBACK_VAR.sizeRadiusFull]: '9999px', - [FALLBACK_VAR.sizeGap1]: '4px', - [FALLBACK_VAR.sizeGap2]: '8px', - [FALLBACK_VAR.sizeGap3]: '12px', - [FALLBACK_VAR.sizeGap4]: '16px', - [FALLBACK_VAR.sizeGap5]: '20px', - [FALLBACK_VAR.sizeGap6]: '24px', - [FALLBACK_VAR.sizeGap8]: '32px', - [FALLBACK_VAR.sizeGap10]: '40px', - [FALLBACK_VAR.sizeGap12]: '48px', - [FALLBACK_VAR.sizeGap16]: '64px', -} as const satisfies Record; +const WIDGET_SYSTEM_TOKEN_NAMES = Object.freeze(Object.keys(systemTokens) as SystemTokenName[]); +const WIDGET_SYSTEM_FALLBACK_VARS = Object.freeze(Object.fromEntries( + WIDGET_SYSTEM_TOKEN_NAMES.map(name => [systemCssVariables[name], String(systemTokens[name])]), +)); const WIDGET_TYPOGRAPHY_TOKEN_NAMES = Object.freeze( - (Object.keys(systemTokens) as SystemTokenName[]).filter(name => ( + WIDGET_SYSTEM_TOKEN_NAMES.filter(name => ( name.startsWith('font.') || name.startsWith('lineHeight.') || name.startsWith('letterSpacing.') @@ -169,112 +49,31 @@ export const WIDGET_TYPOGRAPHY_VARIABLE_NAMES = Object.freeze( WIDGET_TYPOGRAPHY_TOKEN_NAMES.map(name => systemCssVariables[name]), ); -const WIDGET_TYPOGRAPHY_FALLBACK_VARS = Object.freeze(Object.fromEntries( - WIDGET_TYPOGRAPHY_TOKEN_NAMES.map(name => [ - systemCssVariables[name], - String(systemTokens[name]), - ]), -)); - export function createWidgetAppearanceFallbackCss(): string { return Object.entries({ + ...WIDGET_SYSTEM_FALLBACK_VARS, ...WIDGET_APPEARANCE_FALLBACK_VARS, - ...WIDGET_TYPOGRAPHY_FALLBACK_VARS, }) .map(([name, value]) => ` ${name}: ${value};`) .join('\n'); } -const WIDGET_APPEARANCE_STATIC_SHELL_VARS = { - '--bf-appearance-token-color-bg-quaternary': widgetVar(FALLBACK_VAR.bgSecondary), - '--bf-appearance-token-color-bg-workbench': widgetVar(FALLBACK_VAR.bgPrimary), - '--bf-appearance-token-color-bg-tooltip': widgetVar(FALLBACK_VAR.bgElevated), - '--bf-appearance-token-color-overlay-white-08': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticWhite)} 8%, transparent)`, - '--bf-appearance-token-color-overlay-white-12': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticWhite)} 12%, transparent)`, - '--bf-appearance-token-color-overlay-white-15': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticWhite)} 15%, transparent)`, - '--bf-appearance-token-color-overlay-white-20': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticWhite)} 20%, transparent)`, - '--bf-appearance-token-color-overlay-white-60': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticWhite)} 60%, transparent)`, - '--bf-appearance-token-color-overlay-black-12': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticBlack)} 12%, transparent)`, - '--bf-appearance-token-color-overlay-black-15': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticBlack)} 15%, transparent)`, - '--bf-appearance-token-color-overlay-black-20': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticBlack)} 20%, transparent)`, - '--bf-appearance-token-color-overlay-black-40': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticBlack)} 40%, transparent)`, - '--bf-appearance-token-color-overlay-black-50': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticBlack)} 50%, transparent)`, - '--bf-appearance-token-color-overlay-black-80': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.staticBlack)} 80%, transparent)`, - '--bf-appearance-token-color-accent-200': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.accent500)} 24%, transparent)`, - '--bf-appearance-token-color-accent-300': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.accent500)} 34%, transparent)`, - '--bf-appearance-token-color-accent-700': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.accent600)} 86%, ${widgetVar(FALLBACK_VAR.staticBlack)})`, - '--bf-appearance-token-color-accent-800': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.accent600)} 92%, ${widgetVar(FALLBACK_VAR.staticBlack)})`, - '--bf-appearance-token-color-success-border': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.success)} 34%, transparent)`, - '--bf-appearance-token-color-warning-border': `color-mix(in srgb, ${widgetVar(FALLBACK_VAR.warning)} 34%, transparent)`, - '--bf-appearance-token-color-info': widgetVar(FALLBACK_VAR.textMuted), - '--bf-appearance-token-color-info-bg': widgetVar(FALLBACK_VAR.elementBgSubtle), - '--bf-appearance-token-color-info-border': widgetVar(FALLBACK_VAR.borderMedium), - '--bf-appearance-token-border-strong': widgetVar(FALLBACK_VAR.borderMedium), - '--bf-appearance-token-border-prominent': widgetVar(FALLBACK_VAR.borderMedium), - '--bf-appearance-token-element-bg-strong': widgetVar(FALLBACK_VAR.elementBgMedium), - '--bf-appearance-token-scrollbar-thumb': widgetVar(FALLBACK_VAR.elementBgMedium), - '--bf-appearance-token-scrollbar-thumb-hover': widgetVar('--bf-appearance-token-element-bg-strong'), - '--bf-appearance-token-glass-bg-base': widgetVar(FALLBACK_VAR.elementBgBase), - '--bf-appearance-token-glass-bg-hover': widgetVar(FALLBACK_VAR.elementBgMedium), - '--bf-appearance-token-glass-bg-active': widgetVar('--bf-appearance-token-element-bg-strong'), - '--bf-appearance-token-glass-border-base': widgetVar(FALLBACK_VAR.borderBase), - '--bf-appearance-token-glass-border-hover': widgetVar(FALLBACK_VAR.borderMedium), - '--bf-appearance-token-shadow-base': `0 4px 8px ${widgetVar(FALLBACK_VAR.overlayBlack30)}`, - '--bf-appearance-token-shadow-lg': `0 8px 16px ${widgetVar(FALLBACK_VAR.overlayBlack30)}`, - '--bf-appearance-token-shadow-xl': `0 12px 24px ${widgetVar(FALLBACK_VAR.overlayBlack30)}`, - '--bf-appearance-token-opacity-disabled': '0.6', - '--bf-appearance-token-opacity-hover': '0.8', - '--bf-appearance-token-opacity-focus': '0.9', - '--bf-appearance-token-motion-slow': '0.6s', - '--bf-appearance-token-btn-primary-bg': widgetVar(FALLBACK_VAR.accent100), - '--bf-appearance-token-btn-primary-color': widgetVar(FALLBACK_VAR.accent600), - '--bf-appearance-token-btn-primary-border': 'transparent', - '--bf-appearance-token-btn-primary-shadow': 'none', - '--bf-appearance-token-btn-primary-hover-bg': widgetVar(FALLBACK_VAR.accent400), - '--bf-appearance-token-btn-primary-hover-color': widgetVar(FALLBACK_VAR.textPrimary), - '--bf-appearance-token-btn-primary-hover-border': 'transparent', - '--bf-appearance-token-btn-primary-hover-shadow': 'none', - '--bf-appearance-token-btn-primary-hover-transform': 'none', - '--bf-appearance-token-btn-primary-active-bg': widgetVar(FALLBACK_VAR.accent100), - '--bf-appearance-token-btn-primary-active-color': widgetVar(FALLBACK_VAR.textPrimary), - '--bf-appearance-token-btn-primary-active-border': 'transparent', - '--bf-appearance-token-btn-primary-active-shadow': 'none', - '--bf-appearance-token-btn-primary-active-transform': 'none', - '--bf-appearance-token-btn-ghost-color': widgetVar(FALLBACK_VAR.textMuted), - '--bf-appearance-token-btn-ghost-hover-bg': widgetVar(FALLBACK_VAR.elementBgSubtle), - '--bf-appearance-token-btn-ghost-hover-color': widgetVar(FALLBACK_VAR.textPrimary), - '--bf-appearance-token-btn-ghost-hover-border': 'transparent', - '--bf-appearance-token-tool-card-header-pad-y': '0.44rem', - '--bf-appearance-token-tool-card-header-pad-right': '0.625rem', - '--bf-appearance-token-tool-card-header-icon-slot': '34px', - '--bf-appearance-token-tool-card-expanded-pad-x': '0.625rem', -} as const; - -export const WIDGET_APPEARANCE_STATIC_SHELL_VAR_NAMES = Object.keys(WIDGET_APPEARANCE_STATIC_SHELL_VARS); - -export function createWidgetAppearanceStaticShellCss(): string { - return Object.entries(WIDGET_APPEARANCE_STATIC_SHELL_VARS) - .map(([name, value]) => ` ${name}: ${value};`) - .join('\n'); -} - export const WIDGET_APPEARANCE_VAR_NAMES = WIDGET_APPEARANCE_VARIABLE_NAMES; export function readWidgetAppearancePayload(): WidgetAppearancePayload | null { const settings = widgetAppearanceAdapter.getSettings(); const vars: Record = {}; for (const name of WIDGET_APPEARANCE_VAR_NAMES) { - const value = settings.vars[name] - ?? WIDGET_APPEARANCE_FALLBACK_VARS[name as keyof typeof WIDGET_APPEARANCE_FALLBACK_VARS]; + const value = settings.vars[name] ?? WIDGET_APPEARANCE_FALLBACK_VARS[name]; if (value) vars[name] = value; } + const computedStyle = typeof document !== 'undefined' && typeof getComputedStyle === 'function' ? getComputedStyle(document.documentElement) : null; for (const name of WIDGET_TYPOGRAPHY_VARIABLE_NAMES) { - const value = computedStyle?.getPropertyValue(name).trim() - || WIDGET_TYPOGRAPHY_FALLBACK_VARS[name]; - vars[name] = value; + vars[name] = computedStyle?.getPropertyValue(name).trim() + || WIDGET_SYSTEM_FALLBACK_VARS[name]; } return { diff --git a/src/web-ui/src/tools/git/components/BranchQuickSwitch.scss b/src/web-ui/src/tools/git/components/BranchQuickSwitch.scss index 69250c26bb..282bcc769f 100644 --- a/src/web-ui/src/tools/git/components/BranchQuickSwitch.scss +++ b/src/web-ui/src/tools/git/components/BranchQuickSwitch.scss @@ -11,14 +11,14 @@ box-sizing: border-box; width: min(280px, calc(100vw - 16px)); overflow: hidden; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-family:var(--bf-font-family-sans); user-select: none; } .branch-quick-switch__search { padding: 8px; - border-bottom: 1px solid var(--bf-appearance-token-border-subtle); + border-bottom: 1px solid var(--bf-color-border-subtle); } .branch-quick-switch__input-field { @@ -28,11 +28,11 @@ .branch-quick-switch__input { width: 100%; padding: 6px 10px; - border: 1px solid var(--bf-appearance-token-border-subtle); + border: 1px solid var(--bf-color-border-subtle); border-radius: 4px; outline: none !important; - background: var(--bf-appearance-token-color-bg-secondary); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-panel); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-xs); transition: border-color 120ms ease, @@ -40,13 +40,13 @@ &:focus, &:focus-visible { - border-color: var(--bf-appearance-token-color-accent-500); + border-color: var(--bf-color-accent-default); outline: none !important; box-shadow: none !important; } &::placeholder { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } } @@ -62,7 +62,7 @@ justify-content: center; gap: 8px; padding: 20px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); text-align: center; } @@ -100,7 +100,7 @@ gap: 8px; overflow-y: auto; padding: 2px 0; - scrollbar-color: var(--bf-appearance-token-scrollbar-thumb) transparent; + scrollbar-color: var(--bf-color-scrollbar-thumb) transparent; scrollbar-width: thin; } @@ -109,7 +109,7 @@ align-items: baseline; gap: 10px; min-width: 0; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } .branch-switch-conflict-dialog__file-path { @@ -131,12 +131,12 @@ } .branch-switch-conflict-dialog__additions { - color: var(--bf-appearance-token-color-success); + color: var(--bf-color-status-success-content); } .branch-switch-conflict-dialog__deletions, .branch-switch-commit-dialog__error { - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); } .branch-switch-commit-dialog { @@ -151,7 +151,7 @@ p { margin: 0; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-base); } @@ -161,7 +161,7 @@ } .branch-switch-commit-dialog__error { - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); } } diff --git a/src/web-ui/src/tools/git/components/CreateBranchDialog/CreateBranchDialog.scss b/src/web-ui/src/tools/git/components/CreateBranchDialog/CreateBranchDialog.scss index c54dd57e7c..e5fe0c9e46 100644 --- a/src/web-ui/src/tools/git/components/CreateBranchDialog/CreateBranchDialog.scss +++ b/src/web-ui/src/tools/git/components/CreateBranchDialog/CreateBranchDialog.scss @@ -17,13 +17,13 @@ margin-bottom: $size-gap-4; gap: $size-gap-3; padding-bottom: $size-gap-3; - border-bottom: 1px solid var(--bf-appearance-token-border-base); + border-bottom: 1px solid var(--bf-color-border-default); } &__title { font-size: var(--bf-font-size-lg); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } &__close-btn { @@ -36,7 +36,7 @@ background: transparent; border: none; border-radius: $size-radius-sm; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); cursor: pointer; transition: transform $motion-fast $easing-standard, @@ -44,8 +44,8 @@ color $motion-fast $easing-standard; &:hover:not(:disabled) { - background: var(--bf-appearance-token-element-bg-base); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface); + color: var(--bf-color-content-primary); } &:disabled { @@ -60,8 +60,8 @@ justify-content: space-between; padding: $size-gap-3; margin-bottom: $size-gap-4; - background: var(--bf-appearance-token-element-bg-subtle); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-subtle); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-sm; } @@ -70,22 +70,22 @@ align-items: center; gap: $size-gap-2; font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-weight: var(--bf-font-weight-medium); svg { - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); } } &__base-value { font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-medium); padding: 2px 8px; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-sm; } @@ -104,23 +104,23 @@ &__label { font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); display: flex; align-items: center; gap: $size-gap-1; } &__required { - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); } &__input { width: 100%; padding: $size-gap-2 $size-gap-3; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-sm; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-sm); transition: @@ -131,13 +131,13 @@ &:focus { outline: none; - border-color: var(--bf-appearance-token-color-accent-500); - background: var(--bf-appearance-token-element-bg-base); - box-shadow: 0 0 0 2px var(--bf-appearance-token-color-accent-200); + border-color: var(--bf-color-accent-default); + background: var(--bf-color-action-neutral-surface); + box-shadow: 0 0 0 2px var(--bf-color-action-secondary-hover); } &::placeholder { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-family: var(--bf-font-family-sans); } @@ -147,11 +147,11 @@ } &--error { - border-color: color-mix(in srgb, var(--bf-appearance-token-color-error) 50%, transparent); + border-color: color-mix(in srgb, var(--bf-color-status-danger-content) 50%, transparent); &:focus { - border-color: color-mix(in srgb, var(--bf-appearance-token-color-error) 80%, transparent); - box-shadow: 0 0 0 2px var(--bf-appearance-token-glass-red-hover); + border-color: color-mix(in srgb, var(--bf-color-status-danger-content) 80%, transparent); + box-shadow: 0 0 0 2px color-mix(in srgb, var(--bf-color-status-danger-content) 15%, transparent); } } } @@ -161,17 +161,17 @@ align-items: center; gap: $size-gap-2; padding: $size-gap-2 $size-gap-3; - background: var(--bf-appearance-token-glass-red-base); - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-error) 25%, transparent); + background: var(--bf-color-status-danger-surface); + border: 1px solid color-mix(in srgb, var(--bf-color-status-danger-content) 25%, transparent); border-radius: $size-radius-sm; - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); font-size: var(--bf-font-size-xs); animation: bitfun-create-branch-dialog-shake 0.4s ease-in-out; } &__hint { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); line-height: var(--bf-line-height-relaxed); div { @@ -192,7 +192,7 @@ content: '•'; position: absolute; left: -12px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } } } @@ -200,12 +200,12 @@ code { display: inline-block; padding: 1px 4px; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-sm; font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-micro); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } } @@ -214,21 +214,21 @@ gap: $size-gap-2; margin-top: $size-gap-4; padding-top: $size-gap-4; - border-top: 1px solid var(--bf-appearance-token-border-base); + border-top: 1px solid var(--bf-color-border-default); justify-content: flex-end; } &__shortcuts { margin-top: $size-gap-2; font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); text-align: center; span { display: inline-block; padding: 2px 6px; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-sm; font-family: var(--bf-font-family-mono); margin: 0 4px; diff --git a/src/web-ui/src/tools/git/components/GitBranchHistoryView/GitBranchHistoryView.scss b/src/web-ui/src/tools/git/components/GitBranchHistoryView/GitBranchHistoryView.scss index 3e30348f06..bf0998c415 100644 --- a/src/web-ui/src/tools/git/components/GitBranchHistoryView/GitBranchHistoryView.scss +++ b/src/web-ui/src/tools/git/components/GitBranchHistoryView/GitBranchHistoryView.scss @@ -3,8 +3,8 @@ flex-direction: column; height: 100%; width: 100%; - background: var(--bf-appearance-token-color-bg-primary); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-canvas); + color: var(--bf-color-content-primary); &--loading, &--error { @@ -26,7 +26,7 @@ p { margin: 0; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-base); text-align: center; } @@ -36,8 +36,8 @@ &__spinner { width: 36px; height: 36px; - border: 3px solid var(--bf-appearance-token-border-base); - border-top-color: var(--bf-appearance-token-color-accent-500); + border: 3px solid var(--bf-color-border-default); + border-top-color: var(--bf-color-accent-default); border-radius: 50%; animation: git-branch-history-spin 0.8s linear infinite; } @@ -47,8 +47,8 @@ align-items: center; justify-content: space-between; padding: 10px 12px; - border-bottom: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-color-bg-secondary); + border-bottom: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-panel); flex-shrink: 0; gap: 12px; } @@ -79,7 +79,7 @@ flex-shrink: 0; &:hover { - background: var(--bf-appearance-token-element-bg-hover); + background: var(--bf-color-action-neutral-surface-hover); } } @@ -110,17 +110,17 @@ &--expanded { .git-branch-history-view__commit-main { - background: var(--bf-appearance-token-color-bg-secondary); + background: var(--bf-color-surface-panel); } } &--selected { .git-branch-history-view__commit-main { - background: var(--bf-appearance-token-color-accent-100); + background: var(--bf-color-action-secondary-background); } &:hover .git-branch-history-view__commit-main { - background: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 12%, transparent); + background: color-mix(in srgb, var(--bf-color-accent-default) 12%, transparent); } } @@ -140,14 +140,14 @@ transition: background 0.15s ease; &:hover { - background: var(--bf-appearance-token-element-bg-base); + background: var(--bf-color-action-neutral-surface); .git-branch-history-view__expand-btn { opacity: 1; } .git-branch-history-view__commit-checkbox .git-branch-history-view__checkbox { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } } } @@ -164,17 +164,17 @@ transition: background 0.15s ease; &:hover { - background: var(--bf-appearance-token-element-bg-hover); + background: var(--bf-color-action-neutral-surface-hover); } } &__checkbox { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); transition: color 0.15s ease; } &__checkbox--checked { - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); } &__checkbox--partial { @@ -182,14 +182,14 @@ display: flex; align-items: center; justify-content: center; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } &__checkbox-partial-mark { position: absolute; width: 8px; height: 2px; - background: var(--bf-appearance-token-color-accent-500); + background: var(--bf-color-accent-default); border-radius: 1px; } @@ -209,8 +209,8 @@ width: 24px; height: 24px; border-radius: 50%; - background: var(--bf-appearance-token-color-accent-200); - color: var(--bf-appearance-token-color-accent-500); + background: var(--bf-color-action-secondary-hover); + color: var(--bf-color-accent-default); flex-shrink: 0; font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-semibold); @@ -222,7 +222,7 @@ width: 2px; flex: 1; min-height: 16px; - background: var(--bf-appearance-token-border-base); + background: var(--bf-color-border-default); margin-top: 4px; } @@ -238,7 +238,7 @@ &__commit-message { font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-regular); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); line-height: var(--bf-line-height-ui); overflow: hidden; text-overflow: ellipsis; @@ -250,7 +250,7 @@ align-items: center; gap: 8px; font-size: var(--bf-font-size-meta); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } &__commit-author { @@ -270,7 +270,7 @@ gap: 3px; font-family: var(--bf-font-family-mono); padding: 1px 4px; - background: var(--bf-appearance-token-color-bg-tertiary); + background: var(--bf-color-surface-tertiary); border-radius: 3px; cursor: pointer; transition: @@ -280,13 +280,13 @@ font-size: var(--bf-font-size-micro); &:hover { - background: var(--bf-appearance-token-element-bg-hover); - color: var(--bf-appearance-token-color-text-secondary); + background: var(--bf-color-action-neutral-surface-hover); + color: var(--bf-color-content-secondary); } &--copied { - background: color-mix(in srgb, var(--bf-appearance-token-color-success) 15%, transparent); - color: var(--bf-appearance-token-color-success); + background: color-mix(in srgb, var(--bf-color-status-success-content) 15%, transparent); + color: var(--bf-color-status-success-content); .git-branch-history-view__copy-icon { opacity: 1; @@ -312,7 +312,7 @@ padding: 0; background: transparent; border: none; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); cursor: pointer; border-radius: 4px; transition: @@ -324,15 +324,15 @@ opacity: 0; &:hover { - color: var(--bf-appearance-token-color-text-primary); - background: var(--bf-appearance-token-color-bg-tertiary); + color: var(--bf-color-content-primary); + background: var(--bf-color-surface-tertiary); } } &__commit-details { margin-left: 36px; padding: 10px 12px; - background: var(--bf-appearance-token-color-bg-secondary); + background: var(--bf-color-surface-panel); border-radius: 6px; margin-bottom: 4px; } @@ -350,20 +350,20 @@ } &__detail-label { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); min-width: 60px; flex-shrink: 0; } &__detail-value { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); word-break: break-all; line-height: var(--bf-line-height-ui); &--mono { font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-micro); - background: var(--bf-appearance-token-color-bg-tertiary); + background: var(--bf-color-surface-tertiary); padding: 2px 6px; border-radius: 3px; } diff --git a/src/web-ui/src/tools/git/components/GitDiffEditor/GitDiffEditor.scss b/src/web-ui/src/tools/git/components/GitDiffEditor/GitDiffEditor.scss index 43f22646fd..b3b2c5c225 100644 --- a/src/web-ui/src/tools/git/components/GitDiffEditor/GitDiffEditor.scss +++ b/src/web-ui/src/tools/git/components/GitDiffEditor/GitDiffEditor.scss @@ -11,7 +11,7 @@ $_diff-padding-desktop: 32px; flex-direction: column; height: 100%; width: 100%; - background: var(--bf-appearance-token-color-bg-primary); + background: var(--bf-color-surface-canvas); overflow: hidden; position: relative; @@ -20,11 +20,11 @@ $_diff-padding-desktop: 32px; align-items: center; gap: $size-gap-2; padding: $size-gap-3 $size-gap-4; - background: var(--bf-appearance-token-color-bg-primary); - border: 1px solid var(--bf-appearance-token-color-error-border); + background: var(--bf-color-surface-canvas); + border: 1px solid var(--bf-color-status-danger-border); border-radius: 0; - border-bottom: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-error) 50%, transparent); - color: var(--bf-appearance-token-color-error); + border-bottom: 1px solid color-mix(in srgb, var(--bf-color-status-danger-content) 50%, transparent); + color: var(--bf-color-status-danger-content); font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-medium); font-family: var(--bf-font-family-mono); @@ -32,7 +32,7 @@ $_diff-padding-desktop: 32px; svg { flex-shrink: 0; - filter: drop-shadow(0 0 8px color-mix(in srgb, var(--bf-appearance-token-color-error) 40%, transparent)); + filter: drop-shadow(0 0 8px color-mix(in srgb, var(--bf-color-status-danger-content) 40%, transparent)); } } @@ -47,12 +47,12 @@ $_diff-padding-desktop: 32px; border-radius: 6px; box-shadow: - inset 0 1px 3px var(--bf-appearance-token-color-overlay-black-20), - 0 0 0 1px var(--bf-appearance-token-color-overlay-white-04); + inset 0 1px 3px color-mix(in srgb, var(--bf-color-content-on-light) 20%, transparent), + 0 0 0 1px color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent); background: linear-gradient( 180deg, - color-mix(in srgb, var(--bf-appearance-token-color-static-white) 1%, transparent) 0%, + color-mix(in srgb, var(--bf-color-content-on-dark) 1%, transparent) 0%, transparent 100% ); @@ -83,10 +83,10 @@ $_diff-padding-desktop: 32px; outline: none !important; border: none !important; box-shadow: none !important; - color: var(--bf-appearance-token-color-text-muted) !important; + color: var(--bf-color-content-muted) !important; &:hover { - color: var(--bf-appearance-token-color-text-secondary) !important; + color: var(--bf-color-content-secondary) !important; background: transparent !important; } @@ -166,19 +166,19 @@ $_diff-padding-desktop: 32px; bottom: 0; left: 50%; width: 1px; - background: var(--bf-appearance-token-border-medium); - border-left: 1px dashed var(--bf-appearance-token-border-medium); + background: var(--bf-color-field-border-hover); + border-left: 1px dashed var(--bf-color-field-border-hover); transition: border-left-color 0.2s ease; } &:hover::before { border-left-style: solid; - border-left-color: var(--bf-appearance-token-color-overlay-white-20); + border-left-color: color-mix(in srgb, var(--bf-color-content-on-dark) 20%, transparent); } } .monaco-diff-editor.side-by-side .editor.original { - border-right: 1px dashed var(--bf-appearance-token-border-medium) !important; + border-right: 1px dashed var(--bf-color-field-border-hover) !important; &:hover { border-right-style: solid !important; @@ -186,7 +186,7 @@ $_diff-padding-desktop: 32px; } .monaco-diff-editor.side-by-side .editor.modified { - border-left: 1px dashed var(--bf-appearance-token-border-medium) !important; + border-left: 1px dashed var(--bf-color-field-border-hover) !important; &:hover { border-left-style: solid !important; @@ -194,17 +194,17 @@ $_diff-padding-desktop: 32px; } .monaco-diff-editor .diffViewport { - background: var(--bf-appearance-token-color-overlay-white-04) !important; + background: color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent) !important; } .monaco-diff-editor .diagonal-fill { - background-color: var(--bf-appearance-token-color-bg-secondary) !important; + background-color: var(--bf-color-surface-panel) !important; background-image: repeating-linear-gradient( 45deg, transparent, transparent 3px, - color-mix(in srgb, var(--bf-appearance-token-color-static-white) 1.5%, transparent) 3px, - color-mix(in srgb, var(--bf-appearance-token-color-static-white) 1.5%, transparent) 6px + color-mix(in srgb, var(--bf-color-content-on-dark) 1.5%, transparent) 3px, + color-mix(in srgb, var(--bf-color-content-on-dark) 1.5%, transparent) 6px ) !important; } } @@ -215,16 +215,16 @@ $_diff-padding-desktop: 32px; top: $size-gap-3; right: $size-gap-3; padding: $size-gap-2 $size-gap-4; - background: var(--bf-appearance-token-color-overlay-black-80); - border: 1px solid var(--bf-appearance-token-color-overlay-white-12); + background: color-mix(in srgb, var(--bf-color-content-on-light) 80%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-content-on-dark) 12%, transparent); border-radius: $size-radius-base; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); font-family: var(--bf-font-family-mono); z-index: $z-overlay; animation: git-diff-editor-fade-in 0.2s ease-out; backdrop-filter: blur(4px); - box-shadow: 0 2px 8px var(--bf-appearance-token-color-overlay-black-30); + box-shadow: 0 2px 8px color-mix(in srgb, var(--bf-color-content-on-light) 30%, transparent); } &__processing-overlay { @@ -233,7 +233,7 @@ $_diff-padding-desktop: 32px; left: 0; right: 0; bottom: 0; - background: var(--bf-appearance-token-color-overlay-black-80); + background: color-mix(in srgb, var(--bf-color-content-on-light) 80%, transparent); backdrop-filter: blur(8px); display: flex; flex-direction: column; @@ -247,7 +247,7 @@ $_diff-padding-desktop: 32px; font-size: var(--bf-font-size-base); font-weight: var(--bf-font-weight-medium); font-family: var(--bf-font-family-mono); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); animation: git-diff-editor-pulse $motion-slow ease-in-out infinite; } } @@ -255,13 +255,13 @@ $_diff-padding-desktop: 32px; &__spinner { width: $_diff-spinner-size; height: $_diff-spinner-size; - border: $_diff-spinner-border solid var(--bf-appearance-token-color-accent-200); - border-top-color: var(--bf-appearance-token-color-accent-500); + border: $_diff-spinner-border solid var(--bf-color-action-secondary-hover); + border-top-color: var(--bf-color-accent-default); border-radius: $size-radius-full; animation: git-diff-editor-spin $motion-lazy $easing-standard infinite; box-shadow: - 0 0 20px color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 30%, transparent), - 0 0 40px var(--bf-appearance-token-color-accent-200); + 0 0 20px color-mix(in srgb, var(--bf-color-accent-default) 30%, transparent), + 0 0 40px var(--bf-color-action-secondary-hover); } &__completed-message { @@ -284,32 +284,32 @@ $_diff-padding-desktop: 32px; border-radius: $size-radius-full; margin-bottom: $size-gap-6; animation: git-diff-editor-scale-bounce 0.5s $easing-standard; - box-shadow: 0 8px 24px var(--bf-appearance-token-color-overlay-black-30); + box-shadow: 0 8px 24px color-mix(in srgb, var(--bf-color-content-on-light) 30%, transparent); &--accepted { background: linear-gradient(135deg, - color-mix(in srgb, var(--bf-appearance-token-color-success) 85%, var(--bf-appearance-token-color-static-white)) 0%, - var(--bf-appearance-token-color-success) 100% + color-mix(in srgb, var(--bf-color-status-success-content) 85%, var(--bf-color-content-on-dark)) 0%, + var(--bf-color-status-success-content) 100% ); - color: var(--bf-appearance-token-color-static-white); + color: var(--bf-color-content-on-dark); box-shadow: - 0 8px 24px color-mix(in srgb, var(--bf-appearance-token-git-color-staged) 40%, transparent), - 0 0 40px color-mix(in srgb, var(--bf-appearance-token-git-color-staged) 20%, transparent); + 0 8px 24px color-mix(in srgb, var(--bf-domain-git-staged) 40%, transparent), + 0 0 40px color-mix(in srgb, var(--bf-domain-git-staged) 20%, transparent); } &--rejected { background: linear-gradient(135deg, - color-mix(in srgb, var(--bf-appearance-token-color-error) 85%, var(--bf-appearance-token-color-static-white)) 0%, - var(--bf-appearance-token-color-error) 100% + color-mix(in srgb, var(--bf-color-status-danger-content) 85%, var(--bf-color-content-on-dark)) 0%, + var(--bf-color-status-danger-content) 100% ); - color: var(--bf-appearance-token-color-static-white); + color: var(--bf-color-content-on-dark); box-shadow: - 0 8px 24px color-mix(in srgb, var(--bf-appearance-token-color-error) 40%, transparent), - 0 0 40px color-mix(in srgb, var(--bf-appearance-token-color-error) 20%, transparent); + 0 8px 24px color-mix(in srgb, var(--bf-color-status-danger-content) 40%, transparent), + 0 0 40px color-mix(in srgb, var(--bf-color-status-danger-content) 20%, transparent); } svg { - filter: drop-shadow(0 2px 8px var(--bf-appearance-token-color-overlay-black-30)); + filter: drop-shadow(0 2px 8px color-mix(in srgb, var(--bf-color-content-on-light) 30%, transparent)); } } @@ -317,7 +317,7 @@ $_diff-padding-desktop: 32px; font-size: var(--bf-font-size-2xl); font-weight: var(--bf-font-weight-semibold); font-family: var(--bf-font-family-mono); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); margin-bottom: $size-gap-4; animation: git-diff-editor-slide-up 220ms cubic-bezier(0.23, 1, 0.32, 1) 40ms both; } @@ -331,7 +331,7 @@ $_diff-padding-desktop: 32px; .git-diff-editor__file-path { font-size: var(--bf-font-size-base); font-family: var(--bf-font-family-mono); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } } @@ -342,11 +342,11 @@ $_diff-padding-desktop: 32px; margin-top: $size-gap-3; &--success { - color: var(--bf-appearance-token-color-success); + color: var(--bf-color-status-success-content); } &--warning { - color: var(--bf-appearance-token-color-warning); + color: var(--bf-color-status-warning-content); } } } @@ -467,8 +467,8 @@ $_diff-padding-desktop: 32px; @media (prefers-contrast: high) { .git-diff-editor { &__spinner { - border-color: var(--bf-appearance-token-color-text-muted); - border-top-color: var(--bf-appearance-token-color-text-primary); + border-color: var(--bf-color-content-muted); + border-top-color: var(--bf-color-content-primary); } &__completed-icon { diff --git a/src/web-ui/src/tools/git/components/GitDiffView/GitDiffView.scss b/src/web-ui/src/tools/git/components/GitDiffView/GitDiffView.scss index f467d4c916..7b2951fe1b 100644 --- a/src/web-ui/src/tools/git/components/GitDiffView/GitDiffView.scss +++ b/src/web-ui/src/tools/git/components/GitDiffView/GitDiffView.scss @@ -11,8 +11,8 @@ $opacity-high: 0.8 !default; flex-direction: column; height: 100%; flex: 1; - background: var(--bf-appearance-token-color-bg-primary); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-canvas); + color: var(--bf-color-content-primary); font-family: var(--bf-font-family-sans); &__header { @@ -20,8 +20,8 @@ $opacity-high: 0.8 !default; align-items: center; justify-content: space-between; padding: $size-gap-3 $size-gap-4; - border-bottom: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-color-bg-primary); + border-bottom: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-canvas); flex-shrink: 0; } @@ -40,12 +40,12 @@ $opacity-high: 0.8 !default; &__commit-range, &__diff-type { padding: 2px $size-gap-1-5; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-xs; font-size: var(--bf-font-size-meta); font-family: var(--bf-font-family-mono); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } &__loading-indicator { @@ -53,7 +53,7 @@ $opacity-high: 0.8 !default; align-items: center; gap: $size-gap-1-5; font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } &__commit-controls { @@ -73,10 +73,10 @@ $opacity-high: 0.8 !default; align-items: center; gap: $size-gap-1; padding: $size-gap-1-5 $size-gap-2; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-sm; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); cursor: pointer; transition: @@ -86,14 +86,14 @@ $opacity-high: 0.8 !default; color $motion-fast $easing-standard; &:hover { - background: var(--bf-appearance-token-element-bg-medium); - border-color: var(--bf-appearance-token-border-medium); + background: var(--bf-color-action-neutral-surface-hover); + border-color: var(--bf-color-field-border-hover); } &--active { - background: var(--bf-appearance-token-color-accent-100); - border-color: var(--bf-appearance-token-color-accent-500); - color: var(--bf-appearance-token-color-accent-500); + background: var(--bf-color-action-secondary-background); + border-color: var(--bf-color-accent-default); + color: var(--bf-color-accent-default); } } @@ -114,7 +114,7 @@ $opacity-high: 0.8 !default; height: 100%; padding: $size-gap-10; text-align: center; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); svg { margin-bottom: $size-gap-4; @@ -125,7 +125,7 @@ $opacity-high: 0.8 !default; font-size: var(--bf-font-size-lg); font-weight: var(--bf-font-weight-medium); margin-bottom: $size-gap-2; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } p { @@ -137,8 +137,8 @@ $opacity-high: 0.8 !default; &__loading-spinner { width: 32px; height: 32px; - border: 3px solid var(--bf-appearance-token-border-base); - border-top-color: var(--bf-appearance-token-color-accent-500); + border: 3px solid var(--bf-color-border-default); + border-top-color: var(--bf-color-accent-default); border-radius: $size-radius-full; animation: bitfun-git-diff-view-spin 1s linear infinite; margin-bottom: $size-gap-4; @@ -151,7 +151,7 @@ $opacity-high: 0.8 !default; } &__file-item { - background: var(--bf-appearance-token-color-bg-primary); + background: var(--bf-color-surface-canvas); border-radius: $size-radius-base; overflow: hidden; transition: @@ -164,13 +164,13 @@ $opacity-high: 0.8 !default; align-items: center; justify-content: space-between; padding: $size-gap-2 $size-gap-3; - background: var(--bf-appearance-token-element-bg-subtle); + background: var(--bf-color-surface-subtle); cursor: pointer; user-select: none; transition: background-color $motion-fast $easing-standard; &:hover { - background: var(--bf-appearance-token-element-bg-base); + background: var(--bf-color-action-neutral-surface); } } @@ -185,7 +185,7 @@ $opacity-high: 0.8 !default; &__file-path { font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-regular); white-space: nowrap; overflow: hidden; @@ -194,7 +194,7 @@ $opacity-high: 0.8 !default; &__file-status-icon { flex-shrink: 0; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); display: flex; align-items: center; } @@ -205,26 +205,26 @@ $opacity-high: 0.8 !default; font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-medium); font-family: var(--bf-font-family-mono); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); &--added { - background: color-mix(in srgb, var(--bf-appearance-token-git-color-added) 10%, transparent); - color: var(--bf-appearance-token-git-color-added); + background: color-mix(in srgb, var(--bf-domain-git-added) 10%, transparent); + color: var(--bf-domain-git-added); } &--modified { - background: color-mix(in srgb, var(--bf-appearance-token-git-color-changes) 10%, transparent); - color: var(--bf-appearance-token-git-color-changes); + background: color-mix(in srgb, var(--bf-domain-git-changes) 10%, transparent); + color: var(--bf-domain-git-changes); } &--deleted { - background: color-mix(in srgb, var(--bf-appearance-token-git-color-deleted) 10%, transparent); - color: var(--bf-appearance-token-git-color-deleted); + background: color-mix(in srgb, var(--bf-domain-git-deleted) 10%, transparent); + color: var(--bf-domain-git-deleted); } &--renamed { - background: var(--bf-appearance-token-git-color-branch-bg); - color: var(--bf-appearance-token-git-color-branch); + background: var(--bf-domain-git-branch-background); + color: var(--bf-domain-git-branch); } } @@ -239,21 +239,21 @@ $opacity-high: 0.8 !default; } &__additions { - color: var(--bf-appearance-token-git-color-added); + color: var(--bf-domain-git-added); display: flex; align-items: center; gap: 4px; } &__deletions { - color: var(--bf-appearance-token-git-color-deleted); + color: var(--bf-domain-git-deleted); display: flex; align-items: center; gap: 4px; } &__expand-icon { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); display: flex; align-items: center; flex-shrink: 0; @@ -262,12 +262,12 @@ $opacity-high: 0.8 !default; &__diff-content { padding: 0; - background: var(--bf-appearance-token-color-bg-primary); + background: var(--bf-color-surface-canvas); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-xs); line-height: var(--bf-line-height-relaxed); overflow-x: auto; - border-top: 1px solid var(--bf-appearance-token-border-base); + border-top: 1px solid var(--bf-color-border-default); } @@ -277,42 +277,42 @@ $opacity-high: 0.8 !default; transition: background $motion-fast $easing-standard; &--added { - background: color-mix(in srgb, var(--bf-appearance-token-git-color-added) 10%, transparent); + background: color-mix(in srgb, var(--bf-domain-git-added) 10%, transparent); &:hover { - background: color-mix(in srgb, var(--bf-appearance-token-git-color-added) 15%, transparent); + background: color-mix(in srgb, var(--bf-domain-git-added) 15%, transparent); } .bitfun-git-diff-view__line-content { - color: var(--bf-appearance-token-git-color-added); + color: var(--bf-domain-git-added); } } &--deleted { - background: color-mix(in srgb, var(--bf-appearance-token-git-color-deleted) 10%, transparent); + background: color-mix(in srgb, var(--bf-domain-git-deleted) 10%, transparent); &:hover { - background: color-mix(in srgb, var(--bf-appearance-token-git-color-deleted) 15%, transparent); + background: color-mix(in srgb, var(--bf-domain-git-deleted) 15%, transparent); } .bitfun-git-diff-view__line-content { - color: var(--bf-appearance-token-git-color-deleted); + color: var(--bf-domain-git-deleted); } } &--context { &:hover { - background: var(--bf-appearance-token-element-bg-subtle); + background: var(--bf-color-surface-subtle); } } &--hunk-header { - background: var(--bf-appearance-token-element-bg-base); - border-top: 1px solid var(--bf-appearance-token-border-base); - border-bottom: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border-top: 1px solid var(--bf-color-border-default); + border-bottom: 1px solid var(--bf-color-border-default); .bitfun-git-diff-view__line-content { - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); font-weight: var(--bf-font-weight-medium); } } @@ -323,10 +323,10 @@ $opacity-high: 0.8 !default; width: 50px; padding: 2px $size-gap-2; text-align: right; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); user-select: none; - border-right: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-element-bg-subtle); + border-right: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-subtle); font-size: var(--bf-font-size-meta); } @@ -334,7 +334,7 @@ $opacity-high: 0.8 !default; flex: 1; padding: 2px $size-gap-3; white-space: pre; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); overflow-x: visible; } @@ -347,7 +347,7 @@ $opacity-high: 0.8 !default; display: flex; align-items: center; justify-content: center; - background: rgba(var(--bf-appearance-token-color-static-black-rgb), 0.6); + background: color-mix(in srgb, var(--bf-color-content-on-light) 60%, transparent); z-index: $z-modal; backdrop-filter: blur(4px); animation: bitfun-git-diff-view-fade-in 0.2s ease-out; @@ -373,7 +373,7 @@ $opacity-high: 0.8 !default; &__dialog-title { font-size: var(--bf-font-size-xl); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } &__ai-generate-btn { @@ -386,7 +386,7 @@ $opacity-high: 0.8 !default; &__ai-spinner { width: 14px; height: 14px; - border: 2px solid rgba(var(--bf-appearance-token-color-static-white-rgb), 0.3); + border: 2px solid color-mix(in srgb, var(--bf-color-content-on-dark) 30%, transparent); border-top-color: currentColor; border-radius: 50%; animation: bitfun-git-diff-view-spin 0.8s linear infinite; @@ -398,10 +398,10 @@ $opacity-high: 0.8 !default; gap: $size-gap-2; padding: $size-gap-3; margin-bottom: $size-gap-3; - background: var(--bf-appearance-token-color-error-bg); - border: 1px solid var(--bf-appearance-token-color-error-border); + background: var(--bf-color-status-danger-surface); + border: 1px solid var(--bf-color-status-danger-border); border-radius: $size-radius-base; - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); font-size: var(--bf-font-size-sm); animation: bitfun-git-diff-view-shake 0.4s ease-in-out; } @@ -420,17 +420,17 @@ $opacity-high: 0.8 !default; &__form-label { font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-weight: var(--bf-font-weight-medium); } &__form-textarea { min-height: 120px; padding: $size-gap-3; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-base; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-sm); line-height: var(--bf-line-height-relaxed); @@ -442,13 +442,13 @@ $opacity-high: 0.8 !default; &:focus { outline: none; - border-color: var(--bf-appearance-token-color-accent-500); - background: var(--bf-appearance-token-element-bg-medium); - box-shadow: 0 0 0 3px var(--bf-appearance-token-color-accent-100); + border-color: var(--bf-color-accent-default); + background: var(--bf-color-action-neutral-surface-hover); + box-shadow: 0 0 0 3px var(--bf-color-action-secondary-background); } &::placeholder { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } &:disabled { @@ -463,8 +463,8 @@ $opacity-high: 0.8 !default; gap: $size-gap-2; padding: $size-gap-3; margin-top: $size-gap-2; - background: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 5%, transparent); - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 20%, transparent); + background: color-mix(in srgb, var(--bf-color-accent-default) 5%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-accent-default) 20%, transparent); border-radius: $size-radius-base; animation: bitfun-git-diff-view-slide-up 0.3s ease-out; } @@ -477,7 +477,7 @@ $opacity-high: 0.8 !default; } &__ai-info-label { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-weight: var(--bf-font-weight-medium); } @@ -485,15 +485,15 @@ $opacity-high: 0.8 !default; padding: 2px 8px; font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-accent-500); - background: var(--bf-appearance-token-color-accent-200); - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 30%, transparent); + color: var(--bf-color-accent-default); + background: var(--bf-color-action-secondary-hover); + border: 1px solid color-mix(in srgb, var(--bf-color-accent-default) 30%, transparent); border-radius: $size-radius-sm; text-transform: capitalize; } &__ai-info-value { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-family: var(--bf-font-family-mono); font-size: var(--bf-font-size-xs); } @@ -507,21 +507,21 @@ $opacity-high: 0.8 !default; &__ai-confidence-bar { width: 60px; height: 4px; - background: var(--bf-appearance-token-color-overlay-white-12); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 12%, transparent); border-radius: 2px; overflow: hidden; } &__ai-confidence-fill { height: 100%; - background: linear-gradient(90deg, var(--bf-appearance-token-color-accent-400), var(--bf-appearance-token-color-accent-600)); + background: linear-gradient(90deg, color-mix(in srgb, var(--bf-color-accent-default) 40%, transparent), var(--bf-color-accent-hover)); border-radius: 2px; transition: width $motion-base $easing-standard; } &__ai-confidence-text { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-weight: var(--bf-font-weight-medium); } @@ -531,10 +531,10 @@ $opacity-high: 0.8 !default; gap: $size-gap-2; padding: $size-gap-2; margin-top: $size-gap-2; - background: var(--bf-appearance-token-color-warning-bg); - border: 1px solid var(--bf-appearance-token-color-warning-border); + background: var(--bf-color-status-warning-surface); + border: 1px solid var(--bf-color-status-warning-border); border-radius: $size-radius-base; - color: var(--bf-appearance-token-color-warning); + color: var(--bf-color-status-warning-content); font-size: var(--bf-font-size-xs); } @@ -552,7 +552,7 @@ $opacity-high: 0.8 !default; label { font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); cursor: pointer; } } @@ -569,13 +569,13 @@ $opacity-high: 0.8 !default; align-items: center; gap: $size-gap-3; padding: $size-gap-3; - background: var(--bf-appearance-token-element-bg-base); + background: var(--bf-color-action-neutral-surface); border-radius: $size-radius-base; margin-bottom: $size-gap-4; font-size: var(--bf-font-size-sm); strong { - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-weight: var(--bf-font-weight-semibold); } } diff --git a/src/web-ui/src/tools/git/components/GitGraphView/GitGraphView.scss b/src/web-ui/src/tools/git/components/GitGraphView/GitGraphView.scss index 287f23c64e..04ceb49726 100644 --- a/src/web-ui/src/tools/git/components/GitGraphView/GitGraphView.scss +++ b/src/web-ui/src/tools/git/components/GitGraphView/GitGraphView.scss @@ -3,8 +3,8 @@ flex-direction: column; height: 100%; width: 100%; - background: var(--bf-appearance-token-color-bg-primary); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-canvas); + color: var(--bf-color-content-primary); &--loading, &--error, @@ -24,7 +24,7 @@ p { margin: 0; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } } @@ -32,8 +32,8 @@ &__spinner { width: 32px; height: 32px; - border: 3px solid var(--bf-appearance-token-color-overlay-white-12); - border-top-color: var(--bf-appearance-token-color-accent-500); + border: 3px solid color-mix(in srgb, var(--bf-color-content-on-dark) 12%, transparent); + border-top-color: var(--bf-color-accent-default); border-radius: 50%; animation: bitfun-git-graph-spin 0.8s linear infinite; } @@ -43,8 +43,8 @@ align-items: center; justify-content: space-between; padding: 12px 16px; - border-bottom: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-color-bg-secondary); + border-bottom: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-panel); flex-shrink: 0; } @@ -65,8 +65,8 @@ align-items: center; gap: 4px; padding: 4px 8px; - background: var(--bf-appearance-token-color-accent-500); - color: var(--bf-appearance-token-color-static-white); + background: var(--bf-color-accent-default); + color: var(--bf-color-content-on-dark); border-radius: 4px; font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-medium); @@ -90,13 +90,13 @@ &__search-count { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); white-space: nowrap; padding: 0 8px; font-family: var(--bf-font-family-mono); &--no-results { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } } @@ -110,7 +110,7 @@ background: transparent; border: none; border-radius: 4px; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); cursor: pointer; transition: transform 140ms cubic-bezier(0.23, 1, 0.32, 1), @@ -118,8 +118,8 @@ color 140ms ease; &:hover:not(:disabled) { - background: var(--bf-appearance-token-element-bg-hover); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface-hover); + color: var(--bf-color-content-primary); } &:active:not(:disabled) { @@ -150,54 +150,54 @@ transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease; &:hover { - background: var(--bf-appearance-token-color-overlay-white-04); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent); } &--selected { - background: var(--bf-appearance-token-color-accent-100); - border-left: 2px solid var(--bf-appearance-token-color-accent-500); + background: var(--bf-color-action-secondary-background); + border-left: 2px solid var(--bf-color-accent-default); z-index: 2; &:hover { - background: var(--bf-appearance-token-color-accent-200); + background: var(--bf-color-action-secondary-hover); } } &--search-match { - background: color-mix(in srgb, var(--bf-appearance-token-color-warning) 6%, transparent); - border-left: 2px solid color-mix(in srgb, var(--bf-appearance-token-color-warning) 40%, transparent); + background: color-mix(in srgb, var(--bf-color-status-warning-content) 6%, transparent); + border-left: 2px solid color-mix(in srgb, var(--bf-color-status-warning-content) 40%, transparent); &:hover { - background: color-mix(in srgb, var(--bf-appearance-token-color-warning) 10%, transparent); + background: color-mix(in srgb, var(--bf-color-status-warning-content) 10%, transparent); } } &--current-search-match { - background: color-mix(in srgb, var(--bf-appearance-token-color-warning) 15%, transparent); - border-left: 3px solid var(--bf-appearance-token-color-warning); - box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--bf-appearance-token-color-warning) 30%, transparent); + background: color-mix(in srgb, var(--bf-color-status-warning-content) 15%, transparent); + border-left: 3px solid var(--bf-color-status-warning-content); + box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--bf-color-status-warning-content) 30%, transparent); z-index: 3; &:hover { - background: color-mix(in srgb, var(--bf-appearance-token-color-warning) 20%, transparent); + background: color-mix(in srgb, var(--bf-color-status-warning-content) 20%, transparent); } &.git-graph-view__hit-area--selected { background: linear-gradient( 90deg, - color-mix(in srgb, var(--bf-appearance-token-color-warning) 20%, transparent), - var(--bf-appearance-token-color-accent-200) + color-mix(in srgb, var(--bf-color-status-warning-content) 20%, transparent), + var(--bf-color-action-secondary-hover) ); - border-left: 3px solid var(--bf-appearance-token-color-warning); + border-left: 3px solid var(--bf-color-status-warning-content); box-shadow: - inset 0 0 0 1px color-mix(in srgb, var(--bf-appearance-token-color-warning) 30%, transparent), - inset 3px 0 0 0 var(--bf-appearance-token-color-accent-500); + inset 0 0 0 1px color-mix(in srgb, var(--bf-color-status-warning-content) 30%, transparent), + inset 3px 0 0 0 var(--bf-color-accent-default); &:hover { background: linear-gradient( 90deg, - color-mix(in srgb, var(--bf-appearance-token-color-warning) 25%, transparent), - var(--bf-appearance-token-color-accent-200) + color-mix(in srgb, var(--bf-color-status-warning-content) 25%, transparent), + var(--bf-color-action-secondary-hover) ); } } @@ -210,19 +210,19 @@ gap: 12px; padding: 0 16px; cursor: pointer; - border-bottom: 1px solid var(--bf-appearance-token-border-base); + border-bottom: 1px solid var(--bf-color-border-default); transition: background 0.15s, box-shadow 0.15s; - background: var(--bf-appearance-token-color-bg-primary); + background: var(--bf-color-surface-canvas); &:hover { - background: var(--bf-appearance-token-element-bg-hover); - box-shadow: 0 1px 3px var(--bf-appearance-token-color-overlay-black-12); + background: var(--bf-color-action-neutral-surface-hover); + box-shadow: 0 1px 3px color-mix(in srgb, var(--bf-color-content-on-light) 12%, transparent); z-index: 1; } &--selected { - background: var(--bf-appearance-token-color-accent-100) !important; - box-shadow: 0 2px 4px var(--bf-appearance-token-color-overlay-black-15); + background: var(--bf-color-action-secondary-background) !important; + box-shadow: 0 2px 4px color-mix(in srgb, var(--bf-color-content-on-light) 15%, transparent); z-index: 2; } @@ -255,22 +255,22 @@ cursor: help; &--branch { - background: var(--bf-appearance-token-color-accent-600); - color: var(--bf-appearance-token-color-static-white); + background: var(--bf-color-accent-hover); + color: var(--bf-color-content-on-dark); } &--remote { - background: var(--bf-appearance-token-color-purple-600); - color: var(--bf-appearance-token-color-static-white); + background: var(--bf-color-accent-secondary-hover); + color: var(--bf-color-content-on-dark); } &--tag { - background: var(--bf-appearance-token-git-color-changes); - color: var(--bf-appearance-token-color-static-white); + background: var(--bf-domain-git-changes); + color: var(--bf-color-content-on-dark); } &--current { - box-shadow: 0 0 0 2px var(--bf-appearance-token-color-bg-primary), + box-shadow: 0 0 0 2px var(--bf-color-surface-canvas), 0 0 0 4px currentColor; } } @@ -293,7 +293,7 @@ align-items: center; gap: 12px; font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); flex-shrink: 0; } @@ -311,7 +311,7 @@ &__commit-hash { font-family: var(--bf-font-family-mono); padding: 2px 6px; - background: var(--bf-appearance-token-color-bg-tertiary); + background: var(--bf-color-surface-tertiary); border-radius: 4px; white-space: nowrap; } @@ -331,15 +331,15 @@ padding: 4px; background: transparent; border: none; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); cursor: pointer; display: flex; align-items: center; border-radius: 4px; &:hover { - background: var(--bf-appearance-token-element-bg-hover); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface-hover); + color: var(--bf-color-content-primary); } } } diff --git a/src/web-ui/src/tools/git/components/GitGraphView/GitGraphView.tsx b/src/web-ui/src/tools/git/components/GitGraphView/GitGraphView.tsx index 0780a919f9..1f29c6ca1a 100644 --- a/src/web-ui/src/tools/git/components/GitGraphView/GitGraphView.tsx +++ b/src/web-ui/src/tools/git/components/GitGraphView/GitGraphView.tsx @@ -453,7 +453,7 @@ function drawNodeWithInfo( const centerY = y + rowHeight / 2; const resolveLaneColor = (lane: number) => ensureMinimumContrast( resolveCanvasColor(colors[lane % colors.length]), - resolveCanvasColor('var(--bf-appearance-token-color-bg-primary)'), + resolveCanvasColor('var(--bf-color-surface-canvas)'), GIT_GRAPH_LANE_MIN_CONTRAST ); const color = resolveLaneColor(node.lane); @@ -540,7 +540,7 @@ function drawNodeWithInfo( if (state.isSelected) { - ctx.strokeStyle = resolveCanvasColor('var(--bf-appearance-token-color-static-white)'); + ctx.strokeStyle = resolveCanvasColor('var(--bf-color-content-on-dark)'); ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(x, centerY, nodeSize + 1.5, 0, Math.PI * 2); @@ -604,7 +604,7 @@ function drawNodeWithInfo( ? APPEARANCE_DOMAIN_TOKENS.gitGraphLane[2] : APPEARANCE_DOMAIN_TOKENS.gitGraphLane[3] ), - resolveCanvasColor('var(--bf-appearance-token-color-static-white)'), + resolveCanvasColor('var(--bf-color-content-on-dark)'), GIT_GRAPH_LANE_MIN_CONTRAST ); const text = displayName; @@ -625,7 +625,7 @@ function drawNodeWithInfo( if (ref.isCurrent) { ctx.save(); - ctx.fillStyle = resolveCanvasColor('var(--bf-appearance-token-color-static-white)'); + ctx.fillStyle = resolveCanvasColor('var(--bf-color-content-on-dark)'); ctx.beginPath(); ctx.arc(refX + refWidth - 4, centerY - refHeight / 2 + 4, 2, 0, Math.PI * 2); ctx.fill(); @@ -634,7 +634,7 @@ function drawNodeWithInfo( ctx.save(); - ctx.fillStyle = resolveCanvasColor('var(--bf-appearance-token-color-static-white)'); + ctx.fillStyle = resolveCanvasColor('var(--bf-color-content-on-dark)'); ctx.font = '500 11px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'; ctx.textBaseline = 'middle'; ctx.textAlign = 'left'; @@ -651,7 +651,7 @@ function drawNodeWithInfo( ctx.save(); - ctx.fillStyle = resolveCanvasColor('var(--bf-appearance-token-color-text-primary)'); + ctx.fillStyle = resolveCanvasColor('var(--bf-color-content-primary)'); ctx.font = '13px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'; ctx.textBaseline = 'middle'; ctx.textAlign = 'left'; @@ -672,7 +672,7 @@ function drawNodeWithInfo( const metaX = textX + ctx.measureText(displayText).width + 20; - ctx.fillStyle = resolveCanvasColor('var(--bf-appearance-token-color-text-muted)'); + ctx.fillStyle = resolveCanvasColor('var(--bf-color-content-muted)'); ctx.font = '12px -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'; let authorName = node.authorName; @@ -692,7 +692,7 @@ function drawNodeWithInfo( const hashX = metaX + ctx.measureText(metaText).width + 16; const hashText = node.hash.substring(0, 7); - ctx.fillStyle = resolveCanvasColor('var(--bf-appearance-token-color-text-disabled)'); + ctx.fillStyle = resolveCanvasColor('var(--bf-color-content-disabled)'); ctx.font = '11px "SF Mono", "Monaco", "Courier New", monospace'; ctx.fillText(hashText, hashX, centerY); diff --git a/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.css b/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.css index 98988a9a66..e393099720 100644 --- a/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.css +++ b/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.css @@ -2,8 +2,8 @@ display: flex; flex-direction: column; height: 100%; - background: var(--bf-appearance-token-color-bg-primary); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-canvas); + color: var(--bf-color-content-primary); font-family:var(--bf-font-family-sans); } @@ -12,8 +12,8 @@ align-items: center; justify-content: space-between; padding: 16px; - border-bottom: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-color-bg-secondary); + border-bottom: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-panel); } .header-left { @@ -26,7 +26,7 @@ margin: 0; font-size: var(--bf-font-size-2xl); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } .header-right { @@ -41,10 +41,10 @@ justify-content: center; width: 32px; height: 32px; - background: var(--bf-appearance-token-color-bg-tertiary); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-tertiary); + border: 1px solid var(--bf-color-border-default); border-radius: 4px; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); cursor: pointer; transition: background-color 0.2s ease, @@ -53,8 +53,8 @@ } .refresh-btn:hover:not(:disabled) { - background: var(--bf-appearance-token-element-bg-hover); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-neutral-surface-hover); + color: var(--bf-color-content-primary); } .refresh-btn:disabled { @@ -67,10 +67,10 @@ align-items: center; gap: 6px; padding: 8px 12px; - background: var(--bf-appearance-token-color-success-bg); - border: 1px solid var(--bf-appearance-token-color-success); + background: var(--bf-color-status-success-surface); + border: 1px solid var(--bf-color-status-success-content); border-radius: 4px; - color: var(--bf-appearance-token-color-success); + color: var(--bf-color-status-success-content); font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-medium); cursor: pointer; @@ -81,8 +81,8 @@ } .save-btn:hover:not(:disabled) { - background: var(--bf-appearance-token-color-success); - color: white; + background: var(--bf-color-status-success-content); + color: var(--bf-color-content-on-dark); } .save-btn:disabled { @@ -100,15 +100,15 @@ } .status-banner.error { - background: var(--bf-appearance-token-color-error-bg); - color: var(--bf-appearance-token-color-error); - border-color: color-mix(in srgb, var(--bf-appearance-token-color-error) 20%, transparent); + background: var(--bf-color-status-danger-surface); + color: var(--bf-color-status-danger-content); + border-color: color-mix(in srgb, var(--bf-color-status-danger-content) 20%, transparent); } .status-banner.success { - background: var(--bf-appearance-token-color-success-bg); - color: var(--bf-appearance-token-color-success); - border-color: color-mix(in srgb, var(--bf-appearance-token-color-success) 20%, transparent); + background: var(--bf-color-status-success-surface); + color: var(--bf-color-status-success-content); + border-color: color-mix(in srgb, var(--bf-color-status-success-content) 20%, transparent); } .close-btn { @@ -123,8 +123,8 @@ .settings-tabs { display: flex; - border-bottom: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-color-bg-secondary); + border-bottom: 1px solid var(--bf-color-border-default); + background: var(--bf-color-surface-panel); } .tab-btn { @@ -135,7 +135,7 @@ background: none; border: none; border-bottom: 2px solid transparent; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-medium); cursor: pointer; @@ -146,13 +146,13 @@ } .tab-btn:hover { - color: var(--bf-appearance-token-color-text-primary); - background: var(--bf-appearance-token-element-bg-hover); + color: var(--bf-color-content-primary); + background: var(--bf-color-action-neutral-surface-hover); } .tab-btn.active { - color: var(--bf-appearance-token-color-accent-500); - border-bottom-color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); + border-bottom-color: var(--bf-color-accent-default); } .settings-content { @@ -167,7 +167,7 @@ .settings-section { margin-bottom: 32px; padding-bottom: 24px; - border-bottom: 1px solid var(--bf-appearance-token-border-base); + border-bottom: 1px solid var(--bf-color-border-default); } .settings-section:last-child { @@ -179,20 +179,20 @@ margin: 0 0 8px; font-size: var(--bf-font-size-base); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } .settings-section h5 { margin: 16px 0 8px; font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } .section-description { margin: 0 0 16px; font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); line-height: var(--bf-line-height-ui); } @@ -207,17 +207,17 @@ margin-bottom: 6px; font-size: var(--bf-font-size-xs); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } .form-group input, .form-group select { width: 100%; padding: 8px 12px; - background: var(--bf-appearance-token-color-bg-tertiary); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-tertiary); + border: 1px solid var(--bf-color-border-default); border-radius: 4px; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-xs); transition: background-color 0.2s ease, @@ -228,18 +228,18 @@ .form-group input:focus, .form-group select:focus { outline: none; - border-color: var(--bf-appearance-token-color-accent-500); - background: var(--bf-appearance-token-element-bg-hover); + border-color: var(--bf-color-accent-default); + background: var(--bf-color-action-neutral-surface-hover); } .form-group input::placeholder { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); } .checkbox-group { padding: 12px; - background: var(--bf-appearance-token-color-bg-tertiary); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-tertiary); + border: 1px solid var(--bf-color-border-default); border-radius: 6px; } @@ -260,7 +260,7 @@ .field-description { margin: 4px 0 0; font-size: var(--bf-font-size-meta); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); line-height: var(--bf-line-height-snug); } @@ -272,8 +272,8 @@ .remote-config { padding: 16px; - background: var(--bf-appearance-token-color-bg-tertiary); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-tertiary); + border: 1px solid var(--bf-color-border-default); border-radius: 6px; margin-bottom: 16px; } @@ -281,10 +281,10 @@ .remote-config h5 { margin: 0 0 12px; padding: 4px 8px; - background: var(--bf-appearance-token-color-accent-100); - border: 1px solid var(--bf-appearance-token-color-accent-500); + background: var(--bf-color-action-secondary-background); + border: 1px solid var(--bf-color-accent-default); border-radius: 3px; - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-semibold); text-transform: uppercase; @@ -293,8 +293,8 @@ .branch-config { padding: 16px; - background: var(--bf-appearance-token-color-bg-tertiary); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-tertiary); + border: 1px solid var(--bf-color-border-default); border-radius: 6px; margin-bottom: 16px; } @@ -302,10 +302,10 @@ .branch-config h5 { margin: 0 0 12px; padding: 4px 8px; - background: var(--bf-appearance-token-color-success-bg); - border: 1px solid var(--bf-appearance-token-color-success); + background: var(--bf-color-status-success-surface); + border: 1px solid var(--bf-color-status-success-content); border-radius: 3px; - color: var(--bf-appearance-token-color-success); + color: var(--bf-color-status-success-content); font-size: var(--bf-font-size-meta); font-weight: var(--bf-font-weight-semibold); display: inline-block; @@ -343,16 +343,16 @@ .error-message { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); margin: 4px 0 16px; } .retry-btn { padding: 8px 16px; - background: var(--bf-appearance-token-color-accent-500); + background: var(--bf-color-accent-default); border: none; border-radius: 4px; - color: white; + color: var(--bf-color-content-on-dark); font-size: var(--bf-font-size-xs); cursor: pointer; transition: background-color 0.2s ease; @@ -365,7 +365,7 @@ } .retry-btn:hover { - background: var(--bf-appearance-token-color-accent-600); + background: var(--bf-color-accent-hover); } @media (max-width: 768px) { @@ -390,7 +390,7 @@ } .tab-btn.active { - border-right-color: var(--bf-appearance-token-color-accent-500); + border-right-color: var(--bf-color-accent-default); border-bottom-color: transparent; } diff --git a/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.scss b/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.scss index 235fc82913..9673c89780 100644 --- a/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.scss +++ b/src/web-ui/src/tools/git/components/GitSettingsView/GitSettingsView.scss @@ -9,8 +9,8 @@ $opacity-high: 0.8 !default; display: flex; flex-direction: column; height: 100%; - background: var(--bf-appearance-token-color-bg-primary); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-surface-canvas); + color: var(--bf-color-content-primary); font-family: var(--bf-font-family-sans); &__header { @@ -18,8 +18,8 @@ $opacity-high: 0.8 !default; align-items: center; justify-content: space-between; padding: $size-gap-4; - border-bottom: 1px solid var(--bf-appearance-token-border-base); - background: var(--bf-appearance-token-element-bg-soft); + border-bottom: 1px solid var(--bf-color-border-default); + background: var(--bf-color-action-quiet-hover); } &__header-left { @@ -31,7 +31,7 @@ $opacity-high: 0.8 !default; margin: 0; font-size: var(--bf-font-size-lg); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } } @@ -50,15 +50,15 @@ $opacity-high: 0.8 !default; position: relative; &--success { - background: var(--bf-appearance-token-color-success-bg); - border-bottom: 1px solid var(--bf-appearance-token-color-success); - color: var(--bf-appearance-token-color-success); + background: var(--bf-color-status-success-surface); + border-bottom: 1px solid var(--bf-color-status-success-content); + color: var(--bf-color-status-success-content); } &--error { - background: var(--bf-appearance-token-color-error-bg); - border-bottom: 1px solid var(--bf-appearance-token-color-error); - color: var(--bf-appearance-token-color-error); + background: var(--bf-color-status-danger-surface); + border-bottom: 1px solid var(--bf-color-status-danger-content); + color: var(--bf-color-status-danger-content); } } @@ -114,21 +114,21 @@ $opacity-high: 0.8 !default; gap: $size-gap-2; font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } &__form-description { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); margin-top: -$size-gap-1; } &__form-input { padding: $size-gap-2 $size-gap-3; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-base; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-sm); font-family: var(--bf-font-family-mono); transition: @@ -137,12 +137,12 @@ $opacity-high: 0.8 !default; &:focus { outline: none; - border-color: var(--bf-appearance-token-color-accent-500); - background: var(--bf-appearance-token-element-bg-medium); + border-color: var(--bf-color-accent-default); + background: var(--bf-color-action-neutral-surface-hover); } &::placeholder { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } &:disabled { @@ -153,10 +153,10 @@ $opacity-high: 0.8 !default; &__form-select { padding: $size-gap-2 $size-gap-3; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-base; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-sm); cursor: pointer; transition: @@ -166,8 +166,8 @@ $opacity-high: 0.8 !default; &:focus { outline: none; - border-color: var(--bf-appearance-token-color-accent-500); - background: var(--bf-appearance-token-element-bg-medium); + border-color: var(--bf-color-accent-default); + background: var(--bf-color-action-neutral-surface-hover); } &:disabled { @@ -191,7 +191,7 @@ $opacity-high: 0.8 !default; label { margin: 0; font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); cursor: pointer; user-select: none; } @@ -211,26 +211,26 @@ $opacity-high: 0.8 !default; gap: $size-gap-2; margin-bottom: $size-gap-4; padding-bottom: $size-gap-2; - border-bottom: 1px solid var(--bf-appearance-token-color-overlay-white-08); + border-bottom: 1px solid color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); } &__section-title { font-size: var(--bf-font-size-base); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); margin: 0; } &__section-description { font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); margin-top: $size-gap-1; } &__config-item { padding: $size-gap-4; - background: var(--bf-appearance-token-element-bg-soft); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-quiet-hover); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-base; margin-bottom: $size-gap-3; transition: @@ -238,8 +238,8 @@ $opacity-high: 0.8 !default; border-color $motion-fast $easing-standard; &:hover { - background: var(--bf-appearance-token-element-bg-base); - border-color: var(--bf-appearance-token-border-medium); + background: var(--bf-color-action-neutral-surface); + border-color: var(--bf-color-field-border-hover); } &:last-child { @@ -255,14 +255,14 @@ $opacity-high: 0.8 !default; &__config-key { font-size: var(--bf-font-size-sm); font-weight: var(--bf-font-weight-medium); - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); margin-bottom: $size-gap-1; font-family: var(--bf-font-family-mono); } &__config-value { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-family: var(--bf-font-family-mono); white-space: nowrap; overflow: hidden; @@ -284,13 +284,13 @@ $opacity-high: 0.8 !default; height: 100%; padding: $size-gap-10; text-align: center; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); h3 { font-size: var(--bf-font-size-lg); font-weight: var(--bf-font-weight-medium); margin: $size-gap-4 0 $size-gap-2 0; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); } p { @@ -305,7 +305,7 @@ $opacity-high: 0.8 !default; &__error-message { font-size: var(--bf-font-size-sm); - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); margin-bottom: $size-gap-4; } @@ -314,8 +314,8 @@ $opacity-high: 0.8 !default; align-items: center; gap: $size-gap-2; padding: $size-gap-3; - background: var(--bf-appearance-token-element-bg-base); - border: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-action-neutral-surface); + border: 1px solid var(--bf-color-border-default); border-radius: $size-radius-base; cursor: pointer; transition: @@ -325,15 +325,15 @@ $opacity-high: 0.8 !default; margin-top: $size-gap-4; &:hover { - background: var(--bf-appearance-token-element-bg-medium); - border-color: var(--bf-appearance-token-border-medium); + background: var(--bf-color-action-neutral-surface-hover); + border-color: var(--bf-color-field-border-hover); } } &__advanced-content { margin-top: $size-gap-3; padding: $size-gap-4; - background: var(--bf-appearance-token-element-bg-subtle); + background: var(--bf-color-surface-subtle); border-radius: $size-radius-base; } } diff --git a/src/web-ui/src/tools/terminal/components/Terminal.scss b/src/web-ui/src/tools/terminal/components/Terminal.scss index 14bba14c4a..098a1c0597 100644 --- a/src/web-ui/src/tools/terminal/components/Terminal.scss +++ b/src/web-ui/src/tools/terminal/components/Terminal.scss @@ -5,7 +5,7 @@ flex-direction: column; width: 100%; height: 100%; - background-color: var(--bf-appearance-token-color-bg-scene); + background-color: var(--bf-color-surface-scene); overflow: hidden; &__container { @@ -26,7 +26,7 @@ &:not(.allow-transparency) { .xterm-viewport { - background-color: var(--bf-appearance-token-color-bg-scene); + background-color: var(--bf-color-surface-scene); } } @@ -44,14 +44,14 @@ justify-content: center; width: 100%; height: 100%; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); gap: 12px; &-spinner { width: 32px; height: 32px; - border: 3px solid var(--bf-appearance-token-element-bg-subtle); - border-top-color: var(--bf-appearance-token-color-accent-500); + border: 3px solid var(--bf-color-surface-subtle); + border-top-color: var(--bf-color-accent-default); border-radius: 50%; animation: terminal-spin 1s linear infinite; } @@ -68,7 +68,7 @@ justify-content: center; width: 100%; height: 100%; - color: var(--bf-appearance-token-color-error); + color: var(--bf-color-status-danger-content); gap: 12px; padding: 20px; @@ -92,8 +92,8 @@ align-items: center; justify-content: space-between; padding: 4px 8px; - background: var(--bf-appearance-token-color-bg-secondary); - border-bottom: 1px solid var(--bf-appearance-token-border-base); + background: var(--bf-color-surface-panel); + border-bottom: 1px solid var(--bf-color-border-default); &-left { display: flex; @@ -109,10 +109,10 @@ &-title { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); .shell-type { - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); margin-left: 8px; } } @@ -126,7 +126,7 @@ background: transparent; border: none; border-radius: 4px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); cursor: pointer; transition: transform 140ms cubic-bezier(0.23, 1, 0.32, 1), @@ -134,17 +134,17 @@ color 140ms ease; &:hover { - background: var(--bf-appearance-token-element-bg-soft); - color: var(--bf-appearance-token-color-text-primary); + background: var(--bf-color-action-quiet-hover); + color: var(--bf-color-content-primary); } &:active { - background: var(--bf-appearance-token-element-bg-base); + background: var(--bf-color-action-neutral-surface); } &--danger:hover { - background: var(--bf-appearance-token-color-error-bg); - color: var(--bf-appearance-token-color-error); + background: var(--bf-color-status-danger-surface); + color: var(--bf-color-status-danger-content); } } } @@ -154,16 +154,16 @@ align-items: center; justify-content: space-between; padding: 2px 8px; - background: var(--bf-appearance-token-color-info); + background: var(--bf-color-status-info-content); font-size: var(--bf-font-size-meta); - color: white; + color: var(--bf-color-content-on-dark); &--error { - background: var(--bf-appearance-token-color-error); + background: var(--bf-color-status-danger-content); } &--exited { - background: var(--bf-appearance-token-color-text-muted); + background: var(--bf-color-content-muted); } &-left { diff --git a/src/web-ui/src/tools/terminal/components/TerminalOutputRenderer.scss b/src/web-ui/src/tools/terminal/components/TerminalOutputRenderer.scss index a79595cc9e..d4839dca2e 100644 --- a/src/web-ui/src/tools/terminal/components/TerminalOutputRenderer.scss +++ b/src/web-ui/src/tools/terminal/components/TerminalOutputRenderer.scss @@ -3,7 +3,7 @@ margin: 0 !important; border: 0 !important; outline: 0 !important; - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); background: transparent !important; box-shadow: none !important; font-family:var(--bf-font-family-mono); @@ -15,8 +15,8 @@ .terminal-output-renderer { overflow: hidden; - border-radius: var(--bf-appearance-token-size-radius-sm); - background: var(--bf-appearance-token-color-bg-scene); + border-radius: var(--bf-radius-sm); + background: var(--bf-color-surface-scene); .xterm { height: 100%; @@ -27,7 +27,7 @@ } &:not(.allow-transparency) .xterm-viewport { - background-color: var(--bf-appearance-token-color-bg-scene); + background-color: var(--bf-color-surface-scene); } .xterm-screen { diff --git a/src/web-ui/src/tools/workspace/components/WorkspaceManager.css b/src/web-ui/src/tools/workspace/components/WorkspaceManager.css index 0d61d76b85..60c0ec64aa 100644 --- a/src/web-ui/src/tools/workspace/components/WorkspaceManager.css +++ b/src/web-ui/src/tools/workspace/components/WorkspaceManager.css @@ -10,29 +10,29 @@ .error-message { padding: 12px 16px; background: linear-gradient(135deg, - var(--bf-appearance-token-color-error-bg) 0%, - var(--bf-appearance-token-glass-red-subtle) 100%); - color: var(--bf-appearance-token-color-error); + var(--bf-color-status-danger-surface) 0%, + color-mix(in srgb, var(--bf-color-status-danger-content) 5%, transparent) 100%); + color: var(--bf-color-status-danger-content); border-radius: 12px; - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-error) 20%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-status-danger-content) 20%, transparent); backdrop-filter: blur(12px) saturate(1.05); -webkit-backdrop-filter: blur(12px) saturate(1.05); box-shadow: - 0 8px 32px color-mix(in srgb, var(--bf-appearance-token-color-error) 12%, transparent), - 0 4px 16px var(--bf-appearance-token-color-overlay-black-08), - inset 0 1px 0 var(--bf-appearance-token-color-overlay-white-12); + 0 8px 32px color-mix(in srgb, var(--bf-color-status-danger-content) 12%, transparent), + 0 4px 16px color-mix(in srgb, var(--bf-color-content-on-light) 8%, transparent), + inset 0 1px 0 color-mix(in srgb, var(--bf-color-content-on-dark) 12%, transparent); } .workspace-manager h3 { margin: 0 0 16px 0; font-size: var(--bf-font-size-2xl); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); display: flex; align-items: center; gap: 8px; margin: 0 0 10px; - color: var(--bf-appearance-token-color-text-primary); + color: var(--bf-color-content-primary); font-size: var(--bf-font-size-base); font-weight: var(--bf-font-weight-semibold); line-height: var(--bf-line-height-tight); @@ -40,20 +40,20 @@ .workspace-card { position: relative; - border: 1px solid var(--bf-appearance-token-color-accent-200); + border: 1px solid var(--bf-color-action-secondary-hover); border-radius: 16px; padding: 20px 24px; background: linear-gradient(135deg, - var(--bf-appearance-token-color-accent-100) 0%, - color-mix(in srgb, var(--bf-appearance-token-color-accent-600) 4%, transparent) 50%, - color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 6%, transparent) 100%); + var(--bf-color-action-secondary-background) 0%, + color-mix(in srgb, var(--bf-color-accent-hover) 4%, transparent) 50%, + color-mix(in srgb, var(--bf-color-accent-default) 6%, transparent) 100%); backdrop-filter: blur(12px) saturate(1.05); -webkit-backdrop-filter: blur(12px) saturate(1.05); box-shadow: - 0 8px 32px color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 12%, transparent), - 0 4px 16px var(--bf-appearance-token-color-overlay-black-08), - inset 0 1px 0 var(--bf-appearance-token-color-overlay-white-12), - inset 0 -1px 0 var(--bf-appearance-token-color-overlay-white-08); + 0 8px 32px color-mix(in srgb, var(--bf-color-accent-default) 12%, transparent), + 0 4px 16px color-mix(in srgb, var(--bf-color-content-on-light) 8%, transparent), + inset 0 1px 0 color-mix(in srgb, var(--bf-color-content-on-dark) 12%, transparent), + inset 0 -1px 0 color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), @@ -70,26 +70,26 @@ right: 0; bottom: 0; background: linear-gradient(135deg, - var(--bf-appearance-token-color-overlay-white-04) 0%, + color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent) 0%, transparent 50%, - color-mix(in srgb, var(--bf-appearance-token-color-static-white) 1%, transparent) 100%); + color-mix(in srgb, var(--bf-color-content-on-dark) 1%, transparent) 100%); pointer-events: none; border-radius: 16px; z-index: 1; } .workspace-card.current { - border-color: var(--bf-appearance-token-color-accent-300); + border-color: var(--bf-color-action-secondary-pressed); background: linear-gradient(135deg, - var(--bf-appearance-token-color-accent-200) 0%, - var(--bf-appearance-token-glass-blue-subtle) 50%, - color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 12%, transparent) 100%); + var(--bf-color-action-secondary-hover) 0%, + color-mix(in srgb, var(--bf-color-accent-hover) 8%, transparent) 50%, + color-mix(in srgb, var(--bf-color-accent-default) 12%, transparent) 100%); box-shadow: - 0 8px 32px var(--bf-appearance-token-color-accent-200), - 0 4px 16px var(--bf-appearance-token-color-overlay-black-08), - 0 2px 8px var(--bf-appearance-token-color-overlay-black-08), - inset 0 1px 0 var(--bf-appearance-token-color-overlay-white-15), - inset 0 -1px 0 var(--bf-appearance-token-color-overlay-white-08); + 0 8px 32px var(--bf-color-action-secondary-hover), + 0 4px 16px color-mix(in srgb, var(--bf-color-content-on-light) 8%, transparent), + 0 2px 8px color-mix(in srgb, var(--bf-color-content-on-light) 8%, transparent), + inset 0 1px 0 color-mix(in srgb, var(--bf-color-content-on-dark) 15%, transparent), + inset 0 -1px 0 color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); } .workspace-card.recent { @@ -97,17 +97,17 @@ } .workspace-card.recent:hover { - border-color: var(--bf-appearance-token-color-accent-300); + border-color: var(--bf-color-action-secondary-pressed); background: linear-gradient(135deg, - color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 12%, transparent) 0%, - color-mix(in srgb, var(--bf-appearance-token-color-accent-600) 6%, transparent) 50%, - var(--bf-appearance-token-color-accent-100) 100%); + color-mix(in srgb, var(--bf-color-accent-default) 12%, transparent) 0%, + color-mix(in srgb, var(--bf-color-accent-hover) 6%, transparent) 50%, + var(--bf-color-action-secondary-background) 100%); transform: translateY(-2px); box-shadow: - 0 12px 40px var(--bf-appearance-token-color-accent-200), - 0 6px 20px var(--bf-appearance-token-color-overlay-black-08), - inset 0 1px 0 var(--bf-appearance-token-color-overlay-white-15), - inset 0 -1px 0 var(--bf-appearance-token-color-overlay-white-08); + 0 12px 40px var(--bf-color-action-secondary-hover), + 0 6px 20px color-mix(in srgb, var(--bf-color-content-on-light) 8%, transparent), + inset 0 1px 0 color-mix(in srgb, var(--bf-color-content-on-dark) 15%, transparent), + inset 0 -1px 0 color-mix(in srgb, var(--bf-color-content-on-dark) 8%, transparent); } .workspace-header { @@ -123,13 +123,13 @@ justify-content: center; width: 48px; height: 48px; - background: linear-gradient(135deg, var(--bf-appearance-token-color-accent-500) 0%, var(--bf-appearance-token-color-accent-600) 100%); - color: var(--bf-appearance-token-color-static-white); + background: linear-gradient(135deg, var(--bf-color-accent-default) 0%, var(--bf-color-accent-hover) 100%); + color: var(--bf-color-content-on-dark); border-radius: 12px; flex-shrink: 0; box-shadow: - 0 4px 16px var(--bf-appearance-token-color-accent-300), - inset 0 1px 0 var(--bf-appearance-token-color-overlay-white-20); + 0 4px 16px var(--bf-color-action-secondary-pressed), + inset 0 1px 0 color-mix(in srgb, var(--bf-color-content-on-dark) 20%, transparent); transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1); @@ -138,8 +138,8 @@ .workspace-icon:hover { transform: scale(1.05); box-shadow: - 0 6px 20px color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 30%, transparent), - inset 0 1px 0 color-mix(in srgb, var(--bf-appearance-token-color-static-white) 25%, transparent); + 0 6px 20px color-mix(in srgb, var(--bf-color-accent-default) 30%, transparent), + inset 0 1px 0 color-mix(in srgb, var(--bf-color-content-on-dark) 25%, transparent); } .workspace-icon.is-assistant { @@ -160,7 +160,7 @@ .workspace-name { font-size: var(--bf-font-size-2xl); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); margin-bottom: 6px; word-break: break-all; line-height: var(--bf-line-height-snug); @@ -168,22 +168,22 @@ .workspace-name__ssh-host { font-weight: var(--bf-font-weight-medium); - color: color-mix(in srgb, var(--bf-appearance-token-color-static-white) 55%, transparent); + color: color-mix(in srgb, var(--bf-color-content-on-dark) 55%, transparent); margin-right: 2px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-weight: var(--bf-font-weight-medium); } .workspace-path { font-size: var(--bf-font-size-base); - color: color-mix(in srgb, var(--bf-appearance-token-color-static-white) 70%, transparent); + color: color-mix(in srgb, var(--bf-color-content-on-dark) 70%, transparent); margin-bottom: 12px; word-break: break-all; font-family: var(--bf-font-family-mono); - background: var(--bf-appearance-token-color-overlay-black-20); + background: color-mix(in srgb, var(--bf-color-content-on-light) 20%, transparent); padding: 4px 8px; border-radius: 6px; - border: 1px solid var(--bf-appearance-token-color-accent-100); + border: 1px solid var(--bf-color-action-secondary-background); } .workspace-meta { @@ -201,13 +201,13 @@ gap: 5px; min-height: 22px; padding: 2px 7px; - border: 1px solid var(--bf-appearance-token-border-subtle); - border-radius: var(--bf-appearance-token-size-radius-sm); - background: var(--bf-appearance-token-element-bg-soft); + border: 1px solid var(--bf-color-border-subtle); + border-radius: var(--bf-radius-sm); + background: var(--bf-color-action-quiet-hover); } .workspace-type { - color: var(--bf-appearance-token-color-text-secondary); + color: var(--bf-color-content-secondary); font-size: var(--bf-font-size-xs); text-transform: capitalize; } @@ -216,7 +216,7 @@ display: inline-flex; align-items: center; gap: 4px; - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); font-size: var(--bf-font-size-xs); } @@ -226,20 +226,20 @@ gap: 6px; padding: 4px 10px; border-radius: 999px; - background: var(--bf-appearance-token-color-accent-100); - border: 1px solid var(--bf-appearance-token-color-accent-200); + background: var(--bf-color-action-secondary-background); + border: 1px solid var(--bf-color-action-secondary-hover); } .workspace-identity__label { font-size: var(--bf-font-size-meta); text-transform: uppercase; letter-spacing: var(--bf-letter-spacing-wide); - color: color-mix(in srgb, var(--bf-appearance-token-color-static-white) 55%, transparent); + color: color-mix(in srgb, var(--bf-color-content-on-dark) 55%, transparent); } .workspace-identity__value { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); } .workspace-related-paths { @@ -253,7 +253,7 @@ font-size: var(--bf-font-size-meta); text-transform: uppercase; letter-spacing: var(--bf-letter-spacing-wide); - color: rgba(var(--bf-appearance-token-color-static-white-rgb), 0.55); + color: color-mix(in srgb, var(--bf-color-content-on-dark) 55%, transparent); } .workspace-related-paths__list { @@ -266,15 +266,15 @@ .workspace-related-paths__more { padding: 8px 10px; border-radius: 10px; - background: color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 6%, transparent); - border: 1px solid color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 12%, transparent); + background: color-mix(in srgb, var(--bf-color-accent-default) 6%, transparent); + border: 1px solid color-mix(in srgb, var(--bf-color-accent-default) 12%, transparent); } .workspace-related-paths__path { display: block; font-size: var(--bf-font-size-xs); font-family: var(--bf-font-family-mono); - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); word-break: break-all; } @@ -282,20 +282,20 @@ display: block; margin-top: 4px; font-size: var(--bf-font-size-xs); - color: color-mix(in srgb, var(--bf-appearance-token-color-static-white) 72%, transparent); + color: color-mix(in srgb, var(--bf-color-content-on-dark) 72%, transparent); line-height: var(--bf-line-height-support); } .workspace-related-paths__more { font-size: var(--bf-font-size-xs); - color: color-mix(in srgb, var(--bf-appearance-token-color-static-white) 62%, transparent); + color: color-mix(in srgb, var(--bf-color-content-on-dark) 62%, transparent); } .workspace-type { font-size: var(--bf-font-size-xs); padding: 2px 8px; - background-color: var(--bf-appearance-token-color-bg-secondary); - color: var(--bf-appearance-token-color-text-secondary); + background-color: var(--bf-color-surface-panel); + color: var(--bf-color-content-secondary); border-radius: 4px; text-transform: capitalize; } @@ -305,7 +305,7 @@ align-items: center; gap: 4px; font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-text-muted); + color: var(--bf-color-content-muted); } .workspace-actions { @@ -323,7 +323,7 @@ gap: 16px; margin-top: 20px; padding-top: 20px; - border-top: 1px solid var(--bf-appearance-token-color-accent-200); + border-top: 1px solid var(--bf-color-action-secondary-hover); position: relative; } @@ -333,10 +333,10 @@ gap: 6px; padding: 12px 16px; background: linear-gradient(135deg, - var(--bf-appearance-token-color-accent-50) 0%, - color-mix(in srgb, var(--bf-appearance-token-color-accent-600) 2%, transparent) 100%); + color-mix(in srgb, var(--bf-color-accent-default) 4%, transparent) 0%, + color-mix(in srgb, var(--bf-color-accent-hover) 2%, transparent) 100%); border-radius: 8px; - border: 1px solid var(--bf-appearance-token-color-accent-100); + border: 1px solid var(--bf-color-action-secondary-background); transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1), @@ -345,15 +345,15 @@ .stat-item:hover { background: linear-gradient(135deg, - var(--bf-appearance-token-color-accent-100) 0%, - color-mix(in srgb, var(--bf-appearance-token-color-accent-600) 4%, transparent) 100%); - border-color: var(--bf-appearance-token-color-accent-200); + var(--bf-color-action-secondary-background) 0%, + color-mix(in srgb, var(--bf-color-accent-hover) 4%, transparent) 100%); + border-color: var(--bf-color-action-secondary-hover); transform: translateY(-1px); } .stat-label { font-size: var(--bf-font-size-xs); - color: var(--bf-appearance-token-color-overlay-white-60); + color: color-mix(in srgb, var(--bf-color-content-on-dark) 60%, transparent); font-weight: var(--bf-font-weight-medium); text-transform: uppercase; letter-spacing: var(--bf-letter-spacing-wider); @@ -362,7 +362,7 @@ .stat-value { font-size: var(--bf-font-size-xl); font-weight: var(--bf-font-weight-semibold); - color: var(--bf-appearance-token-color-accent-500); + color: var(--bf-color-accent-default); } .no-workspace, @@ -373,22 +373,22 @@ justify-content: center; min-height: 112px; padding: 24px 18px; - border: 1px dashed var(--bf-appearance-token-border-subtle); - border-radius: var(--bf-appearance-token-size-radius-lg); - background: var(--bf-appearance-token-color-overlay-white-04); - color: var(--bf-appearance-token-color-text-muted); + border: 1px dashed var(--bf-color-border-subtle); + border-radius: var(--bf-radius-lg); + background: color-mix(in srgb, var(--bf-color-content-on-dark) 4%, transparent); + color: var(--bf-color-content-muted); text-align: center; - color: var(--bf-appearance-token-color-overlay-white-60); + color: color-mix(in srgb, var(--bf-color-content-on-dark) 60%, transparent); background: linear-gradient(135deg, - color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 3%, transparent) 0%, - color-mix(in srgb, var(--bf-appearance-token-color-accent-600) 1%, transparent) 100%); + color-mix(in srgb, var(--bf-color-accent-default) 3%, transparent) 0%, + color-mix(in srgb, var(--bf-color-accent-hover) 1%, transparent) 100%); border-radius: 12px; - border: 1px dashed color-mix(in srgb, var(--bf-appearance-token-color-accent-500) 20%, transparent); + border: 1px dashed color-mix(in srgb, var(--bf-color-accent-default) 20%, transparent); } .no-workspace svg { margin-bottom: 20px; - color: var(--bf-appearance-token-color-accent-400); + color: color-mix(in srgb, var(--bf-color-accent-default) 40%, transparent); opacity: 0.8; } @@ -424,7 +424,7 @@ } .stat-item + .stat-item { - border-top: 1px solid var(--bf-appearance-token-border-subtle); + border-top: 1px solid var(--bf-color-border-subtle); border-left: 0; } } diff --git a/tests/e2e/specs/l0-appearance.spec.ts b/tests/e2e/specs/l0-appearance.spec.ts index f297fa762c..16d6ef2fe8 100644 --- a/tests/e2e/specs/l0-appearance.spec.ts +++ b/tests/e2e/specs/l0-appearance.spec.ts @@ -156,13 +156,13 @@ describe('L0 Appearance', () => { const appearanceStyles = await browser.execute(() => { const styles = window.getComputedStyle(document.documentElement); const appearanceVariables = Array.from(styles) - .filter(property => property.startsWith('--bf-appearance-')); + .filter(property => property.startsWith('--bf-color-')); return { variableCount: appearanceVariables.length, - background: styles.getPropertyValue('--bf-appearance-token-color-bg-primary').trim(), - text: styles.getPropertyValue('--bf-appearance-token-color-text-primary').trim(), - accent: styles.getPropertyValue('--bf-appearance-token-color-accent-500').trim(), + background: styles.getPropertyValue('--bf-color-surface-canvas').trim(), + text: styles.getPropertyValue('--bf-color-content-primary').trim(), + accent: styles.getPropertyValue('--bf-color-accent-default').trim(), }; }); @@ -180,16 +180,16 @@ describe('L0 Appearance', () => { const styles = window.getComputedStyle(document.documentElement); const navPanel = document.querySelector('[data-testid="nav-panel"]'); return { - primary: styles.getPropertyValue('--bf-appearance-token-color-bg-primary').trim(), - scene: styles.getPropertyValue('--bf-appearance-token-color-bg-scene').trim(), - softSurface: styles.getPropertyValue('--bf-appearance-token-color-accent-100').trim(), - text: styles.getPropertyValue('--bf-appearance-token-color-text-primary').trim(), - mutedText: styles.getPropertyValue('--bf-appearance-token-color-text-muted').trim(), - accent: styles.getPropertyValue('--bf-appearance-token-color-accent-500').trim(), - primaryButton: styles.getPropertyValue('--bf-appearance-token-btn-primary-bg').trim(), - successBackground: styles.getPropertyValue('--bf-appearance-token-color-success-bg').trim(), - errorBackground: styles.getPropertyValue('--bf-appearance-token-color-error-bg').trim(), - border: styles.getPropertyValue('--bf-appearance-token-border-base').trim(), + primary: styles.getPropertyValue('--bf-color-surface-canvas').trim(), + scene: styles.getPropertyValue('--bf-color-surface-scene').trim(), + softSurface: styles.getPropertyValue('--bf-color-action-secondary-background').trim(), + text: styles.getPropertyValue('--bf-color-content-primary').trim(), + mutedText: styles.getPropertyValue('--bf-color-content-muted').trim(), + accent: styles.getPropertyValue('--bf-color-accent-default').trim(), + primaryButton: styles.getPropertyValue('--bf-color-action-primary-background').trim(), + successBackground: styles.getPropertyValue('--bf-color-status-success-surface').trim(), + errorBackground: styles.getPropertyValue('--bf-color-status-danger-surface').trim(), + border: styles.getPropertyValue('--bf-color-border-default').trim(), navBackground: navPanel ? window.getComputedStyle(navPanel).backgroundColor : null, }; }); @@ -248,8 +248,8 @@ describe('L0 Appearance', () => { return { appearanceMode: document.documentElement.getAttribute('data-bf-appearance-mode'), - textPrimary: rootStyle.getPropertyValue('--bf-appearance-token-color-text-primary').trim(), - scene: rootStyle.getPropertyValue('--bf-appearance-token-color-bg-scene').trim(), + textPrimary: rootStyle.getPropertyValue('--bf-color-content-primary').trim(), + scene: rootStyle.getPropertyValue('--bf-color-surface-scene').trim(), buttonBackground: buttonRule?.style.background ?? null, buttonBorder: buttonRule?.style.borderColor ?? null, iconColor: iconRule?.style.color ?? null, @@ -261,9 +261,9 @@ describe('L0 Appearance', () => { appearanceMode: 'light', textPrimary: '#1c1c1f', scene: '#ffffff', - buttonBackground: 'var(--bf-appearance-token-color-text-primary)', - buttonBorder: 'var(--bf-appearance-token-color-text-primary)', - iconColor: 'var(--bf-appearance-token-color-bg-scene)', + buttonBackground: 'var(--bf-color-content-primary)', + buttonBorder: 'var(--bf-color-content-primary)', + iconColor: 'var(--bf-color-surface-scene)', iconStroke: 'currentcolor', }); }); @@ -449,7 +449,7 @@ describe('L0 Appearance', () => { ? window.getComputedStyle(cardPrimaryAction).backgroundColor : null, neutralActionBackground: window.getComputedStyle(card) - .getPropertyValue('--bf-appearance-token-element-bg-base') + .getPropertyValue('--bf-color-action-neutral-surface') .trim(), primaryActionLabel: cardPrimaryAction?.textContent?.trim() ?? '', width: cardRect.width, @@ -688,16 +688,16 @@ describe('L0 Appearance', () => { }; }); expect(miniAppHoverContract).toEqual({ - cardBackground: 'var(--bf-appearance-token-element-bg-subtle)', - cardBorder: 'var(--bf-appearance-token-border-base)', - cardShadow: 'var(--bf-appearance-token-shadow-sm)', + cardBackground: 'var(--bf-color-surface-subtle)', + cardBorder: 'var(--bf-color-border-default)', + cardShadow: 'var(--bf-shadow-sm)', cardTransform: 'translateY(-3px)', primaryBackground: 'var(--miniapp-card-inverse-bg)', primaryColor: 'var(--miniapp-card-inverse-color)', deleteBackground: 'var(--miniapp-card-inverse-bg)', deleteColor: 'var(--miniapp-card-inverse-color)', - lightInverseBackground: 'var(--bf-appearance-token-color-static-black)', - lightInverseColor: 'var(--bf-appearance-token-color-static-white)', + lightInverseBackground: 'var(--bf-color-content-on-light)', + lightInverseColor: 'var(--bf-color-content-on-dark)', }); const importAction = await $('[data-testid="miniapp-import-action"]'); @@ -770,21 +770,21 @@ describe('L0 Appearance', () => { return { appearanceId: document.documentElement.getAttribute('data-bf-appearance'), appearanceMode: document.documentElement.getAttribute('data-bf-appearance-mode'), - contentBackgroundToken: rootStyles.getPropertyValue('--bf-appearance-token-color-bg-primary').trim(), - contentTextToken: rootStyles.getPropertyValue('--bf-appearance-token-color-text-primary').trim(), - contentSecondaryTextToken: rootStyles.getPropertyValue('--bf-appearance-token-color-text-secondary').trim(), - contentBorderToken: rootStyles.getPropertyValue('--bf-appearance-token-border-subtle').trim(), - contentSurfaceToken: rootStyles.getPropertyValue('--bf-appearance-token-element-bg-subtle').trim(), - configSectionBackgroundToken: rootStyles.getPropertyValue('--bf-appearance-token-config-page-section-bg').trim(), - configSectionBorderToken: rootStyles.getPropertyValue('--bf-appearance-token-config-page-section-border').trim(), - configSectionBorderWidthToken: rootStyles.getPropertyValue('--bf-appearance-token-config-page-section-border-width').trim(), - configDividerToken: rootStyles.getPropertyValue('--bf-appearance-token-config-page-divider').trim(), - chromeBackgroundToken: rootStyles.getPropertyValue('--bf-appearance-token-chrome-bg-primary').trim(), - chromeTextToken: rootStyles.getPropertyValue('--bf-appearance-token-chrome-text-primary').trim(), + contentBackgroundToken: rootStyles.getPropertyValue('--bf-color-surface-canvas').trim(), + contentTextToken: rootStyles.getPropertyValue('--bf-color-content-primary').trim(), + contentSecondaryTextToken: rootStyles.getPropertyValue('--bf-color-content-secondary').trim(), + contentBorderToken: rootStyles.getPropertyValue('--bf-color-border-subtle').trim(), + contentSurfaceToken: rootStyles.getPropertyValue('--bf-color-surface-subtle').trim(), + configSectionBackgroundToken: rootStyles.getPropertyValue('--bf-component-config-page-section-background').trim(), + configSectionBorderToken: rootStyles.getPropertyValue('--bf-component-config-page-section-border').trim(), + configSectionBorderWidthToken: rootStyles.getPropertyValue('--bf-component-config-page-section-border-width').trim(), + configDividerToken: rootStyles.getPropertyValue('--bf-component-config-page-divider').trim(), + chromeBackgroundToken: navStyles.getPropertyValue('--bf-color-surface-canvas').trim(), + chromeTextToken: navStyles.getPropertyValue('--bf-color-content-primary').trim(), bodyBackground: bodyStyles.backgroundColor, workbenchBackground: workbenchStyles.backgroundColor, navBackground: navStyles.backgroundColor, - navTextToken: navStyles.getPropertyValue('--bf-appearance-token-color-text-primary').trim(), + navTextToken: navStyles.getPropertyValue('--bf-color-content-primary').trim(), settingsTitleColor: window.getComputedStyle(settingsTitle).color, settingsActiveItemColor: window.getComputedStyle(settingsActiveItem).color, settingsSectionBackground: window.getComputedStyle(settingsSectionBody).backgroundColor, @@ -793,9 +793,9 @@ describe('L0 Appearance', () => { settingsSectionShadow: window.getComputedStyle(settingsSectionBody).boxShadow, settingsRowDivider: window.getComputedStyle(settingsRowDivider).borderTopColor, appearanceSelectBorder: window.getComputedStyle(appearanceSelect).borderTopColor, - sceneBarTextToken: sceneBarStyles.getPropertyValue('--bf-appearance-token-color-text-primary').trim(), + sceneBarTextToken: sceneBarStyles.getPropertyValue('--bf-color-content-primary').trim(), viewportBackground: viewportStyles.backgroundColor, - viewportTextToken: viewportStyles.getPropertyValue('--bf-appearance-token-color-text-primary').trim(), + viewportTextToken: viewportStyles.getPropertyValue('--bf-color-content-primary').trim(), viewportRadius: viewportStyles.borderTopLeftRadius, }; }); @@ -925,7 +925,7 @@ describe('L0 Appearance', () => { id: root.getAttribute('data-bf-appearance'), mode: root.getAttribute('data-bf-appearance-mode'), revision: root.getAttribute('data-bf-appearance-revision'), - background: styles.getPropertyValue('--bf-appearance-token-color-bg-primary').trim(), + background: styles.getPropertyValue('--bf-color-surface-canvas').trim(), }; }); diff --git a/tests/e2e/specs/l0-navigation.spec.ts b/tests/e2e/specs/l0-navigation.spec.ts index a03d066fae..223094afc2 100644 --- a/tests/e2e/specs/l0-navigation.spec.ts +++ b/tests/e2e/specs/l0-navigation.spec.ts @@ -311,7 +311,7 @@ describe('L0 Navigation Panel', () => { const cardRect = card.getBoundingClientRect(); const sessionRect = session.getBoundingClientRect(); const selectedBackgroundProbe = document.createElement('span'); - selectedBackgroundProbe.style.backgroundColor = 'var(--bf-appearance-token-element-bg-soft)'; + selectedBackgroundProbe.style.backgroundColor = 'var(--bf-color-action-quiet-hover)'; session.append(selectedBackgroundProbe); const selectedBackground = window.getComputedStyle(selectedBackgroundProbe).backgroundColor; selectedBackgroundProbe.remove(); diff --git a/website/package.json b/website/package.json index 627d8e94b9..afa230c4aa 100644 --- a/website/package.json +++ b/website/package.json @@ -2,6 +2,10 @@ "name": "bitfun-playbook", "private": true, "type": "module", + "dependencies": { + "@bitfun/design-tokens": "workspace:^", + "@bitfun/theme-bitfun": "workspace:^" + }, "scripts": { "build": "node scripts/build.mjs", "dev": "node scripts/serve.mjs --watch --port 4174", diff --git a/website/scripts/build.mjs b/website/scripts/build.mjs index 53fc1b72d4..3f7536f38c 100644 --- a/website/scripts/build.mjs +++ b/website/scripts/build.mjs @@ -1,8 +1,10 @@ #!/usr/bin/env node import { createHash } from 'node:crypto'; +import { execFile } from 'node:child_process'; import { cp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'; import path from 'node:path'; +import { promisify } from 'node:util'; import { fileURLToPath } from 'node:url'; const buildScriptPath = fileURLToPath(import.meta.url); @@ -11,6 +13,18 @@ const repositoryRoot = path.resolve(websiteRoot, '..'); const sourceRoot = path.join(websiteRoot, 'src'); const outputRoot = path.join(websiteRoot, 'dist'); const catalogPath = path.join(repositoryRoot, 'docs/interactive-capabilities/capabilities.json'); +const execFileAsync = promisify(execFile); +const designTokensRoot = path.join(repositoryRoot, 'design-system/packages/design-tokens'); +const themeRoot = path.join(repositoryRoot, 'design-system/packages/theme-bitfun'); + +async function buildThemeContracts() { + await execFileAsync(process.execPath, [path.join(designTokensRoot, 'scripts/build.mjs')], { + cwd: repositoryRoot, + }); + await execFileAsync(process.execPath, [path.join(themeRoot, 'scripts/build.mjs')], { + cwd: repositoryRoot, + }); +} function escapeHtml(value) { return String(value) @@ -18,7 +32,7 @@ function escapeHtml(value) { .replaceAll('<', '<') .replaceAll('>', '>') .replaceAll('"', '"') - .replaceAll("'", '''); + .replaceAll("'", '''); } function embeddedJson(value) { @@ -35,11 +49,16 @@ function renderPage(template, { title, description, url, pageData, assetVersion } async function main() { + await buildThemeContracts(); + const designTokensCssPath = fileURLToPath(import.meta.resolve('@bitfun/design-tokens/tokens.css')); + const themeCssPath = fileURLToPath(import.meta.resolve('@bitfun/theme-bitfun/themes.css')); const catalog = JSON.parse(await readFile(catalogPath, 'utf8')); const template = await readFile(path.join(sourceRoot, 'index.html'), 'utf8'); const appSource = await readFile(path.join(sourceRoot, 'app.js'), 'utf8'); const searchSource = await readFile(path.join(sourceRoot, 'search.js'), 'utf8'); const stylesSource = await readFile(path.join(sourceRoot, 'styles.css'), 'utf8'); + const designTokensSource = await readFile(designTokensCssPath, 'utf8'); + const themeSource = await readFile(themeCssPath, 'utf8'); const buildSource = await readFile(buildScriptPath); const logoPath = path.join(repositoryRoot, 'src/apps/desktop/icons/Logo-ICON.png'); const logoSource = await readFile(logoPath); @@ -56,6 +75,8 @@ async function main() { .update(appSource) .update(searchSource) .update(stylesSource) + .update(designTokensSource) + .update(themeSource) .update(buildSource) .update(logoSource) .update(socialSource) @@ -69,6 +90,8 @@ async function main() { appSource.replace("'./search.js'", `'./search.js?v=${assetVersion}'`), ); await writeFile(path.join(outputRoot, 'assets/search.js'), searchSource); + await writeFile(path.join(outputRoot, 'assets/design-tokens.css'), designTokensSource); + await writeFile(path.join(outputRoot, 'assets/theme.css'), themeSource); await cp(path.join(sourceRoot, 'styles.css'), path.join(outputRoot, 'assets/styles.css')); await cp(logoPath, path.join(outputRoot, 'assets/bitfun.png')); diff --git a/website/scripts/site-ui.test.mjs b/website/scripts/site-ui.test.mjs index be886dbc99..a6fd88d626 100644 --- a/website/scripts/site-ui.test.mjs +++ b/website/scripts/site-ui.test.mjs @@ -38,13 +38,6 @@ function cssBlock(selector) { return match[1]; } -function customProperties(block) { - return Object.fromEntries( - [...block.matchAll(/(--[a-z-]+)\s*:\s*([^;]+);/gu)] - .map(([, key, value]) => [key, value.trim()]), - ); -} - test('theme contract defaults to system and exposes all three choices', () => { assert.match(templateSource, /localStorage\.getItem\('bitfun-playbook-theme'\)/u); assert.match(templateSource, /let theme = 'system'/u); @@ -52,12 +45,12 @@ test('theme contract defaults to system and exposes all three choices', () => { assert.match(appSource, /const THEME_CHOICES = \['system', 'light', 'dark'\]/u); assert.match(appSource, /data-theme-choice="\$\{theme\}"/u); assert.match(appSource, /addEventListener\('change'/u); - assert.match(stylesSource, /html\[data-theme='dark'\]/u); - assert.match(stylesSource, /html\[data-theme='system'\]/u); - - const explicitDark = customProperties(cssBlock("html[data-theme='dark']")); - const systemDark = customProperties(cssBlock("html[data-theme='system']")); - assert.deepEqual(systemDark, explicitDark, 'system-dark tokens must match explicit dark mode'); + assert.match(templateSource, /data-bf-design-system-root/u); + assert.match(templateSource, /root\.dataset\.colorScheme/u); + assert.match(templateSource, /\/assets\/design-tokens\.css/u); + assert.match(templateSource, /\/assets\/theme\.css/u); + assert.match(appSource, /--bf-color-surface-canvas/u); + assert.match(appSource, /documentElement\.dataset\.colorScheme = resolvedTheme\(\)/u); }); test('hero title, search, and statistics remain in layout flow', () => { @@ -136,17 +129,12 @@ test('sidebar navigation preserves its scroll position across page loads', () => assert.match(appSource, /sidebarNav\.querySelector\('\[aria-current="page"\]'\)/u); }); -test('dark mode gives the agent callout its own subdued surface tokens', () => { - const light = customProperties(cssBlock(':root')); - const dark = customProperties(cssBlock("html[data-theme='dark']")); - assert.notEqual(dark['--agent-panel'], light['--agent-panel']); - assert.equal(dark['--agent-panel'], '#20271a'); - assert.match(cssBlock('.detail-aside'), /background:\s*var\(--agent-panel\)/u); - assert.match(cssBlock('.detail-aside'), /color:\s*var\(--agent-panel-ink\)/u); - assert.notEqual(dark['--danger'], light['--danger']); - assert.match(cssBlock('.control-unsupported'), /color:\s*var\(--danger\)/u); - assert.doesNotMatch(cssBlock('.control-unsupported'), /#[0-9a-f]{3,8}/iu); - assert.doesNotMatch(stylesSource, /var\(--lime(?:-ink)?\)/u); +test('callouts and ordinary UI consume canonical semantic color tokens only', () => { + assert.match(cssBlock('.detail-aside'), /background:\s*var\(--bf-color-status-success-surface\)/u); + assert.match(cssBlock('.detail-aside'), /color:\s*var\(--bf-color-status-success-content\)/u); + assert.match(cssBlock('.control-unsupported'), /color:\s*var\(--bf-color-status-danger-content\)/u); + assert.doesNotMatch(stylesSource, /#[0-9a-f]{3,8}\b|rgba?\(|hsla?\(/iu); + assert.doesNotMatch(stylesSource, /var\(--(?:paper|ink|muted|line|panel|accent|danger|shadow)\)/u); }); test('build emits a source-sensitive immutable release id', () => { @@ -155,6 +143,8 @@ test('build emits a source-sensitive immutable release id', () => { assert.equal(release.releaseId, release.assetVersion); assert.match(release.catalogDigest, /^[0-9a-f]{64}$/u); assert.match(builtIndex, new RegExp(`/assets/styles\\.css\\?v=${release.releaseId}`, 'u')); + assert.match(builtIndex, new RegExp(`/assets/design-tokens\\.css\\?v=${release.releaseId}`, 'u')); + assert.match(builtIndex, new RegExp(`/assets/theme\\.css\\?v=${release.releaseId}`, 'u')); assert.match(builtIndex, new RegExp(`/assets/app\\.js\\?v=${release.releaseId}`, 'u')); assert.match(builtApp, new RegExp(`\\./search\\.js\\?v=${release.releaseId}`, 'u')); }); diff --git a/website/src/app.js b/website/src/app.js index 67628dcba7..f60570bf4b 100644 --- a/website/src/app.js +++ b/website/src/app.js @@ -59,7 +59,7 @@ function escapeHtml(value) { .replaceAll('<', '<') .replaceAll('>', '>') .replaceAll('"', '"') - .replaceAll("'", '''); + .replaceAll("'", '''); } function text(zh, en) { @@ -99,6 +99,15 @@ function resolvedTheme(theme = state.theme) { return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; } +function syncThemeColor() { + const surface = getComputedStyle(document.documentElement) + .getPropertyValue('--bf-color-surface-canvas') + .trim(); + if (surface) { + document.querySelector('meta[name="theme-color"]')?.setAttribute('content', surface); + } +} + function syncThemeControls() { document.querySelectorAll('[data-theme-choice]').forEach((button) => { const active = button.dataset.themeChoice === state.theme; @@ -110,10 +119,8 @@ function syncThemeControls() { function applyTheme(theme, persist = true) { state.theme = THEME_CHOICES.includes(theme) ? theme : 'system'; document.documentElement.dataset.theme = state.theme; - document.querySelector('meta[name="theme-color"]')?.setAttribute( - 'content', - resolvedTheme() === 'dark' ? '#131411' : '#f6f5f0', - ); + document.documentElement.dataset.colorScheme = resolvedTheme(); + syncThemeColor(); if (persist) writePreference(THEME_STORAGE_KEY, state.theme); syncThemeControls(); } diff --git a/website/src/index.html b/website/src/index.html index e1abe224c3..1695ae7f66 100644 --- a/website/src/index.html +++ b/website/src/index.html @@ -3,7 +3,7 @@ - + @@ -19,15 +19,20 @@ const stored = localStorage.getItem('bitfun-playbook-theme'); if (['light', 'dark'].includes(stored)) theme = stored; } catch {} - document.documentElement.dataset.theme = theme; + const root = document.documentElement; const dark = theme === 'dark' || (theme === 'system' && matchMedia('(prefers-color-scheme: dark)').matches); - document.querySelector('meta[name="theme-color"]') - ?.setAttribute('content', dark ? '#131411' : '#f6f5f0'); + root.setAttribute('data-bf-design-system-root', ''); + root.dataset.theme = theme; + root.dataset.colorScheme = dark ? 'dark' : 'light'; + root.dataset.contrast = 'standard'; + root.dataset.density = 'comfortable'; })(); + + __PAGE_TITLE__ diff --git a/website/src/styles.css b/website/src/styles.css index c66554e261..42f857aed8 100644 --- a/website/src/styles.css +++ b/website/src/styles.css @@ -1,107 +1,19 @@ :root { - color-scheme: light; - --paper: #f6f5f0; - --ink: #171714; - --muted: #6c6b64; - --line: #dcdad1; - --panel: #fbfaf6; - --accent: #f2663b; - --accent-soft: #f7ded4; - --agent-panel: #bdd663; - --agent-panel-ink: #29380b; - --agent-panel-muted: #667338; - --agent-panel-border: #171714; - --grid-line: rgba(23, 23, 20, 0.035); - --panel-translucent: rgba(251, 250, 246, 0.86); - --surface-hover: rgba(23, 23, 20, 0.06); - --sidebar-link: #4c4b46; - --accent-ink: #7e321c; - --setting-soft: #dfeacf; - --setting-ink: #405616; - --danger: #a7372c; - --kbd-bg: #fff; - --focused-bg: #fff3eb; - --backdrop: rgba(23, 23, 20, 0.38); - --shadow: #171714; - --drawer-shadow: rgba(23, 23, 20, 0.18); - --placeholder: #99978d; - --brand-bg: #171714; - --brand-ink: #f6f5f0; --sans: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif; --mono: 'SFMono-Regular', Consolas, 'Liberation Mono', ui-monospace, monospace; } -html[data-theme='dark'] { - color-scheme: dark; - --paper: #131411; - --ink: #f1efe7; - --muted: #aaa99f; - --line: #36382f; - --panel: #1b1c18; - --accent: #ff7449; - --accent-soft: #48291f; - --agent-panel: #20271a; - --agent-panel-ink: #e3eccb; - --agent-panel-muted: #a4af88; - --agent-panel-border: #52613a; - --grid-line: rgba(241, 239, 231, 0.035); - --panel-translucent: rgba(27, 28, 24, 0.9); - --surface-hover: rgba(241, 239, 231, 0.07); - --sidebar-link: #c8c6bc; - --accent-ink: #ffb79d; - --setting-soft: #314023; - --setting-ink: #d3ec9d; - --danger: #ff9b8e; - --kbd-bg: #252620; - --focused-bg: #3b251d; - --backdrop: rgba(0, 0, 0, 0.62); - --shadow: #050604; - --drawer-shadow: rgba(0, 0, 0, 0.42); - --placeholder: #7f8178; -} - -@media (prefers-color-scheme: dark) { - html[data-theme='system'] { - color-scheme: dark; - --paper: #131411; - --ink: #f1efe7; - --muted: #aaa99f; - --line: #36382f; - --panel: #1b1c18; - --accent: #ff7449; - --accent-soft: #48291f; - --agent-panel: #20271a; - --agent-panel-ink: #e3eccb; - --agent-panel-muted: #a4af88; - --agent-panel-border: #52613a; - --grid-line: rgba(241, 239, 231, 0.035); - --panel-translucent: rgba(27, 28, 24, 0.9); - --surface-hover: rgba(241, 239, 231, 0.07); - --sidebar-link: #c8c6bc; - --accent-ink: #ffb79d; - --setting-soft: #314023; - --setting-ink: #d3ec9d; - --danger: #ff9b8e; - --kbd-bg: #252620; - --focused-bg: #3b251d; - --backdrop: rgba(0, 0, 0, 0.62); - --shadow: #050604; - --drawer-shadow: rgba(0, 0, 0, 0.42); - --placeholder: #7f8178; - } -} - * { box-sizing: border-box; } [hidden] { display: none !important; } html { scroll-behavior: smooth; } body { margin: 0; background: - linear-gradient(var(--grid-line) 1px, transparent 1px), - linear-gradient(90deg, var(--grid-line) 1px, transparent 1px), - var(--paper); + linear-gradient(color-mix(in srgb, var(--bf-color-border-subtle) 45%, transparent) 1px, transparent 1px), + linear-gradient(90deg, color-mix(in srgb, var(--bf-color-border-subtle) 45%, transparent) 1px, transparent 1px), + var(--bf-color-surface-canvas); background-size: 24px 24px; - color: var(--ink); + color: var(--bf-color-content-primary); font-family: var(--sans); -webkit-font-smoothing: antialiased; } @@ -112,7 +24,7 @@ code, kbd, pre { font-family: var(--mono); } .page-shell { min-height: 100vh; } .site-header { width: min(1480px, calc(100% - 40px)); margin-inline: auto; } .docs-shell { width: min(1480px, calc(100% - 40px)); margin-inline: auto; display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: 44px; align-items: start; } -.docs-content { min-width: 0; padding-left: 44px; border-left: 1px solid var(--line); } +.docs-content { min-width: 0; padding-left: 44px; border-left: 1px solid var(--bf-color-border-default); } .docs-content main, .docs-content .site-footer { width: min(100%, 1240px); margin-inline: auto; } .site-header { @@ -120,29 +32,29 @@ code, kbd, pre { font-family: var(--mono); } display: flex; align-items: center; justify-content: space-between; - border-bottom: 1px solid var(--line); + border-bottom: 1px solid var(--bf-color-border-default); } .brand { display: flex; align-items: center; gap: 12px; text-decoration: none; } .brand-mark { width: 40px; height: 40px; display: grid; place-items: center; - border-radius: 11px; background: var(--brand-bg); color: var(--brand-ink); + border-radius: 11px; background: var(--bf-color-action-primary-background); color: var(--bf-color-action-primary-content); font-weight: 700; font-size: 20px; transform: rotate(-4deg); } .brand > span:last-child { display: grid; line-height: 1; gap: 5px; } .brand strong { font-size: 17px; letter-spacing: -0.03em; } -.brand small { font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em; color: var(--muted); } +.brand small { font-family: var(--mono); font-size: 9px; letter-spacing: 0.18em; color: var(--bf-color-content-muted); } .header-actions { display: flex; align-items: center; gap: 22px; } .header-link { font-size: 13px; font-weight: 600; text-decoration: none; } .language-toggle, .copy-button, .sidebar-toggle { - border: 1px solid var(--ink); background: transparent; color: inherit; + border: 1px solid var(--bf-color-content-primary); background: transparent; color: inherit; border-radius: 999px; padding: 8px 13px; cursor: pointer; font-size: 12px; font-weight: 700; } -.language-toggle:hover, .copy-button:hover, .sidebar-toggle:hover { background: var(--ink); color: var(--paper); } +.language-toggle:hover, .copy-button:hover, .sidebar-toggle:hover { background: var(--bf-color-content-primary); color: var(--bf-color-surface-canvas); } .sidebar-toggle { display: none; align-items: center; gap: 7px; } -.theme-control { display: inline-flex; align-items: center; gap: 2px; padding: 3px; border: 1px solid var(--line); border-radius: 999px; background: var(--panel-translucent); } -.theme-control button { display: inline-flex; align-items: center; gap: 5px; min-height: 30px; border: 0; border-radius: 999px; padding: 5px 9px; background: transparent; color: var(--muted); cursor: pointer; font-size: 10px; font-weight: 700; } -.theme-control button:hover { color: var(--ink); } -.theme-control button.active { background: var(--ink); color: var(--paper); } +.theme-control { display: inline-flex; align-items: center; gap: 2px; padding: 3px; border: 1px solid var(--bf-color-border-default); border-radius: 999px; background: var(--bf-color-surface-panel); } +.theme-control button { display: inline-flex; align-items: center; gap: 5px; min-height: 30px; border: 0; border-radius: 999px; padding: 5px 9px; background: transparent; color: var(--bf-color-content-muted); cursor: pointer; font-size: 10px; font-weight: 700; } +.theme-control button:hover { color: var(--bf-color-content-primary); } +.theme-control button.active { background: var(--bf-color-content-primary); color: var(--bf-color-surface-canvas); } .theme-control button > span:first-child { font-size: 13px; line-height: 1; } .docs-sidebar { @@ -151,155 +63,155 @@ code, kbd, pre { font-family: var(--mono); } } .sidebar-mobile-head { display: none; align-items: center; justify-content: space-between; padding: 0 4px 16px; } .sidebar-mobile-head strong { font-size: 14px; } -.sidebar-mobile-head button { width: 34px; height: 34px; border: 1px solid var(--line); border-radius: 9px; background: transparent; cursor: pointer; font-size: 22px; } -.sidebar-search { display: flex; align-items: center; gap: 8px; margin-bottom: 18px; padding: 9px 11px; border: 1px solid var(--line); border-radius: 10px; background: var(--panel-translucent); } -.sidebar-search:focus-within { border-color: var(--ink); box-shadow: 2px 2px 0 var(--shadow); } -.sidebar-search > span { color: var(--accent); font-size: 18px; transform: rotate(-14deg); } -.sidebar-search input { width: 100%; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--ink); font-size: 12px; } +.sidebar-mobile-head button { width: 34px; height: 34px; border: 1px solid var(--bf-color-border-default); border-radius: 9px; background: transparent; cursor: pointer; font-size: 22px; } +.sidebar-search { display: flex; align-items: center; gap: 8px; margin-bottom: 18px; padding: 9px 11px; border: 1px solid var(--bf-color-border-default); border-radius: 10px; background: var(--bf-color-surface-panel); } +.sidebar-search:focus-within { border-color: var(--bf-color-field-border-focus); box-shadow: var(--bf-shadow-xs); } +.sidebar-search > span { color: var(--bf-color-accent-default); font-size: 18px; transform: rotate(-14deg); } +.sidebar-search input { width: 100%; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--bf-color-content-primary); font-size: 12px; } .docs-sidebar nav { min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding-right: 8px; scrollbar-width: thin; } .sidebar-home, .sidebar-links a { display: flex; align-items: center; text-decoration: none; border-radius: 8px; } -.sidebar-home { gap: 8px; margin-bottom: 22px; padding: 9px 10px; color: var(--muted); font-size: 12px; font-weight: 650; } -.sidebar-home:hover, .sidebar-home.active { background: var(--ink); color: var(--paper); } +.sidebar-home { gap: 8px; margin-bottom: 22px; padding: 9px 10px; color: var(--bf-color-content-muted); font-size: 12px; font-weight: 650; } +.sidebar-home:hover, .sidebar-home.active { background: var(--bf-color-content-primary); color: var(--bf-color-surface-canvas); } .sidebar-section + .sidebar-section { margin-top: 28px; } -.sidebar-kind-heading { display: flex; align-items: center; justify-content: space-between; padding: 0 8px 12px; border-bottom: 1px solid var(--line); } +.sidebar-kind-heading { display: flex; align-items: center; justify-content: space-between; padding: 0 8px 12px; border-bottom: 1px solid var(--bf-color-border-default); } .sidebar-kind-heading h2 { margin: 0; font: 700 11px/1 var(--mono); letter-spacing: 0.12em; text-transform: uppercase; } -.sidebar-kind-heading span { color: var(--muted); font: 500 10px/1 var(--mono); } +.sidebar-kind-heading span { color: var(--bf-color-content-muted); font: 500 10px/1 var(--mono); } .sidebar-group { margin-top: 18px; } -.sidebar-group h3 { margin: 0 8px 7px; color: var(--muted); font-size: 10px; font-weight: 650; letter-spacing: 0.04em; } +.sidebar-group h3 { margin: 0 8px 7px; color: var(--bf-color-content-muted); font-size: 10px; font-weight: 650; letter-spacing: 0.04em; } .sidebar-links { display: grid; gap: 2px; } -.sidebar-links a { min-height: 32px; padding: 7px 9px; color: var(--sidebar-link); font-size: 12px; line-height: 1.45; } -.sidebar-links a:hover { background: var(--surface-hover); color: var(--ink); } -.sidebar-links a.active { position: relative; background: var(--accent-soft); color: var(--accent-ink); font-weight: 750; } -.sidebar-links a.active::before { content: ''; position: absolute; left: 0; width: 3px; height: 16px; border-radius: 99px; background: var(--accent); } -.sidebar-empty { padding: 24px 8px; color: var(--muted); font-size: 12px; line-height: 1.6; } +.sidebar-links a { min-height: 32px; padding: 7px 9px; color: var(--bf-color-content-secondary); font-size: 12px; line-height: 1.45; } +.sidebar-links a:hover { background: var(--bf-color-action-quiet-hover); color: var(--bf-color-content-primary); } +.sidebar-links a.active { position: relative; background: var(--bf-color-status-info-surface); color: var(--bf-color-accent-default); font-weight: 750; } +.sidebar-links a.active::before { content: ''; position: absolute; left: 0; width: 3px; height: 16px; border-radius: 99px; background: var(--bf-color-accent-default); } +.sidebar-empty { padding: 24px 8px; color: var(--bf-color-content-muted); font-size: 12px; line-height: 1.6; } .sidebar-backdrop { display: none; } .hero { padding: 88px 0 78px; } .eyebrow, .section-label { - margin: 0 0 20px; font: 500 11px/1 var(--mono); letter-spacing: 0.12em; color: var(--muted); + margin: 0 0 20px; font: 500 11px/1 var(--mono); letter-spacing: 0.12em; color: var(--bf-color-content-muted); } .hero h1 { display: grid; gap: clamp(8px, 1.1vw, 16px); max-width: 940px; margin: 0; font-size: clamp(52px, 6.4vw, 96px); line-height: 0.94; letter-spacing: -0.065em; font-weight: 600; } .hero h1 > span, .hero h1 em { display: block; } -.hero h1 em { font-family: Georgia, 'Songti SC', 'STSong', serif; font-weight: 400; line-height: 1.03; letter-spacing: -0.045em; color: var(--accent); } -.hero-copy { max-width: 650px; margin: 34px 0 38px; font-size: 18px; line-height: 1.7; color: var(--muted); } +.hero h1 em { font-family: Georgia, 'Songti SC', 'STSong', serif; font-weight: 400; line-height: 1.03; letter-spacing: -0.045em; color: var(--bf-color-accent-default); } +.hero-copy { max-width: 650px; margin: 34px 0 38px; font-size: 18px; line-height: 1.7; color: var(--bf-color-content-muted); } .hero-actions { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: end; gap: clamp(24px, 3vw, 44px); } .search-box { width: 100%; min-width: 0; height: 68px; display: flex; align-items: center; gap: 14px; - padding: 0 18px 0 22px; border: 1px solid var(--ink); border-radius: 16px; - background: var(--panel); box-shadow: 6px 6px 0 var(--shadow); + padding: 0 18px 0 22px; border: 1px solid var(--bf-color-content-primary); border-radius: 16px; + background: var(--bf-color-surface-panel); box-shadow: var(--bf-shadow-lg); } -.search-box:focus-within { box-shadow: 6px 6px 0 var(--accent); } +.search-box:focus-within { border-color: var(--bf-color-field-border-focus); box-shadow: var(--bf-shadow-accent-glow); } .search-glyph { font-size: 29px; transform: rotate(-15deg); } -.search-box input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; font-size: 17px; color: var(--ink); } -.search-box input::placeholder { color: var(--placeholder); } -.search-box kbd { border: 1px solid var(--line); border-radius: 6px; padding: 5px 7px; background: var(--kbd-bg); color: var(--muted); font-size: 11px; } +.search-box input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; font-size: 17px; color: var(--bf-color-content-primary); } +.search-box input::placeholder { color: var(--bf-color-content-disabled); } +.search-box kbd { border: 1px solid var(--bf-color-border-default); border-radius: 6px; padding: 5px 7px; background: var(--bf-color-key-hint-background); color: var(--bf-color-content-muted); font-size: 11px; } .hero-stat { display: flex; align-items: baseline; justify-self: end; gap: 9px; padding: 0 2px 7px 0; white-space: nowrap; transform: rotate(-1deg); } -.hero-stat strong { font: 500 38px/1 var(--mono); color: var(--accent); } -.hero-stat span { font-size: 11px; line-height: 1.35; color: var(--muted); } -.hero-stat i { width: 1px; height: 30px; margin: 0 7px; background: var(--line); transform: rotate(8deg); } +.hero-stat strong { font: 500 38px/1 var(--mono); color: var(--bf-color-accent-default); } +.hero-stat span { font-size: 11px; line-height: 1.35; color: var(--bf-color-content-muted); } +.hero-stat i { width: 1px; height: 30px; margin: 0 7px; background: var(--bf-color-border-default); transform: rotate(8deg); } -.catalog-section { border-top: 1px solid var(--line); padding: 56px 0 96px; } +.catalog-section { border-top: 1px solid var(--bf-color-border-default); padding: 56px 0 96px; } .catalog-toolbar { display: flex; align-items: end; justify-content: space-between; gap: 24px; margin-bottom: 28px; } .catalog-toolbar .section-label { margin-bottom: 10px; } .catalog-toolbar h2 { margin: 0; font-size: 34px; letter-spacing: -0.045em; } -.catalog-toolbar > p { margin: 0; color: var(--muted); font-size: 13px; } -.kind-switch { display: inline-flex; gap: 4px; padding: 4px; margin-bottom: 18px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel-translucent); } +.catalog-toolbar > p { margin: 0; color: var(--bf-color-content-muted); font-size: 13px; } +.kind-switch { display: inline-flex; gap: 4px; padding: 4px; margin-bottom: 18px; border: 1px solid var(--bf-color-border-default); border-radius: 12px; background: var(--bf-color-surface-panel); } .kind-switch button { - border: 0; border-radius: 8px; padding: 10px 16px; background: transparent; color: var(--muted); + border: 0; border-radius: 8px; padding: 10px 16px; background: transparent; color: var(--bf-color-content-muted); cursor: pointer; font-size: 13px; font-weight: 600; } .kind-switch button span { margin-left: 5px; font: 500 10px/1 var(--mono); } -.kind-switch button.active { background: var(--ink); color: var(--paper); } +.kind-switch button.active { background: var(--bf-color-content-primary); color: var(--bf-color-surface-canvas); } .category-rail { display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 14px; scrollbar-width: thin; } .category-pill { - flex: 0 0 auto; border: 1px solid var(--line); border-radius: 999px; background: var(--panel); - padding: 9px 13px; color: var(--muted); cursor: pointer; font-size: 12px; + flex: 0 0 auto; border: 1px solid var(--bf-color-border-default); border-radius: 999px; background: var(--bf-color-surface-panel); + padding: 9px 13px; color: var(--bf-color-content-muted); cursor: pointer; font-size: 12px; } .category-pill span { margin-left: 5px; font-family: var(--mono); font-size: 10px; } -.category-pill.active, .category-pill:hover { border-color: var(--ink); background: var(--ink); color: var(--paper); } +.category-pill.active, .category-pill:hover { border-color: var(--bf-color-content-primary); background: var(--bf-color-content-primary); color: var(--bf-color-surface-canvas); } .capability-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 20px; } .capability-card { - min-height: 260px; display: flex; flex-direction: column; padding: 22px; border: 1px solid var(--line); - border-radius: 14px; background: var(--panel-translucent); text-decoration: none; + min-height: 260px; display: flex; flex-direction: column; padding: 22px; border: 1px solid var(--bf-color-border-default); + border-radius: 14px; background: var(--bf-color-surface-panel); text-decoration: none; transition: transform 160ms ease, border-color 160ms ease, box-shadow 160ms ease; } -.capability-card:hover { transform: translateY(-3px); border-color: var(--ink); box-shadow: 4px 4px 0 var(--shadow); } -.card-topline { display: flex; align-items: center; gap: 9px; color: var(--muted); font-size: 10px; letter-spacing: 0.04em; } -.kind-badge { display: inline-flex; align-items: center; width: fit-content; border-radius: 5px; padding: 5px 7px; background: var(--accent-soft); color: var(--accent-ink); font: 700 10px/1 var(--mono); } -.kind-setting .kind-badge { background: var(--setting-soft); color: var(--setting-ink); } +.capability-card:hover { transform: translateY(-3px); border-color: var(--bf-color-border-strong); box-shadow: var(--bf-shadow-base); } +.card-topline { display: flex; align-items: center; gap: 9px; color: var(--bf-color-content-muted); font-size: 10px; letter-spacing: 0.04em; } +.kind-badge { display: inline-flex; align-items: center; width: fit-content; border-radius: 5px; padding: 5px 7px; background: var(--bf-color-status-info-surface); color: var(--bf-color-accent-default); font: 700 10px/1 var(--mono); } +.kind-setting .kind-badge { background: var(--bf-color-status-warning-surface); color: var(--bf-color-status-warning-content); } .category-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .capability-card strong { margin-top: 28px; font-size: 21px; line-height: 1.3; letter-spacing: -0.03em; } -.secondary-title { margin-top: 5px; color: var(--muted); font-size: 12px; } -.capability-card > p { margin: 18px 0 24px; color: var(--muted); font-size: 13px; line-height: 1.65; } -.matched-item { display: flex; align-items: flex-start; gap: 8px; margin: -8px 0 18px; padding: 10px; border-radius: 8px; background: var(--accent-soft); color: var(--accent-ink); font-size: 11px; line-height: 1.45; } +.secondary-title { margin-top: 5px; color: var(--bf-color-content-muted); font-size: 12px; } +.capability-card > p { margin: 18px 0 24px; color: var(--bf-color-content-muted); font-size: 13px; line-height: 1.65; } +.matched-item { display: flex; align-items: flex-start; gap: 8px; margin: -8px 0 18px; padding: 10px; border-radius: 8px; background: var(--bf-color-status-info-surface); color: var(--bf-color-accent-default); font-size: 11px; line-height: 1.45; } .matched-item i { flex: 0 0 auto; font: 700 9px/1.5 var(--mono); font-style: normal; letter-spacing: 0.05em; text-transform: uppercase; } -.card-link { margin-top: auto; padding-top: 15px; border-top: 1px solid var(--line); font-size: 12px; font-weight: 700; } -.card-link span { float: right; color: var(--accent); } -.empty-state { grid-column: 1 / -1; text-align: center; padding: 80px 20px; border: 1px dashed var(--line); border-radius: 14px; } -.empty-state > span { font-size: 50px; color: var(--accent); } +.card-link { margin-top: auto; padding-top: 15px; border-top: 1px solid var(--bf-color-border-default); font-size: 12px; font-weight: 700; } +.card-link span { float: right; color: var(--bf-color-accent-default); } +.empty-state { grid-column: 1 / -1; text-align: center; padding: 80px 20px; border: 1px dashed var(--bf-color-border-default); border-radius: 14px; } +.empty-state > span { font-size: 50px; color: var(--bf-color-accent-default); } .empty-state h3 { margin: 14px 0 6px; } -.empty-state p, .result-note { color: var(--muted); } +.empty-state p, .result-note { color: var(--bf-color-content-muted); } .result-note { text-align: center; margin-top: 26px; font-size: 12px; } -.breadcrumb { display: flex; gap: 10px; padding-top: 40px; color: var(--muted); font-size: 12px; } -.breadcrumb a { text-decoration: none; border-bottom: 1px solid var(--line); } +.breadcrumb { display: flex; gap: 10px; padding-top: 40px; color: var(--bf-color-content-muted); font-size: 12px; } +.breadcrumb a { text-decoration: none; border-bottom: 1px solid var(--bf-color-border-default); } .detail-layout { display: grid; grid-template-columns: minmax(0, 760px) minmax(260px, 1fr); gap: 96px; padding: 80px 0 100px; } -.detail-category { display: flex; align-items: center; gap: 9px; color: var(--muted); font-size: 12px; } +.detail-category { display: flex; align-items: center; gap: 9px; color: var(--bf-color-content-muted); font-size: 12px; } .detail-main > h1 { margin: 20px 0 4px; font-size: clamp(44px, 6vw, 78px); line-height: 0.98; letter-spacing: -0.065em; } -.detail-alt-title { margin: 0; color: var(--accent); font-family: Georgia, serif; font-size: 28px; } -.detail-summary { margin: 32px 0; max-width: 700px; color: var(--muted); font-size: 18px; line-height: 1.75; } -.entry-callout { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-top: 34px; padding: 18px 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); } -.entry-callout span { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; } +.detail-alt-title { margin: 0; color: var(--bf-color-accent-default); font-family: Georgia, serif; font-size: 28px; } +.detail-summary { margin: 32px 0; max-width: 700px; color: var(--bf-color-content-muted); font-size: 18px; line-height: 1.75; } +.entry-callout { display: flex; align-items: center; justify-content: space-between; gap: 20px; margin-top: 34px; padding: 18px 20px; border: 1px solid var(--bf-color-border-default); border-radius: 12px; background: var(--bf-color-surface-panel); } +.entry-callout span { color: var(--bf-color-content-muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; } .entry-callout strong { font-size: 13px; text-align: right; } -.content-section { padding-top: 64px; margin-top: 64px; border-top: 1px solid var(--line); } +.content-section { padding-top: 64px; margin-top: 64px; border-top: 1px solid var(--bf-color-border-default); } .content-section .section-label { margin-bottom: 10px; } .content-section h2, .detail-aside h2 { margin: 0 0 24px; font-size: 28px; letter-spacing: -0.04em; } .highlight-list { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; padding: 0; list-style: none; } -.highlight-list li { display: flex; align-items: start; gap: 12px; min-height: 82px; padding: 18px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); font-size: 14px; line-height: 1.55; scroll-margin-top: 32px; } -.highlight-list li span { color: var(--accent); font-weight: 800; } +.highlight-list li { display: flex; align-items: start; gap: 12px; min-height: 82px; padding: 18px; border: 1px solid var(--bf-color-border-default); border-radius: 12px; background: var(--bf-color-surface-panel); font-size: 14px; line-height: 1.55; scroll-margin-top: 32px; } +.highlight-list li span { color: var(--bf-color-accent-default); font-weight: 800; } .inventory-list li > div { display: grid; gap: 7px; } -.inventory-list li small { color: var(--muted); font-family: Georgia, serif; font-size: 12px; line-height: 1.45; } -.control-badge { width: fit-content; padding: 4px 6px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); font: 700 9px/1 var(--mono); font-style: normal; letter-spacing: 0.02em; } -.control-direct { border-color: var(--accent); background: var(--accent-soft); color: var(--accent-ink); } -.control-delegate { background: var(--setting-soft); color: var(--setting-ink); } -.control-unsupported { border-color: var(--danger); color: var(--danger); } -.inventory-list li.focused { border-color: var(--accent); background: var(--focused-bg); box-shadow: 4px 4px 0 var(--accent); animation: focus-pulse 1.4s ease-out 1; } +.inventory-list li small { color: var(--bf-color-content-muted); font-family: Georgia, serif; font-size: 12px; line-height: 1.45; } +.control-badge { width: fit-content; padding: 4px 6px; border: 1px solid var(--bf-color-border-default); border-radius: 999px; color: var(--bf-color-content-muted); font: 700 9px/1 var(--mono); font-style: normal; letter-spacing: 0.02em; } +.control-direct { border-color: var(--bf-color-accent-default); background: var(--bf-color-status-info-surface); color: var(--bf-color-accent-default); } +.control-delegate { background: var(--bf-color-status-warning-surface); color: var(--bf-color-status-warning-content); } +.control-unsupported { border-color: var(--bf-color-status-danger-content); color: var(--bf-color-status-danger-content); } +.inventory-list li.focused { border-color: var(--bf-color-accent-default); background: var(--bf-color-status-info-surface); box-shadow: var(--bf-shadow-accent-glow); animation: focus-pulse 1.4s ease-out 1; } @keyframes focus-pulse { 0% { transform: scale(0.985); } 45% { transform: scale(1.012); } 100% { transform: scale(1); } } .step-list { display: grid; gap: 0; margin: 0; padding: 0; list-style: none; } -.step-list li { display: grid; grid-template-columns: 42px 1fr; align-items: center; gap: 14px; padding: 18px 0; border-bottom: 1px solid var(--line); } -.step-list li > span { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 50%; background: var(--ink); color: var(--paper); font: 600 12px/1 var(--mono); } +.step-list li { display: grid; grid-template-columns: 42px 1fr; align-items: center; gap: 14px; padding: 18px 0; border-bottom: 1px solid var(--bf-color-border-default); } +.step-list li > span { width: 34px; height: 34px; display: grid; place-items: center; border-radius: 50%; background: var(--bf-color-content-primary); color: var(--bf-color-surface-canvas); font: 600 12px/1 var(--mono); } .step-list p { margin: 0; font-size: 15px; line-height: 1.6; } -.manual-empty { padding: 22px; border: 1px dashed var(--line); border-radius: 12px; color: var(--muted); font-size: 14px; line-height: 1.65; } +.manual-empty { padding: 22px; border: 1px dashed var(--bf-color-border-default); border-radius: 12px; color: var(--bf-color-content-muted); font-size: 14px; line-height: 1.65; } .operation-list { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } -.operation-list article { padding: 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); } -.operation-list code, .option-table code { color: var(--accent); font-size: 10px; } +.operation-list article { padding: 20px; border: 1px solid var(--bf-color-border-default); border-radius: 12px; background: var(--bf-color-surface-panel); } +.operation-list code, .option-table code { color: var(--bf-color-accent-default); font-size: 10px; } .operation-list h3, .option-table h3 { margin: 15px 0 7px; font-size: 15px; } -.operation-list p, .option-table p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.6; } -.option-table { border: 1px solid var(--line); border-radius: 12px; overflow: hidden; } -.option-table article { display: grid; grid-template-columns: minmax(150px, 0.8fr) minmax(220px, 1.4fr) 130px; align-items: center; gap: 20px; padding: 18px; background: var(--panel); } -.option-table article + article { border-top: 1px solid var(--line); } +.operation-list p, .option-table p { margin: 0; color: var(--bf-color-content-muted); font-size: 13px; line-height: 1.6; } +.option-table { border: 1px solid var(--bf-color-border-default); border-radius: 12px; overflow: hidden; } +.option-table article { display: grid; grid-template-columns: minmax(150px, 0.8fr) minmax(220px, 1.4fr) 130px; align-items: center; gap: 20px; padding: 18px; background: var(--bf-color-surface-panel); } +.option-table article + article { border-top: 1px solid var(--bf-color-border-default); } .option-table h3 { margin: 0 0 7px; } -.option-table article > span { justify-self: end; padding: 6px 8px; border-radius: 6px; background: var(--paper); color: var(--muted); font: 500 10px/1.3 var(--mono); text-align: right; } +.option-table article > span { justify-self: end; padding: 6px 8px; border-radius: 6px; background: var(--bf-color-surface-canvas); color: var(--bf-color-content-muted); font: 500 10px/1.3 var(--mono); text-align: right; } .prompt-list { display: grid; gap: 9px; } -.prompt-list button { display: flex; align-items: center; justify-content: space-between; gap: 18px; width: 100%; padding: 18px 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); color: var(--ink); cursor: pointer; text-align: left; } -.prompt-list button:hover { border-color: var(--ink); box-shadow: 3px 3px 0 var(--shadow); } +.prompt-list button { display: flex; align-items: center; justify-content: space-between; gap: 18px; width: 100%; padding: 18px 20px; border: 1px solid var(--bf-color-border-default); border-radius: 12px; background: var(--bf-color-surface-panel); color: var(--bf-color-content-primary); cursor: pointer; text-align: left; } +.prompt-list button:hover { border-color: var(--bf-color-border-strong); box-shadow: var(--bf-shadow-sm); } .prompt-list span { font-size: 14px; line-height: 1.5; } -.prompt-list small { color: var(--muted); font: 600 10px/1 var(--mono); text-transform: uppercase; } -.detail-aside { position: sticky; top: 40px; align-self: start; padding: 28px; border: 1px solid var(--agent-panel-border); border-radius: 16px; background: var(--agent-panel); color: var(--agent-panel-ink); box-shadow: 7px 7px 0 var(--shadow); transform: rotate(1deg); } +.prompt-list small { color: var(--bf-color-content-muted); font: 600 10px/1 var(--mono); text-transform: uppercase; } +.detail-aside { position: sticky; top: 40px; align-self: start; padding: 28px; border: 1px solid var(--bf-color-status-success-border); border-radius: 16px; background: var(--bf-color-status-success-surface); color: var(--bf-color-status-success-content); box-shadow: var(--bf-shadow-xl); transform: rotate(1deg); } .detail-aside ol { padding-left: 20px; font-size: 13px; line-height: 1.7; } .detail-aside li + li { margin-top: 10px; } -.manual-aside .section-label { color: var(--agent-panel-muted); } -.manual-aside > p:not(.section-label) { color: var(--agent-panel-ink); font-size: 14px; line-height: 1.65; } -.manual-aside .copy-button { width: 100%; margin-top: 18px; border-color: var(--agent-panel-ink); color: var(--agent-panel-ink); } -.manual-aside .copy-button:hover { background: var(--agent-panel-ink); color: var(--agent-panel); } -.back-link { display: block; margin-top: 18px; color: var(--agent-panel-ink); font-size: 12px; text-align: center; } -.site-footer { min-height: 100px; display: flex; justify-content: space-between; align-items: center; border-top: 1px solid var(--line); color: var(--muted); font-size: 11px; } +.manual-aside .section-label { color: var(--bf-color-status-success-content); } +.manual-aside > p:not(.section-label) { color: var(--bf-color-status-success-content); font-size: 14px; line-height: 1.65; } +.manual-aside .copy-button { width: 100%; margin-top: 18px; border-color: var(--bf-color-status-success-content); color: var(--bf-color-status-success-content); } +.manual-aside .copy-button:hover { background: var(--bf-color-status-success-content); color: var(--bf-color-status-success-surface); } +.back-link { display: block; margin-top: 18px; color: var(--bf-color-status-success-content); font-size: 12px; text-align: center; } +.site-footer { min-height: 100px; display: flex; justify-content: space-between; align-items: center; border-top: 1px solid var(--bf-color-border-default); color: var(--bf-color-content-muted); font-size: 11px; } .site-footer code { font-size: 10px; } .loading-shell, .fatal-error { min-height: 100vh; display: grid; place-content: center; justify-items: center; gap: 16px; } -.loading-mark { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 14px; background: var(--ink); color: var(--paper); font-size: 26px; font-weight: 700; } +.loading-mark { width: 52px; height: 52px; display: grid; place-items: center; border-radius: 14px; background: var(--bf-color-content-primary); color: var(--bf-color-surface-canvas); font-size: 26px; font-weight: 700; } /* The persistent desktop contents rail leaves less room than the viewport width suggests. Stack before the stats' intrinsic width can overflow. */ @@ -322,12 +234,12 @@ code, kbd, pre { font-family: var(--mono); } .sidebar-toggle { display: inline-flex; } .docs-sidebar { position: fixed; inset: 0 auto 0 0; z-index: 80; width: min(340px, calc(100vw - 44px)); height: 100dvh; min-height: 0; - padding: 18px 14px 24px 18px; border-right: 1px solid var(--ink); background: var(--paper); - box-shadow: 12px 0 0 var(--drawer-shadow); transform: translateX(calc(-100% - 18px)); + padding: 18px 14px 24px 18px; border-right: 1px solid var(--bf-color-content-primary); background: var(--bf-color-surface-canvas); + box-shadow: var(--bf-shadow-overlay); transform: translateX(calc(-100% - 18px)); transition: transform 180ms cubic-bezier(0.23, 1, 0.32, 1); } .sidebar-mobile-head { display: flex; } - .sidebar-backdrop { position: fixed; inset: 0; z-index: 70; width: 100%; height: 100%; border: 0; background: var(--backdrop); opacity: 0; pointer-events: none; transition: opacity 180ms ease; } + .sidebar-backdrop { position: fixed; inset: 0; z-index: 70; width: 100%; height: 100%; border: 0; background: var(--bf-color-overlay-scrim); opacity: 0; pointer-events: none; transition: opacity 180ms ease; } body.sidebar-open { overflow: hidden; } body.sidebar-open .docs-sidebar { transform: translateX(0); } body.sidebar-open .sidebar-backdrop { display: block; opacity: 1; pointer-events: auto; } @@ -352,7 +264,7 @@ code, kbd, pre { font-family: var(--mono); } .hero-copy { font-size: 15px; } .hero-stat { flex-wrap: wrap; gap: 7px 9px; } .hero-stat i { display: none; } - .search-box { height: 60px; padding-inline: 15px; box-shadow: 4px 4px 0 var(--shadow); } + .search-box { height: 60px; padding-inline: 15px; box-shadow: var(--bf-shadow-base); } .search-box kbd { display: none; } .catalog-toolbar { align-items: start; flex-direction: column; } .kind-switch { display: flex; width: 100%; }