Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ee8280ddb |
@@ -167,28 +167,34 @@
|
||||
<div class="stage-media" in:xfade out:xfade>
|
||||
{#if output && video}
|
||||
<!-- svelte-ignore a11y_media_has_caption -->
|
||||
<video
|
||||
bind:this={videoEl}
|
||||
src={assetUrl(output)}
|
||||
controls
|
||||
playsinline
|
||||
preload="metadata"
|
||||
onloadedmetadata={(e) => {
|
||||
clearOutputMissing(output);
|
||||
noteVideo(e);
|
||||
}}
|
||||
onerror={() => output && markOutputMissing(output)}
|
||||
></video>
|
||||
<div class="print a-photo">
|
||||
{#if st.tone === 'ok' && !fileGone}<span class="a-fix">{t('jobst.done')}</span>{/if}
|
||||
<video
|
||||
bind:this={videoEl}
|
||||
src={assetUrl(output)}
|
||||
controls
|
||||
playsinline
|
||||
preload="metadata"
|
||||
onloadedmetadata={(e) => {
|
||||
clearOutputMissing(output);
|
||||
noteVideo(e);
|
||||
}}
|
||||
onerror={() => output && markOutputMissing(output)}
|
||||
></video>
|
||||
</div>
|
||||
{:else if output}
|
||||
<img
|
||||
src={assetUrl(output)}
|
||||
alt={prompt || t('desk.tabResult')}
|
||||
onload={(e) => {
|
||||
clearOutputMissing(output);
|
||||
noteImg(e);
|
||||
}}
|
||||
onerror={() => output && markOutputMissing(output)}
|
||||
/>
|
||||
<div class="print a-photo">
|
||||
{#if st.tone === 'ok' && !fileGone}<span class="a-fix">{t('jobst.done')}</span>{/if}
|
||||
<img
|
||||
src={assetUrl(output)}
|
||||
alt={prompt || t('desk.tabResult')}
|
||||
onload={(e) => {
|
||||
clearOutputMissing(output);
|
||||
noteImg(e);
|
||||
}}
|
||||
onerror={() => output && markOutputMissing(output)}
|
||||
/>
|
||||
</div>
|
||||
{:else if fileGone}
|
||||
<div class="stage-empty gone">
|
||||
<span>{t('desk.missingTitle')}</span>
|
||||
@@ -362,14 +368,24 @@
|
||||
inset: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: var(--sp-5);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.stage-media > img,
|
||||
.stage-media > video {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
/* 相纸白边 (HEL-680):检视舞台上的结果按相纸呈现,媒体自适应内含 */
|
||||
.print {
|
||||
position: relative;
|
||||
display: grid;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
--paper-w: 5px;
|
||||
}
|
||||
.print > img,
|
||||
.print > video {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
.stage-empty {
|
||||
display: grid;
|
||||
|
||||
@@ -183,7 +183,8 @@
|
||||
|
||||
<div class="out">
|
||||
{#if output}
|
||||
<div class="thumb" class:portrait>
|
||||
<div class="thumb a-photo" class:portrait>
|
||||
{#if st.tone === 'ok' && !fileGone}<span class="a-fix">{t('jobst.done')}</span>{/if}
|
||||
{#if isVideoOutput(job, output)}
|
||||
<video
|
||||
src={assetUrl(output)}
|
||||
@@ -238,15 +239,42 @@
|
||||
background-color var(--d-state) ease,
|
||||
box-shadow var(--d-state) ease;
|
||||
}
|
||||
/* 选中框:金色描边从上一条记录滑到新选中的记录(feed 驱动 WAAPI) */
|
||||
/* 选中框:取景框角线从上一条记录滑到新选中的记录(feed 驱动 WAAPI,
|
||||
HEL-680 四角短线取代整框描边) */
|
||||
.sel-mark {
|
||||
position: absolute;
|
||||
inset: -1px;
|
||||
z-index: 3;
|
||||
display: none;
|
||||
border: 1px solid var(--accent-line);
|
||||
border-radius: inherit;
|
||||
pointer-events: none;
|
||||
background-image:
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0);
|
||||
background-position:
|
||||
left top,
|
||||
left top,
|
||||
right top,
|
||||
right top,
|
||||
left bottom,
|
||||
left bottom,
|
||||
right bottom,
|
||||
right bottom;
|
||||
background-size:
|
||||
14px 2px,
|
||||
2px 14px,
|
||||
14px 2px,
|
||||
2px 14px,
|
||||
14px 2px,
|
||||
2px 14px,
|
||||
14px 2px,
|
||||
2px 14px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.take.selected {
|
||||
border-color: transparent;
|
||||
@@ -458,6 +486,12 @@
|
||||
background: var(--bg-4);
|
||||
box-shadow: inset 0 0 0 1px var(--on-media-line);
|
||||
}
|
||||
/* 相纸白边 (HEL-680):有产出的记录缩略图按相纸呈现,压过占位态样式 */
|
||||
.thumb.a-photo {
|
||||
border-radius: 2px;
|
||||
background: var(--accent);
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
.thumb.portrait {
|
||||
width: 96px;
|
||||
aspect-ratio: 3 / 4;
|
||||
|
||||
@@ -52,7 +52,12 @@
|
||||
'var(--avatar-4)',
|
||||
'var(--avatar-5)',
|
||||
];
|
||||
const placeholder = $derived(PLACEHOLDER_GRADIENTS[project.id % PLACEHOLDER_GRADIENTS.length]);
|
||||
const placeholderIdx = $derived(project.id % PLACEHOLDER_GRADIENTS.length);
|
||||
const placeholder = $derived(PLACEHOLDER_GRADIENTS[placeholderIdx]);
|
||||
// HEL-680 灰阶封面占位:1–2 亮阶配深图标,3–5 暗阶配浅图标
|
||||
const placeholderIconColor = $derived(
|
||||
placeholderIdx <= 1 ? 'var(--accent-ink)' : 'var(--text)',
|
||||
);
|
||||
|
||||
const coverUrl = $derived(assetUrl(project.cover_path));
|
||||
|
||||
@@ -174,7 +179,12 @@
|
||||
onerror={() => (coverFailed = true)}
|
||||
/>
|
||||
{:else}
|
||||
<span class="cover-ph" style:background={placeholder} aria-hidden="true">
|
||||
<span
|
||||
class="cover-ph"
|
||||
style:background={placeholder}
|
||||
style:color={placeholderIconColor}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<Icon name="film" size={22} />
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
@@ -402,6 +402,7 @@
|
||||
flex-shrink: 0;
|
||||
margin-bottom: var(--sp-5);
|
||||
border-radius: var(--r-md);
|
||||
border-bottom: 2px solid var(--accent-lo);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
background: var(--accent-grad);
|
||||
|
||||
@@ -132,9 +132,7 @@ let {
|
||||
min-height: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background:
|
||||
radial-gradient(ellipse at center, rgba(139, 92, 246, 0.08), transparent 55%),
|
||||
#050508;
|
||||
background: var(--stage-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-md);
|
||||
overflow: hidden;
|
||||
|
||||
@@ -79,14 +79,14 @@
|
||||
let criticNotes = $state<string[]>([]);
|
||||
|
||||
const preview = createMutation({
|
||||
mutationFn: async (vars?: { force?: boolean }) => {
|
||||
mutationFn: async (vars: { force?: boolean } | void) => {
|
||||
if (!clip && !scene) throw new Error(t('promptPreview.noClipSelected'));
|
||||
return jobsApi.previewPrompt(projectId, {
|
||||
clip_id: clip?.id,
|
||||
scene_id: clip ? undefined : scene?.id,
|
||||
workflow_id: workflow?.id,
|
||||
input_values: compactInputValues(inputValues),
|
||||
force: Boolean(vars?.force),
|
||||
force: Boolean((vars as { force?: boolean } | undefined)?.force),
|
||||
});
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
|
||||
@@ -203,7 +203,7 @@ title={t('filmstrip.clipTitle', {
|
||||
inset: 0 0 auto 0;
|
||||
height: 3px;
|
||||
z-index: 1;
|
||||
background: #3f3f46;
|
||||
background: var(--bg-4);
|
||||
}
|
||||
|
||||
.clip.status-done .bar {
|
||||
|
||||
@@ -1902,7 +1902,7 @@ export const de: Dict = {
|
||||
'home.stageProgress': 'Fünf-Phasen-Fortschritt',
|
||||
'tasks.sourceWorkbench': 'Kreativ-Fluss',
|
||||
'jobst.idSuffix': ' · ComfyUI-Prompt-ID {id}',
|
||||
'jobst.done': 'Fertig',
|
||||
'jobst.done': 'Fixiert',
|
||||
'jobst.doneDetail': 'ComfyUI ist fertig, Ergebnisse gespeichert',
|
||||
'jobst.dryRun': 'Platzhalter',
|
||||
'jobst.dryRunDetail': 'Nur Platzhalter: Dry-run ist aktiv, ComfyUI wurde nicht aufgerufen',
|
||||
|
||||
@@ -1901,7 +1901,7 @@ export const en = {
|
||||
'home.stageProgress': 'Five-stage progress',
|
||||
'tasks.sourceWorkbench': 'Creation flow',
|
||||
'jobst.idSuffix': ' · ComfyUI prompt ID {id}',
|
||||
'jobst.done': 'Done',
|
||||
'jobst.done': 'Fixed',
|
||||
'jobst.doneDetail': 'ComfyUI finished and the results are saved',
|
||||
'jobst.dryRun': 'Placeholder',
|
||||
'jobst.dryRunDetail': 'Placeholder only: Dry-run is on, ComfyUI was not called',
|
||||
|
||||
@@ -1902,7 +1902,7 @@ export const es: Dict = {
|
||||
'home.stageProgress': 'Progreso de cinco etapas',
|
||||
'tasks.sourceWorkbench': 'Flujo de creación',
|
||||
'jobst.idSuffix': ' · ID de prompt de ComfyUI {id}',
|
||||
'jobst.done': 'Listo',
|
||||
'jobst.done': 'Fijado',
|
||||
'jobst.doneDetail': 'ComfyUI terminó y los resultados se guardaron',
|
||||
'jobst.dryRun': 'Marcador',
|
||||
'jobst.dryRunDetail': 'Solo marcador: Dry-run activo, no se llamó a ComfyUI',
|
||||
|
||||
@@ -1902,7 +1902,7 @@ export const fr: Dict = {
|
||||
'home.stageProgress': 'Progression en cinq étapes',
|
||||
'tasks.sourceWorkbench': 'Flux de création',
|
||||
'jobst.idSuffix': ' · ID de prompt ComfyUI {id}',
|
||||
'jobst.done': 'Terminé',
|
||||
'jobst.done': 'Fixé',
|
||||
'jobst.doneDetail': 'ComfyUI a terminé, résultats enregistrés',
|
||||
'jobst.dryRun': 'Substitut',
|
||||
'jobst.dryRunDetail': 'Substitut uniquement : Dry-run actif, ComfyUI n\'a pas été appelé',
|
||||
|
||||
@@ -1900,7 +1900,7 @@ export const ja: Dict = {
|
||||
'home.stageProgress': '五段階の進捗',
|
||||
'tasks.sourceWorkbench': '制作フロー',
|
||||
'jobst.idSuffix': ' · ComfyUI プロンプト ID {id}',
|
||||
'jobst.done': '完了',
|
||||
'jobst.done': '定着',
|
||||
'jobst.doneDetail': 'ComfyUI の実行が完了し、結果を保存しました',
|
||||
'jobst.dryRun': 'プレースホルダー',
|
||||
'jobst.dryRunDetail': 'プレースホルダーのみ:Dry-run が有効で ComfyUI は呼び出されていません',
|
||||
|
||||
@@ -1900,7 +1900,7 @@ export const ko: Dict = {
|
||||
'home.stageProgress': '5단계 진행',
|
||||
'tasks.sourceWorkbench': '제작 흐름',
|
||||
'jobst.idSuffix': ' · ComfyUI 프롬프트 ID {id}',
|
||||
'jobst.done': '완료',
|
||||
'jobst.done': '정착',
|
||||
'jobst.doneDetail': 'ComfyUI 실행이 끝나 결과를 저장했습니다',
|
||||
'jobst.dryRun': '자리표시자',
|
||||
'jobst.dryRunDetail': '자리표시자만: Dry-run이 켜져 있어 ComfyUI를 호출하지 않았습니다',
|
||||
|
||||
@@ -1900,8 +1900,8 @@ export const zh: Dict = {
|
||||
'home.stageProgress': '五段进度',
|
||||
'tasks.sourceWorkbench': '创作流程',
|
||||
'jobst.idSuffix': ' · ComfyUI 任务 ID {id}',
|
||||
'jobst.done': '完成',
|
||||
'jobst.doneDetail': 'ComfyUI 已执行完成,结果已保存',
|
||||
'jobst.done': '定影',
|
||||
'jobst.doneDetail': '生成完成,结果已定影保存',
|
||||
'jobst.dryRun': '占位结果',
|
||||
'jobst.dryRunDetail': '占位结果:当前开启了 Dry-run,没有调用 ComfyUI,不是真实生成',
|
||||
'jobst.noOutput': '无产出',
|
||||
|
||||
@@ -589,6 +589,11 @@
|
||||
function avatarStyle(n: number): string {
|
||||
return `var(--avatar-${Math.min(Math.max(n, 1), 5)})`;
|
||||
}
|
||||
|
||||
// HEL-680 灰阶头像:1–2 亮阶配深字,3–5 暗阶配浅字,按阶数决定。
|
||||
function avatarLight(n: number | undefined): boolean {
|
||||
return Math.min(Math.max(n ?? 1, 1), 5) <= 2;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#snippet skillRow(skill: SkillAdminEntry, detail: string)}
|
||||
@@ -655,7 +660,7 @@
|
||||
class:selected
|
||||
onclick={() => selectAgent(agent.key)}
|
||||
>
|
||||
<span class="avatar" class:dark={agent.avatar_dark} style:background={avatarStyle(agent.avatar)}>
|
||||
<span class="avatar" class:dark={avatarLight(agent.avatar)} style:background={avatarStyle(agent.avatar)}>
|
||||
{agent.char}
|
||||
</span>
|
||||
<span class="agent-meta">
|
||||
@@ -693,7 +698,7 @@
|
||||
<section class="mid">
|
||||
{#if activeAgent}
|
||||
<header class="chat-head">
|
||||
<span class="avatar lg" class:dark={activeAgent.avatar_dark} style:background={avatarStyle(activeAgent.avatar)}>
|
||||
<span class="avatar lg" class:dark={avatarLight(activeAgent.avatar)} style:background={avatarStyle(activeAgent.avatar)}>
|
||||
{activeAgent.char}
|
||||
</span>
|
||||
<div class="chat-head-meta">
|
||||
|
||||
+181
-59
@@ -4,62 +4,67 @@
|
||||
|
||||
:root {
|
||||
/* ------------------------------------------------------------------
|
||||
* 融合视觉 design tokens — HEL-649 整站施工规范 §一(流水台结构 ×
|
||||
* 放映厅配色)。Single source of truth for the whole app: pages and
|
||||
* components reference these variables only — no hardcoded colors,
|
||||
* no ad-hoc overrides. Gold is for key actions and the current
|
||||
* selection only; status colors each carry exactly one meaning.
|
||||
* 无彩灰阶 design tokens — HEL-680 S1(白栖知 theme-1「暗房放大机」
|
||||
* × HEL-679 已确认融合样稿)。Single source of truth for the whole
|
||||
* app: pages and components reference these variables only — no
|
||||
* hardcoded colors, no ad-hoc overrides. 界面只有暖调黑白灰,作品是
|
||||
* 屏幕上唯一成片的颜色;状态色仅按主题卡的两处有限例外(琥珀
|
||||
* #A3915F、红 #B3564A)使用,不放大成全站主色。选中=取景框角线,
|
||||
* 完成=「定影」,结果=相纸白边。
|
||||
* ------------------------------------------------------------------ */
|
||||
|
||||
/* 底色:蓝黑四阶,逐层浮起 (§1.1) */
|
||||
--bg: #07090e;
|
||||
--bg-2: #0c0f16;
|
||||
--bg-3: #121724;
|
||||
--bg-4: #1a2133;
|
||||
--line: #1b2233;
|
||||
--line-2: #2a3450;
|
||||
--page-glow: radial-gradient(1200px 500px at 70% -10%, rgba(38, 52, 92, 0.25), transparent 60%);
|
||||
--float-bg: linear-gradient(180deg, #10152a, var(--bg-2));
|
||||
--overlay: rgba(4, 6, 10, 0.6);
|
||||
--media-scrim: rgba(7, 9, 14, 0.65);
|
||||
/* 底色:显影灰阶四阶,逐层浮起(theme-1:#212120 底 / #2C2C2A 面板) */
|
||||
--bg: #212120;
|
||||
--bg-2: #262625;
|
||||
--bg-3: #2c2c2a;
|
||||
--bg-4: #383835;
|
||||
--line: #313130;
|
||||
--line-2: #454542;
|
||||
--page-glow: radial-gradient(1200px 500px at 70% -10%, rgba(245, 244, 238, 0.035), transparent 60%);
|
||||
--float-bg: linear-gradient(180deg, #2e2e2c, var(--bg-2));
|
||||
--overlay: rgba(18, 18, 17, 0.62);
|
||||
--media-scrim: rgba(18, 18, 17, 0.66);
|
||||
--on-media: #fff;
|
||||
--on-media-line: rgba(255, 255, 255, 0.05);
|
||||
--composer-bg: linear-gradient(180deg, #0e1220, var(--bg-2));
|
||||
--composer-focus: 0 0 0 1px rgba(242, 199, 132, 0.12), 0 8px 28px rgba(0, 0, 0, 0.4);
|
||||
--composer-bg: linear-gradient(180deg, #2a2a28, var(--bg-2));
|
||||
--composer-focus: 0 0 0 1px rgba(245, 244, 238, 0.12), 0 8px 28px rgba(0, 0, 0, 0.4);
|
||||
|
||||
/* 放映金:主按钮、当前选中、改过的参数、聚焦框、Toast 动作 (§1.2) */
|
||||
--accent: #f2c784;
|
||||
--accent-ink: #23170a;
|
||||
--accent-soft: rgba(242, 199, 132, 0.13);
|
||||
--accent-hi: #f7d9a2;
|
||||
--accent-lo: #ecaf63;
|
||||
--accent-glow: rgba(236, 175, 99, 0.28);
|
||||
--accent-line: rgba(242, 199, 132, 0.55);
|
||||
/* 相纸白(重点色):主按钮、当前选中、改过的参数、聚焦框、Toast 动作
|
||||
(theme-1 #F5F4EE 重点) */
|
||||
--accent: #f5f4ee;
|
||||
--accent-ink: #212120;
|
||||
--accent-soft: rgba(245, 244, 238, 0.08);
|
||||
--accent-hi: #ffffff;
|
||||
--accent-lo: #ddddd7;
|
||||
--accent-glow: rgba(240, 239, 233, 0.2);
|
||||
--accent-line: rgba(245, 244, 238, 0.55);
|
||||
--accent-grad: linear-gradient(180deg, var(--accent-hi), var(--accent-lo));
|
||||
--accent-grad-hover: linear-gradient(180deg, #fbe3b6, #f0b968);
|
||||
--accent-ring: 0 0 0 1px rgba(242, 199, 132, 0.7), 0 0 22px var(--accent-glow);
|
||||
--btn-glow: 0 2px 14px var(--accent-glow), inset 0 1px 0 rgba(255, 255, 255, 0.35);
|
||||
--btn-glow-hover: 0 4px 18px var(--accent-glow), inset 0 1px 0 rgba(255, 255, 255, 0.4);
|
||||
--accent-wash: linear-gradient(180deg, rgba(242, 199, 132, 0.05), transparent 40%);
|
||||
--sel-shadow: 0 0 0 1px rgba(242, 199, 132, 0.15), 0 6px 24px rgba(0, 0, 0, 0.35);
|
||||
--accent-grad-hover: linear-gradient(180deg, #ffffff, #e8e7df);
|
||||
--accent-ring: 0 0 0 1px rgba(245, 244, 238, 0.7), 0 0 22px var(--accent-glow);
|
||||
--btn-glow: 0 2px 10px rgba(0, 0, 0, 0.38), inset 0 1px 0 rgba(255, 255, 255, 0.55);
|
||||
--btn-glow-hover: 0 3px 14px rgba(0, 0, 0, 0.44), inset 0 1px 0 rgba(255, 255, 255, 0.65);
|
||||
--accent-wash: linear-gradient(180deg, rgba(245, 244, 238, 0.05), transparent 40%);
|
||||
--sel-shadow: 0 0 0 1px rgba(245, 244, 238, 0.14), 0 6px 24px rgba(0, 0, 0, 0.35);
|
||||
|
||||
/* 信号色:绿=完成/已确认/通过,青=进行中/在线,红=失败/危险,
|
||||
琥珀=待确认/文件缺失/限额 (§1.3) */
|
||||
--ok: #49cb90;
|
||||
--ok-soft: rgba(73, 203, 144, 0.13);
|
||||
--run: #54dfd2;
|
||||
--run-soft: rgba(84, 223, 210, 0.13);
|
||||
--run-grad: linear-gradient(90deg, #3bbfb4, var(--run));
|
||||
--err: #f0645a;
|
||||
--err-soft: rgba(240, 100, 90, 0.13);
|
||||
--err-line: rgba(240, 100, 90, 0.6);
|
||||
--warn: #f0b45c;
|
||||
--warn-soft: rgba(240, 180, 92, 0.13);
|
||||
/* 信号色:完成=显影亮灰(「定影」,配图标/文字双编码),进行中=灰阶
|
||||
+动效;红/琥珀只按 theme-1 卡片的有限例外使用(红=失败/危险
|
||||
#B3564A 系,琥珀=待确认/文件缺失 #A3915F) */
|
||||
--ok: #ddddd7;
|
||||
--ok-soft: rgba(221, 221, 215, 0.1);
|
||||
--run: #b8b6ac;
|
||||
--run-soft: rgba(184, 182, 172, 0.12);
|
||||
--run-grad: linear-gradient(90deg, #8f8e85, #c6c5c0);
|
||||
--err: #d07a6b;
|
||||
--err-solid: #b3564a;
|
||||
--err-soft: rgba(181, 86, 74, 0.15);
|
||||
--err-line: rgba(208, 122, 107, 0.55);
|
||||
--warn: #a3915f;
|
||||
--warn-soft: rgba(163, 145, 95, 0.13);
|
||||
|
||||
/* 文字与字体 (§1.4);--text-2 是深底可读性下限,不得再暗 */
|
||||
--text: #f4f6fa;
|
||||
--text-2: #aab2c5;
|
||||
--text-3: #6d7690;
|
||||
/* 文字与字体;--text-3 是深底可读性下限(≥4.5:1 on --bg-3),不得再暗 */
|
||||
--text: #f0efe9;
|
||||
--text-2: #a8a69c;
|
||||
--text-3: #94938c;
|
||||
--font: 'PingFang SC', 'Noto Sans SC', 'Microsoft YaHei', system-ui, sans-serif;
|
||||
--mono: 'JetBrains Mono', ui-monospace, monospace;
|
||||
--fs-title: 15px;
|
||||
@@ -95,8 +100,14 @@
|
||||
/* 专属符号 (§1.7):齿孔只在记录流/输入台分隔带,光晕只在播放舞台 */
|
||||
--sprocket: radial-gradient(circle 2px, var(--line-2) 98%, transparent);
|
||||
--stage-bg:
|
||||
radial-gradient(60% 45% at 50% 38%, rgba(242, 199, 132, 0.07), transparent 70%),
|
||||
radial-gradient(80% 70% at 50% 50%, #0d1220, #05070c);
|
||||
radial-gradient(60% 45% at 50% 38%, rgba(245, 244, 238, 0.045), transparent 70%),
|
||||
radial-gradient(80% 70% at 50% 50%, #232322, #171716);
|
||||
|
||||
/* 取景框角线与相纸白边 (HEL-680):内容级选中/结果呈现的统一语言 */
|
||||
--frame-w: 2px;
|
||||
--frame-arm: 12px;
|
||||
--frame-inset: -4px;
|
||||
--paper-w: 4px;
|
||||
|
||||
/* 动效 (§1.6,取 HEL-648 实测值);只动 transform / opacity */
|
||||
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
|
||||
@@ -113,13 +124,13 @@
|
||||
--d-progress: 400ms;
|
||||
--press-scale: 0.97;
|
||||
|
||||
/* Avatar five-color set — five agents only; the one colorful gradient
|
||||
family the spec keeps (§3.6). */
|
||||
--avatar-1: linear-gradient(135deg, #e8a33d, #b96a1b);
|
||||
--avatar-2: linear-gradient(135deg, #5b8def, #3a5fa9);
|
||||
--avatar-3: linear-gradient(135deg, #3fb97f, #2a7a54);
|
||||
--avatar-4: linear-gradient(135deg, #b98be0, #7a4fa9);
|
||||
--avatar-5: linear-gradient(135deg, #d98e6a, #a95535);
|
||||
/* Avatar five-step grayscale (HEL-680 无彩化):1–2 亮阶配深字,
|
||||
3–5 暗阶配浅字;仍是五个身份位,只是从彩色渐变改为显影灰阶。 */
|
||||
--avatar-1: linear-gradient(135deg, #e8e7df, #cdcbc4);
|
||||
--avatar-2: linear-gradient(135deg, #b5b3aa, #9c9a91);
|
||||
--avatar-3: linear-gradient(135deg, #6b6a66, #55544f);
|
||||
--avatar-4: linear-gradient(135deg, #55544f, #424140);
|
||||
--avatar-5: linear-gradient(135deg, #424140, #2e2e2c);
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* Legacy token names (§六 映射表) — aliases only, never new values,
|
||||
@@ -297,7 +308,7 @@ code,
|
||||
color: var(--err);
|
||||
}
|
||||
.a-btn.danger-solid {
|
||||
background: var(--err);
|
||||
background: var(--err-solid);
|
||||
color: var(--on-media);
|
||||
}
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
@@ -550,11 +561,47 @@ button.status-chip:active {
|
||||
.a-chip.changed {
|
||||
color: var(--accent);
|
||||
}
|
||||
/* Selected filter chip (§3.5 筛选芯片组): 当前选中 = 金色文字 + accent-soft 底 */
|
||||
/* Selected filter chip (§3.5 筛选芯片组): 当前选中 = 取景框角线缩影 +
|
||||
相纸白文字 + accent-soft 底 (HEL-680) */
|
||||
.a-chip.sel {
|
||||
position: relative;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
}
|
||||
.a-chip.sel::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 2px;
|
||||
pointer-events: none;
|
||||
background-image:
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0);
|
||||
background-position:
|
||||
left top,
|
||||
left top,
|
||||
right top,
|
||||
right top,
|
||||
left bottom,
|
||||
left bottom,
|
||||
right bottom,
|
||||
right bottom;
|
||||
background-size:
|
||||
6px 1.5px,
|
||||
1.5px 6px,
|
||||
6px 1.5px,
|
||||
1.5px 6px,
|
||||
6px 1.5px,
|
||||
1.5px 6px,
|
||||
6px 1.5px,
|
||||
1.5px 6px;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.a-chip.warn {
|
||||
color: var(--warn);
|
||||
}
|
||||
@@ -753,6 +800,81 @@ button.a-tile:disabled {
|
||||
box-shadow: 0 0 0 1px var(--line);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* 取景框角线选中 (HEL-680):内容级选中态的唯一语言——四角短线取景,
|
||||
* 不整框描边。挂在需要角线的元素上(元素自身可 overflow 可见;被
|
||||
* overflow:hidden 裁切的容器改用 --frame-inset 正值画在内侧)。
|
||||
* ------------------------------------------------------------------ */
|
||||
.a-frame {
|
||||
position: relative;
|
||||
}
|
||||
.a-frame::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: var(--frame-inset, -4px);
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
background-image:
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0),
|
||||
linear-gradient(var(--accent) 0 0);
|
||||
background-position:
|
||||
left top,
|
||||
left top,
|
||||
right top,
|
||||
right top,
|
||||
left bottom,
|
||||
left bottom,
|
||||
right bottom,
|
||||
right bottom;
|
||||
background-size:
|
||||
var(--frame-arm, 12px) var(--frame-w, 2px),
|
||||
var(--frame-w, 2px) var(--frame-arm, 12px),
|
||||
var(--frame-arm, 12px) var(--frame-w, 2px),
|
||||
var(--frame-w, 2px) var(--frame-arm, 12px),
|
||||
var(--frame-arm, 12px) var(--frame-w, 2px),
|
||||
var(--frame-w, 2px) var(--frame-arm, 12px),
|
||||
var(--frame-arm, 12px) var(--frame-w, 2px),
|
||||
var(--frame-w, 2px) var(--frame-arm, 12px);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* 相纸白边 (HEL-680):结果媒体外的相纸白框,底边略厚如手工相纸。
|
||||
挂在承载 img/video 的媒体容器上;容器尺寸由调用方决定。 */
|
||||
.a-photo {
|
||||
background: var(--accent);
|
||||
border: var(--paper-w, 4px) solid var(--accent);
|
||||
border-bottom-width: calc(var(--paper-w, 4px) + 2px);
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.35);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 「定影」完成章 (HEL-680):已定影结果右上角的完成印记,随 jobst.done
|
||||
文案走(中文=定影)。absolute 定位,挂在有媒体的结果容器内。 */
|
||||
.a-fix {
|
||||
position: absolute;
|
||||
top: var(--sp-3);
|
||||
right: var(--sp-3);
|
||||
z-index: 2;
|
||||
padding: 1px 6px;
|
||||
border: 1px solid currentColor;
|
||||
border-radius: 3px;
|
||||
background: var(--media-scrim);
|
||||
color: var(--ok);
|
||||
font-size: var(--fs-mini);
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.1em;
|
||||
text-indent: 0.1em;
|
||||
transform: rotate(-4deg);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Floating surface for pop / drawer / confirm / toast / lightbox (§四.3). */
|
||||
.a-float {
|
||||
background: var(--float-bg);
|
||||
|
||||
@@ -209,7 +209,13 @@
|
||||
{:else}
|
||||
<div class="grid">
|
||||
{#each visible as item (item.path)}
|
||||
<div class="card" class:selected={selected.has(item.path)}>
|
||||
<div
|
||||
class="card"
|
||||
class:selected={selected.has(item.path)}
|
||||
class:a-frame={selected.has(item.path)}
|
||||
style:--frame-inset="3px"
|
||||
style:--frame-arm="16px"
|
||||
>
|
||||
<label class="check">
|
||||
<input
|
||||
type="checkbox"
|
||||
@@ -217,12 +223,12 @@
|
||||
onchange={() => toggle(item.path)}
|
||||
/>
|
||||
</label>
|
||||
<button
|
||||
type="button"
|
||||
class="media"
|
||||
onclick={() => openPreview(item)}
|
||||
title={item.name}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
class="media a-photo"
|
||||
onclick={() => openPreview(item)}
|
||||
title={item.name}
|
||||
>
|
||||
<SafeMedia src={assetUrl(item.path)} kind={item.kind} alt={item.name} controls={false} />
|
||||
</button>
|
||||
<div class="meta">
|
||||
@@ -341,7 +347,6 @@
|
||||
transition: border-color var(--d-state) ease;
|
||||
}
|
||||
.card.selected {
|
||||
border-color: var(--accent-line);
|
||||
background: linear-gradient(180deg, var(--accent-soft), transparent 32%), var(--bg-2);
|
||||
}
|
||||
.card :global(.media-el) {
|
||||
@@ -380,6 +385,14 @@
|
||||
cursor: zoom-in;
|
||||
overflow: hidden;
|
||||
}
|
||||
/* 相纸白边 (HEL-680):素材墙里的作品按相纸呈现 */
|
||||
.media.a-photo {
|
||||
border: var(--paper-w, 4px) solid var(--accent);
|
||||
border-bottom-width: calc(var(--paper-w, 4px) + 2px);
|
||||
background: var(--accent);
|
||||
border-radius: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.media :global(img),
|
||||
.media :global(video) {
|
||||
width: 100%;
|
||||
|
||||
@@ -392,14 +392,8 @@
|
||||
char: string;
|
||||
dark?: boolean;
|
||||
}[] = [
|
||||
{
|
||||
role: 'story',
|
||||
labelKey: 'models.agentStory',
|
||||
color: 'var(--avatar-1)',
|
||||
char: '剧',
|
||||
dark: true,
|
||||
},
|
||||
{ role: 'style', labelKey: 'models.agentStyle', color: 'var(--avatar-2)', char: '视' },
|
||||
{ role: 'story', labelKey: 'models.agentStory', color: 'var(--avatar-1)', char: '剧', dark: true },
|
||||
{ role: 'style', labelKey: 'models.agentStyle', color: 'var(--avatar-2)', char: '视', dark: true },
|
||||
{ role: 'script', labelKey: 'models.agentScript', color: 'var(--avatar-3)', char: '分' },
|
||||
{ role: 'assets', labelKey: 'models.agentAssets', color: 'var(--avatar-4)', char: '素' },
|
||||
{ role: 'video', labelKey: 'models.agentVideo', color: 'var(--avatar-5)', char: '镜' },
|
||||
|
||||
@@ -496,7 +496,11 @@
|
||||
<aside class="side-col">
|
||||
{#if currentAgent}
|
||||
<div class="side-card agent-card">
|
||||
<span class="agent-avatar" style:background={`var(--avatar-${currentAgent.avatar})`}>
|
||||
<span
|
||||
class="agent-avatar"
|
||||
class:light={(currentAgent.avatar ?? 1) <= 2}
|
||||
style:background={`var(--avatar-${currentAgent.avatar})`}
|
||||
>
|
||||
{currentAgent.char}
|
||||
</span>
|
||||
<div class="agent-copy">
|
||||
@@ -740,6 +744,10 @@
|
||||
color: var(--text);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
/* HEL-680 灰阶头像:1–2 亮阶用深字 */
|
||||
.agent-avatar.light {
|
||||
color: var(--accent-ink);
|
||||
}
|
||||
.agent-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user