create-pmos 0.14.0 → 0.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 (39) hide show
  1. package/README.md +57 -0
  2. package/package.json +1 -1
  3. package/payload/KIT-VERSION +2 -2
  4. package/workspace/README.md +44 -12
  5. package/workspace/design-parity.js +358 -0
  6. package/workspace/lib/console-state.js +48 -1
  7. package/workspace/lib/engine/workflow-state.js +13 -3
  8. package/workspace/lib/find-browser.js +60 -0
  9. package/workspace/lib/focus.js +967 -0
  10. package/workspace/lib/four-panel.js +345 -0
  11. package/workspace/lib/git-info.js +28 -1
  12. package/workspace/lib/handoff.js +280 -0
  13. package/workspace/lib/layout.js +68 -46
  14. package/workspace/lib/mobile-nav.js +157 -0
  15. package/workspace/lib/profiles.js +285 -0
  16. package/workspace/lib/repo-scan.js +469 -0
  17. package/workspace/package-lock.json +29 -2
  18. package/workspace/package.json +14 -4
  19. package/workspace/public/index.html +79 -279
  20. package/workspace/public/pm/app.js +242 -0
  21. package/workspace/public/pm/data.js +877 -0
  22. package/workspace/public/pm/dom.js +116 -0
  23. package/workspace/public/pm/fixture.js +979 -0
  24. package/workspace/public/pm/mobile.css +200 -0
  25. package/workspace/public/pm/mobile.js +403 -0
  26. package/workspace/public/pm/modes.js +1076 -0
  27. package/workspace/public/pm/panel-detail.js +648 -0
  28. package/workspace/public/pm/panel-initiatives.js +426 -0
  29. package/workspace/public/pm/panel-repos.js +460 -0
  30. package/workspace/public/pm/panel-tabs.js +487 -0
  31. package/workspace/public/pm/state.js +164 -0
  32. package/workspace/public/pm/tab-doc.js +279 -0
  33. package/workspace/public/pm/tab-task.js +83 -0
  34. package/workspace/public/pm/tab-term.js +560 -0
  35. package/workspace/public/pm/tokens.css +73 -0
  36. package/workspace/public/vendor/ibm-plex-mono-500.woff2 +0 -0
  37. package/workspace/server.js +1072 -31
  38. package/workspace/public/app.js +0 -3450
  39. package/workspace/public/styles.css +0 -1444
