clay-server 2.31.0 → 2.32.0-beta.10

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 (82) hide show
  1. package/lib/browser-mcp-server.js +32 -44
  2. package/lib/codex-defaults.js +18 -0
  3. package/lib/debate-mcp-server.js +14 -31
  4. package/lib/mcp-local.js +31 -1
  5. package/lib/project-connection.js +9 -6
  6. package/lib/project-debate.js +8 -0
  7. package/lib/project-filesystem.js +47 -1
  8. package/lib/project-http.js +75 -8
  9. package/lib/project-mate-interaction.js +102 -16
  10. package/lib/project-mcp.js +4 -0
  11. package/lib/project-notifications.js +9 -0
  12. package/lib/project-sessions.js +94 -51
  13. package/lib/project-user-message.js +12 -7
  14. package/lib/project.js +234 -99
  15. package/lib/public/app.js +135 -454
  16. package/lib/public/codex-avatar.png +0 -0
  17. package/lib/public/css/debate.css +3 -2
  18. package/lib/public/css/filebrowser.css +91 -1
  19. package/lib/public/css/icon-strip.css +21 -5
  20. package/lib/public/css/input.css +338 -104
  21. package/lib/public/css/mates.css +43 -0
  22. package/lib/public/css/mention.css +48 -4
  23. package/lib/public/css/menus.css +1 -1
  24. package/lib/public/css/messages.css +2 -0
  25. package/lib/public/css/notifications-center.css +26 -0
  26. package/lib/public/css/tooltip.css +47 -0
  27. package/lib/public/index.html +78 -26
  28. package/lib/public/modules/app-connection.js +138 -37
  29. package/lib/public/modules/app-cursors.js +18 -17
  30. package/lib/public/modules/app-debate-ui.js +9 -9
  31. package/lib/public/modules/app-dm.js +175 -131
  32. package/lib/public/modules/app-favicon.js +28 -26
  33. package/lib/public/modules/app-header.js +79 -68
  34. package/lib/public/modules/app-home-hub.js +55 -47
  35. package/lib/public/modules/app-loop-ui.js +34 -18
  36. package/lib/public/modules/app-loop-wizard.js +6 -6
  37. package/lib/public/modules/app-messages.js +199 -153
  38. package/lib/public/modules/app-misc.js +23 -12
  39. package/lib/public/modules/app-notifications.js +119 -9
  40. package/lib/public/modules/app-panels.js +203 -49
  41. package/lib/public/modules/app-projects.js +161 -150
  42. package/lib/public/modules/app-rate-limit.js +5 -4
  43. package/lib/public/modules/app-rendering.js +149 -101
  44. package/lib/public/modules/app-skills-install.js +4 -4
  45. package/lib/public/modules/context-sources.js +102 -66
  46. package/lib/public/modules/dom-refs.js +21 -0
  47. package/lib/public/modules/filebrowser.js +173 -2
  48. package/lib/public/modules/input.js +122 -0
  49. package/lib/public/modules/markdown.js +5 -1
  50. package/lib/public/modules/mate-sidebar.js +38 -0
  51. package/lib/public/modules/mention.js +24 -6
  52. package/lib/public/modules/scheduler.js +1 -1
  53. package/lib/public/modules/sidebar-mates.js +79 -35
  54. package/lib/public/modules/sidebar-mobile.js +34 -30
  55. package/lib/public/modules/sidebar-projects.js +60 -57
  56. package/lib/public/modules/sidebar-sessions.js +75 -69
  57. package/lib/public/modules/sidebar.js +12 -20
  58. package/lib/public/modules/skills.js +8 -9
  59. package/lib/public/modules/sticky-notes.js +1 -2
  60. package/lib/public/modules/store.js +9 -2
  61. package/lib/public/modules/stt.js +4 -1
  62. package/lib/public/modules/terminal.js +12 -0
  63. package/lib/public/modules/tools.js +18 -13
  64. package/lib/public/modules/tooltip.js +32 -5
  65. package/lib/sdk-bridge.js +562 -1114
  66. package/lib/sdk-message-processor.js +150 -135
  67. package/lib/sdk-worker.js +4 -0
  68. package/lib/server-dm.js +1 -0
  69. package/lib/server.js +86 -1
  70. package/lib/sessions.js +81 -37
  71. package/lib/ws-schema.js +2 -0
  72. package/lib/yoke/adapters/claude-worker.js +559 -0
  73. package/lib/yoke/adapters/claude.js +1483 -0
  74. package/lib/yoke/adapters/codex.js +1121 -0
  75. package/lib/yoke/adapters/gemini.js +709 -0
  76. package/lib/yoke/codex-app-server.js +307 -0
  77. package/lib/yoke/index.js +199 -0
  78. package/lib/yoke/instructions.js +62 -0
  79. package/lib/yoke/interface.js +98 -0
  80. package/lib/yoke/mcp-bridge-server.js +294 -0
  81. package/lib/yoke/package.json +7 -0
  82. package/package.json +3 -1
