@zq-silk/yui 2.14.0 → 2.16.0

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 (70) hide show
  1. package/dist/config/configCatalog.js +1 -1
  2. package/dist/controlPlaneCli.js +1 -1
  3. package/dist/job/projectSync.js +3 -3
  4. package/dist/storage/sqliteSchema.js +12 -0
  5. package/dist/storage/storageVersions.js +1 -1
  6. package/dist/storage/upgrade/projectSyncClockMigration.js +30 -0
  7. package/dist/web/assets/assetManifest.js +23 -1
  8. package/dist/web/assets/client/app/catalog.js +40 -14
  9. package/dist/web/assets/client/app/login.js +156 -0
  10. package/dist/web/assets/client/app/main.js +33 -9
  11. package/dist/web/assets/client/app/manage.js +18 -0
  12. package/dist/web/assets/client/app/selection.js +4 -1
  13. package/dist/web/assets/client/app/taskView.js +22 -5
  14. package/dist/web/assets/client/i18n/en.js +28 -4
  15. package/dist/web/assets/client/i18n/zh-CN.js +28 -4
  16. package/dist/web/assets/client/index.js +8 -0
  17. package/dist/web/assets/client/layout/manageShell.js +30 -8
  18. package/dist/web/assets/client/layout/shortcuts.js +7 -3
  19. package/dist/web/assets/client/layout/sidebarNav.js +147 -0
  20. package/dist/web/assets/client/layout/sizing.js +5 -2
  21. package/dist/web/assets/client/layout/workspace.js +120 -21
  22. package/dist/web/assets/client/lib/api.js +5 -0
  23. package/dist/web/assets/client/lib/motion.js +59 -0
  24. package/dist/web/assets/client/lib/prefs.js +29 -2
  25. package/dist/web/assets/client/lib/session.js +21 -0
  26. package/dist/web/assets/client/lib/theme.js +11 -4
  27. package/dist/web/assets/client/ui/primitives.js +27 -0
  28. package/dist/web/assets/client/views/dock/terminal.js +4 -1
  29. package/dist/web/assets/client/views/overview.js +8 -5
  30. package/dist/web/assets/client/views/task/page.js +10 -10
  31. package/dist/web/assets/shared/brand.js +22 -0
  32. package/dist/web/assets/shared/geometry.js +7 -1
  33. package/dist/web/assets/shared/icons.js +5 -0
  34. package/dist/web/assets/shared/motion.js +74 -0
  35. package/dist/web/assets/shell/appRail.js +14 -0
  36. package/dist/web/assets/shell/dialogs.js +1 -0
  37. package/dist/web/assets/shell/dock.js +19 -6
  38. package/dist/web/assets/shell/index.js +6 -2
  39. package/dist/web/assets/shell/login.js +57 -0
  40. package/dist/web/assets/shell/manage.js +32 -20
  41. package/dist/web/assets/shell/settingsContent.js +1 -1
  42. package/dist/web/assets/shell/sidebar.js +16 -23
  43. package/dist/web/assets/styles/base.js +1 -1
  44. package/dist/web/assets/styles/index.js +4 -0
  45. package/dist/web/assets/styles/layout/responsive.js +63 -19
  46. package/dist/web/assets/styles/layout/workspace.js +53 -16
  47. package/dist/web/assets/styles/motion.js +51 -0
  48. package/dist/web/assets/styles/tokens.js +5 -3
  49. package/dist/web/assets/styles/ui/controls.js +1 -1
  50. package/dist/web/assets/styles/ui/forms.js +1 -1
  51. package/dist/web/assets/styles/ui/surfaces.js +1 -2
  52. package/dist/web/assets/styles/views/conversation.js +1 -1
  53. package/dist/web/assets/styles/views/dock.js +22 -2
  54. package/dist/web/assets/styles/views/login.js +45 -0
  55. package/dist/web/assets/styles/views/manage.js +25 -42
  56. package/dist/web/assets/styles/views/page.js +2 -3
  57. package/dist/web/assets/styles/views/records.js +1 -1
  58. package/dist/web/assets/styles/views/settings.js +1 -1
  59. package/dist/web/assets/styles/views/sidebar.js +25 -20
  60. package/dist/web/assets/styles/views/task.js +9 -15
  61. package/dist/web/assets/styles/views/terminal.js +1 -1
  62. package/dist/web/webAccess.js +129 -9
  63. package/dist/web/webServer.js +170 -14
  64. package/docs/release-workflow.md +67 -0
  65. package/docs/release-workflow.zh-CN.md +49 -0
  66. package/docs/storage-baseline.md +7 -1
  67. package/docs/storage-baseline.zh-CN.md +6 -1
  68. package/docs/testing/verification-levels.md +77 -11
  69. package/docs/testing/verification-levels.zh-CN.md +63 -9
  70. package/package.json +1 -1
@@ -1,18 +1,58 @@
1
+ import { RAIL_WIDTH } from "../../shared/geometry.js";
1
2
  /*
2
- * WORKSPACE — the three-region application frame.
3
- * sidebar | center (task details) | divider | dock (session)
4
- * body.dock-open shows the dock; body.dock-center swaps the dock into the
5
- * middle so the order becomes sidebar | dock | divider | center. The sidebar's
6
- * own divider overlays its right edge, so it adds no grid column; --sidebar-w
7
- * is the default width and a stored preference overrides it inline. Region
3
+ * WORKSPACE — the application frame.
4
+ * rail | sidebar | center (task details) | divider | dock (session)
5
+ * The rail is the global Workbench / Models / Settings navigation, shared with
6
+ * the management pages. body.dock-open shows the dock; body.dock-center swaps
7
+ * the dock into the middle so the order becomes rail | sidebar | dock |
8
+ * divider | center. body.sidebar-collapsed folds the task list away (the page
9
+ * header then offers .side-expand to bring it back). The sidebar's own
10
+ * divider overlays its right edge, so it adds no grid column; --sidebar-w is
11
+ * the default width and a stored preference overrides it inline. Region
8
12
  * contents are styled by the view stylesheets.
9
13
  */
