From aa31b95ea576543afcdb1995ffc827c725659f5e Mon Sep 17 00:00:00 2001 From: digital-garbage <133010426+digital-garbage@users.noreply.github.com> Date: Fri, 6 Nov 2026 14:28:45 +0200 Subject: [PATCH] Timeline header on one line; kit literals into tokens; Composer fits; running-state viewport test; remove Auto Montage - Header: view toggles (Assets/Preview/Properties/Auto-hide) move to the top bar; progress, the prompt warning and scene actions (rate, upscale, interpolate) move to the row under the toolbar; the timeline head never wraps from 1000px up and never clips its controls. The top bar grows a line instead of spilling when it wraps. - Kit: every literal pixel size in element CSS is a token (the ratchet test is now zero); Composer's text box follows the viewport; the catalogue shows the component sizes. - test:viewport adds a fake ComfyUI queue and socket for the render-running state and asserts the header is one row. - Auto Montage removed (button, window, code, README/docs, tests). Saved projects holding pieces it made still load: the reused flag is kept. Co-Authored-By: Claude Sonnet 5.5 --- CHANGELOG.md | 1 + README.md | 7 -- app/e2e/viewports.mjs | 27 ++++++- app/ui/catalogue/catalogue.js | 3 +- app/ui/composer/elements/button.css | 6 +- app/ui/composer/elements/choice.css | 22 +++--- app/ui/composer/elements/gallery.css | 14 ++-- app/ui/composer/elements/input.css | 10 +-- app/ui/composer/elements/layout.css | 19 ++--- app/ui/composer/elements/nle.css | 2 +- app/ui/composer/elements/overlay.css | 20 +++--- app/ui/composer/elements/polish.css | 2 +- app/ui/composer/elements/settings.css | 8 +-- app/ui/composer/elements/slider.css | 16 ++--- app/ui/composer/elements/stage.css | 2 +- app/ui/composer/elements/status.css | 20 +++--- app/ui/composer/elements/tile.css | 10 +-- app/ui/composer/elements/track.css | 4 +- app/ui/composer/elements/wheel.css | 6 +- .../tests/rule_kit_uses_the_scale.test.js | 13 ++-- app/ui/composer/tokens/tokens.css | 20 ++++++ app/ui/features/dock/index.js | 2 +- app/ui/features/generate/index.js | 4 +- app/ui/features/generate/progress.js | 2 +- app/ui/features/generate/warn.js | 2 +- app/ui/features/interpolate/index.js | 2 +- app/ui/features/montage/build.js | 64 ----------------- app/ui/features/montage/build.test.js | 66 ------------------ app/ui/features/montage/index.js | 51 -------------- app/ui/features/peek/index.js | 2 +- app/ui/features/rating/index.js | 2 +- app/ui/features/tour/index.js | 2 +- app/ui/features/upscale/index.js | 2 +- app/ui/frame.css | 20 +++++- app/ui/modules.js | 1 - app/ui/shell/edits.js | 2 +- app/ui/shell/scenes.js | 2 +- core/projects.py | 2 +- core/suggestions.py | 2 +- core/tests/test_projects.py | 4 +- core/tests/test_suggestions.py | 2 +- docs/how-to-start.md | 4 +- docs/images/montage.jpg | Bin 159548 -> 0 bytes pyproject.toml | 2 +- 44 files changed, 174 insertions(+), 300 deletions(-) delete mode 100644 app/ui/features/montage/build.js delete mode 100644 app/ui/features/montage/build.test.js delete mode 100644 app/ui/features/montage/index.js delete mode 100644 docs/images/montage.jpg diff --git a/CHANGELOG.md b/CHANGELOG.md index 737d3a2f..dd3209eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Changed +- **Auto Montage is gone** (the button, its window and its code). A saved project that already holds pieces it made loads normally: they stay on the timeline as ordinary copies and are still never regenerated. - **"Video detail" (Engine > Post) is gone.** The other Post settings (edge smoothing, auto contrast, auto brightness, colour strength) stay. A project or setting that still holds Video detail loads normally: its values are skipped and the Log says so once. - **LoRA Loader shows one slot at a time.** With no LoRA picked it shows only the first picker. Once a LoRA is chosen its strengths (and stage) appear, together with the picker for the next slot, and so on up to eight. A slot that already holds a LoRA never hides. - **Simpler Project and Scene settings.** The rarely used groups (Video input, Source trim, Final render size, Split preview) are folded under "More" and stay open once opened. diff --git a/README.md b/README.md index 8c783ecc..2d9c5369 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,6 @@ A rewrite from scratch, not an update of 4.x. Every feature is a module that ann - **Models & Pipeline**: the pipeline as cards, not a graph. Pick files, swap or add nodes (any installed custom node), wire outputs to inputs, import a ComfyUI workflow. The server refuses what would not build and says why. - **Modules**: switch each feature on or off in Settings. A pipeline runs without an optional node whose module is missing, and tells you so. - **Learning from ratings**: rate a clip and the guidance, steering and prompt modules start acting on your taste once they have enough ratings. -- **Auto Montage**: builds a new cut from your rendered clips; the originals stay untouched. The full list of features, and what is proven and what is experimental, is in [CHANGELOG.md](CHANGELOG.md). @@ -72,12 +71,6 @@ Press the middle mouse button anywhere and your most used actions fan out under

Picker wheel

-### Auto Montage - -Builds a new cut at the end of the timeline from your rendered clips. The originals stay as they are. - -

Auto Montage