Binary file
@@ -2,10 +2,11 @@
2
2
  .debate-floor-mode #schedule-btn,
3
3
  .debate-floor-mode #ask-mate-btn,
4
4
  .debate-floor-mode #config-chip-wrap,
5
- .debate-floor-mode #context-sources-bar,
5
+ .debate-floor-mode #context-sources-btn-wrap,
6
6
  .debate-floor-mode #mention-menu,
7
7
  .debate-floor-mode #slash-menu,
8
- .debate-floor-mode #suggestion-chips {
8
+ .debate-floor-mode #suggestion-chips,
9
+ .debate-floor-mode #ghost-suggestion {
9
10
  display: none !important;
10
11
  }
11
12
 
@@ -92,7 +92,97 @@
92
92
  background: var(--filebrowser-bg);
93
93
  border: 1px solid var(--filebrowser-border);
94
94
  border-radius: 8px;
95
- margin: 0 6px 12px;
95
+ margin: 6px 6px 12px;
96
+ display: flex;
97
+ flex-direction: column;
98
+ }
99
+ #sidebar-panel-files.hidden { display: none; }
100
+
101
+ /* --- File browser titlebar --- */
102
+ .fb-titlebar {
103
+ display: flex;
104
+ align-items: center;
105
+ justify-content: space-between;
106
+ padding: 6px 6px;
107
+ border-bottom: 1px solid var(--filebrowser-border);
108
+ flex-shrink: 0;
109
+ user-select: none;
110
+ }
111
+ .fb-titlebar-title {
112
+ font-size: 12px;
113
+ font-weight: 600;
114
+ color: var(--text-secondary);
115
+ flex: 1;
116
+ text-align: center;
117
+ pointer-events: none;
118
+ }
119
+ .fb-titlebar button {
120
+ display: flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ width: 24px;
124
+ height: 24px;
125
+ border-radius: 6px;
126
+ border: none;
127
+ background: transparent;
128
+ color: var(--text-dimmer);
129
+ cursor: pointer;
130
+ padding: 0;
131
+ transition: color 0.15s, background 0.15s;
132
+ }
133
+ .fb-titlebar button .lucide { width: 13px; height: 13px; }
134
+ .fb-titlebar button:hover { color: var(--text); background: var(--sidebar-hover); }
135
+
136
+ /* --- File search bar (always visible) --- */
137
+ .fb-search-bar {
138
+ display: flex;
139
+ align-items: center;
140
+ padding: 4px 6px 6px;
141
+ position: relative;
142
+ flex-shrink: 0;
143
+ }
144
+ .fb-search-icon {
145
+ position: absolute;
146
+ left: 14px;
147
+ width: 13px;
148
+ height: 13px;
149
+ color: var(--text-dimmer);
150
+ pointer-events: none;
151
+ }
152
+ #fb-search-input {
153
+ width: 100%;
154
+ height: 28px;
155
+ padding: 0 8px 0 28px;
156
+ border: 1px solid var(--border);
157
+ border-radius: 6px;
158
+ background: var(--bg);
159
+ color: var(--text);
160
+ font-family: inherit;
161
+ font-size: 12px;
162
+ outline: none;
163
+ transition: border-color 0.15s;
164
+ }
165
+ #fb-search-input:focus { border-color: var(--accent); }
166
+ #fb-search-input::placeholder { color: var(--text-dimmer); }
167
+
168
+ /* Search match highlight */
169
+ .file-tree-name mark {
170
+ background: color-mix(in srgb, var(--accent) 30%, transparent);
171
+ color: inherit;
172
+ border-radius: 2px;
173
+ padding: 0 1px;
174
+ }
175
+ .fb-search-empty {
176
+ padding: 16px 12px;
177
+ font-size: 12px;
178
+ color: var(--text-dimmer);
179
+ text-align: center;
180
+ }
181
+
182
+ #file-tree {
183
+ flex: 1;
184
+ overflow-y: auto;
185
+ min-height: 0;
96
186
  }
