@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.
Files changed (307) hide show
  1. package/PLUGINS.md +249 -0
  2. package/README.md +379 -2
  3. package/WORKSPACES.md +69 -0
  4. package/actions/ai-items.js +293 -0
  5. package/actions/audio.js +48 -0
  6. package/actions/build-order.js +79 -0
  7. package/actions/checks.js +95 -0
  8. package/actions/claude-session.js +104 -0
  9. package/actions/commands-center.js +258 -0
  10. package/actions/composer.js +267 -0
  11. package/actions/ddev-addons.js +90 -0
  12. package/actions/ddev-mail.js +80 -0
  13. package/actions/ddev.js +237 -0
  14. package/actions/folders.js +165 -0
  15. package/actions/images-svg.js +33 -0
  16. package/actions/images.js +145 -0
  17. package/actions/navigation.js +190 -0
  18. package/actions/node.js +222 -0
  19. package/actions/notes.js +55 -0
  20. package/actions/plugins.js +36 -0
  21. package/actions/project-make.js +28 -0
  22. package/actions/rag.js +202 -0
  23. package/actions/row-actions.js +262 -0
  24. package/actions/screens.js +270 -0
  25. package/actions/testing.js +121 -0
  26. package/actions/video-edit.js +54 -0
  27. package/ai-inventory.js +182 -0
  28. package/ai-items.js +202 -0
  29. package/assistant-cast.js +176 -0
  30. package/assistant-suggestions.js +91 -0
  31. package/assistant.js +484 -0
  32. package/audio-voice.js +528 -0
  33. package/auth-google.js +260 -0
  34. package/build-ai.js +52 -0
  35. package/build-order-page.js +191 -0
  36. package/build-order.js +313 -0
  37. package/builder-args.js +117 -0
  38. package/changelog.js +302 -0
  39. package/chat-threads.js +134 -0
  40. package/checks.js +105 -0
  41. package/claude-args.js +282 -0
  42. package/claude-sessions.js +129 -0
  43. package/command-author.js +117 -0
  44. package/command-block.js +20 -0
  45. package/commands/defaults.yml +159 -0
  46. package/commands-page.js +460 -0
  47. package/commands.js +568 -0
  48. package/cucumber.js +43 -0
  49. package/ddev-addons-page.js +124 -0
  50. package/ddev-addons.js +154 -0
  51. package/ddev-custom-commands.js +96 -0
  52. package/ddev-domains.js +84 -0
  53. package/ddev-import.js +93 -0
  54. package/ddev-mail-page.js +167 -0
  55. package/ddev-mail.js +110 -0
  56. package/ddev-options.js +145 -0
  57. package/ddev-snapshots.js +126 -0
  58. package/ddev.js +145 -0
  59. package/docs/DEVELOPER-GUIDE.md +224 -0
  60. package/docs/README.md +252 -0
  61. package/docs/REFERENCE.md +684 -0
  62. package/docs/USER-GUIDE.md +697 -0
  63. package/docs/screenshots/assistant/avatar-board.png +0 -0
  64. package/docs/screenshots/assistant/avatar-coffee.png +0 -0
  65. package/docs/screenshots/assistant/avatar-colours.png +0 -0
  66. package/docs/screenshots/assistant/avatar-icons.png +0 -0
  67. package/docs/screenshots/assistant/avatar-moves.png +0 -0
  68. package/docs/screenshots/assistant/avatar-pick-cookieman.png +0 -0
  69. package/docs/screenshots/assistant/avatar-settings-voices.png +0 -0
  70. package/docs/screenshots/assistant/avatar-status.png +0 -0
  71. package/docs/screenshots/create-card/create-card.png +0 -0
  72. package/docs/screenshots/create-card/start-ai.png +0 -0
  73. package/docs/screenshots/guide-clone-address.png +0 -0
  74. package/docs/screenshots/guide-clone-worktree-off.png +0 -0
  75. package/docs/screenshots/guide-clone-worktree-on.png +0 -0
  76. package/docs/screenshots/guide-ddev-menu.png +0 -0
  77. package/docs/screenshots/guide-domains.png +0 -0
  78. package/docs/screenshots/guide-home.png +0 -0
  79. package/docs/screenshots/guide-ide-menu.png +0 -0
  80. package/docs/screenshots/guide-remove-refusal.png +0 -0
  81. package/docs/screenshots/guide-rows-worktree.png +0 -0
  82. package/docs/screenshots/guide-screens.png +0 -0
  83. package/docs/screenshots/guide-settings.png +0 -0
  84. package/docs/screenshots/guide-workspace-page.png +0 -0
  85. package/docs/screenshots/home/card-settings.png +0 -0
  86. package/docs/screenshots/home/drag-reorder.png +0 -0
  87. package/docs/screenshots/home/edit-card.png +0 -0
  88. package/docs/screenshots/images/claude-code-image.png +0 -0
  89. package/docs/screenshots/images/edit-with-ai.png +0 -0
  90. package/docs/screenshots/images/gallery.png +0 -0
  91. package/docs/screenshots/images/generate-description.png +0 -0
  92. package/docs/screenshots/images/generate-plan.png +0 -0
  93. package/docs/screenshots/images/providers.png +0 -0
  94. package/docs/screenshots/images/svg-form.png +0 -0
  95. package/docs/screenshots/images/svg-result.png +0 -0
  96. package/docs/screenshots/images/upload.png +0 -0
  97. package/docs/screenshots/new-folder/2-form.png +0 -0
  98. package/docs/screenshots/new-folder/8-ddev-options.png +0 -0
  99. package/docs/screenshots/new-folder/files-folder.png +0 -0
  100. package/docs/screenshots/projects/ddev-custom-commands.png +0 -0
  101. package/docs/screenshots/projects/state-chip-stop.png +0 -0
  102. package/docs/screenshots/readme/dashboard-dark.png +0 -0
  103. package/docs/screenshots/readme/dashboard-light.png +0 -0
  104. package/docs/screenshots/readme/dev-dark.png +0 -0
  105. package/docs/screenshots/readme/dev-light.png +0 -0
  106. package/docs/screenshots/readme/docs-dark.png +0 -0
  107. package/docs/screenshots/readme/docs-light.png +0 -0
  108. package/docs/screenshots/readme/icons/ai.svg +4 -0
  109. package/docs/screenshots/readme/icons/code.svg +4 -0
  110. package/docs/screenshots/readme/icons/docs.svg +4 -0
  111. package/docs/screenshots/readme/icons/services.svg +4 -0
  112. package/docs/screenshots/readme/icons/sites.svg +4 -0
  113. package/docs/screenshots/readme/test-report-dark.png +0 -0
  114. package/docs/screenshots/readme/test-report-light.png +0 -0
  115. package/docs/screenshots/readme/test-scenarios.png +0 -0
  116. package/docs/screenshots/readme/test-steps.png +0 -0
  117. package/docs/screenshots/readme/videos-dark.png +0 -0
  118. package/docs/screenshots/readme/videos-light.png +0 -0
  119. package/docs/screenshots/screens-menu.png +0 -0
  120. package/docs/screenshots/screens-new.png +0 -0
  121. package/docs/screenshots/settings/auth-google-lists.png +0 -0
  122. package/docs/screenshots/settings/delete-1-row.png +0 -0
  123. package/docs/screenshots/settings/delete-2-confirm.png +0 -0
  124. package/docs/screenshots/settings/delete-3-type-name.png +0 -0
  125. package/docs/screenshots/settings/delete-4-type-yes.png +0 -0
  126. package/event-log.js +59 -0
  127. package/files-browser.js +247 -0
  128. package/folders.js +121 -0
  129. package/format.js +73 -0
  130. package/git-info.js +81 -0
  131. package/github-auth.js +62 -0
  132. package/html.js +10 -0
  133. package/icons.js +83 -0
  134. package/images-ai.js +447 -0
  135. package/images-create.js +226 -0
  136. package/images-page.js +417 -0
  137. package/images-records.js +39 -0
  138. package/images-render.js +36 -0
  139. package/images-svg-core.js +214 -0
  140. package/images-svg-sanitize.js +188 -0
  141. package/images-svg.js +241 -0
  142. package/images.js +270 -0
  143. package/jobs.js +430 -0
  144. package/linger.js +21 -0
  145. package/lists.js +292 -0
  146. package/media-info.js +136 -0
  147. package/navigation-page.js +264 -0
  148. package/navigation.js +394 -0
  149. package/notes.js +0 -0
  150. package/package.json +47 -4
  151. package/palette-index.js +46 -0
  152. package/playwright.config.js +23 -0
  153. package/plugin-install.js +239 -0
  154. package/plugin-loader.js +466 -0
  155. package/plugin-manifest.js +83 -0
  156. package/plugin-settings.js +44 -0
  157. package/plugins/workspace-notes/index.js +59 -0
  158. package/plugins-page.js +103 -0
  159. package/project-make.js +241 -0
  160. package/project-name.js +210 -0
  161. package/public/assistant-avatar-moves.js +646 -0
  162. package/public/assistant-avatar-ui.js +1223 -0
  163. package/public/assistant-avatar.js +530 -0
  164. package/public/avatar/druplicon.vrm +0 -0
  165. package/public/css/base.css +260 -0
  166. package/public/css/components/ai-assistant.css +263 -0
  167. package/public/css/components/assistant-avatar.css +279 -0
  168. package/public/css/components/assistant-views.css +198 -0
  169. package/public/css/components/build-order.css +74 -0
  170. package/public/css/components/clone-as-a-git-worktree.css +30 -0
  171. package/public/css/components/command-palette.css +61 -0
  172. package/public/css/components/commands-center.css +139 -0
  173. package/public/css/components/confirm-dialog.css +40 -0
  174. package/public/css/components/create-card.css +8 -0
  175. package/public/css/components/ddev-menu.css +23 -0
  176. package/public/css/components/deep-chat.css +17 -0
  177. package/public/css/components/density.css +11 -0
  178. package/public/css/components/floating-assistant-workspace-pages.css +55 -0
  179. package/public/css/components/folders.css +5 -0
  180. package/public/css/components/full-height-left-assistant-sidebar-all-pages.css +39 -0
  181. package/public/css/components/full-height-right-actions-rail-pages-that-have-actions.css +267 -0
  182. package/public/css/components/grid-and-list.css +203 -0
  183. package/public/css/components/help-page.css +36 -0
  184. package/public/css/components/hero.css +16 -0
  185. package/public/css/components/images.css +70 -0
  186. package/public/css/components/layout-rhythm-and-spacing-polish.css +139 -0
  187. package/public/css/components/mic-on-any-field-that-wants-typing.css +416 -0
  188. package/public/css/components/modal-fit.css +113 -0
  189. package/public/css/components/page-width.css +23 -0
  190. package/public/css/components/plugins-page.css +9 -0
  191. package/public/css/components/project-cards.css +256 -0
  192. package/public/css/components/project-rows.css +390 -0
  193. package/public/css/components/reordering-the-workspace-cards.css +85 -0
  194. package/public/css/components/responsive-home-and-the-workspace-pages.css +457 -0
  195. package/public/css/components/running-commands-as-toasts.css +327 -0
  196. package/public/css/components/settings-editor-core-config-yml.css +828 -0
  197. package/public/css/components/short-results-as-a-toast-at-the-top.css +203 -0
  198. package/public/css/components/sound-player.css +84 -0
  199. package/public/css/components/suggest-agents-skills-commands.css +112 -0
  200. package/public/css/components/tab-modal.css +142 -0
  201. package/public/css/components/terminals.css +244 -0
  202. package/public/css/components/test-report-media-one-file-per-row-paged.css +144 -0
  203. package/public/css/components/top-toolbar-logo-breadcrumb.css +107 -0
  204. package/public/css/components/video-edit.css +6 -0
  205. package/public/css/components/web-ide-open-with.css +23 -0
  206. package/public/css/components/working-indicators.css +158 -0
  207. package/public/css/components/workspace-cards.css +79 -0
  208. package/public/favicon.ico +0 -0
  209. package/public/favicon.png +0 -0
  210. package/public/htmx.min.js +1 -0
  211. package/public/logo.png +0 -0
  212. package/public/media-player.js +215 -0
  213. package/public/mic.js +255 -0
  214. package/public/narration.js +110 -0
  215. package/public/palette.js +278 -0
  216. package/public/sortable.js +251 -0
  217. package/public/suggest.js +337 -0
  218. package/public/terminal.js +903 -0
  219. package/public/themes/default/theme.css +267 -0
  220. package/public/themes/ember/theme.css +180 -0
  221. package/public/themes/press/theme.css +290 -0
  222. package/public/themes/slate/theme.css +182 -0
  223. package/public/touch-icon.png +0 -0
  224. package/public/ui.js +2721 -0
  225. package/public/vendor/ace/LICENSE.txt +24 -0
  226. package/public/vendor/ace/ace.js +23 -0
  227. package/public/vendor/ace/ext-language_tools.js +8 -0
  228. package/public/vendor/ace/ext-searchbox.js +8 -0
  229. package/public/vendor/ace/mode-css.js +8 -0
  230. package/public/vendor/ace/mode-html.js +8 -0
  231. package/public/vendor/ace/mode-javascript.js +8 -0
  232. package/public/vendor/ace/mode-markdown.js +8 -0
  233. package/public/vendor/ace/mode-sh.js +8 -0
  234. package/public/vendor/ace/mode-yaml.js +8 -0
  235. package/public/vendor/ace/theme-textmate.js +8 -0
  236. package/public/vendor/ace/theme-tomorrow_night.js +8 -0
  237. package/public/vendor/ace/worker-yaml.js +1 -0
  238. package/public/vendor/deep-chat.LICENSE +21 -0
  239. package/public/vendor/deep-chat.bundle.js +1 -0
  240. package/public/vendor/fonts/dm-serif-text-LICENSE.txt +93 -0
  241. package/public/vendor/fonts/dm-serif-text-latin-400-italic.woff2 +0 -0
  242. package/public/vendor/fonts/dm-serif-text-latin-400-normal.woff2 +0 -0
  243. package/public/vendor/fonts/figtree-LICENSE.txt +93 -0
  244. package/public/vendor/fonts/figtree-latin-400-italic.woff2 +0 -0
  245. package/public/vendor/fonts/figtree-latin-400-normal.woff2 +0 -0
  246. package/public/vendor/fonts/figtree-latin-600-italic.woff2 +0 -0
  247. package/public/vendor/fonts/figtree-latin-600-normal.woff2 +0 -0
  248. package/public/vendor/fonts/jetbrains-mono-LICENSE.txt +93 -0
  249. package/public/vendor/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
  250. package/public/vendor/fonts/ubuntu-mono-LICENSE.txt +98 -0
  251. package/public/vendor/fonts/ubuntu-mono-latin-wght-normal.woff2 +0 -0
  252. package/public/vendor/tabler-LICENSE.txt +21 -0
  253. package/public/vendor/tabler-sprite.svg +1 -0
  254. package/public/vendor/three/LICENSE +21 -0
  255. package/public/vendor/three/addons/loaders/GLTFLoader.js +4860 -0
  256. package/public/vendor/three/addons/utils/BufferGeometryUtils.js +1501 -0
  257. package/public/vendor/three/addons/utils/SkeletonUtils.js +496 -0
  258. package/public/vendor/three/three.core.min.js +6 -0
  259. package/public/vendor/three/three.module.min.js +6 -0
  260. package/public/vendor/three-vrm/LICENSE +22 -0
  261. package/public/vendor/three-vrm/three-vrm.module.min.js +983 -0
  262. package/public/vendor/uikit-icons.min.js +1 -0
  263. package/public/vendor/uikit.min.css +1 -0
  264. package/public/vendor/uikit.min.js +1 -0
  265. package/public/vendor/webship-icons/ui/bookmark-outlined.svg +1 -0
  266. package/public/vendor/webship-icons/ui/headset.svg +1 -0
  267. package/public/vendor/webship-icons/ui/menu.svg +1 -0
  268. package/public/vendor/webship-icons/ui/pause.svg +1 -0
  269. package/public/vendor/webship-icons/ui/play.svg +1 -0
  270. package/public/vendor/webship-icons/ui/share.svg +1 -0
  271. package/public/vendor/webship-icons/ui/sound-off.svg +1 -0
  272. package/public/vendor/webship-icons/ui/sound-on.svg +1 -0
  273. package/public/vendor/webship-icons/ui/stop.svg +1 -0
  274. package/public/vendor/xterm/addon-fit.js +2 -0
  275. package/public/vendor/xterm/addon-unicode11.js +2 -0
  276. package/public/vendor/xterm/addon-web-links.js +2 -0
  277. package/public/vendor/xterm/xterm.css +218 -0
  278. package/public/vendor/xterm/xterm.js +2 -0
  279. package/rag.js +169 -0
  280. package/reader.js +132 -0
  281. package/repo-blobs.js +66 -0
  282. package/report-pdf.js +337 -0
  283. package/row-layout.js +1439 -0
  284. package/screenrc +37 -0
  285. package/screens.js +1063 -0
  286. package/scripts/code-server-start.sh +190 -0
  287. package/scripts/images-claude-finish.js +107 -0
  288. package/scripts/screen-host.sh +114 -0
  289. package/scripts/screen-runner.js +362 -0
  290. package/scripts/screen-then.js +47 -0
  291. package/scripts/update.sh +350 -0
  292. package/server.js +7923 -0
  293. package/settings-file.js +423 -0
  294. package/speech.js +297 -0
  295. package/tab-modal.js +75 -0
  296. package/test-reports.js +260 -0
  297. package/themes.js +381 -0
  298. package/transcripts.js +168 -0
  299. package/urls.js +13 -0
  300. package/validate.js +18 -0
  301. package/version-check.js +94 -0
  302. package/video-edit.js +588 -0
  303. package/waiting.js +85 -0
  304. package/workspace-card-tools.js +41 -0
  305. package/workspace-delete.js +139 -0
  306. package/workspace-types.js +85 -0
  307. package/workspaces.js +553 -0