- ### Train your own LoRA (add-on) Teach the model your style from your own media and results you rated. Pick the data, describe each item, press Start. It is an add-on you switch on in Settings > Modules, and it has been run on MiniMax H3 only. diff --git a/app/e2e/viewports.mjs b/app/e2e/viewports.mjs index 42151eb9..4f6846af 100644 --- a/app/e2e/viewports.mjs +++ b/app/e2e/viewports.mjs @@ -1,11 +1,12 @@ // The app at the screens people really have, in a real browser: no page overflow, every window inside the viewport, -// both timeline lanes visible. Not part of `npm test` (it needs browsers): run it with `npm run test:viewport`. +// both timeline lanes visible, the timeline header on one row from 1000px wide, idle and while a render is running (a fake ComfyUI queue and socket). Not part of `npm test` (it needs browsers): run it with `npm run test:viewport`. // FUNUI_BROWSERS=chromium,firefox picks the engines (default: every one that is installed). import playwright from "playwright"; import { start } from "./stub.mjs"; const SIZES = [[1280, 720], [1024, 1024], [1366, 768], [1920, 1080], [2560, 1440], [768, 1024], [720, 1280], [1080, 1920]]; const WINDOWS = [["Settings", /^Settings$/], ["Log", /^Log$/], ["Composer", /Composer/], ["Sampler", /Sampler/], ["Training", /Training/]]; +const CLIENT = "viewport-test"; const wanted = (process.env.FUNUI_BROWSERS || "chromium,firefox").split(","); const inspect = () => { @@ -13,28 +14,48 @@ const inspect = () => { const seen = [...document.querySelectorAll(".cx-modal, .cx-popover, .cx-window")].filter((e) => box(e).width > 0); const out = seen.map((e) => ({ name: e.className.toString().split(" ")[0], r: box(e) })); const nle = document.querySelector(".cx-nle"), lanes = [...document.querySelectorAll(".cx-nle-gutter-lane")]; + const head = [...document.querySelectorAll(".cx-panel-head")].find((h) => h.textContent.startsWith("Timeline")), act = head && head.querySelector(".cx-panel-actions"); + const header = innerWidth < 1000 || !head ? [] : [box(head).height > 50 && `Timeline header is ${Math.round(box(head).height)}px tall (more than one row)`, act.scrollWidth > act.clientWidth + 1 && `Timeline header clips ${act.scrollWidth - act.clientWidth}px of its controls`].filter(Boolean); return { + header, over: [document.documentElement.scrollWidth - innerWidth, document.documentElement.scrollHeight - innerHeight], windows: out.filter(({ r }) => r.left < -1 || r.top < -1 || r.right > innerWidth + 1 || r.bottom > innerHeight + 1).map(({ name, r }) => `${name} ${Math.round(r.left)},${Math.round(r.top)}..${Math.round(r.right)},${Math.round(r.bottom)}`), lanes: lanes.length < 2 ? ["fewer than two lanes"] : lanes.filter((l) => box(l).bottom > box(nle).bottom + 1).map((l) => `lane ends ${Math.round(box(l).bottom)}, timeline ${Math.round(box(nle).bottom)}`), }; }; +// A render in progress, as ComfyUI would show it: the page's own client id in the queue, and the socket reporting step 4 of 5. +async function fakeRunning(page) { + await page.addInitScript((id) => sessionStorage.setItem("funui.client-id", id), CLIENT); + await page.route("**/queue", (route) => route.fulfill({ json: { queue_pending: [], queue_running: [[1, "pid1", {}, { client_id: CLIENT, funui_scene_id: "s1", funui_scene_ids: ["s1"], funui_project_id: "p1" }, []]] } })); + await page.routeWebSocket(/\/ws\?/, (ws) => { + const say = (type, data) => ws.send(JSON.stringify({ type, data })); + setTimeout(() => { say("execution_start", { prompt_id: "pid1" }); say("progress_state", { prompt_id: "pid1", nodes: { 3: { state: "running", value: 4, max: 5, node_id: "3", display_node_id: "3" } } }); }, 300); + }); +} + const { server, url } = await start(0); const problems = []; let ran = 0; for (const name of wanted) { let browser; try { browser = await playwright[name].launch(); } catch { console.log(`skipping ${name}: not installed`); continue; } - for (const [w, h] of SIZES) { + for (const [w, h, running] of SIZES.flatMap(([w, h]) => [[w, h, false], [w, h, true]])) { const page = await browser.newPage({ viewport: { width: w, height: h } }); - const note = (what) => problems.push(`${name} ${w}x${h}: ${what}`); + const note = (what) => problems.push(`${name} ${w}x${h}${running ? " running" : ""}: ${what}`); + if (running) await fakeRunning(page); await page.goto(url); await page.getByText(/Continue with/).click(); await page.waitForTimeout(800); + if (running) { + await page.waitForTimeout(700); + if (!(await page.getByText(/Step 4\/5/).count())) note("the running render's progress is not shown"); + if (process.env.FUNUI_SHOTS) await page.screenshot({ path: `${process.env.FUNUI_SHOTS}/running-${name}-${w}x${h}.png` }); + } const main = await page.evaluate(inspect); if (main.over[0] > 0 || main.over[1] > 0) note(`page overflows by ${main.over}`); main.lanes.forEach((m) => note(m)); + main.header.forEach((m) => note(m)); for (const [label, text] of WINDOWS) { await page.getByText(text).first().click({ timeout: 1500 }).catch(() => note(`${label} cannot be opened`)); await page.waitForTimeout(500); diff --git a/app/ui/catalogue/catalogue.js b/app/ui/catalogue/catalogue.js index 0c2599a2..0d161f50 100644 --- a/app/ui/catalogue/catalogue.js +++ b/app/ui/catalogue/catalogue.js @@ -19,7 +19,8 @@ const GROUPS = [ { id: "motion", title: "Motion", match: (n) => /^--dur-|^--ease-/.test(n), render: renderMotion }, { id: "state", title: "States", match: (n) => /^--(bw|disabled-opacity)$/.test(n), render: renderState }, { id: "density", title: "Density", match: (n) => n.startsWith("--cell-"), render: renderBar }, - { id: "layout", title: "Layout", match: (n) => /^--menubar-h$/.test(n), render: renderBar }, + { id: "layout", title: "Layout", match: (n) => /^--(menubar-h|gutter|control-col)$/.test(n), render: renderBar }, + { id: "size", title: "Component sizes", match: (n) => /^--(bw-2|ring-w|blur-|shadow-blur|mark-size|tick-|thumb-size|toggle-w|slider-|list-control-w|wheel-|skeleton-w|tile-|field-min-w|menu-min-w|note-max-w|split-|dialog-w|popover-max-w|drawer-|settings-|modal-h|listbox|textarea|window-field|win-margin|lane-)/.test(n), render: renderBar }, // Colour is last and greedy: anything left that a browser accepts as a colour. { id: "colour", title: "Colour", match: isColourName, render: renderSwatch }, ]; diff --git a/app/ui/composer/elements/button.css b/app/ui/composer/elements/button.css index 233f9d98..98b3cb48 100644 --- a/app/ui/composer/elements/button.css +++ b/app/ui/composer/elements/button.css @@ -11,7 +11,7 @@ .cx-btn-xl { height: var(--ctl-h-xl); padding: 0 var(--ctl-pad-x-xl); font-size: var(--fs-4); } .cx-btn-lg { height: var(--ctl-h-lg); padding: 0 var(--ctl-pad-x-lg); font-size: var(--fs-5); } .cx-btn-md { height: var(--ctl-h-md); padding: 0 var(--ctl-pad-x-md); font-size: var(--fs-5); } -.cx-btn-menu { height: 26px; padding: 0 var(--sp-4); font-size: var(--fs-5); } +.cx-btn-menu { height: var(--ctl-h-menu); padding: 0 var(--sp-4); font-size: var(--fs-5); } .cx-btn-sm { height: var(--ctl-h-sm); padding: 0 var(--ctl-pad-x-sm); font-size: var(--fs-6); } .cx-btn:hover:not(:disabled) { border-color: var(--line-hover); background: var(--hover); } @@ -72,8 +72,8 @@ } .cx-btn-spin { - width: 11px; height: 11px; border-radius: var(--r-pill); - border: 2px solid color-mix(in srgb, currentColor 30%, transparent); + width: var(--ctl-icon-xs); height: var(--ctl-icon-xs); border-radius: var(--r-pill); + border: var(--bw-2) solid color-mix(in srgb, currentColor 30%, transparent); border-top-color: currentColor; animation: cx-spin 800ms linear infinite; } diff --git a/app/ui/composer/elements/choice.css b/app/ui/composer/elements/choice.css index 1f790584..e1ea71ae 100644 --- a/app/ui/composer/elements/choice.css +++ b/app/ui/composer/elements/choice.css @@ -7,15 +7,15 @@ .cx-check { display: inline-flex; } .cx-check-box { - width: 16px; height: 16px; flex: none; + width: var(--sp-7); height: var(--sp-7); flex: none; border: var(--bw) solid var(--line); border-radius: var(--r-2); background: var(--elev-2); display: inline-flex; align-items: center; justify-content: center; transition: background var(--dur-1) var(--ease-standard), border-color var(--dur-1) var(--ease-standard); } .cx-check-box::after { - content: ""; width: 9px; height: 5px; - border-left: 2px solid var(--on-accent); border-bottom: 2px solid var(--on-accent); + content: ""; width: var(--tick-w); height: var(--tick-h); + border-left: var(--bw-2) solid var(--on-accent); border-bottom: var(--bw-2) solid var(--on-accent); transform: rotate(-45deg) translateY(-1px) scale(.6); opacity: 0; transition: opacity var(--dur-1) var(--ease-standard), transform var(--dur-1) var(--ease-standard); } @@ -23,7 +23,7 @@ .cx-check-input:checked + .cx-check-face .cx-check-box::after { opacity: 1; transform: rotate(-45deg) translateY(-1px) scale(1); } .cx-check-input:indeterminate + .cx-check-face .cx-check-box { background: var(--accent); border-color: var(--accent); } .cx-check-input:indeterminate + .cx-check-face .cx-check-box::after { - opacity: 1; width: 8px; height: 0; border-bottom: 2px solid var(--on-accent); + opacity: 1; width: var(--sp-4); height: 0; border-bottom: var(--bw-2) solid var(--on-accent); border-left: 0; transform: none; } .cx-check-input:focus-visible + .cx-check-face .cx-check-box { border-color: var(--accent); box-shadow: var(--focus-ring); } @@ -47,7 +47,7 @@ .cx-check-label { font-size: var(--fs-4); line-height: var(--lh-4); color: var(--text); } .cx-checklist { display: flex; flex-direction: column; - max-height: 200px; overflow-y: auto; + max-height: var(--listbox-max-h); overflow-y: auto; border: var(--bw) solid var(--line); border-radius: var(--r-3); padding: var(--sp-3) var(--sp-4); } @@ -55,12 +55,12 @@ .cx-radio-group { display: flex; gap: var(--sp-4); } .cx-radio-vertical { flex-direction: column; gap: var(--sp-2); } .cx-radio-dot { - width: 16px; height: 16px; flex: none; border-radius: var(--r-pill); + width: var(--sp-7); height: var(--sp-7); flex: none; border-radius: var(--r-pill); border: var(--bw) solid var(--line); background: var(--elev-2); display: inline-flex; align-items: center; justify-content: center; } .cx-radio-dot::after { - content: ""; width: 8px; height: 8px; border-radius: var(--r-pill); + content: ""; width: var(--sp-4); height: var(--sp-4); border-radius: var(--r-pill); background: var(--accent); transform: scale(0); transition: transform var(--dur-1) var(--ease-standard); } @@ -92,17 +92,17 @@ .cx-toggle-track { - width: 34px; height: 20px; flex: none; border-radius: var(--r-pill); + width: var(--toggle-w); height: var(--sp-8); flex: none; border-radius: var(--r-pill); background: var(--line); position: relative; transition: background var(--dur-1) var(--ease-standard); } .cx-toggle-knob { - position: absolute; top: 2px; left: 2px; width: 16px; height: 16px; + position: absolute; top: var(--sp-1); left: var(--sp-1); width: var(--sp-7); height: var(--sp-7); border-radius: var(--r-pill); background: var(--elev-1); transition: transform var(--dur-1) var(--ease-standard); } .cx-toggle-input:checked + .cx-check-face .cx-toggle-track { background: var(--accent); } -.cx-toggle-input:checked + .cx-check-face .cx-toggle-track .cx-toggle-knob { transform: translateX(14px); } +.cx-toggle-input:checked + .cx-check-face .cx-toggle-track .cx-toggle-knob { transform: translateX(calc(var(--toggle-w) - var(--sp-7) - 2 * var(--sp-1))); } .cx-toggle-input:focus-visible + .cx-check-face .cx-toggle-track { box-shadow: var(--focus-ring); } /* Colour: the swatch sized to the control height so it lines up with every @@ -124,7 +124,7 @@ cursor: pointer; } -.cx-swatch::-webkit-color-swatch-wrapper { padding: 2px; } +.cx-swatch::-webkit-color-swatch-wrapper { padding: var(--sp-1); } .cx-swatch::-webkit-color-swatch { border: 0; border-radius: var(--r-2); } .cx-swatch::-moz-color-swatch { border: 0; border-radius: var(--r-2); } diff --git a/app/ui/composer/elements/gallery.css b/app/ui/composer/elements/gallery.css index a50fffd9..7a2e1a0f 100644 --- a/app/ui/composer/elements/gallery.css +++ b/app/ui/composer/elements/gallery.css @@ -2,7 +2,7 @@ * 280px panel however wide the window is. */ .cx-gallery-wrap { container-type: inline-size; width: 100%; } .cx-gallery { - display: grid; gap: clamp(6px, 2.5cqw, 12px); + display: grid; gap: clamp(var(--sp-3), 2.5cqw, var(--sp-6)); grid-template-columns: repeat(auto-fill, minmax(var(--cell, var(--cell-thumb)), 1fr)); } .cx-gallery[data-cols="1"] { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -23,7 +23,7 @@ display: flex; align-items: center; justify-content: center; } .cx-cell-img { width: 100%; height: 100%; object-fit: cover; display: block; } -.cx-cell-glyph { font-size: clamp(18px, calc(var(--cell, 96px) * .3), 34px); color: var(--faint); } +.cx-cell-glyph { font-size: clamp(var(--cell-glyph-min), calc(var(--cell, var(--cell-default)) * .3), var(--cell-glyph-max)); color: var(--faint); } .cx-cell-badge, .cx-cell-duration { position: absolute; bottom: var(--sp-1); font-size: var(--fs-8); padding: 1px var(--sp-2); border-radius: var(--r-1); @@ -31,10 +31,10 @@ } .cx-cell-badge { left: var(--sp-1); } .cx-cell-duration { right: var(--sp-1); font-variant-numeric: tabular-nums; } -.cx-cell-flags { position: absolute; top: 2px; right: 2px; display: flex; gap: var(--sp-1); pointer-events: none; } -.cx-cell-flag { font-size: 11px; font-weight: 700; line-height: 1; padding: 2px 4px; border-radius: var(--r-1); background: var(--accent); color: var(--void); } +.cx-cell-flags { position: absolute; top: var(--sp-1); right: var(--sp-1); display: flex; gap: var(--sp-1); pointer-events: none; } +.cx-cell-flag { font-size: var(--fs-7); font-weight: 700; line-height: 1; padding: var(--sp-1) var(--sp-2); border-radius: var(--r-1); background: var(--accent); color: var(--void); } .cx-cell-name { - font-size: clamp(11px, calc(var(--cell, 96px) * .115), 13px); + font-size: clamp(var(--fs-7), calc(var(--cell, var(--cell-default)) * .115), var(--fs-4)); line-height: var(--lh-snug); padding: 0 var(--sp-3) var(--sp-3); text-align: left; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; @@ -62,7 +62,7 @@ .cx-media-row:hover { border-color: var(--line-hover); background: var(--elev-2); } .cx-media-row.cx-on { border-color: var(--accent); background: var(--accent-soft); } .cx-media-row-thumb { - position: relative; flex: none; inline-size: 40px; aspect-ratio: 16 / 10; + position: relative; flex: none; inline-size: var(--sp-11); aspect-ratio: 16 / 10; display: flex; align-items: center; justify-content: center; background: var(--void); border-radius: var(--r-1); overflow: hidden; } @@ -96,7 +96,7 @@ /* A floor and a ceiling. A clip grows with its length (flex-grow, set by the element), and one clip in a project must not become the whole strip. --strip-w is the zoom level, set on .cx-strip itself and inherited. */ - flex: none; width: var(--strip-w, 72px); min-inline-size: var(--strip-w, 72px); + flex: none; width: var(--strip-w, var(--cell-thumb)); min-inline-size: var(--strip-w, var(--cell-thumb)); max-inline-size: var(--cell-panel); aspect-ratio: 16 / 10; padding: 0; border: var(--bw) solid var(--line); border-radius: var(--r-2); diff --git a/app/ui/composer/elements/input.css b/app/ui/composer/elements/input.css index cdbdb9ca..2bc42881 100644 --- a/app/ui/composer/elements/input.css +++ b/app/ui/composer/elements/input.css @@ -30,14 +30,16 @@ font-size: var(--fs-4); line-height: var(--lh-snug); resize: vertical; min-height: var(--ctl-h-xl); } +/* In a window the box shares the room with its tabs, hint and folds: it gives way as the screen gets shorter, so the window does not scroll inside itself. */ +.cx-window .cx-textarea { max-block-size: min(28dvh, var(--window-field-max-h)); } .cx-autogrow { resize: none; overflow: hidden; } .cx-fold { min-height: var(--ctl-h-md); height: var(--ctl-h-md); padding: var(--sp-2) var(--ctl-pad-x-sm); font-size: var(--fs-5); } -.cx-fold:not(:focus) { padding-block: 0; line-height: calc(var(--ctl-h-md) - 2px); } /* folded: the first line centred, the rest fully out of sight */ +.cx-fold:not(:focus) { padding-block: 0; line-height: calc(var(--ctl-h-md) - var(--bw-2)); } /* folded: the first line centred, the rest fully out of sight */ .cx-search { appearance: none; } .cx-search::-webkit-search-cancel-button { filter: grayscale(1) opacity(.6); } -.cx-filter { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 220px; } +.cx-filter { display: flex; flex-direction: column; gap: var(--sp-3); min-width: var(--field-min-w); } /* filterList always builds its own search box, which is right everywhere it is the ONLY way to narrow the list -- and wrong stacked under a search box that already re-queries the server on every keystroke: two boxes doing the @@ -48,7 +50,7 @@ .cx-node-picker-results .cx-filter > .cx-search { display: none; } .cx-filter-list { display: flex; flex-direction: column; gap: 1px; - max-height: 240px; overflow-y: auto; overflow-x: hidden; + max-height: var(--textarea-max-h); overflow-y: auto; overflow-x: hidden; border: var(--bw) solid var(--line); border-radius: var(--r-3); background: var(--elev-1); padding: var(--sp-1); } @@ -78,7 +80,7 @@ kit; there is no path from item data to a raw colour. */ .cx-filter-icon { display: inline-flex; align-items: center; justify-content: center; - width: 22px; height: 22px; flex: 0 0 auto; border-radius: var(--r-2); + width: var(--ctl-h-chip); height: var(--ctl-h-chip); flex: 0 0 auto; border-radius: var(--r-2); background: var(--elev-3); color: var(--text); font-size: var(--fs-6); line-height: 1; /* Optical, against the label's cap-height, not the row's own top edge. */ margin-block-start: 1px; diff --git a/app/ui/composer/elements/layout.css b/app/ui/composer/elements/layout.css index ef8e645f..e6d89bbd 100644 --- a/app/ui/composer/elements/layout.css +++ b/app/ui/composer/elements/layout.css @@ -104,7 +104,7 @@ /* One accent mark per panel. Carried over from v4, where it is what makes a head read as the top of something rather than as a strip of grey. */ .cx-panel-title::before { - content: ""; flex: none; inline-size: 5px; block-size: 5px; + content: ""; flex: none; inline-size: var(--mark-size); block-size: var(--mark-size); border-radius: var(--r-pill); background: var(--accent); } /* Wraps, like the head around it. The head was made to wrap when a zone got @@ -167,7 +167,7 @@ .cx-list-row:last-child { border-bottom: 0; } .cx-list-label { font-size: var(--fs-4); flex: 1; min-width: 0; } .cx-list-hint { font-size: var(--fs-7); color: var(--muted); } -.cx-list-control { flex: none; width: 92px; } +.cx-list-control { flex: none; width: var(--list-control-w); } /* Separated from the row's own control by a rule, so the arrows read as * "reorder this row" rather than "adjust that number". */ .cx-list-actions { @@ -187,7 +187,7 @@ } .cx-tabs-underline { border-bottom: var(--bw) solid var(--line); gap: var(--sp-5); } .cx-tabs-underline .cx-tab { - padding: var(--sp-3) 0; border-bottom: 2px solid transparent; margin-bottom: -1px; + padding: var(--sp-3) 0; border-bottom: var(--bw-2) solid transparent; margin-bottom: -1px; } .cx-tabs-underline .cx-tab.cx-on { color: var(--text); border-bottom-color: var(--accent); } .cx-tabs-dock .cx-tab { @@ -198,7 +198,7 @@ .cx-tabs-dock .cx-tab.cx-on { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); } .cx-tab:hover { color: var(--text); } -.cx-split { display: flex; width: 100%; min-height: 120px; min-inline-size: 0; } +.cx-split { display: flex; width: 100%; min-height: var(--split-min-h); min-inline-size: 0; } .cx-split-v { flex-direction: column; } /* A column, so what is inside a pane inherits the pane's height instead of sizing to its own content. A panel in a pane was the right size with a body @@ -217,7 +217,7 @@ a 360px viewport. Wrapping rather than a media query because the kit sizes itself from its container, not from the window. */ .cx-split-h { flex-wrap: wrap; } -.cx-split-h > .cx-split-pane { min-inline-size: min(100%, 260px); } +.cx-split-h > .cx-split-pane { min-inline-size: min(100%, var(--split-pane-min)); } .cx-split-h > .cx-split-pane:first-child { max-inline-size: 100%; } .cx-split-bar { flex: none; background: transparent; position: relative; } .cx-split-h > .cx-split-bar { width: var(--gutter); cursor: col-resize; } @@ -267,7 +267,7 @@ } .cx-rail-item:hover { background: var(--hover); color: var(--text); } .cx-rail-item.cx-on { background: var(--accent-soft); color: var(--accent-text); } -.cx-rail-icon { width: 18px; text-align: center; } +.cx-rail-icon { width: var(--ctl-h-icon); text-align: center; } /* Workspace: a centre that shrinks, panels docked either side. The rails hold the toggles and never collapse, so the control for a panel is @@ -292,7 +292,7 @@ heading broke mid-word. A panel is as wide as a settings row needs; when the window cannot afford two of them it stops docking them (below). */ flex: 0 0 auto; - inline-size: clamp(268px, 24vw, 360px); + inline-size: clamp(var(--drawer-min-w), 24vw, var(--drawer-max-w)); min-block-size: 0; overflow: auto; display: flex; flex-direction: column; @@ -349,7 +349,8 @@ button floating above the first panel. */ .cx-frame-head { display: flex; align-items: center; - block-size: var(--menubar-h); padding-inline: var(--gutter); + /* A minimum, so a bar whose items wrap in a narrow window grows a line instead of spilling over the panels. */ + min-block-size: var(--menubar-h); padding-inline: var(--gutter); padding-block: var(--sp-1); border-block-end: var(--bw) solid var(--line); background: var(--grad-band); } .cx-frame-head > * { flex: 1 1 auto; min-inline-size: 0; } @@ -375,7 +376,7 @@ position: absolute; inset-block: 0; z-index: 1; - inline-size: min(86vw, 360px); + inline-size: min(86vw, var(--drawer-max-w)); background: var(--elev-1); box-shadow: var(--shadow-3); } diff --git a/app/ui/composer/elements/nle.css b/app/ui/composer/elements/nle.css index 62ab9db9..3624a175 100644 --- a/app/ui/composer/elements/nle.css +++ b/app/ui/composer/elements/nle.css @@ -55,5 +55,5 @@ .cx-nle-playhead { position: absolute; inset-block: 0; inline-size: 0; z-index: 2; pointer-events: none; - border-inline-start: 2px solid var(--accent-hi); + border-inline-start: var(--bw-2) solid var(--accent-hi); } diff --git a/app/ui/composer/elements/overlay.css b/app/ui/composer/elements/overlay.css index a6e36cd0..4833a1fe 100644 --- a/app/ui/composer/elements/overlay.css +++ b/app/ui/composer/elements/overlay.css @@ -27,7 +27,7 @@ * whole app painted twice, side by side, until a window resize forced a * repaint. */ .cx-modal-stacked { - box-shadow: 0 20px 48px color-mix(in srgb, var(--shadow-ink) 90%, transparent); + box-shadow: 0 var(--sp-8) var(--shadow-blur-lg) color-mix(in srgb, var(--shadow-ink) 90%, transparent); } @keyframes cx-pop { from { opacity: 0; transform: translateY(-6px) scale(.99); } } @@ -36,7 +36,7 @@ itself grows and shrinks on every click, which nothing in a real System Settings window does. A real height, not a max, holds the frame still; .cx-modal-body's own scroll takes the rest. */ -.cx-settings-modal { height: min(660px, 90vh); } /* v4's own window size, verbatim */ +.cx-settings-modal { height: min(var(--modal-h), 90vh); } /* v4's own window size, verbatim */ .cx-modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-5); @@ -87,11 +87,11 @@ repositioning could bring it back: anchor.js can move a box, it cannot shrink one. Measured at 1436px inside a 1280px viewport. */ max-height: 60vh; overflow-y: auto; - max-inline-size: min(92vw, 480px); + max-inline-size: min(92vw, var(--popover-max-w)); overflow-wrap: anywhere; animation: cx-pop var(--dur-1) var(--ease-standard); } -.cx-popover-menu { min-width: 180px; } +.cx-popover-menu { min-width: var(--menu-min-w); } /* a popover holding a panel (settings, fields), not a list of items, needs room to the sides */ .cx-popover[role="dialog"] { padding: var(--sp-5) var(--sp-6); } @@ -107,7 +107,7 @@ .cx-menu-item.cx-danger { color: var(--danger); } .cx-menu-label { flex: 1; } .cx-menu-hint { font-size: var(--fs-7); color: var(--faint); } -.cx-menu-icon { width: 16px; text-align: center; color: var(--muted); } +.cx-menu-icon { width: var(--sp-7); text-align: center; color: var(--muted); } .cx-menu-sep { height: 1px; background: var(--line); margin: var(--sp-2) 0; } .cx-menu-heading { padding: var(--sp-2) var(--sp-4); font-size: var(--fs-7); letter-spacing: .06em; text-transform: uppercase; color: var(--faint); } @@ -117,10 +117,10 @@ border: var(--bw) solid var(--line); border-radius: var(--r-2); padding: var(--sp-2) var(--sp-3); font-size: var(--fs-6); box-shadow: var(--shadow-2); - max-width: 260px; + max-width: var(--note-max-w); } -.cx-autocomplete { min-width: 220px; inline-size: min(92vw, 420px); padding: var(--sp-1); } +.cx-autocomplete { min-width: var(--field-min-w); inline-size: min(92vw, var(--dialog-w)); padding: var(--sp-1); } /* a suggestion is one line: the trigger, then as much of its prompt as fits */ .cx-autocomplete .cx-menu-label { flex: none; max-inline-size: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .cx-autocomplete .cx-menu-hint { flex: 1 1 0; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } @@ -151,7 +151,7 @@ .cx-window-body { flex: 1; overflow: auto; padding: var(--sp-5); } .cx-rolled .cx-window-body, .cx-rolled .cx-window-grip { display: none; } .cx-window-grip { - position: absolute; right: 0; bottom: 0; width: 16px; height: 16px; + position: absolute; right: 0; bottom: 0; width: var(--sp-7); height: var(--sp-7); cursor: nwse-resize; background: linear-gradient(135deg, transparent 50%, var(--line) 50%, var(--line) 60%, transparent 60%); } @@ -167,13 +167,13 @@ .cx-slideover-layer { align-items: stretch; } .cx-slideover { position: relative; margin-left: auto; - width: min(420px, 92vw); display: flex; flex-direction: column; + width: min(var(--dialog-w), 92vw); display: flex; flex-direction: column; background: var(--elev-1); border-left: var(--bw) solid var(--line); box-shadow: var(--shadow-3); animation: cx-slide-in var(--dur-2) var(--ease-standard); } .cx-slideover-left { margin-left: 0; margin-right: auto; border-left: 0; border-right: var(--bw) solid var(--line); } -@keyframes cx-slide-in { from { transform: translateX(12px); opacity: 0; } } +@keyframes cx-slide-in { from { transform: translateX(var(--sp-6)); opacity: 0; } } .cx-slideover-head { display: flex; align-items: center; justify-content: space-between; padding: var(--sp-5) var(--sp-6); border-bottom: var(--bw) solid var(--line); diff --git a/app/ui/composer/elements/polish.css b/app/ui/composer/elements/polish.css index 03f31f48..9d7c5740 100644 --- a/app/ui/composer/elements/polish.css +++ b/app/ui/composer/elements/polish.css @@ -45,7 +45,7 @@ body { -webkit-font-smoothing: antialiased; letter-spacing: -.003em; } .cx-filter-list { border-color: var(--line); border-radius: var(--r-4); } /* hairlines are quieter, rows roomier */ -.cx-segmented { border-color: transparent; background: var(--elev-2); border-radius: var(--r-4); padding: 2px; } +.cx-segmented { border-color: transparent; background: var(--elev-2); border-radius: var(--r-4); padding: var(--sp-1); } .cx-segmented .cx-segment { border-radius: var(--r-3); } /* timeline: quiet clips, the selected one speaks */ diff --git a/app/ui/composer/elements/settings.css b/app/ui/composer/elements/settings.css index 02344a20..ad48f9ad 100644 --- a/app/ui/composer/elements/settings.css +++ b/app/ui/composer/elements/settings.css @@ -1,10 +1,10 @@ /* The Settings window, after macOS System Settings / About: a sidebar that stays open, a large title, * and rows grouped into rounded inset cards -- label on the left, value on the right, hairlines between. */ -.cx-settings-modal { height: min(680px, 92vh); } +.cx-settings-modal { height: min(var(--settings-h), 92vh); } .cx-settings-modal .cx-modal-body { padding: 0; } -.cx-settings-body.cx-stack { display: grid; grid-template-columns: 232px minmax(0, 1fr); block-size: 100%; min-block-size: 0; } +.cx-settings-body.cx-stack { display: grid; grid-template-columns: var(--settings-rail-w) minmax(0, 1fr); block-size: 100%; min-block-size: 0; } /* sidebar */ .cx-settings-rail { @@ -15,7 +15,7 @@ .cx-settings-rail .cx-search { inline-size: 100%; } .cx-settings-rail .cx-filter-list { gap: var(--sp-1); } .cx-settings-rail .cx-filter-row { gap: var(--sp-5); padding: var(--sp-3) var(--sp-4); border-radius: var(--r-4); font-size: var(--fs-4); } -.cx-settings-rail .cx-filter-icon { inline-size: 24px; block-size: 24px; border-radius: 6px; font-size: var(--fs-5); margin: 0; } +.cx-settings-rail .cx-filter-icon { inline-size: var(--sp-9); block-size: var(--sp-9); border-radius: var(--sp-3); font-size: var(--fs-5); margin: 0; } .cx-settings-rail .cx-filter-row.cx-on { background: var(--accent); color: var(--on-accent); } .cx-settings-rail .cx-filter-row.cx-on .cx-filter-label { font-weight: var(--fw-medium); } .cx-settings-rail .cx-filter-gap { block-size: var(--sp-5); } @@ -34,7 +34,7 @@ /* a run of rows (and switches) is one card */ :is(.cx-settings-content, .cx-modal-body) .cx-stack > :is(.cx-settings-row, .cx-toggle-row) { background-color: var(--elev-2); border: 0; border-radius: var(--r-5); - padding: var(--sp-5) var(--sp-7); min-block-size: 40px; display: flex; align-items: center; + padding: var(--sp-5) var(--sp-7); min-block-size: var(--sp-11); display: flex; align-items: center; } :is(.cx-settings-content, .cx-modal-body) .cx-stack > .cx-toggle-row > label { inline-size: 100%; display: flex; } :is(.cx-settings-content, .cx-modal-body) .cx-stack > :is(.cx-settings-row, .cx-toggle-row):has(+ :is(.cx-settings-row, .cx-toggle-row)) { border-end-start-radius: 0; border-end-end-radius: 0; } diff --git a/app/ui/composer/elements/slider.css b/app/ui/composer/elements/slider.css index 14575810..7c3520a2 100644 --- a/app/ui/composer/elements/slider.css +++ b/app/ui/composer/elements/slider.css @@ -2,29 +2,29 @@ .cx-range { appearance: none; -webkit-appearance: none; - flex: 1; min-width: 80px; height: 18px; background: transparent; cursor: pointer; + flex: 1; min-width: var(--slider-min-w); height: var(--ctl-h-icon); background: transparent; cursor: pointer; /* --fill is written by the element as the value changes, so the filled part * of the track follows the theme's accent without JS naming a colour. */ --fill: 0%; } .cx-range::-webkit-slider-runnable-track { - height: 4px; border-radius: var(--r-pill); + height: var(--sp-2); border-radius: var(--r-pill); background: linear-gradient(to right, var(--accent) var(--fill), var(--line) var(--fill)); } .cx-range::-moz-range-track { - height: 4px; border-radius: var(--r-pill); + height: var(--sp-2); border-radius: var(--r-pill); background: linear-gradient(to right, var(--accent) var(--fill), var(--line) var(--fill)); } .cx-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; - width: 14px; height: 14px; margin-top: -5px; + width: var(--thumb-size); height: var(--thumb-size); margin-top: -5px; border-radius: var(--r-pill); background: var(--elev-1); - border: 2px solid var(--accent); + border: var(--bw-2) solid var(--accent); transition: transform var(--dur-1) var(--ease-standard); } .cx-range::-moz-range-thumb { - width: 14px; height: 14px; border-radius: var(--r-pill); - background: var(--elev-1); border: 2px solid var(--accent); + width: var(--thumb-size); height: var(--thumb-size); border-radius: var(--r-pill); + background: var(--elev-1); border: var(--bw-2) solid var(--accent); } .cx-range:hover::-webkit-slider-thumb { transform: scale(1.12); } .cx-range:focus-visible { outline: none; } @@ -32,7 +32,7 @@ .cx-range:focus-visible::-moz-range-thumb { box-shadow: var(--focus-ring); } .cx-range:disabled { opacity: var(--disabled-opacity); cursor: default; } -.cx-slider-sm .cx-range { height: 14px; } +.cx-slider-sm .cx-range { height: var(--thumb-size); } .cx-readout { font-family: var(--font-mono); font-variant-numeric: tabular-nums; diff --git a/app/ui/composer/elements/stage.css b/app/ui/composer/elements/stage.css index 723f6a17..d1979f0a 100644 --- a/app/ui/composer/elements/stage.css +++ b/app/ui/composer/elements/stage.css @@ -1,5 +1,5 @@ .cx-stage { position: absolute; pointer-events: none; overflow: hidden; z-index: 2; } .cx-stage-item { position: absolute; pointer-events: auto; cursor: move; touch-action: none; } .cx-stage-item img { display: block; } -.cx-stage-grip { position: absolute; inset-inline-end: -5px; inset-block-end: -5px; inline-size: 10px; block-size: 10px; background: var(--accent); border: var(--bw) solid #000; cursor: nwse-resize; border-radius: var(--r-1); } +.cx-stage-grip { position: absolute; inset-inline-end: -5px; inset-block-end: -5px; inline-size: var(--sp-5); block-size: var(--sp-5); background: var(--accent); border: var(--bw) solid #000; cursor: nwse-resize; border-radius: var(--r-1); } :has(> .cx-stage) { position: relative; } diff --git a/app/ui/composer/elements/status.css b/app/ui/composer/elements/status.css index d704c7b1..3b294559 100644 --- a/app/ui/composer/elements/status.css +++ b/app/ui/composer/elements/status.css @@ -4,13 +4,13 @@ border: var(--bw) solid var(--line); border-radius: var(--r-pill); font-size: var(--fs-6); color: var(--muted); white-space: nowrap; } -.cx-chip-dot { width: 6px; height: 6px; border-radius: var(--r-pill); background: currentColor; } +.cx-chip-dot { width: var(--sp-3); height: var(--sp-3); border-radius: var(--r-pill); background: currentColor; } .cx-chip-good { color: var(--good); border-color: color-mix(in srgb, var(--good) 30%, var(--line)); } .cx-chip-warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 30%, var(--line)); } .cx-chip-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 30%, var(--line)); } .cx-chip-info { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 30%, var(--line)); } -.cx-dot { width: 8px; height: 8px; border-radius: var(--r-pill); background: var(--muted); display: inline-block; flex: none; } +.cx-dot { width: var(--sp-4); height: var(--sp-4); border-radius: var(--r-pill); background: var(--muted); display: inline-block; flex: none; } .cx-dot-good { background: var(--good); } .cx-dot-warn { background: var(--warn); } .cx-dot-danger { background: var(--danger); } @@ -33,7 +33,7 @@ .cx-inline-error { font-size: var(--fs-6); color: var(--danger); } .cx-progress { - width: 100%; height: 4px; border-radius: var(--r-pill); + width: 100%; height: var(--sp-2); border-radius: var(--r-pill); background: var(--line); overflow: hidden; } .cx-progress-fill { @@ -47,12 +47,12 @@ .cx-spinner { display: inline-block; border-radius: var(--r-pill); - border: 2px solid color-mix(in srgb, var(--muted) 30%, transparent); + border: var(--bw-2) solid color-mix(in srgb, var(--muted) 30%, transparent); border-top-color: var(--accent); animation: cx-spin 800ms linear infinite; } -.cx-spinner-md { width: 16px; height: 16px; } -.cx-spinner-sm { width: 12px; height: 12px; } +.cx-spinner-md { width: var(--sp-7); height: var(--sp-7); } +.cx-spinner-sm { width: var(--sp-6); height: var(--sp-6); } .cx-empty { display: flex; flex-direction: column; align-items: center; gap: var(--sp-3); @@ -80,9 +80,9 @@ background-size: 200% 100%; animation: cx-shimmer 1.4s linear infinite; } -.cx-skeleton-line .cx-skeleton-cell { height: 10px; } +.cx-skeleton-line .cx-skeleton-cell { height: var(--sp-5); } .cx-skeleton-line .cx-skeleton-cell:last-child { width: 60%; } -.cx-skeleton-block .cx-skeleton-cell { height: 44px; } +.cx-skeleton-block .cx-skeleton-cell { height: var(--lane-h-audio); } .cx-skeleton-grid .cx-skeleton-cell { aspect-ratio: 16 / 10; } @keyframes cx-shimmer { to { background-position: -200% 0; } } @@ -101,7 +101,7 @@ .cx-toast-good { border-color: color-mix(in srgb, var(--good) 45%, var(--line)); } .cx-toast-warn { border-color: color-mix(in srgb, var(--warn) 45%, var(--line)); } .cx-toast-danger { border-color: color-mix(in srgb, var(--danger) 45%, var(--line)); } -@keyframes cx-rise { from { opacity: 0; transform: translateY(8px); } } +@keyframes cx-rise { from { opacity: 0; transform: translateY(var(--sp-4)); } } .cx-progress-inline { display: inline-flex; align-items: center; gap: var(--sp-4); min-inline-size: 0; } -.cx-progress-inline .cx-progress { inline-size: 90px; flex: none; } +.cx-progress-inline .cx-progress { inline-size: var(--skeleton-w); flex: none; } diff --git a/app/ui/composer/elements/tile.css b/app/ui/composer/elements/tile.css index 0ace8c41..73ad9fd0 100644 --- a/app/ui/composer/elements/tile.css +++ b/app/ui/composer/elements/tile.css @@ -1,19 +1,19 @@ .cx-grid { display: grid !important; gap: var(--sp-5); } .cx-grid-pair { grid-template-columns: 1fr 1fr; gap: var(--sp-4); margin-block-start: var(--sp-5); } -.cx-grid-cards { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); } +.cx-grid-cards { grid-template-columns: repeat(auto-fill, minmax(var(--tile-col), 1fr)); } .cx-tile { position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: var(--sp-1); padding: var(--sp-5) var(--sp-6); border: 0; border-radius: var(--r-5); background: var(--elev-2); color: var(--text); text-align: left; cursor: pointer; } .cx-tile:hover { background: var(--hover); } .cx-tile-title { font-size: var(--fs-4); font-weight: var(--fw-medium); } .cx-tile-sub { font-size: var(--fs-6); color: var(--muted); } -.cx-tile-node { gap: var(--sp-2); min-block-size: 84px; padding: var(--sp-6) var(--sp-6) var(--sp-5); } +.cx-tile-node { gap: var(--sp-2); min-block-size: var(--tile-min-h); padding: var(--sp-6) var(--sp-6) var(--sp-5); } .cx-tile-node .cx-tile-title { font-weight: var(--fw-semibold); padding-inline-end: var(--sp-6); } .cx-tile-node .cx-tile-sub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-inline-size: 100%; } -.cx-tile-state { position: absolute; inset-block-start: var(--sp-6); inset-inline-end: var(--sp-6); inline-size: 8px; block-size: 8px; border-radius: var(--r-pill); background: var(--good); } -.cx-tile-state.cx-tile-needs { background: var(--warn); box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 25%, transparent); } +.cx-tile-state { position: absolute; inset-block-start: var(--sp-6); inset-inline-end: var(--sp-6); inline-size: var(--sp-4); block-size: var(--sp-4); border-radius: var(--r-pill); background: var(--good); } +.cx-tile-state.cx-tile-needs { background: var(--warn); box-shadow: 0 0 0 var(--ring-w) color-mix(in srgb, var(--warn) 25%, transparent); } -.cx-tile-add { align-items: center; justify-content: center; min-block-size: 84px; background: transparent; border: var(--bw) dashed var(--line); color: var(--muted); } +.cx-tile-add { align-items: center; justify-content: center; min-block-size: var(--tile-min-h); background: transparent; border: var(--bw) dashed var(--line); color: var(--muted); } .cx-tile-add .cx-tile-title { font-weight: var(--fw-medium); } @media (max-width: 1150px) { .cx-hint-low { display: none; } } diff --git a/app/ui/composer/elements/track.css b/app/ui/composer/elements/track.css index e8f29e39..5a7969c9 100644 --- a/app/ui/composer/elements/track.css +++ b/app/ui/composer/elements/track.css @@ -23,7 +23,7 @@ insetInlineStart in JS: a clip under the pixel floor must not push every clip after it out of step with the ruler and the playhead, which both stay in pure seconds*pxPerSecond regardless of any floor. */ -.cx-track-clips { position: relative; min-inline-size: 100%; block-size: 45px; } +.cx-track-clips { position: relative; min-inline-size: 100%; block-size: var(--lane-h-audio); } .cx-track-clip { position: absolute; inset-block: 0; padding: 0; border: var(--bw) solid var(--line); border-radius: var(--r-2); @@ -48,6 +48,6 @@ read as "this is where you are" the way a line through both does. */ .cx-track-playhead { position: absolute; inset-block: 0; inline-size: 0; - border-inline-start: 2px solid var(--accent-hi); + border-inline-start: var(--bw-2) solid var(--accent-hi); pointer-events: none; z-index: 1; } diff --git a/app/ui/composer/elements/wheel.css b/app/ui/composer/elements/wheel.css index 971bdc8f..2f0436e7 100644 --- a/app/ui/composer/elements/wheel.css +++ b/app/ui/composer/elements/wheel.css @@ -5,7 +5,7 @@ position: fixed; pointer-events: auto; border-radius: var(--r-pill); background: color-mix(in srgb, var(--elev-3) 92%, transparent); box-shadow: var(--shadow-3), inset 0 0 0 var(--bw) var(--line); - backdrop-filter: blur(6px); + backdrop-filter: blur(var(--blur-sm)); animation: cx-wheel-in var(--dur-1) var(--ease-standard); } @keyframes cx-wheel-in { from { opacity: 0; transform: scale(.9); } } @@ -24,7 +24,7 @@ .cx-wheel-item { position: absolute; transform: translate(-50%, -50%); display: flex; flex-direction: column; align-items: center; gap: var(--sp-1); - width: 70px; padding: var(--sp-1) 0; line-height: 1.15; overflow-wrap: anywhere; /* long names wrap inside the ring instead of sticking out of it */ + width: var(--wheel-item-w); padding: var(--sp-1) 0; line-height: 1.15; overflow-wrap: anywhere; /* long names wrap inside the ring instead of sticking out of it */ background: transparent; border: 0; color: var(--muted); font-size: var(--fs-7); cursor: pointer; text-align: center; transition: color var(--dur-1) var(--ease-standard), @@ -59,4 +59,4 @@ /* Half wheels sit ON the edge: the off-screen half is simply clipped by the * viewport, which is what gives the edge-panel silhouette. The flat side gets a * straight edge so it reads as pinned rather than cropped by accident. */ -.cx-wheel-half { backdrop-filter: blur(8px); } +.cx-wheel-half { backdrop-filter: blur(var(--blur-md)); } diff --git a/app/ui/composer/tests/rule_kit_uses_the_scale.test.js b/app/ui/composer/tests/rule_kit_uses_the_scale.test.js index 8ccdaef4..07a37f6c 100644 --- a/app/ui/composer/tests/rule_kit_uses_the_scale.test.js +++ b/app/ui/composer/tests/rule_kit_uses_the_scale.test.js @@ -1,6 +1,7 @@ // Sizes and gaps come from the scale in tokens.css (--sp-*, --ctl-h-*, --lane-*, ...), not from literals in element -// rules: a literal is a number nobody can change in one place. This is a ratchet: the count of literal pixel values -// in element CSS may go down, never up. Lowering it is the point; when it does, lower LITERAL_PX here too. +// rules: a literal is a number nobody can change in one place. There are none left. Exempt by design: a 1px hairline +// (that is --bw's own value), 0, token definitions (a line starting `--`, where a number belongs), and the width in a +// @media / @container condition (a custom property cannot be used there; the breakpoints are listed in tokens.css). import test from "node:test"; import assert from "node:assert/strict"; import { readdirSync, readFileSync } from "node:fs"; @@ -8,17 +9,15 @@ import { fileURLToPath } from "node:url"; import { dirname, join } from "node:path"; const dir = join(dirname(fileURLToPath(import.meta.url)), "..", "elements"); -const LITERAL_PX = 118; -test("element CSS does not grow new literal pixel sizes", () => { +test("element CSS has no literal pixel sizes", () => { let found = 0; for (const f of readdirSync(dir).filter((n) => n.endsWith(".css"))) { const css = readFileSync(join(dir, f), "utf8").replace(/\/\*[\s\S]*?\*\//g, ""); for (const decl of css.split(/[;{}]/)) { - if (/^\s*--/.test(decl)) continue; // a token definition is where a number belongs + if (/^\s*(--|@media|@container)/.test(decl)) continue; // a token definition is where a number belongs; a breakpoint cannot use one found += (decl.match(/(? { diff --git a/app/ui/features/generate/index.js b/app/ui/features/generate/index.js index f64108c2..c421c16d 100644 --- a/app/ui/features/generate/index.js +++ b/app/ui/features/generate/index.js @@ -141,7 +141,7 @@ export default { if (kept === false) tell(`Scene ${snap.scenes.findIndex((s) => s.id === root.id) + 1} was removed while it was being made, so its result is not on the timeline. It is in ComfyUI's output folder as ${images[images.length - 1].filename}.`); snap.scene_renders = structuredClone(p.project.scene_renders || {}); // ...and in what the next shot reads } - if (!made && !stopped && !said) tell("Nothing to generate: every scene is left out, a video clip or an Auto Montage piece."); + if (!made && !stopped && !said) tell("Nothing to generate: every scene is left out or a video clip."); } finally { busy = false; draw(); } } app.runner.units = (units, times) => runUnits(units, times); @@ -206,7 +206,7 @@ export default { if (key === drawn) return; // progress ticks must not rebuild the buttons drawn = key; const working = busy || held || g.state().phase === QUEUED || g.state().phase === RUNNING; // also a run this page did not start - const go = c.button.sm({ label: working ? "Generating…" : "▶ Generate", tone: "primary", disabled: working || !open, title: "Generate every scene on the timeline, except left-out scenes, video clips and Auto Montage pieces. An earlier render of a scene stays as a take.", + const go = c.button.sm({ label: working ? "Generating…" : "▶ Generate", tone: "primary", disabled: working || !open, title: "Generate every scene on the timeline, except left-out scenes and video clips. An earlier render of a scene stays as a take.", onClick: () => runUnits(unitsOf(p.scenes)) }); const one = c.button.sm({ label: picked > 1 ? `Selected (${picked})` : "Selected", title: "Generate only the picked scenes", disabled: working || !picked, onClick: () => runUnits(unitsOf(pickedScenes())) }); const stop = c.button.sm({ label: "■ Stop", tone: "danger", title: "Stop the run that is going, and any Upscale or Interpolate in progress", onClick: () => { diff --git a/app/ui/features/generate/progress.js b/app/ui/features/generate/progress.js index 85a7e3ac..c7af96c6 100644 --- a/app/ui/features/generate/progress.js +++ b/app/ui/features/generate/progress.js @@ -6,7 +6,7 @@ export const elapsed = (ms) => { const s = Math.max(0, Math.floor(ms / 1000)); r export default { id: "generate-progress", - mount: "timeline.actions", + mount: "timeline.toolbar.end", needs: ["generate"], setup({ host, app }) { const g = app.generate; diff --git a/app/ui/features/generate/warn.js b/app/ui/features/generate/warn.js index bba438de..9373c42c 100644 --- a/app/ui/features/generate/warn.js +++ b/app/ui/features/generate/warn.js @@ -4,7 +4,7 @@ import { composer as c } from "../../composer/composer.js"; export default { id: "generate-warn", - mount: "timeline.actions", + mount: "timeline.toolbar.end", needs: ["pipeline"], setup({ host, app }) { const chip = c.button.sm({ label: "⚠ Nothing encodes your prompt", tone: "ghost", disabled: true, diff --git a/app/ui/features/interpolate/index.js b/app/ui/features/interpolate/index.js index c5605f60..701c8df6 100644 --- a/app/ui/features/interpolate/index.js +++ b/app/ui/features/interpolate/index.js @@ -7,7 +7,7 @@ import { DEFAULTS, RTX, interpolate, modeLabel } from "./job.js"; export default { id: "interpolate", - mount: "timeline.actions", + mount: "timeline.toolbar.end", needs: ["project", "api", "selection"], modules: ["interpolate"], setup({ host, app }) { diff --git a/app/ui/features/montage/build.js b/app/ui/features/montage/build.js deleted file mode 100644 index 84593f4d..00000000 --- a/app/ui/features/montage/build.js +++ /dev/null @@ -1,64 +0,0 @@ -// Auto Montage, trailer-style: the lead clip is cut into segments that shrink as it goes, and after each one a segment from a -// pool of other rendered clips is cut in. Every piece reuses media that already exists and is its own unit (`reused`): Generate never -// makes it and it never lengthens the clip it was copied from. Pure. -import { trackFor } from "../../shell/audio.js"; -import { snapFrames, effFps, seconds, isVideoClip } from "../../shell/scenes.js"; - -const newId = () => "c" + Math.random().toString(36).slice(2, 10) + Date.now().toString(36); -const clone = (x) => JSON.parse(JSON.stringify(x)); - -/** What a clip can play from: {fps, from (seconds into its file), total (seconds), render?} or null when it has nothing yet. */ -export function playable(sc, p) { - const fps = effFps(sc, p); - if (seconds(sc, p) * fps < 9) return null; // shorter than the shortest piece the model can make - if (isVideoClip(sc)) return sc.source && sc.source.media_ref ? { fps, from: sc.source_in || 0, total: seconds(sc, p) } : null; - const r = (p.scene_renders || {})[sc.id]; - return r && r.media ? { fps, from: (r.inSec || 0) + (sc.source_in || 0), total: seconds(sc, p), render: r } : null; -} - -/** Cut a clip's length into [{start, frames}] (frames), each `base * decay^i` long (decay 1 = all equal), rounded DOWN to the frame grid so no piece reaches past the clip or overlaps the next. */ -export function chop(totalFrames, base, decay = 1) { - const out = []; - for (let at = 0, i = 0; at < totalFrames - 8; i += 1) { - const frames = snapFrames(Math.min(totalFrames - at, Math.max(9, Math.round(base * decay ** i))), "floor"); - out.push({ start: at, frames }); - at += frames; - } - return out; -} - -/** Append the montage to `p` (the scenes, and their renders). -> how many clips were added (0 = nothing could be built). */ -export function build(p, { leadId, poolIds, segmentFrames = 100, decay = 1, random = Math.random }) { - const find = (id) => p.scenes.find((s) => s.id === id); - const lead = find(leadId), leadSrc = lead && playable(lead, p); - const pool = (poolIds || []).map(find).filter((s) => s && playable(s, p)); - if (!leadSrc || !pool.length) return 0; - const base = Math.max(9, Math.round(segmentFrames)), dk = Math.min(1, Math.max(0.3, decay)); - const leadSegs = chop(snapFrames(leadSrc.total * leadSrc.fps, "floor"), base, dk); - // Each pool clip is its own queue read front to back: chance only picks WHICH clip to draw from next. - const queues = pool.map((sc) => ({ sc, src: playable(sc, p), cursor: 0, chunks: chop(snapFrames(playable(sc, p).total * playable(sc, p).fps, "floor"), base, 1) })).filter((q) => q.chunks.length); - if (!leadSegs.length || !queues.length) return 0; - const next = () => { - let open = queues.filter((q) => q.cursor < q.chunks.length); - if (!open.length) { queues.forEach((q) => { q.cursor = 0; }); open = queues; } // every clip used up: each starts over from its own beginning - const q = open[Math.floor(random() * open.length)]; - return { sc: q.sc, src: q.src, ...q.chunks[q.cursor++] }; - }; - const piece = (sc, src, start, frames) => { - const out = clone(sc), at = start / src.fps; - const id = newId(); - Object.assign(out, { id, gen_unit_id: id, reused: true, cut_offset_frames: 0, frames, rating: "", transition_to_next: "cut", transition_frames: null, frames_mode: "timeline", excluded: false, audio_separated: false, audio_volume: sc.audio_separated ? (trackFor(p, sc.id) || {}).volume ?? 1 : sc.audio_volume }); - if (isVideoClip(sc)) Object.assign(out, { source_in: src.from + at, source_dur: frames / src.fps }); - else { - out.source_in = 0; // the render entry below already starts where this piece does - p.scene_renders = p.scene_renders || {}; - p.scene_renders[out.id] = { media: src.render.media, inSec: src.from + at, renderPrompt: src.render.renderPrompt ? { ...src.render.renderPrompt } : null }; - } - return out; - }; - const built = []; - leadSegs.forEach((seg) => { built.push(piece(lead, leadSrc, seg.start, seg.frames)); const c = next(); built.push(piece(c.sc, c.src, c.start, c.frames)); }); - built[built.length - 1].transition_to_next = ""; - p.scenes.push(...built); - return built.length; -} diff --git a/app/ui/features/montage/build.test.js b/app/ui/features/montage/build.test.js deleted file mode 100644 index 160317b4..00000000 --- a/app/ui/features/montage/build.test.js +++ /dev/null @@ -1,66 +0,0 @@ -import test from "node:test"; -import assert from "node:assert/strict"; -import { build, chop, playable } from "./build.js"; -import { isGenerative, genUnitId } from "../../shell/scenes.js"; -import { removeScene } from "../../shell/edits.js"; - -const media = (n) => ({ filename: `${n}.mp4`, subfolder: "", type: "output" }); -const project = () => ({ num_frames_per_scene: 97, frame_rate: 25, - scenes: [{ id: "L", text: "lead" }, { id: "A", text: "a" }, { id: "B", text: "b" }, { id: "N", text: "no render" }], - scene_renders: { L: { media: media("L") }, A: { media: media("A"), inSec: 1 }, B: { media: media("B") } } }); - -test("chop: segments shrink by the decay, never below 9 frames, and stop within the length (the last few frames may be left over)", () => { - const segs = chop(97, 40, 0.5); - assert.ok(segs.every((s) => s.frames >= 9)); - assert.ok(segs.every((s, i) => i === 0 || s.start === segs[i - 1].start + segs[i - 1].frames), "pieces butt up exactly: no overlap, no gap"); - assert.ok(segs.every((s) => s.start + s.frames <= 97), "no piece reaches past the clip"); - assert.equal(chop(97, 100, 1).length, 1); -}); - -test("build: lead pieces alternate with pool pieces, each pool clip is read front to back, renders are reused", () => { - const p = project(); - const n = build(p, { leadId: "L", poolIds: ["A"], segmentFrames: 33, decay: 1, random: () => 0 }); - const added = p.scenes.slice(4); - assert.equal(n, added.length); - assert.equal(added.length % 2, 0); - assert.ok(added.every((s) => s.reused && s.gen_unit_id === s.id && !isGenerative(s)), "every piece is its own unit that Generate never makes"); - assert.ok(!p.scenes.slice(0, 4).some((s) => genUnitId(s) !== s.id), "the originals gain no unit mates, so Generate cannot lengthen them"); - const fromL = added.filter((_, i) => i % 2 === 0); - assert.deepEqual(fromL.map((s) => p.scene_renders[s.id].inSec).slice(0, 2), [0, 33 / 25], "the lead plays in order"); - const fromA = added.filter((_, i) => i % 2 === 1); - assert.deepEqual(fromA.map((s) => p.scene_renders[s.id].inSec).slice(0, 2), [1, 1 + 33 / 25], "A is read in order"); - assert.equal(p.scene_renders[fromA[1].id].inSec, 1 + 33 / 25, "a piece plays from where it starts in A's render"); - assert.equal(p.scene_renders[fromA[1].id].media.filename, "A.mp4"); - assert.equal(added[added.length - 1].transition_to_next, ""); - assert.ok(added.every((s) => s.frames_mode === "timeline" && s.source_in === 0)); - - const before = added.map((s) => [s.id, p.scene_renders[s.id].inSec]); - p.scenes.find((s) => s.id === "L").frames_mode = "timeline"; - removeScene(p, "L"); - assert.deepEqual(added.map((s) => [s.id, p.scene_renders[s.id].inSec]), before, "deleting the original leaves the montage as it was"); -}); - -test("build: nothing is built without a rendered lead and a rendered pool; the project is left alone", () => { - const p = project(), before = JSON.stringify(p); - assert.equal(build(p, { leadId: "N", poolIds: ["A"] }), 0); - assert.equal(build(p, { leadId: "L", poolIds: ["N"] }), 0); - assert.equal(JSON.stringify(p), before); -}); - -test("build: deleting a piece leaves no ghost, and an off-grid clip is never read past its end", () => { - const p = project(); - p.scene_renders.L = { media: media("L") }; - p.scenes[0].frames = 103; p.scenes[0].frames_mode = "timeline"; // 103 is off the 8k+1 grid; its nearest grid length, 105, is past the end - build(p, { leadId: "L", poolIds: ["A"], segmentFrames: 33, decay: 1, random: () => 0 }); - const lastLead = p.scenes.filter((s) => s.reused).filter((_, i) => i % 2 === 0).pop(); - assert.ok(p.scene_renders[lastLead.id].inSec * 25 + lastLead.frames <= 103, "no piece plays past the clip"); - const piece = p.scenes.find((s) => s.reused); - removeScene(p, piece.id); - assert.equal((p.scene_ghosts || []).some((g) => g.id === piece.id), false); -}); - -test("playable: a clip shorter than the shortest piece offers nothing to cut", () => { - const p = project(); - p.scenes[1].frames = 5; p.scenes[1].frames_mode = "timeline"; - assert.equal(playable(p.scenes[1], p), null); -}); diff --git a/app/ui/features/montage/index.js b/app/ui/features/montage/index.js deleted file mode 100644 index 48d77ad0..00000000 --- a/app/ui/features/montage/index.js +++ /dev/null @@ -1,51 +0,0 @@ -// Auto Montage: the button in the timeline header and its window. -import { offer } from "../../shell/actions.js"; -import { composer as c } from "../../composer/composer.js"; -import { snapFrames } from "../../shell/scenes.js"; -import { playable, build } from "./build.js"; - -const snippet = (sc) => { const t = (sc.text || "").trim().replace(/\s+/g, " "); return t ? (t.length > 36 ? `${t.slice(0, 36)}…` : t) : "(no prompt)"; }; - -export default { - id: "montage", - mount: "timeline.actions", - needs: ["project", "selection"], - setup({ host, app }) { - const p = app.project, sel = app.selection; - const button = c.button.sm({ label: "⚡ Auto Montage", tone: "ghost", disabled: true, onClick: ask }); - host.append(button.node); - const clips = () => (p.project ? p.scenes.filter((s) => !s.excluded && playable(s, p.project)) : []); - - function ask() { - const list = clips(); - if (list.length < 2) return c.toast.warn({ text: "Auto Montage needs at least two rendered clips on the timeline: one lead and at least one cutaway." }); - const picked = list.filter((s) => sel.ids.includes(s.id)); - let lead = (picked[0] || list[0]).id; - const pool = new Set(picked.slice(1).map((s) => s.id)); - const leadFrames = Math.round(playable(picked[0] || list[0], p.project).total * playable(picked[0] || list[0], p.project).fps); - let seg = Math.max(9, snapFrames(leadFrames / 2.5, "floor")), decay = 0.85; // a handful of lead pieces, not one lump and not a flicker - const label = (s) => `${snippet(s)} — ${Math.round(playable(s, p.project).total * playable(s, p.project).fps)}f`; - const body = c.region.stack({ gap: "md" }); - const draw = () => body.set([ - c.field.default({ label: "Lead clip (plays in order)", control: c.select.md({ label: "Lead clip", value: lead, options: list.map((s) => ({ value: s.id, label: label(s) })), onChange: (v) => { lead = v; pool.delete(v); draw(); } }) }), - c.field.default({ label: "Cutaway pool (random draw, in order within each clip)", control: c.checklist.default({ label: "Cutaway pool", values: [...pool], - items: list.filter((s) => s.id !== lead).map((s) => ({ value: s.id, label: label(s) })), onChange: (v) => { pool.clear(); v.forEach((x) => pool.add(x)); } }) }), - c.field.default({ label: "Segment length (frames)", hint: "How long the lead clip's first piece and each cutaway piece are, in frames. Rounded down to 9, 17, 25 ... frames.", control: c.number.md({ label: "Segment length", value: seg, min: 9, step: 1, precision: 0, onChange: (v) => { seg = v; } }) }), - c.field.default({ label: "Acceleration", hint: "1.0 = equal segments; lower = the lead clip's segments get shorter toward the end", control: c.slider.readout({ label: "Acceleration", value: decay, min: 0.5, max: 1, step: 0.05, onCommit: (v) => { decay = v; } }) }), - ]); - draw(); - const win = c.modal.generic({ title: "Auto Montage", subtitle: "Adds a new cut at the end of the timeline: the lead clip in pieces (shorter and shorter, set by Acceleration) with pieces of the cutaway clips between them. Your original clips stay as they are.", size: "md", body }); - win.setFooter({ actions: [c.button.sm({ label: "Build montage", tone: "primary", onClick: () => { - if (!pool.size) return c.toast.warn({ text: "Pick at least one cutaway clip." }); - const added = p.edit((pr) => build(pr, { leadId: lead, poolIds: [...pool], segmentFrames: seg, decay }) || false); - win.close("done"); - c.toast[added ? "good" : "warn"]({ text: added ? `Added ${added} clips to the end of the timeline.` : "Could not build the montage: the clips need more rendered length." }); - } })] }); - } - const draw = () => button.setDisabled(!p.project); - draw(); - const offered = offer(app, { id: "auto-montage", label: "Auto Montage", icon: "⚡", run: () => { if (!button.node.disabled) ask(); } }); - const off = app.on(draw); - return () => { off(); offered(); }; - }, -}; diff --git a/app/ui/features/peek/index.js b/app/ui/features/peek/index.js index 3891d7ad..df1b5bb2 100644 --- a/app/ui/features/peek/index.js +++ b/app/ui/features/peek/index.js @@ -6,7 +6,7 @@ const KEY = "funui_timeline_peek"; export default { id: "peek", - mount: "timeline.status", + mount: "menubar.right", needs: ["peek"], setup({ host, app }) { let on = false; diff --git a/app/ui/features/rating/index.js b/app/ui/features/rating/index.js index 5b86abe3..989b98dd 100644 --- a/app/ui/features/rating/index.js +++ b/app/ui/features/rating/index.js @@ -16,7 +16,7 @@ export function notTaught(r, ps) { export default { id: "rating", - mount: "timeline.actions", + mount: "timeline.toolbar.end", needs: ["project", "api", "selection", "pipeline"], setup({ host, app }) { const p = app.project, sel = app.selection; diff --git a/app/ui/features/tour/index.js b/app/ui/features/tour/index.js index 0c038565..04a19538 100644 --- a/app/ui/features/tour/index.js +++ b/app/ui/features/tour/index.js @@ -10,7 +10,7 @@ const STEPS = [ { at: "zone:2", side: "left", title: "Properties", text: "Project settings (size, length, postfix) and the picked scene's prompt, source, references and length." }, { at: "zone:3", side: "top", title: "Timeline", text: "One clip per scene. Drag the edges to trim, press S to split, Space to play. Lanes below carry separated sound." }, { at: "button:◆ Composer", side: "top", title: "Composer", text: "Write the whole story in one box, cut at the cut word; keep templates, $variables and shortcuts; chat with the prompt enhancer." }, - { at: "button:▶ Generate", side: "top", title: "Generate", text: "Makes every scene on the timeline, except left-out scenes, video clips and Auto Montage pieces; an earlier render of a scene stays as a take. “Generate this scene” in Properties makes just the picked one; rate a result so FunUI learns your taste." }, + { at: "button:▶ Generate", side: "top", title: "Generate", text: "Makes every scene on the timeline, except left-out scenes and video clips; an earlier render of a scene stays as a take. “Generate this scene” in Properties makes just the picked one; rate a result so FunUI learns your taste." }, { at: "main", side: "bottom", title: "FAQ", text: "Nothing happens? Check the ComfyUI chip at the top right and the Log window. Wrong look? Settings ▸ Appearance. Lost a layout? View ▸ Reset Layout. Lost a project? File ▸ Open recent. That is the tour: Help ▸ Start tour runs it again." }, ]; diff --git a/app/ui/features/upscale/index.js b/app/ui/features/upscale/index.js index 79536688..4e3b9c61 100644 --- a/app/ui/features/upscale/index.js +++ b/app/ui/features/upscale/index.js @@ -7,7 +7,7 @@ import { RTX, RTX_DEFAULTS, keepsSize, keyOf, qualityLabel, swap, upscale } from export default { id: "upscale", - mount: "timeline.actions", + mount: "timeline.toolbar.end", needs: ["project", "api", "selection"], modules: ["render"], setup({ host, app }) { diff --git a/app/ui/frame.css b/app/ui/frame.css index ba90a397..890792cd 100644 --- a/app/ui/frame.css +++ b/app/ui/frame.css @@ -2,7 +2,7 @@ :root { --media-w: clamp(180px, 20vw, 280px); --properties-w: clamp(270px, 28vw, 360px); --timeline-h: clamp(340px, 42vh, 380px); --pad: 10px; --pgap: 10px; } .fp-main { flex-direction: column; padding: 0 var(--pad) var(--pad); gap: var(--pgap); } /* Narrower windows wrap the timeline's header and toolbar onto more rows, so its fixed height gets more room for the lanes. */ -@media (max-width: 1250px) { :root { --timeline-h: clamp(360px, 44vh, 400px); } } +@media (max-width: 1250px) { :root { --timeline-h: clamp(380px, 44vh, 440px); } } .fp-row { flex: 1 1 auto; flex-direction: row; min-block-size: 0; gap: var(--pgap); } .fp-row > *, .fp-main > :nth-child(2) { min-inline-size: 0; border: var(--bw) solid var(--line); border-radius: var(--card-r); overflow: hidden; background: var(--elev-1); } .fp-row > :first-child { flex: 0 0 var(--media-w); } @@ -49,3 +49,21 @@ :root.fp-peek .fp-peek-strip:hover { color: var(--text); } :root.fp-peek.fp-peek-open .fp-peek-strip { display: none; } :root.fp-peek .fp-split-bottom { display: none; } + +/* The timeline's header is ONE line wherever its controls can physically fit (about 1000px and up). It never spreads + its controls apart: the room goes to the text that can give way (hints, the step counter), which truncates, and + below the widest layouts a button that has an icon shows only the icon (its label stays for screen readers). */ +@media (min-width: 1000px) { + .fp-main > :nth-child(2) > .cx-panel-head { flex-wrap: nowrap; column-gap: var(--sp-3); } + .fp-main > :nth-child(2) > .cx-panel-head .cx-panel-actions { flex: 1 1 0; flex-wrap: nowrap; min-inline-size: 0; overflow: hidden; } + .fp-main > :nth-child(2) > .cx-panel-head .cx-panel-status { flex: none; flex-wrap: nowrap; gap: var(--sp-2); } + .fp-main > :nth-child(2) > .cx-panel-head .cx-toolbar { flex-wrap: nowrap; min-inline-size: 0; } + .fp-main > :nth-child(2) > .cx-panel-head .cx-panel-actions > .cx-toolbar { flex: 0 1 auto; } + .fp-main > :nth-child(2) > .cx-panel-head .cx-btn, .fp-main > :nth-child(2) > .cx-panel-head .cx-chip { flex: none; } + .fp-main > :nth-child(2) > .cx-panel-head :is(.cx-hint, .cx-t) { flex: 0 1 auto; min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +} +@media (min-width: 1000px) and (max-width: 1500px) { + .fp-main > :nth-child(2) > .cx-panel-head .cx-btn:has(.cx-btn-icon) .cx-btn-label { + position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; + } +} diff --git a/app/ui/modules.js b/app/ui/modules.js index 7f602aec..ae9f4d9f 100644 --- a/app/ui/modules.js +++ b/app/ui/modules.js @@ -36,7 +36,6 @@ export default [ "./features/preview/lanes.js", "./features/preview/peek.js", "./features/preview/fx.js", - "./features/montage/index.js", "./features/generate/warn.js", "./features/generate/progress.js", "./features/continuity/index.js", diff --git a/app/ui/shell/edits.js b/app/ui/shell/edits.js index 7631be1d..6b651cca 100644 --- a/app/ui/shell/edits.js +++ b/app/ui/shell/edits.js @@ -36,7 +36,7 @@ function ghostOrDrop(p, sc, afterId, pending) { const renders = p.scene_renders || (p.scene_renders = {}); const r = renders[sc.id]; delete renders[sc.id]; - if (sc.reused) return; // a montage piece is a copy: nothing to regenerate, so nothing to leave behind + if (sc.reused) return; // a reused copy is a copy: nothing to regenerate, so nothing to leave behind p.scene_ghosts = (p.scene_ghosts || []).filter((g) => g.id !== sc.id); if (!(r && r.media) && !pending) return; p.scene_ghosts.push({ diff --git a/app/ui/shell/scenes.js b/app/ui/shell/scenes.js index 10e3ac25..92e3885a 100644 --- a/app/ui/shell/scenes.js +++ b/app/ui/shell/scenes.js @@ -7,7 +7,7 @@ export const DRIVEN = { frames: "num_frames_per_scene", fps: "frame_rate" }; export const genUnitId = (sc) => (sc && (sc.gen_unit_id || sc.id)) || ""; export const isVideoClip = (sc) => Boolean(sc && sc.source && sc.source.type === "video"); -export const isGenerative = (sc) => Boolean(sc) && !isVideoClip(sc) && !sc.reused; // a montage piece only replays media that already exists +export const isGenerative = (sc) => Boolean(sc) && !isVideoClip(sc) && !sc.reused; // a reused copy (from older projects) only replays media that already exists /** A timeline cut of one generated clip: only its root owns the prompt, rating and source. */ export const isSubclip = (sc) => Boolean(sc) && (sc.cut_offset_frames || 0) > 0; diff --git a/core/projects.py b/core/projects.py index 334fb928..09dd9079 100644 --- a/core/projects.py +++ b/core/projects.py @@ -229,7 +229,7 @@ class Scene: #: (cut_offset_frames == 0) owns prompt, rating and source. gen_unit_id: str | None = None cut_offset_frames: int = 0 - #: A copy of already-rendered media (Auto Montage pieces): never generated, never part of another clip's unit. + #: A copy of already-rendered media (copies made by an older version's Auto Montage, still loaded from saved projects): never generated, never part of another clip's unit. reused: bool = False guides: list = field(default_factory=list) #: Slip edit: where in the generated media this clip starts and how long it runs. diff --git a/core/suggestions.py b/core/suggestions.py index c3989a3f..184557db 100644 --- a/core/suggestions.py +++ b/core/suggestions.py @@ -120,7 +120,7 @@ def stats() -> dict: if k < b: votes.setdefault((k, b), []).append((when, v)) # Habits: what the cut uses now. - if sc.excluded or sc.reused or not (sc.text or "").strip(): # a montage piece replays a shot, it is not a new one + if sc.excluded or sc.reused or not (sc.text or "").strip(): # a reused copy replays a shot, it is not a new one continue present = fired(sc.text) scanned += 1 diff --git a/core/tests/test_projects.py b/core/tests/test_projects.py index 9e14b15e..aba743f2 100644 --- a/core/tests/test_projects.py +++ b/core/tests/test_projects.py @@ -576,8 +576,8 @@ def test_timeline_fields_are_checked_not_trusted(): assert s.guides == [{"k": 1}] and s.gen_unit_id is None and s.excluded is False -def test_a_montage_piece_stays_reused_through_a_save(): - """Auto Montage marks its copies `reused`; losing the flag on save would let Generate remake them.""" +def test_a_reused_copy_stays_reused_through_a_save(): + """Copies made by the removed Auto Montage carry `reused`; losing the flag on save would let Generate remake them.""" s = projects.Scene.from_dict({"id": "p1", "gen_unit_id": "p1", "reused": True}) assert s.reused is True and projects.Scene.from_dict(__import__("dataclasses").asdict(s)).reused is True assert projects.Scene.from_dict({"id": "x", "reused": "yes"}).reused is False diff --git a/core/tests/test_suggestions.py b/core/tests/test_suggestions.py index 95526b49..4e606535 100644 --- a/core/tests/test_suggestions.py +++ b/core/tests/test_suggestions.py @@ -44,7 +44,7 @@ def test_excluded_scenes_and_sub_clips_are_skipped_and_follows_use_timeline_orde assert s["follows"] == [["neon", "rain", 1]] -def test_auto_montage_pieces_are_not_shots_the_user_wrote(): +def test_reused_copies_are_not_shots_the_user_wrote(): for n in ("rain", "neon"): shortcuts.save({"name": n, "triggers": [n], "replacements": ["r"]}) scenes = [projects.Scene(id="a", text="rain"), projects.Scene(id="b", text="neon"), diff --git a/docs/how-to-start.md b/docs/how-to-start.md index c078d09c..000f4a2d 100644 --- a/docs/how-to-start.md +++ b/docs/how-to-start.md @@ -43,7 +43,7 @@ Click **Composer** and write all scenes in one box, separated by the cut word (s ## 6. Generate -- **▶ Generate** makes every scene on the timeline (not left-out scenes, video clips or Auto Montage pieces). An earlier render of a scene stays as a take. +- **▶ Generate** makes every scene on the timeline (not left-out scenes or video clips). An earlier render of a scene stays as a take. - **Selected** makes only the picked scene. **Takes ×N** makes the same scene several times, differing only by seed. - No picture needed: on H3, a scene with no source image is generated from text alone. @@ -51,7 +51,7 @@ Watch the Log window if nothing happens: any module that fails says why there, a ## 7. Cut, render, export -Trim and split clips on the timeline. **⚡ Auto Montage** builds a new cut at the end from your rendered clips; your originals stay as they are. **⧉ Render** joins the timeline into one file; **⤓ Export** downloads the picked clip (picture only: a clip whose sound was separated is silent there, Render mixes it). +Trim and split clips on the timeline. **⧉ Render** joins the timeline into one file; **⤓ Export** downloads the picked clip (picture only: a clip whose sound was separated is silent there, Render mixes it). ## 8. Teach it your taste (optional) diff --git a/docs/images/montage.jpg b/docs/images/montage.jpg deleted file mode 100644 index a3af9e52f46c126ad4a5c06712d3080541b6e420..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 159548 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 Vv*2h^tGon)bEW818L9og{{nC)<3Ioa diff --git a/pyproject.toml b/pyproject.toml index 505e842f..178ab6f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "ComfyUI-FunPack" # Unique identifier for your node. Immutable after creation. -description = "An AI movie studio inside ComfyUI: a browser-based studio with timeline, per-scene prompts and one-click montage generation, plus a self-improving engine that learns from your ratings. Every feature is a module, so a broken one is simply absent." +description = "An AI movie studio inside ComfyUI: a browser-based studio with timeline, per-scene prompts and one-click generation, plus a self-improving engine that learns from your ratings. Every feature is a module, so a broken one is simply absent." version = "5.1.0" # Custom Node version. Must be semantically versioned. # Release codename ("Classy Chopper" for 5.x) lives in core/update.py:CODENAMES, keyed by major, shown in Settings > About. license = { text = "GNU GPL v3" }