97
187
 
98
188
  #sidebar-panel-files.fb-enter { animation: fb-in 0.2s ease-out both; }
@@ -222,16 +222,32 @@
222
222
  animation: permShake 2s ease-in-out infinite;
223
223
  }
224
224
 
225
- /* Mate status dot (bottom-right, matching user online dot) */
225
+ /* Mate status dot (top-left) */
226
226
  .icon-strip-mate .icon-strip-status {
227
- top: auto;
228
- left: auto;
229
- bottom: 5px;
230
- right: 5px;
227
+ top: 3px;
228
+ left: 3px;
229
+ bottom: auto;
230
+ right: auto;
231
231
  border-color: var(--sidebar-bg);
232
232
  z-index: 3;
233
233
  }
234
234
 
235
+ /* Mate vendor badge (bottom-right) */
236
+ .icon-strip-mate .icon-strip-vendor-badge {
237
+ position: absolute;
238
+ bottom: 3px;
239
+ right: 3px;
240
+ width: 14px;
241
+ height: 14px;
242
+ border-radius: 50%;
243
+ border: 1.5px solid var(--sidebar-bg);
244
+ background: #fff;
245
+ object-fit: cover;
246
+ object-position: center;
247
+ z-index: 3;
248
+ pointer-events: none;
249
+ }
250
+
235
251
  .icon-strip-mate.active .icon-strip-status {
236
252
  opacity: 1;
237
253
  background: var(--success);
@@ -275,44 +275,53 @@
275
275
  Context Sources — chips above input
276
276
  ========================================================================== */
277
277
 
278
- #context-sources-bar {
278
+ /* --- Context Sources (button in toolbar, chips in input-row) --- */
279
+
280
+ #context-sources-btn-wrap {
281
+ position: relative;
279
282
  display: flex;
280
283
  align-items: center;
281
- flex-wrap: wrap;
282
- gap: 4px;
283
- padding: 0 8px 4px;
284
- position: relative;
285
284
  }
286
285
 
287
286
  #context-sources-add {
288
287
  display: inline-flex;
289
288
  align-items: center;
290
- gap: 6px;
291
- padding: 6px 12px;
292
- border-radius: 6px;
293
- border: 1px dashed var(--border);
289
+ gap: 3px;
290
+ height: 36px;
291
+ padding: 0 10px;
292
+ border-radius: 18px;
293
+ border: none;
294
294
  background: transparent;
295
- color: var(--text-dimmer);
295
+ color: var(--text-muted);
296
296
  font-family: inherit;
297
297
  font-size: 12px;
298
298
  font-weight: 500;
299
299
  cursor: pointer;
300
- transition: color 0.15s, border-color 0.15s, background 0.15s;
300
+ transition: background 0.15s, color 0.15s;
301
+ white-space: nowrap;
301
302
  }
302
303
 
303
- #context-sources-add .lucide { width: 12px; height: 12px; }
304
+ #context-sources-add .lucide { width: 20px; height: 20px; flex-shrink: 0; }
304
305
 
305
306
  #context-sources-add:hover {
306
- color: var(--text-secondary);
307
- border-color: var(--text-dimmer);
308
- background: var(--sidebar-hover);
307
+ background: rgba(var(--overlay-rgb), 0.06);
308
+ color: var(--text);
309
309
  }
310
310
 
311
- #context-sources-chips {
312
- display: flex;
311
+ /* Badge count when sources are active */
312
+ #context-sources-add .ctx-badge {
313
+ display: inline-flex;
313
314
  align-items: center;
314
- flex-wrap: wrap;
315
- gap: 4px;
315
+ justify-content: center;
316
+ min-width: 16px;
317
+ height: 16px;
318
+ padding: 0 4px;
319
+ border-radius: 8px;
320
+ background: #3b82f6;
321
+ color: #fff;
322
+ font-size: 10px;
323
+ font-weight: 700;
324
+ line-height: 1;
316
325
  }
317
326
 