@@ -0,0 +1,416 @@
1
+ /* ---------- Mic on any field that wants typing ---------- */
2
+
3
+ /* Injected by ui.js around every text input and textarea, so a field added later
4
+ gets one without being touched. */
5
+ .field-mic-wrap { position: relative; display: block; }
6
+
7
+ .field-mic {
8
+ position: absolute;
9
+ top:0.375rem;
10
+ right:0.375rem;
11
+ width:1.625rem;
12
+ height:1.625rem;
13
+ border: 1px solid var(--line);
14
+ border-radius:31.25rem;
15
+ background: var(--surface);
16
+ color: var(--text-subtle);
17
+ display: inline-flex;
18
+ align-items: center;
19
+ justify-content: center;
20
+ cursor: pointer;
21
+ padding: 0;
22
+ transition: background .15s, border-color .15s, color .15s;
23
+ }
24
+
25
+ .field-mic:hover { border-color: var(--brand-primary); color: var(--brand-primary); }
26
+ .field-mic.listening { border-color: var(--brand-primary); color: var(--brand-primary); animation: mic-pulse 1.2s infinite; }
27
+
28
+ /* Keep the text clear of the button. */
29
+ .field-mic-wrap > .uk-input,
30
+ .field-mic-wrap > .uk-textarea { padding-right:2.375rem; }
31
+
32
+ /* A textarea's mic sits at the top-right; an input's is vertically centred. */
33
+ .field-mic-wrap > .uk-input ~ .field-mic { top: 50%; transform: translateY(-50%); }
34
+
35
+ /* Toolbar spans full width; its content aligns with the shell */
36
+ .toolbar-inner { padding:0 1.5rem; }
37
+
38
+ /* Stack on tablets/phones: sidebar becomes a normal block above content */
39
+ @media (max-width: 59.9375em) {
40
+ .assistant-side {
41
+ position: static;
42
+ width: auto;
43
+ padding:0.875rem 0.875rem 0;
44
+ }
45
+ .assistant-side .chat-log { max-height:20rem; }
46
+ .app-content { margin-left: 0; }
47
+ }
48
+
49
+ /* Markdown tables etc. inside chat replies */
50
+ .chat-log .msg table { border-collapse: collapse; margin:0.375rem 0; font-size:0.8125rem; }
51
+ .chat-log .msg th, .chat-log .msg td { border: 1px solid var(--line); padding:0.25rem 0.5rem; }
52
+ .chat-log .msg code { background: var(--surface-muted); padding:0.0625rem 0.25rem; border-radius:0.25rem; font-size:0.75rem; }
53
+
54
+ /* Builder Arguments group */
55
+ .builder-args { margin-bottom: 0; }
56
+ .builder-args .uk-accordion-title { font-size:0.9375rem; }
57
+ .builder-args .arg-row {
58
+ display: flex;
59
+ align-items: center;
60
+ gap:0.625rem;
61
+ padding:0.375rem 0;
62
+ cursor: pointer;
63
+ }
64
+ .builder-args .arg-row code { min-width:11.875rem; }
65
+ .builder-args .arg-value { max-width:21.25rem; }
66
+
67
+ /* Hierarchical project-domain alias on running rows */
68
+ /* Launch sits with the hostname it opens, not in the actions row: the row is what you DO to a
69
+ project, and opening its site is where you GO. Reading "Launch webship-sandbox-1.ddev.site" as
70
+ one phrase also removes the guess about which of several URLs the button lands on. */
71
+ .proj-launch-line {
72
+ display: flex;
73
+ align-items: center;
74
+ gap: 0.5rem;
75
+ margin-top: 0.25rem;
76
+ }
77
+
78
+ .proj-alias { display: block; font-size:0.6875rem; margin-top:0.125rem; color: var(--link) !important; }
79
+ .proj-launch-line .proj-alias { margin-top: 0; }
80
+ .proj-alias:hover { text-decoration: underline; }
81
+
82
+ /* Build form: the cmd-*.sh picker reads as one composer-style control —
83
+ same bordered card, same focus ring, same brand accent as the prompt box. */
84
+ .build-form {
85
+ padding:0.625rem 0.75rem;
86
+ background: var(--surface-card);
87
+ border: 1px solid var(--line);
88
+ border-radius:0.875rem;
89
+ box-shadow: 0 1px 2px rgba(43, 68, 124, .06);
90
+ }
91
+ .build-form:focus-within {
92
+ border-color: var(--brand-primary);
93
+ box-shadow: 0 0 0 3px var(--subtle-brand);
94
+ }
95
+ .build-form .uk-select,
96
+ .build-form .uk-input {
97
+ border: 1px solid var(--line);
98
+ border-radius:0.625rem;
99
+ background-color: var(--surface-input);
100
+ height:2.625rem;
101
+ }
102
+ .build-form .uk-select:focus,
103
+ .build-form .uk-input:focus {
104
+ border-color: var(--brand-primary);
105
+ box-shadow: 0 0 0 3px var(--subtle-brand);
106
+ }
107
+ .build-form .uk-select {
108
+ font-weight: 500;
109
+ color: var(--ink);
110
+ }
111
+ .build-form .uk-button-primary { border-radius:31.25rem; padding:0 1.25rem; height:2.625rem; line-height:2.625rem; }
112
+
113
+ /* Logos and icons in both themes.
114
+ The emblem is Webship Primary blue and reads on light and dark alike, so it
115
+ never changes. The full lockup has two exports because its wordmark is ink
116
+ on light and white on dark — swap the file, never recolour the artwork. */
117
+ .brand-emblem { display: block; }
118
+ .brand-logo-on-dark { display: none; }
119
+ html.dark .brand-logo-on-light { display: none; }
120
+ html.dark .brand-logo-on-dark { display: block; }
121
+
122
+ /* UIKit icons inherit currentColor, so they follow the theme already — but the
123
+ toolbar mark and the assistant sparkle sit on tinted surfaces, so pin their
124
+ colour rather than letting a parent override it. */
125
+ .toolbar .uk-icon, .assistant-panel .uk-icon { color: currentColor; }
126
+ html.dark .ai-mark { color: var(--text-inverse); }
127
+
128
+ /* Buttons: the Webship default. Primary is brand blue with a soft brand shadow;
129
+ secondary is the deep brand navy; default is a quiet outline that turns
130
+ brand on hover. Pill radius throughout, matching the composer controls. */
131
+ .uk-button {
132
+ border-radius:31.25rem;
133
+ font-weight: 500;
134
+ text-transform: none;
135
+ transition: background-color .15s ease, border-color .15s ease, box-shadow .15s ease, color .15s ease;
136
+ }
137
+ .uk-button-primary {
138
+ background-color: var(--brand-primary);
139
+ border: 1px solid var(--brand-primary);
140
+ color: var(--text-inverse);
141
+ box-shadow: 0 1px 2px rgba(0, 116, 224, .25);
142
+ }
143
+ .uk-button-primary:hover,
144
+ .uk-button-primary:focus {
145
+ background-color: var(--brand-pressed);
146
+ border-color: var(--brand-pressed);
147
+ color: var(--text-inverse);
148
+ box-shadow: 0 2px 8px rgba(0, 116, 224, .3);
149
+ }
150
+ .uk-button-secondary {
151
+ background-color: var(--brand-secondary);
152
+ border: 1px solid var(--brand-secondary);
153
+ color: var(--text-inverse);
154
+ }
155
+ .uk-button-secondary:hover,
156
+ .uk-button-secondary:focus {
157
+ background-color: var(--brand-2-pressed);
158
+ border-color: var(--brand-2-pressed);
159
+ color: var(--text-inverse);
160
+ }
161
+ .uk-button-default {
162
+ background-color: transparent;
163
+ border: 1px solid var(--line);
164
+ color: var(--ink);
165
+ }
166
+ .uk-button-default:hover,
167
+ .uk-button-default:focus {
168
+ background-color: var(--subtle-brand);
169
+ border-color: var(--link);
170
+ color: var(--link);
171
+ }
172
+ .uk-button-danger { border-radius:31.25rem; }
173
+ .uk-button:focus-visible {
174
+ outline: 0;
175
+ box-shadow: 0 0 0 3px var(--subtle-brand);
176
+ }
177
+ /* The prompt toolbar: command picker on the left, actions on the right. */
178
+ .chat-tools-spacer { flex: 1; }
179
+ .chat-input .command-picker {
180
+ height:2.125rem;
181
+ max-width:14.375rem;
182
+ padding:0 1.625rem 0 0.625rem;
183
+ border: 1px solid var(--line);
184
+ border-radius:31.25rem;
185
+ background-color: var(--subtle-light);
186
+ color: var(--text-subtle-2);
187
+ font-size:0.8125rem;
188
+ font-weight: 500;
189
+ }
190
+ .chat-input .command-picker:focus {
191
+ border-color: var(--brand-primary);
192
+ box-shadow: 0 0 0 3px var(--subtle-brand);
193
+ background-color: var(--surface-input);
194
+ }
195
+
196
+ /* Mic: a round icon button that reads as an action, with a soft brand hover
197
+ and a recording state, rather than a bare pill. */
198
+ .chat-input .mic-btn {
199
+ width:2.125rem;
200
+ height:2.125rem;
201
+ min-width:2.125rem;
202
+ padding: 0;
203
+ border-radius: 50%;
204
+ border: 1px solid var(--line);
205
+ background: var(--subtle-light);
206
+ color: var(--text-subtle-2);
207
+ display: inline-flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+ }
211
+ .chat-input .mic-btn:hover,
212
+ .chat-input .mic-btn:focus {
213
+ background: var(--subtle-brand);
214
+ border-color: var(--link);
215
+ color: var(--link);
216
+ }
217
+ .chat-input .mic-btn.listening {
218
+ background: var(--brand-primary);
219
+ border-color: var(--brand-primary);
220
+ color: var(--text-inverse);
221
+ animation: mic-pulse 1.4s ease-in-out infinite;
222
+ }
223
+ @keyframes mic-pulse {
224
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(0, 116, 224, .45); }
225
+ 50% { box-shadow: 0 0 0 6px rgba(0, 116, 224, 0); }
226
+ }
227
+ .chat-input .send-btn { height:2.125rem; }
228
+
229
+ /* Auto-mode plan card: the agent's proposal before it acts. UIKit buttons,
230
+ Webship tokens — nothing new imported. */
231
+ .plan-card {
232
+ margin-top:0.625rem;
233
+ padding:0.625rem 0.75rem;
234
+ background: var(--subtle-brand);
235
+ border: 1px solid var(--brand-primary);
236
+ border-radius:0.75rem;
237
+ }
238
+ .plan-summary {
239
+ margin:0 0 0.5rem;
240
+ color: var(--ink);
241
+ font-weight: 500;
242
+ font-size:0.875rem;
243
+ }
244
+ .plan-actions { display: flex; flex-wrap: wrap; gap:0.375rem; }
245
+ .plan-card-done { opacity: .55; pointer-events: none; }
246
+
247
+ /* Typeface, per the brand tokens. UIKit keeps its own sizing and rhythm;
248
+ only the families change. */
249
+ /* Typography, per the brand tokens (Figma 2070-473).
250
+ Headings 1 and 2 are Secondary at the display line-height; 3 to 6 are Primary
251
+ SemiBold at 1.4. h3 and the card titles were on the serif before, which the design
252
+ does not do — only H1 and H2 are Secondary. */
253
+ /* One declaration per role. `font:` sets the family, the weight, the size and the line-height
254
+ in one go, from the role token, so none of the four can be set without the other three.
255
+ Tracking is not part of the shorthand, so it is stated beside it. */
256
+ body, .uk-button, .uk-input, .uk-select, .uk-textarea { font: var(--type-body); }
257
+
258
+ /* The .uk-h* classes are listed beside the tags for the same reason the colour rule lists
259
+ them: a class outranks a tag, and UIKit's own .uk-h3 sets a family. An h2 marked .uk-h3 —
260
+ which is how every "Build a new project" heading is written — was rendering in the system
261
+ font rather than in Figtree. Naming the class here is what lets a heading be sized as one
262
+ level while staying on the brand. */
263
+ h1, .uk-h1 { font: var(--type-h1); letter-spacing: var(--tracking-h1); }
264
+ h2, .uk-h2 { font: var(--type-h2); letter-spacing: var(--tracking-h2); }
265
+ h3, .uk-h3, .uk-card-title { font: var(--type-h3); letter-spacing: var(--tracking-h3); }
266
+ h4, .uk-h4 { font: var(--type-h4); letter-spacing: var(--tracking-h4); }
267
+ h5, .uk-h5 { font: var(--type-h5); letter-spacing: var(--tracking-h5); }
268
+ .toolbar-product { font: var(--type-h5); letter-spacing: var(--tracking-h5); }
269
+
270
+ /* H6 is a small-caps label, not a sixth heading: set small and opened up, so it labels the
271
+ thing under it instead of competing with the body text beside it. */
272
+ h6, .uk-h6 {
273
+ font: var(--type-h6);
274
+ letter-spacing: var(--tracking-h6);
275
+ text-transform: uppercase;
276
+ }
277
+
278
+ .uk-text-meta, .uk-text-small { font: var(--type-caption); }
279
+
280
+ code, pre, .job-output, .chat-log pre { font-family: var(--font-code); }
281
+
282
+ /* The project card's own title: a folder is a place, so it reads like a heading
283
+ rather than a bold line in a list, and the URLs sit under it as one inline row. */
284
+ .project-title {
285
+ display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
286
+ margin: .15rem 0 .35rem; font-size: 1.15rem; font-weight: 700; line-height: 1.25;
287
+ }
288
+ /* The folder icon sits in the card's top-left corner, in the padding itself, with
289
+ the name beside it — the card looks like the folder it stands for. */
290
+ /* The folder icon and its name start at the card's own left edge, so a column of
291
+ cards reads as a column of folders rather than an indented list. */
292
+ .project-row { position: relative; }
293
+ .project-head { padding-left: 0; margin-left: -0.5rem; }
294
+ .project-title { margin-top: 0; display: flex; align-items: center; gap: .5rem; }
295
+ .project-title::before { content: "📁"; font-size: 1.9rem; line-height: 1; }
296
+ @media (max-width: 640px) {
297
+ .project-head { margin-left: -0.35rem; }
298
+ .project-title::before { font-size: 1.6rem; }
299
+ }
300
+ /* The links get their own line under the title, not the title's line. */
301
+ .proj-launch-line { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; margin: .15rem 0 .35rem; }
302
+ .proj-launch-line .proj-alias { display: inline-flex; align-items: center; gap: .25rem; }
303
+ /* Storybook is a different destination from the site, so it reads as one: the brand colour and a
304
+ book, against the muted grey the other aliases use. It is the component library, and the whole
305
+ reason for showing it is that people go looking for it and cannot find the address. */
306
+ /* `!important` is not a shortcut here: `.proj-alias` already carries
307
+ `color: var(--link) !important` from an earlier component, and no amount of specificity beats an
308
+ !important declaration. These two say something different from "this is a link", so they have to
309
+ match it. */
310
+ .proj-launch-line .proj-storybook { color: var(--brand-primary) !important; white-space: nowrap; }
311
+ .proj-launch-line .proj-storybook .tabler-icon { color: currentColor; }
312
+ /* An address two projects both claim. Not a link: it resolves to whichever started last, so
313
+ following it from this row would be a guess. Warning ink, and the title names the others. */
314
+ .proj-launch-line .proj-domain-clash { color: var(--warning-ink) !important; white-space: nowrap; cursor: help; }
315
+
316
+
317
+ /* The state badges sit in a row of pill buttons, so they are shaped like them:
318
+ same height, same radius, same rhythm — a label that reads as part of the
319
+ group rather than a sticker dropped beside it. */
320
+ .project-state { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
321
+ .project-state > .uk-label,
322
+ .project-state .uk-label {
323
+ height: 26px; display: inline-flex; align-items: center;
324
+ border-radius: 500px; padding: 0 12px; font-size: 13px; line-height: 1;
325
+ text-transform: none; letter-spacing: 0;
326
+ }
327
+ .project-state .act-with-status { display: inline-flex; align-items: center; }
328
+
329
+
330
+ /* Folder on the left, state on the right, one line: the two things you identify
331
+ a card by, at its two ends. */
332
+ .project-title-row { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
333
+ .project-title-row .project-title { margin-bottom: 0; }
334
+ .project-title-state { flex: none; }
335
+ /* Every badge on the name line is the same pill, and the selector says so by naming the WRAPPER rather
336
+ than one badge inside it. Scoped to `.project-title-state` alone, the agent badge that joined it
337
+ later fell back to bare UIkit — a 2px corner, 21px tall, UPPERCASE — beside a 26px pill, which reads
338
+ as one of the two being broken. */
339
+ .project-title-status .uk-label,
340
+ .project-title-state .uk-label {
341
+ height: 26px; display: inline-flex; align-items: center;
342
+ border-radius: 500px; padding: 0 12px; font-size: 13px; line-height: 1;
343
+ text-transform: none; letter-spacing: 0;
344
+ }
345
+
346
+
347
+ /* One rhythm for both rows of controls: the same gap between every button, and
348
+ the caption under a menu ("webship", "offline") no longer widens its column. */
349
+ .project-state-actions { display: inline-flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
350
+ .project-actions { display: flex; align-items: flex-start; gap: .4rem; flex-wrap: wrap; }
351
+ .project-state .act-with-status,
352
+ .project-actions .act-with-status { display: inline-flex; flex-direction: column; align-items: center; gap: 0; }
353
+ .act-with-status .act-status { margin: 0; line-height: 1.1; }
354
+ .project-actions .act-menu, .project-state .act-menu { margin: 0; }
355
+
356
+
357
+ /* Every line in the card starts where the folder icon does: one left edge for the
358
+ title, the links, the runtime menus and the action menus. */
359
+ .project-row .project-head,
360
+ .project-row .project-state,
361
+ .project-row .project-actions { margin-left: -0.5rem; }
362
+ .project-row .project-head { margin-left: -0.5rem; }
363
+ @media (max-width: 640px) {
364
+ .project-row .project-head,
365
+ .project-row .project-state,
366
+ .project-row .project-actions { margin-left: -0.35rem; }
367
+ }
368
+
369
+
370
+ /* A stopped project's local links are still its addresses — shown, but quieter,
371
+ so a running row still reads as the one you can open right now.
372
+ Quieter with a TOKEN, not with opacity: fading brand blue to 60% over white gives a pale sky blue at
373
+ 2.42:1 — the row went from "quieter" to unreadable, and a colour that was checked stopped being the
374
+ colour rendered. --text-subtle is 8.45:1 and is the quiet one by design. */
375
+ .proj-launch-line.is-stopped .uk-button,
376
+ .proj-launch-line.is-stopped .proj-alias:not(.proj-plugin-link) { color: var(--text-subtle); }
377
+
378
+ /* The DDEV menu is a palette, not a list: at nearly thirty entries a single
379
+ column runs off the screen, so it flows into two and each group stays whole. */
380
+ .ddev-dropdown-wide { width: 34rem; max-width: 92vw; }
381
+ .ddev-nav-columns { column-count: 2; column-gap: 1.25rem; }
382
+ .ddev-nav-columns > li { break-inside: avoid; }
383
+ .ddev-nav-columns > li.uk-nav-header { break-before: column-avoid; margin-top: .4rem; }
384
+ .ddev-nav-columns > li.uk-nav-divider { display: none; } /* the headers already separate the groups */
385
+ @media (max-width: 640px) {
386
+ .ddev-dropdown-wide { width: auto; }
387
+ .ddev-nav-columns { column-count: 1; }
388
+ }
389
+
390
+ /* The terminal takes the height it is given: most of the viewport inside the
391
+ modal, the whole tab on its own page, the whole screen in fullscreen. A
392
+ fixed height wasted a tall window and clipped a short one. */
393
+ .browser-term { height: min(72vh, 900px); }
394
+ .browser-term .xterm { height: 100%; }
395
+ #editor-modal .uk-modal-dialog:has(.browser-term) { width: 92vw; max-width: 1400px; }
396
+ /* Fullscreen wins over every page rule: the element that goes fullscreen is the
397
+ terminal's wrapper, so the pane inside it takes the whole screen minus the
398
+ status line. The !important is deliberate — the standalone page's own height
399
+ rule is more specific, and in fullscreen it is simply wrong. */
400
+ .browser-term:fullscreen,
401
+ .browser-term:-webkit-full-screen { height: 100vh !important; width: 100vw; border-radius: 0; padding: 6px; }
402
+ :fullscreen .browser-term,
403
+ .terminal-page :fullscreen .browser-term { height: calc(100vh - 2.75rem) !important; }
404
+ :fullscreen { background: var(--code-bg); }
405
+ .browser-term { background: var(--code-bg); padding: 8px; border-radius: 6px; }
406
+
407
+ /* A session that stopped to ask something: the one badge on this page that is a
408
+ call to act, so it is allowed to move. */
409
+ .needs-input { animation: needs-input-pulse 2s ease-in-out infinite; }
410
+ /* The pulse is a RING, not a fade: pulsing opacity took the label's own text to 3.9:1 for half of
411
+ every cycle, so the one badge that is asking for attention was the one that became hard to read. */
412
+ @keyframes needs-input-pulse {
413
+ 0%, 100% { box-shadow: 0 0 0 0 var(--warning); }
414
+ 50% { box-shadow: 0 0 0 0.3rem transparent; }
415
+ }
416
+ @media (prefers-reduced-motion: reduce) { .needs-input { animation: none; } }
@@ -0,0 +1,113 @@
1
+ /* The editor modal fits the screen.
2
+ *
3
+ * It used to grow with its content and scroll as a whole, so on a 1080px screen New screen was 1205px
4
+ * tall (1565 with Claude Code) and its Start button sat 130 to 490px below the fold, with the title and
5
+ * tabs scrolled away above it. Now the dialog is capped to the viewport and is a column of three:
6
+ *
7
+ * .modal-head the title and tabs, pinned at the top
8
+ * (the form) scrolls between them
9
+ * .modal-actions the buttons that do something, pinned at the bottom
10
+ *
11
+ * A form opts in with those two classes; one that does not still gets the capped height and its own scroll.
12
+ * The editors take the height that is left (see the Ace rules), so a script or a prompt is as tall as the
13
+ * screen allows rather than a fixed 62vh. Desktop first; nothing here relies on a height the content sets.
14
+ */
15
+
16
+ #editor-modal .uk-modal-dialog {
17
+ display: flex;
18
+ flex-direction: column;
19
+ max-height: calc(100dvh - 7rem);
20
+ margin-top: 0.25rem;
21
+ margin-bottom: 0.25rem;
22
+ }
23
+
24
+ #editor-modal .uk-modal-body {
25
+ flex: 1 1 auto;
26
+ min-height: 0;
27
+ overflow-y: auto;
28
+ overscroll-behavior: contain;
29
+ scroll-padding-block: 4.5rem;
30
+ padding: 1.375rem 1.625rem;
31
+ }
32
+
33
+ /* The actions are the last thing in the form, so the body has no padding under them to scroll past. */
34
+ #editor-modal .uk-modal-body:has(.modal-actions) { padding-bottom: 0; }
35
+
36
+ /* With a pinned header the body has no padding above it, or the form scrolls through that strip. */
37
+ #editor-modal .uk-modal-body:has(.modal-head) { padding-top: 0; }
38
+
39
+ #editor-modal .modal-head {
40
+ position: sticky;
41
+ top: 0;
42
+ z-index: 4;
43
+ margin: 0 calc(-1 * 1.625rem) 1rem;
44
+ padding: 1.375rem calc(1.625rem + 2rem) 0.75rem 1.625rem;
45
+ background: var(--surface-card);
46
+ border-bottom: 1px solid var(--line);
47
+ }
48
+ #editor-modal .modal-head > :last-child { margin-bottom: 0; }
49
+
50
+ /* The card inside the dialog brought its own 20px top margin and two empty result boxes brought 20px each below
51
+ it, so the pinned parts sat 20px in from the edges of the body and slipped when the form scrolled. */
52
+ #editor-modal .editor-card.uk-margin-top { margin-top: 0; }
53
+ #editor-modal .editor-card > .uk-margin-top:empty { margin: 0; }
54
+
55
+ #editor-modal .modal-actions,
56
+ #editor-modal form > :last-child:has(> button[type="submit"]) {
57
+ position: sticky;
58
+ bottom: 0;
59
+ z-index: 4;
60
+ margin: 1rem calc(-1 * 1.625rem) 0;
61
+ padding: 0.75rem 1.625rem;
62
+ background: var(--surface-card);
63
+ border-top: 1px solid var(--line);
64
+ box-shadow: 0 -0.5rem 0.75rem -0.5rem rgba(0, 0, 0, 0.12);
65
+ }
66
+ #editor-modal .modal-actions > :last-child { margin-bottom: 0; }
67
+
68
+ /* The editors take what is left of the screen. The chrome above and below them is about 19rem (title,
69
+ tabs, the fields around, the action row), and the form they sit in adds its own. */
70
+ #editor-modal .ace-host:not(.ace-host-single) {
71
+ height: clamp(12rem, calc(100dvh - 19rem), 46rem) !important;
72
+ }
73
+ /* New screen puts three fieldsets above its prompt, so the prompt gets less, but never less than a few lines. */
74
+ #editor-modal .new-screen-card .ace-host:not(.ace-host-single) {
75
+ height: clamp(11rem, calc(100dvh - 44rem), 26rem) !important;
76
+ }
77
+
78
+ /* New screen asks for the prompt before the Claude options: the prompt is what a person writes, and the options
79
+ (a model, a permission mode, 34 flags) have good defaults. Same fields, only the order they are met in. */
80
+ #editor-modal .new-screen-card form { display: flex; flex-direction: column; }
81
+ #editor-modal .new-screen-card form > fieldset[data-claude-only] { order: 3; }
82
+ #editor-modal .new-screen-card form > .modal-actions { order: 4; }
83
+ #editor-modal .new-screen-card form > fieldset:not([data-claude-only]):last-of-type { order: 2; }
84
+
85
+ /* The list of sections to remove had its own 12rem scroll box, which hid the last of seven inside a modal that
86
+ already scrolls: the pinned header and actions make a second scroll area pointless. */
87
+ #editor-modal .video-edit-sections { max-height: none; overflow: visible; }
88
+
89
+ /* Focus on the pinned action buttons was a 1.19:1 ring (the subtle brand tint on white). */
90
+ #editor-modal .modal-actions .uk-button:focus-visible,
91
+ #editor-modal .modal-head a:focus-visible {
92
+ outline: 2px solid var(--brand-primary);
93
+ outline-offset: 2px;
94
+ }
95
+ /* A pale grey checkbox border on white is 1.6:1; a control's edge needs 3:1 (WCAG 1.4.11). */
96
+ #editor-modal .uk-checkbox,
97
+ #editor-modal .uk-radio { border-color: var(--text-subtle); }
98
+ /* ...and a 16px box is under the 24px minimum target (WCAG 2.2, 2.5.8). */
99
+ #editor-modal .uk-checkbox,
100
+ #editor-modal .uk-radio { width: 1.5rem; height: 1.5rem; }
101
+
102
+ /* The accordion and the folded prompt open with a short height change. Someone who has asked their system for
103
+ less motion gets the content at once. */
104
+ @media (prefers-reduced-motion: reduce) {
105
+ #editor-modal [uk-accordion] .uk-accordion-content,
106
+ #editor-modal [uk-accordion] > li > * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
107
+ }
108
+
109
+ /* The folded prompt reads as a disclosure, not as a field: the summary is a plain line a person can click. */
110
+ #editor-modal .video-edit-ask > summary { cursor: pointer; list-style-position: inside; padding: 0.25rem 0; }
111
+ #editor-modal .video-edit-ask[open] > summary { margin-bottom: 0.25rem; }
112
+ #editor-modal .video-edit-accordion > li + li { margin-top: 0.5rem; }
113
+ #editor-modal .video-edit-accordion .uk-accordion-title { font-size: 1rem; }
@@ -0,0 +1,23 @@
1
+ /* ---------- How much of the window a page's content may use ----------
2
+ *
3
+ * `uk-container-small` capped every page at 900px, which was the right answer when the assistant was a
4
+ * fixed 25rem column and the rail was a fixed column opposite it: 900px was what was left. Both move
5
+ * now — the assistant can be closed, floating or on its own page — so on a wide screen the pages that
6
+ * most want the room were rendering in a ribbon with empty page beside them.
7
+ *
8
+ * Comfortable stays the default, because a reading width is a real constraint rather than an oversight:
9
+ * a settings form at 1900px is worse than one at 900px. The wider ones are offered, not imposed.
10
+ *
11
+ * The selector has to beat UIKit's own `.uk-container-small` max-width, which is a single class in a
12
+ * stylesheet linked after this one — so it is qualified, never `!important`.
13
+ */
14
+
15
+ /* Every page body, not just the ones capped at UIKit's `small`: the home page is a `large` container
16
+ and the width control did nothing there at all, which is the page most worth widening — 22 cards. */
17
+ html[data-page-width="wide"] .page-body { max-width: 87.5rem; }
18
+ html[data-page-width="full"] .page-body { max-width: none; }
19
+
20
+ /* The rail row that chooses it. It is a control, not a link, so it does not take the nav's current
21
+ marking — and collapsed, the icon and its title still say what it is. */
22
+ .actions-nav .actions-width { cursor: pointer; }
23
+ .width-dropdown { min-width: 12rem; }
@@ -0,0 +1,9 @@
1
+ /* Settings → Plugins: one card per plugin package, with the four steps it walks. */
2
+ .plugin-cards { display: grid; gap: 0.75rem; }
3
+ .plugin-card .uk-card-title { font-size: 1.05rem; }
4
+ .plugin-steps { display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; }
5
+ .plugin-step { color: var(--text-subtle); }
6
+ .plugin-step.is-done { color: var(--ok-ink, var(--brand-primary)); font-weight: 600; }
7
+ .plugin-step-sep { color: var(--line); }
8
+ .plugin-buttons { display: flex; flex-wrap: wrap; gap: 0.35rem; }
9
+ .plugin-require .uk-input { max-width: 100%; }