@njeybe/nativ 2.2.0 → 2.3.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 (138) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/README.md +15 -0
  3. package/dist/server/studio-ui/document.d.ts +3 -0
  4. package/dist/server/studio-ui/document.js +22 -0
  5. package/dist/server/studio-ui/pages/benchmarks/index.d.ts +2 -0
  6. package/dist/server/studio-ui/pages/benchmarks/index.js +11 -0
  7. package/dist/server/studio-ui/pages/benchmarks/script.d.ts +1 -0
  8. package/dist/server/studio-ui/pages/benchmarks/script.js +104 -0
  9. package/dist/server/studio-ui/pages/benchmarks/styles.d.ts +1 -0
  10. package/dist/server/studio-ui/pages/benchmarks/styles.js +30 -0
  11. package/dist/server/studio-ui/pages/database/browser.d.ts +1 -0
  12. package/dist/server/studio-ui/pages/database/browser.js +326 -0
  13. package/dist/server/studio-ui/pages/database/connection.d.ts +1 -0
  14. package/dist/server/studio-ui/pages/database/connection.js +158 -0
  15. package/dist/server/studio-ui/pages/database/data-shell.d.ts +1 -0
  16. package/dist/server/studio-ui/pages/database/data-shell.js +165 -0
  17. package/dist/server/studio-ui/pages/database/drift.d.ts +1 -0
  18. package/dist/server/studio-ui/pages/database/drift.js +301 -0
  19. package/dist/server/studio-ui/pages/database/events.d.ts +1 -0
  20. package/dist/server/studio-ui/pages/database/events.js +231 -0
  21. package/dist/server/studio-ui/pages/database/explorer.d.ts +1 -0
  22. package/dist/server/studio-ui/pages/database/explorer.js +183 -0
  23. package/dist/server/studio-ui/pages/database/index.d.ts +2 -0
  24. package/dist/server/studio-ui/pages/database/index.js +28 -0
  25. package/dist/server/studio-ui/pages/database/markup.d.ts +1 -0
  26. package/dist/server/studio-ui/pages/database/markup.js +32 -0
  27. package/dist/server/studio-ui/pages/database/state.d.ts +2 -0
  28. package/dist/server/studio-ui/pages/database/state.js +57 -0
  29. package/dist/server/studio-ui/pages/database/styles.d.ts +1 -0
  30. package/dist/server/studio-ui/pages/database/styles.js +118 -0
  31. package/dist/server/studio-ui/pages/flow/index.d.ts +2 -0
  32. package/dist/server/studio-ui/pages/flow/index.js +11 -0
  33. package/dist/server/studio-ui/pages/flow/layout.d.ts +1 -0
  34. package/dist/server/studio-ui/pages/flow/layout.js +105 -0
  35. package/dist/server/studio-ui/pages/flow/plan-view.d.ts +1 -0
  36. package/dist/server/studio-ui/pages/flow/plan-view.js +67 -0
  37. package/dist/server/studio-ui/pages/flow/script.d.ts +1 -0
  38. package/dist/server/studio-ui/pages/flow/script.js +61 -0
  39. package/dist/server/studio-ui/pages/flow/styles.d.ts +1 -0
  40. package/dist/server/studio-ui/pages/flow/styles.js +59 -0
  41. package/dist/server/studio-ui/pages/flow/timeline-model.d.ts +1 -0
  42. package/dist/server/studio-ui/pages/flow/timeline-model.js +95 -0
  43. package/dist/server/studio-ui/pages/flow/timeline-view.d.ts +1 -0
  44. package/dist/server/studio-ui/pages/flow/timeline-view.js +92 -0
  45. package/dist/server/studio-ui/pages/home/index.d.ts +2 -0
  46. package/dist/server/studio-ui/pages/home/index.js +11 -0
  47. package/dist/server/studio-ui/pages/home/script.d.ts +1 -0
  48. package/dist/server/studio-ui/pages/home/script.js +160 -0
  49. package/dist/server/studio-ui/pages/home/styles.d.ts +1 -0
  50. package/dist/server/studio-ui/pages/home/styles.js +48 -0
  51. package/dist/server/studio-ui/pages/index.d.ts +2 -0
  52. package/dist/server/studio-ui/pages/index.js +17 -0
  53. package/dist/server/studio-ui/pages/tasks/index.d.ts +2 -0
  54. package/dist/server/studio-ui/pages/tasks/index.js +11 -0
  55. package/dist/server/studio-ui/pages/tasks/script.d.ts +1 -0
  56. package/dist/server/studio-ui/pages/tasks/script.js +96 -0
  57. package/dist/server/studio-ui/pages/tasks/styles.d.ts +1 -0
  58. package/dist/server/studio-ui/pages/tasks/styles.js +37 -0
  59. package/dist/server/studio-ui/pages/team/index.d.ts +2 -0
  60. package/dist/server/studio-ui/pages/team/index.js +11 -0
  61. package/dist/server/studio-ui/pages/team/script.d.ts +1 -0
  62. package/dist/server/studio-ui/pages/team/script.js +112 -0
  63. package/dist/server/studio-ui/pages/team/styles.d.ts +1 -0
  64. package/dist/server/studio-ui/pages/team/styles.js +22 -0
  65. package/dist/server/studio-ui/pages/types.d.ts +13 -0
  66. package/dist/server/studio-ui/pages/types.js +1 -0
  67. package/dist/server/studio-ui/pages/worktrees/index.d.ts +2 -0
  68. package/dist/server/studio-ui/pages/worktrees/index.js +11 -0
  69. package/dist/server/studio-ui/pages/worktrees/script.d.ts +1 -0
  70. package/dist/server/studio-ui/pages/worktrees/script.js +104 -0
  71. package/dist/server/studio-ui/pages/worktrees/styles.d.ts +1 -0
  72. package/dist/server/studio-ui/pages/worktrees/styles.js +15 -0
  73. package/dist/server/studio-ui/shell/actions.d.ts +1 -0
  74. package/dist/server/studio-ui/shell/actions.js +49 -0
  75. package/dist/server/studio-ui/shell/boot.d.ts +2 -0
  76. package/dist/server/studio-ui/shell/boot.js +13 -0
  77. package/dist/server/studio-ui/shell/console.d.ts +1 -0
  78. package/dist/server/studio-ui/shell/console.js +194 -0
  79. package/dist/server/studio-ui/shell/core.d.ts +1 -0
  80. package/dist/server/studio-ui/shell/core.js +50 -0
  81. package/dist/server/studio-ui/shell/detail-view.d.ts +1 -0
  82. package/dist/server/studio-ui/shell/detail-view.js +80 -0
  83. package/dist/server/studio-ui/shell/detail.d.ts +1 -0
  84. package/dist/server/studio-ui/shell/detail.js +83 -0
  85. package/dist/server/studio-ui/shell/dispatch.d.ts +1 -0
  86. package/dist/server/studio-ui/shell/dispatch.js +156 -0
  87. package/dist/server/studio-ui/shell/events-tools.d.ts +1 -0
  88. package/dist/server/studio-ui/shell/events-tools.js +94 -0
  89. package/dist/server/studio-ui/shell/format.d.ts +1 -0
  90. package/dist/server/studio-ui/shell/format.js +151 -0
  91. package/dist/server/studio-ui/shell/icons.d.ts +2 -0
  92. package/dist/server/studio-ui/shell/icons.js +20 -0
  93. package/dist/server/studio-ui/shell/markup-head.d.ts +1 -0
  94. package/dist/server/studio-ui/shell/markup-head.js +43 -0
  95. package/dist/server/studio-ui/shell/markup-panels.d.ts +2 -0
  96. package/dist/server/studio-ui/shell/markup-panels.js +7 -0
  97. package/dist/server/studio-ui/shell/markup-tools.d.ts +1 -0
  98. package/dist/server/studio-ui/shell/markup-tools.js +222 -0
  99. package/dist/server/studio-ui/shell/model.d.ts +1 -0
  100. package/dist/server/studio-ui/shell/model.js +192 -0
  101. package/dist/server/studio-ui/shell/paint.d.ts +1 -0
  102. package/dist/server/studio-ui/shell/paint.js +154 -0
  103. package/dist/server/studio-ui/shell/palette-view.d.ts +1 -0
  104. package/dist/server/studio-ui/shell/palette-view.js +60 -0
  105. package/dist/server/studio-ui/shell/palette.d.ts +1 -0
  106. package/dist/server/studio-ui/shell/palette.js +80 -0
  107. package/dist/server/studio-ui/shell/pipeline-state.d.ts +1 -0
  108. package/dist/server/studio-ui/shell/pipeline-state.js +152 -0
  109. package/dist/server/studio-ui/shell/proposals.d.ts +1 -0
  110. package/dist/server/studio-ui/shell/proposals.js +197 -0
  111. package/dist/server/studio-ui/shell/pure.d.ts +3 -0
  112. package/dist/server/studio-ui/shell/pure.js +9 -0
  113. package/dist/server/studio-ui/shell/router.d.ts +1 -0
  114. package/dist/server/studio-ui/shell/router.js +95 -0
  115. package/dist/server/studio-ui/shell/sidebar-view.d.ts +1 -0
  116. package/dist/server/studio-ui/shell/sidebar-view.js +38 -0
  117. package/dist/server/studio-ui/shell/sync.d.ts +1 -0
  118. package/dist/server/studio-ui/shell/sync.js +120 -0
  119. package/dist/server/studio-ui/shell/toasts-format.d.ts +1 -0
  120. package/dist/server/studio-ui/shell/toasts-format.js +89 -0
  121. package/dist/server/studio-ui/shell/triage.d.ts +1 -0
  122. package/dist/server/studio-ui/shell/triage.js +210 -0
  123. package/dist/server/studio-ui/styles/console.d.ts +1 -0
  124. package/dist/server/studio-ui/styles/console.js +83 -0
  125. package/dist/server/studio-ui/styles/dialogs.d.ts +1 -0
  126. package/dist/server/studio-ui/styles/dialogs.js +118 -0
  127. package/dist/server/studio-ui/styles/responsive.d.ts +1 -0
  128. package/dist/server/studio-ui/styles/responsive.js +28 -0
  129. package/dist/server/studio-ui/styles/shell.d.ts +1 -0
  130. package/dist/server/studio-ui/styles/shell.js +117 -0
  131. package/dist/server/studio-ui/styles/strategist.d.ts +1 -0
  132. package/dist/server/studio-ui/styles/strategist.js +77 -0
  133. package/dist/server/studio-ui/styles/tokens-base.d.ts +1 -0
  134. package/dist/server/studio-ui/styles/tokens-base.js +131 -0
  135. package/dist/server/studio-ui.d.ts +1 -10
  136. package/dist/server/studio-ui.js +63 -5314
  137. package/package.json +2 -2
  138. package/plugin/.claude-plugin/plugin.json +1 -1