10
14
  export const WORKSPACE_STYLES = `
15
+ :root{--rail-w:${RAIL_WIDTH}px}
11
16
  .app{display:grid;height:100vh;height:100dvh;grid-template-rows:minmax(0,1fr);
12
- grid-template-areas:"sidebar center divider dock";
13
- grid-template-columns:var(--sidebar-w) minmax(0,1fr) 0 0}
14
- body.dock-open .app{grid-template-columns:var(--sidebar-w) minmax(0,1fr) var(--divider-w) var(--dock-w)}
15
- body.dock-open.dock-center .app{grid-template-areas:"sidebar dock divider center";grid-template-columns:var(--sidebar-w) var(--dock-w) var(--divider-w) minmax(0,1fr)}
17
+ grid-template-areas:"rail sidebar center divider dock";
18
+ grid-template-columns:var(--rail-w) var(--sidebar-w) minmax(0,1fr) 0 0}
19
+ body.dock-open .app{grid-template-columns:var(--rail-w) var(--sidebar-w) minmax(0,1fr) var(--divider-w) var(--dock-w)}
20
+ body.dock-open.dock-center .app{grid-template-areas:"rail sidebar dock divider center";grid-template-columns:var(--rail-w) var(--sidebar-w) var(--dock-w) var(--divider-w) minmax(0,1fr)}
21
+ body.sidebar-collapsed{--sidebar-w:0px}
22
+ body.sidebar-collapsed:not(.sidebar-drawer) .sidebar,body.sidebar-collapsed .sidebar-divider{display:none}
23
+
24
+ /* Global rail: brand, then the three areas as icon-over-label tiles. */
25
+ .app-rail{grid-area:rail;display:flex;flex-direction:column;align-items:center;gap:6px;min-height:0;padding:10px 0 12px;background:var(--surface);border-right:1px solid var(--line);overflow-y:auto}
26
+ .rail-brand{display:grid;place-items:center;width:40px;height:40px;margin-bottom:6px;border-radius:var(--r-md);text-decoration:none}
27
+ .rail-brand .brand-mark{display:grid;place-items:center}
28
+ .rail-brand:hover .brand-mark{box-shadow:0 0 0 3px var(--accent-soft)}
29
+ .rail-items{display:flex;flex-direction:column;align-items:center;gap:4px}
30
+ .rail-item{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;width:48px;min-height:50px;padding:6px 2px;border-radius:var(--r-md);color:var(--ink-3);font-size:10.5px;font-weight:550;line-height:1.15;text-align:center;text-decoration:none;transition:background var(--t-fast),color var(--t-fast),transform var(--t-fast) var(--ease)}
31
+ .rail-item .icon{width:18px;height:18px;flex:none}
32
+ .rail-item span{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
33
+ .rail-item:hover{background:var(--surface-3);color:var(--ink)}
34
+ .rail-item[aria-current="page"]{background:var(--accent-soft);color:var(--accent)}
35
+
36
+ /* Task-list switch in the page header: only while the list is out of view. */
37
+ .icon-btn.side-expand{display:none}
38
+ .side-expand .i-menu{display:none}
39
+ .side-expand>span{display:contents}
40
+ body.sidebar-collapsed .side-expand{display:inline-grid}
41
+ .side-title{flex:1;min-width:0;font-size:var(--fs-md);font-weight:650;letter-spacing:-.01em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
42
+ .sidebar-scrim[hidden]{display:none}
43
+
44
+ /* Top bar: the first row of the center column on every page. Its height and
45
+ rule line up with the task-list head and the dock head, so the frame reads
46
+ as one header row: list switch, location, then the page's actions. */
47
+ .top-bar{position:sticky;top:0;z-index:var(--z-sticky);display:flex;align-items:center;gap:6px;height:var(--header-h);padding:0 16px 0 12px;border-bottom:1px solid var(--line);background:var(--canvas)}
48
+ .top-title{min-width:0;overflow:hidden;color:var(--ink);font-size:var(--fs-md);font-weight:600;text-overflow:ellipsis;white-space:nowrap}
49
+ .crumbs{display:flex;align-items:center;gap:4px;min-width:0;font-size:var(--fs-sm);white-space:nowrap}
50
+ .crumb,.crumb-sep{flex:none}
51
+ .crumb{padding:3px 6px;border:0;border-radius:var(--r-xs);background:transparent;color:var(--ink-3);font-size:var(--fs-sm)}
52
+ button.crumb:hover{color:var(--ink);background:var(--surface-3)}
53
+ .crumb-sep{color:var(--ink-4)}
54
+ .crumb-current{min-width:0;overflow:hidden;padding:3px 6px;color:var(--ink);font-weight:600;text-overflow:ellipsis}
55
+ code.crumb-current{font-weight:500;font-size:var(--fs-xs);color:var(--ink-2)}
16
56
 
17
57
  /* Resize dividers: a wide invisible hit area around a 1px rule that lights up
18
58
  on hover, focus and while dragging. */
@@ -25,16 +65,13 @@ body.sidebar-resizing,body.dock-resizing{cursor:col-resize;user-select:none}
25
65
 
26
66
  /* Sidebar */
27
67
  .sidebar{grid-area:sidebar;display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--surface);border-right:1px solid var(--line);container:sidebar/inline-size}
28
- .sidebar-divider{grid-area:sidebar;justify-self:end;z-index:20;width:var(--divider-w);margin-right:-5px}
68
+ .sidebar-divider{grid-area:sidebar;justify-self:end;z-index:var(--z-header);width:var(--divider-w);margin-right:-5px}
29
69
  .sidebar-divider span{left:3px;background:transparent}
30
70
  .side-head{flex:none;display:flex;align-items:center;gap:10px;height:var(--header-h);padding:0 12px 0 16px;border-bottom:1px solid var(--line)}
31
- .brand{display:flex;align-items:center;gap:10px;flex:1;min-width:0}
32
- .attention-bar{flex:none;margin:10px 12px 0}
33
- .status-tabs{flex:none;margin:10px 0 0;padding:0 12px}
71
+ .status-tabs{flex:none;margin:4px 0 0;padding:0 12px}
34
72
  .task-list{flex:1;min-height:0;overflow-y:auto;padding:4px 8px 12px;scrollbar-gutter:stable}
35
73
  .pager{flex:none;display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:6px;padding:8px 12px;border-top:1px solid var(--line)}
36
74
  .pager .pager-clear{grid-column:1/-1}
37
- .side-foot{flex:none;display:flex;align-items:center;gap:4px;padding:10px;border-top:1px solid var(--line)}
38
75
 
39
76
  /* Center */
40
77
  .center{grid-area:center;min-width:0;min-height:0;overflow-y:auto;scrollbar-gutter:stable;background:var(--canvas)}
@@ -42,7 +79,7 @@ body.sidebar-resizing,body.dock-resizing{cursor:col-resize;user-select:none}
42
79
  .detail{min-height:100%}
43
80
 
44
81
  /* Dock */
45
- .dock-divider{grid-area:divider;background:var(--canvas);z-index:5}
82
+ .dock-divider{grid-area:divider;background:var(--canvas);z-index:var(--z-raised)}
46
83
  .dock-divider span{left:4px;background:var(--line-2)}
47
84
  .dock{grid-area:dock;display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--surface)}
48
85
  body.dock-open:not(.dock-center) .dock{border-left:0}
@@ -0,0 +1,51 @@
1
+ import { BREAKPOINTS } from "../shared/geometry.js";
2
+ import { motionKeyframes } from "../shared/motion.js";
3
+ /*
4
+ * MOTION — the shared animation library. Timings, curves and layers are the
5
+ * tokens generated from shared/motion.ts; this sheet holds the keyframes and
6
+ * the component motion that is the same everywhere:
7
+ * dialogs scale + fade in, quicker fade out; the backdrop fades
8
+ * (@starting-style + allow-discrete, as Radix Dialog does)
9
+ * popovers <details> menus pop in from their anchor
10
+ * press buttons settle slightly under the pointer
11
+ * pages cross-document View Transitions between Workbench, Models
12
+ * and Settings; the rail stays put
13
+ * layout same-document View Transitions for column changes (the
14
+ * client wraps sidebar collapse and dock open/close)
15
+ * Everything honours prefers-reduced-motion (base.ts turns it all off).
16
+ */
17
+ export const MOTION_STYLES = `
18
+ ${motionKeyframes()}
19
+ .dialog{opacity:0;transform:scale(.96);transition:opacity var(--t-exit) var(--ease-exit),transform var(--t-exit) var(--ease-exit),overlay var(--t-exit) allow-discrete,display var(--t-exit) allow-discrete}
20
+ .dialog[open]{opacity:1;transform:none;transition-duration:var(--t-base);transition-timing-function:var(--ease-standard)}
21
+ .dialog::backdrop{opacity:0;transition:opacity var(--t-exit) var(--ease-exit),overlay var(--t-exit) allow-discrete,display var(--t-exit) allow-discrete}
22
+ .dialog[open]::backdrop{opacity:1;transition-duration:var(--t-base)}
23
+ @starting-style{.dialog[open]{opacity:0;transform:scale(.96)}.dialog[open]::backdrop{opacity:0}}
24
+ details[open]>.cv-popbody,details[open]>.dock-target-menu{animation:m-pop var(--t-base) var(--ease-standard)}
25
+ .cv-attach>.cv-popbody,.cv-model>.cv-popbody{transform-origin:bottom left}
26
+ .cv-model>.cv-popbody{transform-origin:bottom right}
27
+ .cv-menu>.cv-popbody{transform-origin:top right}
28
+ .dock-target-menu{transform-origin:top left}
29
+ .icon-btn:active:not(:disabled),.rail-item:active{transform:scale(.94)}
30
+ /* Workbench ⇄ Models ⇄ Settings are separate documents: the browser
31
+ cross-fades them (no blank frame) and the rail stays put between them. */
32
+ @view-transition{navigation:auto}
33
+ ::view-transition-old(root),::view-transition-new(root){animation-duration:var(--t-page);animation-timing-function:var(--ease-sheet)}
34
+ @media(prefers-reduced-motion:reduce){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}}
35
+ /* Page content entering after an explicit navigation (client/lib/motion). */
36
+ .m-enter{animation:m-rise var(--t-base) var(--ease-standard)}
37
+ @media(min-width:${BREAKPOINTS.narrow + 1}px){
38
+ .app-rail{view-transition-name:app-rail}
39
+ /* Column changes: client/lib/motion sets .vt-layout for the transition
40
+ only. Each column glides between its old and new box showing its new
41
+ content (no double image); a column that appears or leaves fades. */
42
+ .vt-layout .sidebar{view-transition-name:sidebar}
43
+ .vt-layout .center{view-transition-name:center}
44
+ .vt-layout .dock{view-transition-name:dock}
45
+ ::view-transition-group(sidebar),::view-transition-group(center),::view-transition-group(dock){animation-duration:var(--t-layout);animation-timing-function:var(--ease-sheet);overflow:clip}
46
+ ::view-transition-old(sidebar),::view-transition-new(sidebar),::view-transition-old(center),::view-transition-new(center),::view-transition-old(dock),::view-transition-new(dock){width:100%;height:100%;object-fit:none;object-position:0 0;animation:none}
47
+ ::view-transition-old(sidebar),::view-transition-old(center),::view-transition-old(dock){opacity:0}
48
+ ::view-transition-old(sidebar):only-child,::view-transition-old(dock):only-child{opacity:1;animation:m-fade var(--t-exit) var(--ease-exit) reverse both}
49
+ ::view-transition-new(sidebar):only-child,::view-transition-new(dock):only-child{animation:m-fade var(--t-layout) var(--ease-standard) both}
50
+ }
51
+ `;
@@ -1,4 +1,5 @@
1
1
  import { DIVIDER_WIDTH, DOCK } from "../shared/geometry.js";
2
+ import { motionTokenStyles } from "../shared/motion.js";
2
3
  import { themeTokenStyles } from "../shared/themes.js";
3
4
  /*
4
5
  * DESIGN TOKENS
@@ -6,8 +7,9 @@ import { themeTokenStyles } from "../shared/themes.js";
6
7
  * Geometry, type, radii, motion and the focus ring are theme-independent and
7
8
  * live once on :root. Colour and effect tokens come from the theme registry
8
9
  * (shared/themes.ts), one block per theme, so switching a theme can never move
9
- * or resize anything. Layout widths come from shared/geometry.ts, the same
10
- * source the client layout controller clamps against.
10
+ * or resize anything. Layout widths come from shared/geometry.ts and motion
11
+ * (durations, easings, stacking layers) from shared/motion.ts, the same
12
+ * sources the client scripts read.
11
13
  */
12
14
  export const TOKEN_STYLES = `
