diff --git a/movie_editor/frontend/styles.css b/movie_editor/frontend/styles.css index dd2ec1a2..15a006d4 100644 --- a/movie_editor/frontend/styles.css +++ b/movie_editor/frontend/styles.css @@ -503,13 +503,6 @@ input[type=number] { font-family: var(--font-mono); } .tl-zlabel { font-family: var(--font-mono); font-size: 10px; letter-spacing: 1px; text-transform: uppercase; color: var(--faint); } .tl-keys { font-family: var(--font-mono); font-size: 10px; letter-spacing: .5px; color: var(--faint); margin-right: 10px; opacity: .8; } .tl-rating { font-size: 12px; padding: 3px 6px; background: var(--ink-2); border: 1px solid var(--line); border-radius: 6px; color: var(--amber-2); max-width: 200px; } -.tl-render-prompt { - font-family: var(--font-mono); font-size: 10px; color: var(--amber-2); opacity: .9; - max-width: 220px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - border: 1px solid color-mix(in srgb, var(--amber) 30%, var(--line)); border-radius: 6px; padding: 3px 7px; - background: color-mix(in srgb, var(--amber-soft) 35%, var(--ink-2)); -} - .render-prompt-warn { border: 1px solid color-mix(in srgb, var(--amber) 35%, var(--line)); background: color-mix(in srgb, var(--amber-soft) 25%, var(--ink-1)); @@ -629,6 +622,21 @@ body.tl-reordering { cursor: grabbing; user-select: none; } .clip-rated { font-size: 10px; font-family: var(--font-mono); color: var(--amber-2); line-height: 1.2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex-shrink: 0; } .clip.has-media .clip-rated { position: relative; z-index: 1; } +.clip-gen-prompt { + font-size: 10px; line-height: 1.25; flex-shrink: 0; min-height: 0; + border-top: 1px solid color-mix(in srgb, var(--amber) 25%, var(--line)); + padding-top: 3px; margin-top: 1px; +} +.clip-gen-prompt-label { + display: block; font-family: var(--font-mono); font-size: 8.5px; letter-spacing: .4px; + text-transform: uppercase; color: var(--faint); margin-bottom: 1px; +} +.clip-gen-prompt-text { + color: var(--amber-2); overflow: hidden; + display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; +} +.clip.has-media .clip-gen-prompt { position: relative; z-index: 1; } +.clip.prompt-mismatch { border-color: color-mix(in srgb, var(--amber) 45%, var(--line)); } .clip-actions { position: absolute; top: 5px; right: 8px; display: flex; gap: 2px; opacity: 0; transition: opacity .12s; } .clip:hover .clip-actions { opacity: 1; } .ic-btn { width: 18px; height: 18px; padding: 0; font-size: 11px; line-height: 1; border: 1px solid var(--line); diff --git a/movie_editor/frontend/timeline.js b/movie_editor/frontend/timeline.js index 996d6fef..721b018c 100644 --- a/movie_editor/frontend/timeline.js +++ b/movie_editor/frontend/timeline.js @@ -277,6 +277,18 @@ clip.append(rated); } + if (hasRender(st, scene.id) && S.renderPromptMismatch) { + const mismatch = S.renderPromptMismatch(scene.id); + if (mismatch) { + clip.classList.add("prompt-mismatch"); + const gen = el("div", "clip-gen-prompt"); + gen.title = "Timeline prompt was edited after generation — rate against this text"; + gen.append(el("span", "clip-gen-prompt-label", "Generated with")); + gen.append(el("span", "clip-gen-prompt-text", mismatch.rendered || "(empty)")); + clip.append(gen); + } + } + const actions = el("div", "clip-actions"); const mk = (label, title, cls, fn) => { const b = el("button", "ic-btn" + (cls ? " " + cls : ""), label); b.title = title; b.onclick = (e) => { e.stopPropagation(); fn(); }; return b; }; actions.append(mk("⟈", "Split clip at playhead", "", () => { @@ -553,17 +565,12 @@ const rlabel = el("span", "tl-keys", `★ Scene ${sceneNo}`); const rsel = el("select", "tl-rating"); rsel.title = mismatch - ? `Rate against the generated prompt — timeline text was edited after this render` + ? `Rate against the generated prompt on the clip — timeline text was edited after this render` : "Rate this scene's render — FunPack Studio refines from it next generation"; rsel.append(new Option("— rate —", "")); (st.ratingLabels || []).forEach((l) => { const o = new Option(l, l); if (l === (sc.rating || "")) o.selected = true; rsel.append(o); }); rsel.onchange = () => S.setSceneRating(sc.id, rsel.value); bar.append(rlabel); bar.append(rsel); - if (mismatch) { - const hint = el("span", "tl-render-prompt", mismatch.rendered); - hint.title = "Generated with this prompt — use it when rating (timeline text differs)"; - bar.append(hint); - } } const spacer = el("div", "tl-spacer"); bar.append(spacer);