@@ -1,1444 +0,0 @@
1
- /* PMOS Terminal Workspace — GUI client. D38 token layer.
2
- ────────────────────────────────────────────────────────────────────────────────────────────
3
- The palette is the shadcn `radix-sera` style on the `mist` base colour, ported VERBATIM from
4
- the sibling product's design system (its components.json + react-src/styles/app.css) so the
5
- two surfaces read as one house. The port is CSS-only: the workspace stays a no-build local
6
- companion app, so what comes across is the token layer + the component vocabulary, not React,
7
- Tailwind or Radix.
8
- Three things to know before editing:
9
- 1. --radius is 0. That is the style's signature, not an oversight. Everything derives from
10
- it through the scale below, so re-rounding the whole app is a ONE-token change. Never
11
- hardcode a px radius — the exceptions are 50% (dots) and 999px (pills/meters), which are
12
- shapes rather than radii.
13
- 2. shadcn's --accent is a MUTED HOVER SURFACE, not a brand hue. The brand blue lives in
14
- --primary (fills) and --brand (text/borders). Reaching for --accent to mean "blue" is the
15
- one mistake this palette invites.
16
- 3. The --xt-* block must stay concrete hex/rgba: those values are read by xtheme() in app.js
17
- and handed to xterm.js, whose colour parser does NOT understand oklch().
18
- ──────────────────────────────────────────────────────────────────────────────────────────── */
19
-
20
- /* Vendored, not CDN-linked: this app has to render correctly with no network at all. */
21
- @font-face{
22
- font-family:"Space Grotesk Variable";
23
- src:url("/vendor/space-grotesk-var.woff2") format("woff2-variations");
24
- font-weight:300 700; font-style:normal; font-display:swap;
25
- }
26
- /* Plex Mono is the terminal's face, so `swap` would be wrong here: swapping the grid out from
27
- under a live xterm re-flows every row mid-session. `block` holds a short invisible period and
28
- then keeps the fallback forever if the face never arrives — and app.js re-measures on
29
- document.fonts.ready either way, so the grid is correct in both outcomes.
30
- Both weights are real files: xterm renders bold text, and a synthesised bold on a monospace
31
- face is wider than the regular one, which breaks cell alignment. */
32
- @font-face{
33
- font-family:"IBM Plex Mono";
34
- src:url("/vendor/ibm-plex-mono-400.woff2") format("woff2");
35
- font-weight:400; font-style:normal; font-display:block;
36
- }
37
- @font-face{
38
- font-family:"IBM Plex Mono";
39
- src:url("/vendor/ibm-plex-mono-700.woff2") format("woff2");
40
- font-weight:700; font-style:normal; font-display:block;
41
- }
42
-
43
- :root{
44
- /* ── shadcn radix-sera / mist — light ── */
45
- --background:oklch(1 0 0);
46
- --foreground:oklch(0.148 0.004 228.8);
47
- --card:oklch(1 0 0);
48
- --card-foreground:oklch(0.148 0.004 228.8);
49
- --popover:oklch(1 0 0);
50
- --popover-foreground:oklch(0.148 0.004 228.8);
51
- --primary:oklch(0.488 0.243 264.376);
52
- --primary-foreground:oklch(0.97 0.014 254.604);
53
- --secondary:oklch(0.967 0.001 286.375);
54
- --secondary-foreground:oklch(0.21 0.006 285.885);
55
- --muted:oklch(0.963 0.002 197.1);
56
- --muted-foreground:oklch(0.56 0.021 213.5);
57
- --accent:oklch(0.963 0.002 197.1);
58
- --accent-foreground:oklch(0.218 0.008 223.9);
59
- --destructive:oklch(0.577 0.245 27.325);
60
- --border:oklch(0.925 0.005 214.3);
61
- --input:oklch(0.925 0.005 214.3);
62
- --ring:oklch(0.723 0.014 214.4);
63
- --sidebar:oklch(0.987 0.002 197.1);
64
- --sidebar-foreground:oklch(0.148 0.004 228.8);
65
- --sidebar-primary:oklch(0.546 0.245 262.881);
66
- --sidebar-border:oklch(0.925 0.005 214.3);
67
-
68
- /* --brand is the brand blue AS TEXT OR BORDER on the current surface. --primary is tuned to
69
- be a filled background (it pairs with --primary-foreground), and in dark it is far too deep
70
- to read as type — so the two are separate tokens rather than one reused in both roles. */
71
- --brand:oklch(0.488 0.243 264.376);
72
- --brand-wash:color-mix(in oklab, var(--brand) 7%, transparent);
73
-
74
- /* Status hues. shadcn ships --destructive only; a workspace that reports agent state needs a
75
- full set, so these are authored in the same oklch space to sit with the palette. Each is
76
- picked to clear text contrast on THIS theme's surfaces — hence separate light/dark values
77
- rather than one hue dimmed by opacity. */
78
- --success:oklch(0.52 0.14 152);
79
- --warning:oklch(0.55 0.12 72);
80
- --info:oklch(0.52 0.09 195);
81
- --purple:oklch(0.5 0.2 300);
82
- --success-wash:color-mix(in oklab, var(--success) 10%, transparent);
83
- --warning-wash:color-mix(in oklab, var(--warning) 10%, transparent);
84
- --info-wash:color-mix(in oklab, var(--info) 10%, transparent);
85
-
86
- --glass:color-mix(in oklab, var(--background) 80%, transparent);
87
- --shadow:oklch(0.148 0.004 228.8 / 0.18);
88
- --term-bg:oklch(0.148 0.004 228.8);
89
-
90
- /* ── radius scale (shadcn) — derived, never hardcoded ── */
91
- --radius:0rem;
92
- --radius-sm:calc(var(--radius) * 0.6);
93
- --radius-md:calc(var(--radius) * 0.8);
94
- --radius-lg:var(--radius);
95
- --radius-xl:calc(var(--radius) * 1.4);
96
-
97
- /* ── motion vocabulary (shadcn): one house curve, three duration tiers ── */
98
- --ease-emphasized:cubic-bezier(0.4, 0, 0.2, 1);
99
- --duration-fast:150ms;
100
- --duration-base:250ms;
101
- --duration-slow:350ms;
102
-
103
- /* ── type scale. The workspace used to label everything in 8.5–11px uppercase mono; that
104
- density was the single loudest "dated terminal dashboard" signal. Chrome now speaks the
105
- sans scale and mono is reserved for things that ARE code: the terminal, paths, branches,
106
- diffs, code spans. ── */
107
- --text-2xs:11px; --text-xs:12px; --text-sm:13px; --text-base:14px; --text-lg:16px;
108
- --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"Liberation Mono",monospace;
109
- --sans:"Space Grotesk Variable",ui-sans-serif,system-ui,-apple-system,sans-serif;
110
-
111
- /* layout knobs the JS adjusts (rail width, library/document split) */
112
- --rail-w:400px; --libsplit:44%;
113
-
114
- /* xterm palette tokens — the single source for the JS terminal theme (xtheme()). Dark in BOTH
115
- themes by design; the terminal is a terminal, not a themed surface. Concrete hex only (see
116
- note 3 at the top of this file). */
117
- --xt-bg:#090b0c; --xt-fg:#c4ccce; --xt-cursor:#47cf79; --xt-sel:rgba(43,127,255,.3);
118
- --xt-black:#090b0c; --xt-red:#ff6467; --xt-green:#47cf79; --xt-yellow:#f4b93c;
119
- --xt-blue:#2b7fff; --xt-magenta:#b48df4; --xt-cyan:#53d1d0; --xt-white:#d2d9db;
120
- --xt-brblack:#6f7d81; --xt-brgreen:#81e8a0; --xt-accent-text:#2b7fff; --xt-brwhite:#f9fbfb;
121
- }
122
-
123
- /* ── shadcn radix-sera / mist — dark. This is the workspace's DEFAULT (index.html ships
124
- data-theme="dark"); the light block above is the base the toggle falls back to. ── */
125
- :root[data-theme="dark"]{
126
- --background:oklch(0.148 0.004 228.8);
127
- --foreground:oklch(0.987 0.002 197.1);
128
- --card:oklch(0.218 0.008 223.9);
129
- --card-foreground:oklch(0.987 0.002 197.1);
130
- --popover:oklch(0.218 0.008 223.9);
131
- --popover-foreground:oklch(0.987 0.002 197.1);
132
- --primary:oklch(0.424 0.199 265.638);
133
- --primary-foreground:oklch(0.97 0.014 254.604);
134
- --secondary:oklch(0.274 0.006 286.033);
135
- --secondary-foreground:oklch(0.985 0 0);
136
- --muted:oklch(0.275 0.011 216.9);
137
- --muted-foreground:oklch(0.723 0.014 214.4);
138
- --accent:oklch(0.275 0.011 216.9);
139
- --accent-foreground:oklch(0.987 0.002 197.1);
140
- --destructive:oklch(0.704 0.191 22.216);
141
- --border:oklch(1 0 0 / 10%);
142
- --input:oklch(1 0 0 / 15%);
143
- --ring:oklch(0.56 0.021 213.5);
144
- --sidebar:oklch(0.218 0.008 223.9);
145
- --sidebar-foreground:oklch(0.987 0.002 197.1);
146
- --sidebar-primary:oklch(0.623 0.214 259.815);
147
- --sidebar-border:oklch(1 0 0 / 10%);
148
-
149
- --brand:oklch(0.623 0.214 259.815);
150
- --brand-wash:color-mix(in oklab, var(--brand) 12%, transparent);
151
-
152
- --success:oklch(0.76 0.17 152);
153
- --warning:oklch(0.82 0.15 82);
154
- --info:oklch(0.79 0.11 195);
155
- --purple:oklch(0.72 0.15 300);
156
- --success-wash:color-mix(in oklab, var(--success) 10%, transparent);
157
- --warning-wash:color-mix(in oklab, var(--warning) 10%, transparent);
158
- --info-wash:color-mix(in oklab, var(--info) 10%, transparent);
159
-
160
- --glass:color-mix(in oklab, var(--background) 78%, transparent);
161
- --shadow:oklch(0 0 0 / 0.6);
162
- --term-bg:oklch(0.148 0.004 228.8);
163
- }
164
-
165
- *{box-sizing:border-box;margin:0;padding:0}
166
- html,body{height:100%}
167
- body{background:var(--background); color:var(--foreground); font-family:var(--sans);
168
- font-size:var(--text-sm); line-height:1.5; -webkit-font-smoothing:antialiased; overflow:hidden}
169
- button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
170
- /* shadcn's focus ring: a soft halo in --ring rather than a hard outline */
171
- :focus-visible{outline:2px solid var(--ring); outline-offset:2px; border-radius:var(--radius-sm)}
172
- .mono{font-family:var(--mono)}
173
-
174
- /* Motion, ported from the sibling design system: gentle fades and small lifts, no bounce. Every
175
- one of these is neutralised by the reduced-motion guard at the bottom of this file. */
176
- @keyframes motion-fade{from{opacity:0}to{opacity:1}}
177
- @keyframes motion-rise{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
178
- @keyframes motion-pop-in{from{opacity:0;transform:scale(.96)}to{opacity:1;transform:none}}
179
-
180
- /* The rows are fixed and the middle row is minmax(0,1fr): without the 0 minimum a tall column
181
- (a long needs strip, a long document) grows the row past the viewport and body{overflow:hidden}
182
- silently clips the BOTTOM OF THE TERMINAL. Every nested column repeats the min-height:0. */
183
- .app{display:grid; grid-template-rows:44px minmax(0,1fr) 28px; height:100vh; height:100dvh}
184
-
185
- /* ── top bar ── */
186
- /* position+z-index so the header's own popover (the layout menu) paints ABOVE the body: the two
187
- are grid siblings, and without this the later-in-DOM body wins the paint order and swallows
188
- every click aimed at the menu. */
189
- .bar{display:flex; align-items:center; gap:10px; padding:0 12px; min-width:0; position:relative; z-index:50;
190
- border-bottom:1px solid var(--border); background:var(--glass); backdrop-filter:blur(8px)}
191
- /* the product mark reads as a filled brand tile, the way a shadcn sidebar header does */
192
- .mark{width:24px;height:24px;display:grid;place-items:center;border-radius:var(--radius-md);
193
- background:var(--primary);color:var(--primary-foreground);font-size:var(--text-xs);font-weight:600}
194
- .bar b{font-size:var(--text-base);font-weight:600;letter-spacing:-.01em}
195
- .bar .sub{font-size:var(--text-xs);color:var(--muted-foreground)}
196
- .bar .conn{font-size:var(--text-xs);display:inline-flex;gap:6px;align-items:center;color:var(--muted-foreground)}
197
- .bar .conn::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--muted-foreground)}
198
- .bar .conn.live{color:var(--success)} .bar .conn.live::before{background:var(--success);animation:pulse 2.2s infinite}
199
- .bar .conn.off{color:var(--warning)} .bar .conn.off::before{background:var(--warning)}
200
- @keyframes pulse{0%,100%{opacity:1}50%{opacity:.35}}
201
- .bar .right{margin-left:auto;display:flex;gap:6px}
202
- /* shadcn Button, `ghost` variant: no resting border or fill, the hover surface does the work */
203
- .ibtn{min-height:32px;min-width:36px;padding:0 10px;display:grid;place-items:center;
204
- border:1px solid transparent;background:transparent;border-radius:var(--radius-md);
205
- color:var(--muted-foreground);font-size:var(--text-sm);font-weight:500;
206
- transition:background-color var(--duration-fast) var(--ease-emphasized),
207
- color var(--duration-fast) var(--ease-emphasized)}
208
- .ibtn:hover{background:var(--accent);color:var(--accent-foreground)}
209
- .ibtn[aria-pressed="true"]{background:var(--accent);color:var(--brand)}
210
-
211
- /* ── the arrangement (workspace-layout-system) ──────────────────────────────────────────────
212
- The template is COMPUTED from the current layout by applyLayout() and written into these three
213
- custom properties — never as a direct grid declaration. That is deliberate: an inline
214
- `grid-template-columns` would outrank the ≤760px media query below and take the phone's
215
- single-column switcher with it. Custom properties lose to a later direct declaration, so the
216
- two responsive systems stay in charge of their own widths (R9). */
217
- .body{display:grid; position:relative;
218
- grid-template-columns:var(--lay-cols, 262px minmax(0,1fr) minmax(0,var(--rail-w)));
219
- grid-template-rows:var(--lay-rows, minmax(0,1fr));
220
- grid-template-areas:var(--lay-areas, "side term read");
221
- min-height:0}
222
- .side{grid-area:side} .term-col{grid-area:term} .rail{grid-area:read}
223
- .body[data-side="off"]>.side{display:none}
224
- .body[data-reader="off"]>.rail{display:none}
225
- /* docked bottom, the reader is a wide short pane under the terminal, not a column beside it */
226
- .body[data-reader="bottom"]>.rail{border-left:0;border-top:1px solid var(--border)}
227
- .body[data-reader="bottom"] .railgrip{display:none}
228
- .body[data-side="right"]>.side{border-right:0;border-left:1px solid var(--border)}
229
- .body[data-reader="left"]>.rail{border-left:0;border-right:1px solid var(--border)}
230
- .body[data-reader="left"] .railgrip{left:auto;right:-3px}
231
-
232
- /* ── left column: the workspace — repos over running agents. Both panes fold and the column
233
- resizes, which is the parity the rail always had and this one never did (R11). ── */
234
- .side{border-right:1px solid var(--border);background:var(--sidebar);min-height:0;
235
- display:flex;flex-direction:column;position:relative}
236
- .side>.pane{flex:1 1 0}
237
- .side>.pane[data-fold="off"]{flex:0 0 auto}
238
- .side>.pane+.pane{border-top:1px solid var(--border)}
239
- .pane{display:flex;flex-direction:column;min-height:0;min-width:0}
240
- .pane-body{overflow-y:auto;overscroll-behavior:contain;flex:1;min-height:0;padding-bottom:10px}
241
- .pane[data-fold="off"]>.pane-body{display:none}
242
- .pane[data-fold="off"]{flex:0 0 auto}
243
-
244
- /* Pane header = shadcn's SidebarGroupLabel: 12px medium in muted-foreground, sentence case. The
245
- uppercase-tracked-mono caption this replaced was the loudest dated signal in the whole app. */
246
- .cap{font-size:var(--text-xs);font-weight:500;
247
- color:var(--muted-foreground);padding:10px 10px 8px 12px;display:flex;gap:8px;align-items:center;
248
- min-height:38px;flex:none;background:var(--sidebar);border-bottom:1px solid var(--border)}
249
- .cap .ct{color:var(--warning);font-size:var(--text-xs);font-weight:500}
250
- .cap .mini{margin-left:auto;width:26px;height:26px;display:grid;place-items:center;border-radius:var(--radius-sm);
251
- border:0;background:transparent;color:var(--muted-foreground);font-size:var(--text-base);
252
- transition:background-color var(--duration-fast) var(--ease-emphasized),
253
- color var(--duration-fast) var(--ease-emphasized)}
254
- .cap .mini:hover{background:var(--accent);color:var(--accent-foreground)}
255
- /* a pane header that folds its body away */
256
- .cap .fold{display:inline-flex;align-items:center;gap:6px;font:inherit;color:var(--muted-foreground)}
257
- .cap .fold:hover{color:var(--foreground)}
258
- .cap .fold .chev{font-size:var(--text-2xs);transition:transform var(--duration-fast) var(--ease-emphasized)}
259
- .pane[data-fold="off"] .cap .fold .chev{transform:rotate(-90deg)}
260
- @media (prefers-reduced-motion:reduce){.cap .fold .chev{transition:none}}
261
- /* the move affordance every relocatable pane carries. Keyboard reaches every position it offers
262
- through the layout menu's position controls (`.lay-pos`), so this is an accelerator and never
263
- the only path (R12). That was asserted here before it was true — the menu had no position
264
- controls at all, and `side:right` / `reader:bottom` were pointer-only. Review-Gate finding. */
265
- .cap .grip{width:22px;min-height:26px;display:grid;place-items:center;border-radius:var(--radius-sm);flex:none;
266
- color:var(--muted-foreground);cursor:grab;letter-spacing:-2px;margin-left:-4px;touch-action:none}
267
- .cap .grip:hover{background:var(--accent);color:var(--brand)}
268
- .cap .grip:active{cursor:grabbing}
269
-
270
- /* a column's outer edge, dragged to resize. The rail's original .railgrip is one of these. */
271
- .edge{position:absolute;top:0;bottom:0;width:7px;z-index:20;cursor:col-resize;touch-action:none}
272
- .edge:hover,.edge.on{background:linear-gradient(90deg,transparent,var(--ring),transparent)}
273
- .side>.edge{right:-3px}
274
- .body[data-side="right"]>.side>.edge{right:auto;left:-3px}
275
-
276
- /* drop targets — visible only while a grip is being dragged */
277
- .drop{position:absolute;inset:0;z-index:40;display:none;grid-area:1/1/-1/-1}
278
- .body.dragging>.drop{display:block}
279
- .dz{position:absolute;border:1px dashed var(--input);border-radius:var(--radius-lg);
280
- background:var(--brand-wash);display:grid;place-items:center;
281
- font-size:var(--text-sm);font-weight:500;color:var(--muted-foreground)}
282
- .dz.hot{border-style:solid;border-color:var(--brand);color:var(--brand);
283
- background:var(--accent);box-shadow:0 0 0 1px var(--ring)}
284
- .dz[data-z="left"]{left:8px;top:8px;bottom:8px;width:22%}
285
- .dz[data-z="right"]{right:8px;top:8px;bottom:8px;width:22%}
286
- .dz[data-z="bottom"]{left:26%;right:26%;bottom:8px;height:30%}
287
- .dz[data-z="off"]{left:26%;right:26%;top:8px;height:20%}
288
- .dz.no{display:none}
289
- .laghost{position:fixed;z-index:70;pointer-events:none;padding:5px 10px;border-radius:var(--radius-md);
290
- background:var(--popover);border:1px solid var(--border);color:var(--foreground);
291
- font-size:var(--text-xs);box-shadow:0 8px 24px -8px var(--shadow)}
292
-
293
- /* ── the layout control ── */
294
- .ibtn.lay-chip{gap:7px;display:inline-flex;align-items:center;padding:0 11px}
295
- .ibtn.lay-chip i{font-style:normal;color:var(--muted-foreground);font-size:var(--text-xs)}
296
- .ibtn.lay-chip[aria-expanded="true"]{background:var(--accent);color:var(--accent-foreground)}
297
- /* shadcn Popover: --popover surface, hairline border, one soft elevation shadow */
298
- .lay-menu{position:absolute;top:40px;right:12px;z-index:60;width:272px;background:var(--popover);
299
- color:var(--popover-foreground);border:1px solid var(--border);border-radius:var(--radius-lg);padding:6px;
300
- box-shadow:0 10px 38px -10px var(--shadow);animation:motion-pop-in var(--duration-fast) var(--ease-emphasized)}
301
- .lay-cap{font-size:var(--text-xs);font-weight:500;color:var(--muted-foreground);margin:4px 8px 6px}
302
- /* shadcn DropdownMenuItem */
303
- .lay-row{display:flex;align-items:center;gap:8px;width:100%;padding:6px 8px;border-radius:var(--radius-sm);
304
- font-size:var(--text-sm);color:var(--popover-foreground);text-align:left;min-height:36px;
305
- transition:background-color var(--duration-fast) var(--ease-emphasized)}
306
- .lay-row:hover{background:var(--accent);color:var(--accent-foreground)}
307
- .lay-row[aria-current="true"]{background:var(--accent);color:var(--brand);font-weight:500}
308
- .lay-row .nm{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
309
- /* a keyboard hint reads as a key — mono is right here, it IS a literal keystroke */
310
- .lay-row .kbd{font-family:var(--mono);font-size:var(--text-2xs);color:var(--muted-foreground);
311
- background:var(--muted);border-radius:var(--radius-sm);padding:1px 5px;flex:none}
312
- /* a wireframe of the arrangement — the name alone does not say what you get */
313
- .lay-mini{width:28px;height:18px;border:1px solid var(--input);border-radius:var(--radius-sm);
314
- display:flex;gap:1px;padding:1px;flex:none;background:var(--background)}
315
- .lay-mini span{background:var(--input);border-radius:var(--radius-sm)}
316
- .lay-row[aria-current="true"] .lay-mini span{background:var(--brand)}
317
- .lay-act{display:flex;align-items:center;justify-content:center;min-width:26px;min-height:26px;
318
- border-radius:var(--radius-sm);color:var(--muted-foreground);font-size:var(--text-xs);flex:none}
319
- .lay-act:hover{background:var(--secondary);color:var(--brand)}
320
- .lay-act.del:hover{color:var(--destructive)}
321
-
322
- /* R12 — the position controls. Every value the pointer drag can produce is a focusable button
323
- here, which is what makes "the layout control can always bring a pane back" a fact about the
324
- DOM rather than an argument about the grid template. */
325
- .lay-pos{margin-top:6px;padding-top:6px;border-top:1px solid var(--border);display:grid;gap:4px}
326
- .pos-row{display:flex;align-items:center;gap:3px}
327
- .pos-lbl{font-size:var(--text-2xs);color:var(--muted-foreground);width:52px;flex:none}
328
- .pos-btn{flex:1;min-height:34px;display:flex;flex-direction:column;align-items:center;justify-content:center;
329
- gap:1px;border-radius:var(--radius-sm);border:1px solid transparent;color:var(--muted-foreground);
330
- font-size:var(--text-2xs);line-height:1}
331
- .pos-btn i{font-style:normal;font-size:var(--text-sm)}
332
- .pos-btn:hover{background:var(--accent);color:var(--accent-foreground)}
333
- .pos-btn:focus-visible{outline:2px solid var(--ring);outline-offset:1px}
334
- .pos-btn[aria-pressed="true"]{background:var(--accent);color:var(--brand);border-color:var(--ring);font-weight:500}
335
- /* a coarse pointer gets the 44px target R12 asks for; a mouse does not need the extra height */
336
- @media (pointer:coarse){.pos-btn{min-height:44px}.lay-act{min-width:44px;min-height:44px}.lay-row{padding:11px 8px}}
337
- .lay-add{display:block;width:100%;margin-top:4px;padding:9px;border:1px dashed var(--border);
338
- border-radius:var(--radius-md);font-size:var(--text-sm);color:var(--muted-foreground);
339
- transition:color var(--duration-fast) var(--ease-emphasized),
340
- border-color var(--duration-fast) var(--ease-emphasized)}
341
- .lay-add:hover{color:var(--foreground);border-color:var(--ring)}
342
- .lay-new{padding:6px 5px 2px}
343
- .lay-foot{font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.55;
344
- margin:9px 8px 4px;padding-top:8px;border-top:1px solid var(--border)}
345
- .lay-foot b{color:var(--foreground);font-weight:500}
346
-
347
- /* workspaces — one server, many repos; the row carries the switch + a forget affordance.
348
- The row is shadcn's SidebarMenuButton: no border, the --accent surface carries state. */
349
- .wsrow{display:flex;align-items:stretch}
350
- .ws{display:flex;align-items:center;gap:8px;flex:1;min-width:0;text-align:left;min-height:40px;padding:0 8px 0 12px;
351
- font-size:var(--text-sm);color:var(--sidebar-foreground);border-left:2px solid transparent;
352
- transition:background-color var(--duration-fast) var(--ease-emphasized)}
353
- .ws:hover{background:var(--accent)}
354
- .ws[aria-current="true"]{border-left-color:var(--brand);background:var(--accent);font-weight:500}
355
- .ws .cue{color:var(--muted-foreground);font-size:var(--text-2xs);flex:none}
356
- /* the repo NAME is a path fragment — mono earns its place here */
357
- .ws .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);font-size:var(--text-xs)}
358
- /* shadcn Badge, `outline` variant */
359
- .ws .tag{font-size:var(--text-2xs);font-weight:500;color:var(--muted-foreground);
360
- border:1px solid var(--border);border-radius:var(--radius-sm);padding:1px 6px;flex:none}
361
- .ws small{margin-left:auto;font-size:var(--text-2xs);font-weight:500;color:var(--success);flex:none}
362
- .wsrow .forget{width:30px;display:grid;place-items:center;color:var(--muted-foreground);font-size:var(--text-xs);opacity:0}
363
- .wsrow:hover .forget,.wsrow .forget:focus-visible{opacity:1}
364
- .wsrow .forget:hover{color:var(--destructive)}
365
-
366
- /* one line, always: at 13px the full label wraps inside a 262px sidebar and the dashed box grows
367
- into a two-line slab. It ellipsizes instead — the + and the first words carry the meaning. */
368
- .newsess{display:flex;gap:8px;align-items:center;margin:10px 12px 4px;min-height:38px;padding:0 12px;
369
- border:1px dashed var(--border);border-radius:var(--radius-md);font-size:var(--text-xs);
370
- color:var(--muted-foreground);width:calc(100% - 24px);
371
- white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
372
- transition:color var(--duration-fast) var(--ease-emphasized),
373
- border-color var(--duration-fast) var(--ease-emphasized)}
374
- .newsess:hover{color:var(--foreground);border-color:var(--ring)}
375
- .newsess i{font-style:normal}
376
-
377
- /* ── inline forms: name a session before it starts · add a repo by picking a folder.
378
- These are the shadcn Field/Label/Input/Button primitives: a 13px medium label above a
379
- 36px input with a hairline --input border, and a filled primary + ghost cancel below. ── */
380
- .miniform{margin:8px 12px 6px;display:flex;flex-direction:column;gap:8px}
381
- .miniform[hidden]{display:none}
382
- .miniform .lbl{font-size:var(--text-sm);font-weight:500;color:var(--foreground)}
383
- .miniform input{min-height:36px;padding:0 12px;border:1px solid var(--input);border-radius:var(--radius-md);
384
- background:transparent;color:var(--foreground);font-family:var(--sans);font-size:var(--text-sm);
385
- outline:none;width:100%;
386
- transition:border-color var(--duration-fast) var(--ease-emphasized),
387
- box-shadow var(--duration-fast) var(--ease-emphasized)}
388
- .miniform input::placeholder{color:var(--muted-foreground)}
389
- .miniform input:focus{border-color:var(--ring);box-shadow:0 0 0 3px var(--brand-wash)}
390
- .miniform .row{display:flex;gap:8px}
391
- /* Button, `default` variant — a filled brand action, not an outlined one */
392
- .miniform button{min-height:36px;padding:0 14px;border:1px solid transparent;border-radius:var(--radius-md);
393
- background:var(--primary);font-size:var(--text-sm);font-weight:500;color:var(--primary-foreground);
394
- transition:opacity var(--duration-fast) var(--ease-emphasized),
395
- background-color var(--duration-fast) var(--ease-emphasized)}
396
- .miniform button:hover{opacity:.9}
397
- /* `ghost` variant — the dismissive half of a pair never competes with the primary */
398
- .miniform button.quiet{background:transparent;color:var(--muted-foreground)}
399
- .miniform button.quiet:hover{background:var(--accent);color:var(--accent-foreground);opacity:1}
400
- /* the primary way to add a repo: the machine's own folder chooser, not a typed path. `outline`
401
- variant so it reads as a distinct choice rather than a second submit. */
402
- .miniform .pick{min-height:40px;background:transparent;border-color:var(--input);
403
- color:var(--foreground);font-size:var(--text-sm);display:flex;align-items:center;justify-content:center;gap:8px}
404
- .miniform .pick:hover{background:var(--accent);opacity:1}
405
- .miniform .hint{font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.5}
406
- .miniform .hint code{font-family:var(--mono);font-size:var(--text-2xs);background:var(--muted);
407
- padding:1px 5px;border-radius:var(--radius-sm);color:var(--foreground)}
408
- /* shadcn ToggleGroup: one inset track, the selected item lifts onto the --background surface */
409
- .seg{display:flex;gap:2px;border:1px solid var(--border);border-radius:var(--radius-md);
410
- background:var(--muted);padding:2px}
411
- .seg button{flex:1;min-height:30px;border:0;border-radius:var(--radius-sm);background:transparent;
412
- color:var(--muted-foreground);font-size:var(--text-sm);font-weight:500;padding:0;
413
- transition:background-color var(--duration-fast) var(--ease-emphasized),
414
- color var(--duration-fast) var(--ease-emphasized)}
415
- .seg button:hover{color:var(--foreground)}
416
- .seg button[aria-checked="true"]{background:var(--background);color:var(--foreground);
417
- box-shadow:0 1px 2px var(--shadow)}
418
-
419
- /* ── running agents ── */
420
- .sessrow{display:flex;align-items:stretch;position:relative}
421
- .sess{display:block;flex:1;min-width:0;text-align:left;padding:7px 4px 7px 11px;
422
- border-left:3px solid transparent;min-height:44px}
423
- .sess:hover,.sessrow:hover .sess{background:var(--accent)}
424
- .sess[aria-current="true"]{background:var(--accent);border-left-color:var(--brand)}
425
- .sessrow:has(.sess[aria-current="true"]){background:var(--accent)}
426
- .sess .r1{display:flex;align-items:center;gap:7px}
427
- .sess .st{width:11px;text-align:center;font-size:var(--text-xs);flex:none}
428
- .sess[data-state="working"] .st{color:var(--success);animation:pulse 2.2s infinite}
429
- /* The five presented states take five distinct hues, because R8 requires hue to carry the state
430
- on its own (as shape and word each do). green working · yellow quiet · blue NEEDS YOU ·
431
- red MAYBE BLOCKED · grey exited. `needs` takes the BRAND hue rather than a danger one: a
432
- finished turn is an invitation, not a failure, and red is reserved for the state that may be a
433
- problem. (It read `--accent` before the shadcn port; under that palette --accent is the muted
434
- hover SURFACE, so the brand hue is now --brand. Same intent, correct token.)
435
- `blocked` was styled --warn while it was dead code; it is defined for real now, and must not
436
- share `quiet`'s hue — a weak claim that looks exactly like no claim communicates nothing. */
437
- .sess[data-state="needs"] .st{color:var(--brand)}
438
- .sess[data-state="blocked"] .st{color:var(--destructive)}
439
- .sess[data-state="done"] .st{color:var(--info)}
440
- .sess[data-state="idle"] .st,.sess[data-state="exited"] .st{color:var(--muted-foreground)}
441
- @media (prefers-reduced-motion:reduce){.sess .st,.bar .conn.live::before{animation:none!important}}
442
- .sess .nm{font-size:var(--text-sm);font-weight:500;color:var(--foreground);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
443
- .sess .sub{font-size:var(--text-xs);color:var(--muted-foreground);margin:2px 0 0 18px;display:block;
444
- overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
445
- .sess[data-state="needs"] .sub{color:var(--brand)}
446
- .sess[data-state="blocked"] .sub{color:var(--destructive)}
447
- /* "opening focus" — the permanent lead label on the run-title sub-line. It states plainly that the
448
- title is the run's FIRST prompt (frozen, no timestamp), never its current activity. */
449
- .sess .sub .lead{font-size:var(--text-2xs);font-weight:500;color:var(--muted-foreground);margin-right:6px}
450
- /* ── harness tower (workspace-harness-tower): the state chip, the agent's own last words,
451
- and the per-session harness drill-in. State is carried by SHAPE (the glyph), HUE, and the
452
- WORD in the chip — three channels, so nothing depends on colour alone. ── */
453
- .sess[data-state="quiet"] .st{color:var(--warning)}
454
- /* shadcn Badge, `secondary` variant — the state WORD, one of the three channels state travels on */
455
- .sess .chip{margin-left:auto;flex:none;font-size:var(--text-2xs);font-weight:500;
456
- color:var(--muted-foreground);white-space:nowrap;background:var(--muted);
457
- border-radius:var(--radius-sm);padding:2px 7px}
458
- .sess[data-state="working"] .chip{color:var(--success)}
459
- .sess[data-state="quiet"] .chip{color:var(--warning)}
460
- .sess[data-state="needs"] .chip{color:var(--brand)}
461
- .sess[data-state="blocked"] .chip{color:var(--destructive)}
462
- .sess[data-state="exited"] .chip{color:var(--muted-foreground)}
463
- /* the last words WRAP — bounded to two lines here, in full in the terminal. The shipped .sub
464
- stays nowrap; this is a separate line, so nothing existing changes shape. */
465
- .sess .says{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
466
- margin:4px 0 0 18px;font-size:var(--text-xs);line-height:1.5;color:var(--muted-foreground)}
467
- .sess .says.na{color:var(--muted-foreground);font-style:italic}
468
- .sess[aria-current="true"] .says{color:var(--foreground)}
469
-
470
- details.hz{margin:0 8px 4px 14px}
471
- details.hz>summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:6px;
472
- min-height:44px;font-size:var(--text-xs);color:var(--muted-foreground)}
473
- details.hz>summary::-webkit-details-marker{display:none}
474
- details.hz>summary::before{content:"▸";font-size:var(--text-2xs)}
475
- details.hz[open]>summary::before{content:"▾"}
476
- details.hz>summary:hover{color:var(--foreground)}
477
- details.hz .sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
478
- details.hz .kv{display:grid;grid-template-columns:72px minmax(0,1fr);gap:6px 10px;padding:0 0 10px 15px}
479
- details.hz .kv dt{font-size:var(--text-xs);color:var(--muted-foreground);padding-top:1px}
480
- details.hz .kv dd{font-size:var(--text-xs);line-height:1.5;color:var(--foreground);min-width:0;overflow-wrap:anywhere}
481
- details.hz .kv dd b{color:var(--foreground);font-weight:500}
482
- /* an unavailable fact is DRAWN as unavailable — never as a plausible constant */
483
- details.hz .kv dd.na{color:var(--muted-foreground);font-style:italic}
484
- details.hz .kv dd.na::before{content:"— ";font-style:normal}
485
- details.hz .kv .src{font-family:var(--mono);font-size:var(--text-2xs);color:var(--muted-foreground)}
486
-
487
- /* rename affordance — the name is a guess at creation; it must stay editable (R11) */
488
- .sessrow .ren{width:30px;flex:none;display:grid;place-items:center;color:var(--muted-foreground);font-size:var(--text-xs);opacity:0}
489
- .sessrow:hover .ren,.sessrow .ren:focus-visible{opacity:1}
490
- .sessrow .ren:hover{color:var(--brand)}
491
- .renbox{width:100%;min-height:44px;padding:0 10px;border:1px solid var(--brand);border-radius:var(--radius-md);
492
- background:var(--secondary);color:var(--foreground);font-family:var(--mono);font-size:var(--text-xs);outline:none}
493
- .sessrow .renbox{margin:0 8px}
494
-
495
- /* ── terminal column ── */
496
- .term-col{display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--term-bg)}
497
- /* Terminal GROUPS (R6): one by default, two side by side when the layout says split. Each group
498
- owns a tab strip and a host; the #needs strip and the scratchpad stay with the column. */
499
- .groups{flex:1;min-height:0;min-width:0;display:flex;flex-direction:row}
500
- .group{flex:1 1 0;min-width:0;min-height:0;display:flex;flex-direction:column;background:var(--term-bg)}
501
- .group[hidden]{display:none}
502
- .group+.group{border-left:1px solid var(--border)}
503
- .group[data-focus="true"] .stabs{box-shadow:inset 0 2px 0 var(--brand)}
504
- .groups[data-split="off"] .group[data-focus="true"] .stabs{box-shadow:none}
505
- .stabs{display:flex;gap:2px;padding:6px 8px 0;background:var(--muted);flex:none;
506
- border-bottom:1px solid var(--border);overflow-x:auto;min-height:44px;align-items:flex-end}
507
- /* tab = wrap of two SIBLING buttons (select + close) — valid interactive structure */
508
- .stab-wrap{flex:none;display:inline-flex;align-items:center;gap:0;
509
- border:1px solid transparent;border-bottom:0;border-radius:var(--radius-md) var(--radius-md) 0 0}
510
- .stab-wrap[data-active="true"]{background:var(--term-bg);border-color:var(--border)}
511
- .stab{display:inline-flex;align-items:center;gap:7px;min-height:38px;padding:0 6px 0 12px;
512
- font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground)}
513
- /* The ACTIVE tab is painted in --term-bg so it reads as continuous with the terminal below it —
514
- and --term-bg is dark in BOTH themes (the terminal is a terminal). So its label has to come
515
- from the terminal's own foreground, not the page's: --foreground here is near-black in light
516
- mode, which rendered the active tab as black text on a black tab. */
517
- .stab-wrap[data-active="true"] .stab{color:var(--xt-brwhite)}
518
- .stab .g{font-size:var(--text-xs)}
519
- .stab-wrap[data-state="needs"] .g{color:var(--brand)} .stab-wrap[data-state="blocked"] .g{color:var(--destructive)}
520
- .stab-wrap[data-state="working"] .g{color:var(--success)}
521
- .stab-wrap[data-state="done"] .g{color:var(--info)}
522
- .stab-wrap[data-state="quiet"] .g{color:var(--warning)}
523
- .stab-wrap[data-state="idle"] .g,.stab-wrap[data-state="exited"] .g{color:var(--muted-foreground)}
524
- .stab-wrap .x{width:26px;min-height:38px;display:grid;place-items:center;border-radius:var(--radius-sm);
525
- color:var(--muted-foreground);font-size:var(--text-sm);margin-right:4px}
526
- .stab-wrap .x:hover{background:var(--accent);color:var(--accent-foreground)}
527
- /* on the dark active tab the hover surface has to be light, or the ✕ vanishes into it */
528
- .stab-wrap[data-active="true"] .x{color:var(--xt-brblack)}
529
- .stab-wrap[data-active="true"] .x:hover{background:rgba(255,255,255,.12);color:var(--xt-brwhite)}
530
- .stab-wrap .renbox{min-height:32px;width:150px;margin:0 6px 3px}
531
-
532
- .termhost{flex:1;position:relative;min-height:0;overflow:hidden}
533
- .termpane{position:absolute;inset:0;padding:8px 8px 6px 10px;display:none}
534
- .termpane.on{display:block}
535
- .termpane .xterm{height:100%}
536
- /* Touch scrollback: xterm's .xterm-viewport owns the scroll, but iOS Safari won't pan it by swipe
537
- without an explicit touch-action + momentum flag (the terminal otherwise swallows the gesture).
538
- Presentation-only; harmless on pointer devices. */
539
- .termpane .xterm .xterm-viewport{touch-action:pan-y;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
540
- .termpane .xterm .xterm-screen{touch-action:pan-y}
541
- /* scoped to termhost (its positioned ancestor) — sidebar/tabs/needs stay clickable */
542
- .exited-overlay{position:absolute;inset:0;z-index:5;display:none;place-items:center;background:var(--glass)}
543
- .exited-overlay.on{display:grid}
544
- .exited-overlay .card{border:1px solid var(--input);border-radius:var(--radius-lg);background:var(--sidebar);
545
- padding:16px 18px;text-align:center;max-width:340px}
546
- .exited-overlay .card p{font-size:var(--text-sm);color:var(--foreground);margin-bottom:10px}
547
- .exited-overlay .card .reason{display:block;margin-top:6px;font-family:var(--mono);font-size:var(--text-xs);
548
- color:var(--warning);line-height:1.45;max-width:300px}
549
- .exited-overlay .card .row{display:flex;gap:8px;justify-content:center;flex-wrap:wrap}
550
- .exited-overlay .card button{min-height:44px;padding:0 16px;border:1px solid var(--brand);border-radius:var(--radius-md);
551
- background:var(--secondary);font-family:var(--mono);font-size:var(--text-xs);color:var(--brand)}
552
- .exited-overlay .card button.quiet{border-color:var(--input);color:var(--muted-foreground)}
553
- .exited-overlay .card button.quiet:hover{border-color:var(--destructive);color:var(--foreground)}
554
- /* a workspace with no sessions says so — it never shows another workspace's terminal */
555
- .empty-overlay{position:absolute;inset:0;z-index:4;display:none;place-items:center;padding:20px}
556
- .empty-overlay.on{display:grid}
557
- .empty-overlay .card{border:1px dashed var(--input);border-radius:var(--radius-lg);background:var(--sidebar);
558
- padding:16px 18px;text-align:center;max-width:360px}
559
- .empty-overlay .card p{font-size:var(--text-sm);color:var(--foreground)}
560
- .empty-overlay .card .reason{margin-top:6px;font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.45}
561
-
562
- /* needs-you strips */
563
- .needs{border-top:1px solid var(--warning);background:var(--warning-wash);padding:10px 14px 12px;flex:none;
564
- max-height:38vh;overflow-y:auto}
565
- .needs.accept{border-top-color:var(--info);background:var(--info-wash)}
566
- .needs .k{font-size:var(--text-xs);color:var(--warning)}
567
- .needs.accept .k{color:var(--info)}
568
- .needs .q{font-size:var(--text-sm);color:var(--foreground);line-height:1.5;margin:4px 0 9px;max-width:90ch}
569
- .needs .row{display:flex;flex-wrap:wrap;align-items:center;gap:8px;font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground)}
570
- .dlink{display:inline-flex;align-items:center;min-height:44px;padding:0 6px;color:var(--brand);text-decoration:underline}
571
- .gbtn{display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 16px;border:1px solid var(--input);
572
- border-radius:var(--radius-lg);background:var(--secondary);font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground)}
573
- .gbtn:hover{border-color:var(--warning);color:var(--foreground)}
574
- .needs.accept .gbtn:hover{border-color:var(--info)}
575
- .gbtn.primary{border-color:var(--warning)} .needs.accept .gbtn.primary{border-color:var(--info)}
576
- .wpath{width:100%;font-size:var(--text-xs);color:var(--muted-foreground);margin-top:2px}
577
-
578
- /* ── right rail: the library over the document reader ── */
579
- .rail{border-left:1px solid var(--input);background:var(--sidebar);position:relative;
580
- display:flex;flex-direction:column;min-height:0;min-width:0}
581
- /* drag the rail's own edge — a document read at 340px is a column of ten words */
582
- .railgrip{position:absolute;left:-4px;top:0;bottom:0;width:8px;z-index:5;cursor:col-resize}
583
- .railgrip::after{content:"";position:absolute;inset:0 3px;border-radius:var(--radius-sm);background:transparent}
584
- .railgrip:hover::after,.railgrip:focus-visible::after{background:var(--brand)}
585
- .rail .lib-pane{flex:1 1 var(--libsplit);min-height:34px}
586
- .rail .doc-pane{flex:1 1 calc(100% - var(--libsplit));min-height:34px}
587
- .rail .doc-pane[hidden]{display:none}
588
- .rail .pane[data-fold="off"]{flex:0 0 auto}
589
- .railsplit{flex:none;height:7px;cursor:row-resize;background:var(--muted);
590
- border-block:1px solid var(--border);position:relative}
591
- .railsplit[hidden]{display:none}
592
- .railsplit::after{content:"";position:absolute;inset:2px 42% 2px 42%;border-radius:var(--radius-sm);background:var(--input)}
593
- .railsplit:hover::after,.railsplit:focus-visible::after{background:var(--brand)}
594
-
595
- /* library — two lenses over one file set: initiatives (how the PM thinks) / folders (how the
596
- repo is laid out). The initiative lens joins a unit of work's scattered artifacts. */
597
- /* shadcn Tabs: an inset --muted track, the selected lens lifted onto --background. Four lenses
598
- have to survive a narrow rail, so the group is allowed to SHRINK and scroll rather than push
599
- the refresh control off the end of the header — which is what a fixed-width group did. */
600
- .lens{margin-left:auto;display:inline-flex;gap:2px;border-radius:var(--radius-md);
601
- background:var(--muted);padding:2px;min-width:0;overflow-x:auto;scrollbar-width:none}
602
- .lens::-webkit-scrollbar{display:none}
603
- .lens button{min-height:24px;padding:0 7px;font-size:var(--text-2xs);font-weight:500;flex:none;
604
- border-radius:var(--radius-sm);color:var(--muted-foreground);background:transparent;
605
- transition:background-color var(--duration-fast) var(--ease-emphasized),
606
- color var(--duration-fast) var(--ease-emphasized)}
607
- .lens button:hover{color:var(--foreground)}
608
- .lens button[aria-selected="true"]{background:var(--background);color:var(--foreground);
609
- box-shadow:0 1px 2px var(--shadow)}
610
- /* shadcn Input */
611
- .libfind{margin:8px 12px 4px;min-height:34px;padding:0 12px;width:calc(100% - 24px);
612
- border:1px solid var(--input);border-radius:var(--radius-md);background:transparent;color:var(--foreground);
613
- font-family:var(--sans);font-size:var(--text-sm);outline:none;
614
- transition:border-color var(--duration-fast) var(--ease-emphasized),
615
- box-shadow var(--duration-fast) var(--ease-emphasized)}
616
- .libfind::placeholder{color:var(--muted-foreground)}
617
- .libfind:focus{border-color:var(--ring);box-shadow:0 0 0 3px var(--brand-wash)}
618
- .grp{font-size:var(--text-2xs);
619
- color:var(--muted-foreground);padding:8px 14px 4px}
620
- details.init{margin:0}
621
- details.init>summary{list-style:none;cursor:pointer;min-height:38px;display:flex;align-items:center;gap:7px;
622
- padding:0 14px;font-family:var(--mono);font-size:var(--text-xs);color:var(--foreground)}
623
- details.init>summary::-webkit-details-marker{display:none}
624
- details.init>summary::before{content:"▸";font-size:var(--text-2xs);color:var(--muted-foreground);transition:transform .12s;flex:none}
625
- details.init[open]>summary::before{transform:rotate(90deg)}
626
- @media (prefers-reduced-motion:reduce){details.init>summary::before{transition:none}}
627
- details.init>summary:hover{background:var(--accent)}
628
- details.init .iid{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
629
- details.init .n{font-size:var(--text-2xs);color:var(--muted-foreground);border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 4px;flex:none}
630
- details.init .ititle{display:none}
631
- .doc.art{display:flex;align-items:center;gap:8px;padding-left:28px}
632
- .doc.art .role{flex:none;width:66px;font-size:var(--text-2xs);color:var(--muted-foreground)}
633
- .doc.art .role[data-role="PRD"]{color:var(--brand)}
634
- .doc.art .role[data-role="rubric"],.doc.art .role[data-role="eval"]{color:var(--info)}
635
- .doc.art .role[data-role="design brief"],.doc.art .role[data-role="design"]{color:var(--warning)}
636
- .doc.art .dn{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
637
- details.tree{margin:0}
638
- details.tree>summary{list-style:none;cursor:pointer;min-height:38px;display:flex;align-items:center;gap:7px;
639
- padding:0 14px;font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground)}
640
- details.tree>summary::-webkit-details-marker{display:none}
641
- details.tree>summary::before{content:"▸";font-size:var(--text-2xs);color:var(--muted-foreground);transition:transform .12s;flex:none}
642
- details.tree[open]>summary::before{transform:rotate(90deg)}
643
- @media (prefers-reduced-motion:reduce){details.tree>summary::before{transition:none}}
644
- details.tree>summary:hover{color:var(--foreground)}
645
- .tree .tree>summary{padding-left:28px}
646
- .tree .tree .tree>summary{padding-left:42px}
647
- .doc{display:block;width:100%;text-align:left;color:var(--muted-foreground);font-size:var(--text-xs);
648
- padding:5px 14px 5px 30px;min-height:36px;line-height:1.3;border-left:3px solid transparent;font-family:var(--mono)}
649
- .tree .tree .doc{padding-left:44px}
650
- .tree .tree .tree .doc{padding-left:58px}
651
- .doc:hover{color:var(--foreground);background:var(--accent)}
652
- .doc.on{color:var(--brand);border-left-color:var(--brand);font-weight:600}
653
- /* a non-markdown file: shown so the folder map is complete, but inert (the reader is .md-only) */
654
- .file{display:block;width:100%;text-align:left;color:var(--muted-foreground);font-size:var(--text-xs);
655
- padding:5px 14px 5px 30px;min-height:36px;line-height:1.3;border-left:3px solid transparent;
656
- font-family:var(--mono);opacity:.62;cursor:default}
657
- .tree .tree .file{padding-left:44px}
658
- .tree .tree .tree .file{padding-left:58px}
659
- /* the library refresh (↻): hugs the lens toggle, spins briefly on click */
660
- .cap .librefresh{margin-left:6px;width:26px;height:26px;flex:none}
661
- .librefresh.spin{animation:libspin .5s linear}
662
- @keyframes libspin{from{transform:rotate(0)}to{transform:rotate(360deg)}}
663
- @media (prefers-reduced-motion:reduce){.librefresh.spin{animation:none}}
664
- .empty{padding:10px 16px;font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.5}
665
- .empty b{color:var(--foreground)}
666
-
667
- /* ── the document reader (bottom of the rail) ── */
668
- .doc-pane .cap{padding-right:6px;gap:6px}
669
- /* the crumb is a FILE PATH — mono earns its place. It yields space to the controls beside it
670
- rather than shouldering them off the end of the header. */
671
- .doc-pane .crumb{margin-left:auto;font-family:var(--mono);font-size:var(--text-2xs);
672
- color:var(--muted-foreground);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
673
- direction:rtl;text-align:right;max-width:50%;min-width:0;flex:0 1 auto}
674
- /* `ghost` icon button, matching the other cap controls instead of being the one outlined box */
675
- .doc-pane .x{flex:none;width:28px;height:28px;display:grid;place-items:center;border-radius:var(--radius-sm);
676
- border:0;background:transparent;color:var(--muted-foreground);font-size:var(--text-sm);
677
- transition:background-color var(--duration-fast) var(--ease-emphasized),
678
- color var(--duration-fast) var(--ease-emphasized)}
679
- .doc-pane .x:hover{background:var(--destructive);color:var(--primary-foreground)}
680
- .doc-body{overflow-y:auto;overscroll-behavior:contain;flex:1;min-height:0;
681
- padding:18px 22px 64px;line-height:1.65;font-size:14px;color:var(--foreground)}
682
- .doc-body>*{max-width:72ch}
683
- .doc-body h1{font-size:21px;font-weight:600;line-height:1.3;margin:4px 0 12px;color:var(--foreground);text-wrap:balance}
684
- .doc-body h2{font-size:16px;font-weight:600;line-height:1.35;margin:26px 0 8px;color:var(--foreground);
685
- padding-bottom:5px;border-bottom:1px solid var(--border)}
686
- .doc-body h3{font-size:14px;font-weight:600;margin:20px 0 6px;color:var(--foreground)}
687
- .doc-body h4,.doc-body h5,.doc-body h6{font-size:var(--text-sm);font-weight:600;margin:16px 0 5px;color:var(--muted-foreground)}
688
- .doc-body p{margin:0 0 12px}
689
- .doc-body ul,.doc-body ol{margin:0 0 12px;padding-left:22px}
690
- .doc-body li{margin:0 0 5px;padding-left:2px}
691
- .doc-body li>ul,.doc-body li>ol{margin:5px 0 0}
692
- .doc-body li::marker{color:var(--muted-foreground)}
693
- .doc-body ul.task{list-style:none;padding-left:6px}
694
- .doc-body ul.task li{display:flex;gap:8px;align-items:baseline}
695
- .doc-body ul.task .box{flex:none;font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground)}
696
- .doc-body ul.task .box.done{color:var(--success)}
697
- .doc-body code{font-family:var(--mono);font-size:var(--text-sm);color:var(--brand);background:var(--secondary);
698
- padding:1.5px 5px;border-radius:var(--radius-sm);word-break:break-word}
699
- .doc-body pre{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-md);
700
- padding:12px 14px;overflow-x:auto;margin:0 0 14px;max-width:100%}
701
- .doc-body pre code{background:none;padding:0;color:var(--muted-foreground);font-size:var(--text-sm);line-height:1.6;word-break:normal}
702
- .doc-body pre .lang{display:block;font-family:var(--mono);font-size:var(--text-2xs);
703
- color:var(--muted-foreground);margin-bottom:7px}
704
- .doc-body blockquote{border-left:3px solid var(--input);background:var(--card);
705
- padding:9px 14px;margin:0 0 14px;border-radius:0 var(--radius-md) var(--radius-md) 0;color:var(--muted-foreground)}
706
- .doc-body blockquote p:last-child{margin-bottom:0}
707
- .doc-body hr{border:0;border-top:1px solid var(--border);margin:22px 0}
708
- .doc-body a{color:var(--brand);text-decoration:underline;text-underline-offset:2px}
709
- .doc-body a:hover{color:var(--brand)}
710
- .doc-body strong{color:var(--foreground);font-weight:600}
711
- .doc-body del{color:var(--muted-foreground)}
712
- /* tables (rubrics ARE tables) — scroll inside their own box, never the page */
713
- .doc-body .tablewrap{overflow-x:auto;margin:0 0 14px;border:1px solid var(--border);border-radius:var(--radius-md);max-width:100%}
714
- .doc-body table{border-collapse:collapse;width:100%;font-size:var(--text-sm)}
715
- .doc-body th,.doc-body td{text-align:left;padding:8px 11px;border-bottom:1px solid var(--border);vertical-align:top}
716
- .doc-body th{background:var(--muted);color:var(--foreground);font-weight:600;font-size:var(--text-sm);
717
- letter-spacing:.03em;white-space:nowrap}
718
- .doc-body tbody tr:nth-child(even){background:var(--card)}
719
- .doc-body tbody tr:last-child td{border-bottom:0}
720
- /* the identity block every PMOS artifact opens with, as a card instead of raw YAML */
721
- .doc-body .fm{border:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg);
722
- padding:10px 12px;margin:0 0 18px;display:grid;grid-template-columns:auto 1fr;gap:4px 12px;
723
- font-size:var(--text-sm);max-width:72ch}
724
- .doc-body .fm dt{font-size:var(--text-2xs);
725
- color:var(--muted-foreground);padding-top:2px}
726
- .doc-body .fm dd{color:var(--foreground);min-width:0;overflow-wrap:anywhere}
727
- .doc-empty{padding:16px;color:var(--muted-foreground);font-size:var(--text-sm)}
728
-
729
- /* ── ⌘K jump palette + the in-app folder browser ── */
730
- .palette{position:fixed;inset:0;z-index:90;background:var(--glass);backdrop-filter:blur(3px);
731
- display:grid;place-items:start center;padding-top:12vh}
732
- .palette-box{width:min(560px,92vw);background:var(--sidebar);border:1px solid var(--input);
733
- border-radius:var(--radius-xl);overflow:hidden;box-shadow:0 24px 80px -24px var(--shadow)}
734
- .palette-box input{width:100%;min-height:48px;padding:0 16px;background:var(--muted);border:0;
735
- border-bottom:1px solid var(--border);color:var(--foreground);font-family:var(--mono);font-size:var(--text-base);outline:none}
736
- .palette-list{max-height:52vh;overflow-y:auto;padding:6px}
737
- .pitem{display:flex;align-items:center;gap:9px;width:100%;text-align:left;min-height:40px;padding:0 12px;
738
- border-radius:var(--radius-md);font-family:var(--mono);font-size:var(--text-sm);color:var(--muted-foreground)}
739
- .pitem .kind{font-size:var(--text-2xs);color:var(--muted-foreground);margin-left:auto}
740
- .pitem.sel,.pitem:hover{background:var(--accent);color:var(--foreground)}
741
- .pitem .g{font-size:var(--text-xs);color:var(--muted-foreground)}
742
- .pitem .badge{font-size:var(--text-2xs);color:var(--success);
743
- border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 4px;margin-left:auto}
744
- .fs-head{display:flex;align-items:center;gap:8px;padding:8px 10px;background:var(--muted);
745
- border-bottom:1px solid var(--border)}
746
- .fs-up{width:34px;min-height:34px;display:grid;place-items:center;border:1px solid var(--border);
747
- border-radius:var(--radius-md);background:var(--secondary);color:var(--muted-foreground)}
748
- .fs-up:hover{border-color:var(--brand);color:var(--brand)}
749
- .fs-crumb{flex:1;min-width:0;font-family:var(--mono);font-size:var(--text-xs);color:var(--foreground);
750
- overflow:hidden;text-overflow:ellipsis;white-space:nowrap;direction:rtl;text-align:left}
751
- .fs-use{min-height:34px;padding:0 12px;border:1px solid var(--brand);border-radius:var(--radius-md);
752
- background:var(--brand-wash);color:var(--brand);font-family:var(--mono);font-size:var(--text-xs)}
753
- .fs-head .x{width:34px;min-height:34px;display:grid;place-items:center;border:1px solid var(--border);
754
- border-radius:var(--radius-md);background:var(--secondary);color:var(--muted-foreground);font-size:var(--text-sm)}/* ── status strip ── */
755
- .strip{display:flex;align-items:center;gap:14px;padding:0 12px;border-top:1px solid var(--border);
756
- background:var(--muted);font-size:var(--text-xs);color:var(--muted-foreground);min-width:0}
757
- .strip span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
758
- /* `flex:none` here would pin the hint list at its full width and push the page into a horizontal
759
- scroll once the type got bigger than the 9.5px it was originally set at. It ellipsizes instead:
760
- the strip is the lowest-priority text on screen and must never widen the app. */
761
- .strip .right{margin-left:auto;color:var(--muted-foreground);flex:0 1 auto;min-width:0}
762
-
763
- /* ── on-demand surfaces (Plan · Deliver · Measure · Report), rendered in the reader ── */
764
- /* phase accents — status is NEVER hue-alone: every surface pairs colour with a glyph + label */
765
- .sf-wrap{--plan:var(--brand);--deliver:var(--success);--measure:var(--info);--report:var(--warning)}
766
- .sf-head{position:sticky;top:0;z-index:2;display:flex;align-items:center;gap:8px;flex-wrap:wrap;
767
- padding:12px 22px;background:var(--muted);border-bottom:1px solid var(--border);margin:0 0 4px}
768
- .sf-views{display:inline-flex;gap:6px;flex-wrap:wrap}
769
- .sf-views button{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);border:1px solid var(--border);
770
- border-radius:var(--radius-md);padding:4px 10px;background:var(--secondary)}
771
- .sf-views button:hover{border-color:var(--input);color:var(--foreground)}
772
- .sf-views button.on{border-color:var(--brand);color:var(--brand);background:var(--brand-wash)}
773
- .sf-chip{margin-left:auto;display:inline-flex;gap:6px;align-items:center;font-size:var(--text-2xs);
774
- letter-spacing:.05em;color:var(--success);border:1px solid var(--border);border-radius:99px;padding:3px 10px}
775
- .sf-chip::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--success)}
776
- .sf-body{padding:14px 22px 40px;display:flex;flex-direction:column;gap:16px}
777
- .sf-body .untr{color:var(--muted-foreground);font-style:italic;opacity:.75;font-size:var(--text-xs)}
778
- .sf-note{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.6;border-top:1px solid var(--border);padding-top:11px}
779
-
780
- /* focal band: what needs you (leads) */
781
- .sf-needs{border:1px solid var(--warning);border-radius:var(--radius-xl);overflow:hidden;
782
- background:radial-gradient(120% 140% at 0 0,var(--warning-wash),transparent 60%),var(--card)}
783
- .sf-needs .nh{display:flex;align-items:center;gap:9px;padding:12px 15px 9px}
784
- .sf-needs .nh .dot{width:8px;height:8px;border-radius:50%;background:var(--warning);flex:none;box-shadow:0 0 0 4px var(--warning-wash)}
785
- .sf-needs .nh b{font-size:var(--text-base);color:var(--foreground)}
786
- .sf-needs .nh .sub{font-family:var(--mono);font-size:var(--text-xs);color:var(--warning);margin-left:auto}
787
- .sf-needs .need{display:flex;align-items:center;gap:11px;padding:10px 15px;border-top:1px solid var(--border)}
788
- .sf-needs .need .ph{width:3px;align-self:stretch;border-radius:var(--radius-sm);background:var(--warning);flex:none}
789
- .sf-needs .need .txt{flex:1;min-width:0}
790
- .sf-needs .need .t{font-size:var(--text-sm);color:var(--foreground);line-height:1.45}
791
- .sf-needs .need .m{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);margin-top:3px}
792
- .sf-needs .need .go{flex:none;min-height:36px;padding:0 13px;border:1px solid var(--warning);border-radius:var(--radius-md);
793
- background:var(--secondary);font-family:var(--mono);font-size:var(--text-xs);color:var(--warning)}
794
- .sf-needs .need .go:hover{background:var(--warning-wash);color:var(--foreground)}
795
- .sf-needs.calm{border-color:var(--info)}
796
- .sf-needs.calm .nh .dot{background:var(--info);box-shadow:0 0 0 4px var(--info-wash)}
797
- .sf-needs.calm .nh .sub{color:var(--info)}
798
- .sf-needs.calm .calm-body{padding:2px 15px 13px;font-size:var(--text-sm);color:var(--muted-foreground);line-height:1.5}
799
-
800
- /* one restrained instrument (not a chart wall) */
801
- .sf-pulse{display:flex;align-items:center;gap:13px;flex-wrap:wrap}
802
- .sf-pulse .n{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground)}
803
- .sf-pulse .n b{color:var(--foreground);font-size:15px;font-weight:600}
804
- .sf-dist{flex:1;min-width:150px;height:8px;border-radius:99px;overflow:hidden;display:flex;background:var(--accent)}
805
- .sf-dist i{height:100%}
806
- .sf-dist i[data-phase="plan"]{background:var(--plan)} .sf-dist i[data-phase="deliver"]{background:var(--deliver)}
807
- .sf-dist i[data-phase="measure"]{background:var(--measure)} .sf-dist i[data-phase="report"]{background:var(--report)}
808
- .sf-legend{display:flex;gap:12px;flex-wrap:wrap;font-size:var(--text-2xs);color:var(--muted-foreground)}
809
-
810
- /* the list: rows with a phase spine,not a wall of identical cards */
811
- .sf-grp{font-size:var(--text-2xs);color:var(--muted-foreground);padding:4px 2px 2px}
812
- .sf-list{display:flex;flex-direction:column}
813
- .sf-row{border-top:1px solid var(--border)}
814
- .sf-row:first-child{border-top:0}
815
- .sf-row>summary{list-style:none;cursor:pointer;display:grid;grid-template-columns:3px auto 1fr auto auto;gap:11px;
816
- align-items:center;padding:11px 4px;min-height:54px}
817
- .sf-row>summary::-webkit-details-marker{display:none}
818
- .sf-row>summary:hover{background:var(--accent)}
819
- .sf-spine{width:3px;align-self:stretch;border-radius:var(--radius-sm);background:var(--input)}
820
- .sf-row[data-phase="plan"] .sf-spine,.sf-rcrow[data-phase="plan"] .sf-spine{background:var(--plan)}
821
- .sf-row[data-phase="deliver"] .sf-spine,.sf-rcrow[data-phase="deliver"] .sf-spine{background:var(--deliver)}
822
- .sf-row[data-phase="measure"] .sf-spine,.sf-rcrow[data-phase="measure"] .sf-spine{background:var(--measure)}
823
- .sf-row[data-phase="report"] .sf-spine,.sf-rcrow[data-phase="report"] .sf-spine{background:var(--report)}
824
- .sf-stat .g{font-size:var(--text-xs);color:var(--muted-foreground);white-space:nowrap}
825
- .sf-id{font-family:var(--mono);font-size:var(--text-sm);color:var(--foreground);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
826
- .sf-id .ti{display:block;font-family:var(--sans);font-size:var(--text-xs);color:var(--muted-foreground);margin-top:2px;
827
- overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
828
- .sf-metrics{display:flex;align-items:center;gap:13px;flex:none;font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground)}
829
- .sf-metrics .m{display:flex;flex-direction:column;gap:2px}
830
- .sf-metrics .k{font-size:var(--text-2xs);color:var(--muted-foreground)}
831
- .sf-metrics b{color:var(--brand);font-size:var(--text-base)}
832
- .sf-prog{width:52px;height:5px;border-radius:99px;background:var(--accent);overflow:hidden;display:block}
833
- .sf-prog i{display:block;height:100%;background:linear-gradient(90deg,var(--brand),var(--info))}
834
- .sf-chev{color:var(--muted-foreground);font-size:var(--text-xs);transition:transform .14s}
835
- .sf-row[open] .sf-chev{transform:rotate(90deg)}
836
- @media (prefers-reduced-motion:reduce){.sf-chev{transition:none}}
837
- .sf-detail{padding:2px 12px 15px 18px;display:grid;gap:11px;background:var(--muted)}
838
- .sf-detail h4{font-size:var(--text-2xs);color:var(--muted-foreground);margin-bottom:4px}
839
- .sf-detail p{font-size:var(--text-sm);color:var(--foreground);line-height:1.5}
840
- .sf-arts{display:flex;flex-wrap:wrap;gap:6px}
841
- .sf-art{display:inline-flex;align-items:center;gap:7px;font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);
842
- border:1px solid var(--border);border-radius:var(--radius-md);padding:4px 9px;background:var(--secondary)}
843
- .sf-art:hover{border-color:var(--brand);color:var(--brand)}
844
- .sf-art .role{font-size:var(--text-2xs);color:var(--muted-foreground)}
845
-
846
- /* roadmap (list-calendar) · okr · report */
847
- .sf-rc h4{font-family:var(--mono);font-size:var(--text-2xs);color:var(--brand);
848
- margin-bottom:6px;padding-bottom:5px;border-bottom:1px solid var(--border)}
849
- .sf-rcrow{display:grid;grid-template-columns:3px 1fr auto;gap:10px;align-items:center;padding:7px 2px}
850
- .sf-rcrow .nm{font-family:var(--mono);font-size:var(--text-xs);color:var(--foreground);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
851
- .sf-rcrow .st{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground)}
852
- .sf-kr{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);padding:13px;margin-bottom:2px}
853
- .sf-kr .obj{font-size:var(--text-base);color:var(--foreground);font-weight:600;margin-bottom:9px}
854
- .sf-kr .krrow{padding:8px 0;border-top:1px solid var(--border)}
855
- .sf-kr .krh{display:flex;gap:9px;align-items:baseline}
856
- .sf-kr .krh .lab{font-family:var(--mono);font-size:var(--text-xs);color:var(--info);flex:none}
857
- .sf-kr .krh span:last-child{font-size:var(--text-sm);color:var(--foreground)}
858
- .sf-kr .lev{margin-top:5px}
859
- .sf-rep .lead{font-size:var(--text-xs);color:var(--muted-foreground);margin-bottom:6px}
860
- .sf-rep h3{font-size:var(--text-base);color:var(--foreground);font-weight:600;margin:16px 0 6px;padding-bottom:5px;border-bottom:1px solid var(--border)}
861
- .sf-rep ul{margin:0;padding-left:20px}
862
- .sf-rep li{margin-bottom:5px;font-size:var(--text-sm);color:var(--foreground);line-height:1.5}
863
-
864
- /* honest can't-produce + loading */
865
- .sf-fail{border:1px dashed var(--input);border-radius:var(--radius-xl);background:var(--card);padding:24px;text-align:center}
866
- .sf-fail .mk{width:34px;height:34px;margin:0 auto 12px;display:grid;place-items:center;border-radius:var(--radius-lg);border:1px solid var(--input);color:var(--muted-foreground);font-size:16px}
867
- .sf-fail h3{font-size:14px;color:var(--foreground);margin-bottom:6px}
868
- .sf-fail p{font-size:var(--text-sm);color:var(--muted-foreground);line-height:1.6;max-width:48ch;margin:0 auto 5px}
869
- .sf-fail .miss{font-size:var(--text-xs);color:var(--warning)}
870
- .sf-fail code{font-family:var(--mono);color:var(--brand);background:var(--secondary);padding:1px 6px;border-radius:var(--radius-sm)}
871
- .sf-skel{display:flex;flex-direction:column;gap:11px}
872
- .sf-skel i{height:50px;border-radius:var(--radius-lg);background:linear-gradient(90deg,var(--card),var(--accent),var(--card));background-size:200% 100%;animation:sfsh 1.3s infinite}
873
- @keyframes sfsh{0%{background-position:200% 0}100%{background-position:-200% 0}}
874
- @media (prefers-reduced-motion:reduce){.sf-skel i{animation:none;opacity:.7}}
875
-
876
- /* ── the scheduled lens (a persistent third library lens, in the library pane) ── */
877
- .sc-load{padding:14px;color:var(--muted-foreground);font-size:var(--text-xs)}
878
- .sc-wrap{--plan:var(--brand);padding:8px 10px 12px}
879
- .sc-sum{display:flex;align-items:center;gap:9px;padding:9px 11px;border-radius:var(--radius-lg);background:var(--card);border:1px solid var(--border);margin-bottom:10px}
880
- .sc-sum .dot{width:7px;height:7px;border-radius:50%;background:var(--success);flex:none;box-shadow:0 0 0 4px var(--info-wash)}
881
- .sc-sum.warn .dot{background:var(--warning);box-shadow:0 0 0 4px var(--warning-wash)}
882
- .sc-sum .t{font-size:var(--text-sm);color:var(--foreground);min-width:0}
883
- .sc-sum .t b{color:var(--foreground)}
884
- .sc-new{margin-left:auto;min-height:30px;padding:0 11px;border:1px solid var(--brand);border-radius:var(--radius-md);background:var(--brand-wash);color:var(--brand);font-family:var(--mono);font-size:var(--text-xs);flex:none}
885
- .sc-list{display:flex;flex-direction:column;gap:7px}
886
- .sc-row{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);overflow:hidden}
887
- .sc-main{display:grid;grid-template-columns:3px auto 1fr auto;gap:10px;align-items:center;padding:10px 11px}
888
- .sc-rail{width:3px;align-self:stretch;border-radius:var(--radius-sm);background:var(--input)}
889
- .sc-row[data-health="armed"] .sc-rail{background:var(--brand)}
890
- .sc-row[data-health="running"] .sc-rail{background:var(--success);animation:pulse 1.6s infinite}
891
- .sc-row[data-health="failed"] .sc-rail{background:var(--destructive)}
892
- @media (prefers-reduced-motion:reduce){.sc-row[data-health="running"] .sc-rail{animation:none}}
893
- .sc-tog{position:relative;width:34px;height:20px;border-radius:99px;background:var(--accent);border:1px solid var(--input);flex:none;cursor:pointer;transition:background .15s}
894
- .sc-tog[aria-checked="true"]{background:var(--brand-wash);border-color:var(--brand)}
895
- .sc-tog .knob{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;background:var(--muted-foreground);transition:transform .15s,background .15s}
896
- .sc-tog[aria-checked="true"] .knob{transform:translateX(14px);background:var(--brand)}
897
- @media (prefers-reduced-motion:reduce){.sc-tog,.sc-tog .knob{transition:none}}
898
- .sc-id{min-width:0}
899
- .sc-id .nm{font-family:var(--mono);font-size:var(--text-sm);color:var(--foreground);display:flex;align-items:center;gap:6px;overflow:hidden}
900
- .sc-id .nm .g{color:var(--muted-foreground);font-size:var(--text-2xs);flex:none}
901
- .sc-id .nm .name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
902
- .sc-id .nm .skill{font-size:var(--text-2xs);color:var(--purple);border:1px solid var(--border);border-radius:var(--radius-sm);padding:1px 5px;flex:none}
903
- .sc-id .cad{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
904
- .sc-run{text-align:right;flex:none;font-size:var(--text-xs)}
905
- .sc-run .next{color:var(--brand)}
906
- .sc-run .fail{color:var(--destructive)}
907
- .sc-run .off{color:var(--muted-foreground)}
908
- .sc-more{display:flex;gap:6px;padding:0 11px 10px 24px}
909
- .sc-more button{min-height:30px;padding:0 9px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--secondary);font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground)}
910
- .sc-more .rn{border-color:var(--brand);color:var(--brand)}
911
- .sc-more button:hover{border-color:var(--input);color:var(--foreground)}
912
- .sc-more .rn:hover{background:var(--brand-wash)}
913
- .sc-empty{text-align:center;padding:22px 14px}
914
- .sc-empty .mk{width:30px;height:30px;margin:0 auto 10px;display:grid;place-items:center;border-radius:var(--radius-md);border:1px dashed var(--input);color:var(--muted-foreground);font-size:14px}
915
- .sc-empty p{font-size:var(--text-sm);color:var(--muted-foreground);line-height:1.55;max-width:32ch;margin:0 auto 11px}
916
- .sc-note{font-family:var(--mono);font-size:var(--text-2xs);color:var(--muted-foreground);line-height:1.6;border-top:1px solid var(--border);margin-top:11px;padding-top:10px}
917
- .sc-note b{color:var(--purple)}
918
- /* create form */
919
- .sc-form{border:1px solid var(--brand);border-radius:var(--radius-lg);background:var(--muted);padding:12px;display:grid;gap:9px;margin:0 0 10px}
920
- .sc-form label{font-size:var(--text-2xs);color:var(--muted-foreground);display:block;margin-bottom:4px}
921
- .sc-form input,.sc-form select{width:100%;min-height:34px;padding:0 9px;border:1px solid var(--input);border-radius:var(--radius-md);background:var(--secondary);color:var(--foreground);font-family:var(--mono);font-size:var(--text-xs);outline:none}
922
- .sc-form input:focus,.sc-form select:focus{border-color:var(--brand)}
923
- .sc-f2{display:grid;grid-template-columns:1fr 1fr;gap:8px}
924
- .sc-seg{display:flex;border:1px solid var(--border);border-radius:var(--radius-md);overflow:hidden}
925
- .sc-seg button{flex:1;min-height:32px;background:var(--secondary);color:var(--muted-foreground);font-family:var(--mono);font-size:var(--text-2xs)}
926
- .sc-seg button+button{border-left:1px solid var(--border)}
927
- .sc-seg button[aria-pressed="true"]{background:var(--accent);color:var(--brand)}
928
- .sc-hint{font-size:var(--text-2xs);color:var(--muted-foreground);line-height:1.5}
929
- .sc-hint b{color:var(--success)}
930
- .sc-frow{display:flex;gap:8px}
931
- .sc-form .save{min-height:36px;padding:0 13px;border:1px solid var(--brand);border-radius:var(--radius-md);background:var(--brand-wash);color:var(--brand);font-family:var(--mono);font-size:var(--text-xs)}
932
- .sc-form .cancel{min-height:36px;padding:0 11px;border:1px solid var(--border);border-radius:var(--radius-md);background:var(--secondary);color:var(--muted-foreground);font-family:var(--mono);font-size:var(--text-xs)}
933
- /* New Skill flow — the GUI that replaces editing server code (workspace-skill-authoring) */
934
- .sc-acts{margin-left:auto;display:flex;gap:6px;flex:none}
935
- .sc-new.ghost{border-color:var(--input);background:var(--secondary);color:var(--muted-foreground)}
936
- .sc-new.ghost:hover{border-color:var(--purple);color:var(--purple)}
937
- .sc-form textarea{width:100%;min-height:34px;padding:7px 9px;border:1px solid var(--input);border-radius:var(--radius-md);background:var(--secondary);color:var(--foreground);font-family:var(--mono);font-size:var(--text-xs);outline:none;resize:vertical;line-height:1.5}
938
- .sc-form textarea:focus{border-color:var(--brand)}
939
- .sk-form{border-color:var(--purple)}
940
- .sk-head{font-family:var(--mono);font-size:var(--text-xs);color:var(--foreground);display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
941
- .sk-head .sk-sub{font-size:var(--text-2xs);letter-spacing:.04em;color:var(--muted-foreground);text-transform:none}
942
- .sc-ai{min-height:36px;padding:0 11px;border:1px solid var(--purple);border-radius:var(--radius-md);background:var(--accent);color:var(--purple);font-family:var(--mono);font-size:var(--text-xs)}
943
- .sc-ai:hover{background:var(--brand-wash)}
944
- .needs.report{border-top-color:var(--info);background:var(--info-wash)}
945
- .needs.report .k{color:var(--info)}/* a session that fired from a schedule carries a small badge */
946
- .sess .schtag{margin-left:6px;font-size:var(--text-2xs);color:var(--purple);
947
- border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 4px;vertical-align:middle}
948
-
949
- /* Narrow: the rail floats over the terminal instead of squeezing it below a usable width. */
950
- @media (max-width:1100px){
951
- /* applyLayout() drops the reader's track from the template at this width and sets data-float,
952
- so the grid here is sidebar + terminal and the reader floats over the terminal rather than
953
- squeezing it below a usable width. Docked BOTTOM it keeps its row and does not float. */
954
- .body[data-float="on"]>.rail{position:absolute;top:0;right:0;bottom:0;left:auto;
955
- width:min(420px,86vw);z-index:30;box-shadow:-18px 0 50px -30px var(--shadow)}
956
- .body[data-float="on"][data-reader="left"]>.rail{right:auto;left:0;
957
- box-shadow:18px 0 50px -30px var(--shadow)}/* Split is forced OFF below this width by applyLayout() — two terminal groups inside what is
958
- left of a narrow window is two unusable terminals. The layout menu says so rather than
959
- silently ignoring the choice (R9). */
960
- .lay-narrow{display:block}
961
- }
962
- .lay-narrow{display:none;font-size:var(--text-xs);color:var(--warning);
963
- line-height:1.5;margin:6px 5px 0}
964
-
965
- /* history lens — episodic recall over this workspace's own session scrollback */
966
- .hi-hint{padding:14px;color:var(--muted-foreground);font-size:var(--text-xs);line-height:1.6}
967
- .hi-list{display:flex;flex-direction:column;gap:7px;padding:8px 10px 12px}
968
- .hi-row{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);padding:9px 11px}
969
- .hi-head{display:flex;align-items:baseline;gap:8px;margin-bottom:5px}
970
- .hi-head b{font-size:var(--text-sm);color:var(--foreground)}
971
- .hi-meta{font-size:var(--text-xs);color:var(--muted-foreground)}
972
- .hi-ctx{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);white-space:pre-wrap;word-break:break-word}
973
- .hi-hit{font-family:var(--mono);font-size:var(--text-xs);color:var(--foreground);white-space:pre-wrap;word-break:break-word;padding:2px 0}
974
-
975
- /* ── reader: multi-format preview + local images (workspace-reader-preview) ── */
976
- .doc-src{margin:0;padding:12px 14px;font-family:var(--mono);font-size:var(--text-sm);line-height:1.6;
977
- color:var(--foreground);white-space:pre-wrap;word-break:break-word;background:var(--card);
978
- border:1px solid var(--border);border-radius:var(--radius-md);overflow-x:auto}
979
- .doc-body img.doc-img{max-width:100%;height:auto;border:1px solid var(--border);border-radius:var(--radius-md);
980
- background:var(--card);display:block;margin:10px 0}
981
- .img-view{padding:6px 2px}
982
- .img-view img.doc-img{margin:0}
983
- .html-view{display:flex;flex-direction:column;gap:8px}
984
- .html-bar{display:flex;gap:6px;align-items:center}
985
- .html-tab{font-family:var(--mono);font-size:var(--text-xs);letter-spacing:.02em;padding:3px 9px;
986
- border:1px solid var(--border);background:var(--secondary);color:var(--muted-foreground);border-radius:var(--radius-md);cursor:pointer}
987
- .html-tab:hover{border-color:var(--input);color:var(--foreground)}
988
- .html-tab.on{border-color:var(--brand);color:var(--brand);background:var(--accent)}
989
- .html-tab .sbx{font-size:var(--text-2xs);opacity:.7}
990
- .html-pane{min-height:0}
991
- .html-frame{width:100%;min-height:60vh;border:1px solid var(--border);border-radius:var(--radius-md);
992
- background:white} /* a standalone HTML doc assumes a light page; keyword, not hex (token-hygiene) */
993
- /* ── mobile (≤760px): one column at a time + a bottom switcher; the terminal is the priority pane.
994
- The 3-column desktop layout above is untouched at wide widths — everything here is inside the
995
- ≤760 query (or the .mobmenu, which is display:none until then). Touch targets ≥44px; the control
996
- bar sends the keys a phone keyboard lacks straight to the PTY. ── */
997
- .mobmenu{display:none}
998
- @media (max-width:760px){
999
- /* an extra row above the status strip carries the control bar + switcher */
1000
- .app{grid-template-rows:44px minmax(0,1fr) auto 28px}
1001
- /* collapse to a single column; the switcher decides which pane is shown. These are DIRECT
1002
- declarations and the layout writes custom properties, so the phone's arrangement wins here
1003
- whatever layout the desktop is on — the two systems never fight (R9). */
1004
- .body{grid-template-columns:1fr;grid-template-rows:minmax(0,1fr);grid-template-areas:none;position:relative}
1005
- /* the named areas are gone here, so the panes must stop asking for them — a stale `grid-area`
1006
- places them on implicit tracks and the pane spills over the switcher it is covering */
1007
- .body>.side,.body>.term-col,.body>.rail,.body>.drop{grid-area:auto}
1008
- .body>.side,.body>.term-col,.body>.rail{display:none}
1009
- .body[data-mview="sessions"]>.side{display:flex}
1010
- .body[data-mview="terminal"]>.term-col{display:flex}
1011
- .body[data-mview="library"]>.rail,
1012
- .body[data-reader="off"][data-mview="library"]>.rail{display:flex}
1013
- /* the rail is a full-width pane here, not the floating overlay the ≤1100 rule makes it */
1014
- .body[data-float="on"]>.rail,.rail{position:static;width:auto;box-shadow:none;z-index:auto;
1015
- border-left:0;border-top:0}
1016
- .railgrip,.railsplit,.side>.edge{display:none} /* edge-drag is a pointer affordance; the switcher owns layout on touch */
1017
- .cap .grip,.lay-chip{display:none} /* and so is the whole layout control (R9) */
1018
- .side>.pane{flex:1 1 0}
1019
- /* one group on a phone, always — the split is a desktop arrangement */
1020
- .groups{flex-direction:column}
1021
- .group+.group{display:none}
1022
-
1023
- /* the mobile menu: a terminal control bar (terminal view only) over the pane switcher */
1024
- /* min-width:0 lets this grid item shrink below its content min-size, so the control bar's
1025
- fixed-width buttons scroll inside it instead of widening the whole page */
1026
- .mobmenu{display:block;min-width:0;background:var(--muted);border-top:1px solid var(--border);
1027
- padding-bottom:env(safe-area-inset-bottom)}
1028
- .ctrlbar{display:none;min-width:0;gap:5px;padding:6px 8px;overflow-x:auto;-webkit-overflow-scrolling:touch;
1029
- border-bottom:1px solid var(--border)}
1030
- .mobmenu[data-view="terminal"] .ctrlbar{display:flex}
1031
- .ctrlbar button{flex:1 0 auto;min-width:44px;min-height:44px;display:grid;place-items:center;
1032
- border:1px solid var(--border);border-radius:var(--radius-md);background:var(--secondary);color:var(--foreground);
1033
- font-family:var(--mono);font-size:14px}
1034
- .ctrlbar button:active{background:var(--accent)}
1035
- .ctrlbar button[aria-pressed="true"]{border-color:var(--brand);color:var(--brand);background:var(--brand-wash)}
1036
- .ctrlbar .lbl{font-size:var(--text-xs);letter-spacing:.04em}
1037
- .mobtabs{display:flex}
1038
- .mobtabs button{flex:1;min-height:52px;display:flex;flex-direction:column;align-items:center;justify-content:center;
1039
- gap:2px;font-family:var(--mono);font-size:var(--text-xs);letter-spacing:.06em;color:var(--muted-foreground);
1040
- border-top:2px solid transparent;background:var(--muted)}
1041
- .mobtabs button+button{border-left:1px solid var(--border)}
1042
- .mobtabs button[aria-selected="true"]{color:var(--brand);border-top-color:var(--brand);background:var(--accent)}
1043
- @media (prefers-reduced-motion:reduce){.mobtabs button,.ctrlbar button{transition:none}}
1044
-
1045
- /* the header must fit a phone: drop the desktop "workspace" tag and let the status text ellipsize */
1046
- .bar{gap:7px;padding:0 10px}
1047
- .bar .sub{display:none}
1048
- .bar .conn{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
1049
- /* the strip's right half is a list of KEYBOARD hints (⌘K, F2, Esc) — on a phone it advertises
1050
- keys that are not there, so the connection state gets the whole strip instead */
1051
- .strip .right{display:none}
1052
- }
1053
-
1054
- /* ── console surfaces (D64 Track B): needs-you · radar · metrics over file-mode state ────────── */
1055
- /* Honesty by construction: error is unmistakably RED (--bad), empty is CALM (--teal), the loading
1056
- skeleton (.sf-skel, reused) is neither. A broken read can only ever draw .cs-error. */
1057
- .cs-error{border:1px solid var(--destructive);border-radius:var(--radius-xl);padding:16px 18px;
1058
- background:radial-gradient(120% 140% at 0 0,rgba(242,101,95,.14),transparent 60%),var(--card)}
1059
- .cs-err-head{display:flex;align-items:center;gap:9px}
1060
- .cs-err-head .mk{width:22px;height:22px;display:grid;place-items:center;border-radius:var(--radius-md);
1061
- background:var(--destructive);color:white;font-size:var(--text-sm);flex:none}
1062
- .cs-err-head b{font-size:var(--text-base);color:var(--destructive)}
1063
- .cs-err-why{margin-top:8px;font-size:var(--text-sm);color:var(--foreground);line-height:1.5}
1064
- .cs-err-note{margin-top:7px;font-family:var(--mono);font-size:var(--text-xs);color:var(--destructive);opacity:.9;line-height:1.5}
1065
- .cs-empty{border:1px solid var(--info);border-radius:var(--radius-xl);padding:16px 18px;
1066
- background:radial-gradient(120% 140% at 0 0,var(--info-wash),transparent 60%),var(--card)}
1067
- .cs-empty>.dot{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--info);
1068
- box-shadow:0 0 0 4px var(--info-wash);margin-right:8px;vertical-align:middle}
1069
- .cs-empty b{font-size:var(--text-base);color:var(--foreground)}
1070
- .cs-empty p{margin-top:6px;font-size:var(--text-sm);color:var(--muted-foreground);line-height:1.5}
1071
- .cs-empty-note{font-family:var(--mono);font-size:var(--text-xs);color:var(--info);opacity:.85}
1072
- .cs-src{font-size:var(--text-xs);color:var(--muted-foreground)}
1073
- .sf-chip.src::before{background:var(--info)}
1074
- /* needs-you */
1075
- .cs-needs{border:1px solid var(--warning);border-radius:var(--radius-xl);overflow:hidden;
1076
- background:radial-gradient(120% 140% at 0 0,var(--warning-wash),transparent 60%),var(--card)}
1077
- .cs-needs .cs-h,.cs-wm .cs-h,.cs-per .cs-h{display:flex;align-items:center;gap:9px;padding:12px 15px 9px}
1078
- .cs-needs .cs-h .dot{width:8px;height:8px;border-radius:50%;background:var(--warning);flex:none;box-shadow:0 0 0 4px var(--warning-wash)}
1079
- .cs-h b{font-size:var(--text-base);color:var(--foreground)}
1080
- .cs-h .src{font-size:var(--text-xs);color:var(--muted-foreground);margin-left:auto}
1081
- .cs-need{display:flex;align-items:center;gap:11px;padding:10px 15px;border-top:1px solid var(--border)}
1082
- .cs-need .ph{width:3px;align-self:stretch;border-radius:var(--radius-sm);background:var(--warning);flex:none}
1083
- .cs-need[data-kind="accept"] .ph{background:var(--brand)}
1084
- .cs-need .txt{flex:1;min-width:0}
1085
- .cs-need .t{font-size:var(--text-sm);color:var(--foreground);line-height:1.45}
1086
- .cs-need .m{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);margin-top:3px}
1087
- /* radar + metrics cards */
1088
- .cs-cards{display:flex;gap:12px;flex-wrap:wrap;margin:10px 0 4px}
1089
- .cs-card{flex:1;min-width:150px;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);padding:13px 15px}
1090
- .cs-card.warnedge{border-color:var(--warning)}
1091
- .cs-card h4{font-size:var(--text-xs);color:var(--muted-foreground);margin-bottom:7px}
1092
- .cs-big{font-size:26px;font-weight:600;color:var(--foreground);line-height:1;display:flex;align-items:baseline;gap:6px}
1093
- .cs-big .u{font-size:var(--text-xs);font-weight:400;color:var(--muted-foreground);font-family:var(--mono)}
1094
- .cs-sub{margin-top:7px;font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.5}
1095
- .cs-caveat{margin-top:8px;font-size:var(--text-xs);color:var(--warning);line-height:1.5;border-top:1px solid var(--border);padding-top:7px}
1096
- .cs-wm{margin-top:12px;border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;background:var(--card)}
1097
- .cs-wm .cs-h .dot{width:8px;height:8px;border-radius:50%;flex:none}
1098
- .cs-wm .cs-h .dot.ok{background:var(--success);box-shadow:0 0 0 4px var(--info-wash)}
1099
- .cs-wm .cs-h .dot.warn{background:var(--warning);box-shadow:0 0 0 4px var(--warning-wash)}
1100
- .cs-wmrow{display:flex;align-items:center;gap:10px;padding:8px 15px;border-top:1px solid var(--border)}
1101
- .cs-wmrow .rag{width:9px;height:9px;border-radius:50%;flex:none;background:var(--muted-foreground)}
1102
- .cs-wmrow .rag.rag-green{background:var(--success)}
1103
- .cs-wmrow .rag.rag-amber{background:var(--warning)}
1104
- .cs-wmrow .rag.rag-red{background:var(--destructive)}
1105
- .cs-wmrow .nm{flex:1;min-width:0;font-size:var(--text-sm);color:var(--foreground);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1106
- .cs-wmrow .nm .ti{color:var(--muted-foreground);margin-left:7px;font-size:var(--text-xs)}
1107
- .cs-wmrow .st{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);flex:none}
1108
- .cs-none,.cs-per .cs-none{padding:10px 15px;font-size:var(--text-xs);color:var(--muted-foreground)}
1109
- .cs-per{margin-top:12px;border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;background:var(--card)}
1110
- .cs-perrow{display:flex;align-items:center;gap:10px;padding:6px 15px;border-top:1px solid var(--border)}
1111
- .cs-perrow .nm{width:40%;min-width:0;font-size:var(--text-sm);color:var(--foreground);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1112
- .cs-perrow .bar{flex:1;height:6px;border-radius:var(--radius-sm);background:var(--secondary);overflow:hidden}
1113
- .cs-perrow .bar i{display:block;height:100%;background:var(--brand);border-radius:var(--radius-sm)}
1114
- .cs-perrow .v{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);flex:none;width:28px;text-align:right}
1115
-
1116
- /* ── workflow ladder (workflow-enforcement) ──────────────────────────────────────────────────
1117
- Where each in-flight initiative is, what is next, and what is blocking. Status is carried by a
1118
- glyph AND a colour, never by colour alone — the whole surface has to survive being read by
1119
- someone who cannot separate the red from the green, and `blocked` is the state that must never
1120
- be missed. `unknown` is styled as its own thing rather than a dim `done`, because collapsing the
1121
- two is precisely the false green this surface exists to prevent. */
1122
- .cs-workflow>.cs-h{display:flex;align-items:center;gap:9px;padding:0 0 10px}
1123
- .cs-workflow>.cs-h .dot{width:8px;height:8px;border-radius:50%;background:var(--success);flex:none;box-shadow:0 0 0 4px var(--info-wash)}
1124
- .cs-workflow>.cs-h .dot.warn{background:var(--warning);box-shadow:0 0 0 4px var(--warning-wash)}
1125
- .wf-degraded{border:1px solid var(--warning);border-radius:var(--radius-lg);background:var(--warning-wash);
1126
- padding:10px 14px;margin-bottom:12px;font-size:var(--text-sm);color:var(--foreground);line-height:1.55}
1127
- .wf-degraded b{color:var(--warning)}
1128
- .wf-card{border:1px solid var(--border);border-radius:var(--radius-xl);background:var(--card);
1129
- overflow:hidden;margin-bottom:12px}
1130
- .wf-card[data-blocked="1"]{border-color:var(--destructive)}
1131
- .wf-top{display:flex;align-items:center;gap:9px;padding:12px 15px 9px}
1132
- .wf-id{font-family:var(--mono);font-size:var(--text-sm);color:var(--foreground);background:none;border:0;
1133
- padding:0;cursor:pointer;text-align:left}
1134
- .wf-id:hover{color:var(--brand);text-decoration:underline}
1135
- .wf-lane{font-family:var(--mono);font-size:var(--text-xs);
1136
- color:var(--muted-foreground);border:1px solid var(--border);border-radius:var(--radius-sm);padding:2px 7px;background:var(--secondary)}
1137
- .wf-here{font-family:var(--mono);font-size:var(--text-2xs);
1138
- color:var(--brand);border:1px solid var(--brand);border-radius:var(--radius-sm);padding:2px 7px;
1139
- background:var(--brand-wash)}
1140
- .wf-more{margin-top:2px;padding:10px 15px;border:1px dashed var(--input);border-radius:var(--radius-lg);
1141
- font-size:var(--text-sm);color:var(--muted-foreground);line-height:1.5}
1142
- .wf-anchor{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);margin-left:auto;
1143
- white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:45%}
1144
- .wf-rail{display:flex;align-items:center;gap:5px;padding:0 15px 11px;flex-wrap:wrap}
1145
- .wf-st{font-family:var(--mono);font-size:var(--text-xs);letter-spacing:.05em;color:var(--muted-foreground)}
1146
- .wf-st.past{color:var(--muted-foreground)}
1147
- .wf-st.at{color:var(--foreground);border-bottom:2px solid var(--brand);padding-bottom:1px}
1148
- .wf-sep{width:12px;height:1px;background:var(--input);flex:none}
1149
- .wf-steps{border-top:1px solid var(--border)}
1150
- .wf-step{display:flex;align-items:baseline;gap:9px;padding:5px 15px}
1151
- .wf-g{font-family:var(--mono);font-size:var(--text-xs);width:11px;flex:none;text-align:center;color:var(--muted-foreground)}
1152
- .wf-step[data-st="done"] .wf-g{color:var(--success)}
1153
- .wf-step[data-st="blocked"] .wf-g{color:var(--destructive)}
1154
- .wf-step[data-st="unknown"] .wf-g{color:var(--warning)}
1155
- .wf-k{font-family:var(--mono);font-size:var(--text-xs);width:74px;flex:none;color:var(--muted-foreground)}
1156
- .wf-step[data-st="na"] .wf-k,.wf-step[data-st="pending"] .wf-k{color:var(--muted-foreground)}
1157
- .wf-step[data-st="blocked"] .wf-k{color:var(--destructive)}
1158
- .wf-e{flex:1;min-width:0;font-size:var(--text-sm);color:var(--muted-foreground);line-height:1.5}
1159
- .wf-step[data-st="na"] .wf-e,.wf-step[data-st="pending"] .wf-e{color:var(--muted-foreground)}
1160
- .wf-rule{font-family:var(--mono);font-size:var(--text-2xs);border:1px solid var(--destructive);border-radius:var(--radius-sm);
1161
- padding:1px 5px;color:var(--destructive);margin-left:5px}
1162
- .wf-next{padding:0 15px 6px 109px;font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.5}
1163
- .wf-next[data-st="blocked"]{color:var(--warning)}
1164
- .wf-do{border-top:1px solid var(--border);padding:10px 15px;font-size:var(--text-sm);color:var(--foreground);
1165
- line-height:1.5;background:var(--warning-wash)}
1166
- .wf-do b{font-family:var(--mono);font-size:var(--text-xs);
1167
- color:var(--warning);margin-right:8px}
1168
- .wf-do.ok{background:var(--info-wash)}
1169
- .wf-do.ok b{color:var(--success)}
1170
-
1171
- /* ── branch awareness (workspace-session-controls) ── */
1172
- /* the branch name IS a git ref — mono. shadcn Badge `secondary`: a filled --muted chip with no
1173
- border, so a long branch name sits quietly beside the product mark instead of drawing a box
1174
- around itself. */
1175
- .bar .branch{font-family:var(--mono);font-size:var(--text-2xs);color:var(--muted-foreground);
1176
- padding:3px 8px;border:0;border-radius:var(--radius-sm);background:var(--muted);
1177
- white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:26ch}
1178
- .bar .branch[hidden]{display:none}
1179
- /* a dirty tree is a real signal, but it is ambient — it tints the chip, it does not outline it */
1180
- .bar .branch.dirty{color:var(--warning);background:var(--warning-wash)}
1181
-
1182
- /* worktree housekeeping — folded away until a repo actually has extra working trees */
1183
- .wtbox{margin-top:8px;font-size:var(--text-xs)}
1184
- .wtbox[hidden]{display:none}
1185
- .wtbox>summary{cursor:pointer;color:var(--muted-foreground);padding:3px 2px;list-style:none;
1186
- display:flex;align-items:center;gap:5px}
1187
- .wtbox>summary::-webkit-details-marker{display:none}
1188
- .wtbox>summary:hover{color:var(--foreground)}
1189
- .wtrow{display:flex;align-items:baseline;gap:6px;padding:4px 2px;border-top:1px solid var(--border)}
1190
- /* a worktree row names a BRANCH and a PATH — mono earns its place */
1191
- .wtrow .wtb{font-family:var(--mono);color:var(--foreground);flex:1;min-width:0;overflow-wrap:anywhere}
1192
- .wtrow .wtwhy{color:var(--muted-foreground);font-size:var(--text-2xs);flex-basis:100%;line-height:1.35}
1193
- /* shadcn Button, `outline` variant at the small size */
1194
- .wtrow button{flex:none;border:1px solid var(--input);border-radius:var(--radius-sm);background:transparent;
1195
- color:var(--foreground);font-size:var(--text-2xs);padding:2px 7px;cursor:pointer;
1196
- transition:border-color var(--duration-fast) var(--ease-emphasized),
1197
- color var(--duration-fast) var(--ease-emphasized)}
1198
- /* removing a worktree deletes a folder — the hover states that intent in the warning hue */
1199
- .wtrow button:hover:not(:disabled){border-color:var(--warning);color:var(--warning)}
1200
- .wtrow button:disabled{opacity:.4;cursor:not-allowed}
1201
-
1202
- /* new-session branch picker — matches the miniform vocabulary */
1203
- .brwrap{display:flex;flex-direction:column;gap:6px}
1204
- .brwrap[hidden]{display:none}
1205
- .brwrap select{min-height:38px;padding:0 8px;border:1px solid var(--input);border-radius:var(--radius-md);
1206
- background:var(--secondary);color:var(--foreground);font-family:var(--mono);font-size:var(--text-xs)}
1207
- .brwrap select:focus{border-color:var(--brand)}
1208
- .brwrap input[hidden]{display:none}
1209
- .miniform .hint.warn{color:var(--warning)}
1210
- .miniform .hint[hidden]{display:none}
1211
- .miniform .lbl .opt{color:var(--muted-foreground);font-weight:400}
1212
- /* the isolate toggle: the difference between "this session gets a branch" and "the whole repo
1213
- moves" is one line, so it reads as a sentence rather than a settings row */
1214
- .brwrap .chk{display:flex;align-items:flex-start;gap:7px;font-size:var(--text-xs);color:var(--foreground);
1215
- line-height:1.35;cursor:pointer}
1216
- .brwrap .chk[hidden]{display:none}
1217
- /* accent-color paints the native checkbox — that is a FILL, so it takes --primary (the brand
1218
- fill) and not --accent, which under this palette is the muted hover surface. */
1219
- .brwrap .chk input{flex:none;margin:1px 0 0;accent-color:var(--primary);cursor:pointer}
1220
-
1221
- /* ── scratchpad drawer: bottom of the terminal column, collapsible, never overlays anything ── */
1222
- .scratch{flex:none;border-top:1px solid var(--border);background:var(--sidebar);display:flex;flex-direction:column;min-height:0}
1223
- .scratch-head{display:flex;align-items:center;gap:8px;padding:5px 10px;min-height:34px;
1224
- background:var(--muted);border-bottom:1px solid transparent}
1225
- .scratch[data-open="true"] .scratch-head{border-bottom-color:var(--border)}
1226
- .scratch-toggle{display:inline-flex;align-items:center;gap:7px;border:0;background:none;
1227
- font-size:var(--text-2xs);color:var(--muted-foreground);cursor:pointer}
1228
- .scratch-toggle:hover{color:var(--foreground)}
1229
- .scratch-toggle .chev{display:inline-block;transition:transform .15s;font-size:var(--text-2xs)}
1230
- .scratch[data-open="true"] .scratch-toggle .chev{transform:rotate(180deg)}
1231
- /* whose pad this is — the pad is per TAB, so the drawer names the tab it is staging for */
1232
- .scratch-who{font-family:var(--mono);font-size:var(--text-xs);color:var(--foreground);letter-spacing:.04em;
1233
- max-width:22ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1234
- .scratch-who:not(:empty)::before{content:"· "}
1235
- .scratch-status{font-family:var(--mono);font-size:var(--text-xs);color:var(--muted-foreground);letter-spacing:.04em}
1236
- .scratch-actions{margin-left:auto;display:flex;gap:6px}
1237
- .scratch-actions .mini{min-height:28px;padding:0 10px;border:1px solid var(--border);border-radius:var(--radius-md);
1238
- background:var(--secondary);color:var(--brand);font-family:var(--mono);font-size:var(--text-xs);letter-spacing:0;cursor:pointer}
1239
- .scratch-actions .mini:hover{border-color:var(--brand)}
1240
- .scratch-actions .mini:disabled{color:var(--muted-foreground);border-color:var(--border);cursor:not-allowed;opacity:.6}
1241
- .scratch-text{display:none;width:100%;box-sizing:border-box;resize:vertical;height:22vh;min-height:90px;max-height:45vh;
1242
- border:0;padding:10px 12px;background:var(--term-bg);color:var(--foreground);
1243
- font-family:var(--mono);font-size:var(--text-sm);line-height:1.5;outline:none}
1244
- .scratch[data-open="true"] .scratch-text{display:block}
1245
-
1246
- /* The cap's controls carry TEXT labels, not icons, so they size to content. And `hidden` has to
1247
- actually hide: `.cap .mini` sets display:grid, which beats the UA's [hidden]{display:none} — the
1248
- attribute was being set correctly and doing nothing, so every control showed at once. Only the
1249
- first control takes the margin-left:auto that pushes the group right. */
1250
- .cap .mini[hidden],.cap .x[hidden]{display:none}
1251
- .cap .docrev{width:auto;min-width:0;padding:0 9px;font-size:var(--text-xs)}
1252
- .cap .mini ~ .mini{margin-left:0}
1253
-
1254
- /* ── the document editor (workspace-doc-editor) ──────────────────────────────────────────────
1255
- The reader gains an edit mode. Quiet on purpose: editing a document should feel local and
1256
- undramatic, so there is no toolbar, no modal, and no mode banner — a control in the cap, a
1257
- textarea in the reader's own type, and the diff shown beside it as you type. */
1258
- .ed-wrap{display:grid;grid-template-rows:minmax(0,1fr) auto;height:100%;min-height:0}
1259
- .ed-split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:0;min-height:0;overflow:hidden}
1260
- .ed-split[data-diff="off"]{grid-template-columns:minmax(0,1fr)}
1261
- .ed-split[data-diff="off"] .ed-diff{display:none}
1262
- .ed-ta{width:100%;height:100%;box-sizing:border-box;resize:none;border:0;outline:none;
1263
- padding:14px 16px;background:var(--background);color:var(--foreground);
1264
- font-family:var(--mono);font-size:var(--text-sm);line-height:1.8;tab-size:2}
1265
- .ed-diff{border-left:1px solid var(--border);overflow-y:auto;background:var(--sidebar);
1266
- font-family:var(--mono);font-size:var(--text-xs);line-height:1.75;padding:8px 0}
1267
- .ed-l{display:grid;grid-template-columns:3px 1fr;align-items:start}
1268
- .ed-l .g{align-self:stretch;border-radius:var(--radius-sm);background:transparent}
1269
- .ed-l .t{padding:0 10px;white-space:pre-wrap;word-break:break-word;color:var(--muted-foreground)}
1270
- .ed-l.del .g{background:var(--destructive)}
1271
- .ed-l.del .t{color:var(--muted-foreground);text-decoration:line-through;text-decoration-color:rgba(242,101,95,.5)}
1272
- .ed-l.add .g{background:var(--success)}
1273
- .ed-l.add .t{color:var(--foreground)}
1274
- .ed-l.ctx .t{color:var(--muted-foreground)}
1275
- .ed-none{padding:14px 16px;font-size:var(--text-sm);color:var(--muted-foreground);line-height:1.6}
1276
- .ed-bar{display:flex;align-items:center;gap:12px;padding:8px 14px;border-top:1px solid var(--border);
1277
- background:var(--muted);font-size:var(--text-sm);color:var(--muted-foreground)}
1278
- .ed-bar .n{font-family:var(--mono)}
1279
- .ed-bar .n b{color:var(--success);font-weight:600}
1280
- .ed-bar .n i{color:var(--destructive);font-style:normal;font-weight:600}
1281
- .ed-bar input{flex:1;min-width:80px;border:1px solid var(--border);border-radius:var(--radius-md);
1282
- padding:6px 10px;background:var(--secondary);color:var(--foreground);font-family:var(--sans);
1283
- font-size:var(--text-sm);outline:none}
1284
- .ed-bar input:focus{border-color:var(--brand)}
1285
- .ed-bar .dirty{color:var(--warning)}
1286
- .ed-err{margin:0 14px 8px;padding:8px 11px;border-radius:var(--radius-md);border:1px solid var(--destructive);
1287
- background:rgba(242,101,95,.08);font-size:var(--text-sm);line-height:1.5;color:var(--foreground)}
1288
-
1289
- /* the change log for one document — read, not managed */
1290
- .hist{padding:16px 18px;max-width:640px}
1291
- .hist h3{font-size:14px;font-weight:600;margin-bottom:3px}
1292
- .hist .sub{font-size:var(--text-sm);color:var(--muted-foreground);margin-bottom:18px;line-height:1.6}
1293
- .hist-row{padding:11px 0;border-top:1px solid var(--border)}
1294
- .hist-row:first-of-type{border-top:0}
1295
- .hist-when{font-size:var(--text-xs);color:var(--muted-foreground)}
1296
- .hist-when b{color:var(--success);font-weight:600}
1297
- .hist-when i{color:var(--destructive);font-style:normal;font-weight:600}
1298
- .hist-note{margin-top:4px;font-size:var(--text-sm);color:var(--foreground);line-height:1.55}
1299
- .hist-none{font-size:var(--text-sm);color:var(--muted-foreground);line-height:1.6}
1300
-
1301
- /* ── alignment (workspace-doc-editor R5–R7) ──────────────────────────────────────────────────
1302
- Downstream of a save and offered, never blocking. The offer is one line that can be dismissed;
1303
- nothing accumulates and nothing badges.
1304
- Tokens follow the radix-sera port: --brand is the blue for text/borders, --primary is for fills,
1305
- and --accent is a muted hover surface, not a hue. Radii come from the scale — never a px. */
1306
- .al-offer{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:12px 14px;padding:10px 12px;
1307
- border-radius:var(--radius-md);background:var(--brand-wash);border:1px solid var(--brand);
1308
- font-size:var(--text-sm);line-height:1.5;color:var(--foreground)}
1309
- .al-offer button{font-size:var(--text-sm);color:var(--brand);padding:2px 0}
1310
- .al-offer button:hover{text-decoration:underline}
1311
- .al-offer button.q{color:var(--muted-foreground);margin-left:auto}
1312
- .al{padding:16px 18px 40px;max-width:660px}
1313
- .al-lede{font-size:var(--text-base);line-height:1.5;color:var(--foreground);margin-bottom:5px}
1314
- .al-sub{font-size:var(--text-sm);line-height:1.6;color:var(--muted-foreground);margin-bottom:16px}
1315
- .al-c{display:flex;gap:9px;align-items:flex-start;padding:9px 0;border-top:1px solid var(--border);cursor:pointer}
1316
- .al-c:first-of-type{border-top:0}
1317
- .al-c input{margin-top:3px;accent-color:var(--primary);width:15px;height:15px;flex:none}
1318
- .al-p{font-size:var(--text-sm);color:var(--foreground);display:block;word-break:break-all}
1319
- .al-why{display:block;margin-top:2px;font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.5}
1320
- .al-acts{display:flex;gap:15px;align-items:center;flex-wrap:wrap;margin-top:14px}
1321
- .al-acts button{font-size:var(--text-sm);color:var(--brand);padding:3px 0;min-height:30px}
1322
- .al-acts button:hover{text-decoration:underline}
1323
- .al-acts button.q{color:var(--muted-foreground)}
1324
- .al-acts button:disabled{color:var(--muted-foreground);text-decoration:none;cursor:default}
1325
- .al-note{font-size:var(--text-xs);color:var(--muted-foreground)}
1326
- .al-d{padding:13px 0;border-top:1px solid var(--border)}
1327
- .al-d.done{opacity:.45}
1328
- .al-d.done .al-code,.al-d.done .al-acts{display:none}
1329
- .al-d.done .al-p::after{content:" · settled";color:var(--success);font-family:var(--sans);font-size:var(--text-xs)}
1330
- .al-code{margin-top:9px;font-family:var(--mono);font-size:var(--text-xs);line-height:1.75;
1331
- border-top:1px solid var(--border);border-bottom:1px solid var(--border);padding:6px 0}
1332
- .al-err{margin-top:9px;padding:8px 11px;border-radius:var(--radius-md);border:1px solid var(--destructive);
1333
- background:rgba(242,101,95,.08);font-size:var(--text-sm);line-height:1.5;color:var(--foreground)}
1334
-
1335
- /* ── The sidebar tree (workspace-initiative-nav-build, R1–R6) ─────────────────────────────────
1336
- Repository → its working trees, each labelled by the initiative on its branch → sessions.
1337
- Replaces the old `workspaces` + `running agents` pair. Session-row styles are reused verbatim
1338
- from that pane — only the nesting is new. Colours go through the D38 semantic tokens: a hex
1339
- fallback here would be a second source of truth for a value the token layer owns, which is the
1340
- drift `token-hygiene` exists to catch. */
1341
- .repo-group{margin-bottom:6px}
1342
- .repo-head{display:flex;align-items:center;gap:6px;width:100%;padding:4px 8px;background:none;
1343
- border:0;color:var(--foreground);font:inherit;font-weight:600;font-size:var(--text-xs);
1344
- cursor:default;text-align:left}
1345
- .repo-head .cue{color:var(--muted-foreground);font-size:var(--text-2xs)}
1346
- .repo-head small{margin-left:auto;color:var(--muted-foreground);font-family:var(--mono);font-size:var(--text-2xs)}
1347
-
1348
- .treerow{border-left:2px solid transparent}
1349
- .treerow[data-open="true"]{border-left-color:var(--border)}
1350
- .tr-head{display:flex;align-items:flex-start}
1351
- .tr-toggle{background:none;border:0;color:var(--muted-foreground);cursor:pointer;
1352
- padding:6px 2px 6px 8px;font:inherit;line-height:1.2}
1353
- .tr-toggle .cue{font-size:var(--text-2xs)}
1354
- .tr{flex:1;min-width:0;display:block;text-align:left;background:none;border:0;color:inherit;
1355
- font:inherit;padding:5px 6px 6px 0;cursor:pointer}
1356
- .tr:hover,.tr-head:hover .tr{background:var(--accent)}
1357
- .tr[aria-current="true"]{background:var(--accent);font-weight:500}
1358
- .tr .r1{display:flex;align-items:baseline;gap:6px}
1359
- .tr .r1 .g{font-size:var(--text-2xs);width:9px;flex:none}
1360
- .treerow[data-st="working"] .r1 .g{color:var(--success)}
1361
- .treerow[data-st="quiet"] .r1 .g,
1362
- .treerow[data-st="idle"] .r1 .g,
1363
- .treerow[data-st="exited"] .r1 .g{color:var(--muted-foreground)}
1364
- .treerow[data-st="blocked"] .r1 .g{color:var(--destructive)}
1365
- .tr .r1 .nm{font-size:var(--text-xs);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1366
- .tr .r1 .dir{margin-left:auto;flex:none;font-family:var(--mono);font-size:var(--text-2xs);
1367
- color:var(--muted-foreground)}
1368
- .tr .r2{display:flex;flex-wrap:wrap;gap:6px;align-items:baseline;padding-left:15px;margin-top:2px;
1369
- font-family:var(--mono);font-size:var(--text-2xs);color:var(--muted-foreground)}
1370
- .tr .wf{display:inline-flex;gap:6px;align-items:baseline}
1371
- .tr .wf .lane{color:var(--muted-foreground)}
1372
- .tr .wf .stg{color:var(--brand)}
1373
- .tr .wf .nx{color:var(--muted-foreground)}
1374
- /* THE THREE-VALUED VOCABULARY (R2). Two renderings for three facts means one is always mislabelled
1375
- — which is how an ordinary folder came to render as an alarm on the same surface that uses
1376
- --destructive for a corrupt state queue. `.bl` keeps the alarm; `.gone` is the quiet, specific
1377
- "the read succeeded and there is nothing here"; a value is styled as neither. */
1378
- .tr .wf .bl,.tr .r2 .bl{color:var(--destructive)}
1379
- .tr .wf .gone,.tr .r2 .gone{color:var(--muted-foreground);opacity:.8}
1380
- .tr .wf .drv{color:var(--muted-foreground);font-style:italic}
1381
- .tr .needs-n{color:var(--warning)}
1382
- .tr .rollup{color:var(--muted-foreground)}
1383
- /* R5 — the branch a ladder was derived from, and when. Never optional when a stage is shown. */
1384
- .tr .attrib{display:block;padding-left:15px;margin-top:2px;font-family:var(--mono);
1385
- font-size:var(--text-2xs);color:var(--muted-foreground)}
1386
- .tr .attrib b{color:var(--foreground);font-weight:500}
1387
- .tr-sessions{padding-left:14px}
1388
- .tree-new{display:block;width:calc(100% - 8px);margin:2px 0 6px 4px;padding:4px 8px;background:none;
1389
- border:1px dashed var(--border);border-radius:var(--radius-sm);color:var(--muted-foreground);
1390
- font:inherit;font-size:var(--text-2xs);cursor:pointer;text-align:left}
1391
- .tree-new:hover{color:var(--foreground);border-color:var(--input)}
1392
- /* R5 — the composer's target. "run an agent here" named nothing once every repository was on
1393
- screen at once; this is the referent, and it updates on every selection change. */
1394
- .miniform .where{font-family:var(--mono);font-size:var(--text-2xs);color:var(--muted-foreground);
1395
- margin:0 0 6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1396
- .miniform .where[data-none="1"]{color:var(--warning)}
1397
- .cap .ct[data-bad="1"]{color:var(--destructive)}
1398
-
1399
- /* ── The rail's initiative dossier (R7·R8·R9) ────────────────────────────────────────────────── */
1400
- .reading{font-family:var(--mono);font-size:var(--text-2xs);color:var(--muted-foreground);
1401
- overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:12ch}
1402
- .reading[data-away="1"]{color:var(--warning);max-width:none}
1403
- .dz-head{padding:10px 12px 8px;border-bottom:1px solid var(--border)}
1404
- .dz-id{font-size:var(--text-sm);font-weight:600;letter-spacing:-.01em}
1405
- .dz-t{font-size:var(--text-xs);color:var(--muted-foreground);margin-top:2px;line-height:1.4}
1406
- .dz-meta{display:flex;gap:5px;flex-wrap:wrap;margin-top:7px}
1407
- .dz-meta .pill{font-family:var(--mono);font-size:var(--text-2xs);padding:2px 5px;
1408
- border-radius:var(--radius-sm);background:var(--secondary);color:var(--muted-foreground);
1409
- border:1px solid var(--border)}
1410
- .dz-meta .pill.lane{color:var(--purple)}
1411
- /* R5 — the branch a ladder came from, never optional beside a stage */
1412
- .dz-attrib{margin-top:7px;font-family:var(--mono);font-size:var(--text-2xs);
1413
- color:var(--muted-foreground);line-height:1.5}
1414
- .dz-attrib b{color:var(--foreground);font-weight:500}
1415
- .dz-attrib .sub{display:block;opacity:.85}
1416
- .dz-next{margin:9px 12px;padding:8px 10px;border-radius:var(--radius-md);background:var(--success-wash);
1417
- border:1px solid var(--border);font-size:var(--text-xs);color:var(--foreground);line-height:1.5}
1418
- .dz-next b{display:block;font-family:var(--mono);font-size:var(--text-2xs);letter-spacing:.12em;
1419
- text-transform:uppercase;color:var(--success);margin-bottom:3px;font-weight:500}
1420
- /* accepted AND owing, together — a green badge alone is the watermelon */
1421
- .dz-next.owed{background:var(--warning-wash)}
1422
- .dz-next.owed b{color:var(--warning)}
1423
- .dz-next.done b{color:var(--muted-foreground)}
1424
- .dz-wait{margin:9px 12px;font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.5}
1425
- .dz-wait .sub{display:block;font-size:var(--text-2xs);margin-top:3px;opacity:.85}
1426
- .dz-none{margin:9px 12px;font-size:var(--text-xs);color:var(--muted-foreground);line-height:1.55}
1427
- .dz-arts{padding:0 12px 14px}
1428
- .dz-sec{padding-top:10px}
1429
- .dz-sec+.dz-sec{border-top:1px solid var(--border);margin-top:8px}
1430
- .dz-sec h5{display:flex;gap:7px;align-items:baseline;font-family:var(--mono);
1431
- font-size:var(--text-2xs);letter-spacing:.13em;text-transform:uppercase;
1432
- color:var(--muted-foreground);font-weight:500;margin-bottom:5px}
1433
- .dz-sec h5 .c{opacity:.8;letter-spacing:0}
1434
- .dz-art{display:flex;gap:7px;align-items:baseline;width:100%;text-align:left;padding:4px 7px;
1435
- margin-bottom:3px;border-radius:var(--radius-sm);background:var(--card);border:1px solid var(--border);
1436
- color:inherit;font:inherit;cursor:pointer}
1437
- .dz-art:hover{border-color:var(--input);background:var(--accent)}
1438
- .dz-art .role{font-family:var(--mono);font-size:var(--text-2xs);letter-spacing:.1em;
1439
- text-transform:uppercase;color:var(--info);width:74px;flex:none}
1440
- .dz-art .pth{font-family:var(--mono);font-size:var(--text-2xs);color:var(--muted-foreground);
1441
- overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
1442
- /* `n/a for this lane` must never look like `missing` — that difference is the whole of R8 */
1443
- .dz-na{font-size:var(--text-2xs);color:var(--muted-foreground);font-style:italic;line-height:1.5;
1444
- padding:2px 0 4px}