318
327
  .context-chip {
@@ -371,9 +380,9 @@
371
380
 
372
381
  #context-sources-picker {
373
382
  position: absolute;
374
- bottom: calc(100% + 4px);
383
+ bottom: calc(100% + 8px);
375
384
  left: 0;
376
- min-width: 200px;
385
+ min-width: 220px;
377
386
  max-height: 320px;
378
387
  overflow-y: auto;
379
388
  background: var(--sidebar-bg);
@@ -705,6 +714,10 @@
705
714
  box-shadow: 0 0 0 1px var(--border);
706
715
  }
707
716
 
717
+ #input-textarea-wrap {
718
+ position: relative;
719
+ }
720
+
708
721
  #input {
709
722
  width: 100%;
710
723
  background: transparent;
@@ -733,26 +746,99 @@
733
746
  display: flex;
734
747
  align-items: center;
735
748
  justify-content: space-between;
749
+ gap: 4px;
736
750
  }
737
751
 
738
752
  #input-bottom-right {
739
753
  display: flex;
740
754
  align-items: center;
741
755
  gap: 4px;
756
+ flex-shrink: 0;
757
+ }
758
+
759
+ /* --- Vendor toggle (split toggle) --- */
760
+ #vendor-toggle-wrap {
761
+ display: flex;
762
+ align-items: center;
763
+ border: 1px solid var(--border);
764
+ border-radius: 8px;
765
+ overflow: hidden;
766
+ height: 30px;
767
+ flex-shrink: 0;
768
+ }
769
+ #vendor-toggle-wrap.hidden { display: none; }
770
+ #vendor-toggle-wrap.locked {
771
+ border: none;
772
+ height: auto;
773
+ pointer-events: none;
774
+ }
775
+ #vendor-toggle-wrap.locked .vendor-toggle-btn:not(.active) { display: none; }
776
+ #vendor-toggle-wrap.locked .vendor-toggle-btn.active {
777
+ background: transparent;
778
+ padding: 0;
779
+ gap: 0;
780
+ opacity: 0.7;
781
+ }
782
+ #vendor-toggle-wrap.locked .vendor-toggle-btn.active .vendor-toggle-label { display: none; }
783
+ #vendor-toggle-wrap.locked .vendor-toggle-btn:first-child { border-right: none; }
784
+ .vendor-toggle-btn {
785
+ display: flex;
786
+ align-items: center;
787
+ gap: 4px;
788
+ padding: 0 10px;
789
+ height: 100%;
790
+ border: none;
791
+ background: transparent;
792
+ cursor: pointer;
793
+ font-size: 12px;
794
+ color: var(--text-secondary);
795
+ transition: background 0.15s, color 0.15s;
796
+ white-space: nowrap;
797
+ }
798
+ .vendor-toggle-btn:first-child { border-right: 1px solid var(--border); }
799
+ .vendor-toggle-btn.active {
800
+ background: var(--accent-12);
801
+ color: var(--accent);
802
+ font-weight: 600;
803
+ }
804
+ .vendor-toggle-btn.disabled {
805
+ opacity: 0.35;
806
+ cursor: default;
807
+ }
808
+ .vendor-toggle-icon {
809
+ width: 16px;
810
+ height: 16px;
811
+ border-radius: 4px;
812
+ object-fit: cover;
813
+ }
814
+ .vendor-toggle-label {
815
+ pointer-events: none;
816
+ }
817
+ @media (max-width: 900px) {
818
+ .vendor-toggle-label { display: none; }
819
+ .vendor-toggle-btn { padding: 0 8px; }
742
820
  }
743
821
 
744
822
  /* --- Attach buttons & menu --- */
745
823
  #attach-wrap {
746
824
  position: relative;
747
- flex-shrink: 0;
825
+ min-width: 0;
748
826
  display: flex;
749
827
  align-items: center;
750
828
  gap: 2px;
829
+ flex-wrap: nowrap;
830
+ overflow: hidden;
831
+ }
832
+
833
+ /* Allow popovers (context picker) to escape when open */
834
+ #attach-wrap:has(#context-sources-picker:not(.hidden)) {
835
+ overflow: visible;
751
836
  }
752
837
 
753
838
  #attach-file-btn,
754
839
  #attach-image-btn,
755
- #schedule-btn {
840
+ #schedule-btn,
841
+ #input-more-btn {
756
842
  width: 36px;
757
843
  height: 36px;
758
844
  border-radius: 50%;
@@ -769,69 +855,63 @@
769
855
 
770
856
  #attach-file-btn .lucide,