@@ -0,0 +1,83 @@
1
+ // Runner console drawer and proposal review styles.
2
+ export const consoleCss = String.raw `/* Live runner console drawer */
3
+ body.has-console { padding-bottom: min(58vh, 520px); }
4
+ body.has-console-min { padding-bottom: 56px; }
5
+ #runner-console-drawer { position: fixed; inset: auto 0 0 var(--sidebar-w); z-index: 60; display: flex; flex-direction: column; max-height: min(58vh, 520px); background: var(--term-bg); color: var(--term-text); border-top: 1px solid var(--chip-border); box-shadow: var(--shadow-float); animation: rc-slide-up .28s cubic-bezier(.2, .8, .2, 1); }
6
+ #runner-console-drawer[hidden] { display: none; }
7
+ #runner-console-drawer.is-min .rc-body, #runner-console-drawer.is-min .rc-foot { display: none; }
8
+ @keyframes rc-slide-up { from { transform: translateY(100%); } to { transform: translateY(0); } }
9
+ .rc-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 8px 14px; border-bottom: 1px solid var(--term-line); }
10
+ .rc-task { font-family: var(--mono); font-size: 12.5px; font-weight: 600; }
11
+ .rc-title { font-size: 12.5px; color: var(--term-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 34ch; }
12
+ .rc-steps { display: flex; align-items: center; gap: 6px; margin: 0 0 0 auto; padding: 0; list-style: none; }
13
+ .rc-step { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px; font-size: 11px; color: var(--term-muted); border: 1px solid var(--term-line); border-radius: var(--r-control); }
14
+ .rc-step.is-done { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 55%, transparent); }
15
+ .rc-step.is-active { color: var(--term-text); background: color-mix(in srgb, var(--primary) 32%, transparent); border-color: var(--primary); }
16
+ .rc-step.is-failed { color: var(--term-text); background: color-mix(in srgb, var(--danger) 32%, transparent); border-color: var(--danger); }
17
+ .rc-controls { display: flex; gap: 6px; flex: none; }
18
+ .rc-btn { padding: 5px 9px; font: 500 11px/1 var(--font); color: var(--term-text); background: transparent; border: 1px solid var(--term-line); border-radius: var(--r-control); cursor: pointer; }
19
+ .rc-btn:hover { background: color-mix(in srgb, var(--term-muted) 22%, transparent); }
20
+ .rc-btn:disabled { opacity: .45; cursor: not-allowed; }
21
+ .rc-btn[aria-pressed="true"] { border-color: var(--primary); background: color-mix(in srgb, var(--primary) 34%, transparent); }
22
+ .rc-btn.danger { color: var(--term-text); border-color: var(--danger); }
23
+ .rc-btn.danger:hover { background: color-mix(in srgb, var(--danger) 30%, transparent); }
24
+ .rc-btn:focus-visible { outline: 2px solid var(--term-text); outline-offset: 2px; }
25
+ .rc-body { flex: 1 1 auto; min-height: 120px; margin: 0; padding: 10px 14px; overflow: auto; font-family: var(--mono); font-size: 12.5px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; }
26
+ .rc-body:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
27
+ .rc-empty { color: var(--term-muted); }
28
+ .rc-fg-muted { color: var(--term-muted); }
29
+ .rc-fg-warn { color: var(--warn); }
30
+ .rc-fg-ok { color: var(--ok); }
31
+ .rc-fg-info { color: var(--accent); }
32
+ .rc-fg-danger { color: color-mix(in srgb, var(--danger) 55%, #fff); }
33
+ .rc-bold { font-weight: 700; }
34
+ .rc-foot { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; padding: 7px 14px; font-size: 11.5px; color: var(--term-muted); border-top: 1px solid var(--term-line); }
35
+ .rc-foot strong { font-family: var(--mono); font-weight: 600; color: var(--term-text); }
36
+ #runner-console-drawer.is-min .rc-tabs { display: none; }
37
+ .rc-tabs { display: flex; gap: 2px; padding: 0 14px; border-bottom: 1px solid var(--term-line); }
38
+ .rc-tab { display: inline-flex; align-items: center; gap: 6px; padding: 8px 10px; font: 500 12px/1 var(--font); color: var(--term-muted); background: none; border: none; border-bottom: 2px solid transparent; margin-bottom: -1px; cursor: pointer; }
39
+ .rc-tab:hover { color: var(--term-text); }
40
+ .rc-tab[aria-selected="true"] { color: var(--term-text); border-bottom-color: var(--primary); }
41
+ .rc-tab:focus-visible { outline: 2px solid var(--term-text); outline-offset: -2px; }
42
+ .rc-tab .rc-count { min-width: 18px; padding: 0 5px; font-family: var(--mono); font-size: 10.5px; line-height: 16px; text-align: center; color: var(--term-text); background: color-mix(in srgb, var(--term-muted) 22%, transparent); border-radius: var(--r-control); }
43
+ .rc-diff { flex: 1 1 auto; min-height: 120px; display: flex; flex-direction: column; overflow: hidden; }
44
+ #runner-console-drawer.is-min .rc-diff { display: none; }
45
+ .rc-diff-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 8px 14px; font-size: 11.5px; color: var(--term-muted); border-bottom: 1px solid var(--term-line); }
46
+ .rc-diff-bar code { color: var(--term-text); font-family: var(--mono); }
47
+ .rc-diff-bar .rc-btn { margin-left: auto; }
48
+ .rc-files { display: flex; flex-wrap: wrap; gap: 4px; margin: 0; padding: 8px 14px 0; list-style: none; }
49
+ .rc-files li { padding: 1px 7px; font-family: var(--mono); font-size: 11px; color: var(--term-text); border: 1px solid var(--term-line); border-radius: var(--r-control); max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
50
+ .rc-diff-body { flex: 1 1 auto; margin: 0; padding: 10px 14px; overflow: auto; font-family: var(--mono); font-size: 12px; line-height: 1.5; white-space: pre; }
51
+ .rc-diff-body:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
52
+ /* Console tab 3: self-healing proposal review (dark drawer surface). */
53
+ .rc-tab .rc-count.is-proposal { color: #fff; background: var(--proposal); }
54
+ .rc-heal { flex: 1 1 auto; min-height: 120px; overflow: auto; padding: 12px 14px 14px; font-size: 13px; line-height: 1.5; }
55
+ #runner-console-drawer.is-min .rc-heal { display: none; }
56
+ .rc-heal:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
57
+ .heal-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
58
+ .heal-head h3 { margin: 0; font-size: 13.5px; font-weight: 600; color: var(--term-text); }
59
+ .heal-tag { font: 500 11px/18px var(--mono); padding: 0 7px; color: var(--term-text); border: 1px solid var(--term-line); border-radius: var(--r-control); }
60
+ .heal-verdict { display: inline-flex; align-items: center; gap: 5px; font: 600 11.5px/20px var(--font); padding: 0 8px; border-radius: var(--r-control); }
61
+ .heal-verdict.pass { color: var(--ok); background: color-mix(in srgb, var(--ok) 16%, transparent); border: 1px solid color-mix(in srgb, var(--ok) 45%, transparent); }
62
+ .heal-verdict.fail { color: color-mix(in srgb, var(--danger) 55%, #fff); background: color-mix(in srgb, var(--danger) 18%, transparent); border: 1px solid color-mix(in srgb, var(--danger) 45%, transparent); }
63
+ .heal-diag { margin: 0 0 10px; color: var(--term-muted); overflow-wrap: anywhere; }
64
+ .heal-diag strong { color: var(--term-text); font-weight: 600; }
65
+ .heal-grid { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 12px; }
66
+ .heal-section h4 { margin: 0 0 6px; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--term-muted); }
67
+ .heal-patch { margin: 0; padding: 8px 10px; font-family: var(--mono); font-size: 12px; line-height: 1.55; white-space: pre-wrap; overflow-wrap: anywhere; background: rgb(148 163 184 / 0.08); border: 1px solid var(--term-line); border-radius: var(--r-control); }
68
+ .heal-checks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
69
+ .heal-checks li { display: flex; gap: 7px; align-items: flex-start; color: var(--term-muted); font-size: 12.5px; }
70
+ .heal-checks li b { color: var(--term-text); font-family: var(--mono); font-weight: 500; }
71
+ .heal-checks .ok { color: var(--ok); }
72
+ .heal-checks .bad { color: color-mix(in srgb, var(--danger) 55%, #fff); }
73
+ /* Pinned to the drawer's bottom edge so the decision never needs a scroll. */
74
+ .heal-actions { position: sticky; bottom: -14px; display: flex; justify-content: flex-end; gap: 8px; flex-wrap: wrap; margin: 12px -14px -14px; padding: 10px 14px; background: var(--term-bg); border-top: 1px solid var(--term-line); }
75
+ .rc-btn.approve { color: #fff; background: var(--success); border-color: var(--success); }
76
+ .rc-btn.approve:hover:not(:disabled) { background: color-mix(in srgb, var(--success) 88%, #000); }
77
+ .rc-btn.reject { color: color-mix(in srgb, var(--danger) 55%, #fff); border-color: color-mix(in srgb, var(--danger) 50%, transparent); }
78
+ .rc-btn.reject:hover:not(:disabled) { background: color-mix(in srgb, var(--danger) 16%, transparent); }
79
+ .heal-result { margin: 0 0 10px; padding: 8px 10px; color: var(--ok); border: 1px solid color-mix(in srgb, var(--ok) 45%, transparent); border-radius: var(--r-control); }
80
+ .heal-result.is-error { color: color-mix(in srgb, var(--danger) 55%, #fff); border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
81
+ .heal-skel { height: 12px; margin: 8px 0; border-radius: 4px; background: var(--term-line); animation: blink 1.4s ease-in-out infinite; }
82
+ @media (max-width: 768px) { .heal-grid { grid-template-columns: 1fr; } }
83
+ `;
@@ -0,0 +1 @@
1
+ export declare const dialogsCss: string;
@@ -0,0 +1,118 @@
1
+ // Toasts, dialogs, dispatch modal and small shared widgets.
2
+ export const dialogsCss = String.raw `/* Toasts */
3
+ /* Bottom-right so notifications never cover the sticky header and navigation. */
4
+ .toast-host { position: fixed; right: 16px; bottom: 16px; z-index: 100; display: flex; flex-direction: column; gap: 8px; width: min(440px, calc(100vw - 32px)); pointer-events: none; }
5
+ .toast { pointer-events: auto; display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; font-size: 13.5px; background: var(--surface); border: 1px solid var(--border); border-left: 3px solid var(--danger); border-radius: var(--r-card); box-shadow: var(--shadow-float); animation: toast-in .18s ease-out; }
6
+ .toast.ok { border-left-color: var(--success); }
7
+ .toast .t-body { flex: 1; min-width: 0; overflow-wrap: anywhere; }
8
+ .toast .t-hint { color: var(--muted); font-size: 12.5px; }
9
+ .toast button { background: none; border: none; color: var(--muted); cursor: pointer; font-size: 16px; line-height: 1; }
10
+ @keyframes toast-in { from { opacity: 0; transform: translateY(6px); } }
11
+
12
+ /* Dialogs */
13
+ dialog { border: none; padding: 0; background: transparent; color: var(--text); width: min(640px, calc(100vw - 32px)); max-height: calc(100vh - 32px); }
14
+ dialog.narrow { width: min(460px, calc(100vw - 32px)); }
15
+ dialog::backdrop { background: rgb(10 10 20 / 0.4); backdrop-filter: blur(2px); }
16
+ .modal { padding: 22px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-card); box-shadow: var(--shadow-float); }
17
+ .modal h2 { margin: 0 0 4px; font-size: 18px; font-weight: 600; }
18
+ .modal .lead { color: var(--muted); margin: 0 0 16px; font-size: 14px; line-height: 1.55; }
19
+ .field { margin-bottom: 16px; }
20
+ .field label { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13.5px; margin-bottom: 6px; }
21
+ .field-row { display: flex; gap: 8px; }
22
+ .field-row .input { flex: 1; font-family: var(--mono); font-size: 12.5px; min-width: 0; }
23
+ .field-row + .field-row { margin-top: 8px; }
24
+ .field-row select.input { font-family: var(--font); }
25
+ .param-grid { display: grid; grid-template-columns: 140px 1fr 96px; gap: 8px; margin-top: 8px; }
26
+ .param-grid .input { font-family: var(--mono); font-size: 12.5px; min-width: 0; }
27
+ .param-grid select.input { font-family: var(--font); }
28
+ .param-grid .span-2 { grid-column: span 2; }
29
+ .field .current { display: flex; align-items: center; gap: 8px; margin-top: 6px; font-size: 12.5px; color: var(--muted); min-width: 0; }
30
+ .field .current code { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
31
+ .field-error { margin: 6px 0 0; font-size: 13px; color: var(--danger); }
32
+ .result { margin-top: 6px; font-size: 13px; }
33
+ .result.ok { color: var(--success); } .result.err { color: var(--danger); }
34
+ .modal-foot { display: flex; justify-content: flex-end; gap: 8px; margin-top: 8px; }
35
+ .modal-prod-guard { border-color: var(--danger-line); }
36
+ .challenge-badge { display: inline-flex; align-items: center; gap: 6px; padding: 1px 8px; border-radius: var(--r-control); font-size: 11px; font-weight: 700; color: var(--danger); background: var(--danger-bg); border: 1px solid var(--danger-line); margin-bottom: 12px; }
37
+ .challenge-box { padding: 14px; border-radius: var(--r-control); border: 1px solid var(--danger-line); background: var(--danger-bg); margin: 12px 0; }
38
+ .challenge-box p { margin: 0 0 8px; font-size: 13.5px; line-height: 1.5; }
39
+ .challenge-box code { color: var(--danger); font-weight: 700; font-size: 13px; }
40
+ .record-form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; max-height: 60vh; overflow-y: auto; padding-right: 4px; margin-bottom: 16px; }
41
+ .record-form-grid .field-full { grid-column: 1 / -1; }
42
+ .record-form-grid label { display: block; font-size: 12.5px; font-weight: 600; margin-bottom: 4px; color: var(--muted); }
43
+ .record-form-grid label b { color: var(--text); font-family: var(--mono); }
44
+ .record-form-grid .input { width: 100%; }
45
+ .record-form-grid textarea.input { min-height: 64px; font-family: var(--mono); font-size: 12px; }
46
+
47
+ /* Task chips used by the dispatch dialog */
48
+ .tcard-id { display: inline-flex; align-items: center; gap: 5px; min-width: 0; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
49
+ .file-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 4px; }
50
+ .file { max-width: 100%; padding: 1px 7px; font-family: var(--mono); font-size: 11.5px; background: var(--chip); border: 1px solid var(--chip-border); border-radius: var(--r-control); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
51
+ .cmd { flex: 1; min-width: 0; font-size: 12.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
52
+ .cmd-label { color: var(--text); font-weight: 600; font-size: 12px; }
53
+
54
+ /* Intelligent dispatch modal */
55
+ .dispatch-task { display: flex; flex-direction: column; gap: 8px; padding: 12px 14px; margin-bottom: 16px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--r-control); }
56
+ .dispatch-task-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
57
+ .dispatch-task h3 { margin: 0; font-size: 14.5px; font-weight: 600; line-height: 1.45; }
58
+ .dispatch-task .cmd { flex: none; white-space: normal; overflow-wrap: anywhere; }
59
+ textarea.cmd-preview { min-height: 92px; font-family: var(--mono); font-size: 12px; background: var(--bg); }
60
+ .field-hint { margin: 6px 0 0; font-size: 12.5px; color: var(--muted); }
61
+ .switches { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
62
+ .switch { display: flex; align-items: flex-start; gap: 10px; cursor: pointer; }
63
+ .switch input { position: absolute; opacity: 0; width: 1px; height: 1px; }
64
+ .switch-track { position: relative; flex: none; width: 32px; height: 18px; margin-top: 1px; background: var(--chip-border); border-radius: 999px; transition: background .15s; }
65
+ .switch-track::after { content: ""; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; background: var(--surface); border-radius: 50%; box-shadow: var(--shadow); transition: transform .15s; }
66
+ .switch input:checked + .switch-track { background: var(--primary); }
67
+ .switch input:checked + .switch-track::after { transform: translateX(14px); }
68
+ .switch input:focus-visible + .switch-track { outline: 2px solid var(--primary); outline-offset: 2px; }
69
+ .switch input:disabled + .switch-track { opacity: .45; }
70
+ /* Dual-mode dispatch: engine cards + thinking budget chips (radio groups, keyboard-native). */
71
+ .choice-group { margin: 0 0 16px; padding: 0; border: none; min-width: 0; }
72
+ .choice-group > legend { padding: 0; margin-bottom: 8px; font-size: 13px; font-weight: 600; }
73
+ .engine-options { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
74
+ .engine-option { position: relative; display: flex; gap: 10px; align-items: flex-start; padding: 11px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-control); cursor: pointer; transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1); }
75
+ .engine-option:hover { border-color: var(--chip-border); }
76
+ .engine-option input, .budget-chip input { position: absolute; opacity: 0; width: 1px; height: 1px; }
77
+ .engine-option .icon { flex: none; margin-top: 2px; color: var(--muted); }
78
+ .engine-option b { display: block; font-size: 13.5px; font-weight: 600; }
79
+ .engine-option span span { display: block; font-size: 12.5px; color: var(--muted); line-height: 1.45; }
80
+ .engine-option:has(input:checked) { border-color: var(--primary); background: var(--primary-tint); box-shadow: inset 0 0 0 1px var(--primary); }
81
+ .engine-option:has(input:checked) .icon { color: var(--primary); }
82
+ .engine-option:has(input:focus-visible), .budget-chip:has(input:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
83
+ .budget-chips { display: flex; flex-wrap: wrap; gap: 6px; }
84
+ .budget-chip { position: relative; display: inline-flex; align-items: center; min-height: 32px; padding: 0 11px; font-size: 13px; background: var(--chip); border: 1px solid var(--chip-border); border-radius: var(--r-control); cursor: pointer; transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1); }
85
+ .budget-chip small { margin-left: 5px; font-family: var(--mono); font-size: 11.5px; color: var(--muted); }
86
+ .budget-chip:has(input:checked) { color: var(--primary); background: var(--primary-tint); border-color: var(--primary); }
87
+ .budget-chip:has(input:checked) small { color: var(--primary); }
88
+ @media (max-width: 768px) { .engine-options { grid-template-columns: 1fr; } }
89
+ /* Grounded spend KPI (ui_specs.md View 1, card 3). */
90
+ .cache-pill { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: 6px; row-gap: 1px; padding: 5px 9px; font-size: 12.5px; line-height: 1.4; color: var(--success); background: var(--success-bg); border: 1px solid var(--success-line); border-radius: var(--r-control); font-variant-numeric: tabular-nums; }
91
+ .cache-pill .label { white-space: nowrap; }
92
+ .cache-pill b { font-weight: 650; }
93
+ /* The savings line wraps under the rate instead of being clipped in a narrow card. */
94
+ .cache-pill .save { flex-basis: 100%; color: var(--muted); }
95
+ .tel-chips { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
96
+ .tel-chips li { display: flex; flex-direction: column; gap: 1px; min-width: 0; padding: 5px 8px; background: var(--chip); border: 1px solid var(--chip-border); border-radius: var(--r-control); }
97
+ .tel-chips span { font-size: 11.5px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
98
+ .tel-chips b { font-family: var(--mono); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
99
+ .kpi-note { margin: 0; font-size: 13px; color: var(--muted); }
100
+ .kpi-note .btn { margin-left: 6px; }
101
+ .dot-proposal { background: var(--proposal); }
102
+ /* Self-healing proposals on the kanban and in the sidebar. */
103
+ .badge-proposal { color: var(--proposal); background: var(--proposal-bg); border-color: var(--proposal-line); }
104
+ .nav-tab .count.count-proposal { color: var(--proposal); background: var(--proposal-bg); border-color: var(--proposal-line); }
105
+ .tcard.has-proposal { border-color: var(--proposal-line); box-shadow: inset 3px 0 0 var(--proposal), var(--shadow); }
106
+ .proposal-banner { display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 11px; font: 600 13px/1.4 var(--font); text-align: left; color: var(--proposal); background: var(--proposal-bg); border: 1px solid var(--proposal-line); border-radius: var(--r-control); cursor: pointer; transition: all 150ms cubic-bezier(0.4, 0, 0.2, 1); }
107
+ .proposal-banner:hover { border-color: var(--proposal); }
108
+ .proposal-banner:active { transform: scale(0.98); }
109
+ .proposal-banner:focus-visible { outline: 2px solid var(--proposal); outline-offset: 2px; }
110
+ .proposal-banner .icon { flex: none; }
111
+ .switch input:disabled ~ .switch-text { opacity: .55; }
112
+ .switch-text { display: flex; flex-direction: column; font-size: 13.5px; }
113
+ .switch-text b { font-weight: 600; }
114
+ .switch-text span { font-size: 12.5px; color: var(--muted); }
115
+ kbd { padding: 0 5px; font-family: var(--mono); font-size: 11px; color: var(--muted); background: var(--chip); border: 1px solid var(--chip-border); border-radius: 4px; }
116
+ .btn.primary kbd { color: var(--accent-fg); background: transparent; border-color: color-mix(in srgb, var(--accent-fg) 45%, transparent); }
117
+
118
+ `;
@@ -0,0 +1 @@
1
+ export declare const responsiveCss: string;
@@ -0,0 +1,28 @@
1
+ // Responsive rules for the kept pages and dialogs.
2
+ export const responsiveCss = String.raw `/* Responsive */
3
+ @media (max-width: 900px) {
4
+ #runner-console-drawer { inset: auto 0 0 0; }
5
+ .panes { grid-template-columns: 1fr; }
6
+ .summary-banner { grid-template-columns: repeat(2, minmax(0, 1fr)); }
7
+ .hero { grid-template-columns: 1fr; }
8
+ .hero-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
9
+ }
10
+ @media (max-width: 820px) {
11
+ table.grid thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
12
+ table.grid, table.grid tbody, table.grid tr, table.grid td { display: block; }
13
+ table.grid tr { padding: 10px 16px; border-bottom: 1px solid var(--border); }
14
+ table.grid tbody tr:last-child { border-bottom: none; }
15
+ table.grid td { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 4px 0; border: none; text-align: right; min-width: 0; }
16
+ table.grid td::before { content: attr(data-label); flex: none; font-size: 12px; color: var(--muted); text-align: left; }
17
+ table.grid tbody tr:hover td { background: none; }
18
+ .path, .cell-sub { max-width: 58vw; }
19
+ }
20
+ @media (max-width: 640px) {
21
+ .panel-actions, .panel-actions input.input, .panel-actions select.input { width: 100%; max-width: none; }
22
+ .param-grid { grid-template-columns: 1fr; }
23
+ .param-grid .span-2 { grid-column: auto; }
24
+ .record-form-grid { grid-template-columns: 1fr; }
25
+ .diagnostic-banner { flex-direction: column; align-items: flex-start; }
26
+ }
27
+ @media (prefers-reduced-motion: reduce) { *, *::before, *::after { animation: none !important; transition: none !important; } }
28
+ `;
@@ -0,0 +1 @@
1
+ export declare const shellCss: string;
@@ -0,0 +1,117 @@
1
+ // App shell: sidebar, top bar, page frame, status helpers, detail panel, palette.
2
+ export const shellCss = String.raw `/* Layout */
3
+ .app { display: grid; grid-template-columns: var(--sidebar-w) minmax(0, 1fr); min-height: 100vh; }
4
+ .side { border-right: 1px solid var(--line); background: var(--surface); padding: 16px 12px; display: flex; flex-direction: column; gap: 20px; position: sticky; top: 0; height: 100vh; overflow-y: auto; }
5
+ .brand { display: flex; align-items: center; gap: 10px; padding: 0 6px; }
6
+ .logo { width: 26px; height: 26px; border-radius: 7px; background: var(--accent); color: var(--accent-fg); display: grid; place-items: center; font-weight: 700; font-size: 14px; flex: none; }
7
+ .brand b { font-weight: 600; white-space: nowrap; }
8
+ .brand .ver { margin-left: auto; font: 11px var(--mono); color: var(--fg-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
9
+ .nav { display: flex; flex-direction: column; gap: 14px; }
10
+ .nav-group { display: flex; flex-direction: column; gap: 2px; }
11
+ .nav-glabel { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--fg-3); padding: 0 8px 4px; }
12
+ .nav-item { display: flex; align-items: center; gap: 10px; min-height: 32px; padding: 7px 8px; border-radius: 7px; border: 0; background: none; text-align: left; color: var(--fg-2); width: 100%; cursor: pointer; transition: background .15s, color .15s; }
13
+ .nav-item svg { width: 16px; height: 16px; flex: none; }
14
+ .nav-item:hover { background: var(--surface-2); color: var(--fg); }
15
+ .nav-item[aria-current="page"] { background: var(--accent-soft); color: var(--accent); font-weight: 500; }
16
+ .nav-badge { margin-left: auto; font: 500 11px var(--font); font-variant-numeric: tabular-nums; min-width: 20px; padding: 1px 6px; border-radius: 999px; background: var(--surface-2); color: var(--fg-2); text-align: center; }
17
+ .nav-badge.warn { background: var(--warn-soft); color: var(--warn); }
18
+ .nav-badge.run { background: var(--run-soft); color: var(--run); }
19
+ .side-foot { margin-top: auto; font-size: 12px; color: var(--fg-3); padding: 0 8px; display: flex; flex-direction: column; gap: 4px; }
20
+ .side-foot > div { display: flex; flex-direction: column; gap: 4px; }
21
+ .side-foot .mono { color: var(--fg-2); font-size: 11px; word-break: break-all; }
22
+ .foot-project { color: var(--fg); font-weight: 500; }
23
+ .main { min-width: 0; display: flex; flex-direction: column; }
24
+ .top { position: sticky; top: env(safe-area-inset-top, 0px); z-index: 20; background: color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px 24px; }
25
+ .crumb { color: var(--fg-3); font-size: 13px; }
26
+ .crumb b { color: var(--fg); font-weight: 500; }
27
+ .top-right { margin-left: auto; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
28
+ .btn.ghost { background: none; border-color: transparent; color: var(--fg-2); box-shadow: none; }
29
+ .btn.ghost:hover { background: var(--surface-2); }
30
+ .btn svg { width: 14px; height: 14px; }
31
+ .kbd { font: 11px var(--mono); padding: 0 5px; border: 1px solid var(--line); border-radius: 4px; color: var(--fg-3); }
32
+ .live { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--fg-2); }
33
+ .live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--fg-3); }
34
+ .live[data-state="live"] .live-dot { background: var(--ok); }
35
+ .live-dot.flash { animation: live-flash .9s ease-out; }
36
+ @keyframes live-flash { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 65%, transparent); } 100% { box-shadow: 0 0 0 9px transparent; } }
37
+ @keyframes blink { 50% { opacity: .35; } }
38
+ .banner { margin: 0; padding: 8px 24px; background: var(--warn-soft); color: var(--warn); font-size: 13px; border-bottom: 1px solid var(--line); display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
39
+ .page { padding: 28px 24px 64px; max-width: 1240px; width: 100%; margin: 0 auto; }
40
+ .page:focus { outline: none; }
41
+ .page-view { min-width: 0; display: flex; flex-direction: column; gap: 22px; }
42
+ #panel-worktrees, #panel-benchmarks, #panel-database { display: block; }
43
+
44
+ /* Shared helpers for pages */
45
+ .num { font-variant-numeric: tabular-nums; }
46
+ .faint { color: var(--fg-3); }
47
+ .st { display: inline-grid; place-items: center; width: 16px; height: 16px; flex: none; }
48
+ .st svg { width: 16px; height: 16px; }
49
+ .st.completed { color: var(--ok); } .st.blocked { color: var(--bad); } .st.pending { color: var(--fg-3); } .st.in_progress { color: var(--run); }
50
+ .pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--run); box-shadow: 0 0 0 0 color-mix(in srgb, var(--run) 50%, transparent); animation: pulse 1.6s infinite; }
51
+ @keyframes pulse { 70% { box-shadow: 0 0 0 7px transparent; } 100% { box-shadow: 0 0 0 0 transparent; } }
52
+ .agent { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--fg-2); white-space: nowrap; }
53
+ .agent i { width: 7px; height: 7px; border-radius: 2px; background: var(--c, var(--fg-3)); }
54
+ .status-pill { font-size: 11.5px; font-weight: 500; padding: 1px 8px; border-radius: 999px; white-space: nowrap; }
55
+ .status-pill.completed { background: var(--ok-soft); color: var(--ok); } .status-pill.in_progress { background: var(--run-soft); color: var(--run); }
56
+ .status-pill.blocked { background: var(--bad-soft); color: var(--bad); } .status-pill.pending { background: var(--surface-2); color: var(--fg-2); }
57
+ .sel { height: 30px; border: 1px solid var(--line); border-radius: 7px; background: var(--surface); padding: 0 28px 0 10px; max-width: 100%; }
58
+ .row-btn { display: grid; grid-template-columns: 18px 88px minmax(0, 1fr) auto auto; gap: 12px; align-items: center; min-height: 32px; padding: 9px 16px; border: 0; background: none; text-align: left; border-top: 1px solid var(--line); width: 100%; cursor: pointer; }
59
+ .row-btn:hover { background: var(--surface-2); }
60
+ .row-btn .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
61
+ .ui-empty { padding: 36px 16px; text-align: center; color: var(--fg-2); }
62
+ .ui-empty b { display: block; color: var(--fg); font-weight: 600; margin-bottom: 4px; }
63
+ .skel { height: 14px; border-radius: 6px; margin-bottom: 10px; background: var(--surface-2); }
64
+ .skel-head .skel:first-child { height: 22px; }
65
+ .skel-block { background: var(--surface); border: 1px solid var(--line); border-radius: 12px; padding: 16px; }
66
+
67
+ /* Detail panel */
68
+ .scrim { position: fixed; inset: 0; background: rgba(10,10,20,.25); z-index: 40; }
69
+ .drawer { position: fixed; top: 0; right: 0; bottom: 0; width: min(440px, 100%); background: var(--surface); border-left: 1px solid var(--line); box-shadow: var(--shadow); z-index: 41; display: flex; flex-direction: column; padding-top: env(safe-area-inset-top, 0px); }
70
+ .drawer:focus { outline: none; }
71
+ .drawer-head { display: flex; align-items: center; gap: 8px; padding: 14px 18px; border-bottom: 1px solid var(--line); }
72
+ .drawer-head .close { margin-left: auto; }
73
+ .drawer-body { padding: 18px; overflow: auto; display: flex; flex-direction: column; gap: 18px; padding-bottom: calc(18px + env(safe-area-inset-bottom, 0px)); }
74
+ .drawer h3 { margin: 0; font-size: 17px; font-weight: 600; text-wrap: balance; }
75
+ .drawer .kv { display: grid; grid-template-columns: 110px minmax(0, 1fr); gap: 8px 12px; font-size: 13px; margin: 0; }
76
+ .drawer .kv dt { color: var(--fg-3); }
77
+ .drawer .kv dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }
78
+ .dlabel { font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--fg-3); margin-bottom: 6px; }
79
+ .drawer .chips { display: flex; flex-wrap: wrap; gap: 6px; }
80
+ .drawer .chip { display: inline-flex; align-items: center; gap: 6px; min-height: 26px; padding: 3px 8px; border: 1px solid var(--line); border-radius: 7px; background: var(--surface); font-size: 12px; font-family: var(--font); }
81
+ .drawer .chip.mono { font-family: var(--mono); }
82
+ .drawer button.chip { cursor: pointer; }
83
+ .drawer button.chip:hover { border-color: var(--line-2); }
84
+ .drawer .code { font: 12px var(--mono); background: var(--surface-2); border-radius: 8px; padding: 10px 12px; overflow-x: auto; white-space: pre; }
85
+ .drawer .code.wrap { white-space: pre-wrap; overflow-wrap: anywhere; }
86
+ .drawer .reason { background: var(--bad-soft); color: var(--fg); border-radius: 8px; padding: 10px 12px; font-size: 13px; }
87
+
88
+ /* Command palette */
89
+ .pal-wrap { position: fixed; inset: 0; z-index: 50; display: flex; justify-content: center; align-items: flex-start; padding: 12vh 16px 16px; background: rgba(10,10,20,.3); }
90
+ .pal { width: min(620px, 100%); background: var(--surface); border: 1px solid var(--line); border-radius: 12px; box-shadow: var(--shadow); overflow: hidden; }
91
+ .pal input { width: 100%; border: 0; border-bottom: 1px solid var(--line); background: none; padding: 14px 16px; font-size: 15px; outline: none; }
92
+ .pal ul { list-style: none; margin: 0; padding: 6px; max-height: 50vh; overflow: auto; }
93
+ .pal li { display: grid; grid-template-columns: 18px 150px minmax(0, 1fr) auto; gap: 10px; align-items: center; min-height: 32px; padding: 8px 10px; border-radius: 7px; cursor: pointer; }
94
+ .pal li[aria-selected="true"] { background: var(--accent-soft); }
95
+ .pal li .t { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
96
+ .pal li.pal-none { display: block; cursor: default; }
97
+ .pal-ico svg { width: 16px; height: 16px; display: block; }
98
+ .pal .hint { padding: 8px 16px; border-top: 1px solid var(--line); font-size: 12px; color: var(--fg-3); display: flex; gap: 14px; }
99
+ .toast-host { bottom: calc(16px + env(safe-area-inset-bottom, 0px)); }
100
+
101
+ @media (max-width: 760px) {
102
+ .app { grid-template-columns: minmax(0, 1fr); }
103
+ .side { position: static; height: auto; flex-direction: row; align-items: center; padding: 10px 16px; gap: 12px; overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--line); }
104
+ .side-foot, .brand .ver, .brand b, .nav-glabel { display: none; }
105
+ .nav { flex-direction: row; gap: 2px; }
106
+ .nav-group { flex-direction: row; }
107
+ .nav-item { width: auto; white-space: nowrap; }
108
+ .top, .page { padding-left: 16px; padding-right: 16px; }
109
+ .banner { padding-inline: 16px; }
110
+ .row-btn { grid-template-columns: 18px minmax(0, 1fr) auto; }
111
+ .hide-sm { display: none; }
112
+ .pal li { grid-template-columns: 18px minmax(0, 1fr); }
113
+ .drawer { width: 100%; }
114
+ #runner-console-drawer { inset: auto 0 0 0; }
115
+ }
116
+ @media (prefers-reduced-motion: reduce) { .pulse, .live-dot.flash { animation: none; } * { transition: none !important; } }
117
+ `;
@@ -0,0 +1 @@
1
+ export declare const strategistCss: string;
@@ -0,0 +1,77 @@
1
+ // Tier 1 strategist chip, verdicts and decision card styles.
2
+ export const strategistCss = String.raw `/* Tier 1 AI Strategist (ui_specs.md §5): header chip, triage verdicts, decision card. */
3
+ .t1 { position: relative; }
4
+ .t1-chip { display: inline-flex; align-items: center; gap: 7px; min-height: 32px; padding: 0 10px; font: 500 12.5px/1 var(--font); color: var(--text); background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-control); cursor: pointer; white-space: nowrap; transition: background .15s, border-color .15s; }
5
+ .t1-chip:hover { background: var(--bg); border-color: var(--chip-border); }
6
+ .t1-chip:focus-visible, .t1-switch:focus-visible, .t1-opt:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
7
+ .t1-chip .t1-spark { color: var(--primary); }
8
+ .t1-chip[data-state="triaging"] { border-color: var(--active-line); }
9
+ .t1-chip[data-state="triaging"] .t1-spark { color: var(--active); animation: blink 1s ease-in-out infinite; }
10
+ .t1-chip[data-state="attention"] { border-color: var(--proposal-line); }
11
+ .t1-chip[data-state="attention"] .t1-spark { color: var(--proposal); }
12
+ .t1-chip-label { color: var(--muted); }
13
+ .t1-caret { color: var(--muted); transition: transform .15s; }
14
+ .t1-chip[aria-expanded="true"] .t1-caret { transform: rotate(180deg); }
15
+ .t1-menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 30; width: 300px; padding: 12px; font-size: 12.5px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-card); box-shadow: var(--shadow-float); }
16
+ .t1-menu:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
17
+ .t1-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-height: 28px; color: var(--muted); }
18
+ .t1-row b, .t1-row code { color: var(--text); font-weight: 500; font-variant-numeric: tabular-nums; }
19
+ .t1-row code { font-family: var(--mono); font-size: 12px; }
20
+ .t1-switch { position: relative; width: 54px; height: 24px; padding: 0 8px; font: 600 10.5px/22px var(--mono); color: var(--muted); text-align: right; background: var(--chip); border: 1px solid var(--chip-border); border-radius: 12px; cursor: pointer; transition: background .15s, border-color .15s; }
21
+ .t1-switch::before { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: var(--surface); box-shadow: var(--shadow); transition: transform .15s; }
22
+ .t1-switch[aria-checked="true"] { color: #fff; text-align: left; background: var(--success); border-color: var(--success); }
23
+ .t1-switch[aria-checked="true"]::before { transform: translateX(30px); }
24
+ .t1-switch:disabled { opacity: .5; cursor: not-allowed; }
25
+ .t1-policy { display: flex; gap: 6px; margin: 8px 0; padding: 8px; line-height: 1.45; color: var(--muted); background: var(--bg); border: 1px solid var(--border); border-radius: var(--r-control); }
26
+ .t1-policy .icon { flex: none; margin-top: 1px; color: var(--success); }
27
+ .t1-stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; margin: 0; }
28
+ .t1-stats div { min-width: 0; padding: 6px 8px; border: 1px solid var(--border); border-radius: var(--r-control); }
29
+ .t1-stats dt { font-size: 11px; color: var(--muted); }
30
+ .t1-stats dd { margin: 2px 0 0; font: 600 15px/1.2 var(--mono); font-variant-numeric: tabular-nums; color: var(--text); }
31
+ .t1-strip { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin: 0 0 10px; padding: 8px 10px; color: var(--term-muted); border: 1px solid var(--term-line); border-radius: var(--r-control); }
32
+ .t1-strip > span { display: inline-flex; align-items: center; gap: 6px; }
33
+ .t1-strip strong { color: var(--term-text); font-weight: 600; }
34
+ .t1-strip.is-triaging { border-color: color-mix(in srgb, var(--active) 60%, transparent); background: color-mix(in srgb, var(--active) 14%, transparent); }
35
+ .rc-btn.t1-run { color: #fff; background: var(--active); border-color: var(--active); }
36
+ .rc-btn.t1-run:hover:not(:disabled) { background: color-mix(in srgb, var(--active) 88%, #000); }
37
+ .t1-banner { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; padding: 8px 10px; font-weight: 600; border-radius: var(--r-control); }
38
+ .t1-banner.is-resolved { color: #fff; background: var(--success); }
39
+ .t1-banner.is-safe { color: var(--ok); border: 1px solid color-mix(in srgb, var(--ok) 45%, transparent); }
40
+ .t1-card { margin: 0 0 12px; padding: 12px 12px 12px 16px; border: 1px solid var(--term-line); border-left: 4px solid var(--proposal); border-radius: var(--r-card); }
41
+ .t1-card-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
42
+ .t1-badge { font: 600 11.5px/20px var(--font); padding: 0 8px; color: var(--proposal); background: var(--proposal-bg); border-radius: var(--r-control); }
43
+ .t1-meta { margin-left: auto; font: 500 11px/18px var(--mono); color: var(--term-muted); }
44
+ .t1-parts { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; counter-reset: t1; }
45
+ .t1-parts > li { counter-increment: t1; }
46
+ .t1-parts h4 { margin: 0 0 3px; font-size: 12.5px; font-weight: 600; color: var(--term-text); }
47
+ .t1-parts h4::before { content: counter(t1) ". "; color: var(--proposal); }
48
+ .t1-parts p { margin: 0; color: var(--term-muted); overflow-wrap: anywhere; }
49
+ .t1-options { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; }
50
+ .t1-opt { display: flex; flex-direction: column; align-items: flex-start; gap: 2px; flex: 1 1 200px; min-width: 0; padding: 8px 10px; font: inherit; text-align: left; color: var(--term-text); background: transparent; border: 1px solid var(--muted); border-radius: var(--r-control); cursor: pointer; transition: background .15s, border-color .15s, box-shadow .15s; }
51
+ .t1-opt b { font-weight: 600; }
52
+ .t1-opt span { font-size: 12px; color: var(--term-muted); }
53
+ .t1-opt:hover { border-color: var(--term-text); }
54
+ .t1-opt.is-recommended { background: var(--primary); border-color: var(--primary); }
55
+ .t1-opt.is-recommended:hover { background: var(--primary-hover); border-color: var(--primary-hover); }
56
+ .t1-opt.is-recommended span { color: color-mix(in srgb, #fff 82%, var(--primary)); }
57
+ .t1-opt[aria-checked="true"] { box-shadow: 0 0 0 2px var(--term-bg), 0 0 0 4px var(--proposal); }
58
+ .t1-custom { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; font-size: 12px; color: var(--term-muted); }
59
+ .t1-custom textarea { width: 100%; box-sizing: border-box; min-height: 52px; padding: 6px 8px; font: 12.5px/1.45 var(--font); color: var(--term-text); background: rgb(148 163 184 / 0.08); border: 1px solid var(--term-line); border-radius: var(--r-control); resize: vertical; }
60
+ .t1-custom textarea:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
61
+ .t1-decided { margin: 8px 0 0; font-size: 12px; color: var(--term-muted); }
62
+ @media (prefers-reduced-motion: reduce) { .t1-chip[data-state="triaging"] .t1-spark { animation: none; } }
63
+ @media (max-width: 760px) {
64
+ .t1-chip-label, .t1-chip-model { display: none; }
65
+ .t1-menu { position: fixed; top: 56px; left: 16px; right: 16px; width: auto; }
66
+ }
67
+ .df-add { display: block; color: var(--ok); background: color-mix(in srgb, var(--ok) 12%, transparent); }
68
+ .df-del { display: block; color: color-mix(in srgb, var(--danger) 55%, #fff); background: color-mix(in srgb, var(--danger) 14%, transparent); }
69
+ .df-hunk { display: block; color: var(--accent); }
70
+ .df-file { display: block; margin-top: 8px; font-weight: 700; color: var(--term-text); }
71
+ .df-meta { display: block; color: var(--term-muted); }
72
+ @media (max-width: 760px) {
73
+ .rc-steps { order: 3; margin-left: 0; width: 100%; }
74
+ .rc-title { max-width: 100%; }
75
+ }
76
+
77
+ `;
@@ -0,0 +1 @@
1
+ export declare const tokensBaseCss: string;
@@ -0,0 +1,131 @@
1
+ // Design tokens (light, dark, old-name aliases), base rules and shared legacy components.
2
+ const DARK = `--bg: #0e0e13; --surface: #16161d; --surface-2: #1d1d26; --line: #2a2a36; --line-2: #383847;
3
+ --fg: #ececf2; --fg-2: #a4a4b7; --fg-3: #6e6e82;
4
+ --accent: #8e8aff; --accent-soft: #23224a; --accent-fg: #0e0e13;
5
+ --ok: #4ade80; --ok-soft: #13281b; --run: #60a5fa; --run-soft: #142238;
6
+ --bad: #f87171; --bad-soft: #341617; --warn: #fbbf24; --warn-soft: #2f2410;
7
+ --ag-backend: #38bdf8; --ag-frontend: #a78bfa; --ag-qa: #fbbf24; --ag-flutter: #2dd4bf;
8
+ --ag-architect: #8e8aff; --ag-devops: #94a3b8; --ag-database: #34d399; --ag-security: #f87171;
9
+ --shadow: 0 1px 2px rgba(0,0,0,.3), 0 6px 20px rgba(0,0,0,.35); color-scheme: dark;`;
10
+ export const tokensBaseCss = String.raw `:root {
11
+ --bg: #f6f6f9;
12
+ --surface: #ffffff;
13
+ --surface-2: #f0f0f5;
14
+ --line: #e3e3ea; --line-2: #d2d2dc;
15
+ --fg: #16161f; --fg-2: #54546a; --fg-3: #8b8b9e;
16
+ --accent: #4f46e5; --accent-soft: #eeeefe; --accent-fg: #ffffff;
17
+ --ok: #15803d; --ok-soft: #e7f5ec;
18
+ --run: #2563eb; --run-soft: #e7eefd;
19
+ --bad: #dc2626; --bad-soft: #fdecec;
20
+ --warn: #b45309; --warn-soft: #fcf2e1;
21
+ --ag-backend: #0284c7; --ag-frontend: #7c3aed; --ag-qa: #d97706; --ag-flutter: #0d9488;
22
+ --ag-architect: #4f46e5; --ag-devops: #64748b; --ag-database: #059669; --ag-security: #dc2626;
23
+ --shadow: 0 1px 2px rgba(22,22,40,.05), 0 4px 16px rgba(22,22,40,.06);
24
+ --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
25
+ --mono: ui-monospace, "Cascadia Mono", "SFMono-Regular", Consolas, Menlo, monospace;
26
+ color-scheme: light;
27
+ /* Old names used by Worktrees, Benchmarks, Database and the kept tools follow the new tokens. */
28
+ --border: var(--line); --text: var(--fg); --muted: var(--fg-2);
29
+ --primary: var(--accent); --primary-hover: color-mix(in srgb, var(--accent) 86%, var(--fg));
30
+ --primary-active: color-mix(in srgb, var(--accent) 72%, var(--fg));
31
+ --primary-tint: var(--accent-soft); --primary-line: color-mix(in srgb, var(--accent) 35%, var(--surface));
32
+ --success: var(--ok); --success-bg: var(--ok-soft); --success-line: color-mix(in srgb, var(--ok) 35%, var(--surface));
33
+ --active: var(--run); --active-bg: var(--run-soft); --active-line: color-mix(in srgb, var(--run) 35%, var(--surface));
34
+ --danger: var(--bad); --danger-bg: var(--bad-soft); --danger-line: color-mix(in srgb, var(--bad) 35%, var(--surface));
35
+ --warn-bg: var(--warn-soft);
36
+ --proposal: var(--warn); --proposal-bg: var(--warn-soft); --proposal-line: color-mix(in srgb, var(--warn) 40%, var(--surface));
37
+ --chip: var(--surface-2); --chip-border: var(--line-2);
38
+ --term-bg: #0f172a; --term-text: #f8fafc; --term-muted: #94a3b8; --term-line: rgb(148 163 184 / 0.28);
39
+ --r-control: 7px; --r-card: 12px;
40
+ --shadow-float: 0 12px 32px -8px rgb(15 23 42 / 0.25), 0 2px 6px -2px rgb(15 23 42 / 0.1);
41
+ --sidebar-w: 224px;
42
+ }
43
+ @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) {
44
+ ${DARK}
45
+ } }
46
+ :root[data-theme="dark"] {
47
+ ${DARK}
48
+ }
49
+ * { box-sizing: border-box; }
50
+ [hidden] { display: none !important; }
51
+ html, body { margin: 0; background: var(--bg); color: var(--fg); font-family: var(--font); font-size: 14px; line-height: 1.45; -webkit-font-smoothing: antialiased; }
52
+ body { min-height: 100vh; }
53
+ button, input, select, textarea { font: inherit; color: inherit; }
54
+ :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
55
+ .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
56
+ code, .mono { font-family: var(--mono); font-size: 12px; }
57
+ .muted { color: var(--fg-2); }
58
+ .text-danger { color: var(--bad); }
59
+ .icon { flex: none; display: block; }
60
+ .card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--shadow); }
61
+ .count { display: inline-block; min-width: 20px; padding: 0 6px; font-size: 11px; font-weight: 600; line-height: 18px; text-align: center; color: var(--text); background: var(--chip); border: 1px solid var(--border); border-radius: var(--r-control); font-variant-numeric: tabular-nums; }
62
+
63
+
64
+ /* Panels */
65
+ .panel { min-width: 0; }
66
+ .panel:focus-visible { outline-offset: 6px; border-radius: var(--r-card); }
67
+ .panel-head { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 12px 16px; margin: 4px 0 20px; }
68
+ .panel-title { min-width: 0; }
69
+ .panel-head h1 { margin: 0; font-size: 22px; font-weight: 650; letter-spacing: -0.015em; }
70
+ .panel-head .lead { margin: 4px 0 0; color: var(--muted); font-size: 15.5px; line-height: 1.6; max-width: 860px; }
71
+ .panel-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
72
+ .panel-actions select.input { max-width: 260px; }
73
+ .panel-actions input.input { width: 240px; max-width: 100%; }
74
+
75
+ /* Buttons */
76
+ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 32px; padding: 0 12px; border: 1px solid var(--border); background: var(--surface); color: var(--text); border-radius: var(--r-control); box-shadow: var(--shadow); cursor: pointer; font-size: 13.5px; font-weight: 500; white-space: nowrap; transition: background .15s, border-color .15s, color .15s; }
77
+ .btn:hover { background: var(--bg); border-color: var(--chip-border); }
78
+ .btn.primary { background: var(--primary); border-color: var(--primary); color: var(--accent-fg); }
79
+ .btn.primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); }
80
+ .btn.danger, .btn-danger { color: var(--danger); border-color: var(--danger-line); }
81
+ .btn.danger:hover, .btn-danger:hover { background: var(--danger-bg); border-color: var(--danger); }
82
+ .btn.danger-solid { background: var(--danger); border-color: var(--danger); color: #fff; }
83
+ .btn.danger-solid:hover { background: color-mix(in srgb, var(--danger) 88%, #000); }
84
+ .btn.small { min-height: 28px; padding: 0 10px; font-size: 12.5px; }
85
+ .btn:disabled { opacity: .5; cursor: not-allowed; }
86
+ .btn.is-busy .icon { animation: spin .9s linear infinite; }
87
+ .spinner { width: 12px; height: 12px; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; animation: spin .7s linear infinite; flex: none; }
88
+ @keyframes spin { to { transform: rotate(360deg); } }
89
+
90
+ /* Badges */
91
+ .badge { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 600; line-height: 1.5; padding: 0 7px; border-radius: var(--r-control); border: 1px solid transparent; white-space: nowrap; }
92
+ button.badge { font: inherit; font-size: 11px; font-weight: 600; cursor: pointer; }
93
+ .badge-success, .badge-online, .badge-added { color: var(--success); background: var(--success-bg); border-color: var(--success-line); }
94
+ .badge-active, .badge-altered, .badge-fk { color: var(--active); background: var(--active-bg); border-color: var(--active-line); }
95
+ .badge-danger, .badge-offline, .badge-dropped, .badge-prod { color: var(--danger); background: var(--danger-bg); border-color: var(--danger-line); }
96
+ .badge-neutral, .badge-agent { color: var(--text); background: var(--chip); border-color: var(--chip-border); }
97
+ .badge-agent { font-family: var(--mono); font-weight: 500; font-size: 11.5px; }
98
+ .badge-accent, .badge-pk, .badge-collection { color: var(--primary); background: var(--primary-tint); border-color: var(--primary-line); }
99
+ .badge-subcol { color: var(--active); background: var(--active-bg); border: 1px dashed var(--active); }
100
+ .badge-media { color: var(--primary); background: var(--surface); border-color: var(--primary-line); cursor: zoom-in; }
101
+ button.badge-media:hover { background: var(--primary-tint); }
102
+ .badge-source { font-family: var(--mono); font-weight: 500; color: var(--active); background: var(--active-bg); border-color: var(--active-line); }
103
+ .badge-synth { font-family: var(--mono); font-weight: 500; color: var(--primary); background: var(--primary-tint); border-color: var(--primary-line); }
104
+
105
+ /* Shared states */
106
+ .skeleton { height: 42px; border-radius: var(--r-control); margin-bottom: 8px; background: linear-gradient(90deg, var(--chip) 0%, var(--border) 50%, var(--chip) 100%); background-size: 200% 100%; animation: shimmer 1.3s infinite linear; }
107
+ .skeleton.short { width: 60%; }
108
+ .skeleton.tall { height: 150px; margin: 0; }
109
+ @keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
110
+ .state { padding: 40px 24px; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 6px; }
111
+ .state h2 { margin: 6px 0 0; font-size: 17px; font-weight: 600; }
112
+ .state p { margin: 0; color: var(--muted); max-width: 620px; font-size: 15px; line-height: 1.55; }
113
+ .state .btn { margin-top: 10px; }
114
+ .state-icon { color: var(--primary); }
115
+ .state-error .state-icon { color: var(--danger); }
116
+ .notice { margin: 0 0 14px; padding: 10px 14px; font-size: 13.5px; background: var(--danger-bg); border: 1px solid var(--danger-line); border-radius: var(--r-control); }
117
+ .section { padding: 20px; margin-bottom: 16px; }
118
+ .section > h3 { margin: 0 0 12px; font-size: 15px; display: flex; align-items: center; gap: 8px; }
119
+ .section-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
120
+ .section-head h2 { margin: 0; font-size: 16px; font-weight: 600; }
121
+ .progress { height: 6px; border-radius: var(--r-control); background: var(--chip); overflow: hidden; }
122
+ .progress > span { display: block; height: 100%; border-radius: inherit; background: var(--primary); transition: width .5s cubic-bezier(.2, .8, .2, 1); }
123
+ .progress.success > span { background: var(--success); }
124
+ .progress.danger > span { background: var(--danger); }
125
+ .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--chip-border); }
126
+ .dot.on, .dot-completed { background: var(--success); }
127
+ .dot.off, .dot-blocked { background: var(--danger); }
128
+ .dot-in_progress { background: var(--active); }
129
+ .dot-pending { background: var(--chip-border); }
130
+
131
+ `;
@@ -1,15 +1,6 @@
1
- /**
2
- * Nativ Mission Control Studio — self-contained single-page dashboard.
3
- * Implements .ai/ui_specs.md: modern minimalist light tokens, five primary views (Overview & Status,
4
- * Live Tasks kanban, Agent Worktrees, Benchmarks, embedded Database Studio) and a real-time
5
- * EventSource client on /api/events. No external assets: served inline by studio-server.
6
- *
7
- * The page is a String.raw template so client-side regexes keep their backslashes.
8
- * Client script must not contain backticks or "${" sequences.
9
- */
10
1
  export interface StudioUiOptions {
11
2
  version?: string;
12
- /** Project name shown in the header; filled from the pipeline API when omitted. */
3
+ /** Project name shown in the sidebar; filled from the pipeline API when omitted. */
13
4
  projectName?: string;
14
5
  }
15
6
  export declare function renderStudioHtml(options?: StudioUiOptions): string;