diff --git a/Cargo.lock b/Cargo.lock index f72ff4fe..c882225f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -298,7 +298,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1755d0ef8e00e87b6b825dfbe5a35d34d3b302e97e80a48e93f9cd361fbada06" dependencies = [ - "kurbo", + "kurbo 0.13.1", "peniko", "raw-window-handle", "smallvec", @@ -313,7 +313,7 @@ dependencies = [ "anyrender", "debug_timer", "futures-channel", - "kurbo", + "kurbo 0.13.1", "peniko", "pollster 0.4.0", "rustc-hash 2.1.3", @@ -872,7 +872,7 @@ dependencies = [ "icu_segmenter", "image", "keyboard-types", - "kurbo", + "kurbo 0.13.1", "linebender_resource_handle", "markup5ever", "objc2 0.6.5", @@ -920,7 +920,7 @@ dependencies = [ "bytemuck", "color", "euclid", - "kurbo", + "kurbo 0.13.1", "parley", "peniko", "skrifa", @@ -2245,6 +2245,21 @@ dependencies = [ "thiserror 2.0.21", ] +[[package]] +name = "egui_extras" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cbdc785020861553f230f23d330ba1fb72613b9d8e0e457f3bdc8ba6db6dcf" +dependencies = [ + "ahash", + "egui", + "enum-map", + "itertools 0.15.0", + "log", + "profiling", + "resvg 0.45.1", +] + [[package]] name = "egui_glow" version = "0.36.2" @@ -2331,6 +2346,26 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" +[[package]] +name = "enum-map" +version = "2.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" +dependencies = [ + "enum-map-derive", +] + +[[package]] +name = "enum-map-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "enumflags2" version = "0.7.12" @@ -3548,12 +3583,18 @@ dependencies = [ "byteorder-lite", "moxcms", "num-traits", - "png", + "png 0.18.1", "tiff", "zune-core", "zune-jpeg", ] +[[package]] +name = "imagesize" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" + [[package]] name = "imagesize" version = "0.15.0" @@ -3900,6 +3941,17 @@ dependencies = [ "libc", ] +[[package]] +name = "kurbo" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62026ae44756f8a599ba21140f350303d4f08dcdcc71b5ad9c9bb8128c13c62" +dependencies = [ + "arrayvec", + "euclid", + "smallvec", +] + [[package]] name = "kurbo" version = "0.13.1" @@ -4438,7 +4490,7 @@ dependencies = [ "mp4-atom", "mpeg2ts", "num_enum", - "roxmltree", + "roxmltree 0.21.2", "rustc-hash 2.1.3", "scuffle-av1", "serde", @@ -4639,6 +4691,7 @@ dependencies = [ "eframe", "egui", "egui_dock", + "egui_extras", "egui_kittest", "futures-util", "global-hotkey", @@ -4663,7 +4716,7 @@ dependencies = [ "pollster 1.0.1", "qrcodegen", "raw-window-handle", - "resvg", + "resvg 0.50.0", "rune-fx", "same-file", "serde", @@ -5878,7 +5931,7 @@ checksum = "839c8299360d2e998bdb106dc0a6cd71dcc5f4df51df1b620361bf50e283cca6" dependencies = [ "bytemuck", "color", - "kurbo", + "kurbo 0.13.1", "linebender_resource_handle", "smallvec", ] @@ -6106,6 +6159,19 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + [[package]] name = "png" version = "0.18.1" @@ -6669,6 +6735,20 @@ dependencies = [ "tower-service", ] +[[package]] +name = "resvg" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8928798c0a55e03c9ca6c4c6846f76377427d2c1e1f7e6de3c06ae57942df43" +dependencies = [ + "log", + "pico-args", + "rgb", + "svgtypes 0.15.3", + "tiny-skia 0.11.4", + "usvg 0.45.1", +] + [[package]] name = "resvg" version = "0.50.0" @@ -6679,9 +6759,9 @@ dependencies = [ "log", "pico-args", "rgb", - "svgtypes", - "tiny-skia", - "usvg", + "svgtypes 0.16.2", + "tiny-skia 0.12.0", + "usvg 0.50.0", ] [[package]] @@ -6794,6 +6874,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "roxmltree" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" + [[package]] name = "roxmltree" version = "0.21.2" @@ -7883,13 +7969,23 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb" +[[package]] +name = "svgtypes" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68c7541fff44b35860c1a7a47a7cadf3e4a304c457b58f9870d9706ece028afc" +dependencies = [ + "kurbo 0.11.3", + "siphasher", +] + [[package]] name = "svgtypes" version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f12b12995e3638c70618c1facb1ce65302f6a6f706b675f07c58a5d7391120e" dependencies = [ - "kurbo", + "kurbo 0.13.1", "siphasher", ] @@ -8025,7 +8121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix 1.1.6", "windows-sys 0.61.2", @@ -8148,6 +8244,21 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-skia" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "png 0.17.16", + "tiny-skia-path 0.11.4", +] + [[package]] name = "tiny-skia" version = "0.12.0" @@ -8159,8 +8270,19 @@ dependencies = [ "bytemuck", "cfg-if", "log", - "png", - "tiny-skia-path", + "png 0.18.1", + "tiny-skia-path 0.12.0", +] + +[[package]] +name = "tiny-skia-path" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", ] [[package]] @@ -8830,6 +8952,28 @@ dependencies = [ "usage-argv", ] +[[package]] +name = "usvg" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80be9b06fbae3b8b303400ab20778c80bbaf338f563afe567cf3c9eea17b47ef" +dependencies = [ + "base64 0.22.1", + "data-url", + "flate2", + "imagesize 0.13.0", + "kurbo 0.11.3", + "log", + "pico-args", + "roxmltree 0.20.0", + "simplecss", + "siphasher", + "strict-num", + "svgtypes 0.15.3", + "tiny-skia-path 0.11.4", + "xmlwriter", +] + [[package]] name = "usvg" version = "0.50.0" @@ -8837,16 +8981,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdb896f04730b97805bbc3191fc57e4bf03face0f14577dd42e783c4d8c98802" dependencies = [ "data-url", - "imagesize", - "kurbo", + "imagesize 0.15.0", + "kurbo 0.13.1", "log", "pico-args", - "roxmltree", + "roxmltree 0.21.2", "simplecss", "siphasher", "strict-num", - "svgtypes", - "tiny-skia-path", + "svgtypes 0.16.2", + "tiny-skia-path 0.12.0", ] [[package]] @@ -8895,7 +9039,7 @@ dependencies = [ "futures-intrusive", "log", "peniko", - "png", + "png 0.18.1", "skrifa", "static_assertions", "thiserror 2.0.21", @@ -9940,6 +10084,12 @@ dependencies = [ "markup5ever", ] +[[package]] +name = "xmlwriter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" + [[package]] name = "yasna" version = "0.6.0" diff --git a/README.md b/README.md index fc460cf0..c39b9170 100644 --- a/README.md +++ b/README.md @@ -112,17 +112,21 @@ uplink holds up once you are live. ## Panels -Every panel is a tab you can drag, split, or stack. +Every panel is a tab you can drag, split, or stack. Blue, the studio's accent, +means on air (and marks what is picked or switched on), amber anything cued, +off air, muted, or degraded, and red an error, such as a failure or a +clipping meter. An icon-only button +names itself, and its key, under the pointer. | Panel | Use it to | | --- | --- | -| Preview, Program | See the scene you are editing, at its own size, and the one that is live, and drag items in the preview to place them. A preview no tab shows is not drawn. **Cut** puts the preview on program at once; **Transition** takes it there by the transition picked beside it, over the time set there, or for a stinger by the media source and cut point set there (see [Transitions](#transitions)). **Interact** passes the mouse over the preview to the browser source under it instead, and the keyboard to the one last clicked. | -| Scenes | See each scene live in a small picture beside its name, redrawn a few times a second while it is on screen. Pick the scene in preview, and add, rename (double-click), reorder, remove, or tick **Publish** on one and pick the audio scene it carries (see [Published scenes](#published-scenes)). A scene on program, or still leaving it in a transition, cannot be removed, even by an undo, until program cuts away from it. Add, rename, reorder, and remove audio scenes too (see [Audio scenes](#audio-scenes)). | +| Preview, Program | See the scene you are editing, at its own size, and the one that is live, and drag items in the preview to place them. The program is framed in blue; the preview blue while it shows the scene on program and amber, NEXT, while it shows another. A preview no tab shows is not drawn. **Cut** puts the preview on program at once; **Transition** takes it there by the transition picked beside it, over the time set there, or for a stinger by the media source and cut point set there (see [Transitions](#transitions)). **Interact** passes the mouse over the preview to the browser source under it instead, and the keyboard to the one last clicked. | +| Scenes | See each scene live on its pad, redrawn a few times a second while it is on screen, with its hotkey and an ON AIR or NEXT tag. Click a pad to pick the scene in preview, and add, rename (double-click), reorder, remove, or switch on **Publish** for one and pick the audio scene it carries (see [Published scenes](#published-scenes)). A scene on program, or still leaving it in a transition, cannot be removed, even by an undo, until program cuts away from it. Add, rename, reorder, and remove audio scenes too (see [Audio scenes](#audio-scenes)). | | History | See every edit, and undo or redo back to any of them. | -| Items | Place, show, hide, and order what the preview scene or the top layer draws, back to front. The top layer is edited over a scene of the program's size. Select an item to filter or copy it. | +| Items | Place, show or hide (the eye), and order what the preview scene or the top layer draws, back to front. Drag a position or size field sideways to change it, or click it to type. The top layer is edited over a scene of the program's size. Select an item to filter or copy it. | | Sources | Add a source by hand, see whether each and its own track are live and where it is shown, clone one, and remove one. Select a source to filter it. A camera or broadcast without a new picture, or a microphone or system audio without new sound, for a second reads as stalled. A browser source shows whether its page is copied on the GPU or, as a fallback, uploaded from memory (CPU, saying why on hover), in place of a track, and **Reload** restarts its page. A media file reads as ended once it plays to its end without looping, **Play** plays it from its start, **Stop** stops it at once, blank and silent, until played again, and **Reload** reads the file again. | | Devices | List this machine's cameras, displays, windows, and audio inputs, and add one as a source. | -| Guests | Invite a guest, show their join link as a QR code, see who joined, and take a guest out of every scene. | +| Guests | Invite a guest, show their join link as a QR code in a sheet over the window, see who joined, and take a guest out of every scene. | | Filters | Remove the selected source's background, crop the selected source or item, add, order, and set its filters, set an item's blend mode, and copy or paste filters. | | Keyframes | Animate the selected item: add, time, ease, and remove its keyframes, and set how far each moves, resizes, crops, and filters it (see [Keyframes](#keyframes)). **Play** plays the preview scene's keyframes again. | | Audio | Pick the audio scene on program and the one to listen to and on which output, set each sound's gain, pan, mute, and delay, and send each sound and audio scene into audio scenes, with a meter on every one. | @@ -132,7 +136,9 @@ Every panel is a tab you can drag, split, or stack. | Replay | Replay the last moments of the program or a source in a replay source, slowed down if you like, or save them as a clip. | | Hotkeys | Bind keys to cut, transition, preview a scene, replay, save a clip, and start or stop recording, and clear them (see [Hotkeys](#hotkeys)). | -While recording, a red dot in the Program panel says so. +While recording, a blue dot in the Program panel says so. The pill at the right +of the menu bar is the stream's health at a glance; click it for each relay +and problem. A new source, from the Sources or Devices panel, is placed over whatever the Items panel shows. The **top layer** is drawn over program, and over the @@ -1139,14 +1145,15 @@ the studio. The window draws effects of its own, which never reach the program, a published scene, or a recording: -- The Program monitor glows red while the studio is connected to a relay, +- The Program monitor glows blue while the studio is connected to a relay, the recording dot pulses, and each cut or transition, from its button or a hotkey, bursts on the monitor. - The **Cut** button is polished metal that ripples under the pointer, the - Hotkeys panel shows each bound key on a keycap, each panel has a faint grain, - and first launch draws its screen over a soft gradient. + Hotkeys panel shows each bound key on a dark plastic keycap, each panel but + the two monitors has a faint grain, and first launch draws its screen over a + soft gradient. - The Health panel and its tab pulse amber while the worst problem is - degraded, and flicker with electricity while it is unhealthy. + degraded, and flicker red with electricity while it is unhealthy. **View > Effects** sets how they move: **Full**, **Reduced**, which holds each on one still pose, or **Off**. Until you pick one it follows the system's diff --git a/quest/m0/ux/README.md b/quest/m0/ux/README.md index f6c3fc13..99a4d2f4 100644 --- a/quest/m0/ux/README.md +++ b/quest/m0/ux/README.md @@ -75,8 +75,16 @@ shows those pictures beside the frames they implement. as released and 3 to 5 ms with femtovg's pipeline cache patched. Patched Slint also made the program render about four times slower, and Slint's licenses require GPLv3 or attribution with an embedded ban. egui's gaps - (SVG icons, gradients) are painter work the [kit](/quest/m0/ux/kit.md) - owns. + (SVG icons, gradients) are painter work, done in the kit + (`rs/moq-studio/src/kit`). +- **Color:** ✅ one shared accent (`kit::ACCENT`, `--accent` in + `mock/kit.css`), blue until proper branding replaces that one value, for + what is on air (the ON AIR tag, the tally frame, the live control) and for + selection, toggles, and sliders (rejected: a separate token for on air). + Red is errors alone, a clipping meter among them; amber is cued, off air, + muted, and degraded (rejected: red for the program, as hardware switchers + do; red or amber for both a mute and a clip). Decided by the maintainer in + [moq-dev/studio#164](https://github.com/moq-dev/studio/pull/164#issuecomment-6887308961). - **Milestones:** ✅ redesigning what exists is m0, here. Features that do not exist yet are [m1](/quest/m1/README.md), and three more are [m2](/quest/m2/README.md) (rejected: all in m0; all in m1). @@ -115,7 +123,8 @@ quest links its own. - Editing the live picture, with layers beside it: Meld Studio and StreamYard, which stay safe by constraining what a click can do. -- Cue and take, red for program and amber for preview: hardware switchers. +- Cue and take, a tally for program and amber for preview: hardware switchers, + which draw the program red where this draws it in the accent. vMix and OBS Studio Mode show the cost of the split this plan rejects. - Selection handles, smart guides, a toolbar on the selected thing, and an inspector that follows the selection: Figma and Keynote. @@ -144,7 +153,8 @@ PR hands them to the maintainer as `## Waiting` with what to look at: credentials, and ending it. - **Other apps in front:** hotkeys, and later the mini controller, while a full-screen game has focus. -- **Readability:** contrast, and red against amber for a color-blind reader. +- **Readability:** contrast, and the accent, amber, and red told apart by a + color-blind reader. ## Related diff --git a/quest/m0/ux/go-live.md b/quest/m0/ux/go-live.md index 8f254d13..5e63911a 100644 --- a/quest/m0/ux/go-live.md +++ b/quest/m0/ux/go-live.md @@ -51,7 +51,8 @@ opened by a double click, so none of that can stay a flag only. sentence and its fix are advice, since a streamer on a bad connection may still choose to go. Only having nothing to send, no destination switched on, disables the confirm. -- GO LIVE is not red. Red stays the on-air state alone. +- GO LIVE is not in the accent, which stays the on-air state, nor red, which + is errors alone. - **A replay of the program** needs the relay's cache, so off air it says so rather than failing. - **Recent shows** are kept per user. A show's picture is the last frame of diff --git a/quest/m0/ux/kit.md b/quest/m0/ux/kit.md deleted file mode 100644 index 0ea7032b..00000000 --- a/quest/m0/ux/kit.md +++ /dev/null @@ -1,49 +0,0 @@ -# [L] The studio's look - -## Goal - -The studio has a look of its own: its colors, type, spacing, and icons come -from one set of tokens, and its controls are its own widgets, drawn as the -[mock-ups](/quest/m0/ux/mock/shell-live.webp) draw them. Today's panels wear -it at once, and a gallery view of `just shots` shows every widget in every -state. - -Today the app sets no fonts, style, or visuals, draws no icons in its panels, -and hard-codes a handful of colors. - -## Plan - -`mock/kit.css` is the reference: its custom properties are the tokens, and -its classes are the widgets. - -- **Tokens:** near-black surfaces in three steps, one line color, text in - three strengths. Red is the program and nothing else. Amber is - everything that is not right and not on air: cued, off air, degraded, or - needing attention. Green is a healthy level. Blue is selection. -- **Type:** three bundled faces under an open license: a condensed face for - state and names (ON AIR, scene names, page names), a plain face for - everything else, and a monospace for clocks and rates, whose digits must - not jitter. The mock-ups use Barlow Condensed, Inter, and JetBrains Mono; - keep them unless one fails to render well in egui. Bundled, - never the machine's, as overlays already do. -- **Icons:** one open-licensed set in a single stroke weight (the mock-ups - draw in Lucide's style), named by role in one place. Draw Lucide's SVGs - through `egui_extras`' SVG loader; egui has no SVG icons of its own. Every icon-only - control has a tooltip that names it and its key. -- **Widgets:** the scene pad, the pill, the icon button, the toggle, the - slider, the fader, the segmented meter, the number field that drags, the - popover, the tooltip, the sheet, the keycap, and the tally frame. -- **Stage wash:** draw it as a gradient mesh, since egui has no radial - gradient (the spike's stack of discs read as an arch). -- **Effects:** today's rune-fx effects (`rs/moq-studio/src/fx.rs`) read the - tokens, and stop registering spots while panels draw, which ties them to - the layout. The Effects setting and reduced motion keep working. - -Measure the UI's frame time before and after, under a real compositor. - -Recommendation: keep each widget's state in the caller, so the pages can -draw from a snapshot of the engine rather than holding its lock while they -draw, as `Studio::ui` does today. - -Human check: taste, on the gallery's screenshots, and readability of red -against amber. diff --git a/quest/m0/ux/live.md b/quest/m0/ux/live.md index 6a347527..1baa2b82 100644 --- a/quest/m0/ux/live.md +++ b/quest/m0/ux/live.md @@ -5,7 +5,7 @@ The studio opens to the LIVE page of the [mock-up](/quest/m0/ux/mock/shell-live.webp), in its own frame: -- **The picture** is the program, in a red tally frame, as large as the +- **The picture** is the program, in a tally frame in the accent, as large as the window allows. The Preview monitor and the Program monitor are gone. - **Scene pads** show each scene's live thumbnail, name, and key. A click takes the scene on air by the show's transition. @@ -62,6 +62,11 @@ picture's shape, tested without a window: for every size from the minimum up, no region overlaps another and the picture is the largest rectangle. The mock-up's three arrangements are its cases. +Build the page from the kit (`rs/moq-studio/src/kit`): its pads, tally frame, +stage wash, meters, pill and popover, icon buttons, and tokens, which +`just shots kit` shows. Its widgets keep no state, so they draw from the +snapshot below. + Draw the pages from a snapshot of the engine, not while holding its lock (`Studio::ui` holds `engine.state` across the whole dock today, and the render thread wants the same lock). Split `ui.rs`, 4,900 lines behind one @@ -73,7 +78,3 @@ that the program's render time is unchanged. Human check: taste and feel on the maintainer's machine, a second monitor and mixed display scales, and the custom frame's drag, resize, snap, and full-screen behavior on each desktop, which no headless run exercises. - -## Required - -- [The studio's look](/quest/m0/ux/kit.md) - the widgets the page is built from diff --git a/quest/m0/ux/mix.md b/quest/m0/ux/mix.md index 24821d1a..994db839 100644 --- a/quest/m0/ux/mix.md +++ b/quest/m0/ux/mix.md @@ -33,7 +33,8 @@ section has them. "Audio scene" stays the word, since it was chosen over - A fader is gain in decibels, with unity marked and a double click returning to it, as pan returns to center today. - The meter keeps the peak tick and the red at full scale of - `rs/moq-studio/src/ui/levels.rs`, drawn as segments. + `rs/moq-studio/src/ui/levels.rs`, drawn as `kit::Meter`'s segments: red is + a clip, an error. A muted sound's control is amber, as `kit.css` draws it. - A sound heard twice by construction cannot happen here, since an audio scene plays a sound once however it reaches it. Show that: a dot is filled when the sound reaches the audio scene by any route, and hollow-ringed when diff --git a/quest/m0/ux/mock/add-apps.webp b/quest/m0/ux/mock/add-apps.webp index c3b554fe..294b1abb 100644 Binary files a/quest/m0/ux/mock/add-apps.webp and b/quest/m0/ux/mock/add-apps.webp differ diff --git a/quest/m0/ux/mock/add-cameras.webp b/quest/m0/ux/mock/add-cameras.webp index 714aadee..09c47275 100644 Binary files a/quest/m0/ux/mock/add-cameras.webp and b/quest/m0/ux/mock/add-cameras.webp differ diff --git a/quest/m0/ux/mock/add-drop.webp b/quest/m0/ux/mock/add-drop.webp index 18dd6b82..2d747d12 100644 Binary files a/quest/m0/ux/mock/add-drop.webp and b/quest/m0/ux/mock/add-drop.webp differ diff --git a/quest/m0/ux/mock/add-guests.webp b/quest/m0/ux/mock/add-guests.webp index 6fb1676d..e1259d59 100644 Binary files a/quest/m0/ux/mock/add-guests.webp and b/quest/m0/ux/mock/add-guests.webp differ diff --git a/quest/m0/ux/mock/add-system.webp b/quest/m0/ux/mock/add-system.webp index 74839f54..5e177b00 100644 Binary files a/quest/m0/ux/mock/add-system.webp and b/quest/m0/ux/mock/add-system.webp differ diff --git a/quest/m0/ux/mock/add.html b/quest/m0/ux/mock/add.html index 00ec1482..aac630ae 100644 --- a/quest/m0/ux/mock/add.html +++ b/quest/m0/ux/mock/add.html @@ -39,7 +39,7 @@ .g2 .card .tx{flex-direction:row;align-items:baseline;justify-content:space-between;gap:8px;margin:9px 2px 0 38px} .card b{font:600 12.5px/1.2 var(--ui);white-space:nowrap;overflow:hidden;text-overflow:ellipsis} .card small{flex:none;font:400 11.5px/1.2 var(--ui);color:var(--dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:5px} -.card.on .th{outline:2px solid var(--sel);outline-offset:2px} +.card.on .th{outline:2px solid var(--accent);outline-offset:2px} .card.lift{opacity:.3} .card.lift .th{outline:2px dashed var(--dim);outline-offset:2px} .bd{position:absolute;left:6px;bottom:-10px;z-index:2;box-shadow:0 0 0 2px var(--p2)} @@ -66,24 +66,24 @@ /* what is picked, and the one action */ .pick{display:flex;align-items:center;gap:12px;padding:10px 14px;border-top:1px solid var(--line);background:var(--p2);flex:none} -.pick .th{width:64px;height:36px;border-radius:6px;flex:none;outline:2px solid var(--sel);outline-offset:1px} +.pick .th{width:64px;height:36px;border-radius:6px;flex:none;outline:2px solid var(--accent);outline-offset:1px} .pick .n{font:600 13px/1.2 var(--ui);min-width:0} .pick .n small{display:block;font:400 11.5px/1.2 var(--ui);color:var(--dim);margin-top:3px} .pick .opt{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dim);white-space:nowrap} -.btn.pri{background:var(--sel);border-color:transparent;color:#fff;height:34px;padding:0 14px;font-size:13px} +.btn.pri{background:var(--accent);border-color:transparent;color:#fff;height:34px;padding:0 14px;font-size:13px} /* drag onto the picture */ -.land{position:absolute;left:3%;top:21%;width:40%;aspect-ratio:16/10;border:2px dashed var(--sel);border-radius:6px;background:#4f8cff2e;z-index:6} -.land i{position:absolute;width:8px;height:8px;background:var(--sel);border-radius:50%} +.land{position:absolute;left:3%;top:21%;width:40%;aspect-ratio:16/10;border:2px dashed var(--accent);border-radius:6px;background:#4f8cff2e;z-index:6} +.land i{position:absolute;width:8px;height:8px;background:var(--accent);border-radius:50%} .land i:nth-child(1){left:-5px;top:-5px}.land i:nth-child(2){right:-5px;top:-5px}.land i:nth-child(3){left:-5px;bottom:-5px}.land i:nth-child(4){right:-5px;bottom:-5px} .vg{position:absolute;left:3%;top:10%;bottom:4%;width:1px;background:#ff3df0;z-index:7} .snap{position:absolute;left:calc(3% + 10px);top:calc(21% + 40% * 10 / 16 * 16 / 9 + 10px);z-index:7;padding:4px 7px;border-radius:6px;background:#000d;color:#ff7af5;font:600 11px/1 var(--ui);white-space:nowrap} -.ghost{position:absolute;z-index:30;width:176px;padding:6px 6px 9px;border-radius:11px;background:#1c1c25;border:1px solid var(--sel);box-shadow:0 22px 44px #000d;opacity:.94;transform:rotate(-3deg)} +.ghost{position:absolute;z-index:30;width:176px;padding:6px 6px 9px;border-radius:11px;background:#1c1c25;border:1px solid var(--accent);box-shadow:0 22px 44px #000d;opacity:.94;transform:rotate(-3deg)} .ptr{position:absolute;z-index:31;width:22px;height:22px} .hint{position:absolute;left:0;right:0;bottom:22px;display:flex;justify-content:center;gap:8px;align-items:center;color:var(--dim);font-size:12px} /* a desktop that owns the picker */ -.sysbtn{height:84px;border-radius:14px;background:var(--sel);color:#fff;display:flex;align-items:center;gap:14px;padding:0 20px;font:700 26px/1 var(--disp);letter-spacing:.03em} +.sysbtn{height:84px;border-radius:14px;background:var(--accent);color:#fff;display:flex;align-items:center;gap:14px;padding:0 20px;font:700 26px/1 var(--disp);letter-spacing:.03em} .sysbtn svg.i{width:26px;height:26px} .sysbtn .go{width:20px;height:20px;opacity:.8} .sysnote{display:flex;gap:9px;align-items:flex-start;margin-top:12px;color:var(--dim);font-size:12.5px;line-height:1.45} diff --git a/quest/m0/ux/mock/firstrun-check.webp b/quest/m0/ux/mock/firstrun-check.webp index 223579fa..e1bdc373 100644 Binary files a/quest/m0/ux/mock/firstrun-check.webp and b/quest/m0/ux/mock/firstrun-check.webp differ diff --git a/quest/m0/ux/mock/firstrun-format.webp b/quest/m0/ux/mock/firstrun-format.webp index 8161c993..e182d4e3 100644 Binary files a/quest/m0/ux/mock/firstrun-format.webp and b/quest/m0/ux/mock/firstrun-format.webp differ diff --git a/quest/m0/ux/mock/firstrun-layout.webp b/quest/m0/ux/mock/firstrun-layout.webp index 24a63cfc..973b0d3d 100644 Binary files a/quest/m0/ux/mock/firstrun-layout.webp and b/quest/m0/ux/mock/firstrun-layout.webp differ diff --git a/quest/m0/ux/mock/firstrun-sources.webp b/quest/m0/ux/mock/firstrun-sources.webp index 4b1b0915..f1d9a3c3 100644 Binary files a/quest/m0/ux/mock/firstrun-sources.webp and b/quest/m0/ux/mock/firstrun-sources.webp differ diff --git a/quest/m0/ux/mock/firstrun.html b/quest/m0/ux/mock/firstrun.html index 8b62201a..b553a038 100644 --- a/quest/m0/ux/mock/firstrun.html +++ b/quest/m0/ux/mock/firstrun.html @@ -23,13 +23,13 @@ .prog{display:flex;gap:6px} .prog i{width:40px;height:4px;border-radius:2px;background:var(--p3)} .prog i.done{background:var(--dim)}.prog i.on{background:var(--text)} -.tick{position:absolute;right:14px;top:14px;z-index:3;width:26px;height:26px;border-radius:50%;background:var(--sel);display:grid;place-items:center;color:#fff} +.tick{position:absolute;right:14px;top:14px;z-index:3;width:26px;height:26px;border-radius:50%;background:var(--accent);display:grid;place-items:center;color:#fff} .tick svg.i{width:15px;height:15px;stroke-width:3} /* format */ .fmt{display:flex;gap:28px;margin-top:40px} .opt{position:relative;width:452px;border-radius:20px;background:var(--p1);border:2px solid var(--line);padding:26px 26px 24px} -.opt.on{border-color:var(--sel);background:#4f8cff12;box-shadow:0 0 0 5px #4f8cff1f} +.opt.on{border-color:var(--accent);background:#4f8cff12;box-shadow:0 0 0 5px #4f8cff1f} .opt .art{height:292px;display:grid;place-items:center} .scr{position:relative;padding:8px;background:#000;border:2px solid #3b3b48} .scr.wide{width:396px;border-radius:14px;margin-bottom:30px} @@ -61,7 +61,7 @@ .o{min-width:0} .o .th{position:relative;aspect-ratio:16/9;border-radius:7px;background:var(--p2)} .o .th::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 0 0 1px #ffffff1c} -.o.on .th{outline:2px solid var(--sel);outline-offset:2px} +.o.on .th{outline:2px solid var(--accent);outline-offset:2px} .o span{display:block;margin-top:8px;font:500 11.5px/1.2 var(--ui);color:var(--dim);text-align:center;white-space:nowrap} .o.on span{color:var(--text)} .o .th.c{display:grid;place-items:center;color:var(--dim)} @@ -121,7 +121,7 @@ /* layout */ .tpls{display:grid;grid-template-columns:repeat(4,298px);gap:20px;margin-top:40px} .tpl{position:relative;border-radius:18px;background:var(--p1);border:2px solid var(--line);padding:10px 10px 18px} -.tpl.on{border-color:var(--sel);background:#4f8cff12;box-shadow:0 0 0 5px #4f8cff1f} +.tpl.on{border-color:var(--accent);background:#4f8cff12;box-shadow:0 0 0 5px #4f8cff1f} .tpl .th{aspect-ratio:16/9;border-radius:10px;overflow:hidden} .tpl .th.empty{border:2px dashed var(--line);display:grid;place-items:center;color:var(--faint)} .tpl .th.empty svg.i{width:28px;height:28px} diff --git a/quest/m0/ux/mock/golive-health.webp b/quest/m0/ux/mock/golive-health.webp index 2d27732e..9ed1f227 100644 Binary files a/quest/m0/ux/mock/golive-health.webp and b/quest/m0/ux/mock/golive-health.webp differ diff --git a/quest/m0/ux/mock/golive-library.webp b/quest/m0/ux/mock/golive-library.webp index ec226c4d..068580c2 100644 Binary files a/quest/m0/ux/mock/golive-library.webp and b/quest/m0/ux/mock/golive-library.webp differ diff --git a/quest/m0/ux/mock/golive-preflight.webp b/quest/m0/ux/mock/golive-preflight.webp index a3537c64..1a71b3ef 100644 Binary files a/quest/m0/ux/mock/golive-preflight.webp and b/quest/m0/ux/mock/golive-preflight.webp differ diff --git a/quest/m0/ux/mock/golive-ready.webp b/quest/m0/ux/mock/golive-ready.webp index 2fc5e9a4..b26a6cb5 100644 Binary files a/quest/m0/ux/mock/golive-ready.webp and b/quest/m0/ux/mock/golive-ready.webp differ diff --git a/quest/m0/ux/mock/golive.html b/quest/m0/ux/mock/golive.html index 080c6a01..c4494ab7 100644 --- a/quest/m0/ux/mock/golive.html +++ b/quest/m0/ux/mock/golive.html @@ -146,7 +146,7 @@ `; const V={ - 'ready':{label:'Off air',cls:'L',note:'Off air. The same LIVE page before the show: the frame around the picture is neutral instead of red, the tag reads OFF AIR, and the live control is one large GO LIVE button. Nothing else on the page changes, so there is no separate setup screen to learn.', + 'ready':{label:'Off air',cls:'L',note:'Off air. The same LIVE page before the show: the frame around the picture is neutral instead of the accent, the tag reads OFF AIR, and the live control is one large GO LIVE button. Nothing else on the page changes, so there is no separate setup screen to learn.', html:()=>topbar('LIVE')+stage({pic:'soon',cue:true})+dock(),after:offair()}, 'preflight':{label:'GO LIVE pressed',cls:'L',note:'The go-live sheet. It drops from the button and shades only what is near it: where the stream is going, each destination with a switch and its state, then four checks that fill in as they finish. A failed check is one plain sentence with its fix, and the confirm button counts the destinations.', html:()=>topbar('LIVE')+stage({pic:'soon',cue:true})+dock()+sheet(),after:offair(true)}, diff --git a/quest/m0/ux/mock/kit.css b/quest/m0/ux/mock/kit.css index 675da877..62164a34 100644 --- a/quest/m0/ux/mock/kit.css +++ b/quest/m0/ux/mock/kit.css @@ -1,7 +1,7 @@ /* Shared look of the studio mock-ups: tokens, chrome, fake pictures. Reference only; the app is not HTML. */ /* Mock-up only: fixed colors on purpose, this is the app's own dark chrome. */ .mock{--bg:#09090c;--p1:#111116;--p2:#18181f;--p3:#22222b;--line:#2a2a35;--text:#f3f3f6;--dim:#8d8d9c;--faint:#5b5b69; - --air:#ff2d46;--cue:#ffb020;--ok:#35d07f;--sel:#4f8cff; + --accent:#4f8cff;--cue:#ffb020;--ok:#35d07f;--err:#ff2d46; --disp:'Barlow Condensed','Arial Narrow',sans-serif;--ui:Inter,system-ui,sans-serif;--mono:'JetBrains Mono',ui-monospace,monospace} *{box-sizing:border-box} body{margin:0;font-family:Inter,system-ui,sans-serif} @@ -26,16 +26,16 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 /* top bar: the window's own title bar */ .top{grid-column:1/-1;display:flex;align-items:center;gap:14px;padding:0 14px;background:var(--p1);border-bottom:1px solid var(--line)} -.logo{width:22px;height:22px;border-radius:7px;background:conic-gradient(from 210deg,var(--air),#ff8a3d,var(--air))} +.logo{width:22px;height:22px;border-radius:7px;background:conic-gradient(from 210deg,#ff2d46,#ff8a3d,#ff2d46)} .show{font:600 14px/1 var(--ui)} .pill{display:flex;align-items:center;gap:7px;height:28px;padding:0 10px;border-radius:14px;background:var(--p2);border:1px solid var(--line);font:500 12px/1 var(--ui);white-space:nowrap} .pill b{font:500 12px/1 var(--mono)} .dot{width:8px;height:8px;border-radius:50%;background:var(--ok)} -.onair{height:30px;padding:0 12px;border-radius:6px;background:var(--air);color:#fff;font:700 17px/30px var(--disp);letter-spacing:.1em;display:flex;gap:10px;box-shadow:0 0 22px #ff2d4666} +.onair{height:30px;padding:0 12px;border-radius:6px;background:var(--accent);color:#fff;font:700 17px/30px var(--disp);letter-spacing:.1em;display:flex;gap:10px;box-shadow:0 0 22px #4f8cff66} .onair b{font:500 14px/30px var(--mono);letter-spacing:0} .btn{height:30px;padding:0 12px;border-radius:8px;border:1px solid var(--line);background:var(--p2);color:var(--text);font:600 12px/28px var(--ui);display:flex;align-items:center;gap:7px;white-space:nowrap} -.btn.end{background:transparent;border-color:var(--air);color:var(--air)} -.btn.rec .dot{background:var(--air)} +.btn.end{background:transparent;border-color:var(--accent);color:var(--accent)} +.btn.rec .dot{background:var(--accent)} .wc{display:flex;gap:7px;margin-left:4px}.wc i{width:12px;height:12px;border-radius:50%;background:var(--p3)} /* rail */ @@ -49,18 +49,18 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 .stagewrap{position:relative;min-width:0;min-height:0;display:flex;flex-direction:column;padding:16px 18px 8px;gap:8px; background:radial-gradient(120% 90% at 50% 0,#15151d,var(--bg))} .stage{position:relative;flex:1;min-height:0;display:flex;align-items:center;justify-content:center;container-type:size} -.tally{position:relative;width:min(100cqw - 12px,(100cqh - 12px)*16/9);aspect-ratio:16/9;border-radius:10px;outline:3px solid var(--air);outline-offset:3px;box-shadow:0 0 60px #ff2d4633} +.tally{position:relative;width:min(100cqw - 12px,(100cqh - 12px)*16/9);aspect-ratio:16/9;border-radius:10px;outline:3px solid var(--accent);outline-offset:3px;box-shadow:0 0 60px #4f8cff33} .tally.cue{outline-color:var(--cue);box-shadow:0 0 60px #ffb02026} .tally.cue::after{content:"";position:absolute;inset:-10px;border-radius:16px;z-index:-1; background:repeating-linear-gradient(-45deg,#ffb02033 0 12px,transparent 12px 24px)} -.tag{position:absolute;left:12px;top:12px;z-index:5;padding:0 9px;border-radius:5px;background:var(--air);color:#fff;font:700 15px/24px var(--disp);letter-spacing:.12em} +.tag{position:absolute;left:12px;top:12px;z-index:5;padding:0 9px;border-radius:5px;background:var(--accent);color:#fff;font:700 15px/24px var(--disp);letter-spacing:.12em} .tag.cue{background:var(--cue);color:#1a1200} .under{display:flex;align-items:center;gap:8px;height:30px;color:var(--dim);font-size:12px} .seg{display:flex;border:1px solid var(--line);border-radius:8px;overflow:hidden} .seg span{padding:5px 9px;font:500 11.5px/1 var(--ui);color:var(--dim)} .seg span.on{background:var(--p3);color:var(--text)} .chip{display:flex;align-items:center;gap:6px;height:26px;padding:0 9px;border-radius:8px;border:1px solid var(--line);font:500 11.5px/1 var(--ui);color:var(--dim);white-space:nowrap} -.rewind{flex:1;height:6px;border-radius:3px;background:linear-gradient(90deg,var(--p3) 0 78%,var(--air) 78% 100%);position:relative} +.rewind{flex:1;height:6px;border-radius:3px;background:linear-gradient(90deg,var(--p3) 0 78%,var(--accent) 78% 100%);position:relative} .rewind::after{content:"";position:absolute;right:0;top:-4px;width:3px;height:14px;background:#fff;border-radius:2px} /* fake pictures: sizes in cqw so the same markup is a thumbnail */ @@ -77,7 +77,7 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 .cam{right:3%;bottom:6%;width:19%;aspect-ratio:1;border-radius:50%;overflow:hidden;background:linear-gradient(160deg,#2b3350,#141826);box-shadow:0 0 0 .35cqw #fff,0 1cqw 3cqw #000a} .cam::before{content:"";position:absolute;left:32%;top:20%;width:36%;aspect-ratio:1;border-radius:50%;background:#e9b48f} .cam::after{content:"";position:absolute;left:14%;top:58%;width:72%;height:60%;border-radius:45% 45% 0 0;background:#3b6cf6} -.l3{left:3%;bottom:7%;padding:.9cqw 1.6cqw;border-radius:.9cqw;background:linear-gradient(90deg,#111a,#1118);border-left:.5cqw solid var(--air);color:#fff;font:700 2.6cqw/1.1 var(--disp);letter-spacing:.04em;backdrop-filter:blur(6px)} +.l3{left:3%;bottom:7%;padding:.9cqw 1.6cqw;border-radius:.9cqw;background:linear-gradient(90deg,#111a,#1118);border-left:.5cqw solid #ff2d46;color:#fff;font:700 2.6cqw/1.1 var(--disp);letter-spacing:.04em;backdrop-filter:blur(6px)} .l3 small{display:block;font:500 1.3cqw/1.4 var(--ui);letter-spacing:0;opacity:.8} .chat{background:linear-gradient(135deg,#2a1638,#101826)} .chat .cam{left:6%;top:10%;right:auto;bottom:auto;width:56%;height:80%;aspect-ratio:auto;border-radius:2cqw} @@ -94,12 +94,12 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 .close .obj{left:36%;top:22%;width:28%;height:52%;border-radius:2cqw;background:linear-gradient(160deg,#f6d365,#fda085);box-shadow:0 3cqw 5cqw #000a} /* selection on the stage */ -.selbox{position:absolute;right:3%;bottom:6%;width:19%;aspect-ratio:1;border:2px solid var(--sel);z-index:6} -.selbox i{position:absolute;width:10px;height:10px;background:#fff;border:2px solid var(--sel);border-radius:2px} +.selbox{position:absolute;right:3%;bottom:6%;width:19%;aspect-ratio:1;border:2px solid var(--accent);z-index:6} +.selbox i{position:absolute;width:10px;height:10px;background:#fff;border:2px solid var(--accent);border-radius:2px} .selbox i:nth-child(1){left:-6px;top:-6px}.selbox i:nth-child(2){right:-6px;top:-6px}.selbox i:nth-child(3){left:-6px;bottom:-6px}.selbox i:nth-child(4){right:-6px;bottom:-6px} .ctx{position:absolute;right:1%;bottom:calc(6% + 19% * 16 / 9 + 14px);z-index:7;display:flex;gap:2px;padding:4px;border-radius:10px;background:#1c1c25f2;border:1px solid var(--line);box-shadow:0 10px 30px #000a} .ctx span{display:flex;align-items:center;gap:6px;padding:6px 9px;border-radius:7px;font:500 12px/1 var(--ui);color:var(--text);white-space:nowrap} -.ctx span.on{background:var(--sel)} +.ctx span.on{background:var(--accent)} .guide{position:absolute;top:0;bottom:0;right:calc(3% + 9.5%);width:1px;background:#ff3df0;z-index:6} /* dock */ @@ -109,9 +109,9 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 .pad .th{height:66px;border-radius:7px;overflow:hidden} .pad .nm{display:flex;align-items:center;justify-content:space-between;padding:7px 4px 8px;font:600 14px/1 var(--disp);letter-spacing:.06em;text-transform:uppercase;white-space:nowrap;overflow:hidden} .pad kbd{position:absolute;right:8px;top:8px;z-index:2;background:#000a} -.pad.air{border-color:var(--air);box-shadow:0 0 24px #ff2d4640} +.pad.air{border-color:var(--accent);box-shadow:0 0 24px #4f8cff40} .pad.cued{border-color:var(--cue);box-shadow:0 0 24px #ffb02033} -.pad .tg{position:absolute;left:8px;top:8px;z-index:2;font:700 11px/16px var(--disp);letter-spacing:.12em;padding:0 5px;border-radius:3px;background:var(--air);color:#fff} +.pad .tg{position:absolute;left:8px;top:8px;z-index:2;font:700 11px/16px var(--disp);letter-spacing:.12em;padding:0 5px;border-radius:3px;background:var(--accent);color:#fff} .pad.cued .tg{background:var(--cue);color:#1a1200} .pad.add{height:100px;display:grid;place-items:center;border:2px dashed var(--line);background:transparent;color:var(--dim);width:52px} .tr{display:flex;flex-direction:column;align-items:center;gap:6px;color:var(--dim);font:500 10.5px/1 var(--ui)} @@ -123,9 +123,9 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 linear-gradient(90deg,var(--ok) 0 var(--v,60%),transparent var(--v,60%)), repeating-linear-gradient(90deg,var(--p3) 0 5px,transparent 5px 7px); -webkit-mask:repeating-linear-gradient(90deg,#000 0 5px,transparent 5px 7px);mask:repeating-linear-gradient(90deg,#000 0 5px,transparent 5px 7px)} -.led.hot{background:linear-gradient(90deg,var(--ok) 0 70%,var(--cue) 70% 88%,var(--air) 88% var(--v),transparent var(--v)),repeating-linear-gradient(90deg,var(--p3) 0 5px,transparent 5px 7px)} +.led.hot{background:linear-gradient(90deg,var(--ok) 0 70%,var(--cue) 70% 88%,var(--err) 88% var(--v),transparent var(--v)),repeating-linear-gradient(90deg,var(--p3) 0 5px,transparent 5px 7px)} .mute{width:26px;height:22px;border-radius:6px;background:var(--p3);display:grid;place-items:center;color:var(--text)} -.mute.off{background:var(--air)} +.mute.off{background:var(--cue);color:#1a1200} .master{width:64px;display:flex;flex-direction:column;align-items:center;gap:6px} .vled{flex:1;width:22px;border-radius:3px;background:linear-gradient(0deg,var(--ok) 0 58%,var(--cue) 58% 66%,var(--p3) 66%);-webkit-mask:repeating-linear-gradient(0deg,#000 0 4px,transparent 4px 6px);mask:repeating-linear-gradient(0deg,#000 0 4px,transparent 4px 6px)} .quick{display:flex;gap:6px;position:absolute;right:18px;bottom:8px} @@ -147,19 +147,19 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 .f span em{font:500 10px/1 var(--ui);color:var(--faint);font-style:normal} .shape{display:grid;grid-template-columns:repeat(4,1fr);gap:6px} .shape span{height:44px;border-radius:8px;background:var(--p2);border:1px solid var(--line);display:grid;place-items:center} -.shape span.on{border-color:var(--sel);background:#4f8cff22} +.shape span.on{border-color:var(--accent);background:#4f8cff22} .shape i{display:block;width:22px;height:22px;background:var(--dim)} .sl{display:flex;align-items:center;gap:10px;font-size:12px}.sl .n{width:92px;color:var(--dim)} -.sl .bar{flex:1;height:4px;border-radius:2px;background:linear-gradient(90deg,var(--sel) var(--v,40%),var(--p3) var(--v,40%));position:relative} +.sl .bar{flex:1;height:4px;border-radius:2px;background:linear-gradient(90deg,var(--accent) var(--v,40%),var(--p3) var(--v,40%));position:relative} .sl .bar::after{content:"";position:absolute;left:var(--v,40%);top:-5px;width:14px;height:14px;margin-left:-7px;border-radius:50%;background:#fff} .tog{width:32px;height:18px;border-radius:9px;background:var(--p3);position:relative;flex:none} .tog::after{content:"";position:absolute;left:2px;top:2px;width:14px;height:14px;border-radius:50%;background:#fff} -.tog.on{background:var(--sel)}.tog.on::after{left:16px} +.tog.on{background:var(--accent)}.tog.on::after{left:16px} /* layers drawer */ .drawer{position:absolute;left:0;top:0;bottom:0;width:272px;z-index:8;background:#131319f7;border-right:1px solid var(--line);box-shadow:20px 0 50px #0008;display:flex;flex-direction:column} .ly{display:flex;align-items:center;gap:9px;padding:7px 12px;font-size:12.5px} -.ly.on{background:#4f8cff26;box-shadow:inset 3px 0 0 var(--sel)} +.ly.on{background:#4f8cff26;box-shadow:inset 3px 0 0 var(--accent)} .ly small{display:block;color:var(--faint);font-size:10.5px;margin-top:2px} .ic{width:30px;height:30px;border-radius:8px;display:grid;place-items:center;flex:none;color:#fff} @@ -168,8 +168,8 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 .cuecard .th{height:160px;border-radius:8px;outline:2px solid var(--cue);overflow:hidden;position:relative} .take{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:8px} .take span{height:40px;border-radius:8px;display:grid;place-items:center;font:700 18px/1 var(--disp);letter-spacing:.14em} -.take .t{background:var(--air);color:#fff}.take .a{background:var(--p3)} -.pip{position:absolute;right:26px;top:22px;width:260px;z-index:8;border-radius:10px;outline:3px solid var(--air);overflow:hidden;height:146px;box-shadow:0 16px 40px #000a} +.take .t{background:var(--accent);color:#fff}.take .a{background:var(--p3)} +.pip{position:absolute;right:26px;top:22px;width:260px;z-index:8;border-radius:10px;outline:3px solid var(--accent);overflow:hidden;height:146px;box-shadow:0 16px 40px #000a} .banner{position:absolute;left:50%;top:22px;transform:translateX(-50%);z-index:8;display:flex;align-items:center;gap:10px;padding:6px 6px 6px 14px;border-radius:10px;background:var(--cue);color:#1a1200;font:700 16px/1 var(--disp);letter-spacing:.1em} .banner span{padding:7px 10px;border-radius:7px;background:#1a1200;color:var(--cue);font:600 12px/1 var(--ui);letter-spacing:0} @@ -182,7 +182,7 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 .keys{display:grid;grid-template-columns:repeat(5,112px);gap:8px} .key{height:92px;border-radius:9px;position:relative;overflow:hidden;border:2px solid #000;box-shadow:inset 0 0 0 1px #fff2,0 3px 0 #000} .key b{position:absolute;left:0;right:0;bottom:0;padding:10px 6px 5px;font:700 13px/1 var(--disp);letter-spacing:.08em;text-transform:uppercase;background:linear-gradient(transparent,#000d)} -.key.air{border-color:var(--air);box-shadow:0 0 18px var(--air),0 3px 0 #000} +.key.air{border-color:var(--accent);box-shadow:0 0 18px var(--accent),0 3px 0 #000} .key.plain{background:linear-gradient(#2a2a34,#1b1b23);display:grid;place-items:center;color:var(--dim)} .big{width:104px;height:92px;border-radius:9px;display:grid;place-items:center;font:700 24px/1 var(--disp);letter-spacing:.12em;border:2px solid #000;box-shadow:inset 0 1px 0 #fff3,0 3px 0 #000} .big.cut{background:linear-gradient(#ff5167,#d81932)}.big.auto{background:linear-gradient(#3a3a46,#24242d)} @@ -210,7 +210,7 @@ kbd{font:500 10px/1 var(--mono);padding:3px 5px;border-radius:4px;background:#00 .ib{width:30px;height:30px;border-radius:8px;display:grid;place-items:center;color:var(--dim);flex:none;position:relative} .ib.b{background:var(--p2);border:1px solid var(--line);color:var(--text)} .ib.cue{color:var(--cue);border-color:var(--cue)} -.onair.end{background:#2a0b12;box-shadow:inset 0 0 0 2px var(--air);color:var(--air)} +.onair.end{background:#0b1530;box-shadow:inset 0 0 0 2px var(--accent);color:var(--accent)} .pop{position:absolute;z-index:20;right:118px;top:54px;width:316px;border-radius:12px;background:#17171ef7;border:1px solid var(--line);box-shadow:0 20px 50px #000b;padding:6px 14px 10px;font-size:12.5px} .pop .r{display:flex;align-items:center;gap:8px;padding:8px 0;border-bottom:1px solid var(--line)} .pop .r:last-child{border:0}.pop b{font:500 12px/1 var(--mono)} diff --git a/quest/m0/ux/mock/kit.js b/quest/m0/ux/mock/kit.js index b2fcffdf..bcb68637 100644 --- a/quest/m0/ux/mock/kit.js +++ b/quest/m0/ux/mock/kit.js @@ -73,7 +73,7 @@ document.body.insertAdjacentHTML('afterbegin',String.raw`quietriver gg
hopper what sens do you play on
tin_kettle clip that!!
-
lowtide gifted 5 subs
+
lowtide gifted 5 subs
marrow first time here, this stream looks so clean
ibis song name?
vellum can you show the loadout again
@@ -90,7 +90,7 @@ document.body.insertAdjacentHTML('afterbegin',String.raw`Keep out of the waymoves off what matters
Shape -
+
Border
Shadow
@@ -134,7 +134,7 @@ function topbar(page,o={}){return `
${o.compact?'':`
${I('undo')}
${I('undo')}
`}
${o.nav===false?'':NAV(page)}
${o.compact?'':'Excellent'}
- ${o.compact?'':`
`} + ${o.compact?'':`
`} ${o.end?'
END STREAM
':'
LIVE 01:24:07
'} ${o.compact?'':`
${I('gear')}
`}
`} diff --git a/quest/m0/ux/mock/later-autolayout.webp b/quest/m0/ux/mock/later-autolayout.webp index faeee62e..399bdd71 100644 Binary files a/quest/m0/ux/mock/later-autolayout.webp and b/quest/m0/ux/mock/later-autolayout.webp differ diff --git a/quest/m0/ux/mock/later-autoplace.webp b/quest/m0/ux/mock/later-autoplace.webp index e980423b..d6cef310 100644 Binary files a/quest/m0/ux/mock/later-autoplace.webp and b/quest/m0/ux/mock/later-autoplace.webp differ diff --git a/quest/m0/ux/mock/later-capturehealth.webp b/quest/m0/ux/mock/later-capturehealth.webp index 0ee6969d..191e0bcc 100644 Binary files a/quest/m0/ux/mock/later-capturehealth.webp and b/quest/m0/ux/mock/later-capturehealth.webp differ diff --git a/quest/m0/ux/mock/later-drop.webp b/quest/m0/ux/mock/later-drop.webp index a3fde035..5aecefd8 100644 Binary files a/quest/m0/ux/mock/later-drop.webp and b/quest/m0/ux/mock/later-drop.webp differ diff --git a/quest/m0/ux/mock/later-dual.webp b/quest/m0/ux/mock/later-dual.webp index 80c4f26f..e2f99be1 100644 Binary files a/quest/m0/ux/mock/later-dual.webp and b/quest/m0/ux/mock/later-dual.webp differ diff --git a/quest/m0/ux/mock/later-mini.webp b/quest/m0/ux/mock/later-mini.webp index faf58661..f233554a 100644 Binary files a/quest/m0/ux/mock/later-mini.webp and b/quest/m0/ux/mock/later-mini.webp differ diff --git a/quest/m0/ux/mock/later-multiview.webp b/quest/m0/ux/mock/later-multiview.webp index b4e4be90..f7f9479f 100644 Binary files a/quest/m0/ux/mock/later-multiview.webp and b/quest/m0/ux/mock/later-multiview.webp differ diff --git a/quest/m0/ux/mock/later-panels.webp b/quest/m0/ux/mock/later-panels.webp index 6c401d8c..4fa5ac16 100644 Binary files a/quest/m0/ux/mock/later-panels.webp and b/quest/m0/ux/mock/later-panels.webp differ diff --git a/quest/m0/ux/mock/later-shield.webp b/quest/m0/ux/mock/later-shield.webp index 72310cd2..9b80ad0b 100644 Binary files a/quest/m0/ux/mock/later-shield.webp and b/quest/m0/ux/mock/later-shield.webp differ diff --git a/quest/m0/ux/mock/later.html b/quest/m0/ux/mock/later.html index be08e836..8e139881 100644 --- a/quest/m0/ux/mock/later.html +++ b/quest/m0/ux/mock/later.html @@ -9,7 +9,7 @@