771
857
  #attach-image-btn .lucide,
772
- #schedule-btn .lucide { width: 20px; height: 20px; flex-shrink: 0; }
858
+ #schedule-btn .lucide,
859
+ #input-more-btn .lucide { width: 20px; height: 20px; flex-shrink: 0; }
773
860
 
774
861
  #attach-file-btn:hover,
775
862
  #attach-image-btn:hover,
776
- #schedule-btn:hover { background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
863
+ #schedule-btn:hover,
864
+ #input-more-btn:hover { background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
777
865
 
778
866
  #ask-mate-btn {
779
- height: 28px;
780
- padding: 0 10px;
781
- border-radius: 10px;
782
- border: 1px solid transparent;
783
- background:
784
- linear-gradient(var(--ask-mate-bg, var(--bg)), var(--ask-mate-bg, var(--bg))) padding-box,
785
- linear-gradient(135deg, #4ecdc4 0%, #4ecdc4 25%, #556bf7, #a855f7, #f857a6, #ff6b6b) border-box;
786
- color: transparent;
867
+ width: 36px;
868
+ height: 36px;
869
+ padding: 0;
870
+ border-radius: 50%;
871
+ border: none;
872
+ background: transparent;
873
+ color: var(--text-muted);
787
874
  cursor: pointer;
788
875
  display: flex;
789
876
  align-items: center;
790
- gap: 5px;
791
- font-family: 'Nunito', sans-serif;
792
- font-size: 13px;
793
- font-weight: 800;
794
- letter-spacing: 0.2px;
795
- transition: transform 0.1s, box-shadow 0.3s, border-color 0.3s;
877
+ justify-content: center;
878
+ transition: background 0.15s, color 0.15s;
796
879
  touch-action: manipulation;
797
880
  position: relative;
798
- overflow: hidden;
799
- z-index: 0;
800
881
  }
801
- #ask-mate-btn::before {
802
- content: "";
882
+
883
+ #ask-mate-btn .lucide { width: 20px; height: 20px; flex-shrink: 0; }
884
+
885
+ #ask-mate-btn:hover { background: rgba(var(--overlay-rgb), 0.06); color: var(--text); }
886
+ #ask-mate-btn:active { transform: scale(0.95); }
887
+
888
+ /* Mate avatar overlay on @ button */
889
+ .ask-mate-avatar {
803
890
  position: absolute;
804
- inset: 0;
805
- background: linear-gradient(135deg, #4ecdc4 0%, #4ecdc4 32%, #556bf7 34%, #556bf7 50%, #a855f7 52%, #a855f7 68%, #f857a6 70%, #f857a6 84%, #ff6b6b 86%, #ff6b6b 100%);
806
- border-radius: inherit;
807
- opacity: 0;
808
- transform: scale(0.3);
809
- transition: opacity 0.3s ease, transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
810
- z-index: -1;
811
- }
812
- .ask-mate-label {
813
- white-space: nowrap;
814
- background: linear-gradient(135deg, #4ecdc4 0%, #4ecdc4 25%, #556bf7, #a855f7, #f857a6, #ff6b6b);
815
- -webkit-background-clip: text;
816
- background-clip: text;
817
- -webkit-text-fill-color: transparent;
818
- transition: opacity 0.2s;
891
+ bottom: 0;
892
+ right: -2px;
893
+ width: 20px;
894
+ height: 20px;
895
+ border-radius: 50%;
896
+ border: 1.5px solid var(--input-bg);
897
+ pointer-events: none;
898
+ opacity: 0.55;
899
+ transition: opacity 0.3s, transform 0.3s;
819
900
  }
820
- #ask-mate-btn:hover::before {
821
- opacity: 1;
822
- transform: scale(1);
901
+
902
+ #ask-mate-btn:hover .ask-mate-avatar {
903
+ opacity: 0.85;
823
904
  }
824
- #ask-mate-btn:hover {
825
- border-color: transparent;
826
- background: transparent;
827
- transform: translateY(-1px);
828
- box-shadow: 0 2px 12px rgba(148, 130, 247, 0.4);
905
+
906
+ .ask-mate-avatar.fade-out {
907
+ opacity: 0;
908
+ transform: scale(0.6);
829
909
  }
830
- #ask-mate-btn:hover .ask-mate-label {
831
- background: none;
832
- -webkit-text-fill-color: #fff;
910
+
911
+ .ask-mate-avatar.fade-in {
912
+ opacity: 0.55;
913
+ transform: scale(1);
833
914
  }
834
- #ask-mate-btn:active { transform: translateY(-1px) scale(0.95); }
835
915
 
836
916
  #send-btn {
837
917
  flex-shrink: 0;
@@ -918,52 +998,66 @@
918
998
  }
