@manny-est/node-red-flowpilot 0.2.2 → 0.4.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.
@@ -0,0 +1,1189 @@
1
+ #fp-root {
2
+ height: 100%;
3
+ display: flex;
4
+ flex-direction: column;
5
+ background: var(--red-ui-primary-background, #fff);
6
+ color: var(--red-ui-primary-text-color, #333);
7
+ overflow: hidden;
8
+ }
9
+
10
+ .fp-header {
11
+ padding: 16px;
12
+ border-bottom: 1px solid var(--red-ui-secondary-border-color, #ddd);
13
+ background: var(--red-ui-secondary-background, #f8f8f8);
14
+ }
15
+
16
+ .fp-header-row {
17
+ display: flex;
18
+ align-items: center;
19
+ gap: 12px;
20
+ }
21
+
22
+ .fp-logo {
23
+ width: 36px;
24
+ height: 36px;
25
+ border-radius: 10px;
26
+ background: #1f2f46;
27
+ color: #fff;
28
+ display: flex;
29
+ align-items: center;
30
+ justify-content: center;
31
+ font-weight: 700;
32
+ }
33
+
34
+ .fp-heading {
35
+ flex: 1;
36
+ min-width: 0;
37
+ }
38
+
39
+ .fp-title {
40
+ font-size: 20px;
41
+ font-weight: 700;
42
+ }
43
+
44
+ .fp-subtitle {
45
+ font-size: 14px;
46
+ color: var(--red-ui-secondary-text-color, #777);
47
+ }
48
+
49
+ .fp-view-buttons {
50
+ display: flex;
51
+ gap: 6px;
52
+ position: relative;
53
+ top: 2px;
54
+ }
55
+
56
+ .fp-panel {
57
+ flex: 1;
58
+ min-height: 0;
59
+ display: flex;
60
+ flex-direction: column;
61
+ overflow: hidden;
62
+ }
63
+
64
+ .fp-hidden {
65
+ display: none !important;
66
+ }
67
+
68
+ .fp-warning {
69
+ margin: 16px;
70
+ padding: 12px 14px;
71
+ border: 1px solid #ff9800;
72
+ border-radius: 8px;
73
+ background: rgba(255, 152, 0, 0.12);
74
+ line-height: 1.45;
75
+ }
76
+
77
+ .fp-messages {
78
+ flex: 1;
79
+ min-height: 0;
80
+ overflow-y: auto;
81
+ padding: 0 16px 16px 16px;
82
+ }
83
+
84
+ .fp-message {
85
+ margin-bottom: 12px;
86
+ padding: 12px 14px;
87
+ border-radius: 8px;
88
+ border: 1px solid var(--red-ui-secondary-border-color, #ddd);
89
+ background: var(--red-ui-secondary-background, #f7f7f7);
90
+ line-height: 1.45;
91
+ white-space: pre-wrap;
92
+ }
93
+
94
+ .fp-label {
95
+ font-size: 11px;
96
+ letter-spacing: 0.06em;
97
+ color: var(--red-ui-secondary-text-color, #888);
98
+ margin-bottom: 6px;
99
+ }
100
+
101
+ .fp-user {
102
+ background: rgba(80, 130, 255, 0.12);
103
+ border-color: rgba(80, 130, 255, 0.35);
104
+ }
105
+
106
+ .fp-error {
107
+ background: rgba(255, 80, 80, 0.12);
108
+ border-color: rgba(255, 80, 80, 0.65);
109
+ }
110
+
111
+ /* Rendered markdown inside chat bubbles. */
112
+ .fp-md > *:first-child {
113
+ margin-top: 0;
114
+ }
115
+ .fp-md > *:last-child {
116
+ margin-bottom: 0;
117
+ }
118
+ .fp-md p {
119
+ margin: 0 0 8px 0;
120
+ }
121
+ .fp-md ul, .fp-md ol {
122
+ margin: 0 0 8px 0;
123
+ padding-left: 22px;
124
+ }
125
+ .fp-md li {
126
+ margin-bottom: 2px;
127
+ }
128
+ .fp-md h3, .fp-md h4, .fp-md h5, .fp-md h6 {
129
+ margin: 10px 0 6px 0;
130
+ line-height: 1.3;
131
+ }
132
+ .fp-md code {
133
+ font-family: monospace;
134
+ background: rgba(127, 127, 127, 0.15);
135
+ border-radius: 3px;
136
+ padding: 1px 4px;
137
+ white-space: pre-wrap;
138
+ }
139
+ .fp-md pre {
140
+ margin: 0 0 8px 0;
141
+ padding: 8px 10px;
142
+ border-radius: 5px;
143
+ background: rgba(127, 127, 127, 0.12);
144
+ overflow-x: auto;
145
+ white-space: pre;
146
+ }
147
+ .fp-md pre code {
148
+ background: none;
149
+ padding: 0;
150
+ }
151
+ .fp-md .fp-code-toolbar {
152
+ display: flex;
153
+ justify-content: flex-end;
154
+ margin-bottom: 2px;
155
+ }
156
+ .fp-md a {
157
+ color: var(--red-ui-text-color-link, #1f88e5);
158
+ }
159
+ .fp-md table {
160
+ margin: 0 0 8px 0;
161
+ border-collapse: collapse;
162
+ width: 100%;
163
+ overflow-x: auto;
164
+ display: block;
165
+ }
166
+ .fp-md table tbody, .fp-md table thead {
167
+ display: table;
168
+ width: 100%;
169
+ table-layout: auto;
170
+ }
171
+ .fp-md th, .fp-md td {
172
+ border: 1px solid var(--red-ui-secondary-border-color, #ddd);
173
+ padding: 4px 8px;
174
+ text-align: left;
175
+ }
176
+ .fp-md th {
177
+ background: rgba(127, 127, 127, 0.15);
178
+ font-weight: 600;
179
+ }
180
+
181
+ /* Pending "typing" indicator — three bouncing dots. */
182
+ .fp-typing {
183
+ display: flex;
184
+ gap: 5px;
185
+ padding: 4px 0;
186
+ }
187
+
188
+ .fp-typing span:not(.fp-typing-label) {
189
+ width: 7px;
190
+ height: 7px;
191
+ border-radius: 50%;
192
+ background: var(--red-ui-secondary-text-color, #999);
193
+ opacity: 0.4;
194
+ animation: fp-bounce 1.2s infinite ease-in-out;
195
+ }
196
+
197
+ .fp-typing span:nth-child(2) { animation-delay: 0.18s; }
198
+ .fp-typing span:nth-child(3) { animation-delay: 0.36s; }
199
+
200
+ .fp-typing-label {
201
+ font-size: 11px;
202
+ color: var(--red-ui-secondary-text-color, #999);
203
+ margin-left: 4px;
204
+ align-self: center;
205
+ }
206
+
207
+ .fp-agent-stop {
208
+ margin-left: 8px;
209
+ align-self: center;
210
+ }
211
+
212
+ .fp-agent-stop:disabled {
213
+ opacity: 0.6;
214
+ }
215
+
216
+ @keyframes fp-bounce {
217
+ 0%, 60%, 100% { transform: translateY(0); opacity: 0.4; }
218
+ 30% { transform: translateY(-5px); opacity: 1; }
219
+ }
220
+
221
+ /* Action chips ("paper plane" actions) — a tappable next-step
222
+ the model suggests, rendered below the message that proposed it. */
223
+ .fp-chip-row {
224
+ margin: -4px 0 12px 4px;
225
+ }
226
+
227
+ .fp-chip {
228
+ max-width: 100%;
229
+ overflow: hidden;
230
+ text-overflow: ellipsis;
231
+ white-space: nowrap;
232
+ }
233
+
234
+ /* Big icon-tile chip card (renderActionChip/renderChip's single-CTA
235
+ chips only — NOT the multi-option clarifying-question buttons below,
236
+ which stay small/inline since several sit side by side). Cockpit-family
237
+ styling matching .fp-action-bar's fixed dark palette intentionally —
238
+ "AI-armed and user-armed controls read as one language." */
239
+ .fp-chip-card {
240
+ width: 100%;
241
+ display: flex;
242
+ align-items: center;
243
+ gap: 10px;
244
+ background: #141a21;
245
+ border: 1px solid #2c3742;
246
+ border-radius: 9px;
247
+ padding: 10px 12px;
248
+ color: #dfe6ee;
249
+ cursor: pointer;
250
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), 0 2px 6px rgba(0, 0, 0, 0.18);
251
+ transition: border-color .12s ease, box-shadow .12s ease;
252
+ text-align: left;
253
+ white-space: normal;
254
+ }
255
+
256
+ .fp-chip-card:hover {
257
+ border-color: #46d39a;
258
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), 0 0 0 1px #46d39a, 0 0 14px -2px #46d39a;
259
+ }
260
+
261
+ .fp-chip-card:active {
262
+ transform: translateY(1px);
263
+ }
264
+
265
+ .fp-chip-card .fp-chip-icon {
266
+ display: flex;
267
+ align-items: center;
268
+ justify-content: center;
269
+ width: 30px;
270
+ height: 30px;
271
+ flex: none;
272
+ border-radius: 7px;
273
+ color: #46d39a;
274
+ background: rgba(70, 211, 154, 0.10);
275
+ border: 1px solid rgba(70, 211, 154, 0.35);
276
+ }
277
+
278
+ .fp-chip-card .fp-chip-body {
279
+ flex: 1 1 auto;
280
+ min-width: 0;
281
+ display: block;
282
+ }
283
+
284
+ .fp-chip-card .fp-chip-title {
285
+ display: block;
286
+ font-size: 12.5px;
287
+ font-weight: 600;
288
+ color: #fff;
289
+ overflow: hidden;
290
+ text-overflow: ellipsis;
291
+ white-space: nowrap;
292
+ }
293
+
294
+ .fp-chip-card .fp-chip-sub {
295
+ display: block;
296
+ font-size: 11px;
297
+ color: #8a96a3;
298
+ margin-top: 1px;
299
+ overflow: hidden;
300
+ text-overflow: ellipsis;
301
+ white-space: nowrap;
302
+ }
303
+
304
+ .fp-chip-card .fp-chip-go {
305
+ flex: none;
306
+ color: #46d39a;
307
+ font-size: 16px;
308
+ }
309
+
310
+ .fp-chip-hint {
311
+ margin-top: 4px;
312
+ font-size: 12px;
313
+ color: var(--red-ui-secondary-text-color, #888);
314
+ }
315
+
316
+ /* Clarifying-question quick replies: option buttons + a free-text "Other"
317
+ that reveals an inline input. Reuses .fp-chip's look, wrapped in a row. */
318
+ .fp-question-row {
319
+ display: flex;
320
+ flex-wrap: wrap;
321
+ gap: 6px;
322
+ align-items: center;
323
+ }
324
+
325
+ .fp-question-option,
326
+ .fp-question-other {
327
+ white-space: nowrap;
328
+ }
329
+
330
+ .fp-question-other-row {
331
+ display: flex;
332
+ gap: 6px;
333
+ margin: 6px 0 12px 4px;
334
+ }
335
+
336
+ .fp-question-other-input {
337
+ flex: 1;
338
+ min-width: 0;
339
+ padding: 4px 8px;
340
+ border-radius: 4px;
341
+ border: 1px solid var(--red-ui-form-input-border-color, #ccc);
342
+ background: var(--red-ui-form-input-background, #fff);
343
+ color: var(--red-ui-form-text-color, #333);
344
+ font-family: inherit;
345
+ font-size: 13px;
346
+ }
347
+
348
+ /* Recall results — read-only snippets from earlier conversations. */
349
+ .fp-recall {
350
+ background: rgba(150, 120, 255, 0.10);
351
+ border-color: rgba(150, 120, 255, 0.35);
352
+ }
353
+
354
+ .fp-recall-item {
355
+ margin-top: 8px;
356
+ padding-top: 8px;
357
+ border-top: 1px solid var(--red-ui-secondary-border-color, #ddd);
358
+ }
359
+
360
+ .fp-recall-item:first-of-type {
361
+ margin-top: 0;
362
+ padding-top: 0;
363
+ border-top: none;
364
+ }
365
+
366
+ .fp-recall-meta {
367
+ font-size: 11px;
368
+ color: var(--red-ui-secondary-text-color, #888);
369
+ margin-bottom: 2px;
370
+ }
371
+
372
+ .fp-recall-text {
373
+ font-size: 13px;
374
+ }
375
+
376
+ .fp-recall-use {
377
+ margin-top: 6px;
378
+ }
379
+
380
+ .fp-recall-use:disabled {
381
+ opacity: 0.6;
382
+ }
383
+
384
+ /* "Flight log" conversation list. */
385
+ .fp-history-list {
386
+ margin-top: 10px;
387
+ }
388
+
389
+ .fp-history-item {
390
+ display: flex;
391
+ align-items: center;
392
+ gap: 8px;
393
+ padding: 10px 8px;
394
+ border-radius: 6px;
395
+ border: 1px solid var(--red-ui-secondary-border-color, #ddd);
396
+ margin-bottom: 6px;
397
+ }
398
+
399
+ .fp-history-current {
400
+ border-color: rgba(31, 136, 229, 0.5);
401
+ background: rgba(31, 136, 229, 0.08);
402
+ }
403
+
404
+ .fp-history-main {
405
+ flex: 1;
406
+ min-width: 0;
407
+ cursor: pointer;
408
+ }
409
+
410
+ .fp-history-title {
411
+ font-size: 13px;
412
+ font-weight: 600;
413
+ overflow: hidden;
414
+ text-overflow: ellipsis;
415
+ white-space: nowrap;
416
+ }
417
+
418
+ .fp-history-meta {
419
+ font-size: 11px;
420
+ color: var(--red-ui-secondary-text-color, #888);
421
+ margin-top: 2px;
422
+ }
423
+
424
+ .fp-history-delete {
425
+ flex: 0 0 auto;
426
+ }
427
+
428
+ .fp-json {
429
+ margin: 0;
430
+ padding: 10px;
431
+ border-radius: 6px;
432
+ background: var(--red-ui-secondary-background, #f0f0f0);
433
+ border: 1px solid var(--red-ui-secondary-border-color, #ddd);
434
+ font-family: monospace;
435
+ font-size: 12px;
436
+ line-height: 1.4;
437
+ white-space: pre-wrap;
438
+ word-break: break-word;
439
+ max-height: 320px;
440
+ overflow-y: auto;
441
+ }
442
+
443
+ /* Generated-flow review — bespoke tabs styled to sit comfortably in the editor's
444
+ theme (--red-ui-* variables) without depending on Node-RED's internal
445
+ tab/export markup, which is undocumented and fragile across versions. */
446
+ .fp-tabs {
447
+ display: flex;
448
+ gap: 4px;
449
+ margin-bottom: 10px;
450
+ border-bottom: 1px solid var(--red-ui-secondary-border-color, #ddd);
451
+ }
452
+
453
+ .fp-tab {
454
+ padding: 6px 14px;
455
+ border: none;
456
+ border-bottom: 2px solid transparent;
457
+ background: transparent;
458
+ color: var(--red-ui-secondary-text-color, #888);
459
+ font-size: 12px;
460
+ cursor: pointer;
461
+ }
462
+
463
+ .fp-tab-active {
464
+ color: var(--red-ui-primary-text-color, #333);
465
+ border-bottom-color: #1f88e5;
466
+ font-weight: 600;
467
+ }
468
+
469
+ .fp-review-count {
470
+ font-weight: 600;
471
+ margin-bottom: 6px;
472
+ }
473
+
474
+ .fp-review-list {
475
+ margin: 0 0 10px 0;
476
+ padding-left: 20px;
477
+ }
478
+
479
+ .fp-review-list li {
480
+ margin-bottom: 4px;
481
+ }
482
+
483
+ .fp-type-flag {
484
+ color: #b35900;
485
+ font-size: 11px;
486
+ }
487
+
488
+ .fp-review-warning ul {
489
+ margin: 6px 0;
490
+ padding-left: 20px;
491
+ }
492
+
493
+ .fp-review-actions {
494
+ margin-top: 12px;
495
+ display: flex;
496
+ align-items: center;
497
+ gap: 12px;
498
+ flex-wrap: wrap;
499
+ }
500
+
501
+ .fp-review-hint {
502
+ font-size: 12px;
503
+ color: var(--red-ui-secondary-text-color, #888);
504
+ }
505
+
506
+ /* /build loop stepper — reuses .fp-review's card look (see addGeneratedReview)
507
+ rather than introducing a new visual language. */
508
+ .fp-loop-steps {
509
+ display: flex;
510
+ flex-wrap: wrap;
511
+ gap: 6px;
512
+ margin-bottom: 8px;
513
+ }
514
+
515
+ .fp-loop-step {
516
+ font-size: 12px;
517
+ padding: 4px 10px;
518
+ border-radius: 12px;
519
+ background: var(--red-ui-secondary-background, #eee);
520
+ color: var(--red-ui-secondary-text-color, #888);
521
+ }
522
+
523
+ .fp-loop-step-active {
524
+ background: #1f88e5;
525
+ color: #fff;
526
+ font-weight: 600;
527
+ }
528
+
529
+ .fp-loop-hint {
530
+ font-size: 12px;
531
+ color: var(--red-ui-secondary-text-color, #888);
532
+ margin-bottom: 8px;
533
+ }
534
+
535
+ .fp-loop-actions {
536
+ display: flex;
537
+ justify-content: flex-end;
538
+ }
539
+
540
+ .fp-json-toolbar {
541
+ display: flex;
542
+ justify-content: flex-end;
543
+ margin-bottom: 6px;
544
+ }
545
+
546
+ .fp-compose {
547
+ flex-shrink: 0;
548
+ padding: 14px 16px;
549
+ border-top: 1px solid var(--red-ui-secondary-border-color, #ddd);
550
+ }
551
+
552
+ /* Armed Execute action (e.g. Generate toggled on) — lit blue, matching the
553
+ mode color-coding's blue = "about to propose changes" on #fp-prompt's border. */
554
+ .fp-intents .red-ui-button.fp-action-armed {
555
+ background: rgba(31, 136, 229, 0.16) !important;
556
+ border-color: #1f88e5 !important;
557
+ color: #1f88e5 !important;
558
+ box-shadow: inset 0 -1px 3px rgba(0, 0, 0, 0.3), 0 0 10px -2px rgba(31, 136, 229, 0.8) !important;
559
+ }
560
+
561
+ /* Armed Query intent — lit amber, matching the mode color-coding's amber =
562
+ "won't change your flow" on #fp-prompt's border. Equal specificity to the blue rule
563
+ above, so this later rule wins for buttons inside .fp-intents-query. */
564
+ .fp-intents-query .red-ui-button.fp-action-armed {
565
+ background: rgba(255, 152, 0, 0.16) !important;
566
+ border-color: #ff9800 !important;
567
+ color: #cc7a00 !important;
568
+ box-shadow: inset 0 -1px 3px rgba(0, 0, 0, 0.3), 0 0 10px -2px rgba(255, 152, 0, 0.8) !important;
569
+ }
570
+
571
+ /* Annunciator "on" lamp — a small lit dot in the corner of an armed Execute
572
+ button, on top of the blue glow above. Query intents don't get this (no
573
+ "armed and about to act" implication for a read-only Query action). */
574
+ .fp-intents-execute .red-ui-button.fp-action-armed {
575
+ position: relative;
576
+ }
577
+
578
+ .fp-intents-execute .red-ui-button.fp-action-armed::after {
579
+ content: "";
580
+ position: absolute;
581
+ top: 3px;
582
+ right: 3px;
583
+ width: 4px;
584
+ height: 4px;
585
+ border-radius: 50%;
586
+ background: #1f88e5;
587
+ box-shadow: 0 0 6px 1px #1f88e5;
588
+ }
589
+
590
+ /* Send gets the same accent as an armed Execute action so it's clear that
591
+ clicking it now proposes a change rather than chatting — especially after
592
+ an action chip pre-fills the prompt and switches modes. */
593
+ #fp-send.fp-send-armed {
594
+ box-shadow: 0 0 0 2px #1f88e5;
595
+ }
596
+
597
+ /* Mirrors the blue Execute-armed glow above for an armed Query intent —
598
+ Send adopts the same amber the prompt border already shows. */
599
+ .fp-compose.fp-mode-query #fp-send {
600
+ box-shadow: 0 0 0 2px #ff9800;
601
+ border-color: #ff9800;
602
+ }
603
+
604
+ /* Idle "ready to fly" hover — only when nothing is armed at all, so it
605
+ never fights the blue/amber armed treatments above. */
606
+ .fp-compose:not(.fp-mode-query):not(.fp-mode-execute) #fp-send:hover {
607
+ border-color: #46d39a;
608
+ box-shadow: 0 0 0 2px #46d39a;
609
+ }
610
+
611
+ /* /demo: once the sample prompt has finished typing in, gently pulse Send
612
+ to draw the eye towards it. Stops the moment the user sends or edits. */
613
+ #fp-send.fp-send-breathe {
614
+ animation: fp-breathe 1.6s ease-in-out infinite;
615
+ }
616
+
617
+ @keyframes fp-breathe {
618
+ 0%, 100% { box-shadow: 0 0 0 2px #1f88e5; transform: scale(1); }
619
+ 50% { box-shadow: 0 0 0 6px rgba(31, 136, 229, 0.35); transform: scale(1.05); }
620
+ }
621
+
622
+ /* Cockpit strip: fixed dark background (not theme-derived, by design — a
623
+ stable "instrument panel" the amber/blue accents read against in both
624
+ light and dark editor themes). Scoped tightly to the action bar itself,
625
+ not the whole compose area. */
626
+ .fp-action-bar {
627
+ display: flex;
628
+ align-items: center;
629
+ gap: 12px;
630
+ margin-bottom: 10px;
631
+ background: #1f2f46;
632
+ border-radius: 6px;
633
+ padding: 6px 10px;
634
+ }
635
+
636
+ .fp-action-group {
637
+ flex: 1 1 auto;
638
+ min-width: 0;
639
+ }
640
+
641
+ .fp-action-divider {
642
+ align-self: stretch;
643
+ width: 1px;
644
+ background: rgba(255, 255, 255, 0.35);
645
+ }
646
+
647
+ /* Default (non-hover, non-armed) look for buttons on the dark cockpit
648
+ strip — light-on-dark, with a recessed inset shadow so idle buttons
649
+ read as physical "instrument panel" keys, not flat UI chrome.
650
+ Deliberately NOT !important so the existing amber/blue hover and
651
+ .fp-action-armed rules (above) keep winning. */
652
+ .fp-action-bar .red-ui-button {
653
+ background: transparent;
654
+ border-color: rgba(255, 255, 255, 0.35);
655
+ color: #f0f4f8;
656
+ box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.05);
657
+ }
658
+
659
+ .fp-action-bar .red-ui-button:hover {
660
+ background: rgba(255, 255, 255, 0.12);
661
+ border-color: rgba(255, 255, 255, 0.5);
662
+ color: #fff;
663
+ }
664
+
665
+ /* Icon-style Query/Execute buttons. Hover/armed accents reuse the
666
+ mode color-coding's amber=query / blue=execute coding (see #fp-prompt and
667
+ .fp-action-armed above) so the whole "armed" concept stays one color. */
668
+ .fp-icon-btn {
669
+ width: 32px;
670
+ height: 32px;
671
+ padding: 0 !important;
672
+ display: inline-flex;
673
+ align-items: center;
674
+ justify-content: center;
675
+ font-size: 14px;
676
+ }
677
+
678
+ .fp-icon-btn-query:hover {
679
+ color: #cc7a00 !important;
680
+ border-color: rgba(255, 152, 0, 0.5) !important;
681
+ background: rgba(255, 152, 0, 0.12) !important;
682
+ box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.05),
683
+ 0 0 8px -2px rgba(255, 152, 0, 0.6) !important;
684
+ }
685
+
686
+ .fp-icon-btn-execute:hover {
687
+ color: #1f88e5 !important;
688
+ border-color: rgba(31, 136, 229, 0.5) !important;
689
+ background: rgba(31, 136, 229, 0.12) !important;
690
+ box-shadow: inset 0 -2px 4px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.05),
691
+ 0 0 8px -2px rgba(31, 136, 229, 0.6) !important;
692
+ }
693
+
694
+ .fp-intents {
695
+ display: flex;
696
+ flex-wrap: wrap;
697
+ align-items: center;
698
+ gap: 6px;
699
+ }
700
+
701
+ .fp-intent-more-wrap {
702
+ position: relative;
703
+ flex: 0 0 auto;
704
+ }
705
+
706
+ .fp-intent-more {
707
+ flex: 0 0 auto;
708
+ }
709
+
710
+ .fp-intent-menu {
711
+ position: absolute;
712
+ top: 100%;
713
+ left: 0;
714
+ z-index: 20;
715
+ margin-top: 4px;
716
+ min-width: 140px;
717
+ background: var(--red-ui-primary-background, #fff);
718
+ border: 1px solid var(--red-ui-secondary-border-color, #ddd);
719
+ border-radius: 4px;
720
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
721
+ padding: 4px 0;
722
+ }
723
+
724
+ .fp-intent-menu a {
725
+ display: block;
726
+ padding: 6px 12px;
727
+ color: var(--red-ui-primary-text-color, #333);
728
+ text-decoration: none;
729
+ white-space: nowrap;
730
+ font-size: 12px;
731
+ }
732
+
733
+ .fp-intent-menu a:hover {
734
+ background: var(--red-ui-secondary-background, #f0f0f0);
735
+ }
736
+
737
+ .fp-intent-btn {
738
+ flex: 0 0 auto;
739
+ }
740
+
741
+ .fp-intent-custom {
742
+ border-style: dashed !important;
743
+ }
744
+
745
+ /* Active view button (chat/settings) — filled, using the header color. */
746
+ .fp-view-buttons .red-ui-button.fp-active {
747
+ background: #1f2f46 !important;
748
+ border-color: #1f2f46 !important;
749
+ color: #fff !important;
750
+ }
751
+
752
+ .fp-view-buttons .red-ui-button.fp-active i {
753
+ color: #fff !important;
754
+ }
755
+
756
+ /* De-emphasize Test relative to the primary Send action. */
757
+ /* Provider selector + actions in settings. */
758
+ #fp-provider-select {
759
+ width: 100%;
760
+ box-sizing: border-box;
761
+ padding: 8px;
762
+ border-radius: 5px;
763
+ border: 1px solid var(--red-ui-form-input-border-color, #ccc);
764
+ background: var(--red-ui-form-input-background, #fff);
765
+ color: var(--red-ui-form-text-color, #333);
766
+ }
767
+
768
+ .fp-provider-actions {
769
+ display: flex;
770
+ gap: 8px;
771
+ margin-top: 8px;
772
+ }
773
+
774
+ .fp-custom-intents {
775
+ margin: 8px 0;
776
+ }
777
+
778
+ .fp-custom-intent-row {
779
+ display: flex;
780
+ align-items: center;
781
+ justify-content: space-between;
782
+ gap: 8px;
783
+ padding: 6px 8px;
784
+ margin-bottom: 4px;
785
+ border: 1px solid var(--red-ui-secondary-border-color, #ddd);
786
+ border-radius: 5px;
787
+ }
788
+
789
+ .fp-custom-intent-label {
790
+ font-weight: 600;
791
+ overflow: hidden;
792
+ white-space: nowrap;
793
+ text-overflow: ellipsis;
794
+ }
795
+
796
+ /* Context indicators and the provider/Send footer merged
797
+ into one wrap-capable strip below the prompt box — one line when there's
798
+ room, wraps to two on a narrow sidebar (no regression vs. the previous
799
+ always-two-rows layout). */
800
+ .fp-status-strip {
801
+ display: flex;
802
+ align-items: center;
803
+ gap: 8px;
804
+ margin-top: 8px;
805
+ flex-wrap: wrap;
806
+ }
807
+
808
+ .fp-status-spacer {
809
+ flex: 1 1 auto;
810
+ min-width: 8px;
811
+ }
812
+
813
+ .fp-selection-status {
814
+ font-size: 12px;
815
+ color: var(--red-ui-secondary-text-color, #888);
816
+ display: flex;
817
+ align-items: center;
818
+ gap: 6px;
819
+ }
820
+
821
+ .fp-selection-status::before {
822
+ content: "";
823
+ display: inline-block;
824
+ width: 8px;
825
+ height: 8px;
826
+ border-radius: 50%;
827
+ background: var(--red-ui-secondary-border-color, #ccc);
828
+ }
829
+
830
+ .fp-selection-status.fp-has-selection {
831
+ color: var(--red-ui-primary-text-color, #333);
832
+ font-weight: 600;
833
+ }
834
+
835
+ .fp-selection-status.fp-has-selection::before {
836
+ background: #4caf50;
837
+ }
838
+
839
+ .fp-size-status {
840
+ font-size: 12px;
841
+ color: var(--red-ui-secondary-text-color, #888);
842
+ padding-left: 8px;
843
+ border-left: 1px solid var(--red-ui-secondary-border-color, #ddd);
844
+ }
845
+
846
+ .fp-size-status.fp-size-warn {
847
+ color: #b8860b;
848
+ font-weight: 600;
849
+ }
850
+
851
+ .fp-size-status.fp-size-high {
852
+ color: #c0392b;
853
+ font-weight: 600;
854
+ }
855
+
856
+ /* Compact secrets reminder: a small badge icon carrying the full reminder as
857
+ a tooltip, instead of a persistent multi-line warning box. */
858
+ .fp-secrets-status {
859
+ font-size: 12px;
860
+ width: 18px;
861
+ height: 18px;
862
+ line-height: 18px;
863
+ text-align: center;
864
+ border-radius: 50%;
865
+ background: rgba(255, 152, 0, 0.18);
866
+ border: 1px solid rgba(255, 152, 0, 0.5);
867
+ color: #b35900;
868
+ cursor: default;
869
+ flex: 0 0 auto;
870
+ }
871
+
872
+ .fp-secrets-status-off {
873
+ background: rgba(192, 57, 43, 0.18);
874
+ border-color: rgba(192, 57, 43, 0.6);
875
+ color: #c0392b;
876
+ }
877
+
878
+ .fp-debug-status {
879
+ font-size: 12px;
880
+ color: var(--red-ui-secondary-text-color, #888);
881
+ padding-left: 8px;
882
+ border-left: 1px solid var(--red-ui-secondary-border-color, #ddd);
883
+ }
884
+
885
+ .fp-debug-status a {
886
+ margin-left: 4px;
887
+ color: inherit;
888
+ text-decoration: none;
889
+ }
890
+
891
+ .fp-debug-status a:hover {
892
+ text-decoration: underline;
893
+ }
894
+
895
+ .fp-preview-link {
896
+ font-size: 12px;
897
+ color: var(--red-ui-secondary-text-color, #888);
898
+ text-decoration: none;
899
+ }
900
+
901
+ .fp-preview-link:hover {
902
+ text-decoration: underline;
903
+ }
904
+
905
+ .fp-settings-section {
906
+ margin-top: 18px;
907
+ padding-top: 12px;
908
+ border-top: 1px solid var(--red-ui-secondary-border-color, #ddd);
909
+ font-weight: 700;
910
+ font-size: 13px;
911
+ letter-spacing: 0.03em;
912
+ color: var(--red-ui-secondary-text-color, #777);
913
+ }
914
+
915
+ .fp-settings-group {
916
+ margin-top: 14px;
917
+ padding: 0 12px 12px 12px;
918
+ border: 1px solid var(--red-ui-secondary-border-color, #ddd);
919
+ border-radius: 6px;
920
+ }
921
+
922
+ .fp-settings-group > summary {
923
+ margin: 0 -12px;
924
+ cursor: pointer;
925
+ padding: 10px 12px;
926
+ font-weight: 700;
927
+ font-size: 13px;
928
+ letter-spacing: 0.03em;
929
+ color: var(--red-ui-primary-text-color, #333);
930
+ list-style: none;
931
+ user-select: none;
932
+ }
933
+
934
+ .fp-settings-group > summary::-webkit-details-marker {
935
+ display: none;
936
+ }
937
+
938
+ .fp-settings-group > summary::before {
939
+ content: "▸";
940
+ display: inline-block;
941
+ width: 1em;
942
+ color: var(--red-ui-secondary-text-color, #888);
943
+ }
944
+
945
+ .fp-settings-group[open] > summary::before {
946
+ content: "▾";
947
+ }
948
+
949
+ .fp-settings-group > .fp-settings-section:first-of-type {
950
+ margin-top: 0;
951
+ padding-top: 0;
952
+ border-top: none;
953
+ }
954
+
955
+ .fp-checkbox-row {
956
+ display: flex;
957
+ align-items: center;
958
+ gap: 8px;
959
+ font-weight: 600;
960
+ margin-top: 12px;
961
+ }
962
+
963
+ .fp-checkbox-row input {
964
+ width: auto;
965
+ }
966
+
967
+ .fp-consent-hint {
968
+ font-size: 12px;
969
+ color: var(--red-ui-secondary-text-color, #888);
970
+ margin: 6px 0;
971
+ line-height: 1.4;
972
+ }
973
+
974
+ .fp-agent-stats {
975
+ margin: -4px 0 8px 4px;
976
+ font-size: 11px;
977
+ }
978
+
979
+ .fp-debug-warning {
980
+ font-size: 12px;
981
+ color: var(--red-ui-secondary-text-color, #888);
982
+ text-decoration: underline;
983
+ margin: 2px 0 6px;
984
+ line-height: 1.4;
985
+ }
986
+
987
+ .fp-prompt-wrap {
988
+ position: relative;
989
+ }
990
+
991
+ #fp-prompt {
992
+ display: block;
993
+ width: 100%;
994
+ min-height: 88px;
995
+ box-sizing: border-box;
996
+ resize: none;
997
+ padding: 10px;
998
+ border-radius: 6px;
999
+ border: 1px solid var(--red-ui-form-input-border-color, #ccc);
1000
+ background: var(--red-ui-form-input-background, #fff);
1001
+ color: var(--red-ui-form-text-color, #333);
1002
+ font-family: inherit;
1003
+ font-size: 14px;
1004
+ box-shadow: 0 0 0 1px rgba(255, 152, 0, 0.35);
1005
+ transition: box-shadow 0.15s, border-color 0.15s;
1006
+ }
1007
+
1008
+ /* Mode color-coding — Query/chat (default) is orange ("won't change your
1009
+ flow"); an armed Execute action (Generate/Document/Modify) switches the
1010
+ compose area to blue ("about to propose changes"). */
1011
+ .fp-compose.fp-mode-execute #fp-prompt {
1012
+ border-color: #1f88e5;
1013
+ box-shadow: 0 0 0 1px rgba(31, 136, 229, 0.5);
1014
+ }
1015
+
1016
+ /* An armed Query intent strengthens the default amber glow into a solid
1017
+ border — the "mode readout" confirming a template is loaded and ready
1018
+ to send, mirroring .fp-mode-execute's blue treatment above. */
1019
+ .fp-compose.fp-mode-query #fp-prompt {
1020
+ border-color: #ff9800;
1021
+ box-shadow: 0 0 0 1px rgba(255, 152, 0, 0.5);
1022
+ }
1023
+
1024
+ /* Custom resize handle, top-right: native `resize: vertical` puts its grip
1025
+ at the bottom-right corner, right next to the Send/Clear buttons, which
1026
+ makes it fiddly to grab. This sits in the clear space below the context
1027
+ strip instead, and dragging it changes #fp-prompt's height directly.
1028
+ Offset further from the edge (right: 20px) so it doesn't sit on top of
1029
+ the textarea's scrollbar arrows when the prompt overflows, and hidden
1030
+ until the prompt area is hovered so it doesn't clutter that corner. */
1031
+ .fp-resize-handle {
1032
+ position: absolute;
1033
+ top: 4px;
1034
+ right: 20px;
1035
+ width: 18px;
1036
+ height: 18px;
1037
+ display: flex;
1038
+ align-items: center;
1039
+ justify-content: center;
1040
+ border-radius: 3px;
1041
+ color: var(--red-ui-secondary-text-color, #999);
1042
+ opacity: 0;
1043
+ cursor: ns-resize;
1044
+ font-size: 11px;
1045
+ user-select: none;
1046
+ transition: opacity 0.15s;
1047
+ }
1048
+
1049
+ .fp-prompt-wrap:hover .fp-resize-handle {
1050
+ opacity: 0.5;
1051
+ }
1052
+
1053
+ .fp-resize-handle:hover,
1054
+ .fp-resize-handle.fp-resizing {
1055
+ opacity: 1;
1056
+ background: rgba(127, 127, 127, 0.15);
1057
+ }
1058
+
1059
+ #fp-provider-status {
1060
+ flex: 0 1 auto;
1061
+ min-width: 0;
1062
+ max-width: 55%;
1063
+ color: var(--red-ui-secondary-text-color, #777);
1064
+ overflow: hidden;
1065
+ white-space: nowrap;
1066
+ text-overflow: ellipsis;
1067
+ }
1068
+
1069
+ .fp-settings-actions {
1070
+ display: flex;
1071
+ gap: 8px;
1072
+ }
1073
+
1074
+ .fp-save-status {
1075
+ font-size: 12px;
1076
+ align-self: center;
1077
+ color: var(--red-ui-secondary-text-color, #888);
1078
+ }
1079
+
1080
+ .fp-save-status-error {
1081
+ color: #c0392b;
1082
+ }
1083
+
1084
+ .fp-form {
1085
+ flex: 1;
1086
+ overflow-y: auto;
1087
+ padding: 0 16px 16px 16px;
1088
+ }
1089
+
1090
+ .fp-form label {
1091
+ display: block;
1092
+ margin-top: 12px;
1093
+ margin-bottom: 5px;
1094
+ font-weight: 600;
1095
+ }
1096
+
1097
+ .fp-form input,
1098
+ .fp-form textarea {
1099
+ width: 100%;
1100
+ box-sizing: border-box;
1101
+ border: 1px solid var(--red-ui-form-input-border-color, #ccc);
1102
+ background: var(--red-ui-form-input-background, #fff);
1103
+ color: var(--red-ui-form-text-color, #333);
1104
+ border-radius: 5px;
1105
+ padding: 8px;
1106
+ }
1107
+
1108
+ .fp-form textarea {
1109
+ min-height: 180px;
1110
+ resize: vertical;
1111
+ font-family: monospace;
1112
+ }
1113
+
1114
+ /* Range sliders shouldn't get the bordered/padded text-field box — the
1115
+ padding above insets the native track from both edges, leaving the thumb
1116
+ short of the true ends even at min/max. */
1117
+ .fp-form input[type="range"] {
1118
+ padding: 0;
1119
+ border: none;
1120
+ background: transparent;
1121
+ }
1122
+
1123
+ .fp-settings-actions {
1124
+ margin-top: 16px;
1125
+ padding-bottom: 16px;
1126
+ }
1127
+
1128
+ /* Modify diff review */
1129
+ .fp-diff-node {
1130
+ margin-bottom: 14px;
1131
+ padding: 10px 12px;
1132
+ border-radius: 6px;
1133
+ border: 1px solid var(--red-ui-secondary-border-color, #ddd);
1134
+ background: var(--red-ui-secondary-background, #f7f7f7);
1135
+ }
1136
+
1137
+ .fp-diff-node-title {
1138
+ font-weight: 600;
1139
+ font-size: 12px;
1140
+ margin-bottom: 8px;
1141
+ color: var(--red-ui-primary-text-color, #333);
1142
+ }
1143
+
1144
+ .fp-diff-row {
1145
+ display: grid;
1146
+ grid-template-columns: 120px 1fr 20px 1fr;
1147
+ gap: 4px 8px;
1148
+ align-items: baseline;
1149
+ margin-bottom: 5px;
1150
+ font-size: 12px;
1151
+ font-family: monospace;
1152
+ }
1153
+
1154
+ .fp-diff-key {
1155
+ font-weight: 600;
1156
+ color: var(--red-ui-secondary-text-color, #666);
1157
+ overflow: hidden;
1158
+ text-overflow: ellipsis;
1159
+ white-space: nowrap;
1160
+ }
1161
+
1162
+ .fp-diff-old {
1163
+ color: #c0392b;
1164
+ text-decoration: line-through;
1165
+ word-break: break-all;
1166
+ }
1167
+
1168
+ .fp-diff-arrow {
1169
+ color: var(--red-ui-secondary-text-color, #888);
1170
+ text-align: center;
1171
+ }
1172
+
1173
+ .fp-diff-new {
1174
+ color: #27ae60;
1175
+ font-weight: 600;
1176
+ word-break: break-all;
1177
+ }
1178
+
1179
+ .fp-diff-unchanged {
1180
+ font-size: 12px;
1181
+ color: var(--red-ui-secondary-text-color, #888);
1182
+ font-style: italic;
1183
+ }
1184
+
1185
+ .fp-diff-warn {
1186
+ font-size: 12px;
1187
+ color: #b35900;
1188
+ margin-bottom: 6px;
1189
+ }