界面风格

This commit is contained in:
tianmo committed 2026-11-09 18:40:13 +08:00
1 parent 7ce5ad3166
commit 3e42f940d1
36 files changed
+333 -48

No files matched your search

+16 -1
View File
@@ -10,6 +10,9 @@ const SYSTEM_SETTINGS_CACHE_KEY = 'SpineParticle.SystemSettings.v1'
export type SystemSettingsState = Pick<SettingsState,
| 'uiTheme'
| 'canvasColorMode'
| 'canvasBackgroundColor'
| 'canvasGridColor'
| 'parameterPanelOnRight'
| 'floatingMenuEnabled'
| 'undoLimit'
@@ -42,6 +45,9 @@ function clamp(value: unknown, min: number, max: number, fallback: number) {
export function captureSystemSettings(settings: SettingsState): SystemSettingsState {
return {
uiTheme: settings.uiTheme,
canvasColorMode: settings.canvasColorMode,
canvasBackgroundColor: settings.canvasBackgroundColor,
canvasGridColor: settings.canvasGridColor,
parameterPanelOnRight: settings.parameterPanelOnRight,
floatingMenuEnabled: settings.floatingMenuEnabled,
undoLimit: settings.undoLimit,
@@ -67,11 +73,20 @@ function normalizedSystemSettings(value: Partial<SystemSettingsState>, current:
const axisColor = typeof value.axisColor === 'string' && /^#[0-9a-f]{6}$/i.test(value.axisColor)
? value.axisColor
: current.axisColor
const uiTheme = value.uiTheme === 'gray-white' || value.uiTheme === 'deep-blue'
const uiTheme = value.uiTheme === 'gray-white'
|| value.uiTheme === 'deep-blue'
|| value.uiTheme === 'light'
|| value.uiTheme === 'dark'
? value.uiTheme
: current.uiTheme
const canvasColorMode = value.canvasColorMode === 'custom' ? 'custom' : 'theme'
const colorValue = (color: unknown, fallback: string) =>
typeof color === 'string' && /^#[0-9a-f]{6}$/i.test(color) ? color : fallback
return {
uiTheme,
canvasColorMode,
canvasBackgroundColor: colorValue(value.canvasBackgroundColor, current.canvasBackgroundColor),
canvasGridColor: colorValue(value.canvasGridColor, current.canvasGridColor),
parameterPanelOnRight: booleanValue('parameterPanelOnRight'),
floatingMenuEnabled: booleanValue('floatingMenuEnabled'),
undoLimit: Math.round(clamp(value.undoLimit, 1, 200, current.undoLimit)),
+7
View File
@@ -98,6 +98,13 @@
"interfaceStyle": "Oberflächenstil",
"deepBlueStyle": "Dunkelblau",
"grayWhiteStyle": "Grauweiß",
"lightStyle": "Hell",
"darkStyle": "Dunkel",
"colorSource": "Farbquelle",
"followInterfaceStyle": "Wie Oberflächenstil",
"customColors": "Benutzerdefiniert",
"canvasBackgroundColor": "Canvas-Hintergrund",
"canvasGridColor": "Schachbrettfarbe",
"layout": "Schnittstellenlayout",
"floatingMenu": "Schwebendes Menü",
"floatingMenuParticleOnly": "Wähle zuerst ein Partikelsystem",
+7
View File
@@ -110,6 +110,13 @@
"interfaceStyle": "Interface style",
"deepBlueStyle": "Deep blue",
"grayWhiteStyle": "Gray white",
"lightStyle": "Light",
"darkStyle": "Dark",
"colorSource": "Color source",
"followInterfaceStyle": "Follow interface style",
"customColors": "Custom",
"canvasBackgroundColor": "Canvas background",
"canvasGridColor": "Checkerboard color",
"layout": "Layout",
"floatingMenu": "Floating menu",
"floatingMenuParticleOnly": "Select a particle system first",
+7
View File
@@ -98,6 +98,13 @@
"interfaceStyle": "Estilo de la interfaz",
"deepBlueStyle": "Azul oscuro",
"grayWhiteStyle": "Gris claro",
"lightStyle": "Claro",
"darkStyle": "Oscuro",
"colorSource": "Origen de colores",
"followInterfaceStyle": "Seguir estilo de la interfaz",
"customColors": "Personalizados",
"canvasBackgroundColor": "Fondo del lienzo",
"canvasGridColor": "Color del damero",
"layout": "Diseño de interfaz",
"floatingMenu": "Menú flotante",
"floatingMenuParticleOnly": "Selecciona primero un sistema de partículas",
+7
View File
@@ -98,6 +98,13 @@
"interfaceStyle": "Style de l’interface",
"deepBlueStyle": "Bleu profond",
"grayWhiteStyle": "Gris clair",
"lightStyle": "Clair",
"darkStyle": "Sombre",
"colorSource": "Source des couleurs",
"followInterfaceStyle": "Suivre le style de l’interface",
"customColors": "Personnalisées",
"canvasBackgroundColor": "Fond du canevas",
"canvasGridColor": "Couleur du damier",
"layout": "Disposition de l'interface",
"floatingMenu": "Menu flottant",
"floatingMenuParticleOnly": "Sélectionnez d'abord un système de particules",
+7
View File
@@ -98,6 +98,13 @@
"interfaceStyle": "インターフェーススタイル",
"deepBlueStyle": "ディープブルー",
"grayWhiteStyle": "グレーホワイト",
"lightStyle": "ライト",
"darkStyle": "ダーク",
"colorSource": "カラーソース",
"followInterfaceStyle": "インターフェーススタイルに合わせる",
"customColors": "カスタム",
"canvasBackgroundColor": "キャンバス背景色",
"canvasGridColor": "チェッカー色",
"layout": "インターフェースのレイアウト",
"floatingMenu": "フローティングメニュー",
"floatingMenuParticleOnly": "先にパーティクルシステムを選択してください",
+7
View File
@@ -98,6 +98,13 @@
"interfaceStyle": "인터페이스 스타일",
"deepBlueStyle": "딥 블루",
"grayWhiteStyle": "그레이 화이트",
"lightStyle": "라이트",
"darkStyle": "다크",
"colorSource": "색상 소스",
"followInterfaceStyle": "인터페이스 스타일 따르기",
"customColors": "사용자 지정",
"canvasBackgroundColor": "캔버스 배경색",
"canvasGridColor": "체커 색상",
"layout": "인터페이스 레이아웃",
"floatingMenu": "플로팅 메뉴",
"floatingMenuParticleOnly": "먼저 파티클 시스템을 선택하세요",
+7
View File
@@ -98,6 +98,13 @@
"interfaceStyle": "Estilo da interface",
"deepBlueStyle": "Azul escuro",
"grayWhiteStyle": "Cinza claro",
"lightStyle": "Claro",
"darkStyle": "Escuro",
"colorSource": "Origem das cores",
"followInterfaceStyle": "Seguir estilo da interface",
"customColors": "Personalizadas",
"canvasBackgroundColor": "Fundo da tela",
"canvasGridColor": "Cor do xadrez",
"layout": "Layout da interface",
"floatingMenu": "Menu flutuante",
"floatingMenuParticleOnly": "Selecione primeiro um sistema de partículas",
+7
View File
@@ -110,6 +110,13 @@
"interfaceStyle": "Стиль интерфейса",
"deepBlueStyle": "Тёмно-синий",
"grayWhiteStyle": "Серо-белый",
"lightStyle": "Светлый",
"darkStyle": "Тёмный",
"colorSource": "Источник цвета",
"followInterfaceStyle": "Как стиль интерфейса",
"customColors": "Свои цвета",
"canvasBackgroundColor": "Фон холста",
"canvasGridColor": "Цвет шахматной сетки",
"layout": "Расположение интерфейса",
"floatingMenu": "Плавающее меню",
"floatingMenuParticleOnly": "Сначала выберите систему частиц",
+7
View File
@@ -110,6 +110,13 @@
"interfaceStyle": "界面风格",
"deepBlueStyle": "深蓝风格",
"grayWhiteStyle": "灰白风格",
"lightStyle": "浅色风格",
"darkStyle": "深色风格",
"colorSource": "颜色来源",
"followInterfaceStyle": "跟随界面风格",
"customColors": "自定义",
"canvasBackgroundColor": "画布底色",
"canvasGridColor": "棋盘格颜色",
"layout": "界面布局",
"floatingMenu": "悬浮菜单",
"floatingMenuParticleOnly": "请先选择粒子系统",
+7
View File
@@ -98,6 +98,13 @@
"interfaceStyle": "介面風格",
"deepBlueStyle": "深藍風格",
"grayWhiteStyle": "灰白風格",
"lightStyle": "淺色風格",
"darkStyle": "深色風格",
"colorSource": "顏色來源",
"followInterfaceStyle": "跟隨介面風格",
"customColors": "自訂",
"canvasBackgroundColor": "畫布底色",
"canvasGridColor": "棋盤格顏色",
"layout": "介面佈局",
"floatingMenu": "懸浮選單",
"floatingMenuParticleOnly": "請先選擇粒子系統",
+1 -1
View File
@@ -367,7 +367,7 @@ button:disabled { opacity: .55; cursor: wait; }
.tree-tabs { display: flex; gap: 3px; margin: 6px 0; }
.tree-tabs button { height: 24px; padding: 0 8px; border: 1px solid transparent; border-radius: 5px; background: transparent; color: var(--ui-text-faint); font-size: 10px; cursor: pointer; }
.tree-tabs button:hover { background: var(--ui-control-hover); }
.tree-tabs button.on { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.tree-tabs button.on { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.selected-bone { width: auto; min-width: 0; max-width: 100%; height: 24px; flex: 0 1 auto; overflow: hidden; padding: 0 7px; color: var(--ui-text-faint); background: var(--ui-surface); border: 1px solid transparent; border-radius: 5px; font-size: 10px; text-align: right; white-space: nowrap; text-overflow: ellipsis; }
.selected-bone.active { color: var(--ui-text-body); background: var(--ui-surface-raised); border-color: var(--ui-border-strong); cursor: pointer; }
.selected-bone.active:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); }
+11 -1
View File
@@ -47,7 +47,8 @@ export interface ScenePath {
}
export type SceneObjectType = 'particle' | 'collision' | 'path' | 'spine'
export type UiTheme = 'deep-blue' | 'gray-white'
export type UiTheme = 'deep-blue' | 'gray-white' | 'light' | 'dark'
export type CanvasColorMode = 'theme' | 'custom'
export interface EditorState {
viewScale: number
@@ -59,6 +60,12 @@ export interface EditorState {
export interface SettingsState {
/** 编辑器界面配色;属于浏览器系统设置,不写入工程数据。 */
uiTheme: UiTheme
/** 画布颜色来源:跟随界面风格或使用自定义颜色。 */
canvasColorMode: CanvasColorMode
/** 自定义画布底层颜色。 */
canvasBackgroundColor: string
/** 自定义棋盘格方块颜色。 */
canvasGridColor: string
/** 参数面板是否显示在页面右侧;关闭时显示在左侧。 */
parameterPanelOnRight: boolean
/** 是否用画布左侧悬浮菜单切换参数分区。 */
@@ -195,6 +202,9 @@ export const useParticleStore = defineStore('particle', {
timeline: { playing: true, loop: true, abLoop: false, frame: 0, totalFrames: 60, playbackStart: 0, playbackEnd: 59, fps: 30, recorded: false, animation: 'animation', animations: ['animation'] } as TimelineState,
settings: {
uiTheme: 'deep-blue',
canvasColorMode: 'theme',
canvasBackgroundColor: '#0e1219',
canvasGridColor: '#141a26',
parameterPanelOnRight: true,
floatingMenuEnabled: false,
tickEnabled: false,
+136
View File
@@ -38,6 +38,7 @@ body {
--ui-text-secondary: #8a93bb;
--ui-text-muted: #667;
--ui-text-faint: #647089;
--ui-text-on-soft: #fff;
--ui-accent: #625ff1;
--ui-accent-strong: #7774ff;
--ui-accent-bright: #8982ff;
@@ -105,6 +106,7 @@ body[data-ui-theme='gray-white'] {
--ui-text-secondary: #b7bdc3;
--ui-text-muted: #9aa1a8;
--ui-text-faint: #8f969d;
--ui-text-on-soft: #fff;
--ui-accent: #3f9ed8;
--ui-accent-strong: #61b8ea;
--ui-accent-bright: #82cbef;
@@ -142,6 +144,140 @@ body[data-ui-theme='gray-white'] {
--ui-canvas-bg: #4b4d51;
--ui-canvas-grid: #55585d;
}
body[data-ui-theme='light'] {
color-scheme: light;
--ui-app-bg: #e8ecef;
--ui-chrome-bg: #e0e5e9;
--ui-panel-bg: #f6f8fa;
--ui-surface: #fff;
--ui-surface-soft: #f8fafb;
--ui-surface-muted: #edf1f4;
--ui-surface-raised: #dde5eb;
--ui-control-bg: #fff;
--ui-control-bg-alt: #f3f6f8;
--ui-control-deep: #f7f9fa;
--ui-control-hover: #e4ebf0;
--ui-control-active: #2e779e;
--ui-hover-surface: #e8eef2;
--ui-button-surface: #dbe4ea;
--ui-border: #c8d2da;
--ui-border-control: #b8c5cf;
--ui-border-subtle: #d9e1e7;
--ui-border-strong: #aab8c3;
--ui-border-button: #9eafbb;
--ui-text-primary: #1b2731;
--ui-text: #46545f;
--ui-text-soft: #35434e;
--ui-text-strong: #26343f;
--ui-text-body: #43515c;
--ui-text-secondary: #596b79;
--ui-text-muted: #74838f;
--ui-text-faint: #8c99a4;
--ui-text-on-soft: #24313a;
--ui-accent: #2d84b5;
--ui-accent-strong: #1f6f9e;
--ui-accent-bright: #469bc8;
--ui-accent-text-muted: #206b95;
--ui-accent-text-soft: #1c587b;
--ui-accent-soft: #d6e9f4;
--ui-accent-soft-bg: #c6e0ef;
--ui-accent-bg: #2779a5;
--ui-accent-bg-hover: #1d658b;
--ui-accent-button: #2779a5;
--ui-selected-bg: #2e779e;
--ui-selected-border: #469bc8;
--ui-focus: #2f8fbd;
--ui-scrollbar: #a8b4bd;
--ui-scrollbar-hover: #8e9ca6;
--ui-popover-bg: rgba(250,252,253,.98);
--ui-panel-overlay: rgba(250,252,253,.97);
--ui-nav-bg: #f0f4f6;
--ui-nav-hover: #dfe7ec;
--ui-switch-off: #a7b3bd;
--ui-backdrop: rgba(30,41,52,.32);
--ui-backdrop-soft: rgba(30,41,52,.18);
--ui-backdrop-strong: rgba(24,33,42,.42);
--ui-overlay-soft: rgba(247,250,252,.94);
--ui-border-translucent: rgba(115,132,148,.55);
--ui-border-faint: rgba(100,120,135,.16);
--ui-hover-translucent: rgba(70,101,126,.08);
--ui-selection-translucent: rgba(45,132,181,.14);
--ui-focus-ring: rgba(45,132,181,.18);
--ui-accent-overlay: rgba(45,132,181,.82);
--ui-accent-halo: rgba(45,132,181,.22);
--ui-accent-glow: rgba(45,132,181,.55);
--ui-accent-cross: rgba(70,155,200,.72);
--ui-sunken: #e7edf1;
--ui-canvas-bg: #dfe4e8;
--ui-canvas-grid: #ccd4da;
}
body[data-ui-theme='dark'] {
color-scheme: dark;
--ui-app-bg: #111315;
--ui-chrome-bg: #181b1e;
--ui-panel-bg: #1d2023;
--ui-surface: #24282c;
--ui-surface-soft: #292d31;
--ui-surface-muted: #212428;
--ui-surface-raised: #30353a;
--ui-control-bg: #292d31;
--ui-control-bg-alt: #31363a;
--ui-control-deep: #202327;
--ui-control-hover: #363b40;
--ui-control-active: #3f5666;
--ui-hover-surface: #303438;
--ui-button-surface: #33383d;
--ui-border: #34393e;
--ui-border-control: #3e444a;
--ui-border-subtle: #30353a;
--ui-border-strong: #4c545c;
--ui-border-button: #59626b;
--ui-text-primary: #f0f2f4;
--ui-text: #c3c9ce;
--ui-text-soft: #d8dcdf;
--ui-text-strong: #e5e8ea;
--ui-text-body: #cbd0d5;
--ui-text-secondary: #9da6ae;
--ui-text-muted: #818a92;
--ui-text-faint: #6d767e;
--ui-text-on-soft: #fff;
--ui-accent: #7ba2c3;
--ui-accent-strong: #9bbcd6;
--ui-accent-bright: #b6d3e6;
--ui-accent-text-muted: #afcbe0;
--ui-accent-text-soft: #d2e3ee;
--ui-accent-soft: #2b3d4b;
--ui-accent-soft-bg: #354b5c;
--ui-accent-bg: #365f7a;
--ui-accent-bg-hover: #416d8b;
--ui-accent-button: #416d8b;
--ui-selected-bg: #3f6d8c;
--ui-selected-border: #7ba2c3;
--ui-focus: #a5cae0;
--ui-scrollbar: #4b535b;
--ui-scrollbar-hover: #646e78;
--ui-popover-bg: rgba(29,32,35,.98);
--ui-panel-overlay: rgba(29,32,35,.97);
--ui-nav-bg: #202428;
--ui-nav-hover: #2c3135;
--ui-switch-off: #535a61;
--ui-backdrop: rgba(0,0,0,.68);
--ui-backdrop-soft: rgba(0,0,0,.24);
--ui-backdrop-strong: rgba(0,0,0,.76);
--ui-overlay-soft: rgba(25,28,31,.92);
--ui-border-translucent: rgba(115,125,134,.55);
--ui-border-faint: rgba(115,125,134,.2);
--ui-hover-translucent: rgba(130,145,160,.16);
--ui-selection-translucent: rgba(123,162,195,.24);
--ui-focus-ring: rgba(123,162,195,.2);
--ui-accent-overlay: rgba(123,162,195,.82);
--ui-accent-halo: rgba(123,162,195,.22);
--ui-accent-glow: rgba(123,162,195,.55);
--ui-accent-cross: rgba(182,211,230,.72);
--ui-sunken: #1a1d20;
--ui-canvas-bg: #202326;
--ui-canvas-grid: #282c2f;
}
body { position: fixed; inset: 0; }
* { box-sizing: border-box; }
#app { position: fixed; inset: 0; width: auto; height: auto; overflow: clip; }
+2 -2
View File
@@ -186,11 +186,11 @@ function normalizeHex(value: string, fallback: string) {
.gradient-controls { display: flex; align-items: center; gap: 5px; margin-top: 30px; }
.gradient-color { width: 28px; height: 24px; padding: 1px; border: 1px solid var(--ui-border-strong); border-radius: 4px; background: var(--ui-surface-soft); cursor: pointer; }
.gradient-hex-input { width: 66px; padding: 4px 5px; border: 1px solid var(--ui-border-strong); border-radius: 4px; outline: none; background: var(--ui-control-deep); color: var(--ui-text-body); font-size: 10px; font-family: monospace; }
.gradient-hex-input:focus { border-color: var(--ui-accent-strong); color: #fff; }
.gradient-hex-input:focus { border-color: var(--ui-accent-strong); color: var(--ui-text-primary); }
.gradient-position { display: flex; align-items: center; color: var(--ui-text-faint); font-size: 10px; }
.gradient-position input { width: 43px; padding: 3px 4px; border: 1px solid var(--ui-border-strong); border-radius: 4px; outline: none; background: var(--ui-control-deep); color: var(--ui-text-strong); text-align: right; }
.gradient-action { width: 25px; height: 24px; padding: 0; border: 1px solid var(--ui-border-strong); border-radius: 4px; background: var(--ui-control-hover); color: var(--ui-text-body); cursor: pointer; }
.gradient-action:hover:not(:disabled) { border-color: var(--ui-accent-strong); color: #fff; }
.gradient-action:hover:not(:disabled) { border-color: var(--ui-accent-strong); color: var(--ui-text-primary); }
.gradient-action.danger { color: #e3a5aa; }
.gradient-action:disabled { opacity: .35; cursor: not-allowed; }
.gradient-hint { margin-top: 5px; color: var(--ui-text-faint); font-size: 9px; }
+1 -1
View File
@@ -268,7 +268,7 @@ function onTimelineDrag(e: PointerEvent) {
.floating-section-tab {
display: flex; width: 100%; min-height: 40px; flex: 0 0 auto; align-items: center; gap: 9px;
padding: 0 10px; border: 1px solid var(--ui-border); border-radius: 8px;
background: var(--ui-nav-bg); color: var(--ui-text-body); font: inherit; font-size: 12px; text-align: left; cursor: pointer;
background: var(--ui-nav-bg); color: var(--ui-text-strong); font: inherit; font-size: 12px; text-align: left; cursor: pointer;
}
.floating-section-tab:hover:not(:disabled) { border-color: var(--ui-border-strong); background: var(--ui-nav-hover); color: var(--ui-text-primary); }
.floating-section-tab.selected {
+4 -4
View File
@@ -330,7 +330,7 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
position: absolute; top: 18px; right: 18px; width: 28px; height: 28px; border: 1px solid var(--ui-border-button); border-radius: 6px;
background: var(--ui-control-hover); color: var(--ui-text-body); cursor: pointer;
}
.help-close:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.help-close:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.help-body {
min-height: 0; overflow: auto; padding: 18px 20px 21px;
scrollbar-width: thin; scrollbar-color: var(--ui-scrollbar) transparent;
@@ -373,7 +373,7 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
}
.release-head span { flex: 1; min-width: 0; font-weight: 700; }
.release-head b { color: var(--ui-text-faint); font-size: 12px; font-weight: 400; }
.release-head:hover, .release-card.open .release-head { background: var(--ui-nav-hover); color: #fff; }
.release-head:hover, .release-card.open .release-head { background: var(--ui-nav-hover); color: var(--ui-text-primary); }
.release-card.open .release-head b { color: var(--ui-accent-text-muted); }
.release-body { margin: 0 15px; padding: 12px 0 14px; border-top: 1px solid var(--ui-border-subtle); }
.release-body p { margin: 0; color: var(--ui-text-faint); font-size: 12px; line-height: 1.7; }
@@ -385,10 +385,10 @@ onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
display: flex; align-items: center; gap: 8px; width: 100%; padding: 0; border: 0; background: transparent;
color: var(--ui-accent-text-muted); font: inherit; font-size: 13px; font-weight: 700; text-align: left; cursor: pointer;
}
.help-module-head:hover { color: #fff; }
.help-module-head:hover { color: var(--ui-text-primary); }
.help-module-head .mtitle { flex: 1; min-width: 0; }
.help-module-head .caret { flex: 0 0 auto; color: var(--ui-text-faint); font-size: 12px; }
.help-module.open .help-module-head { color: #fff; }
.help-module.open .help-module-head { color: var(--ui-text-primary); }
.help-module.open .help-module-head .caret { color: var(--ui-accent-text-muted); }
.help-module .mnum {
flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
+2 -2
View File
@@ -321,11 +321,11 @@ function changeImageMode(event: Event) {
.pivot-modal-badge { padding: 2px 7px; border: 1px solid var(--ui-accent-soft); border-radius: 999px; background: var(--ui-accent-soft-bg); color: var(--ui-accent-text-soft); font-size: 10px; font-weight: 500; }
.pivot-modal-desc { margin-top: 3px; color: var(--ui-text-faint); font-size: 11px; }
.pivot-modal-close { width: 28px; height: 28px; padding: 0; border: 0; border-radius: 6px; background: transparent; color: var(--ui-text-faint); font-size: 15px; cursor: pointer; }
.pivot-modal-close:hover { background: var(--ui-border-subtle); color: #fff; }
.pivot-modal-close:hover { background: var(--ui-border-subtle); color: var(--ui-text-primary); }
.pivot-modal-hint { margin: 10px 0 0; color: var(--ui-text-faint); font-size: 11px; }
.pivot-modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--ui-border-subtle); }
.pivot-modal-cancel { height: 34px; padding: 0 16px; border: 1px solid var(--ui-border-strong); border-radius: 7px; background: var(--ui-surface); color: var(--ui-text-body); font-size: 12px; cursor: pointer; }
.pivot-modal-cancel:hover { border-color: var(--ui-accent); color: #fff; }
.pivot-modal-cancel:hover { border-color: var(--ui-accent); color: var(--ui-text-primary); }
.pivot-modal-confirm { height: 34px; padding: 0 22px; border: 1px solid var(--ui-accent-strong); border-radius: 7px; background: var(--ui-accent-button); color: #fff; font-size: 12px; font-weight: 700; cursor: pointer; }
.pivot-modal-confirm:hover { background: var(--ui-accent-strong); }
</style>
+2 -2
View File
@@ -154,6 +154,6 @@ onUnmounted(() => document.removeEventListener('pointerdown', onDocumentPointerD
background: transparent; color: var(--ui-text-body); font: inherit; font-size: 12px; text-align: left; white-space: nowrap; cursor: pointer;
}
.language-option:hover, .language-option:focus-visible { outline: none; background: var(--ui-control-active); color: #fff; }
.language-option.selected { background: var(--ui-accent-soft-bg); color: #fff; }
.language-check { justify-self: end; color: #fff; font-size: 18px; font-weight: 500; }
.language-option.selected { background: var(--ui-accent-soft-bg); color: var(--ui-text-on-soft); }
.language-check { justify-self: end; color: inherit; font-size: 18px; font-weight: 500; }
</style>
+2 -2
View File
@@ -319,11 +319,11 @@ onBeforeUnmount(() => {
.pivot-hint-icon { color: var(--ui-accent-text-soft); font-size: 13px; }
.pivot-zoom { display: flex; align-items: center; gap: 2px; padding: 2px; border: 1px solid var(--ui-border-strong); border-radius: 6px; background: var(--ui-surface); }
.pivot-zoom button { width: 20px; height: 20px; padding: 0; border: 0; border-radius: 4px; background: transparent; color: var(--ui-text-body); font-size: 13px; cursor: pointer; }
.pivot-zoom button:hover:not(:disabled) { background: var(--ui-control-hover); color: #fff; }
.pivot-zoom button:hover:not(:disabled) { background: var(--ui-control-hover); color: var(--ui-text-on-soft); }
.pivot-zoom button:disabled { opacity: .3; cursor: default; }
.pivot-zoom span { min-width: 36px; text-align: center; color: var(--ui-text-body); font-size: 10px; font-variant-numeric: tabular-nums; }
.pivot-expand { width: 24px; height: 24px; padding: 0; border: 1px solid var(--ui-border-strong); border-radius: 6px; background: var(--ui-surface); color: var(--ui-text-body); font-size: 13px; cursor: pointer; }
.pivot-expand:hover { border-color: var(--ui-accent-strong); color: #fff; }
.pivot-expand:hover { border-color: var(--ui-accent-strong); color: var(--ui-text-primary); }
.pivot-stage {
position: relative; display: flex; align-items: center; justify-content: center;
+38 -5
View File
@@ -97,11 +97,39 @@ if (!(store.settings.bonePointDrawSize > 0)) store.settings.bonePointDrawSize =
if (!(store.settings.boneAxisDrawSize > 0)) store.settings.boneAxisDrawSize = 2
if (store.settings.showSkinMesh == null) store.settings.showSkinMesh = false
if (store.settings.showGrid == null) store.settings.showGrid = true
if (store.settings.uiTheme !== 'gray-white' && store.settings.uiTheme !== 'deep-blue') store.settings.uiTheme = 'deep-blue'
if (!['deep-blue', 'gray-white', 'light', 'dark'].includes(store.settings.uiTheme)) store.settings.uiTheme = 'deep-blue'
if (store.settings.canvasColorMode !== 'custom' && store.settings.canvasColorMode !== 'theme') store.settings.canvasColorMode = 'theme'
if (!/^#[0-9a-f]{6}$/i.test(store.settings.canvasBackgroundColor || '')) store.settings.canvasBackgroundColor = '#0e1219'
if (!/^#[0-9a-f]{6}$/i.test(store.settings.canvasGridColor || '')) store.settings.canvasGridColor = '#141a26'
const CANVAS_THEMES: Record<UiTheme, { background: number; grid: number }> = {
'deep-blue': { background: 0x0e1219, grid: 0x141a26 },
'gray-white': { background: 0x4b4d51, grid: 0x55585d },
light: { background: 0xdfe4e8, grid: 0xccd4da },
dark: { background: 0x202326, grid: 0x282c2f },
}
function canvasPalette() {
if (store.settings.canvasColorMode === 'custom') {
return {
background: Number.parseInt(store.settings.canvasBackgroundColor.slice(1), 16),
grid: Number.parseInt(store.settings.canvasGridColor.slice(1), 16),
}
}
return CANVAS_THEMES[store.settings.uiTheme]
}
const colorNumberToHex = (color: number) => `#${color.toString(16).padStart(6, '0')}`
let previousCanvasColorMode = store.settings.canvasColorMode
function updateCanvasTheme() {
if (store.settings.canvasColorMode === 'custom' && previousCanvasColorMode === 'theme') {
const themeColors = CANVAS_THEMES[store.settings.uiTheme]
store.settings.canvasBackgroundColor = colorNumberToHex(themeColors.background)
store.settings.canvasGridColor = colorNumberToHex(themeColors.grid)
}
previousCanvasColorMode = store.settings.canvasColorMode
applyCanvasTheme()
}
let app: Application | null = null
@@ -151,7 +179,7 @@ function createLayers() {
checkerContext.fillRect(14, 0, 14, 14)
checkerContext.fillRect(0, 14, 14, 14)
canvasGrid = new TilingSprite(Texture.from(checker), app!.screen.width, app!.screen.height)
canvasGrid.tint = CANVAS_THEMES[store.settings.uiTheme].grid
canvasGrid.tint = canvasPalette().grid
canvasGrid.visible = store.settings.showGrid
app!.stage.addChild(canvasGrid)
world = new Container()
@@ -202,7 +230,7 @@ function onPanDown(e: PointerEvent) {
}
function applyCanvasTheme() {
const palette = CANVAS_THEMES[store.settings.uiTheme]
const palette = canvasPalette()
if (app) app.renderer.background.color = palette.background
if (canvasGrid) canvasGrid.tint = palette.grid
}
@@ -631,7 +659,7 @@ onMounted(async () => {
app = new Application({
width: el.clientWidth || 800,
height: el.clientHeight || 600,
backgroundColor: CANVAS_THEMES[store.settings.uiTheme].background,
backgroundColor: canvasPalette().background,
backgroundAlpha: 1,
antialias: true,
})
@@ -655,7 +683,12 @@ onMounted(async () => {
watch(() => store.settings.showGrid, (visible) => {
if (canvasGrid) canvasGrid.visible = visible
})
watch(() => store.settings.uiTheme, applyCanvasTheme)
watch(() => [
store.settings.uiTheme,
store.settings.canvasColorMode,
store.settings.canvasBackgroundColor,
store.settings.canvasGridColor,
], updateCanvasTheme)
const textures = await loadDefaultTextures()
dotTex = textures.dotTex
trailTex = textures.trailTex
+21
View File
@@ -45,8 +45,27 @@ function normalizeBoneDebugSizes() {
<select v-model="store.settings.uiTheme" class="sp-select" :aria-label="t('settings.interfaceStyle')">
<option value="deep-blue">{{ t('settings.deepBlueStyle') }}</option>
<option value="gray-white">{{ t('settings.grayWhiteStyle') }}</option>
<option value="light">{{ t('settings.lightStyle') }}</option>
<option value="dark">{{ t('settings.darkStyle') }}</option>
</select>
</label>
<label class="sp-row"><span>{{ t('settings.colorSource') }}</span>
<select v-model="store.settings.canvasColorMode" class="sp-select" :aria-label="t('settings.colorSource')">
<option value="theme">{{ t('settings.followInterfaceStyle') }}</option>
<option value="custom">{{ t('settings.customColors') }}</option>
</select>
</label>
<template v-if="store.settings.canvasColorMode === 'custom'">
<label class="sp-row sp-color-row"><span>{{ t('settings.canvasBackgroundColor') }}</span>
<input type="color" v-model="store.settings.canvasBackgroundColor" class="sp-colr" :aria-label="t('settings.canvasBackgroundColor')" />
<span class="sp-hex">{{ store.settings.canvasBackgroundColor }}</span>
</label>
<label class="sp-row sp-color-row"><span>{{ t('settings.canvasGridColor') }}</span>
<input type="color" v-model="store.settings.canvasGridColor" class="sp-colr" :aria-label="t('settings.canvasGridColor')" />
<span class="sp-hex">{{ store.settings.canvasGridColor }}</span>
</label>
</template>
<div class="sp-divider"></div>
<div class="sp-section-title">{{ t('settings.layout') }}</div>
<label class="sp-switch-row">
<span>{{ t('settings.parameterPanelPosition') }}</span>
@@ -157,6 +176,8 @@ function normalizeBoneDebugSizes() {
.sp-num { width: 52px; background: var(--ui-control-bg); border: 1px solid var(--ui-border-control); border-radius: 5px; color: var(--ui-text-strong); font-size: 12px; padding: 2px 4px; }
.sp-theme-row { margin-top: 0; }
.sp-select { min-width: 96px; height: 26px; padding: 0 6px; border: 1px solid var(--ui-border-control); border-radius: 5px; background: var(--ui-control-bg); color: var(--ui-text-strong); font: inherit; }
.sp-color-row { display: grid; grid-template-columns: 76px 26px 1fr; }
.sp-color-row .sp-hex { text-align: right; }
.sp-undo-limit { margin-left: auto; width: 64px; height: 26px; box-sizing: border-box; }
.sp-colr { width: 26px; height: 22px; border: none; background: none; cursor: pointer; }
.sp-hex { font-size: 11px; color: var(--ui-text-muted); font-variant-numeric: tabular-nums; }
+2 -2
View File
@@ -179,7 +179,7 @@ b { color: #ffcc33; }
height: 28px; padding: 0 11px; border: 1px solid var(--ui-border-button); border-radius: 6px;
background: var(--ui-button-surface); color: var(--ui-text-strong); font-size: 12px; cursor: pointer;
}
.background-btn:hover, .background-btn.on { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft-bg); color: #fff; }
.background-btn:hover, .background-btn.on { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft-bg); color: var(--ui-text-on-soft); }
.background-panel {
position: absolute; right: 0; bottom: calc(100% + 9px); width: 248px; box-sizing: border-box; padding: 10px;
border: 1px solid var(--ui-border-control); border-radius: 9px; background: var(--ui-popover-bg); color: var(--ui-text-body);
@@ -211,7 +211,7 @@ b { color: #ffcc33; }
height: 28px; padding: 0 11px; flex: 0 0 auto; border: 1px solid var(--ui-border-button); border-radius: 6px;
background: var(--ui-button-surface); color: var(--ui-text-strong); font-size: 12px; font-weight: 700; cursor: pointer;
}
.help-btn:hover, .help-btn.on { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft-bg); color: #fff; }
.help-btn:hover, .help-btn.on { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft-bg); color: var(--ui-text-on-soft); }
.zoom-pct { margin-left: 0; font-variant-numeric: tabular-nums; color: var(--ui-text); min-width: 44px; text-align: center; }
.settings-btn {
height: 28px; padding: 0 12px; flex: 0 0 auto; border: 1px solid var(--ui-border-button); border-radius: 6px;
+1 -1
View File
@@ -567,7 +567,7 @@ function onSpineBarDown(e: PointerEvent, spine: SpineSceneObject) {
}
.tl-animation-option > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-animation-option:hover { background: var(--ui-nav-hover); }
.tl-animation-option.on { background: var(--ui-accent-soft); color: #fff; }
.tl-animation-option.on { background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.tl-animation-option > i { color: var(--ui-accent-text-muted); font-style: normal; }
.tl-animation-editor { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 5px; margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--ui-border-subtle); }
.tl-animation-name { min-width: 0; height: 27px; padding: 0 7px; box-sizing: border-box; border: 1px solid var(--ui-border-control); border-radius: 5px; background: var(--ui-control-deep); color: var(--ui-text-strong); outline: none; }
+1 -1
View File
@@ -150,7 +150,7 @@ const { store, sys, automaticLoopDuration, loopDurationFrames, collapsed, toggle
margin-left: auto; height: 22px; padding: 0 7px; border: 1px solid var(--ui-border-strong); border-radius: 5px;
background: var(--ui-surface-raised); color: var(--ui-text-body); font-size: 10px; line-height: 20px; cursor: pointer;
}
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.group-body { padding: 8px 10px 12px; }
.caret { display: inline-block; width: 12px; color: var(--ui-text-muted); font-size: 11px; }
.divider { height: 1px; background: var(--ui-border); margin: 8px 0; }
@@ -85,7 +85,7 @@ const { exportSettings, collapsed, toggle, sectionOpen, resetModule, normalizeEx
margin-left: auto; height: 22px; padding: 0 7px; border: 1px solid var(--ui-border-strong); border-radius: 5px;
background: var(--ui-surface-raised); color: var(--ui-text-body); font-size: 10px; line-height: 20px; cursor: pointer;
}
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.group-body { padding: 8px 10px 12px; }
.caret { display: inline-block; width: 12px; color: var(--ui-text-muted); font-size: 11px; }
.row { display: flex; align-items: center; gap: 8px; margin: 6px 0; font-size: 12px; color: var(--ui-text); }
@@ -173,7 +173,7 @@ const { resolvedCurveEditorMode, sys, textureFileInput, sequenceFileInput, addIm
margin-left: auto; height: 22px; padding: 0 7px; border: 1px solid var(--ui-border-strong); border-radius: 5px;
background: var(--ui-surface-raised); color: var(--ui-text-body); font-size: 10px; line-height: 20px; cursor: pointer;
}
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.group-body { padding: 8px 10px 12px; }
.caret { display: inline-block; width: 12px; color: var(--ui-text-muted); font-size: 11px; }
.divider { height: 1px; background: var(--ui-border); margin: 8px 0; }
@@ -198,7 +198,7 @@ const { resolvedCurveEditorMode, sys, textureFileInput, sequenceFileInput, addIm
.resource-color-picker .hex { margin-left: 0; }
.random-color-hint { margin: -5px 0 9px 68px; color: var(--ui-text-faint); font-size: 9px; line-height: 1.45; }
.hex-input { width: 72px; padding: 4px 6px; border: 1px solid var(--ui-border-strong); border-radius: 5px; outline: none; background: var(--ui-control-deep); color: var(--ui-text-body); font-size: 11px; font-family: monospace; }
.hex-input:focus { border-color: var(--ui-accent-strong); color: #fff; }
.hex-input:focus { border-color: var(--ui-accent-strong); color: var(--ui-text-primary); }
.resource-alpha-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 10px; color: var(--ui-text-secondary); font-size: 12px; }
.alpha-modes { display: flex; gap: 3px; }
.alpha-modes button { padding: 4px 8px; border: 1px solid transparent; border-radius: 5px; background: transparent; color: var(--ui-text-faint); font-size: 11px; cursor: pointer; }
@@ -211,13 +211,13 @@ const { resolvedCurveEditorMode, sys, textureFileInput, sequenceFileInput, addIm
.render-layer-current { display: flex; align-items: center; gap: 6px; margin: 6px 0; }
.render-layer-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ui-text-body); font-size: 11px; }
.mini-btn { flex: 0 0 auto; height: 24px; padding: 0 7px; border: 1px solid var(--ui-border-strong); border-radius: 5px; background: var(--ui-surface-raised); color: var(--ui-text-body); font-size: 10px; cursor: pointer; }
.mini-btn:hover { border-color: var(--ui-accent-strong); color: #fff; }
.mini-btn:hover { border-color: var(--ui-accent-strong); color: var(--ui-text-primary); }
.mini-btn.ghost { background: transparent; }
.slot-picker { margin: 6px 0; padding: 6px; border: 1px solid var(--ui-border-strong); border-radius: 6px; background: var(--ui-surface); }
.slot-list { max-height: 180px; overflow: auto; margin-top: 6px; }
.slot-item { display: flex; align-items: center; gap: 6px; width: 100%; padding: 4px 6px; border: 1px solid transparent; border-radius: 4px; background: transparent; color: var(--ui-text-body); font-size: 11px; text-align: left; cursor: pointer; }
.slot-item:hover { background: var(--ui-surface); }
.slot-item.on { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft-bg); color: #fff; }
.slot-item.on { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft-bg); color: var(--ui-text-on-soft); }
.slot-order { width: 26px; flex: 0 0 26px; color: var(--ui-text-faint); font-variant-numeric: tabular-nums; }
.slot-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.slot-attachment { max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ui-text-faint); font-size: 10px; }
@@ -172,7 +172,7 @@ const { sys, collapsed, toggle, sectionOpen, resetModule, setSpeedOverLifeMode,
margin-left: auto; height: 22px; padding: 0 7px; border: 1px solid var(--ui-border-strong); border-radius: 5px;
background: var(--ui-surface-raised); color: var(--ui-text-body); font-size: 10px; line-height: 20px; cursor: pointer;
}
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.group-body { padding: 8px 10px 12px; }
.caret { display: inline-block; width: 12px; color: var(--ui-text-muted); font-size: 11px; }
.row { display: flex; align-items: center; gap: 8px; margin: 6px 0; font-size: 12px; color: var(--ui-text); }
@@ -566,7 +566,7 @@ function setCollisionLimit(rule: { collisionLimit: number }, event: Event) {
margin-left: auto; height: 22px; padding: 0 7px; border: 1px solid var(--ui-border-strong); border-radius: 5px;
background: var(--ui-surface-raised); color: var(--ui-text-body); font-size: 10px; line-height: 20px; cursor: pointer;
}
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.group-reset:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.group-body { padding: 8px 10px 12px; }
.caret { display: inline-block; width: 12px; color: var(--ui-text-muted); font-size: 11px; }
.divider { height: 1px; background: var(--ui-border); margin: 8px 0; }
@@ -586,7 +586,7 @@ function setCollisionLimit(rule: { collisionLimit: number }, event: Event) {
.image-add:hover { background: var(--ui-accent-button); color: #fff; }
.resource-divider { height: 1px; margin: 9px 0 7px; background: var(--ui-border-subtle); }
.hex-input { width: 72px; padding: 4px 6px; border: 1px solid var(--ui-border-strong); border-radius: 5px; outline: none; background: var(--ui-control-deep); color: var(--ui-text-body); font-size: 11px; font-family: monospace; }
.hex-input:focus { border-color: var(--ui-accent-strong); color: #fff; }
.hex-input:focus { border-color: var(--ui-accent-strong); color: var(--ui-text-primary); }
.alpha-modes { display: flex; gap: 3px; }
.alpha-modes button { padding: 4px 8px; border: 1px solid transparent; border-radius: 5px; background: transparent; color: var(--ui-text-faint); font-size: 11px; cursor: pointer; }
.alpha-modes button:hover { background: var(--ui-control-hover); }
@@ -630,7 +630,7 @@ function setCollisionLimit(rule: { collisionLimit: number }, event: Event) {
.inherit-check { width: 14px; flex: 0 0 14px; color: var(--ui-text-strong); font-size: 12px; }
.inherit-divider { height: 1px; margin: 4px; background: var(--ui-border); }
.event-add { height: 28px; border: 1px dashed var(--ui-border-button); border-radius: 6px; background: transparent; color: var(--ui-text-faint); font-size: 11px; cursor: pointer; }
.event-add:hover { border-color: var(--ui-accent-strong); background: var(--ui-control-hover); color: #fff; }
.event-add:hover { border-color: var(--ui-accent-strong); background: var(--ui-control-hover); color: var(--ui-text-on-soft); }
.modifier-switch { font-weight: 600; }
.modifier-params { margin: 8px 0 0 10px; padding: 2px 0 2px 10px; border-left: 2px solid var(--ui-border-strong); }
.modifier-hint { margin: 7px 0 0 2px; color: var(--ui-text-faint); font-size: 9px; line-height: 1.5; }
@@ -643,12 +643,12 @@ function setCollisionLimit(rule: { collisionLimit: number }, event: Event) {
.collision-filter-tag button { width: 18px; height: 18px; padding: 0; border: 0; border-radius: 4px; background: rgba(11, 15, 26, 0.22); color: inherit; line-height: 16px; cursor: pointer; }
.collision-filter-tag button:hover { background: rgba(11, 15, 26, 0.5); color: #fff; }
.collision-filter-add { width: 30px; height: 30px; padding: 0; border: 1px dashed var(--ui-border-button); border-radius: 6px; background: var(--ui-surface); color: var(--ui-text-faint); font-size: 18px; line-height: 28px; cursor: pointer; }
.collision-filter-add:hover, .collision-filter-add.active { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.collision-filter-add:hover, .collision-filter-add.active { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.collision-filter-add:disabled { opacity: 0.42; cursor: not-allowed; }
.collision-filter-empty { margin-top: 7px; color: var(--ui-text-faint); font-size: 10px; }
.collision-filter-picker { display: grid; gap: 4px; margin-top: 7px; padding: 5px; border: 1px solid var(--ui-border-strong); border-radius: 6px; background: var(--ui-control-deep); }
.collision-filter-picker button { display: flex; min-width: 0; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 8px; border: 0; border-radius: 4px; background: transparent; color: var(--ui-text-body); font-size: 11px; text-align: left; cursor: pointer; }
.collision-filter-picker button:hover { background: var(--ui-control-hover); color: #fff; }
.collision-filter-picker button:hover { background: var(--ui-control-hover); color: var(--ui-text-on-soft); }
.collision-filter-picker button span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.collision-filter-picker button small { flex: none; color: var(--ui-text-faint); font-size: 9px; }
.switch-row input:disabled + .switch-ui { opacity: 0.45; cursor: not-allowed; }
@@ -656,7 +656,7 @@ function setCollisionLimit(rule: { collisionLimit: number }, event: Event) {
.bone-follow-target strong { color: var(--ui-text-body); font-weight: 600; }
.bone-follow-missing { margin: 7px 0 9px; padding: 7px 8px; color: #d49aa3; background: #2a1e26; border: 1px solid #513540; border-radius: 5px; font-size: 10px; line-height: 1.5; }
.bone-follow-rebind { width: 100%; min-height: 28px; margin: 0 0 8px; padding: 4px 8px; overflow: hidden; border: 1px solid var(--ui-accent-soft); border-radius: 5px; background: var(--ui-accent-soft); color: var(--ui-accent-text-soft); font-size: 10px; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.bone-follow-rebind:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.bone-follow-rebind:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.bone-follow-transform-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.modifier-mode-row { display: flex; justify-content: flex-end; gap: 4px; margin-bottom: 6px; }
.gravity-curve-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 10px 0 6px; color: var(--ui-text-faint); font-size: 11px; }
@@ -208,7 +208,7 @@ function presetDisplayName(preset: PresetOption) {
background: transparent; color: var(--ui-text-strong); font: inherit; font-size: 12px; text-align: left; white-space: nowrap; cursor: pointer;
}
.project-context-menu button:hover, .project-context-menu button:focus-visible {
outline: none; background: var(--ui-control-hover); color: #fff;
outline: none; background: var(--ui-control-hover); color: var(--ui-text-on-soft);
}
.config-management-body { padding-bottom: 2px; }
.group-download {
@@ -223,7 +223,7 @@ function presetDisplayName(preset: PresetOption) {
background: var(--ui-border-subtle); color: var(--ui-text-strong); font-size: 11px;
}
.config-toolbar button { height: auto; padding: 5px 8px; line-height: 1.25; overflow-wrap: anywhere; white-space: normal; cursor: pointer; }
.config-toolbar button:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.config-toolbar button:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.config-toolbar select { grid-column: 1 / -1; height: auto; padding: 6px 7px; overflow: hidden; text-overflow: ellipsis; }
.config-toolbar select:disabled { color: var(--ui-text-faint); background: var(--ui-surface); }
.config-message { margin: -4px 0 9px; color: var(--ui-text-body); font-size: 10px; }
@@ -246,7 +246,7 @@ function presetDisplayName(preset: PresetOption) {
display: inline-flex; height: 24px; align-items: center; padding: 0 7px; box-sizing: border-box;
border: 1px solid var(--ui-border-strong); border-radius: 5px; background: var(--ui-surface); color: var(--ui-text-body); font-size: 10px; cursor: pointer;
}
.project-actions button:hover { border-color: var(--ui-accent-strong); background: var(--ui-surface); color: #fff; }
.project-actions button:hover { border-color: var(--ui-accent-strong); background: var(--ui-surface); color: var(--ui-text-primary); }
.project-actions button:first-child:hover { border-color: var(--ui-text-body); background: var(--ui-surface-muted); color: #ef9da9; }
.project-empty { padding: 9px 2px; color: var(--ui-text-faint); font-size: 10px; text-align: center; }
.project-bulk-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; margin-top: 8px; }
@@ -285,8 +285,8 @@ function presetDisplayName(preset: PresetOption) {
display: flex; width: 100%; min-height: 30px; align-items: center; gap: 8px; padding: 0 8px;
border: 0; border-radius: 5px; background: transparent; color: var(--ui-text-body); font: inherit; font-size: 11px; text-align: left; cursor: pointer;
}
.project-save-existing-row:hover { background: var(--ui-surface); color: #fff; }
.project-save-existing-row.selected { background: var(--ui-accent-soft-bg); color: #fff; box-shadow: inset 2px 0 var(--ui-accent-bright); }
.project-save-existing-row:hover { background: var(--ui-surface); color: var(--ui-text-primary); }
.project-save-existing-row.selected { background: var(--ui-accent-soft-bg); color: var(--ui-text-on-soft); box-shadow: inset 2px 0 var(--ui-accent-bright); }
.project-save-existing-row:focus-visible { outline: 1px solid var(--ui-accent-bright); outline-offset: -1px; }
.project-save-existing-row span { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.project-save-existing-row small { flex: 0 0 auto; color: var(--ui-text-faint); font-size: 9px; }
@@ -367,7 +367,7 @@ const displaySystems = computed<DisplaySystem[]>(() => {
background: transparent; color: var(--ui-text-strong); font: inherit; font-size: 12px; text-align: left; cursor: pointer;
}
.scene-context-menu button:hover, .scene-context-menu button:focus-visible {
outline: none; background: var(--ui-control-hover); color: #fff;
outline: none; background: var(--ui-control-hover); color: var(--ui-text-on-soft);
}
.panel { display: flex; width: 100%; height: 100%; flex-direction: column; overflow: hidden; background: var(--ui-panel-bg); border-left: 1px solid var(--ui-border); padding: 12px; box-sizing: border-box; }
.empty, .panel-hint { color: var(--ui-text-muted); font-size: 12px; padding: 8px 0; }
@@ -383,7 +383,7 @@ const displaySystems = computed<DisplaySystem[]>(() => {
height: 24px; padding: 0 6px; border: 1px solid var(--ui-border-strong); border-radius: 5px;
background: var(--ui-border-strong); color: var(--ui-accent-text-muted); font-size: 10px; white-space: nowrap; cursor: pointer;
}
.scene-add:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: #fff; }
.scene-add:hover { border-color: var(--ui-accent-strong); background: var(--ui-accent-soft); color: var(--ui-text-on-soft); }
.scene-add:disabled { opacity: 0.42; cursor: not-allowed; border-color: var(--ui-border-control); background: var(--ui-surface); color: var(--ui-text-faint); }
.group-body { padding: 8px 10px 12px; }
.caret { display: inline-block; width: 12px; color: var(--ui-text-muted); font-size: 11px; }