919
999
 
920
1000
  /* ==========================================================================
921
- Prompt Suggestion Chips
1001
+ Prompt Suggestion Chips (legacy, hidden)
922
1002
  ========================================================================== */
923
1003
 
924
- #suggestion-chips {
925
- display: flex;
926
- flex-wrap: wrap;
927
- gap: 4px;
928
- padding: 4px 6px;
1004
+ #suggestion-chips { display: none; }
1005
+
1006
+ /* ==========================================================================
1007
+ Ghost Suggestion (inline prompt recommendation)
1008
+ ========================================================================== */
1009
+
1010
+ #ghost-suggestion {
1011
+ position: absolute;
1012
+ top: 0;
1013
+ left: 0;
1014
+ right: 0;
1015
+ padding: 8px 10px 4px;
1016
+ font-size: 16px;
1017
+ font-family: inherit;
1018
+ line-height: 1.4;
1019
+ color: var(--text-muted);
1020
+ pointer-events: none;
1021
+ white-space: pre-wrap;
1022
+ overflow: hidden;
1023
+ max-height: 120px;
1024
+ box-sizing: border-box;
929
1025
  }
930
1026
 
931
- #suggestion-chips.hidden { display: none; }
1027
+ #ghost-suggestion.hidden { display: none; }
932
1028
 
933
- .suggestion-chip {
934
- display: inline-flex;
935
- align-items: center;
936
- gap: 5px;
937
- padding: 4px 10px 4px 8px;
938
- border-radius: 6px;
1029
+ /* Hide native placeholder when ghost suggestion is visible */
1030
+ #input-textarea-wrap:has(#ghost-suggestion:not(.hidden)) #input::placeholder {
1031
+ color: transparent;
1032
+ }
1033
+
1034
+ /* Ghost hint — inline "Enter to send" after suggestion text */
1035
+
1036
+ .ghost-hint {
1037
+ font-size: 11px;
1038
+ margin-left: 8px;
1039
+ opacity: 0.55;
1040
+ white-space: nowrap;
1041
+ }
1042
+
1043
+ .ghost-hint kbd {
1044
+ display: inline-block;
1045
+ padding: 1px 5px;
1046
+ border-radius: 3px;
939
1047
  border: 1px solid var(--border);
940
1048
  background: rgba(var(--overlay-rgb), 0.08);
941
- color: var(--text-secondary);
942
- font-size: 12px;
943
1049
  font-family: inherit;
944
- cursor: pointer;
945
- transition: border-color 0.15s, background 0.15s, color 0.15s;
946
- text-align: left;
947
- max-width: 100%;
948
- line-height: 1.2;
949
- }
950
-
951
- .suggestion-chip:hover {
952
- border-color: var(--accent);
953
- background: var(--accent-bg);
954
- color: var(--accent);
1050
+ font-size: 10px;
1051
+ line-height: 1.4;
955
1052
  }
956
1053
 