13
15
  :root{
@@ -17,7 +19,7 @@ export const TOKEN_STYLES = `
17
19
  --r-xs:5px;--r-sm:7px;--r-md:10px;--r-lg:14px;--r-pill:999px;
18
20
  --sidebar-w:clamp(260px,21vw,312px);--dock-w:${DOCK.initial}px;--divider-w:${DIVIDER_WIDTH}px;
19
21
  --center-max:880px;--header-h:56px;--gutter:clamp(16px,3vw,40px);
20
- --t-fast:120ms;--t-med:220ms;--ease:cubic-bezier(.2,.8,.2,1);
22
+ ${motionTokenStyles()}
21
23
  --focus:0 0 0 2px var(--canvas),0 0 0 4px var(--accent-line);
22
24
  }
23
25
  ${themeTokenStyles()}
@@ -27,7 +27,7 @@ export const CONTROL_STYLES = `
27
27
  .btn-link:hover:not(:disabled){background:transparent;text-decoration:underline;text-underline-offset:3px}
28
28
  .link-btn{justify-self:start;padding:0;border:0;background:none;color:var(--accent);font-size:var(--fs-xs);font-weight:500}
29
29
  .link-btn:hover{text-decoration:underline;text-underline-offset:3px}
30
- .icon-btn{display:inline-grid;place-items:center;width:32px;height:32px;flex:none;padding:0;border:0;border-radius:var(--r-sm);background:transparent;color:var(--ink-3);transition:background var(--t-fast),color var(--t-fast)}
30
+ .icon-btn{display:inline-grid;place-items:center;width:32px;height:32px;flex:none;padding:0;border:0;border-radius:var(--r-sm);background:transparent;color:var(--ink-3);transition:background var(--t-fast),color var(--t-fast),transform var(--t-fast) var(--ease)}
31
31
  .icon-btn:hover:not(:disabled){background:var(--surface-3);color:var(--ink)}
32
32
  .icon-btn[aria-pressed="true"]{background:var(--accent-soft);color:var(--accent)}
33
33
  .icon-btn:disabled{opacity:.4}
@@ -41,6 +41,6 @@ export const FORM_STYLES = `
41
41
  .shortcut-list dd{margin:0}
42
42
 
43
43
  /* Toast */
44
- .toast{position:fixed;left:50%;bottom:24px;z-index:90;max-width:min(520px,calc(100vw - 32px));padding:10px 16px;border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2);color:var(--ink);box-shadow:var(--shadow-2);font-size:var(--fs-sm);opacity:0;transform:translate(-50%,8px);pointer-events:none;transition:opacity var(--t-med),transform var(--t-med) var(--ease)}
44
+ .toast{position:fixed;left:50%;bottom:24px;z-index:var(--z-toast);max-width:min(520px,calc(100vw - 32px));padding:10px 16px;border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2);color:var(--ink);box-shadow:var(--shadow-2);font-size:var(--fs-sm);opacity:0;transform:translate(-50%,8px);pointer-events:none;transition:opacity var(--t-base) var(--ease),transform var(--t-base) var(--ease)}
45
45
  .toast.show{opacity:1;transform:translate(-50%,0)}
46
46
  `;
@@ -108,8 +108,7 @@ details[open]>summary .disclosure-chevron{transform:rotate(90deg)}
108
108
  .show-more:hover,.pager-clear:hover{color:var(--accent);border-color:var(--accent-line)}
109
109
  .show-more{justify-self:start;display:inline-flex;align-items:center;height:30px;padding:0 12px;font-weight:500}
110
110
  .loading-block{display:flex;align-items:center;gap:10px;padding:32px 8px;color:var(--ink-3)}
111
- .spinner{width:14px;height:14px;border-radius:50%;border:2px solid var(--line-3);border-top-color:var(--accent);animation:spin .8s linear infinite}
112
- @keyframes spin{to{transform:rotate(360deg)}}
111
+ .spinner{width:14px;height:14px;border-radius:50%;border:2px solid var(--line-3);border-top-color:var(--accent);animation:m-spin .8s linear infinite}
113
112
 
114
113
  /* Metrics */
115
114
  .metric{display:grid;gap:4px;align-content:start;min-width:0;padding:12px 14px;border:1px solid var(--line);border-radius:var(--r-md);background:var(--surface)}
@@ -98,7 +98,7 @@ export const CONVERSATION_STYLES = `
98
98
  .cv-pop{position:relative;flex:none}
99
99
  .cv-pop>summary{list-style:none}
100
100
  .cv-pop>summary::-webkit-details-marker{display:none}
101
- .cv-popbody{position:absolute;z-index:20;display:grid;gap:8px;width:min(300px,calc(100vw - 32px));max-height:min(420px,60vh);overflow:auto;padding:10px;border:1px solid var(--line-2);border-radius:var(--r-lg);background:var(--surface-2);box-shadow:var(--shadow-2);box-sizing:border-box}
101
+ .cv-popbody{position:absolute;z-index:var(--z-popover);display:grid;gap:8px;width:min(300px,calc(100vw - 32px));max-height:min(420px,60vh);overflow:auto;padding:10px;border:1px solid var(--line-2);border-radius:var(--r-lg);background:var(--surface-2);box-shadow:var(--shadow-2);box-sizing:border-box}
102
102
  .cv-attach>.cv-popbody{left:0;bottom:calc(100% + 8px)}
103
103
  .cv-model>.cv-popbody{right:0;bottom:calc(100% + 8px)}
104
104
  .cv-menu>.cv-popbody{right:0;top:calc(100% + 6px)}
@@ -4,9 +4,29 @@
4
4
  * The Live session pane is views/terminal; the dock frame is layout/workspace.
5
5
  */
6
6
  export const DOCK_STYLES = `
7
- .dock-head{height:auto;min-height:var(--header-h);padding-top:6px;padding-bottom:6px}
8
- .dock-head .seg{min-width:0;flex-wrap:wrap}
7
+ .dock-head{height:auto;min-height:var(--header-h);padding-top:6px;padding-bottom:6px;border-bottom:0}
9
8
  .dock-actions{flex-shrink:0}
9
+ /* Who the panel talks to: a title-like menu button with its target list */
10
+ .dock-target{position:relative;min-width:0}
11
+ .dock-target-btn{display:flex;align-items:center;gap:8px;min-width:0;height:34px;padding:0 10px 0 6px;border-radius:var(--r-md);color:var(--ink);font-size:var(--fs-md);font-weight:600;cursor:pointer;list-style:none;transition:background var(--t-fast)}
12
+ .dock-target-btn::-webkit-details-marker{display:none}
13
+ .dock-target-btn:hover,.dock-target[open] .dock-target-btn{background:var(--surface-3)}
14
+ .dock-target-btn>.icon{width:14px;height:14px;flex:none;color:var(--ink-4)}
15
+ .dock-target-icon{display:inline-grid;place-items:center;width:24px;height:24px;flex:none;border-radius:var(--r-sm);background:var(--accent-soft);color:var(--accent)}
16
+ .dock-target-icon .icon{width:14px;height:14px}
17
+ .dock-target-label{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
18
+ .dock-target-menu{position:absolute;left:0;top:calc(100% + 4px);z-index:var(--z-popover);display:grid;gap:2px;min-width:220px;max-width:min(320px,80vw);padding:6px;border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2);box-shadow:var(--shadow-2)}
19
+ .dock-target-menu hr{margin:4px 2px;border:0;border-top:1px solid var(--line)}
20
+ .dock-target-options{display:grid;gap:2px}
21
+ .dock-target-item{display:flex;align-items:center;gap:8px;width:100%;min-width:0;height:32px;padding:0 8px;border:0;border-radius:var(--r-sm);background:transparent;color:var(--ink-2);font-size:var(--fs-sm);text-align:left}
22
+ .dock-target-item span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
23
+ .dock-target-item .icon{width:15px;height:15px;flex:none;color:var(--ink-4)}
24
+ .dock-target-item:hover{background:var(--surface-3);color:var(--ink)}
25
+ .dock-target-item[aria-pressed="true"]{color:var(--ink);font-weight:550}
26
+ .dock-target-item .dock-target-check{color:var(--accent)}
27
+ .dock-tabs{flex:none;padding:0 12px 10px;border-bottom:1px solid var(--line)}
28
+ .dock-tabs .seg{display:flex;flex-wrap:wrap;width:100%;min-width:0}
29
+ .dock-tabs .seg-btn{flex:1 1 auto;justify-content:center}
10
30
  .dock-preview{display:flex;flex-direction:column;min-height:0;overflow:auto}
11
31
  .dock-preview>.feed-note{text-align:left;padding:0 12px;color:var(--ink-3)}
12
32
  .preview-services{flex:none;max-height:40%;overflow:auto}
@@ -0,0 +1,45 @@
1
+ /*
2
+ * LOGIN VIEW — the standalone sign-in document: one card centred on the
3
+ * canvas at every size, headed by the brand and the language control, with a
4
+ * password field (with reveal toggle), inline error/notice states and the
5
+ * plain-HTTP reminder. Colour comes only from theme tokens; on phones the
6
+ * card drops its frame and uses the full width.
7
+ */
8
+ export const LOGIN_STYLES = `
9
+ .login-body{height:auto;min-height:100vh;min-height:100dvh;overflow:auto}
10
+ .login-shell{display:grid;place-items:center;min-height:100vh;min-height:100dvh;padding:max(24px,env(safe-area-inset-top,0px)) 16px max(24px,env(safe-area-inset-bottom,0px));background:radial-gradient(120% 70% at 50% -10%,var(--accent-soft),transparent 60%),var(--canvas)}
11
+ .login-top{display:flex;align-items:center;justify-content:space-between;gap:12px;min-width:0}
12
+ .login-locale{flex:none}
13
+ .login-locale select{height:30px;width:auto;max-width:132px;padding:0 26px 0 9px;line-height:28px;font-size:var(--fs-xs)}
14
+ .login-card{display:grid;gap:20px;width:min(400px,100%);margin-bottom:6vh;padding:28px;border:1px solid var(--line-2);border-radius:var(--r-lg);background:var(--surface);box-shadow:var(--shadow-2)}
15
+ .login-brand{display:flex;align-items:center;gap:10px}
16
+ .login-brand .brand-mark{display:block;width:32px;height:32px;flex:none;border-radius:8px;background:var(--ink);color:var(--canvas);overflow:hidden}
17
+ .brand-glyph{display:block;width:100%;height:100%}
18
+ .brand-dot{fill:var(--accent)}
19
+ .login-brand .brand-name{font-size:var(--fs-lg);font-weight:650;letter-spacing:-.02em}
20
+ .login-heading{display:grid;gap:6px}
21
+ .login-heading h1{font-size:var(--fs-2xl)}
22
+ .login-sub{color:var(--ink-3);font-size:var(--fs-sm);overflow-wrap:anywhere}
23
+ .login-notice{margin:0;padding:10px 12px;border:1px solid var(--line-2);border-left:3px solid var(--tone,var(--info));border-radius:var(--r-sm);background:var(--tone-soft,var(--info-soft));color:var(--ink);font-size:var(--fs-sm)}
24
+ .login-form{display:grid;gap:16px}
25
+ .login-field{display:grid;gap:6px;min-width:0}
26
+ .login-label{color:var(--ink-2);font-size:var(--fs-xs);font-weight:500}
27
+ .login-password{position:relative}
28
+ .login-password input{height:40px;padding-right:44px}
29
+ .login-password input[aria-invalid="true"]{border-color:var(--bad)}
30
+ .login-password input[aria-invalid="true"]:focus{box-shadow:0 0 0 3px var(--bad-soft)}
31
+ .login-reveal{position:absolute;top:4px;right:4px}
32
+ .login-reveal .icon-hide,.login-reveal[aria-pressed="true"] .icon-show{display:none}
33
+ .login-reveal[aria-pressed="true"] .icon-hide{display:block}
34
+ .login-error{margin:0;color:var(--bad);font-size:var(--fs-sm);overflow-wrap:anywhere}
35
+ .login-submit{width:100%;height:40px;font-size:var(--fs-md)}
36
+ .login-spinner{display:none;width:14px;height:14px;flex:none;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:m-spin .8s linear infinite}
37
+ .login-form[aria-busy="true"] .login-spinner{display:inline-block}
38
+ .login-transport{display:flex;align-items:flex-start;gap:8px;margin:0;padding-top:16px;border-top:1px solid var(--line);color:var(--ink-3);font-size:var(--fs-xs)}
39
+ .login-transport .icon{width:14px;height:14px;margin-top:2px;color:var(--warn)}
40
+ @media(max-width:480px){
41
+ .login-shell{padding-left:0;padding-right:0;background:var(--surface)}
42
+ .login-card{width:100%;margin-bottom:0;padding:24px 20px;border:0;border-radius:0;box-shadow:none}
43
+ .login-heading h1{font-size:var(--fs-xl)}
44
+ }
45
+ `;
@@ -1,40 +1,33 @@
1
1
  import { BREAKPOINTS } from "../../shared/geometry.js";
2
2
  /*
3
- * MANAGE VIEW — the frame shared by the management pages (/models and
4
- * /settings): a rail in the dashboard sidebar's language (brand, the fixed
5
- * Workbench / Models / Settings navigation with every section listed under
6
- * its area, the language control) beside one reading column whose sections
7
- * share a heading (area kicker, title, explanation). Page sheets add only
8
- * their own content. Below the narrow breakpoint the rail becomes a top bar:
9
- * brand and language, the three main destinations, then the current area's
10
- * sections, wrapping so every entry stays visible.
3
+ * MANAGE VIEW — what the management pages (/models and /settings) add to the
4
+ * workbench frame (layout/workspace): the section list in the sidebar slot,
5
+ * the language control in the top bar, and one reading column whose sections
6
+ * share a heading (title, explanation). The rail, the collapsible list, the
7
+ * top bar and the narrow-screen drawer are the workbench's own. Page sheets
8
+ * add only their own content.
11
9
  */
12
10
  export const MANAGE_STYLES = `
13
- .manage-body{display:block;height:auto;min-height:100vh;min-height:100dvh;overflow:auto}
14
- .manage-app{display:grid;grid-template-columns:240px minmax(0,1fr);min-height:100vh;min-height:100dvh}
15
11
  .manage-app[hidden],#models-root[hidden],#settings-root[hidden]{display:none}
12
+ .manage-body{--sidebar-w:240px}
13
+ body.manage-body.sidebar-collapsed{--sidebar-w:0px}
16
14
 
17
- /* Rail */
18
- .manage-rail{position:sticky;top:0;display:flex;flex-direction:column;height:100vh;height:100dvh;min-width:0;overflow-y:auto;background:var(--surface);border-right:1px solid var(--line)}
19
- .manage-rail-head{flex:none;display:flex;align-items:center;gap:10px;height:var(--header-h);padding:0 12px 0 16px;border-bottom:1px solid var(--line)}
20
- .manage-rail-head .brand{flex:1;color:var(--ink);text-decoration:none}
21
- .manage-locale{flex:none;min-width:0}
22
- .manage-locale select{height:30px;width:auto;max-width:124px;padding:0 26px 0 9px;line-height:28px;font-size:var(--fs-xs)}
23
- .manage-nav{display:flex;flex-direction:column;gap:6px;padding:12px 8px 20px;min-width:0}
24
- .manage-area{display:grid;gap:2px;min-width:0}
25
- .manage-primary,.manage-link{position:relative;display:flex;align-items:center;min-width:0;border-radius:var(--r-md);text-decoration:none;white-space:nowrap;transition:background var(--t-fast),color var(--t-fast)}
26
- .manage-primary span,.manage-link span{overflow:hidden;text-overflow:ellipsis}
27
- .manage-primary{gap:9px;height:34px;padding:0 10px;color:var(--ink-2);font-size:var(--fs-md);font-weight:550}
28
- .manage-primary .icon{width:16px;height:16px;flex:none;color:var(--ink-4)}
29
- .manage-primary:hover,.manage-link:hover{background:var(--surface-3);color:var(--ink)}
30
- .manage-primary[aria-current]{color:var(--ink)}
31
- .manage-primary[aria-current] .icon{color:var(--accent)}
32
- .manage-sections{display:grid;gap:1px;margin:0 0 4px 18px;padding-left:8px;border-left:1px solid var(--line);min-width:0}
33
- .manage-link{gap:8px;height:30px;padding:0 10px;color:var(--ink-3);font-size:var(--fs-sm);font-weight:500}
15
+ /* Section list: only the current area's sections (the rail switches areas). */
16
+ .manage-nav{flex:1;min-height:0;overflow-y:auto;padding:10px 8px 20px}
17
+ .manage-area:not([data-active="true"]){display:none}
18
+ .manage-sections{display:grid;gap:2px;min-width:0}
19
+ .manage-link{position:relative;display:flex;align-items:center;gap:8px;min-width:0;height:34px;padding:0 10px;border-radius:var(--r-md);color:var(--ink-3);font-size:var(--fs-sm);font-weight:500;text-decoration:none;white-space:nowrap;transition:background var(--t-fast),color var(--t-fast)}
20
+ .manage-link span{overflow:hidden;text-overflow:ellipsis}
21
+ .manage-link:hover{background:var(--surface-3);color:var(--ink)}
34
22
  .manage-link[aria-current="page"]{background:var(--surface-3);color:var(--ink);box-shadow:inset 0 0 0 1px var(--line-2)}
35
- .manage-link[aria-current="page"]::before{content:"";position:absolute;left:-9px;top:6px;bottom:6px;width:2px;border-radius:2px;background:var(--accent)}
23
+ .manage-link[aria-current="page"]::before{content:"";position:absolute;left:0;top:9px;bottom:9px;width:3px;border-radius:0 3px 3px 0;background:var(--accent)}
36
24
  .manage-dirty{display:none;width:7px;height:7px;margin-left:auto;flex:none;border-radius:50%;background:var(--warn);box-shadow:0 0 0 3px var(--warn-soft)}
37
25
  .manage-link[data-dirty="true"] .manage-dirty{display:inline-block}
26
+ @media(pointer:coarse){.manage-link{height:42px}}
27
+
28
+ /* Language control at the end of the top bar */
29
+ .top-locale{flex:none;min-width:0}
30
+ .top-locale select{height:30px;width:auto;max-width:124px;padding:0 26px 0 9px;line-height:28px;font-size:var(--fs-xs)}
38
31
 
39
32
  /* Reading column and the shared section heading */
40
33
  .manage-main{min-width:0;padding:28px var(--gutter) 72px}
@@ -50,20 +43,10 @@ export const MANAGE_STYLES = `
50
43
  .manage-body input[type=checkbox]{width:16px;height:16px;padding:0;accent-color:var(--accent)}
51
44
 
52
45
  @media(max-width:${BREAKPOINTS.narrow}px){
53
- .manage-app{grid-template-columns:minmax(0,1fr)}
54
- .manage-rail{position:static;height:auto;overflow:visible;border-right:0;border-bottom:1px solid var(--line)}
55
- .manage-rail-head{height:52px}
56
- .manage-nav{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;padding:8px 10px}
57
- .manage-area{display:contents}
58
- .manage-primary{justify-content:center;gap:7px;height:36px;padding:0 6px;font-size:var(--fs-sm);background:var(--surface-2);box-shadow:inset 0 0 0 1px var(--line)}
59
- .manage-primary[aria-current]{background:var(--surface-3);box-shadow:inset 0 0 0 1px var(--line-2),inset 0 -2px 0 var(--accent)}
60
- /* Only the current area's sections, as a wrapping strip under the tabs. */
61
- .manage-sections{display:none;grid-column:1/-1;grid-row:2;margin:4px 0 0;padding:0;border:0}
62
- .manage-area[data-active="true"] .manage-sections{display:flex;flex-wrap:wrap;gap:4px}
63
- .manage-link{flex:0 1 auto;max-width:100%;height:32px;padding:0 10px;border:1px solid var(--line)}
64
- .manage-link[aria-current="page"]{border-color:var(--line-2)}
65
- .manage-link[aria-current="page"]::before{left:10px;right:10px;top:auto;bottom:2px;width:auto;height:2px}
66
- .manage-main{padding:18px 14px 56px}
46
+ .manage-main{padding:20px 14px 56px}
47
+ .manage-body .top-locale{display:none}
48
+ /* The top bar already names the section; the page keeps only its explanation. */
49
+ .manage-heading h1{display:none}
67
50
  }
68
51
  @media(max-width:${BREAKPOINTS.small}px){
69
52
  .manage-heading h1{font-size:var(--fs-xl)}
@@ -8,9 +8,8 @@ export const PAGE_STYLES = `
8
8
  .page{max-width:var(--center-max);margin:0 auto;padding:0 var(--gutter) 64px}
9
9
 
10
10
  /* Page scaffolding */
11
- .page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;padding:36px 0 24px}
12
- .kicker{color:var(--accent);font-size:var(--fs-2xs);font-weight:600;text-transform:uppercase;letter-spacing:.1em}
13
- .page-title{margin-top:6px;font-size:var(--fs-2xl);font-weight:650;letter-spacing:-.025em}
11
+ .page-head{display:flex;align-items:flex-end;justify-content:space-between;gap:16px;padding:28px 0 20px}
12
+ .page-title{font-size:var(--fs-2xl);font-weight:650;letter-spacing:-.025em}
14
13
  .page-sub{margin-top:4px;color:var(--ink-3)}
15
14
  .page-foot{margin-top:20px;color:var(--ink-4);font-size:var(--fs-xs);text-align:center}
16
15
  .sub-head{display:flex;align-items:center;gap:8px;margin-top:6px;font-size:var(--fs-sm);font-weight:600}
@@ -50,7 +50,7 @@ summary.work-head:focus-visible{box-shadow:inset 0 0 0 2px var(--accent-line)}
50
50
  .timeline{list-style:none;margin:0;padding:0;position:relative;display:grid;gap:0}
51
51
  .timeline::before{content:"";position:absolute;left:13px;top:6px;bottom:6px;width:1px;background:var(--line-2)}
52
52
  .timeline-item{position:relative;display:grid;grid-template-columns:28px minmax(0,1fr);gap:12px;padding:0 0 18px}
53
- .timeline-mark{position:relative;z-index:1;display:grid;place-items:center;width:28px;height:28px;border-radius:50%;background:var(--surface-2);border:1px solid var(--line-2);color:var(--ink-3)}
53
+ .timeline-mark{position:relative;z-index:var(--z-raised);display:grid;place-items:center;width:28px;height:28px;border-radius:50%;background:var(--surface-2);border:1px solid var(--line-2);color:var(--ink-3)}
54
54
  .kind-decision .timeline-mark{color:var(--ok);border-color:var(--ok-soft);background:var(--ok-soft)}
55
55
  .kind-milestone .timeline-mark{color:var(--accent);border-color:var(--accent-soft);background:var(--accent-soft)}
56
56
  .kind-run .timeline-mark{color:var(--info);border-color:var(--info-soft);background:var(--info-soft)}
@@ -29,7 +29,7 @@ export const SETTINGS_STYLES = `
29
29
  .settings-receipt{white-space:pre-wrap;overflow-wrap:anywhere}
30
30
  .settings-error{color:var(--bad)!important}
31
31
  .settings-observation{max-height:260px;overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;font-size:var(--fs-xs)}
32
- .settings-search{position:sticky;top:0;z-index:1;padding:10px 0;background:var(--canvas)}
32
+ .settings-search{position:sticky;top:var(--header-h);z-index:var(--z-raised);padding:10px 0;background:var(--canvas)}
33
33
  .settings-search input{width:100%;max-width:520px}
34
34
  #settings-status:empty,#browser-receipt:empty{display:none}
35
35
  .mono-line{overflow-wrap:anywhere}
@@ -1,26 +1,38 @@
1
1
  /*
2
- * SIDEBAR VIEW — the task index: brand and sync state, search, attention
3
- * pills, status filter tabs, grouped task rows, the catalog pager and the
4
- * footer buttons. Region sizing lives in layout/workspace.
2
+ * SIDEBAR VIEW — the task index: title and sync state, search, attention
3
+ * pills, status filter tabs, grouped task rows and the catalog pager. The
4
+ * brand mark is shared with the global rail. Region sizing lives in
5
+ * layout/workspace.
5
6
  */
6
7
  export const SIDEBAR_STYLES = `
7
- /* Brand and sync state */
8
- .brand-mark{width:28px;height:28px;border-radius:8px;background:var(--accent);color:var(--accent-ink);font-size:15px;font-weight:700;line-height:1}
8
+ /* Brand mark (global rail, management top bar) and sync state */
9
+ .brand-mark{width:28px;height:28px;border-radius:7px;background:var(--ink);color:var(--canvas);overflow:hidden}
10
+ .brand-glyph{display:block;width:100%;height:100%}
11
+ .brand-dot{fill:var(--accent)}
9
12
  .brand-name{font-size:var(--fs-lg);font-weight:650;letter-spacing:-.02em}
10
13
  .sync{display:inline-flex;align-items:center;gap:6px;height:24px;padding:0 8px;border-radius:var(--r-pill);background:var(--surface-3);color:var(--ink-3);font-size:var(--fs-2xs);font-variant-numeric:tabular-nums}
11
14
  .sync i{width:6px;height:6px;border-radius:50%;background:var(--ink-4)}
12
15
  .sync[data-state="ok"] i{background:var(--ok);box-shadow:0 0 0 3px var(--ok-soft)}
13
- .sync[data-state="syncing"] i{background:var(--info);animation:blink 1s ease-in-out infinite}
16
+ .sync[data-state="syncing"] i{background:var(--info);animation:m-blink 1s ease-in-out infinite}
14
17
  .sync[data-state="error"] i{background:var(--bad);box-shadow:0 0 0 3px var(--bad-soft)}
15
18
  .sync[data-state="error"]{color:var(--bad)}
16
- @keyframes blink{50%{opacity:.35}}
17
19
 
18
- /* Search and attention filters */
19
- .search-field{position:relative;display:flex;align-items:center;flex:none;margin:12px 12px 0}
20
- .search-field>.icon{position:absolute;left:10px;color:var(--ink-4);pointer-events:none}
21
- .search-field input{height:34px;padding:0 34px 0 32px;border-radius:var(--r-md);background:var(--surface-2)}
20
+ /* Tools block: create, search, category and attention, on one 8px rhythm */
21
+ .side-tools{flex:none;display:grid;gap:8px;padding:12px 12px 4px}
22
+ .side-create{width:100%;height:34px;border-radius:var(--r-md);box-shadow:var(--shadow-1)}
23
+ .side-create .icon{width:16px;height:16px;stroke-width:2.2}
24
+ .side-search{display:flex;align-items:center;gap:6px;min-width:0}
25
+ .search-field{position:relative;display:flex;align-items:center;flex:1;min-width:0}
26
+ .search-field>.icon{position:absolute;left:10px;width:15px;height:15px;color:var(--ink-4);pointer-events:none}
27
+ .search-field input{height:34px;padding:0 32px 0 32px;border-radius:var(--r-md);background:var(--surface-2)}
22
28
  .search-field input::-webkit-search-cancel-button{display:none}
23
- .search-field kbd{position:absolute;right:8px}
29
+ .search-field kbd{position:absolute;right:8px;pointer-events:none}
30
+ .search-field:focus-within kbd{opacity:0}
31
+ .side-search-body{width:34px;height:34px;border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface-2)}
32
+ .side-search-body:hover:not(:disabled){border-color:var(--line-3)}
33
+ .source-seg{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));width:100%}
34
+ .source-seg .seg-btn{justify-content:center;min-width:0;overflow:hidden;text-overflow:ellipsis}
35
+ .attention-bar:empty{display:none}
24
36
  .attention-list{display:flex;flex-wrap:wrap;gap:6px}
25
37
  .attention-pill{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 9px;border:1px solid transparent;border-radius:var(--r-pill);background:var(--tone-soft);color:var(--tone);font-size:var(--fs-xs);font-weight:500}
26
38
  .attention-pill b{font-weight:700;font-variant-numeric:tabular-nums}
@@ -59,17 +71,10 @@ export const SIDEBAR_STYLES = `
59
71
  .list-empty{display:grid;justify-items:center;gap:8px;padding:36px 16px;color:var(--ink-4);font-size:var(--fs-sm);text-align:center}
60
72
  .list-empty.is-error{color:var(--bad)}
61
73
 
62
- /* Catalog pager and footer */
74
+ /* Catalog pager */
63
75
  .pager-btn{height:28px;padding:0 10px;border:1px solid var(--line-2);border-radius:var(--r-sm);background:transparent;color:var(--ink-2);font-size:var(--fs-xs)}
64
76
  .pager-btn:hover:not(:disabled){border-color:var(--line-3);color:var(--ink)}
65
77
  .pager-btn:disabled{opacity:.4}
66
78
  .pager-count{grid-column:2;text-align:center;color:var(--ink-4);font-size:var(--fs-2xs);font-variant-numeric:tabular-nums}
67
79
  .pager-clear{height:28px}
68
- .foot-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 8px;border:1px solid var(--line-2);border-radius:var(--r-sm);background:transparent;color:var(--ink-2);font-size:var(--fs-xs);font-weight:500;min-width:0}
69
- .foot-btn span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
70
- .foot-btn:hover{color:var(--ink);border-color:var(--line-3);background:var(--surface-3)}
71
- .foot-btn[aria-pressed="true"]{color:var(--accent);border-color:var(--accent-line);background:var(--accent-soft)}
72
- .foot-btn kbd{margin-left:2px}
73
- .side-foot .icon-btn{margin-left:auto}
74
- .side-foot .icon-btn+.icon-btn{margin-left:0}
75
80
  `;
@@ -1,29 +1,23 @@
1
1
  /*
2
- * TASK VIEW — the task page frame and its Overview tab: the sticky header and
3
- * section tabs, the hero, the "now" banner, input requests that need the
2
+ * TASK VIEW — the task page frame and its Overview tab: the sticky section
3
+ * tabs, the hero, the "now" banner, input requests that need the
4
4
  * user, decisions and planning. Rows inside the other tabs live in
5
5
  * views/records and views/delivery.
6
6
  */
7
7
  export const TASK_STYLES = `
8
- /* Sticky header and tab strip: both bleed through the page gutter and frost
9
- the content scrolling beneath them. */
10
- .task-header,.tabs-wrap{position:sticky;margin:0 calc(-1 * var(--gutter));padding:0 var(--gutter);background:color-mix(in srgb,var(--canvas) 88%,transparent);backdrop-filter:saturate(1.4) blur(10px);-webkit-backdrop-filter:saturate(1.4) blur(10px)}
11
- .task-header{top:0;z-index:10}
12
- .task-bar{display:flex;align-items:center;gap:6px;height:var(--header-h)}
13
- .back-btn{display:none}
14
- .crumbs{display:flex;align-items:center;gap:6px;min-width:0;font-size:var(--fs-sm)}
15
- .crumb{padding:3px 6px;border:0;border-radius:var(--r-xs);background:transparent;color:var(--ink-3)}
16
- .crumb:hover{color:var(--ink);background:var(--surface-3)}
17
- .crumb-sep{color:var(--ink-4)}
18
- .crumb-current{color:var(--ink-2);font-size:var(--fs-xs)}
8
+ /* Section tabs: sticky under the top bar, bleeding through the page gutter
9
+ and frosting the content scrolling beneath them. */
10
+ .tabs-wrap{position:sticky;margin:0 calc(-1 * var(--gutter));padding:0 var(--gutter);background:var(--canvas)}
19
11
  .dock-toggle{height:30px}
20
- .task-hero{padding:14px 0 18px}
12
+ .task-bar-sep{width:1px;height:18px;margin:0 2px;background:var(--line-2)}
13
+ .operator-toggle[aria-pressed="true"]{background:var(--accent-soft);color:var(--accent)}
14
+ .task-hero{padding:28px 0 18px}
21
15
  .task-title{font-size:var(--fs-2xl);font-weight:650;letter-spacing:-.025em;line-height:1.25;overflow-wrap:anywhere}
22
16
  .task-meta{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:12px;color:var(--ink-3);font-size:var(--fs-xs)}
23
17
  .task-meta:empty{display:none}
24
18
  .meta-item{display:inline-flex;align-items:center;gap:5px}
25
19
  .meta-item .when{font-size:inherit}
26
- .tabs-wrap{top:var(--header-h);z-index:9;border-bottom:1px solid var(--line)}
20
+ .tabs-wrap{top:var(--header-h);z-index:calc(var(--z-sticky) - 1);border-bottom:1px solid var(--line)}
27
21
  .tabs{gap:4px}
28
22
  .tab{position:relative;display:inline-flex;align-items:center;gap:7px;flex:none;height:42px;padding:0 10px;border:0;background:transparent;color:var(--ink-3);font-size:var(--fs-sm);font-weight:500}
29
23
  .tab:hover{color:var(--ink)}
@@ -18,7 +18,7 @@ export const TERMINAL_STYLES = `
18
18
  .target-chip .dot{width:7px;height:7px;box-shadow:none}
19
19
  .conn{display:inline-flex;align-items:center;gap:6px;flex:none;color:rgba(255,255,255,.6);font-size:var(--fs-xs);font-weight:500}
20
20
  .conn i{width:7px;height:7px;border-radius:50%;background:rgba(255,255,255,.3)}
21
- .conn[data-state="connecting"] i{background:var(--warn);animation:blink 1s infinite}
21
+ .conn[data-state="connecting"] i{background:var(--warn);animation:m-blink 1s infinite}
22
22
  .conn[data-state="writable"] i{background:var(--chrome-ok);box-shadow:0 0 0 3px rgba(79,209,139,.2)}
23
23
  .conn[data-state="readonly"] i{background:var(--chrome-info)}
24
24
  .conn[data-state="error"] i{background:var(--chrome-bad)}