@phenx-inc/ctlsurf 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/headless/index.mjs +115 -5
- package/out/headless/index.mjs.map +3 -3
- package/out/main/index.js +316 -8
- package/out/preload/index.js +9 -0
- package/out/renderer/assets/{cssMode-Bmzy9hKX.js → cssMode-D7r66wvO.js} +3 -3
- package/out/renderer/assets/{freemarker2-CDAsExTa.js → freemarker2-jSWJIjPG.js} +1 -1
- package/out/renderer/assets/{handlebars-CvpBYG1L.js → handlebars-BnFyz5RH.js} +1 -1
- package/out/renderer/assets/{html-CNhEQqr8.js → html-Bl5UFavp.js} +1 -1
- package/out/renderer/assets/{htmlMode-DD7YPgga.js → htmlMode-D4VByBT6.js} +3 -3
- package/out/renderer/assets/{index-CGHeDwZa.css → index-Cc_TqOCL.css} +318 -0
- package/out/renderer/assets/{index-BDlCPzCG.js → index-DxhW1emk.js} +558 -85
- package/out/renderer/assets/{javascript-CsGLsswK.js → javascript-CMN1OmwG.js} +2 -2
- package/out/renderer/assets/{jsonMode-CTuGgRvC.js → jsonMode-CJ5AYSPV.js} +3 -3
- package/out/renderer/assets/{liquid-BrrN4uul.js → liquid-BGMIDTEm.js} +1 -1
- package/out/renderer/assets/{lspLanguageFeatures-Bhdn2Eqy.js → lspLanguageFeatures-DGifVYB5.js} +1 -1
- package/out/renderer/assets/{mdx-DJo-gax4.js → mdx-B2Z7R10Q.js} +1 -1
- package/out/renderer/assets/{python-DYHeg5b2.js → python-LMDMSSdn.js} +1 -1
- package/out/renderer/assets/{razor-Cqcks14K.js → razor-BZSrziPu.js} +1 -1
- package/out/renderer/assets/{tsMode-YTLgCayh.js → tsMode-DF9m6_3n.js} +1 -1
- package/out/renderer/assets/{typescript-oxBn_Vcw.js → typescript-rZeCMf0a.js} +1 -1
- package/out/renderer/assets/{xml-BEqGMCTc.js → xml-fNSZ-7so.js} +1 -1
- package/out/renderer/assets/{yaml-BGSrk5HC.js → yaml-1wxIuvzh.js} +1 -1
- package/out/renderer/index.html +2 -2
- package/package.json +1 -1
- package/src/main/agents.ts +9 -1
- package/src/main/ctlsurfApi.ts +7 -0
- package/src/main/index.ts +62 -4
- package/src/main/orchestrator.ts +112 -4
- package/src/main/ssh.ts +348 -0
- package/src/preload/index.ts +26 -0
- package/src/renderer/App.tsx +25 -1
- package/src/renderer/components/AgentPicker.tsx +18 -0
- package/src/renderer/components/ProjectPicker.tsx +121 -0
- package/src/renderer/components/RemoteConnect.tsx +315 -0
- package/src/renderer/components/SpeakControls.tsx +8 -2
- package/src/renderer/components/TerminalPanel.tsx +134 -23
- package/src/renderer/components/TicketPanel.tsx +67 -26
- package/src/renderer/styles.css +318 -0
|
@@ -74,6 +74,32 @@ function Segmented({ options, value, onChange }: SegmentedProps) {
|
|
|
74
74
|
)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
// A single ticket row. Shared between the open list and the (collapsible)
|
|
78
|
+
// Done section so both render identically.
|
|
79
|
+
function TicketCard({ ticket, onClick }: { ticket: Ticket; onClick: () => void }) {
|
|
80
|
+
return (
|
|
81
|
+
<button className="ticket-card" onClick={onClick}>
|
|
82
|
+
<span className="ticket-card-bar" style={{ background: colorOf(STATUS_OPTIONS, ticket.status) }} />
|
|
83
|
+
<div className="ticket-card-main">
|
|
84
|
+
<span className="ticket-card-title">{ticket.title || 'Untitled'}</span>
|
|
85
|
+
<div className="ticket-card-meta">
|
|
86
|
+
<span className="ticket-card-status" style={{ color: colorOf(STATUS_OPTIONS, ticket.status) }}>
|
|
87
|
+
<span className="ticket-seg-dot" style={{ background: colorOf(STATUS_OPTIONS, ticket.status) }} />
|
|
88
|
+
{ticket.status}
|
|
89
|
+
</span>
|
|
90
|
+
{ticket.created && <span className="ticket-card-date">{formatDate(ticket.created)}</span>}
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
<span
|
|
94
|
+
className="ticket-card-pri"
|
|
95
|
+
style={{ color: colorOf(PRIORITY_OPTIONS, ticket.priority), borderColor: `${colorOf(PRIORITY_OPTIONS, ticket.priority)}66` }}
|
|
96
|
+
>
|
|
97
|
+
{ticket.priority}
|
|
98
|
+
</span>
|
|
99
|
+
</button>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
77
103
|
// Docked side-pane variant of the ticket UI: header + list/form body + footer.
|
|
78
104
|
// It only mounts when its pane is visible, so it loads on mount and refreshes
|
|
79
105
|
// when the connected project (cwd) changes. Closed via the pane's own header.
|
|
@@ -85,6 +111,9 @@ export function TicketPane() {
|
|
|
85
111
|
const [tickets, setTickets] = useState<Ticket[]>([])
|
|
86
112
|
const [listLoading, setListLoading] = useState(false)
|
|
87
113
|
const [listError, setListError] = useState<string | null>(null)
|
|
114
|
+
// Done tickets are tucked into a collapsed section so the list stays focused
|
|
115
|
+
// on what's still open; the user can expand to review completed work.
|
|
116
|
+
const [showDone, setShowDone] = useState(false)
|
|
88
117
|
|
|
89
118
|
// form state
|
|
90
119
|
const [editingId, setEditingId] = useState<string | null>(null)
|
|
@@ -178,6 +207,10 @@ export function TicketPane() {
|
|
|
178
207
|
return () => window.removeEventListener('keydown', onKey)
|
|
179
208
|
}, [view, handleSave])
|
|
180
209
|
|
|
210
|
+
// Split out Done tickets so they can live in their own collapsed section.
|
|
211
|
+
const activeTickets = tickets.filter(t => t.status !== 'Done')
|
|
212
|
+
const doneTickets = tickets.filter(t => t.status === 'Done')
|
|
213
|
+
|
|
181
214
|
return (
|
|
182
215
|
<div className="ticket-pane" role="region" aria-label="Tickets">
|
|
183
216
|
<div className="ticket-drawer-header">
|
|
@@ -198,6 +231,9 @@ export function TicketPane() {
|
|
|
198
231
|
</span>
|
|
199
232
|
</div>
|
|
200
233
|
</div>
|
|
234
|
+
{view === 'list' && (
|
|
235
|
+
<button className="ticket-drawer-new" onClick={openNewForm} title="New ticket">+ New</button>
|
|
236
|
+
)}
|
|
201
237
|
</div>
|
|
202
238
|
|
|
203
239
|
{view === 'list' ? (
|
|
@@ -214,34 +250,39 @@ export function TicketPane() {
|
|
|
214
250
|
<span className="ticket-empty-hint">Log the first one for this project.</span>
|
|
215
251
|
</div>
|
|
216
252
|
)}
|
|
217
|
-
{!listLoading &&
|
|
218
|
-
<
|
|
219
|
-
<span className="ticket-card-bar" style={{ background: colorOf(STATUS_OPTIONS, t.status) }} />
|
|
220
|
-
<div className="ticket-card-main">
|
|
221
|
-
<span className="ticket-card-title">{t.title || 'Untitled'}</span>
|
|
222
|
-
<div className="ticket-card-meta">
|
|
223
|
-
<span className="ticket-card-status" style={{ color: colorOf(STATUS_OPTIONS, t.status) }}>
|
|
224
|
-
<span className="ticket-seg-dot" style={{ background: colorOf(STATUS_OPTIONS, t.status) }} />
|
|
225
|
-
{t.status}
|
|
226
|
-
</span>
|
|
227
|
-
{t.created && <span className="ticket-card-date">{formatDate(t.created)}</span>}
|
|
228
|
-
</div>
|
|
229
|
-
</div>
|
|
230
|
-
<span
|
|
231
|
-
className="ticket-card-pri"
|
|
232
|
-
style={{ color: colorOf(PRIORITY_OPTIONS, t.priority), borderColor: `${colorOf(PRIORITY_OPTIONS, t.priority)}66` }}
|
|
233
|
-
>
|
|
234
|
-
{t.priority}
|
|
235
|
-
</span>
|
|
236
|
-
</button>
|
|
253
|
+
{!listLoading && activeTickets.map(t => (
|
|
254
|
+
<TicketCard key={t.id} ticket={t} onClick={() => openEditForm(t)} />
|
|
237
255
|
))}
|
|
256
|
+
{!listLoading && activeTickets.length === 0 && doneTickets.length > 0 && (
|
|
257
|
+
<div className="ticket-list-msg">Nothing open — all caught up.</div>
|
|
258
|
+
)}
|
|
259
|
+
{!listLoading && doneTickets.length > 0 && (
|
|
260
|
+
<>
|
|
261
|
+
<button
|
|
262
|
+
type="button"
|
|
263
|
+
className="ticket-done-toggle"
|
|
264
|
+
onClick={() => setShowDone(v => !v)}
|
|
265
|
+
aria-expanded={showDone}
|
|
266
|
+
>
|
|
267
|
+
<span className={`ticket-done-caret ${showDone ? 'open' : ''}`} aria-hidden="true">▸</span>
|
|
268
|
+
<span className="ticket-done-label">Done</span>
|
|
269
|
+
<span className="ticket-done-count">{doneTickets.length}</span>
|
|
270
|
+
</button>
|
|
271
|
+
{showDone && doneTickets.map(t => (
|
|
272
|
+
<TicketCard key={t.id} ticket={t} onClick={() => openEditForm(t)} />
|
|
273
|
+
))}
|
|
274
|
+
</>
|
|
275
|
+
)}
|
|
238
276
|
</div>
|
|
239
|
-
|
|
240
|
-
<
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
277
|
+
{tickets.length > 0 && (
|
|
278
|
+
<div className="ticket-drawer-footer">
|
|
279
|
+
<span className="ticket-drawer-hint">
|
|
280
|
+
{doneTickets.length > 0
|
|
281
|
+
? `${activeTickets.length} open · ${doneTickets.length} done`
|
|
282
|
+
: `${tickets.length} ticket${tickets.length === 1 ? '' : 's'}`}
|
|
283
|
+
</span>
|
|
284
|
+
</div>
|
|
285
|
+
)}
|
|
245
286
|
</>
|
|
246
287
|
) : (
|
|
247
288
|
<>
|
package/src/renderer/styles.css
CHANGED
|
@@ -100,6 +100,17 @@ html, body, #root {
|
|
|
100
100
|
background: #1f2335;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
.titlebar-btn:disabled {
|
|
104
|
+
opacity: 0.4;
|
|
105
|
+
cursor: not-allowed;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Keep the greyed-out look stable on hover for disabled buttons. */
|
|
109
|
+
.titlebar-btn:disabled:hover {
|
|
110
|
+
color: #565f89;
|
|
111
|
+
border-color: #3b3d57;
|
|
112
|
+
}
|
|
113
|
+
|
|
103
114
|
.titlebar-separator {
|
|
104
115
|
width: 1px;
|
|
105
116
|
height: 16px;
|
|
@@ -266,6 +277,15 @@ html, body, #root {
|
|
|
266
277
|
}
|
|
267
278
|
|
|
268
279
|
/* Terminal container */
|
|
280
|
+
.terminal-wrap {
|
|
281
|
+
position: relative;
|
|
282
|
+
flex: 1;
|
|
283
|
+
min-width: 0;
|
|
284
|
+
min-height: 0;
|
|
285
|
+
width: 100%;
|
|
286
|
+
height: 100%;
|
|
287
|
+
}
|
|
288
|
+
|
|
269
289
|
.terminal-container {
|
|
270
290
|
width: 100%;
|
|
271
291
|
height: 100%;
|
|
@@ -277,6 +297,34 @@ html, body, #root {
|
|
|
277
297
|
height: 100%;
|
|
278
298
|
}
|
|
279
299
|
|
|
300
|
+
/* Floating "jump to latest" pill — shown only while scrolled up. */
|
|
301
|
+
.term-jump-latest {
|
|
302
|
+
position: absolute;
|
|
303
|
+
bottom: 14px;
|
|
304
|
+
right: 20px;
|
|
305
|
+
z-index: 5;
|
|
306
|
+
display: inline-flex;
|
|
307
|
+
align-items: center;
|
|
308
|
+
gap: 5px;
|
|
309
|
+
padding: 5px 12px;
|
|
310
|
+
border-radius: 14px;
|
|
311
|
+
background: #2a2b3d;
|
|
312
|
+
border: 1px solid #7aa2f7;
|
|
313
|
+
color: #c0caf5;
|
|
314
|
+
font-family: inherit;
|
|
315
|
+
font-size: 11.5px;
|
|
316
|
+
font-weight: 600;
|
|
317
|
+
cursor: pointer;
|
|
318
|
+
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
|
|
319
|
+
transition: background 0.13s ease, transform 0.06s ease;
|
|
320
|
+
}
|
|
321
|
+
.term-jump-latest:hover {
|
|
322
|
+
background: #343650;
|
|
323
|
+
}
|
|
324
|
+
.term-jump-latest:active {
|
|
325
|
+
transform: translateY(1px);
|
|
326
|
+
}
|
|
327
|
+
|
|
280
328
|
.terminal-fullscreen {
|
|
281
329
|
width: 100%;
|
|
282
330
|
height: 100%;
|
|
@@ -1150,6 +1198,9 @@ html, body, #root {
|
|
|
1150
1198
|
border-radius: 12px;
|
|
1151
1199
|
padding: 32px 40px;
|
|
1152
1200
|
min-width: 360px;
|
|
1201
|
+
max-width: 460px;
|
|
1202
|
+
max-height: 88vh;
|
|
1203
|
+
overflow-y: auto;
|
|
1153
1204
|
text-align: center;
|
|
1154
1205
|
}
|
|
1155
1206
|
|
|
@@ -1218,6 +1269,7 @@ html, body, #root {
|
|
|
1218
1269
|
display: flex;
|
|
1219
1270
|
align-items: center;
|
|
1220
1271
|
justify-content: space-between;
|
|
1272
|
+
gap: 16px;
|
|
1221
1273
|
padding: 14px 18px;
|
|
1222
1274
|
background: #16161e;
|
|
1223
1275
|
border: 1px solid #2a2b3d;
|
|
@@ -1236,11 +1288,13 @@ html, body, #root {
|
|
|
1236
1288
|
font-size: 14px;
|
|
1237
1289
|
font-weight: 600;
|
|
1238
1290
|
color: #c0caf5;
|
|
1291
|
+
flex-shrink: 0;
|
|
1239
1292
|
}
|
|
1240
1293
|
|
|
1241
1294
|
.agent-picker-desc {
|
|
1242
1295
|
font-size: 11px;
|
|
1243
1296
|
color: #565f89;
|
|
1297
|
+
text-align: right;
|
|
1244
1298
|
}
|
|
1245
1299
|
|
|
1246
1300
|
.agent-picker-hint {
|
|
@@ -1265,6 +1319,201 @@ html, body, #root {
|
|
|
1265
1319
|
accent-color: #7aa2f7;
|
|
1266
1320
|
}
|
|
1267
1321
|
|
|
1322
|
+
/* ─── Remote (SSH) connect ───────────────────────── */
|
|
1323
|
+
|
|
1324
|
+
.remote-section-label {
|
|
1325
|
+
font-size: 10px;
|
|
1326
|
+
color: #565f89;
|
|
1327
|
+
text-transform: uppercase;
|
|
1328
|
+
letter-spacing: 1px;
|
|
1329
|
+
text-align: left;
|
|
1330
|
+
margin: 16px 0 8px;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
/* Scroll the host list rather than letting it grow the whole modal. */
|
|
1334
|
+
.remote-host-scroll {
|
|
1335
|
+
max-height: 40vh;
|
|
1336
|
+
overflow-y: auto;
|
|
1337
|
+
padding-right: 4px;
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
/* Project rows: title on top, path muted + truncated below (paths are long). */
|
|
1341
|
+
.project-item {
|
|
1342
|
+
flex-direction: column;
|
|
1343
|
+
align-items: flex-start;
|
|
1344
|
+
gap: 4px;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
.project-item .agent-picker-name {
|
|
1348
|
+
max-width: 100%;
|
|
1349
|
+
overflow: hidden;
|
|
1350
|
+
text-overflow: ellipsis;
|
|
1351
|
+
white-space: nowrap;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
.project-item .agent-picker-desc {
|
|
1355
|
+
text-align: left;
|
|
1356
|
+
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
|
1357
|
+
font-size: 10px;
|
|
1358
|
+
max-width: 100%;
|
|
1359
|
+
overflow: hidden;
|
|
1360
|
+
text-overflow: ellipsis;
|
|
1361
|
+
white-space: nowrap;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
/* Compact host rows so more fit before scrolling. */
|
|
1365
|
+
.remote-host-scroll .agent-picker-item {
|
|
1366
|
+
padding: 10px 14px;
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
.remote-toggle {
|
|
1370
|
+
display: flex;
|
|
1371
|
+
align-items: center;
|
|
1372
|
+
gap: 8px;
|
|
1373
|
+
margin-bottom: 4px;
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
.remote-toggle-label {
|
|
1377
|
+
font-size: 12px;
|
|
1378
|
+
color: #565f89;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
.remote-toggle-btn {
|
|
1382
|
+
flex: 1;
|
|
1383
|
+
padding: 8px 10px;
|
|
1384
|
+
background: #16161e;
|
|
1385
|
+
border: 1px solid #2a2b3d;
|
|
1386
|
+
border-radius: 8px;
|
|
1387
|
+
color: #a9b1d6;
|
|
1388
|
+
font-size: 12px;
|
|
1389
|
+
cursor: pointer;
|
|
1390
|
+
transition: all 0.15s;
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
.remote-toggle-btn:hover {
|
|
1394
|
+
border-color: #7aa2f7;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
.remote-toggle-btn.is-active {
|
|
1398
|
+
border-color: #7aa2f7;
|
|
1399
|
+
background: #1a1b2e;
|
|
1400
|
+
color: #c0caf5;
|
|
1401
|
+
font-weight: 600;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
.remote-manual {
|
|
1405
|
+
display: flex;
|
|
1406
|
+
gap: 8px;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
.remote-input {
|
|
1410
|
+
flex: 1;
|
|
1411
|
+
padding: 10px 12px;
|
|
1412
|
+
background: #16161e;
|
|
1413
|
+
border: 1px solid #2a2b3d;
|
|
1414
|
+
border-radius: 8px;
|
|
1415
|
+
color: #c0caf5;
|
|
1416
|
+
font-family: 'JetBrains Mono', 'Fira Code', monospace;
|
|
1417
|
+
font-size: 12px;
|
|
1418
|
+
outline: none;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
.remote-input:focus {
|
|
1422
|
+
border-color: #7aa2f7;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
.remote-btn {
|
|
1426
|
+
padding: 10px 16px;
|
|
1427
|
+
background: #7aa2f7;
|
|
1428
|
+
border: none;
|
|
1429
|
+
border-radius: 8px;
|
|
1430
|
+
color: #1f2335;
|
|
1431
|
+
font-size: 12px;
|
|
1432
|
+
font-weight: 600;
|
|
1433
|
+
cursor: pointer;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
.remote-btn:disabled {
|
|
1437
|
+
opacity: 0.4;
|
|
1438
|
+
cursor: default;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
.remote-link {
|
|
1442
|
+
margin-top: 18px;
|
|
1443
|
+
background: none;
|
|
1444
|
+
border: none;
|
|
1445
|
+
color: #7aa2f7;
|
|
1446
|
+
font-size: 12px;
|
|
1447
|
+
cursor: pointer;
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
.remote-status {
|
|
1451
|
+
padding: 24px 8px;
|
|
1452
|
+
color: #a9b1d6;
|
|
1453
|
+
font-size: 13px;
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
.remote-status-sub {
|
|
1457
|
+
margin-top: 6px;
|
|
1458
|
+
font-size: 11px;
|
|
1459
|
+
color: #565f89;
|
|
1460
|
+
word-break: break-word;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
.remote-spinner {
|
|
1464
|
+
width: 22px;
|
|
1465
|
+
height: 22px;
|
|
1466
|
+
margin: 0 auto 14px;
|
|
1467
|
+
border: 2px solid #2a2b3d;
|
|
1468
|
+
border-top-color: #7aa2f7;
|
|
1469
|
+
border-radius: 50%;
|
|
1470
|
+
animation: remote-spin 0.8s linear infinite;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
@keyframes remote-spin {
|
|
1474
|
+
to { transform: rotate(360deg); }
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
.remote-target-line {
|
|
1478
|
+
font-size: 13px;
|
|
1479
|
+
color: #a9b1d6;
|
|
1480
|
+
margin-bottom: 4px;
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
.remote-note {
|
|
1484
|
+
font-size: 11px;
|
|
1485
|
+
color: #e0af68;
|
|
1486
|
+
background: rgba(224, 175, 104, 0.08);
|
|
1487
|
+
border: 1px solid rgba(224, 175, 104, 0.25);
|
|
1488
|
+
border-radius: 8px;
|
|
1489
|
+
padding: 8px 12px;
|
|
1490
|
+
margin: 8px 0;
|
|
1491
|
+
text-align: left;
|
|
1492
|
+
line-height: 1.4;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
.remote-error {
|
|
1496
|
+
font-size: 13px;
|
|
1497
|
+
color: #f7768e;
|
|
1498
|
+
margin-bottom: 4px;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
.remote-pw {
|
|
1502
|
+
margin: 8px 0 4px;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
.remote-pw .remote-input {
|
|
1506
|
+
width: 100%;
|
|
1507
|
+
box-sizing: border-box;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
.remote-pw-hint {
|
|
1511
|
+
margin-top: 6px;
|
|
1512
|
+
font-size: 10px;
|
|
1513
|
+
color: #565f89;
|
|
1514
|
+
text-align: left;
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1268
1517
|
/* Settings dialog */
|
|
1269
1518
|
.settings-overlay {
|
|
1270
1519
|
position: fixed;
|
|
@@ -1511,6 +1760,32 @@ html, body, #root {
|
|
|
1511
1760
|
color: #7aa2f7;
|
|
1512
1761
|
font-weight: 600;
|
|
1513
1762
|
}
|
|
1763
|
+
/* "+ New" action in the header (replaces the old footer button). */
|
|
1764
|
+
.ticket-drawer-new {
|
|
1765
|
+
flex-shrink: 0;
|
|
1766
|
+
align-self: center;
|
|
1767
|
+
display: inline-flex;
|
|
1768
|
+
align-items: center;
|
|
1769
|
+
gap: 3px;
|
|
1770
|
+
padding: 5px 11px;
|
|
1771
|
+
border-radius: 7px;
|
|
1772
|
+
background: rgba(122, 162, 247, 0.14);
|
|
1773
|
+
border: 1px solid rgba(122, 162, 247, 0.3);
|
|
1774
|
+
color: #9db4f5;
|
|
1775
|
+
font-family: inherit;
|
|
1776
|
+
font-size: 12px;
|
|
1777
|
+
font-weight: 600;
|
|
1778
|
+
cursor: pointer;
|
|
1779
|
+
transition: background 0.13s ease, border-color 0.13s ease, color 0.13s ease, transform 0.06s ease;
|
|
1780
|
+
}
|
|
1781
|
+
.ticket-drawer-new:hover {
|
|
1782
|
+
background: rgba(122, 162, 247, 0.22);
|
|
1783
|
+
border-color: rgba(122, 162, 247, 0.5);
|
|
1784
|
+
color: #c0d0fb;
|
|
1785
|
+
}
|
|
1786
|
+
.ticket-drawer-new:active {
|
|
1787
|
+
transform: translateY(1px);
|
|
1788
|
+
}
|
|
1514
1789
|
.ticket-drawer-warn {
|
|
1515
1790
|
color: #e0af68;
|
|
1516
1791
|
}
|
|
@@ -1708,6 +1983,49 @@ html, body, #root {
|
|
|
1708
1983
|
text-align: center;
|
|
1709
1984
|
}
|
|
1710
1985
|
|
|
1986
|
+
/* ── collapsible "Done" section header ── */
|
|
1987
|
+
.ticket-done-toggle {
|
|
1988
|
+
display: flex;
|
|
1989
|
+
align-items: center;
|
|
1990
|
+
gap: 7px;
|
|
1991
|
+
width: 100%;
|
|
1992
|
+
margin-top: 3px;
|
|
1993
|
+
padding: 7px 4px;
|
|
1994
|
+
background: none;
|
|
1995
|
+
border: none;
|
|
1996
|
+
border-top: 1px solid #262a3f;
|
|
1997
|
+
color: #6b739b;
|
|
1998
|
+
font-family: inherit;
|
|
1999
|
+
font-size: 11.5px;
|
|
2000
|
+
font-weight: 600;
|
|
2001
|
+
letter-spacing: 0.03em;
|
|
2002
|
+
text-transform: uppercase;
|
|
2003
|
+
cursor: pointer;
|
|
2004
|
+
transition: color 0.13s ease;
|
|
2005
|
+
}
|
|
2006
|
+
.ticket-done-toggle:hover {
|
|
2007
|
+
color: #a9b1d6;
|
|
2008
|
+
}
|
|
2009
|
+
.ticket-done-caret {
|
|
2010
|
+
display: inline-block;
|
|
2011
|
+
font-size: 10px;
|
|
2012
|
+
transition: transform 0.13s ease;
|
|
2013
|
+
}
|
|
2014
|
+
.ticket-done-caret.open {
|
|
2015
|
+
transform: rotate(90deg);
|
|
2016
|
+
}
|
|
2017
|
+
.ticket-done-count {
|
|
2018
|
+
margin-left: auto;
|
|
2019
|
+
min-width: 18px;
|
|
2020
|
+
padding: 1px 6px;
|
|
2021
|
+
border-radius: 9px;
|
|
2022
|
+
background: #262a3f;
|
|
2023
|
+
color: #8088ac;
|
|
2024
|
+
font-size: 11px;
|
|
2025
|
+
font-weight: 600;
|
|
2026
|
+
text-align: center;
|
|
2027
|
+
}
|
|
2028
|
+
|
|
1711
2029
|
.ticket-empty {
|
|
1712
2030
|
display: flex;
|
|
1713
2031
|
flex-direction: column;
|