@webship.co/workspace 0.0.0-stage → 1.0.0-beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PLUGINS.md +249 -0
- package/README.md +379 -2
- package/WORKSPACES.md +69 -0
- package/actions/ai-items.js +293 -0
- package/actions/audio.js +48 -0
- package/actions/build-order.js +79 -0
- package/actions/checks.js +95 -0
- package/actions/claude-session.js +104 -0
- package/actions/commands-center.js +258 -0
- package/actions/composer.js +267 -0
- package/actions/ddev-addons.js +90 -0
- package/actions/ddev-mail.js +80 -0
- package/actions/ddev.js +237 -0
- package/actions/folders.js +165 -0
- package/actions/images-svg.js +33 -0
- package/actions/images.js +145 -0
- package/actions/navigation.js +190 -0
- package/actions/node.js +222 -0
- package/actions/notes.js +55 -0
- package/actions/plugins.js +36 -0
- package/actions/project-make.js +28 -0
- package/actions/rag.js +202 -0
- package/actions/row-actions.js +262 -0
- package/actions/screens.js +270 -0
- package/actions/testing.js +121 -0
- package/actions/video-edit.js +54 -0
- package/ai-inventory.js +182 -0
- package/ai-items.js +202 -0
- package/assistant-cast.js +176 -0
- package/assistant-suggestions.js +91 -0
- package/assistant.js +484 -0
- package/audio-voice.js +528 -0
- package/auth-google.js +260 -0
- package/build-ai.js +52 -0
- package/build-order-page.js +191 -0
- package/build-order.js +313 -0
- package/builder-args.js +117 -0
- package/changelog.js +302 -0
- package/chat-threads.js +134 -0
- package/checks.js +105 -0
- package/claude-args.js +282 -0
- package/claude-sessions.js +129 -0
- package/command-author.js +117 -0
- package/command-block.js +20 -0
- package/commands/defaults.yml +159 -0
- package/commands-page.js +460 -0
- package/commands.js +568 -0
- package/cucumber.js +43 -0
- package/ddev-addons-page.js +124 -0
- package/ddev-addons.js +154 -0
- package/ddev-custom-commands.js +96 -0
- package/ddev-domains.js +84 -0
- package/ddev-import.js +93 -0
- package/ddev-mail-page.js +167 -0
- package/ddev-mail.js +110 -0
- package/ddev-options.js +145 -0
- package/ddev-snapshots.js +126 -0
- package/ddev.js +145 -0
- package/docs/DEVELOPER-GUIDE.md +224 -0
- package/docs/README.md +252 -0
- package/docs/REFERENCE.md +684 -0
- package/docs/USER-GUIDE.md +697 -0
- package/docs/screenshots/assistant/avatar-board.png +0 -0
- package/docs/screenshots/assistant/avatar-coffee.png +0 -0
- package/docs/screenshots/assistant/avatar-colours.png +0 -0
- package/docs/screenshots/assistant/avatar-icons.png +0 -0
- package/docs/screenshots/assistant/avatar-moves.png +0 -0
- package/docs/screenshots/assistant/avatar-pick-cookieman.png +0 -0
- package/docs/screenshots/assistant/avatar-settings-voices.png +0 -0
- package/docs/screenshots/assistant/avatar-status.png +0 -0
- package/docs/screenshots/create-card/create-card.png +0 -0
- package/docs/screenshots/create-card/start-ai.png +0 -0
- package/docs/screenshots/guide-clone-address.png +0 -0
- package/docs/screenshots/guide-clone-worktree-off.png +0 -0
- package/docs/screenshots/guide-clone-worktree-on.png +0 -0
- package/docs/screenshots/guide-ddev-menu.png +0 -0
- package/docs/screenshots/guide-domains.png +0 -0
- package/docs/screenshots/guide-home.png +0 -0
- package/docs/screenshots/guide-ide-menu.png +0 -0
- package/docs/screenshots/guide-remove-refusal.png +0 -0
- package/docs/screenshots/guide-rows-worktree.png +0 -0
- package/docs/screenshots/guide-screens.png +0 -0
- package/docs/screenshots/guide-settings.png +0 -0
- package/docs/screenshots/guide-workspace-page.png +0 -0
- package/docs/screenshots/home/card-settings.png +0 -0
- package/docs/screenshots/home/drag-reorder.png +0 -0
- package/docs/screenshots/home/edit-card.png +0 -0
- package/docs/screenshots/images/claude-code-image.png +0 -0
- package/docs/screenshots/images/edit-with-ai.png +0 -0
- package/docs/screenshots/images/gallery.png +0 -0
- package/docs/screenshots/images/generate-description.png +0 -0
- package/docs/screenshots/images/generate-plan.png +0 -0
- package/docs/screenshots/images/providers.png +0 -0
- package/docs/screenshots/images/svg-form.png +0 -0
- package/docs/screenshots/images/svg-result.png +0 -0
- package/docs/screenshots/images/upload.png +0 -0
- package/docs/screenshots/new-folder/2-form.png +0 -0
- package/docs/screenshots/new-folder/8-ddev-options.png +0 -0
- package/docs/screenshots/new-folder/files-folder.png +0 -0
- package/docs/screenshots/projects/ddev-custom-commands.png +0 -0
- package/docs/screenshots/projects/state-chip-stop.png +0 -0
- package/docs/screenshots/readme/dashboard-dark.png +0 -0
- package/docs/screenshots/readme/dashboard-light.png +0 -0
- package/docs/screenshots/readme/dev-dark.png +0 -0
- package/docs/screenshots/readme/dev-light.png +0 -0
- package/docs/screenshots/readme/docs-dark.png +0 -0
- package/docs/screenshots/readme/docs-light.png +0 -0
- package/docs/screenshots/readme/icons/ai.svg +4 -0
- package/docs/screenshots/readme/icons/code.svg +4 -0
- package/docs/screenshots/readme/icons/docs.svg +4 -0
- package/docs/screenshots/readme/icons/services.svg +4 -0
- package/docs/screenshots/readme/icons/sites.svg +4 -0
- package/docs/screenshots/readme/test-report-dark.png +0 -0
- package/docs/screenshots/readme/test-report-light.png +0 -0
- package/docs/screenshots/readme/test-scenarios.png +0 -0
- package/docs/screenshots/readme/test-steps.png +0 -0
- package/docs/screenshots/readme/videos-dark.png +0 -0
- package/docs/screenshots/readme/videos-light.png +0 -0
- package/docs/screenshots/screens-menu.png +0 -0
- package/docs/screenshots/screens-new.png +0 -0
- package/docs/screenshots/settings/auth-google-lists.png +0 -0
- package/docs/screenshots/settings/delete-1-row.png +0 -0
- package/docs/screenshots/settings/delete-2-confirm.png +0 -0
- package/docs/screenshots/settings/delete-3-type-name.png +0 -0
- package/docs/screenshots/settings/delete-4-type-yes.png +0 -0
- package/event-log.js +59 -0
- package/files-browser.js +247 -0
- package/folders.js +121 -0
- package/format.js +73 -0
- package/git-info.js +81 -0
- package/github-auth.js +62 -0
- package/html.js +10 -0
- package/icons.js +83 -0
- package/images-ai.js +447 -0
- package/images-create.js +226 -0
- package/images-page.js +417 -0
- package/images-records.js +39 -0
- package/images-render.js +36 -0
- package/images-svg-core.js +214 -0
- package/images-svg-sanitize.js +188 -0
- package/images-svg.js +241 -0
- package/images.js +270 -0
- package/jobs.js +430 -0
- package/linger.js +21 -0
- package/lists.js +292 -0
- package/media-info.js +136 -0
- package/navigation-page.js +264 -0
- package/navigation.js +394 -0
- package/notes.js +0 -0
- package/package.json +47 -4
- package/palette-index.js +46 -0
- package/playwright.config.js +23 -0
- package/plugin-install.js +239 -0
- package/plugin-loader.js +466 -0
- package/plugin-manifest.js +83 -0
- package/plugin-settings.js +44 -0
- package/plugins/workspace-notes/index.js +59 -0
- package/plugins-page.js +103 -0
- package/project-make.js +241 -0
- package/project-name.js +210 -0
- package/public/assistant-avatar-moves.js +646 -0
- package/public/assistant-avatar-ui.js +1223 -0
- package/public/assistant-avatar.js +530 -0
- package/public/avatar/druplicon.vrm +0 -0
- package/public/css/base.css +260 -0
- package/public/css/components/ai-assistant.css +263 -0
- package/public/css/components/assistant-avatar.css +279 -0
- package/public/css/components/assistant-views.css +198 -0
- package/public/css/components/build-order.css +74 -0
- package/public/css/components/clone-as-a-git-worktree.css +30 -0
- package/public/css/components/command-palette.css +61 -0
- package/public/css/components/commands-center.css +139 -0
- package/public/css/components/confirm-dialog.css +40 -0
- package/public/css/components/create-card.css +8 -0
- package/public/css/components/ddev-menu.css +23 -0
- package/public/css/components/deep-chat.css +17 -0
- package/public/css/components/density.css +11 -0
- package/public/css/components/floating-assistant-workspace-pages.css +55 -0
- package/public/css/components/folders.css +5 -0
- package/public/css/components/full-height-left-assistant-sidebar-all-pages.css +39 -0
- package/public/css/components/full-height-right-actions-rail-pages-that-have-actions.css +267 -0
- package/public/css/components/grid-and-list.css +203 -0
- package/public/css/components/help-page.css +36 -0
- package/public/css/components/hero.css +16 -0
- package/public/css/components/images.css +70 -0
- package/public/css/components/layout-rhythm-and-spacing-polish.css +139 -0
- package/public/css/components/mic-on-any-field-that-wants-typing.css +416 -0
- package/public/css/components/modal-fit.css +113 -0
- package/public/css/components/page-width.css +23 -0
- package/public/css/components/plugins-page.css +9 -0
- package/public/css/components/project-cards.css +256 -0
- package/public/css/components/project-rows.css +390 -0
- package/public/css/components/reordering-the-workspace-cards.css +85 -0
- package/public/css/components/responsive-home-and-the-workspace-pages.css +457 -0
- package/public/css/components/running-commands-as-toasts.css +327 -0
- package/public/css/components/settings-editor-core-config-yml.css +828 -0
- package/public/css/components/short-results-as-a-toast-at-the-top.css +203 -0
- package/public/css/components/sound-player.css +84 -0
- package/public/css/components/suggest-agents-skills-commands.css +112 -0
- package/public/css/components/tab-modal.css +142 -0
- package/public/css/components/terminals.css +244 -0
- package/public/css/components/test-report-media-one-file-per-row-paged.css +144 -0
- package/public/css/components/top-toolbar-logo-breadcrumb.css +107 -0
- package/public/css/components/video-edit.css +6 -0
- package/public/css/components/web-ide-open-with.css +23 -0
- package/public/css/components/working-indicators.css +158 -0
- package/public/css/components/workspace-cards.css +79 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.png +0 -0
- package/public/htmx.min.js +1 -0
- package/public/logo.png +0 -0
- package/public/media-player.js +215 -0
- package/public/mic.js +255 -0
- package/public/narration.js +110 -0
- package/public/palette.js +278 -0
- package/public/sortable.js +251 -0
- package/public/suggest.js +337 -0
- package/public/terminal.js +903 -0
- package/public/themes/default/theme.css +267 -0
- package/public/themes/ember/theme.css +180 -0
- package/public/themes/press/theme.css +290 -0
- package/public/themes/slate/theme.css +182 -0
- package/public/touch-icon.png +0 -0
- package/public/ui.js +2721 -0
- package/public/vendor/ace/LICENSE.txt +24 -0
- package/public/vendor/ace/ace.js +23 -0
- package/public/vendor/ace/ext-language_tools.js +8 -0
- package/public/vendor/ace/ext-searchbox.js +8 -0
- package/public/vendor/ace/mode-css.js +8 -0
- package/public/vendor/ace/mode-html.js +8 -0
- package/public/vendor/ace/mode-javascript.js +8 -0
- package/public/vendor/ace/mode-markdown.js +8 -0
- package/public/vendor/ace/mode-sh.js +8 -0
- package/public/vendor/ace/mode-yaml.js +8 -0
- package/public/vendor/ace/theme-textmate.js +8 -0
- package/public/vendor/ace/theme-tomorrow_night.js +8 -0
- package/public/vendor/ace/worker-yaml.js +1 -0
- package/public/vendor/deep-chat.LICENSE +21 -0
- package/public/vendor/deep-chat.bundle.js +1 -0
- package/public/vendor/fonts/dm-serif-text-LICENSE.txt +93 -0
- package/public/vendor/fonts/dm-serif-text-latin-400-italic.woff2 +0 -0
- package/public/vendor/fonts/dm-serif-text-latin-400-normal.woff2 +0 -0
- package/public/vendor/fonts/figtree-LICENSE.txt +93 -0
- package/public/vendor/fonts/figtree-latin-400-italic.woff2 +0 -0
- package/public/vendor/fonts/figtree-latin-400-normal.woff2 +0 -0
- package/public/vendor/fonts/figtree-latin-600-italic.woff2 +0 -0
- package/public/vendor/fonts/figtree-latin-600-normal.woff2 +0 -0
- package/public/vendor/fonts/jetbrains-mono-LICENSE.txt +93 -0
- package/public/vendor/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/public/vendor/fonts/ubuntu-mono-LICENSE.txt +98 -0
- package/public/vendor/fonts/ubuntu-mono-latin-wght-normal.woff2 +0 -0
- package/public/vendor/tabler-LICENSE.txt +21 -0
- package/public/vendor/tabler-sprite.svg +1 -0
- package/public/vendor/three/LICENSE +21 -0
- package/public/vendor/three/addons/loaders/GLTFLoader.js +4860 -0
- package/public/vendor/three/addons/utils/BufferGeometryUtils.js +1501 -0
- package/public/vendor/three/addons/utils/SkeletonUtils.js +496 -0
- package/public/vendor/three/three.core.min.js +6 -0
- package/public/vendor/three/three.module.min.js +6 -0
- package/public/vendor/three-vrm/LICENSE +22 -0
- package/public/vendor/three-vrm/three-vrm.module.min.js +983 -0
- package/public/vendor/uikit-icons.min.js +1 -0
- package/public/vendor/uikit.min.css +1 -0
- package/public/vendor/uikit.min.js +1 -0
- package/public/vendor/webship-icons/ui/bookmark-outlined.svg +1 -0
- package/public/vendor/webship-icons/ui/headset.svg +1 -0
- package/public/vendor/webship-icons/ui/menu.svg +1 -0
- package/public/vendor/webship-icons/ui/pause.svg +1 -0
- package/public/vendor/webship-icons/ui/play.svg +1 -0
- package/public/vendor/webship-icons/ui/share.svg +1 -0
- package/public/vendor/webship-icons/ui/sound-off.svg +1 -0
- package/public/vendor/webship-icons/ui/sound-on.svg +1 -0
- package/public/vendor/webship-icons/ui/stop.svg +1 -0
- package/public/vendor/xterm/addon-fit.js +2 -0
- package/public/vendor/xterm/addon-unicode11.js +2 -0
- package/public/vendor/xterm/addon-web-links.js +2 -0
- package/public/vendor/xterm/xterm.css +218 -0
- package/public/vendor/xterm/xterm.js +2 -0
- package/rag.js +169 -0
- package/reader.js +132 -0
- package/repo-blobs.js +66 -0
- package/report-pdf.js +337 -0
- package/row-layout.js +1439 -0
- package/screenrc +37 -0
- package/screens.js +1063 -0
- package/scripts/code-server-start.sh +190 -0
- package/scripts/images-claude-finish.js +107 -0
- package/scripts/screen-host.sh +114 -0
- package/scripts/screen-runner.js +362 -0
- package/scripts/screen-then.js +47 -0
- package/scripts/update.sh +350 -0
- package/server.js +7923 -0
- package/settings-file.js +423 -0
- package/speech.js +297 -0
- package/tab-modal.js +75 -0
- package/test-reports.js +260 -0
- package/themes.js +381 -0
- package/transcripts.js +168 -0
- package/urls.js +13 -0
- package/validate.js +18 -0
- package/version-check.js +94 -0
- package/video-edit.js +588 -0
- package/waiting.js +85 -0
- package/workspace-card-tools.js +41 -0
- package/workspace-delete.js +139 -0
- package/workspace-types.js +85 -0
- package/workspaces.js +553 -0
|
@@ -0,0 +1,828 @@
|
|
|
1
|
+
/* ---------- Settings editor (core/config/*.yml) ---------- */
|
|
2
|
+
|
|
3
|
+
.settings-tabs { display: flex; flex-wrap: wrap; gap:0.375rem; margin-bottom:0.25rem; }
|
|
4
|
+
.settings-tab { border-radius:31.25rem; }
|
|
5
|
+
|
|
6
|
+
.settings-row {
|
|
7
|
+
display: grid;
|
|
8
|
+
grid-template-columns: minmax(14rem, 38%) 1fr;
|
|
9
|
+
align-items: start;
|
|
10
|
+
gap:0.75rem;
|
|
11
|
+
padding:0.4375rem 0;
|
|
12
|
+
border-bottom: 1px solid var(--line);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.settings-row:last-of-type { border-bottom: 0; }
|
|
16
|
+
|
|
17
|
+
/* A row with no hint still reads as one line: only the taller ones need the offset. */
|
|
18
|
+
.settings-row > .uk-input,
|
|
19
|
+
.settings-row > .image-field,
|
|
20
|
+
.settings-row > .settings-toggle { margin-top: 0.0625rem; }
|
|
21
|
+
|
|
22
|
+
.settings-key {
|
|
23
|
+
font-family: var(--font-code);
|
|
24
|
+
font-size: .8rem;
|
|
25
|
+
color: var(--text-subtle);
|
|
26
|
+
word-break: break-all;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* A secret is marked, because the field being empty is meaningful here: it means
|
|
30
|
+
"unchanged", not "no value". */
|
|
31
|
+
.settings-key .uk-label {
|
|
32
|
+
background: var(--subtle-accent);
|
|
33
|
+
/* Not --brand-secondary: that navy does not flip, and on the dark accent tint it was 1.7:1. */
|
|
34
|
+
color: var(--accent-ink);
|
|
35
|
+
margin-left:0.25rem;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.settings-readonly { font-size: .8rem; }
|
|
39
|
+
|
|
40
|
+
@media (max-width: 39.9375em) {
|
|
41
|
+
.settings-row { grid-template-columns: 1fr; gap:0.25rem; }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* The workspaces list in the settings editor: what exists, and the card order. */
|
|
45
|
+
.settings-row-block { align-items: start; }
|
|
46
|
+
|
|
47
|
+
.ws-list {
|
|
48
|
+
list-style: none;
|
|
49
|
+
margin:0 0 0.625rem;
|
|
50
|
+
padding: 0;
|
|
51
|
+
border: 1px solid var(--line);
|
|
52
|
+
border-radius:0.5rem;
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.ws-item {
|
|
57
|
+
display: flex;
|
|
58
|
+
align-items: center;
|
|
59
|
+
gap:0.5rem;
|
|
60
|
+
padding:0.3125rem 0.5rem;
|
|
61
|
+
background: var(--surface-card);
|
|
62
|
+
border-bottom: 1px solid var(--line);
|
|
63
|
+
font-size: .84rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.ws-item:last-child { border-bottom: 0; }
|
|
67
|
+
html.dark .ws-item { background: transparent; }
|
|
68
|
+
|
|
69
|
+
.ws-order {
|
|
70
|
+
min-width:1.375rem;
|
|
71
|
+
font-family: var(--font-code);
|
|
72
|
+
font-size: .72rem;
|
|
73
|
+
color: var(--text-subtle);
|
|
74
|
+
text-align: right;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.ws-name { font-weight: 600; }
|
|
78
|
+
.ws-move { margin-left: auto; display: flex; gap:0.25rem; }
|
|
79
|
+
.ws-move .uk-button { border-radius:0.375rem; padding:0 0.4375rem; line-height:1.5rem; }
|
|
80
|
+
.ws-item { flex-wrap: wrap; }
|
|
81
|
+
.ws-in-use { font-size: .72rem; padding: 0 0.25rem; cursor: help; align-self: center; }
|
|
82
|
+
.ws-move .ws-delete:not(:hover, :focus-visible) { color: var(--text-subtle); }
|
|
83
|
+
.ws-move .ws-delete:is(:hover, :focus-visible) { color: var(--danger); border-color: var(--danger); }
|
|
84
|
+
.ws-delete-step {
|
|
85
|
+
flex-basis: 100%;
|
|
86
|
+
margin: 0.25rem 0 0.25rem 1.875rem;
|
|
87
|
+
padding: 0.5rem 0.75rem;
|
|
88
|
+
border: 1px solid var(--danger);
|
|
89
|
+
border-radius: 0.5rem;
|
|
90
|
+
background: var(--danger-soft);
|
|
91
|
+
}
|
|
92
|
+
.ws-delete-step p { margin: 0 0 0.375rem; }
|
|
93
|
+
.ws-delete-step .ws-delete-error { color: var(--danger-text); font-weight: 600; }
|
|
94
|
+
.ws-delete-fields { display: flex; gap: 0.5rem; align-items: center; }
|
|
95
|
+
.ws-delete-fields .uk-input { max-width: 12.5rem; background: var(--surface-card); }
|
|
96
|
+
.ws-add { display: flex; gap:0.5rem; align-items: center; }
|
|
97
|
+
.ws-add .uk-input { max-width:16.25rem; }
|
|
98
|
+
|
|
99
|
+
/* Drag handle for the workspaces list. */
|
|
100
|
+
.ws-handle {
|
|
101
|
+
cursor: grab;
|
|
102
|
+
/* The same story as .row-handle: quiet by colour, not by fading the token that is already quiet. */
|
|
103
|
+
color: var(--line-strong);
|
|
104
|
+
padding:0 0.125rem;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.ws-item:hover .ws-handle { opacity: 1; color: var(--brand-primary); }
|
|
108
|
+
.ws-list > .uk-sortable-drag { background: var(--subtle-brand); }
|
|
109
|
+
.ws-list > .uk-sortable-placeholder { opacity: .35; }
|
|
110
|
+
|
|
111
|
+
/* A set, not a sequence: modules, themes, profiles, site_templates. No handles or
|
|
112
|
+
arrows, and a scroller once the list is long — themes: is 436 entries. */
|
|
113
|
+
.set-list {
|
|
114
|
+
list-style: none;
|
|
115
|
+
margin:0 0 0.625rem;
|
|
116
|
+
padding:0.375rem 0.5rem;
|
|
117
|
+
border: 1px solid var(--line);
|
|
118
|
+
border-radius:0.5rem;
|
|
119
|
+
display: flex;
|
|
120
|
+
flex-wrap: wrap;
|
|
121
|
+
gap:0.25rem 0.375rem;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.set-list-scroll { max-height:16.25rem; overflow-y: auto; }
|
|
125
|
+
|
|
126
|
+
.set-item {
|
|
127
|
+
font-family: var(--font-code);
|
|
128
|
+
font-size: .74rem;
|
|
129
|
+
background: var(--subtle-light);
|
|
130
|
+
border: 1px solid var(--line);
|
|
131
|
+
border-radius:0.25rem;
|
|
132
|
+
padding:0.0625rem 0.375rem;
|
|
133
|
+
color: var(--text-subtle);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
html.dark .set-item { background: transparent; }
|
|
137
|
+
|
|
138
|
+
/* Icon + description for a workspace, with a live preview of the card line. */
|
|
139
|
+
.pres-preview {
|
|
140
|
+
display: flex;
|
|
141
|
+
align-items: center;
|
|
142
|
+
gap:0.625rem;
|
|
143
|
+
padding:0.5rem 0.625rem;
|
|
144
|
+
margin-bottom:0.5rem;
|
|
145
|
+
border: 1px solid var(--line);
|
|
146
|
+
border-radius:0.5rem;
|
|
147
|
+
background: var(--subtle-light);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
html.dark .pres-preview { background: transparent; }
|
|
151
|
+
|
|
152
|
+
.pres-icon {
|
|
153
|
+
width:2.375rem;
|
|
154
|
+
height:2.375rem;
|
|
155
|
+
min-width:2.375rem;
|
|
156
|
+
border-radius:0.625rem;
|
|
157
|
+
background: var(--subtle-brand);
|
|
158
|
+
color: var(--brand-primary);
|
|
159
|
+
display: inline-flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
justify-content: center;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.pres-fields { display: flex; flex-wrap: wrap; gap:0.5rem; align-items: center; }
|
|
165
|
+
.pres-fields .uk-select { max-width:9.375rem; }
|
|
166
|
+
.pres-fields .uk-input { max-width:20rem; }
|
|
167
|
+
|
|
168
|
+
/* Icon chooser: the icons themselves, not their names. Radios so it works by
|
|
169
|
+
keyboard and needs no JavaScript — :checked + label does the highlighting. */
|
|
170
|
+
.icon-grid {
|
|
171
|
+
display: flex;
|
|
172
|
+
flex-wrap: wrap;
|
|
173
|
+
gap:0.375rem;
|
|
174
|
+
margin-bottom:0.625rem;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.icon-radio {
|
|
178
|
+
position: absolute;
|
|
179
|
+
opacity: 0;
|
|
180
|
+
width: 0;
|
|
181
|
+
height: 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.icon-choice {
|
|
185
|
+
width:2.125rem;
|
|
186
|
+
height:2.125rem;
|
|
187
|
+
border: 1px solid var(--line);
|
|
188
|
+
border-radius:0.5rem;
|
|
189
|
+
display: inline-flex;
|
|
190
|
+
align-items: center;
|
|
191
|
+
justify-content: center;
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
color: var(--text-subtle);
|
|
194
|
+
background: var(--surface-card);
|
|
195
|
+
transition: border-color .15s, color .15s, background .15s;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.icon-choice:hover { border-color: var(--brand-primary); color: var(--brand-primary); }
|
|
199
|
+
|
|
200
|
+
.icon-radio:checked + .icon-choice {
|
|
201
|
+
border-color: var(--brand-primary);
|
|
202
|
+
background: var(--subtle-brand);
|
|
203
|
+
color: var(--brand-primary);
|
|
204
|
+
box-shadow: 0 0 0 2px var(--subtle-brand);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* Keyboard focus has to be visible, since the input itself is off-screen. */
|
|
208
|
+
.icon-radio:focus-visible + .icon-choice {
|
|
209
|
+
outline: 2px solid var(--brand-primary);
|
|
210
|
+
outline-offset: 2px;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* 162 icons: cap the grid and let it scroll, with the filter above it. */
|
|
214
|
+
.icon-filter { max-width:16.25rem; margin-bottom:0.5rem; height:2rem; font-size: .82rem; }
|
|
215
|
+
.icon-grid { max-height:10.5rem; overflow-y: auto; padding:0.125rem; }
|
|
216
|
+
|
|
217
|
+
/* Tabler icons come from the vendored sprite; UIKit's come from uk-icon. Both must
|
|
218
|
+
sit on the same baseline and take the current colour. */
|
|
219
|
+
.tabler-icon { display: inline-block; vertical-align: middle; }
|
|
220
|
+
|
|
221
|
+
.icon-sets { display: flex; flex-direction: column; gap:0.25rem; }
|
|
222
|
+
|
|
223
|
+
.icon-set-label {
|
|
224
|
+
font-size: .7rem;
|
|
225
|
+
font-weight: 700;
|
|
226
|
+
letter-spacing: .06em;
|
|
227
|
+
text-transform: uppercase;
|
|
228
|
+
color: var(--text-subtle);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* The Tabler grid is 2000 tiles, so it gets its own scroller and the filter does
|
|
232
|
+
the real work of finding one. */
|
|
233
|
+
.icon-grid-tabler { max-height:13.125rem; }
|
|
234
|
+
|
|
235
|
+
/* Pager under the icon grid. */
|
|
236
|
+
.icon-pager {
|
|
237
|
+
display: flex;
|
|
238
|
+
align-items: center;
|
|
239
|
+
gap:0.375rem;
|
|
240
|
+
flex-wrap: wrap;
|
|
241
|
+
margin-top:0.375rem;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.icon-pager .icon-page {
|
|
245
|
+
border-radius:0.375rem;
|
|
246
|
+
padding:0 0.5625rem;
|
|
247
|
+
line-height:1.625rem;
|
|
248
|
+
min-width:1.875rem;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.icon-pager .uk-text-meta { font-size: .74rem; }
|
|
252
|
+
|
|
253
|
+
/* The pager on every list (items, projects, backups, commands). It renders both above
|
|
254
|
+
and below the rows: on a 200-row page the bottom one is where you arrive after
|
|
255
|
+
reading, and the top one is where the size chooser is looked for. */
|
|
256
|
+
.list-pager {
|
|
257
|
+
display: flex;
|
|
258
|
+
align-items: center;
|
|
259
|
+
gap: 0.375rem;
|
|
260
|
+
flex-wrap: wrap;
|
|
261
|
+
margin: 0.5rem 0;
|
|
262
|
+
padding: 0.375rem 0;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.list-pager .uk-text-meta { font-size: .78rem; }
|
|
266
|
+
|
|
267
|
+
/* A disabled step renders as a <span>, not a <button>: a button that cannot act still
|
|
268
|
+
takes a tab stop and still looks pressable. It keeps the same footprint so the row
|
|
269
|
+
does not shift as you move between the first and last page. */
|
|
270
|
+
.list-pager [disabled] { opacity: .45; cursor: default; }
|
|
271
|
+
|
|
272
|
+
.list-pager-size {
|
|
273
|
+
display: inline-flex;
|
|
274
|
+
align-items: center;
|
|
275
|
+
gap: 0.375rem;
|
|
276
|
+
margin-right: 0.25rem;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* UIKit's uk-form-small select is sized for a form row; in a pager it only holds
|
|
280
|
+
"20"…"All", so let it shrink to its content instead of stretching the bar. */
|
|
281
|
+
.list-pager-size .uk-select {
|
|
282
|
+
width: auto;
|
|
283
|
+
min-width: 4.5rem;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* Tabler icons come through <use> from an EXTERNAL sprite, and presentation
|
|
287
|
+
attributes on that file's root <svg> do NOT cross into this document — the symbol
|
|
288
|
+
inherits from the host <svg>, which had none, so every icon drew at the default
|
|
289
|
+
1px stroke and looked thin and wrong. Stating them here fixes every use at once
|
|
290
|
+
and keeps the sprite free of 4736 repetitions. */
|
|
291
|
+
.tabler-icon {
|
|
292
|
+
fill: none;
|
|
293
|
+
stroke: currentColor;
|
|
294
|
+
stroke-width: 1.75;
|
|
295
|
+
stroke-linecap: round;
|
|
296
|
+
stroke-linejoin: round;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/* And they are brand-coloured where the old uk-icon carried uk-text-primary: the
|
|
300
|
+
card tile, the page heading and the chooser's preview. Dropping that class when I
|
|
301
|
+
moved to <svg> is why they turned grey. */
|
|
302
|
+
.workspace-card .icon .tabler-icon,
|
|
303
|
+
.page-heading-icon .tabler-icon,
|
|
304
|
+
.pres-icon .tabler-icon { color: var(--brand-primary); }
|
|
305
|
+
|
|
306
|
+
/* A slightly lighter stroke at large sizes: 1.75 reads heavy at 28px+. */
|
|
307
|
+
.workspace-card .icon .tabler-icon,
|
|
308
|
+
.page-heading-icon .tabler-icon { stroke-width: 1.6; }
|
|
309
|
+
|
|
310
|
+
/* Ace, where a file is code. The textarea stays in the DOM (hidden) because it is
|
|
311
|
+
what the form submits — Ace only mirrors into it. */
|
|
312
|
+
.ace-host {
|
|
313
|
+
width: 100%;
|
|
314
|
+
border: 1px solid var(--line);
|
|
315
|
+
border-radius:0.5rem;
|
|
316
|
+
font-size:0.8125rem;
|
|
317
|
+
line-height: 1.5;
|
|
318
|
+
overflow: hidden; /* keep the rounded corners */
|
|
319
|
+
}
|
|
320
|
+
/* A one-line editor (a command line) sizes itself to its line; a read-only one is code to read, with no cursor. */
|
|
321
|
+
.ace-host-single { padding: 0.25rem 0; }
|
|
322
|
+
.ace-host-readonly .ace_cursor-layer { display: none; }
|
|
323
|
+
|
|
324
|
+
/* The gutter, the active line and the rest of the editor's chrome belong to Ace's
|
|
325
|
+
theme — it ships a matched set per theme and overriding one piece from here breaks
|
|
326
|
+
the match. These were keyed on html.dark, so a dark editor forced onto a light page
|
|
327
|
+
(style.editor_theme: dark) got a LIGHT gutter of line numbers beside dark code. Ace
|
|
328
|
+
styles .ace_gutter itself; let it. */
|
|
329
|
+
|
|
330
|
+
/* Ace positions its own scrollbars; the card must not clip the search box. */
|
|
331
|
+
.editor-card { overflow: visible; }
|
|
332
|
+
|
|
333
|
+
/* The editor modal. Wide, because a script needs the width, and tall enough that the
|
|
334
|
+
editor is the page rather than a slot in it. */
|
|
335
|
+
#editor-modal .uk-modal-dialog { width:min(68.75rem, 94vw); }
|
|
336
|
+
#editor-modal .uk-modal-body { padding:1.375rem 1.625rem; }
|
|
337
|
+
#editor-modal .editor-card { box-shadow: none; border: 0; padding: 0; }
|
|
338
|
+
#editor-modal .ace-host:not(.ace-host-single) { height:min(62vh, 38.75rem) !important; }
|
|
339
|
+
|
|
340
|
+
/* The save result sits above the editor, where the eye already is, and is sticky so
|
|
341
|
+
it stays visible while the editor scrolls under it. */
|
|
342
|
+
#editor-result:not(:empty) {
|
|
343
|
+
position: sticky;
|
|
344
|
+
top: 0;
|
|
345
|
+
z-index: 2;
|
|
346
|
+
margin-bottom:0.625rem;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
#editor-result .msg { margin-top: 0; }
|
|
350
|
+
|
|
351
|
+
/* Toolbar: the Webship wordmark from the brand tokens (Figma nodes 7989-1383
|
|
352
|
+
light / 7989-1385 dark — identical geometry, the wordmark ink is the only
|
|
353
|
+
difference, so the file is swapped rather than the artwork recoloured), then the
|
|
354
|
+
product name on its own. "Webship Workspace" beside a Webship wordmark said Webship
|
|
355
|
+
twice. */
|
|
356
|
+
.toolbar-logo { display: flex; align-items: center; gap:0.625rem; }
|
|
357
|
+
|
|
358
|
+
/* UIKit's .uk-logo sets font-size on the anchor, so the product name needs the extra
|
|
359
|
+
specificity — declared 1rem, it was rendering at UIKit's 20px. */
|
|
360
|
+
.toolbar .toolbar-product {
|
|
361
|
+
font-size:1.0625rem;
|
|
362
|
+
font-weight: 600;
|
|
363
|
+
letter-spacing: -0.01em;
|
|
364
|
+
color: var(--ink);
|
|
365
|
+
/* A hairline divider, so the product name reads as ours rather than as part of
|
|
366
|
+
the wordmark. */
|
|
367
|
+
padding-left:0.6875rem;
|
|
368
|
+
border-left: 1px solid var(--line);
|
|
369
|
+
line-height: 1.1;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
/* The item editor's text area: code, so the code face and a tighter rhythm than body text.
|
|
375
|
+
* Moved here from the default theme's file, where only one of the three themes had it. */
|
|
376
|
+
.editor-card .editor-area {
|
|
377
|
+
font-family: var(--font-code);
|
|
378
|
+
font-size: 0.8125rem;
|
|
379
|
+
line-height: 1.5;
|
|
380
|
+
resize: vertical;
|
|
381
|
+
background: var(--surface-input);
|
|
382
|
+
color: var(--text-subtle-2);
|
|
383
|
+
border-color: var(--line);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/* Asking the assistant to change a command, and reviewing what it answered.
|
|
387
|
+
*
|
|
388
|
+
* The proposal is shown as a diff inside the editor rather than applied: a cmd-*.sh is executed by
|
|
389
|
+
* the dashboard and by a terminal, so nothing changes one without a person having read the change. */
|
|
390
|
+
.cmd-ai-row { gap: 0.5rem; }
|
|
391
|
+
.cmd-ai-row .uk-input { flex: 1; }
|
|
392
|
+
|
|
393
|
+
.cmd-proposal { background: var(--busy-soft); border-left: 3px solid var(--link); }
|
|
394
|
+
|
|
395
|
+
.cmd-diff {
|
|
396
|
+
max-height: 18rem;
|
|
397
|
+
overflow: auto;
|
|
398
|
+
margin: 0.5rem 0 0;
|
|
399
|
+
padding: 0.5rem 0.625rem;
|
|
400
|
+
background: var(--code-bg);
|
|
401
|
+
color: var(--code-ink);
|
|
402
|
+
font-family: var(--font-code);
|
|
403
|
+
font-size: 0.72rem;
|
|
404
|
+
line-height: 1.45;
|
|
405
|
+
border-radius: 0.375rem;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/* A number is a number.
|
|
409
|
+
*
|
|
410
|
+
* Sized to its content rather than stretched across the row: a millisecond value is four characters
|
|
411
|
+
* and a full-width box for it reads as though something longer belongs there. The unit sits beside
|
|
412
|
+
* it as quiet text — "1 is normal" answers the question a bare spinner leaves open, and answering it
|
|
413
|
+
* in the label would make every label a sentence. */
|
|
414
|
+
.settings-row > .settings-number {
|
|
415
|
+
width: 9rem;
|
|
416
|
+
flex: 0 0 auto;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.settings-unit {
|
|
420
|
+
align-self: center;
|
|
421
|
+
margin-inline-start: .6rem;
|
|
422
|
+
color: var(--text-subtle);
|
|
423
|
+
font-size: .82rem;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/* The list of voices this browser actually has, under the field that asks for one.
|
|
427
|
+
* Full row width beneath the input rather than beside it: the names are long
|
|
428
|
+
* ("Microsoft Zira - English (United States)") and there can be dozens. */
|
|
429
|
+
.settings-voices {
|
|
430
|
+
flex: 1 0 100%;
|
|
431
|
+
margin-top: .4rem;
|
|
432
|
+
font-size: .82rem;
|
|
433
|
+
line-height: 1.7;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.settings-voices .voice-pick {
|
|
437
|
+
font-size: .82rem;
|
|
438
|
+
text-decoration: none;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/* A command's own description, from its ARGPARSE_DESCRIPTION.
|
|
442
|
+
*
|
|
443
|
+
* On its own line under the file name rather than beside it: the names are long
|
|
444
|
+
* (cmd-webship11-0-x-project.sh) and the descriptions are sentences, so side by side
|
|
445
|
+
* they wrap into each other and neither is scannable. */
|
|
446
|
+
.cmd-id { display: block; }
|
|
447
|
+
|
|
448
|
+
/* The human name leads, because that is what tells two commands apart:
|
|
449
|
+
* cmd-webship11-0-x-project.sh and cmd-webship11-0-0-project.sh differ by
|
|
450
|
+
* one character in the middle. */
|
|
451
|
+
.cmd-title {
|
|
452
|
+
display: block;
|
|
453
|
+
font-weight: 600;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/* The file name still matters — it is what you type — so it stays, in the
|
|
457
|
+
* monospace it will be typed in, one step quieter than the name above it. */
|
|
458
|
+
/* No chip: a filled background here reads as a badge with a meaning, and this is
|
|
459
|
+
* only the file's name. Monospace and one step quieter is enough to mark it as
|
|
460
|
+
* the thing you type. */
|
|
461
|
+
/* A file name, anywhere it appears: settings.yml, a cmd-*.sh, a path.
|
|
462
|
+
*
|
|
463
|
+
* Set as code, because that is what it is — a string you are about to type, and
|
|
464
|
+
* cmd-tools-autostart.sh has more word boundaries than the body font gives it.
|
|
465
|
+
*
|
|
466
|
+
* A NEUTRAL surface, not the brand fill `code` inherits: `--chip-bg` is the
|
|
467
|
+
* primary blue, and a blue pill here reads as a badge with a meaning — a status,
|
|
468
|
+
* a count — rather than as "this is a file name". Grey with a hairline says the
|
|
469
|
+
* same thing quietly, and follows both themes because both are tokens. */
|
|
470
|
+
.fname {
|
|
471
|
+
padding: .05em .35em;
|
|
472
|
+
border: 1px solid var(--line);
|
|
473
|
+
border-radius: .25rem;
|
|
474
|
+
background: var(--surface-muted);
|
|
475
|
+
color: var(--text-subtle-2);
|
|
476
|
+
font-size: .85em;
|
|
477
|
+
white-space: nowrap;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
.cmd-file {
|
|
481
|
+
display: inline-block;
|
|
482
|
+
margin-top: .2rem;
|
|
483
|
+
font-size: .78rem;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/* Inside a tab button the file name inherits the button's own colour, or it
|
|
487
|
+
* disappears against the primary fill when that tab is the active one. */
|
|
488
|
+
/* Inside a button or a heading the pill fights the control it sits in: a tab is
|
|
489
|
+
* already a bordered box, and an h3 does not want a box around half of itself. */
|
|
490
|
+
.settings-tab .fname,
|
|
491
|
+
h3 .fname,
|
|
492
|
+
button .fname {
|
|
493
|
+
padding: 0;
|
|
494
|
+
border: 0;
|
|
495
|
+
background: none;
|
|
496
|
+
color: inherit;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/* The instruction box, wide and two lines high: what goes in it is a sentence
|
|
500
|
+
* aimed at an agent, and a single line hides the start of it while you type the
|
|
501
|
+
* end. The mic sits inside the box, so the row stays two controls wide. */
|
|
502
|
+
.cmd-ai-row {
|
|
503
|
+
display: flex;
|
|
504
|
+
align-items: flex-start;
|
|
505
|
+
gap: .5rem;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.cmd-ai-input {
|
|
509
|
+
flex: 1 1 auto;
|
|
510
|
+
min-width: 0;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.cmd-ai-input .uk-textarea {
|
|
514
|
+
width: 100%;
|
|
515
|
+
min-height: 3.5rem;
|
|
516
|
+
resize: vertical;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
.cmd-desc {
|
|
520
|
+
display: block;
|
|
521
|
+
margin-top: .15rem;
|
|
522
|
+
color: var(--text-subtle);
|
|
523
|
+
font-size: .84rem;
|
|
524
|
+
line-height: 1.5;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/* A command row reads top to bottom: what it is called, what file it is, what it
|
|
528
|
+
* does — then what you can do to it.
|
|
529
|
+
*
|
|
530
|
+
* Side by side, the six action buttons and a full sentence fought for the same
|
|
531
|
+
* line and both lost: the description wrapped into a narrow column while the
|
|
532
|
+
* buttons stacked two-wide. Nothing here needs to be on one line. */
|
|
533
|
+
.cmd-row-stack {
|
|
534
|
+
display: flex;
|
|
535
|
+
flex-direction: column;
|
|
536
|
+
gap: .5rem;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.cmd-row-stack .project-actions {
|
|
540
|
+
display: flex;
|
|
541
|
+
flex-wrap: wrap;
|
|
542
|
+
gap: .35rem;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/* Settings → Row actions: the buttons, what is inside each menu, and your own actions.
|
|
546
|
+
Its own class names, not .ws-list: ui.js posts a .ws-list drag straight to list-order. */
|
|
547
|
+
.row-actions-section { margin-bottom: 1.5rem; }
|
|
548
|
+
.row-list {
|
|
549
|
+
list-style: none;
|
|
550
|
+
margin: 0 0 0.625rem;
|
|
551
|
+
padding: 0;
|
|
552
|
+
border: 1px solid var(--line);
|
|
553
|
+
border-radius: 0.5rem;
|
|
554
|
+
overflow: hidden;
|
|
555
|
+
}
|
|
556
|
+
.row-item {
|
|
557
|
+
display: flex;
|
|
558
|
+
align-items: center;
|
|
559
|
+
gap: 0.5rem;
|
|
560
|
+
padding: 0.3125rem 0.5rem;
|
|
561
|
+
background: var(--surface-card);
|
|
562
|
+
border-bottom: 1px solid var(--line);
|
|
563
|
+
font-size: .84rem;
|
|
564
|
+
}
|
|
565
|
+
.row-item:last-child { border-bottom: 0; }
|
|
566
|
+
html.dark .row-item { background: transparent; }
|
|
567
|
+
/* Quiet by colour, not by fading a token that was already the quiet one: at 55% the handle was under
|
|
568
|
+
the 3:1 a control needs to be seen at all, on the row you have to find before you can drag it. */
|
|
569
|
+
.row-handle { cursor: grab; color: var(--line-strong); padding: 0 0.125rem; }
|
|
570
|
+
.row-item:hover .row-handle { opacity: 1; color: var(--brand-primary); }
|
|
571
|
+
.row-list > .uk-sortable-drag { background: var(--subtle-brand); }
|
|
572
|
+
.row-list > .uk-sortable-placeholder { opacity: .35; }
|
|
573
|
+
.row-item .row-line { width: auto; margin-left: auto; }
|
|
574
|
+
.row-item .ws-move { margin-left: 0.25rem; }
|
|
575
|
+
.row-group { align-items: flex-start; }
|
|
576
|
+
.row-group-body { flex: 1; min-width: 0; }
|
|
577
|
+
.row-entries { display: flex; flex-wrap: wrap; gap: 0.125rem 0.875rem; margin: 0.25rem 0 0 1.5rem; }
|
|
578
|
+
.row-entry { font-size: .8rem; color: var(--text-subtle); }
|
|
579
|
+
.row-menu { border: 1px solid var(--line); border-radius: 0.5rem; padding: 0.375rem 0.75rem; margin-bottom: 0.5rem; }
|
|
580
|
+
.row-menu > summary { cursor: pointer; }
|
|
581
|
+
.row-menu[open] > summary { margin-bottom: 0.5rem; }
|
|
582
|
+
.row-custom-add { display: grid; grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); gap: 0.5rem; align-items: end; }
|
|
583
|
+
.row-custom-add .row-custom-command { grid-column: 1 / -1; }
|
|
584
|
+
.row-custom-table code { white-space: pre-wrap; word-break: break-all; }
|
|
585
|
+
|
|
586
|
+
/* Rows management: rows of buttons, each button opening onto its groups and commands. */
|
|
587
|
+
.row-actions-tabs { margin-bottom: 1rem; }
|
|
588
|
+
.row-block { border: 1px solid var(--line); border-radius: 0.5rem; padding: 0.5rem 0.625rem; margin-bottom: 0.75rem; }
|
|
589
|
+
.row-block-head { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.375rem; }
|
|
590
|
+
.row-block-tools { margin-left: auto; display: flex; gap: 0.25rem; }
|
|
591
|
+
.row-block-tools .uk-button { border-radius: 0.375rem; padding: 0 0.4375rem; line-height: 1.5rem; }
|
|
592
|
+
.row-block-hidden { border-style: dashed; }
|
|
593
|
+
.row-buttons { min-height: 2.25rem; }
|
|
594
|
+
.row-button { flex-wrap: wrap; align-items: flex-start; }
|
|
595
|
+
.row-button > .row-handle { margin-top: 0.25rem; }
|
|
596
|
+
.row-button-body { flex: 1 1 18rem; min-width: 0; }
|
|
597
|
+
.row-button-body > summary { cursor: pointer; padding: 0.125rem 0; }
|
|
598
|
+
.row-button-body[open] > summary { margin-bottom: 0.375rem; }
|
|
599
|
+
.row-button > .row-move { width: auto; }
|
|
600
|
+
.row-entry-list { list-style: none; margin: 0.25rem 0 0 1.25rem; padding: 0; }
|
|
601
|
+
.row-entry-item { display: flex; flex-wrap: nowrap; align-items: flex-start; gap: 0.25rem 0.5rem; padding: 0.0625rem 0; }
|
|
602
|
+
.row-entry-item > .row-handle { flex: none; }
|
|
603
|
+
.row-entry-item > .row-entry { flex: 1 1 auto; min-width: 0; }
|
|
604
|
+
/* An action of yours carries its edit form below it, so its line may wrap. */
|
|
605
|
+
.row-entry-item:has(> .row-edit) { flex-wrap: wrap; }
|
|
606
|
+
.row-entry-list > .uk-sortable-placeholder { opacity: .35; }
|
|
607
|
+
.row-entry-builtin { font-size: .72rem; flex: none; white-space: nowrap; }
|
|
608
|
+
.row-entry-yours { font-size: .68rem; flex: none; white-space: nowrap; }
|
|
609
|
+
.row-edit { flex-basis: 100%; margin-left: 1.5rem; }
|
|
610
|
+
.row-edit > summary { cursor: pointer; }
|
|
611
|
+
.row-add-action, .row-edit-action { border-top: 1px dashed var(--line); margin-top: 0.5rem; padding-top: 0.5rem; }
|
|
612
|
+
.row-add-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: 0.375rem 0.5rem; align-items: end; margin: 0.25rem 0 0.5rem; }
|
|
613
|
+
.row-add-grid .row-add-steps { grid-column: 1 / -1; }
|
|
614
|
+
.row-add-grid .row-add-check { font-size: .8rem; }
|
|
615
|
+
.row-definition-text { font-family: var(--font-code); font-size: .8rem; }
|
|
616
|
+
.row-definition-buttons { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin: 0.5rem 0; }
|
|
617
|
+
.row-definition-buttons .uk-select { width: auto; }
|
|
618
|
+
.row-definition-help pre, .row-activity-log { max-height: 16rem; overflow: auto; font-size: .75rem; }
|
|
619
|
+
.row-options .row-option { display: block; margin-bottom: 0.625rem; }
|
|
620
|
+
.row-columns { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0.5rem; }
|
|
621
|
+
.row-columns-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
622
|
+
.row-columns-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
623
|
+
.row-columns-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
|
624
|
+
.row-columns > .row-groups { min-height: 2.25rem; }
|
|
625
|
+
.row-columns-pick { display: inline-flex; align-items: center; gap: 0.375rem; margin-bottom: 0.375rem; font-size: .8rem; }
|
|
626
|
+
.row-columns-pick .uk-select { width: auto; min-width: 4rem; }
|
|
627
|
+
@media (max-width: 40em) { .row-columns[class] { grid-template-columns: 1fr; } }
|
|
628
|
+
.row-group-name .uk-text-meta { white-space: nowrap; }
|
|
629
|
+
/* Side by side there is less room: the command list steps in less. */
|
|
630
|
+
.row-columns-2 .row-entry-list, .row-columns-3 .row-entry-list, .row-columns-4 .row-entry-list { margin-left: 0.5rem; }
|
|
631
|
+
/* The Rows form's save bar stays in view, and says when there is something to save. */
|
|
632
|
+
.row-save-bar { position: sticky; bottom: 0; z-index: 2; display: flex; align-items: center; justify-content: flex-end; gap: 0.75rem; padding: 0.5rem 0; background: var(--surface-card); border-top: 1px solid var(--line); }
|
|
633
|
+
.row-unsaved-note { display: none; font-size: .8rem; font-weight: 600; color: var(--link); }
|
|
634
|
+
#row-arrange-form[data-dirty="1"] .row-unsaved-note { display: inline; }
|
|
635
|
+
/* A command's own move arrows: small, beside its handle, so it can be reordered without dragging. */
|
|
636
|
+
.row-entry-item > .ws-move { flex: none; margin-left: 0; order: -1; }
|
|
637
|
+
.row-entry-item > .ws-move .uk-button { padding: 0 0.25rem; line-height: 1.125rem; min-height: 0; }
|
|
638
|
+
/* Rows tab at phone width: a command's line wraps so its name keeps a readable width (it was left about 20px,
|
|
639
|
+
one word per line), and a group's line wraps so its move arrows stay inside the list instead of being cut off. */
|
|
640
|
+
@media (max-width: 40em) {
|
|
641
|
+
.row-entry-list { margin-left: 0; }
|
|
642
|
+
.row-entry-item { flex-wrap: wrap; }
|
|
643
|
+
.row-entry-item > .row-entry { flex: 1 1 9rem; }
|
|
644
|
+
.row-group { flex-wrap: wrap; }
|
|
645
|
+
.row-group > .ws-move { margin-left: auto; }
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/* The navigation topbar: entries someone moved up out of the sidebar, in the bar's three regions.
|
|
649
|
+
Quiet by default — the bar is a place, not a toolbar of its own — and the label is hidden under
|
|
650
|
+
640px, where a wordmark plus a divider plus the theme toggle already fill the width. */
|
|
651
|
+
.toolbar-nav { display: flex; align-items: center; gap: 0.25rem; }
|
|
652
|
+
.toolbar-nav-start { margin-left: 0.5rem; padding-left: 0.5rem; border-left: 1px solid var(--line); }
|
|
653
|
+
.toolbar-nav .action-btn {
|
|
654
|
+
display: inline-flex;
|
|
655
|
+
align-items: center;
|
|
656
|
+
gap: 0.35rem;
|
|
657
|
+
height: 32px;
|
|
658
|
+
padding: 0 0.6rem;
|
|
659
|
+
border: 1px solid transparent;
|
|
660
|
+
border-radius: 999px;
|
|
661
|
+
background: transparent;
|
|
662
|
+
color: var(--text-subtle);
|
|
663
|
+
font-size: 0.8125rem;
|
|
664
|
+
line-height: 1;
|
|
665
|
+
white-space: nowrap;
|
|
666
|
+
}
|
|
667
|
+
.toolbar-nav .action-btn:hover,
|
|
668
|
+
.toolbar-nav .action-btn:focus-visible {
|
|
669
|
+
background: var(--subtle-brand);
|
|
670
|
+
border-color: var(--line);
|
|
671
|
+
color: var(--link);
|
|
672
|
+
text-decoration: none;
|
|
673
|
+
}
|
|
674
|
+
@media (max-width: 40em) {
|
|
675
|
+
.toolbar-nav .action-label { display: none; }
|
|
676
|
+
.toolbar-nav .action-btn { padding: 0 0.45rem; }
|
|
677
|
+
.toolbar-nav-start { margin-left: 0.35rem; padding-left: 0.35rem; }
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/* The tiles have their own name: `settings-card` is already the class of the settings FORM wrapper,
|
|
681
|
+
and a grid rule on that squeezed its description into a 71px ribbon down the right. */
|
|
682
|
+
/* Settings, grouped and as a grid. There are 26 of these files on a full tree, and as pills they
|
|
683
|
+
wrapped onto three lines of identical buttons — the hub's own settings, an editor that is not a file
|
|
684
|
+
at all, and twenty-four workspaces, all weighted the same. */
|
|
685
|
+
.settings-group { margin-bottom: 1.5rem; }
|
|
686
|
+
.settings-group-head {
|
|
687
|
+
font-size: 0.75rem;
|
|
688
|
+
text-transform: uppercase;
|
|
689
|
+
letter-spacing: 1px;
|
|
690
|
+
font-weight: 600;
|
|
691
|
+
color: var(--text-subtle);
|
|
692
|
+
margin: 0 0 0.5rem;
|
|
693
|
+
}
|
|
694
|
+
.settings-grid {
|
|
695
|
+
display: grid;
|
|
696
|
+
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
|
|
697
|
+
gap: 0.6rem;
|
|
698
|
+
}
|
|
699
|
+
.settings-tile {
|
|
700
|
+
display: grid;
|
|
701
|
+
grid-template-columns: auto 1fr;
|
|
702
|
+
grid-template-areas: "icon name" "icon meta";
|
|
703
|
+
align-items: center;
|
|
704
|
+
gap: 0 0.6rem;
|
|
705
|
+
padding: 0.65rem 0.75rem;
|
|
706
|
+
border: 1px solid var(--line);
|
|
707
|
+
border-radius: 12px;
|
|
708
|
+
background: var(--surface-card);
|
|
709
|
+
color: var(--text-default);
|
|
710
|
+
text-decoration: none;
|
|
711
|
+
min-width: 0;
|
|
712
|
+
}
|
|
713
|
+
.settings-tile:hover,
|
|
714
|
+
.settings-tile:focus-visible {
|
|
715
|
+
border-color: var(--brand-primary);
|
|
716
|
+
background: var(--subtle-brand);
|
|
717
|
+
color: var(--text-default);
|
|
718
|
+
text-decoration: none;
|
|
719
|
+
}
|
|
720
|
+
.settings-tile.is-current { border-color: var(--brand-primary); background: var(--subtle-brand); }
|
|
721
|
+
.settings-tile-icon { grid-area: icon; color: var(--brand-primary); display: flex; }
|
|
722
|
+
.settings-tile-name { grid-area: name; font-weight: 600; font-size: 0.875rem; }
|
|
723
|
+
.settings-tile-meta {
|
|
724
|
+
grid-area: meta;
|
|
725
|
+
font-size: 0.6875rem;
|
|
726
|
+
line-height: 1.3;
|
|
727
|
+
color: var(--text-subtle);
|
|
728
|
+
overflow: hidden;
|
|
729
|
+
text-overflow: ellipsis;
|
|
730
|
+
white-space: nowrap;
|
|
731
|
+
}
|
|
732
|
+
.settings-back { display: flex; align-items: center; gap: 0.6rem; margin: 0 0 1rem; }
|
|
733
|
+
.settings-back strong { font-size: 1rem; }
|
|
734
|
+
|
|
735
|
+
/* The screens status: quiet while nothing runs, brand while something does — the same state change a
|
|
736
|
+
project row's SCREENS button makes when that project has sessions. The count arrives on a poll, so the
|
|
737
|
+
button follows the badge rather than the server having to re-render it. */
|
|
738
|
+
.actions-screens { gap: 0.35rem; }
|
|
739
|
+
.actions-screens .screens-count:empty { display: none; }
|
|
740
|
+
.actions-screens .uk-badge {
|
|
741
|
+
min-width: 1.05rem;
|
|
742
|
+
height: 1.05rem;
|
|
743
|
+
line-height: 1.05rem;
|
|
744
|
+
font-size: 0.625rem;
|
|
745
|
+
font-weight: 700;
|
|
746
|
+
background: var(--brand-primary);
|
|
747
|
+
color: var(--text-inverse);
|
|
748
|
+
vertical-align: middle;
|
|
749
|
+
}
|
|
750
|
+
.toolbar-nav .actions-screens:has(.uk-badge) {
|
|
751
|
+
background: var(--subtle-brand);
|
|
752
|
+
border-color: var(--brand-primary);
|
|
753
|
+
color: var(--link);
|
|
754
|
+
}
|
|
755
|
+
.toolbar-nav .actions-screens:has(.uk-badge):hover { background: var(--subtle-brand); }
|
|
756
|
+
/* In the rail it is a tile like its neighbours, so the state reads as a border and a tint rather than
|
|
757
|
+
as a different shape. */
|
|
758
|
+
.actions-rail-inner .actions-screens:has(.uk-badge) {
|
|
759
|
+
border-color: var(--brand-primary);
|
|
760
|
+
background: var(--subtle-brand);
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
/* "There is a newer one." It sits beside the version rather than replacing it: what you run and what
|
|
764
|
+
exists are two facts, and the second is only worth room when the answer is yes. */
|
|
765
|
+
.version-hint:empty { display: none; }
|
|
766
|
+
.version-new {
|
|
767
|
+
display: inline-flex;
|
|
768
|
+
align-items: center;
|
|
769
|
+
gap: 0.15rem;
|
|
770
|
+
margin-left: 0.3rem;
|
|
771
|
+
padding: 0.1rem 0.4rem;
|
|
772
|
+
border-radius: 999px;
|
|
773
|
+
background: var(--ok-soft);
|
|
774
|
+
color: var(--ok-ink);
|
|
775
|
+
border: 1px solid var(--ok);
|
|
776
|
+
font-size: 0.6875rem;
|
|
777
|
+
font-weight: 600;
|
|
778
|
+
line-height: 1.4;
|
|
779
|
+
white-space: nowrap;
|
|
780
|
+
text-decoration: none;
|
|
781
|
+
}
|
|
782
|
+
.version-new:hover, .version-new:focus-visible { text-decoration: none; filter: brightness(1.05); }
|
|
783
|
+
|
|
784
|
+
/* Fields or raw YAML: the two ways to edit one settings file. */
|
|
785
|
+
.settings-modes { margin: 0 0 0.75rem; }
|
|
786
|
+
.settings-raw-text { min-height: 30rem; font-family: var(--font-code); font-size: 0.8125rem; }
|
|
787
|
+
|
|
788
|
+
/* ---------- the Styles page ---------- */
|
|
789
|
+
|
|
790
|
+
/* Almost nothing lives here on purpose. The cards are uk-card, the grid is uk-grid with
|
|
791
|
+
uk-child-width and uk-grid-match, the badge is uk-label, the form is uk-form-stacked — so what is
|
|
792
|
+
left is the two things UIkit has no component for: a colour swatch, and a gap between wrapped
|
|
793
|
+
buttons, which UIkit 3 offers no flex-gap utility for. */
|
|
794
|
+
|
|
795
|
+
.style-swatches { gap: .3rem; }
|
|
796
|
+
.style-swatch {
|
|
797
|
+
width: 1.6rem; height: 1.6rem; border-radius: .3rem;
|
|
798
|
+
/* Neutral rather than a token: this sits on the colour it is showing, in whichever style. */
|
|
799
|
+
border: 1px solid rgba(128, 128, 128, .35);
|
|
800
|
+
}
|
|
801
|
+
.style-card-actions { gap: .4rem; }
|
|
802
|
+
|
|
803
|
+
/* The style in use. An outline rather than a border, so the card does not change size when it
|
|
804
|
+
becomes the active one and the grid does not shift under it. */
|
|
805
|
+
.style-card.is-active { outline: 2px solid var(--brand-primary); outline-offset: 2px; }
|
|
806
|
+
|
|
807
|
+
/* The description of a key is the comment written above it in the file. */
|
|
808
|
+
.settings-desc { display: block; margin-top: 0.125rem; font-size: 0.75rem; font-weight: 400; line-height: 1.4; color: var(--text-subtle); }
|
|
809
|
+
/* Find a setting in the file. */
|
|
810
|
+
.settings-find.uk-input { max-width: 26rem; margin: 0.25rem 0 1rem; border-radius: 0.5rem; }
|
|
811
|
+
.settings-row[hidden], .settings-group[hidden] { display: none; }
|
|
812
|
+
/* On or off is a switch, and it says which. */
|
|
813
|
+
.settings-switch {
|
|
814
|
+
appearance: none; flex: none; position: relative; width: 2.25rem; height: 1.25rem; margin: 0; cursor: pointer;
|
|
815
|
+
border-radius: 999px; background: var(--line-strong); transition: background-color 0.15s ease;
|
|
816
|
+
}
|
|
817
|
+
.settings-switch::after {
|
|
818
|
+
content: ""; position: absolute; top: 0.125rem; left: 0.125rem; width: 1rem; height: 1rem; border-radius: 50%;
|
|
819
|
+
background: var(--surface-card); box-shadow: 0 1px 2px rgb(0 0 0 / 20%); transition: transform 0.15s ease;
|
|
820
|
+
}
|
|
821
|
+
.settings-switch:checked { background: var(--brand-primary); }
|
|
822
|
+
.settings-switch:checked::after { transform: translateX(1rem); }
|
|
823
|
+
.settings-switch:focus-visible { outline: 2px solid var(--brand-primary); outline-offset: 2px; }
|
|
824
|
+
.settings-toggle { display: inline-flex; align-items: center; gap: 0.5rem; }
|
|
825
|
+
@media (prefers-reduced-motion: reduce) { .settings-switch, .settings-switch::after { transition: none; } }
|
|
826
|
+
/* Saving is still one button; it says when there is something to save. */
|
|
827
|
+
.settings-save { display: flex; align-items: center; gap: 0.75rem; }
|
|
828
|
+
.settings-dirty { color: var(--warning-ink); font-weight: 600; }
|