957
- .suggestion-chip .lucide {
958
- width: 12px;
959
- height: 12px;
960
- flex-shrink: 0;
961
- color: var(--accent);
1054
+ @keyframes ghost-fade-in {
1055
+ from { opacity: 0; }
1056
+ to { opacity: 1; }
962
1057
  }
963
1058
 
964
- .suggestion-chip-text {
965
- flex: 1;
966
- min-width: 0;
1059
+ #ghost-suggestion:not(.hidden) {
1060
+ animation: ghost-fade-in 0.3s ease;
967
1061
  }
968
1062
 
969
1063
  /* ==========================================================================
@@ -1056,6 +1150,146 @@
1056
1150
  body.keyboard-open #input-area {
1057
1151
  padding-bottom: 8px;
1058
1152
  }
1153
+
1154
+ /* Mobile visibility utilities for input toolbar */
1155
+ .desktop-only { display: none !important; }
1156
+ .mobile-only { display: inline-flex !important; }
1157
+ }
1158
+
1159
+ /* Desktop: hide mobile-only, show desktop-only */
1160
+ @media (min-width: 769px) {
1161
+ .mobile-only { display: none !important; }
1162
+ }
1163
+
1164
+ /* ==========================================================================
1165
+ Input More Bottom Sheet (mobile)
1166
+ ========================================================================== */
1167
+
1168
+ #input-more-sheet {
1169
+ position: fixed;
1170
+ inset: 0;
1171
+ z-index: 10000;
1172
+ pointer-events: none;
1173
+ }
1174
+
1175
+ #input-more-sheet.hidden {
1176
+ display: none;
1177
+ }
1178
+
1179
+ .input-more-backdrop {
1180
+ position: absolute;
1181
+ inset: 0;
1182
+ background: rgba(0, 0, 0, 0.4);
1183
+ opacity: 0;
1184
+ transition: opacity 0.2s ease;
1185
+ pointer-events: auto;
1186
+ }
1187
+
1188
+ #input-more-sheet.open .input-more-backdrop {
1189
+ opacity: 1;
1190
+ }
1191
+
1192
+ .input-more-content {
1193
+ position: absolute;
1194
+ left: 0;
1195
+ right: 0;
1196
+ bottom: 0;
1197
+ background: var(--bg);
1198
+ border-top-left-radius: 16px;
1199
+ border-top-right-radius: 16px;
1200
+ padding: 8px 0 calc(var(--safe-bottom) + 16px);
1201
+ transform: translateY(100%);
1202
+ transition: transform 0.25s ease;
1203
+ pointer-events: auto;
1204
+ box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.15);
1205
+ }
1206
+
1207
+ #input-more-sheet.open .input-more-content {
1208
+ transform: translateY(0);
1209
+ }
1210
+
1211
+ .input-more-handle {
1212
+ width: 40px;
1213
+ height: 4px;
1214
+ border-radius: 2px;
1215
+ background: var(--border-subtle);
1216
+ margin: 8px auto 12px;
1217
+ }
1218
+
1219
+ .input-more-actions {
1220
+ display: grid;
1221
+ grid-template-columns: 1fr 1fr;
1222
+ gap: 8px;
1223
+ padding: 4px 16px 12px;
1224
+ }
1225
+
1226
+ .input-more-action {
1227
+ display: flex;
1228
+ flex-direction: column;
1229
+ align-items: center;
1230
+ justify-content: center;
1231
+ gap: 6px;
1232
+ padding: 16px 8px;
1233
+ background: var(--hover);
1234
+ border: 1px solid var(--border-subtle);
1235
+ border-radius: 10px;
1236
+ font-size: 13px;
1237
+ color: var(--text);
1238
+ cursor: pointer;
1239
+ }
1240
+
1241
+ .input-more-action:active {
1242
+ opacity: 0.7;
1243
+ }
1244
+
1245
+ .input-more-action .lucide {
1246
+ width: 22px;
1247
+ height: 22px;
1248
+ color: var(--text-secondary);
1249
+ }
1250
+
1251
+ .input-more-divider {
1252
+ height: 1px;
1253
+ background: var(--border-subtle);
1254
+ margin: 0 16px;
1255
+ }
1256
+
1257
+ .input-more-section-label {
1258
+ display: flex;
1259
+ align-items: center;
1260
+ gap: 8px;
1261
+ padding: 14px 20px 6px;
1262
+ font-size: 13px;
1263
+ font-weight: 500;
1264
+ color: var(--text-secondary);
1265
+ text-transform: uppercase;
1266
+ letter-spacing: 0.04em;
1267
+ }
1268
+
1269
+ .input-more-section-label .lucide {
1270
+ width: 16px;
1271
+ height: 16px;
1272
+ }
1273
+
1274
+ .input-more-context-body {
1275
+ max-height: 50vh;
1276
+ overflow-y: auto;
1277
+ padding: 0 8px 8px;
1278
+ }
1279
+
1280
+ .input-more-context-body .context-picker-item {
1281
+ padding: 12px 16px;
1282
+ font-size: 15px;
1283
+ border-radius: 8px;
1284
+ }
1285
+
1286
+ .input-more-context-body .context-picker-item .lucide {
1287
+ width: 18px;
1288
+ height: 18px;
1289
+ }
1290
+
1291
+ .input-more-context-body .context-picker-section-label {
1292
+ padding: 10px 16px 4px;
1059
1293
  }
1060
1294
 
1061
1295
  /* ==========================================================================