@orangeworks/orangetree 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,649 @@
1
+ /* ---- theme tokens (light / dark / system) — S7 DES-SETTINGS-003 ----
2
+ Light is the default. [data-theme="dark"] forces dark; [data-theme="light"] forces light;
3
+ no attribute => follow the OS via prefers-color-scheme. The document viewer (viewer.html)
4
+ is a dedicated always-dark reading window and is intentionally not themed here. */
5
+ :root {
6
+ color-scheme: light;
7
+ --bg: #faf8f4; /* page background */
8
+ --surface: #ffffff; /* panes, cards, inputs, buttons, modals, menus */
9
+ --surface-alt: #f5f4f0; /* assistant bubble, busy/sys lines */
10
+ --wash: #fff3e6; /* orange hover/active wash + warm cards */
11
+ --wash-soft: #fbf7ef; /* softer warm surfaces (empty-turn, neutral hover) */
12
+ --code-bg: #2d2a26; /* code blocks + toast background */
13
+ --code-text: #eeeeee; /* text on code/toast (always light) */
14
+ --code-inline: #ece8e0; /* inline code background */
15
+ --text: #333333; /* primary text */
16
+ --text-2: #555555; /* secondary text */
17
+ --text-3: #828282; /* tertiary text */
18
+ --text-faint: #a8a29a; /* muted labels */
19
+ --border: #e5e0d8; /* primary divider/border */
20
+ --border-strong: #d8d2c6; /* control borders */
21
+ --border-soft: #f0ece4; /* faint dividers */
22
+ --accent: #e8740c; /* brand orange */
23
+ --accent-hover: #d4660a;
24
+ --accent-text: #c2620a; /* orange links/labels */
25
+ --accent-border: #f0d9bc; /* warm accent-tint borders */
26
+ --on-accent: #ffffff; /* text on accent fills */
27
+ --danger: #dc2626;
28
+ --danger-hover: #b91c1c;
29
+ --danger-border: #e5b4b4;
30
+ --danger-wash: #fdf0f0;
31
+ --ok: #4ade80;
32
+ --warn: #f59e0b;
33
+ --node-label: #444444; /* canvas node title (on canvas bg) */
34
+ --node-id: #999999; /* canvas node id */
35
+ --edge: #c8bfae; /* tree edge */
36
+ --edge-dep: #b8a8d8; /* dependsOn edge */
37
+ --float: rgba(255, 255, 255, .92); /* floating canvas controls */
38
+ --scrim: rgba(0, 0, 0, .35); /* modal backdrop (neutral) */
39
+ --overlay: rgba(40, 32, 22, .34); /* modal backdrop (warm) */
40
+ --shadow-strong: rgba(0, 0, 0, .22);
41
+ --shadow-soft: rgba(0, 0, 0, .07);
42
+ }
43
+ [data-theme="dark"] {
44
+ color-scheme: dark;
45
+ --bg: #1e1e1e;
46
+ --surface: #252526;
47
+ --surface-alt: #2d2d2e;
48
+ --wash: #2f2f30;
49
+ --wash-soft: #29292a;
50
+ --code-bg: #1a1a1a;
51
+ --code-text: #d4d4d4;
52
+ --code-inline: #333334;
53
+ --text: #d4d4d4;
54
+ --text-2: #bdbdbd;
55
+ --text-3: #9d9d9d;
56
+ --text-faint: #6e6e6e;
57
+ --border: #3c3c3c;
58
+ --border-strong: #4d4d4d;
59
+ --border-soft: #2b2b2b;
60
+ --accent: #f0934a;
61
+ --accent-hover: #e07f30;
62
+ --accent-text: #f0a25a;
63
+ --accent-border: #4d4d4d;
64
+ --on-accent: #1e1e1e;
65
+ --danger: #f87171;
66
+ --danger-hover: #ef4444;
67
+ --danger-border: #5e3a3a;
68
+ --danger-wash: #2c2222;
69
+ --ok: #4ade80;
70
+ --warn: #f59e0b;
71
+ --node-label: #d0d0d0;
72
+ --node-id: #8c8c8c;
73
+ --edge: #4a4a4a;
74
+ --edge-dep: #8478a0;
75
+ --float: rgba(37, 37, 38, .95);
76
+ --scrim: rgba(0, 0, 0, .6);
77
+ --overlay: rgba(0, 0, 0, .6);
78
+ --shadow-strong: rgba(0, 0, 0, .5);
79
+ --shadow-soft: rgba(0, 0, 0, .4);
80
+ }
81
+ @media (prefers-color-scheme: dark) {
82
+ :root:not([data-theme="light"]):not([data-theme="dark"]) {
83
+ color-scheme: dark;
84
+ --bg: #1e1e1e;
85
+ --surface: #252526;
86
+ --surface-alt: #2d2d2e;
87
+ --wash: #2f2f30;
88
+ --wash-soft: #29292a;
89
+ --code-bg: #1a1a1a;
90
+ --code-text: #d4d4d4;
91
+ --code-inline: #333334;
92
+ --text: #d4d4d4;
93
+ --text-2: #bdbdbd;
94
+ --text-3: #9d9d9d;
95
+ --text-faint: #6e6e6e;
96
+ --border: #3c3c3c;
97
+ --border-strong: #4d4d4d;
98
+ --border-soft: #2b2b2b;
99
+ --accent: #f0934a;
100
+ --accent-hover: #e07f30;
101
+ --accent-text: #f0a25a;
102
+ --accent-border: #4d4d4d;
103
+ --on-accent: #1e1e1e;
104
+ --danger: #f87171;
105
+ --danger-hover: #ef4444;
106
+ --danger-border: #5e3a3a;
107
+ --danger-wash: #2c2222;
108
+ --ok: #4ade80;
109
+ --warn: #f59e0b;
110
+ --node-label: #d0d0d0;
111
+ --node-id: #8c8c8c;
112
+ --edge: #4a4a4a;
113
+ --edge-dep: #8478a0;
114
+ --float: rgba(37, 37, 38, .95);
115
+ --scrim: rgba(0, 0, 0, .6);
116
+ --overlay: rgba(0, 0, 0, .6);
117
+ --shadow-strong: rgba(0, 0, 0, .5);
118
+ --shadow-soft: rgba(0, 0, 0, .4);
119
+ }
120
+ }
121
+
122
+ * { box-sizing: border-box; margin: 0; }
123
+ html, body { height: 100%; font-family: system-ui, -apple-system, sans-serif; }
124
+ body { display: flex; flex-direction: column; background: var(--bg); color: var(--text); }
125
+
126
+ #toolbar {
127
+ display: flex; align-items: center; gap: 8px;
128
+ padding: 8px 14px; background: var(--surface); border-bottom: 1px solid var(--border);
129
+ }
130
+ #toolbar h1 { font-size: 16px; margin-right: 8px; color: var(--accent); }
131
+ #toolbar button, #toolbar select {
132
+ padding: 5px 10px; border: 1px solid var(--border-strong); border-radius: 6px;
133
+ background: var(--surface); color: var(--text); cursor: pointer; font-size: 13px;
134
+ }
135
+ #toolbar button:hover:not(:disabled) { background: var(--wash); border-color: var(--accent); }
136
+ #toolbar button:disabled, #toolbar select:disabled { opacity: .4; cursor: default; }
137
+ #sel-info { font-size: 12px; color: var(--text-3); margin-left: auto; }
138
+ .conn { font-size: 10px; color: var(--ok); }
139
+ .conn.off { color: var(--danger); }
140
+
141
+ /* 사용량 위젯 (5시간/주간 구독 한도) */
142
+ .usage { display: flex; align-items: center; gap: 8px; }
143
+ .usage .usage-cap { font-size: 12px; opacity: .6; }
144
+ .usage-item {
145
+ display: inline-flex; align-items: center; gap: 5px;
146
+ font-size: 11px; color: var(--text-3); cursor: default;
147
+ }
148
+ .usage-item .ulabel { color: var(--text-faint); }
149
+ .usage-item .ubar {
150
+ width: 46px; height: 6px; border-radius: 3px;
151
+ background: var(--border-soft); overflow: hidden;
152
+ }
153
+ .usage-item .ubar i { display: block; height: 100%; background: var(--ok); border-radius: 3px; }
154
+ .usage-item .upct { min-width: 30px; text-align: right; font-variant-numeric: tabular-nums; color: var(--text-2); }
155
+ .usage-item.warn .ubar i { background: var(--warn); }
156
+ .usage-item.crit .ubar i { background: var(--danger); }
157
+ .usage-item.crit .upct { color: var(--danger); font-weight: 600; }
158
+
159
+ main { flex: 1; display: flex; min-height: 0; }
160
+ .pane { background: var(--surface); display: flex; flex-direction: column; }
161
+ #explorer { width: var(--exp-w, 345px); flex: none; border-right: 1px solid var(--border); }
162
+ #chat { border-left: 1px solid var(--border); }
163
+ .pane-title { padding: 8px 12px; font-size: 12px; font-weight: 600; color: var(--text-faint); border-bottom: 1px solid var(--border-soft); }
164
+ .pane-empty { padding: 16px 12px; font-size: 12px; color: var(--text-faint); }
165
+
166
+ #canvas-wrap { flex: 1; position: relative; min-width: 0; }
167
+ #canvas { width: 100%; height: 100%; display: block; cursor: grab; touch-action: none; }
168
+ #canvas.panning { cursor: grabbing; }
169
+
170
+ /* 줌 컨트롤 (캔버스 우상단 플로팅) */
171
+ #zoom-ctrl {
172
+ position: absolute; top: 10px; right: 12px; display: flex; gap: 3px;
173
+ background: var(--float); border: 1px solid var(--border); border-radius: 9px;
174
+ padding: 3px; box-shadow: 0 1px 5px var(--shadow-soft);
175
+ }
176
+ #zoom-ctrl button {
177
+ width: 26px; height: 26px; padding: 0; border: none; border-radius: 6px;
178
+ background: transparent; cursor: pointer; color: var(--text-3); font-size: 15px; line-height: 1;
179
+ display: flex; align-items: center; justify-content: center;
180
+ }
181
+ #zoom-ctrl button:hover { background: var(--wash); color: var(--accent); }
182
+
183
+ /* 루트 탭 바 (캔버스 좌상단 플로팅) — S7 DES-CORE-022 */
184
+ #root-tabs {
185
+ position: absolute; top: 10px; left: 12px; z-index: 2;
186
+ display: flex; gap: 3px; max-width: calc(100% - 200px); overflow: hidden;
187
+ background: var(--float); border: 1px solid var(--border); border-radius: 9px;
188
+ padding: 3px; box-shadow: 0 1px 5px var(--shadow-soft);
189
+ }
190
+ #root-tabs[hidden] { display: none; }
191
+ .root-tab {
192
+ padding: 4px 9px; border: none; border-radius: 6px; background: transparent;
193
+ cursor: pointer; color: var(--text-3); font-size: 12px; line-height: 1.2; white-space: nowrap;
194
+ max-width: 140px; overflow: hidden; text-overflow: ellipsis;
195
+ }
196
+ .root-tab:hover { background: var(--wash); color: var(--accent); }
197
+ .root-tab.active { background: var(--wash); color: var(--accent); font-weight: 600; }
198
+ .root-tab.more { color: var(--text-faint); }
199
+
200
+ /* 아카이브 노드 흐리게 — S7 DES-CORE-021 (그리기 단계에서만, 좌표 불변) */
201
+ .node.dimmed { opacity: .38; }
202
+ .node.dimmed.selected { opacity: .72; }
203
+
204
+ /* 툴바 토글 버튼 눌림 상태 (아카이브 표시) */
205
+ #toolbar button.on { background: var(--wash); border-color: var(--accent); color: var(--accent); }
206
+
207
+ /* 노드 */
208
+ .node { cursor: pointer; }
209
+ .node circle.body { stroke-width: 2; transition: stroke-width .1s; }
210
+ .node.selected circle.body { stroke: var(--accent); stroke-width: 3.5; }
211
+ .node text.icon { font-size: 20px; text-anchor: middle; dominant-baseline: central; pointer-events: none; }
212
+ .node text.label { font-size: 12px; text-anchor: middle; fill: var(--node-label); pointer-events: none; }
213
+ .node text.otid { font-size: 9px; text-anchor: middle; fill: var(--node-id); pointer-events: none; }
214
+
215
+ /* 엣지 */
216
+ .edge { fill: none; stroke: var(--edge); stroke-width: 1.5; }
217
+ .edge.dep { stroke-dasharray: 5 4; stroke: var(--edge-dep); }
218
+
219
+ /* 패널 너비 조절 핸들 (탐색기·대화창) */
220
+ #chat-resizer, #exp-resizer {
221
+ flex: 0 0 5px; cursor: col-resize; background: transparent;
222
+ border-left: 1px solid var(--border); transition: background .12s;
223
+ }
224
+ #chat-resizer:hover, #chat-resizer.dragging,
225
+ #exp-resizer:hover, #exp-resizer.dragging { background: var(--accent-border); }
226
+ body.resizing { cursor: col-resize; user-select: none; }
227
+
228
+ /* 대화 패널 */
229
+ #chat { width: var(--chat-w, 340px); flex: none; }
230
+ #chat-log { flex: 1; overflow-y: auto; padding: 10px; display: flex; flex-direction: column; gap: 8px; }
231
+ .msg { max-width: 92%; padding: 8px 10px; border-radius: 10px; font-size: 13px; line-height: 1.5; overflow-wrap: break-word; position: relative; }
232
+ .msg.user { align-self: flex-end; background: var(--wash); border: 1px solid var(--accent-border); }
233
+ .msg.assistant { align-self: flex-start; background: var(--surface-alt); border: 1px solid var(--border); }
234
+ .msg.streaming::after { content: '▍'; animation: blink 1s infinite; color: var(--accent); }
235
+ @keyframes blink { 50% { opacity: 0; } }
236
+ .msg pre { background: var(--code-bg); color: var(--code-text); padding: 8px; border-radius: 6px; overflow-x: auto; font-size: 12px; margin: 6px 0; }
237
+ .msg code { background: var(--code-inline); padding: 1px 4px; border-radius: 4px; font-size: 12px; }
238
+ .msg .tools { margin-top: 4px; font-size: 11px; color: var(--text-faint); }
239
+ .msg .cost { margin-top: 4px; font-size: 10px; color: var(--text-faint); text-align: right; }
240
+ .msg .err { color: var(--danger); }
241
+ /* 한 턴 묶음 — 처리 쉐브론 + 답변 버블. 내부는 좌측 정렬 컬럼. */
242
+ #chat-log .turn { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; width: 100%; }
243
+ /* GFM 블록 */
244
+ .msg p { margin: 4px 0; white-space: pre-wrap; }
245
+ .msg p:first-child { margin-top: 0; } .msg p:last-child { margin-bottom: 0; }
246
+ .msg h1, .msg h2, .msg h3, .msg h4, .msg h5, .msg h6 { font-weight: 700; margin: 8px 0 4px; line-height: 1.3; }
247
+ .msg h1 { font-size: 15px; } .msg h2 { font-size: 14px; } .msg h3, .msg h4, .msg h5, .msg h6 { font-size: 13px; }
248
+ .msg ul, .msg ol { margin: 4px 0; padding-left: 20px; }
249
+ .msg li { margin: 1px 0; }
250
+ .msg blockquote { border-left: 3px solid var(--border-strong); padding-left: 8px; margin: 4px 0; color: var(--text-3); }
251
+ .msg hr { border: none; border-top: 1px solid var(--border); margin: 8px 0; }
252
+ .msg table { border-collapse: collapse; margin: 6px 0; font-size: 12px; display: block; overflow-x: auto; max-width: 100%; }
253
+ .msg th, .msg td { border: 1px solid var(--border-strong); padding: 3px 7px; text-align: left; }
254
+ .msg th { background: var(--code-inline); font-weight: 600; }
255
+ .msg a { color: var(--accent-text); }
256
+ /* 처리 과정(중간 narration + 도구 + 생각) 쉐브론 — 기본 접힘 */
257
+ #chat-log .proc-steps { align-self: flex-start; max-width: 92%; font-size: 11px; }
258
+ #chat-log .proc-steps summary { cursor: pointer; color: var(--text-faint); list-style: none; display: inline-block;
259
+ padding: 2px 8px; border-radius: 8px; background: var(--wash-soft); border: 1px solid var(--border-soft); }
260
+ #chat-log .proc-steps summary::-webkit-details-marker { display: none; }
261
+ #chat-log .proc-steps summary::before { content: '▸ '; }
262
+ #chat-log .proc-steps[open] summary::before { content: '▾ '; }
263
+ #chat-log .proc-steps summary:hover { color: var(--accent); }
264
+ #chat-log .proc-steps .proc-body { color: var(--text-3); padding: 6px 8px; word-break: break-word; line-height: 1.45; }
265
+ /* time-ordered proc-step rows (retires the clustered .proc-think/.proc-tools) — S9 */
266
+ #chat-log .proc-steps .proc-step { margin: 3px 0; }
267
+ #chat-log .proc-steps .step-think { color: var(--text-3); font-style: italic; }
268
+ #chat-log .proc-steps .step-text { color: var(--text-3); }
269
+ #chat-log .proc-steps .proc-think > summary,
270
+ #chat-log .proc-steps .proc-tool-detail > summary { cursor: pointer; list-style: none; color: var(--text-3); }
271
+ #chat-log .proc-steps .proc-think > summary::-webkit-details-marker,
272
+ #chat-log .proc-steps .proc-tool-detail > summary::-webkit-details-marker { display: none; }
273
+ #chat-log .proc-steps .proc-think > div,
274
+ #chat-log .proc-steps .proc-tool-detail > div { margin-top: 3px; padding-left: 8px; white-space: pre-wrap; color: var(--text-faint); border-left: 2px solid var(--border-soft); }
275
+ #chat-log .proc-steps.live > summary { color: var(--accent-text); background: var(--wash); }
276
+
277
+ /* hover ⑂ fork + 📋 copy buttons on each answer segment — S9 */
278
+ #chat-log .msg.assistant { position: relative; }
279
+ #chat-log .msg.assistant .seg-fork,
280
+ #chat-log .msg.assistant .seg-copy {
281
+ position: absolute; top: 4px; opacity: 0; transition: opacity .12s;
282
+ border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: var(--accent-text);
283
+ font-size: 12px; line-height: 1; padding: 2px 5px; cursor: pointer;
284
+ }
285
+ #chat-log .msg.assistant .seg-fork { right: 4px; }
286
+ #chat-log .msg.assistant .seg-copy { right: 34px; }
287
+ #chat-log .msg.assistant:hover .seg-fork,
288
+ #chat-log .msg.assistant:hover .seg-copy { opacity: 1; }
289
+ #chat-log .msg.assistant .seg-fork:hover,
290
+ #chat-log .msg.assistant .seg-copy:hover { background: var(--wash); border-color: var(--accent-border); }
291
+
292
+ /* S10 — fixed headers (#chat-purpose / #chat-meta) */
293
+ #chat-purpose, #chat-meta { padding: 6px 12px; border-bottom: 1px solid var(--border-soft); font-size: 12px; background: var(--wash-soft); }
294
+ #chat-purpose[hidden], #chat-meta[hidden] { display: none; }
295
+ .purpose-head { display: flex; align-items: center; gap: 6px; }
296
+ .purpose-label { font-weight: 600; color: var(--accent-text); }
297
+ .purpose-toggle { margin-left: auto; border: none; background: transparent; cursor: pointer; color: var(--text-faint); font-size: 12px; }
298
+ .purpose-text { color: var(--text-3); max-height: 2.8em; overflow: hidden; line-height: 1.4; }
299
+ .purpose-text.open { max-height: none; }
300
+ .purpose-docs { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; margin-top: 5px; }
301
+ .purpose-docs-label { color: var(--text-faint); }
302
+ .purpose-doc { border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: var(--accent-text); font-size: 11px; padding: 2px 7px; cursor: pointer; }
303
+ .purpose-doc:hover { background: var(--wash); border-color: var(--accent-border); }
304
+ .meta-head { display: flex; gap: 8px; color: var(--text-3); }
305
+ .meta-status { font-weight: 600; color: var(--text-2); }
306
+ .act-log { margin-top: 4px; }
307
+ .act-log summary { cursor: pointer; color: var(--text-faint); }
308
+ .act-list { margin-top: 4px; display: flex; flex-direction: column; gap: 4px; }
309
+ .act-row { display: flex; justify-content: space-between; gap: 8px; }
310
+ .act-req { color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
311
+ .act-sub { color: var(--text-faint); white-space: nowrap; }
312
+ .act-err { color: var(--danger); }
313
+ .act-run { color: var(--accent); }
314
+
315
+ /* S10 — notice line clickable -> goto source node */
316
+ #chat-log .notice-line.clickable { cursor: pointer; }
317
+ #chat-log .notice-line.clickable:hover { color: var(--accent-text); }
318
+
319
+ /* S10 — fork-proposal + permission cards */
320
+ #chat-log .fork-card, #chat-log .perm-card {
321
+ align-self: stretch; border: 1px solid var(--accent-border); border-radius: 10px; background: var(--wash-soft);
322
+ padding: 10px 12px; margin: 4px 0; font-size: 12.5px; display: flex; flex-direction: column; gap: 7px;
323
+ }
324
+ .fork-head, .perm-head { font-weight: 600; color: var(--accent-text); }
325
+ .fork-n { font-weight: 400; color: var(--text-faint); font-size: 11px; }
326
+ .fork-ctx { color: var(--text-3); font-size: 11.5px; }
327
+ .fork-item { display: grid; grid-template-columns: auto 1fr; gap: 4px 7px; align-items: center; }
328
+ .fork-item .fork-title { grid-column: 2; border: 1px solid var(--border-strong); border-radius: 6px; padding: 4px 7px; font: inherit; font-size: 12px; background: var(--surface); color: var(--text); }
329
+ .fork-item .fork-sum { grid-column: 2; color: var(--text-faint); font-size: 11px; }
330
+ .fork-actions, .perm-actions { display: flex; gap: 6px; justify-content: flex-end; }
331
+ .fork-actions button, .perm-actions button { border: 1px solid var(--border-strong); border-radius: 7px; background: var(--surface); color: var(--text); padding: 5px 11px; cursor: pointer; font-size: 12px; }
332
+ .fork-go, .perm-allow { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
333
+ .fork-go:hover, .perm-allow:hover { background: var(--accent-hover); }
334
+ .perm-deny:hover, .fork-ignore:hover, .perm-always:hover { background: var(--wash-soft); }
335
+ .perm-input { background: var(--surface); border: 1px solid var(--border-soft); border-radius: 6px; padding: 6px 8px; font-size: 11px; white-space: pre-wrap; word-break: break-all; max-height: 120px; overflow: auto; color: var(--text-2); }
336
+ .perm-reason { color: var(--text-faint); font-size: 11.5px; }
337
+ #chat-form { display: flex; gap: 6px; padding: 10px; border-top: 1px solid var(--border-soft); flex-direction: column; position: relative; }
338
+
339
+ /* S11 — slash-command autocomplete menu (floats above the textarea) */
340
+ .slash-menu {
341
+ position: absolute; bottom: calc(100% + 4px); left: 10px; right: 10px; z-index: 1100;
342
+ max-height: 260px; overflow-y: auto; padding: 4px;
343
+ background: var(--surface); border: 1px solid var(--border); border-radius: 9px; box-shadow: 0 6px 24px var(--shadow-strong);
344
+ }
345
+ .slash-menu[hidden] { display: none; }
346
+ .slash-row { display: flex; align-items: baseline; gap: 8px; padding: 6px 9px; border-radius: 6px; cursor: pointer; font-size: 12.5px; }
347
+ .slash-row.sel { background: var(--wash); }
348
+ .slash-name { color: var(--accent-text); font-weight: 600; white-space: nowrap; }
349
+ .slash-arg { color: var(--text-faint); font-size: 11px; white-space: nowrap; }
350
+ .slash-desc { color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-left: auto; }
351
+
352
+ /* S12 — attachment chip strip */
353
+ #chat-att { display: flex; flex-wrap: wrap; gap: 6px; padding: 6px 10px 0; }
354
+ #chat-att[hidden] { display: none; }
355
+ .att-chip { display: inline-flex; align-items: center; gap: 5px; padding: 3px 6px; border: 1px solid var(--border); border-radius: 7px; background: var(--surface); font-size: 11px; max-width: 180px; }
356
+ .att-chip img { width: 24px; height: 24px; object-fit: cover; border-radius: 4px; }
357
+ .att-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-3); }
358
+ .att-x { border: none; background: transparent; cursor: pointer; color: var(--text-faint); font-size: 11px; padding: 0 2px; }
359
+ .att-x:hover { color: var(--danger); }
360
+
361
+ /* S1 (P2) — server folder picker modal */
362
+ .dp-overlay { position: fixed; inset: 0; z-index: 1200; display: flex; align-items: center; justify-content: center; background: var(--overlay); padding: 16px; }
363
+ .dp-box { width: min(560px, 94vw); max-height: 84vh; display: flex; flex-direction: column; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 12px 40px var(--shadow-strong); overflow: hidden; }
364
+ .dp-head { display: flex; align-items: center; justify-content: space-between; padding: 12px 14px; border-bottom: 1px solid var(--border-soft); font-weight: 600; }
365
+ .dp-x { border: none; background: transparent; cursor: pointer; color: var(--text-faint); font-size: 15px; }
366
+ .dp-x:hover { color: var(--accent); }
367
+ .dp-path { padding: 8px 14px; font-size: 12px; color: var(--text-3); word-break: break-all; font-family: ui-monospace, monospace; background: var(--bg); }
368
+ .dp-drives { display: flex; flex-wrap: wrap; gap: 5px; padding: 6px 14px 0; }
369
+ .dp-drive { border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface); color: var(--text); cursor: pointer; font-size: 11px; padding: 3px 8px; }
370
+ .dp-drive:hover { background: var(--wash); border-color: var(--accent); }
371
+ .dp-list { flex: 1; overflow-y: auto; padding: 6px 8px; min-height: 120px; }
372
+ .dp-item { display: flex; gap: 7px; align-items: center; padding: 6px 9px; border-radius: 6px; cursor: pointer; font-size: 13px; color: var(--text-2); }
373
+ .dp-item:hover { background: var(--wash); color: var(--accent); }
374
+ .dp-up { color: var(--text-faint); }
375
+ .dp-empty { padding: 10px; color: var(--text-faint); font-size: 12px; }
376
+ .dp-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--border-soft); }
377
+ .dp-foot button { padding: 6px 14px; border-radius: 7px; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); cursor: pointer; font-size: 13px; }
378
+ .dp-cancel:hover { background: var(--wash-soft); }
379
+ .dp-ok { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
380
+ .dp-ok:hover:not(:disabled) { background: var(--accent-hover); }
381
+ .dp-ok:disabled { opacity: .5; cursor: default; }
382
+
383
+ /* S12/S13 — chat bar: attach button + global selectors */
384
+ #chat-bar #chat-attach { border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface); color: var(--text); cursor: pointer; padding: 4px 7px; font-size: 13px; }
385
+ #chat-bar #chat-attach:hover { background: var(--wash); border-color: var(--accent); }
386
+ #chat-bar select { border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface); font-size: 11px; padding: 3px 4px; color: var(--text-2); max-width: 96px; }
387
+ #chat-bar select:focus { outline: none; border-color: var(--accent); }
388
+ #chat-input {
389
+ width: 100%; box-sizing: border-box; resize: none; border: 1px solid var(--border-strong); border-radius: 8px;
390
+ padding: 8px; font-size: 13px; font-family: inherit; line-height: 1.45; background: var(--surface); color: var(--text);
391
+ min-height: calc(1.45em * 2 + 18px);
392
+ max-height: calc(1.45em * 15 + 18px);
393
+ overflow-y: auto;
394
+ }
395
+ #chat-input:focus { outline: none; border-color: var(--accent); }
396
+ #chat-bar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; row-gap: 6px; }
397
+ .bar-space { flex: 1; min-width: 0; }
398
+ #chat-stop { border: 1px solid var(--danger); border-radius: 8px; background: var(--surface); color: var(--danger); padding: 4px 12px; cursor: pointer; font-size: 13px; }
399
+ #chat-stop:hover { background: var(--danger-wash); }
400
+ #chat-send { border: none; border-radius: 8px; background: var(--accent); color: var(--on-accent); padding: 4px 14px; cursor: pointer; font-size: 13px; flex-shrink: 0; }
401
+ #chat-send:disabled { opacity: .5; cursor: default; }
402
+
403
+ /* 탐색기 — 작업 폴더 바 */
404
+ .ws-bar { display: flex; gap: 4px; padding: 8px 8px 6px; border-bottom: 1px solid var(--border-soft); }
405
+ .ws-bar #ws-select { flex: 1; min-width: 0; font-size: 12px; padding: 4px 6px; border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface); color: var(--text); cursor: pointer; }
406
+ .ws-bar #ws-select:focus { outline: none; border-color: var(--accent); }
407
+ .ws-bar button { border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface); color: var(--text); cursor: pointer; font-size: 12px; padding: 0 7px; }
408
+ .ws-bar button:hover { background: var(--wash); border-color: var(--accent); }
409
+
410
+ /* 선택한 프로젝트 목록 (선택창과 탐색기 사이) */
411
+ #ws-list { max-height: 30vh; overflow-y: auto; padding: 4px 8px 6px; border-bottom: 1px solid var(--border-soft); }
412
+ .ws-item { display: flex; align-items: center; justify-content: space-between; gap: 4px; padding: 3px 6px; border-radius: 6px; font-size: 12px; cursor: pointer; }
413
+ .ws-item:hover { background: var(--surface-alt); }
414
+ .ws-item.active { background: var(--wash); border: 1px solid var(--accent-border); padding: 2px 5px; }
415
+ .ws-item .ws-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
416
+ .ws-item.active .ws-name { font-weight: 600; color: var(--accent-text); }
417
+ .ws-item .ws-rm { visibility: hidden; border: none; background: none; cursor: pointer; font-size: 11px; padding: 0 2px; border-radius: 4px; }
418
+ .ws-item:hover .ws-rm { visibility: visible; }
419
+ .ws-item .ws-rm:hover { background: var(--danger-wash); }
420
+ .ws-empty { padding: 4px 6px; font-size: 12px; color: var(--text-faint); }
421
+
422
+ /* 검색 (파일·노드 — SCR-INSIGHT-006) */
423
+ .exp-search-bar { padding: 6px 8px; border-bottom: 1px solid var(--border-soft); }
424
+ .exp-search-bar #exp-search { width: 100%; box-sizing: border-box; font-size: 12px; padding: 4px 8px;
425
+ border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface); color: var(--text); }
426
+ .exp-search-bar #exp-search:focus { outline: none; border-color: var(--accent); }
427
+ .srch-group { font-size: 10px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-faint);
428
+ padding: 8px 4px 3px; font-weight: 600; }
429
+ .srch-hit { display: flex; align-items: baseline; gap: 6px; padding: 3px 4px; border-radius: 4px; cursor: pointer; }
430
+ .srch-hit:hover { background: var(--surface-alt); }
431
+ .srch-hit.disabled { cursor: default; opacity: .55; }
432
+ .srch-hit.disabled:hover { background: none; }
433
+ .srch-hit .srch-ic { flex: none; width: 14px; text-align: center; color: var(--text-faint); }
434
+ .srch-hit .srch-name { flex: none; max-width: 55%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
435
+ .srch-hit .srch-sub { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
436
+ font-size: 11px; color: var(--text-faint); }
437
+
438
+ /* 탐색기 */
439
+ #exp-tree { flex: 1; overflow-y: auto; padding: 6px 8px; font-size: 13px; }
440
+ .exp-footer { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px;
441
+ padding: 6px 12px; font-size: 11px; color: var(--text-faint); border-top: 1px solid var(--border-soft); }
442
+ .exp-footer .app-ver { font-variant-numeric: tabular-nums; }
443
+ .exp-footer .copyright a { color: inherit; text-decoration: none; }
444
+ .exp-footer .copyright a:hover { color: var(--accent); text-decoration: underline; }
445
+ #exp-tree details { margin-left: 0; }
446
+ #exp-tree details > details, #exp-tree details > .exp-file { margin-left: 14px; }
447
+ #exp-tree summary { cursor: pointer; padding: 2px 4px; border-radius: 4px; list-style: none; }
448
+ #exp-tree summary:hover { background: var(--surface-alt); }
449
+ .exp-file { display: flex; align-items: center; justify-content: space-between; padding: 2px 4px; border-radius: 4px; }
450
+ .exp-file:hover { background: var(--surface-alt); }
451
+ .exp-file .fname { cursor: pointer; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
452
+ .exp-file .flink { visibility: hidden; border: none; background: none; cursor: pointer; font-size: 11px; }
453
+ .exp-file .flock { font-size: 10px; color: var(--warn); background: var(--wash-soft); border-radius: 5px; padding: 0 4px; margin-left: 4px; cursor: pointer; }
454
+ .exp-file .flock:hover { color: var(--danger); }
455
+ #exp-root { color: var(--accent-text); font-weight: 400; }
456
+
457
+ /* 탐색기 다중 폴더 */
458
+ .exp-root-group { margin-bottom: 6px; border: 1px solid var(--border-soft); border-radius: 8px; overflow: hidden; background: var(--surface); }
459
+ .exp-folder-head { font-size: 12px; font-weight: 600; color: var(--text-2); padding: 7px 8px; display: flex; gap: 5px; align-items: center;
460
+ background: var(--surface-alt); border-bottom: 1px solid var(--border-soft); position: sticky; top: 0; z-index: 1; cursor: pointer; }
461
+ .exp-folder-head.collapsed { border-bottom: none; }
462
+ .erh-tw { font-size: 9px; color: var(--text-faint); width: 12px; }
463
+ .erh-name { cursor: pointer; }
464
+ .erh-spacer { flex: 1; }
465
+ .erh-btn { border: none; background: none; cursor: pointer; font-size: 13px; color: var(--text-faint); padding: 0 2px; }
466
+ .erh-btn:hover { color: var(--accent); }
467
+ .exp-root-body { padding: 4px 6px; }
468
+ .fmode { font-size: 10px; border-radius: 5px; padding: 0 5px; font-weight: 400; }
469
+ .fmode.ro { background: #fef3c7; color: #b45309; }
470
+ .fmode.rw { background: #dcfce7; color: #166534; }
471
+ .fprimary { font-size: 10px; color: var(--text-faint); font-weight: 400; }
472
+
473
+ /* 프로젝트 설정 모달 */
474
+ #pj-modal { position: fixed; inset: 0; background: var(--scrim); display: flex; align-items: center; justify-content: center; z-index: 20; }
475
+ .pj-box { width: min(560px, 92vw); max-height: 84vh; overflow-y: auto; background: var(--surface); color: var(--text); border-radius: 12px; padding: 16px 18px; box-shadow: 0 12px 40px var(--shadow-strong); display: flex; flex-direction: column; gap: 8px; }
476
+ .pj-head { display: flex; justify-content: space-between; align-items: center; }
477
+ .pj-head button { border: none; background: none; color: var(--text); cursor: pointer; }
478
+ .pj-box label { font-size: 12px; color: var(--text-3); margin-top: 6px; display: flex; justify-content: space-between; align-items: center; }
479
+ .pj-box label button { border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface); color: var(--text); cursor: pointer; font-size: 11px; padding: 2px 8px; }
480
+ .pj-box textarea { border: 1px solid var(--border-strong); border-radius: 8px; padding: 8px; font-size: 13px; font-family: inherit; resize: vertical; background: var(--surface); color: var(--text); }
481
+ .pj-box label .lbl-sub { font-weight: 400; color: var(--text-faint); margin-right: auto; margin-left: 4px; }
482
+ .pj-folder, .pj-ctx { display: flex; align-items: center; gap: 8px; font-size: 12.5px; padding: 4px 2px; }
483
+ .pj-folder span, .pj-ctx span { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
484
+ .pj-folder button, .pj-ctx button { border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface); color: var(--text); cursor: pointer; font-size: 11px; padding: 2px 7px; }
485
+ .pj-actions { display: flex; justify-content: flex-end; margin-top: 8px; }
486
+ #pj-save { border: none; background: var(--accent); color: var(--on-accent); border-radius: 8px; padding: 6px 18px; cursor: pointer; }
487
+ .pj-docidx { max-height: 160px; overflow-y: auto; border: 1px solid var(--border-soft); border-radius: 8px; padding: 2px 6px; }
488
+ .pj-doc { display: flex; align-items: center; gap: 8px; font-size: 12.5px; padding: 4px 2px; cursor: pointer; border-radius: 6px; }
489
+ .pj-doc:hover { background: var(--wash); }
490
+ .pj-doc .pj-doc-path { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--accent-text); }
491
+ .pj-doc .pj-doc-node { color: var(--text-faint); font-size: 11px; white-space: nowrap; }
492
+
493
+ /* 기본 지침 열람 모달 (읽기 전용) */
494
+ .guide-modal { position: fixed; inset: 0; background: var(--scrim); display: flex; align-items: center; justify-content: center; z-index: 22; }
495
+ .guide-box .guide-body { font-size: 13px; line-height: 1.6; color: var(--text-2); }
496
+ .guide-box .guide-body :is(h1, h2, h3) { font-size: 14px; margin: 8px 0 4px; }
497
+ .guide-box .guide-body ul, .guide-box .guide-body ol { margin: 4px 0; padding-left: 18px; }
498
+ .guide-box .guide-body li { margin: 4px 0; }
499
+ .guide-box .guide-body p { margin: 4px 0; }
500
+ .guide-box .guide-body code { background: var(--code-inline); padding: 1px 4px; border-radius: 4px; font-size: 12px; }
501
+ .guide-box .guide-note { margin-top: 8px; font-size: 11.5px; color: var(--text-faint); border-top: 1px solid var(--border-soft); padding-top: 8px; }
502
+
503
+ /* hidden 속성이 display 지정 CSS에 덮이지 않도록 */
504
+ [hidden] { display: none !important; }
505
+
506
+ .candidate-ring { fill: none; stroke: var(--accent); stroke-width: 2; stroke-dasharray: 6 5; animation: spin-dash 6s linear infinite; }
507
+ @keyframes spin-dash { to { stroke-dashoffset: -44; } }
508
+
509
+ /* 자식 완료 roll-up 알림 한 줄 */
510
+ #chat-log .notice-line { align-self: stretch; font-size: 11.5px; color: var(--accent-text); background: var(--wash);
511
+ border: 1px solid var(--accent-border); border-radius: 8px; padding: 5px 9px; }
512
+ /* 환류(returnsTo) 결과 카드 — 자식 detour 완료 -> 부모가 1클릭으로 이어받음 (DES-COLLAB-017) */
513
+ #chat-log .return-card { align-self: stretch; border: 1px solid var(--accent-border); border-radius: 10px; background: var(--wash-soft);
514
+ padding: 10px 12px; margin: 4px 0; font-size: 12.5px; display: flex; flex-direction: column; gap: 7px; }
515
+ #chat-log .return-card .return-head { font-weight: 600; color: var(--accent-text); }
516
+ #chat-log .return-card .return-body { color: var(--text-2); }
517
+ #chat-log .return-card .return-from { color: var(--accent-text); }
518
+ #chat-log .return-card .return-actions { display: flex; gap: 6px; justify-content: flex-end; }
519
+ #chat-log .return-card .return-actions button { border: 1px solid var(--border-strong); border-radius: 7px; background: var(--surface); color: var(--text); padding: 5px 11px; cursor: pointer; font-size: 12px; }
520
+ #chat-log .return-card .return-go { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
521
+ #chat-log .return-card .return-go:hover { background: var(--accent-hover); }
522
+ #chat-log .return-card .return-later:hover { background: var(--wash); }
523
+ #chat-log .change-card .change-files { color: var(--text-faint); font-size: 11px; }
524
+ #chat-log .conflict-card { border-color: var(--danger-border); }
525
+ #chat-log .conflict-card .return-head { color: var(--danger); }
526
+ #chat-log .conflict-card .return-go { background: var(--danger); border-color: var(--danger); color: #fff; }
527
+ #chat-log .conflict-card .return-go:hover { background: var(--danger-hover); }
528
+ /* 재접속 시 진행 중 안내 */
529
+ #chat-log .busy-notice { align-self: center; font-size: 12px; color: var(--text-3); background: var(--surface-alt);
530
+ border: 1px dashed var(--border-strong); border-radius: 8px; padding: 6px 12px; }
531
+ /* done 후속 정리 등 시스템 보고 라인 — 대화 턴과 구분되는 표시 전용 */
532
+ #chat-log .sys-line { align-self: stretch; font-size: 11.5px; color: var(--text-2); background: var(--surface-alt);
533
+ border: 1px solid var(--border); border-radius: 8px; padding: 5px 9px; white-space: pre-wrap; }
534
+ /* 빈 턴(모델이 응답 없이 종료) 안내 + 다시 시도 */
535
+ #chat-log .msg.assistant.empty-turn { background: var(--wash-soft); border-style: dashed; border-color: var(--accent-border); }
536
+ #chat-log .msg.assistant.empty-turn .empty-note { font-size: 12.5px; color: var(--accent-text); }
537
+ #chat-log .empty-retry { align-self: flex-start; margin-top: 2px; }
538
+ #chat-log .empty-retry .retry-btn { border: 1px solid var(--accent-border); border-radius: 7px; background: var(--surface); color: var(--accent-text);
539
+ cursor: pointer; font-size: 12px; padding: 4px 12px; }
540
+ #chat-log .empty-retry .retry-btn:hover { background: var(--wash-soft); }
541
+ #chat-log .empty-retry .retry-btn:disabled { opacity: 0.5; cursor: default; }
542
+
543
+ /* AI 작업중 펄스 링 (레이더 핑) */
544
+ .node .busy-ring { fill: none; stroke: var(--ok); stroke-width: 2.5; transform-origin: center; transform-box: fill-box; animation: otBusyPing 1.6s ease-out infinite; }
545
+ @keyframes otBusyPing { 0% { transform: scale(1); opacity: .55; } 100% { transform: scale(1.85); opacity: 0; } }
546
+ /* 생성 중 노드 — 회색 shimmer */
547
+ .node.preparing circle.body { animation: otPrepShimmer 1.2s ease-in-out infinite; }
548
+ .node.preparing .glyph { animation: otPrepSpin 1.4s linear infinite; transform-origin: center; transform-box: fill-box; }
549
+ @keyframes otPrepShimmer { 0%, 100% { opacity: .55; } 50% { opacity: 1; } }
550
+ @keyframes otPrepSpin { to { transform: rotate(360deg); } }
551
+
552
+ .node .glyph { pointer-events: none; }
553
+
554
+ #btn-quit { border: 1px solid var(--danger-border); border-radius: 6px; background: var(--surface); color: var(--danger); cursor: pointer; font-size: 12px; padding: 4px 8px; }
555
+ #btn-quit:hover { background: var(--danger-wash); border-color: var(--danger); }
556
+
557
+ /* 토스트 */
558
+ #ui-toasts { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; gap: 8px; z-index: 50; }
559
+ .ui-toast { background: var(--code-bg); color: var(--code-text); padding: 10px 16px; border-radius: 9px; font-size: 13px; box-shadow: 0 4px 16px var(--shadow-strong); animation: uiToastIn .2s; }
560
+ .ui-toast.error { background: #b91c1c; }
561
+ .ui-toast.success { background: #15803d; }
562
+ .ui-toast.out { opacity: 0; transition: opacity .3s; }
563
+ @keyframes uiToastIn { from { opacity: 0; transform: translateY(8px); } }
564
+
565
+ /* 문서 뷰어 */
566
+ #viewer-body h1 { font-size: 20px; margin: 14px 0 8px; color: var(--accent-text); }
567
+
568
+ /* ---- ui.ts: modal + body-portal popover ---- */
569
+ .ui-overlay {
570
+ position: fixed; inset: 0; z-index: 1000; display: flex; align-items: center; justify-content: center;
571
+ background: var(--overlay); padding: 16px;
572
+ }
573
+ .ui-modal {
574
+ background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
575
+ box-shadow: 0 12px 40px var(--shadow-strong); display: flex; flex-direction: column;
576
+ max-height: 90vh; overflow: hidden; animation: uiModalIn .12s ease-out;
577
+ }
578
+ @keyframes uiModalIn { from { opacity: 0; transform: translateY(8px) scale(.98); } }
579
+ .ui-head { display: flex; align-items: center; padding: 12px 14px; border-bottom: 1px solid var(--border-soft); }
580
+ .ui-head b { font-size: 14px; color: var(--text); }
581
+ .ui-x { margin-left: auto; border: none; background: transparent; cursor: pointer; color: var(--text-faint); font-size: 15px; line-height: 1; padding: 2px 4px; }
582
+ .ui-x:hover { color: var(--accent); }
583
+ .ui-body { padding: 14px; overflow: auto; display: flex; flex-direction: column; gap: 12px; }
584
+ .ui-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--border-soft); }
585
+ .ui-foot button { padding: 6px 14px; border-radius: 7px; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); cursor: pointer; font-size: 13px; }
586
+ .ui-cancel:hover { background: var(--wash-soft); }
587
+ .ui-foot .ui-ok { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
588
+ .ui-foot .ui-ok:hover { background: var(--accent-hover); }
589
+ .ui-foot .ui-ok.danger { background: var(--danger); border-color: var(--danger); color: #fff; }
590
+ .ui-foot .ui-ok.danger:hover { background: var(--danger-hover); }
591
+ .ui-field { display: flex; flex-direction: column; gap: 5px; }
592
+ .ui-lbl { font-size: 12px; font-weight: 600; color: var(--text-2); }
593
+ /* inline copy-to-clipboard control inside the bug-report body label */
594
+ .ui-lbl .report-copy {
595
+ float: right; font: inherit; font-size: 11px; font-weight: 500; line-height: 1; padding: 2px 6px;
596
+ border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: var(--accent-text); cursor: pointer;
597
+ }
598
+ .ui-lbl .report-copy:hover { background: var(--wash); border-color: var(--accent-border); }
599
+ /* inline image-attach control inside the bug-report images label (mirrors .report-copy) */
600
+ .ui-lbl .report-attach {
601
+ float: right; font: inherit; font-size: 11px; font-weight: 500; line-height: 1; padding: 2px 6px;
602
+ border: 1px solid var(--border); border-radius: 6px; background: var(--surface); color: var(--accent-text); cursor: pointer;
603
+ }
604
+ .ui-lbl .report-attach:hover { background: var(--wash); border-color: var(--accent-border); }
605
+ .report-imgs { display: flex; flex-wrap: wrap; gap: 6px; }
606
+ .ui-field input[type=text], .ui-field textarea, .ui-field select {
607
+ width: 100%; padding: 7px 9px; border: 1px solid var(--border-strong); border-radius: 7px; font: inherit; font-size: 13px; background: var(--surface); color: var(--text);
608
+ }
609
+ .ui-field textarea { resize: vertical; }
610
+ .ui-field input:focus, .ui-field textarea:focus, .ui-field select:focus { outline: none; border-color: var(--accent); }
611
+ .ui-hint { font-size: 11px; color: var(--text-faint); }
612
+ .ui-check { display: flex; align-items: center; gap: 6px; font-size: 13px; cursor: pointer; }
613
+ .ui-radios { display: flex; flex-direction: column; gap: 6px; }
614
+ .ui-radio { display: flex; gap: 8px; align-items: flex-start; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; cursor: pointer; }
615
+ .ui-radio:hover { background: var(--wash-soft); border-color: var(--accent-border); }
616
+ .ui-radio span { display: flex; flex-direction: column; gap: 2px; }
617
+ .ui-radio em { font-style: normal; font-size: 11px; color: var(--text-faint); }
618
+ .ui-msg { font-size: 13px; color: var(--text-2); line-height: 1.5; }
619
+
620
+ /* pairing modal (DES-NET-015) — "클라우드에 연결" */
621
+ .pair-code { font: 700 30px/1.2 ui-monospace, "SFMono-Regular", Menlo, monospace; letter-spacing: 4px; text-align: center; color: var(--text); background: var(--wash-soft); border: 1px solid var(--border-soft); border-radius: 10px; padding: 14px; user-select: all; }
622
+ .pair-approve { display: block; text-align: center; text-decoration: none; padding: 10px 14px; border-radius: 8px; background: var(--accent); border: 1px solid var(--accent); color: var(--on-accent); font-size: 14px; }
623
+ .pair-approve:hover { background: var(--accent-hover); }
624
+ .pair-url { font-size: 11px; color: var(--text-faint); word-break: break-all; }
625
+
626
+ /* connection settings modal */
627
+ .cs-row { display: flex; align-items: center; gap: 8px; }
628
+ .cs-path { flex: 1; font-size: 12px; color: var(--text-2); word-break: break-all; background: var(--wash-soft); border: 1px solid var(--border-soft); border-radius: 6px; padding: 6px 8px; }
629
+ .cs-row .cs-pick { padding: 6px 10px; border-radius: 6px; border: 1px solid var(--border-strong); background: var(--surface); color: var(--text); cursor: pointer; font-size: 12px; white-space: nowrap; }
630
+ .cs-row .cs-pick:hover { background: var(--wash-soft); }
631
+ .cs-adv summary { cursor: pointer; font-size: 12px; color: var(--text-2); padding: 4px 0; }
632
+
633
+ .ui-menu {
634
+ position: fixed; z-index: 1100; min-width: 168px; padding: 5px;
635
+ background: var(--surface); border: 1px solid var(--border); border-radius: 9px;
636
+ box-shadow: 0 8px 28px var(--shadow-strong); display: flex; flex-direction: column;
637
+ animation: uiMenuIn .1s ease-out;
638
+ }
639
+ @keyframes uiMenuIn { from { opacity: 0; transform: translateY(-4px); } }
640
+ .ui-menu-item {
641
+ display: flex; align-items: center; gap: 8px; width: 100%; text-align: left;
642
+ padding: 7px 10px; border: none; background: transparent; border-radius: 6px;
643
+ cursor: pointer; font: inherit; font-size: 13px; color: var(--text);
644
+ }
645
+ .ui-menu-item:hover:not(:disabled) { background: var(--wash); color: var(--accent); }
646
+ .ui-menu-item:disabled { opacity: .4; cursor: default; }
647
+ .ui-menu-item.danger { color: var(--danger); }
648
+ .ui-menu-item.danger:hover:not(:disabled) { background: var(--danger-wash); color: var(--danger-hover); }
649
+ .ui-menu-sep { height: 1px; margin: 4px 6px; background: var(--border-soft); }