@bhooai/nexus-graphql 2.0.11 → 2.0.13

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,1642 @@
1
+ /**
2
+ * GraphQL Explorer HTML — served from the backend at GET /graphql (Accept: text/html),
3
+ * GET /graphiql and GET /explorer.
4
+ *
5
+ * Zero build dependency: loads GraphiQL 3 + graphql 16 via CDN, wraps in a
6
+ * BhooAI Nexus branded chrome (glass-card, mesh, aurora tokens) so the
7
+ * playground feels native to the framework. Includes a tiny AI assistant panel
8
+ * that POSTs to /ai/chat (if the AI server is configured) with the schema SDL
9
+ * as context to generate queries from natural language.
10
+ *
11
+ * No auth guard — the explorer is public when introspection is enabled, just
12
+ * like POST /graphql. Disable with `graphql.explorer: false` in nexus.config.ts.
13
+ */
14
+ const AURORA_CSS = `.agent-shell { display:flex; flex-direction:column; height:100vh; height:100dvh; overflow:hidden; background:#040b18; isolation:isolate; }
15
+ .agent-shell::before { position:fixed; inset:0; z-index:0; pointer-events:none; content:""; opacity:.5;
16
+ background-image:linear-gradient(rgba(95,164,241,.05) 1px, transparent 1px), linear-gradient(90deg, rgba(95,164,241,.05) 1px, transparent 1px);
17
+ background-size:48px 48px; mask-image:linear-gradient(to bottom, black, transparent 78%); }
18
+ .agent-aurora { position:fixed; inset:0; z-index:0; overflow:hidden; pointer-events:none; }
19
+ .agent-aurora i { position:absolute; border-radius:50%; filter:blur(90px); opacity:.55; mix-blend-mode:screen; will-change:transform; }
20
+ .agent-aurora i:nth-child(1) { width:44rem; height:44rem; top:-12rem; left:-8rem; background:radial-gradient(circle at 35% 35%, rgba(84,183,255,.5), transparent 68%); animation:agent-drift-a 30s ease-in-out infinite alternate; }
21
+ .agent-aurora i:nth-child(2) { width:40rem; height:40rem; right:-10rem; bottom:-8rem; background:radial-gradient(circle at 60% 60%, rgba(159,123,255,.45), transparent 68%); animation:agent-drift-b 36s ease-in-out infinite alternate; }
22
+ .agent-aurora i:nth-child(3) { width:34rem; height:34rem; top:24%; left:46%; background:radial-gradient(circle at 50% 50%, rgba(243,110,184,.3), transparent 70%); animation:agent-drift-c 26s ease-in-out infinite alternate; }
23
+ @keyframes agent-drift-a { from { transform:translate3d(0,0,0) scale(1); } to { transform:translate3d(10rem,6rem,0) scale(1.18); } }
24
+ @keyframes agent-drift-b { from { transform:translate3d(0,0,0) scale(1.05); } to { transform:translate3d(-9rem,-5rem,0) scale(.9); } }
25
+ @keyframes agent-drift-c { from { transform:translate3d(0,0,0) scale(.95); } to { transform:translate3d(-7rem,9rem,0) scale(1.15); } }
26
+ .agent-shell > .agent-header,
27
+ .agent-shell > .agent-workspace,
28
+ .agent-shell > .agent-footer { position:relative; z-index:1; }
29
+
30
+ .agent-header { position:relative; z-index:20; flex:0 0 auto; background:linear-gradient(180deg, rgba(9,24,48,.9), rgba(4,14,29,.74)); border-bottom:1px solid rgba(112,168,228,.2); box-shadow:inset 0 1px 0 rgba(255,255,255,.05), 0 12px 40px rgba(2,8,20,.45); backdrop-filter:blur(26px); -webkit-backdrop-filter:blur(26px); }
31
+ .agent-header::after { position:absolute; left:24px; right:24px; bottom:-1px; height:1px; content:""; background:linear-gradient(90deg, transparent, rgba(84,183,255,.55), rgba(159,123,255,.5), transparent); pointer-events:none; }
32
+ .agent-header-inner { display:flex; align-items:center; gap:.7rem; row-gap:.5rem; flex-wrap:wrap; width:calc(100% - 48px); max-width:1400px; margin:0 auto; padding:.72rem 0; }
33
+ .agent-urlbar { display:flex; align-items:center; gap:.4rem; width:calc(100% - 48px); max-width:1400px; margin:0 auto; padding:.32rem 0 .5rem; }
34
+ .agent-urlbar-input { flex:1; min-width:0; display:flex; align-items:center; gap:.5rem; padding:.3rem .4rem .3rem .75rem; border:1px solid rgba(112,168,228,.22); border-radius:.6rem; background:rgba(4,14,29,.5); color:#9fb3d0; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.66rem; transition:border-color .14s, box-shadow .14s, background .14s; }
35
+ .agent-urlbar-input:focus-within { border-color:rgba(84,183,255,.55); box-shadow:0 0 0 2px rgba(84,183,255,.14); background:rgba(8,25,48,.6); }
36
+ .agent-urlbar-lock { flex:0 0 auto; color:#5ef0b3; font-size:.7rem; line-height:1; }
37
+ .agent-urlbar-field { flex:1; min-width:0; border:0; outline:none; color:#dcecff; background:transparent; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.68rem; caret-color:#54b7ff; }
38
+ .agent-urlbar-field::placeholder { color:#4b647f; }
39
+ .agent-urlbar-btn { display:grid; place-items:center; flex:0 0 auto; width:1.7rem; height:1.7rem; border:1px solid rgba(112,168,228,.24); border-radius:.5rem; color:#8fb8e4; background:rgba(84,183,255,.08); font-size:.78rem; line-height:1; cursor:pointer; transition:border-color .14s, color .14s, background .14s, transform .14s; }
40
+ .agent-urlbar-btn:hover { border-color:rgba(84,183,255,.55); color:#bfe9ff; background:rgba(84,183,255,.16); transform:translateY(-1px); }
41
+ .agent-urlbar-btn.copied { color:#6df0bb; border-color:rgba(52,211,153,.5); background:rgba(16,185,129,.14); }
42
+ .agent-urlbar-note { flex:0 0 auto; color:#4d6378; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; letter-spacing:.04em; }
43
+ .agent-header .agent-select-wrap { min-width:0; }
44
+ .agent-header .agent-select { min-width:0; text-overflow:ellipsis; }
45
+ .agent-back { display:inline-flex; align-items:center; gap:.45rem; padding:.5rem .8rem; border:1px solid rgba(84,183,255,.34); border-radius:.6rem; color:#9fd4ff; background:rgba(84,183,255,.1); font-size:.68rem; font-weight:700; letter-spacing:.02em; cursor:pointer; transition:border-color .15s, color .15s, background .15s, transform .15s; }
46
+ .agent-back:hover { border-color:rgba(84,183,255,.7); color:#fff; background:rgba(84,183,255,.2); transform:translateY(-1px); }
47
+ .agent-brand { display:inline-flex; align-items:center; gap:.75rem; margin:0; }
48
+ .agent-brand-badge { position:relative; display:grid; place-items:center; width:2.25rem; height:2.25rem; border-radius:.7rem; border:1px solid rgba(84,183,255,.42); background:linear-gradient(135deg, rgba(38,130,225,.32), rgba(90,67,183,.26)); box-shadow:0 0 20px rgba(58,149,255,.32), inset 0 1px rgba(255,255,255,.16); }
49
+ .agent-brand-badge::after { position:absolute; inset:0; border-radius:.7rem; content:""; background:radial-gradient(120% 120% at 50% 0%, rgba(120,200,255,.28), transparent 55%); }
50
+ .agent-brand-dot { position:relative; z-index:1; width:.52rem; height:.52rem; border-radius:50%; background:#5ef0b3; box-shadow:0 0 12px rgba(94,240,179,.95), 0 0 26px rgba(94,240,179,.45); }
51
+ .agent-brand-text { display:flex; flex-direction:column; gap:.12rem; line-height:1.1; }
52
+ .agent-brand-name { color:#f1f8ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.8rem; font-weight:800; letter-spacing:.16em; text-transform:uppercase; }
53
+ .agent-brand-name em { color:#63bdff; font-style:normal; text-shadow:0 0 18px rgba(84,183,255,.5); }
54
+ .agent-brand-sub { color:#4f6b8c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.55rem; letter-spacing:.14em; text-transform:uppercase; }
55
+ .agent-spacer { flex:1; }
56
+
57
+ /* ── Unified tooltip — single style for every [data-tip] element on the page ── */
58
+ [data-tip]{ position:relative; }
59
+ [data-tip]::after{ position:absolute; left:50%; bottom:calc(100% + 8px); transform:translateX(-50%) translateY(2px); z-index:120; padding:.35rem .6rem; border:1px solid rgba(112,168,228,.28); border-radius:.45rem; background:linear-gradient(160deg, rgba(10,28,55,.97), rgba(6,16,36,.98)); color:#dcecff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; font-weight:600; letter-spacing:.03em; line-height:1.4; white-space:nowrap; content:attr(data-tip); opacity:0; visibility:hidden; pointer-events:none; box-shadow:0 12px 32px rgba(0,0,0,.4), inset 0 1px rgba(255,255,255,.06); backdrop-filter:blur(18px) saturate(140%); -webkit-backdrop-filter:blur(18px) saturate(140%); transition:opacity .16s ease, transform .16s ease, visibility .16s; }
60
+ [data-tip]::before{ position:absolute; left:50%; bottom:calc(100% + 4px); transform:translateX(-50%) rotate(45deg); z-index:119; width:.5rem; height:.5rem; border-right:1px solid rgba(112,168,228,.28); border-bottom:1px solid rgba(112,168,228,.28); background:rgba(10,28,55,.98); content:""; opacity:0; visibility:hidden; pointer-events:none; transition:opacity .16s ease, visibility .16s; }
61
+ [data-tip]:hover::after, [data-tip]:hover::before,
62
+ [data-tip]:focus-visible::after, [data-tip]:focus-visible::before{ opacity:1; visibility:visible; transform:translateX(-50%) translateY(0); }
63
+ [data-tip]:hover::before, [data-tip]:focus-visible::before{ transform:translateX(-50%) rotate(45deg); }
64
+ /* Tooltip below for elements near the top edge (e.g. header buttons). */
65
+ [data-tip="bottom"]::after, [data-tip-bottom]::after{ bottom:auto; top:calc(100% + 8px); transform:translateX(-50%) translateY(-2px); }
66
+ [data-tip="bottom"]::before, [data-tip-bottom]::before{ bottom:auto; top:calc(100% + 4px); transform:translateX(-50%) rotate(45deg); }
67
+ [data-tip="bottom"]:hover::after, [data-tip-bottom]:hover::after{ transform:translateX(-50%) translateY(0); }
68
+ [data-theme="light"] [data-tip]::after{ background:linear-gradient(160deg, rgba(255,255,255,.98), rgba(238,245,255,.98)); color:#0b1220; border-color:rgba(60,110,180,.24); box-shadow:0 12px 32px rgba(20,50,100,.16), inset 0 1px rgba(255,255,255,.7); }
69
+ [data-theme="light"] [data-tip]::before{ background:#f2f7ff; border-color:rgba(60,110,180,.24); }
70
+ .agent-status { display:inline-flex; align-items:center; gap:.42rem; padding:.4rem .7rem; border:1px solid rgba(52,211,153,.32); border-radius:999px; background:rgba(16,185,129,.12); color:#7ee8bd; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.58rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase; }
71
+ .agent-status-dot { width:.42rem; height:.42rem; border-radius:50%; background:#5ef0b3; box-shadow:0 0 10px rgba(94,240,179,.9); animation:agent-pulse 2.4s ease-in-out infinite; }
72
+ .agent-select-wrap { display:inline-flex; align-items:center; gap:.42rem; padding:.22rem .3rem .22rem .6rem; border:1px solid rgba(112,168,228,.2); border-radius:.6rem; background:rgba(20,46,79,.3); transition:border-color .14s, background .14s, box-shadow .14s; }
73
+ .agent-select-wrap:focus-within { border-color:rgba(84,183,255,.55); background:rgba(20,46,79,.5); box-shadow:0 0 0 2px rgba(84,183,255,.15); }
74
+ .agent-select-label { color:#53708f; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.54rem; letter-spacing:.13em; text-transform:uppercase; white-space:nowrap; }
75
+ .agent-select { appearance:auto; -webkit-appearance:auto; padding:.42rem .55rem; border:0; border-radius:.4rem; outline:none; color:#dcecff; background:#0e1b33; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.64rem; font-weight:500; line-height:1.3; max-width:220px; min-height:1.9rem; cursor:pointer; color-scheme:dark; transition:background .14s, box-shadow .14s; }
76
+ .agent-select:hover { background:#132a4d; }
77
+ .agent-select:focus-visible { box-shadow:0 0 0 2px rgba(84,183,255,.35); }
78
+ .agent-select option { background:#0b1024; color:#e5f4ff; padding:.4rem .6rem; font-size:.64rem; }
79
+ .agent-select option:checked { background:#16325c; color:#fff; }
80
+ .agent-select optgroup { background:#0b1024; color:#63bdff; font-style:normal; font-size:.6rem; padding:.3rem .5rem; }
81
+ .agent-select optgroup option { background:#0b1024; color:#dcecff; font-style:normal; }
82
+ .agent-select optgroup option:hover { background:#1c3f6e; color:#fff; }
83
+ .agent-actions { display:inline-flex; align-items:center; gap:.45rem; }
84
+ .agent-clear { display:inline-flex; align-items:center; gap:.4rem; padding:.5rem .75rem; border:1px solid rgba(112,168,228,.24); border-radius:.6rem; color:#8fb8e4; background:rgba(84,183,255,.08); font-size:.66rem; font-weight:700; cursor:pointer; transition:border-color .15s, color .15s, background .15s, transform .15s; }
85
+ .agent-clear:hover { border-color:rgba(84,183,255,.55); color:#bfe9ff; background:rgba(84,183,255,.16); transform:translateY(-1px); }
86
+ .agent-clear.danger { border-color:rgba(251,113,133,.3); color:#f8c0cd; background:rgba(244,63,94,.1); }
87
+ .agent-clear.danger:hover { border-color:rgba(251,113,133,.55); color:#ffe4e6; background:rgba(244,63,94,.24); }
88
+ .agent-modes { display:inline-flex; gap:.25rem; padding:.25rem; border:1px solid rgba(112,168,228,.2); border-radius:.6rem; background:rgba(20,46,79,.28); }
89
+ .agent-mode { padding:.42rem .7rem; border:1px solid transparent; border-radius:.45rem; color:#7d94b2; background:transparent; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; font-weight:700; letter-spacing:.08em; cursor:pointer; transition:color .14s, background .14s, border-color .14s, box-shadow .14s; }
90
+ .agent-mode:hover { color:#dcecff; }
91
+ .agent-mode.mode-plan.active { color:#ffd479; background:linear-gradient(135deg, rgba(245,158,11,.28), rgba(180,83,9,.16)); border-color:rgba(255,196,107,.4); box-shadow:0 0 14px rgba(245,158,11,.2); }
92
+ .agent-mode.mode-auto.active { color:#6df0bb; background:linear-gradient(135deg, rgba(16,185,129,.26), rgba(6,95,70,.16)); border-color:rgba(52,211,153,.4); box-shadow:0 0 14px rgba(16,185,129,.2); }
93
+ .agent-mode.mode-build.active { color:#bfe9ff; background:linear-gradient(135deg, rgba(40,137,235,.34), rgba(76,83,212,.22)); border-color:rgba(84,183,255,.5); box-shadow:0 0 16px rgba(84,183,255,.24), inset 0 1px rgba(255,255,255,.08); }
94
+
95
+ .agent-workspace { flex:1 1 auto; min-height:0; min-width:0; display:flex; width:calc(100% - 48px); max-width:1400px; margin:0 auto; }
96
+ .agent-main { flex:1 1 auto; min-width:0; min-height:0; overflow-y:auto; overflow-x:hidden; padding:2rem 1.75rem 1.5rem; }
97
+ .agent-side { flex:0 0 360px; min-width:0; min-height:0; overflow-y:auto; overflow-x:hidden; border-left:1px solid rgba(112,168,228,.13); background:rgba(4,15,31,.4); padding:1.4rem 0 1.3rem 1.2rem; }
98
+ .agent-side-backdrop { position:fixed; inset:0; z-index:45; background:rgba(2,8,20,.5); backdrop-filter:blur(2px); -webkit-backdrop-filter:blur(2px); animation:agent-fade .2s ease both; }
99
+ @keyframes agent-fade { from { opacity:0; } to { opacity:1; } }
100
+ .agent-side-toggle { display:none; grid:place-items:center / none; place-items:center; width:2.1rem; height:2.1rem; padding:0; border:1px solid rgba(112,168,228,.24); border-radius:.6rem; color:#8fb8e4; background:rgba(84,183,255,.08); font-size:.85rem; line-height:1; cursor:pointer; transition:border-color .15s, color .15s, background .15s, transform .15s; }
101
+ .agent-side-toggle:hover { border-color:rgba(84,183,255,.55); color:#bfe9ff; background:rgba(84,183,255,.16); }
102
+ .agent-side-toggle.on { color:#9fe8ff; border-color:rgba(99,189,255,.6); background:rgba(40,137,235,.2); }
103
+ .agent-side-inner { display:flex; flex-direction:column; gap:1.1rem; }
104
+ .agent-side-head { display:flex; align-items:center; gap:.5rem; color:#6e8aaa; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; letter-spacing:.13em; }
105
+ .agent-side-title { font-weight:800; color:#63bdff; }
106
+ .agent-side-badge { padding:.08rem .45rem; border-radius:999px; color:#ffd479; background:rgba(245,158,11,.16); border:1px solid rgba(255,196,107,.3); font-size:.6rem; font-weight:800; }
107
+ .agent-side-batch { display:flex; gap:.4rem; }
108
+ .agent-side-batch-btn { padding:.34rem .6rem; border-radius:.45rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.58rem; font-weight:700; cursor:pointer; transition:filter .14s, transform .14s; }
109
+ .agent-side-batch-btn.allow { border:1px solid rgba(52,211,153,.4); color:#a7f3d0; background:linear-gradient(135deg, rgba(16,185,129,.55), rgba(5,150,105,.45)); }
110
+ .agent-side-batch-btn.deny { border:1px solid rgba(251,113,133,.4); color:#fecdd3; background:linear-gradient(135deg, rgba(244,63,94,.5), rgba(159,18,57,.42)); }
111
+ .agent-side-batch-btn:hover { filter:brightness(1.14); transform:translateY(-1px); }
112
+ .agent-side-section { display:flex; flex-direction:column; gap:.4rem; }
113
+ .agent-side-section-head { display:flex; align-items:center; gap:.4rem; }
114
+ .agent-side-section-title { color:#536c8c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; letter-spacing:.16em; text-transform:uppercase; }
115
+ .agent-side-section-badge { padding:.05rem .42rem; border-radius:999px; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; font-weight:800; line-height:1.4; border:1px solid; }
116
+ .agent-side-section-badge.approval { color:#ffd479; border-color:rgba(255,196,107,.32); background:rgba(245,158,11,.14); }
117
+ .agent-side-section-badge.running { color:#8ed6ff; border-color:rgba(84,183,255,.34); background:rgba(84,183,255,.12); }
118
+ .agent-side-section-badge.done { color:#6df0bb; border-color:rgba(52,211,153,.3); background:rgba(16,185,129,.12); }
119
+ .agent-side-section-badge.zero { opacity:.45; }
120
+ .agent-side-empty { margin:0; color:#45597a; font-size:.64rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; }
121
+ .agent-task-row { display:flex; align-items:center; gap:.45rem; padding:.4rem .55rem; border:1px solid rgba(112,168,228,.17); border-radius:.55rem; background:rgba(8,25,48,.6); box-shadow:inset 0 1px rgba(255,255,255,.04); cursor:pointer; transition:border-color .14s, background .14s, transform .14s; }
122
+ .agent-task-row:hover { border-color:rgba(84,183,255,.5); background:rgba(84,183,255,.1); transform:translateY(-1px); }
123
+ .agent-task-dot { width:.4rem; height:.4rem; flex:0 0 auto; border-radius:50%; background:#54b7ff; box-shadow:0 0 8px rgba(84,183,255,.7); }
124
+ .agent-task-dot.running { animation:agent-pulse 1s ease-in-out infinite; }
125
+ .agent-task-dot.ok, .agent-task-dot.approved { background:#5ef0b3; box-shadow:0 0 8px rgba(94,240,179,.8); }
126
+ .agent-task-dot.error, .agent-task-dot.denied { background:#fb7185; box-shadow:0 0 8px rgba(244,63,94,.7); }
127
+ .agent-task-dot.approval { background:#fbbf24; box-shadow:0 0 8px rgba(251,191,36,.7); animation:agent-pulse 1s ease-in-out infinite; }
128
+ .agent-task-summary { flex:1; min-width:0; color:#9fb3d0; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
129
+ .agent-task-actions { display:inline-flex; gap:.3rem; flex:0 0 auto; }
130
+ .agent-task-allow, .agent-task-deny { padding:.2rem .45rem; border-radius:.4rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; font-weight:700; cursor:pointer; transition:filter .14s; }
131
+ .agent-task-allow { border:1px solid rgba(52,211,153,.4); color:#a7f3d0; background:rgba(16,185,129,.22); }
132
+ .agent-task-deny { border:1px solid rgba(251,113,133,.4); color:#fecdd3; background:rgba(244,63,94,.22); }
133
+ .agent-task-allow:hover, .agent-task-deny:hover { filter:brightness(1.15); }
134
+ .agent-list { display:flex; flex-direction:column; gap:1rem; }
135
+ .agent-empty { margin:3.5rem 0 0; color:#64758e; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.72rem; line-height:1.9; text-align:center; }
136
+ .agent-empty b { color:#54b7ff; font-weight:600; }
137
+ .agent-hint { display:block; margin-top:.6rem; font-size:.6rem; color:#4c5d77; line-height:1.9; }
138
+ .agent-hint b { color:#7c8fa9; font-weight:600; }
139
+ .agent-approval-actions { display:flex; gap:.5rem; padding:.6rem .85rem; border-top:1px solid rgba(112,168,228,.12); }
140
+ .agent-allow { padding:.45rem .85rem; border:1px solid rgba(52,211,153,.4); border-radius:.5rem; color:#a7f3d0; background:linear-gradient(135deg, rgba(16,185,129,.6), rgba(5,150,105,.5)); font-size:.68rem; font-weight:700; cursor:pointer; transition:filter .15s, transform .15s; }
141
+ .agent-allow:hover { filter:brightness(1.12); transform:translateY(-1px); }
142
+ .agent-deny { padding:.45rem .85rem; border:1px solid rgba(251,113,133,.4); border-radius:.5rem; color:#fecdd3; background:linear-gradient(135deg, rgba(244,63,94,.55), rgba(159,18,57,.48)); font-size:.68rem; font-weight:700; cursor:pointer; transition:filter .15s, transform .15s; }
143
+ .agent-deny:hover { filter:brightness(1.12); transform:translateY(-1px); }
144
+
145
+ .agent-row-user { display:flex; justify-content:flex-end; }
146
+ .agent-row-agent { display:flex; justify-content:flex-start; }
147
+ .agent-msg { display:flex; flex-direction:column; gap:.35rem; max-width:88%; min-width:0; }
148
+ .agent-role { display:inline-flex; align-items:center; gap:.45rem; color:#6e8aaa; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.58rem; letter-spacing:.13em; text-transform:uppercase; }
149
+ .agent-role-user { justify-content:flex-end; }
150
+ .agent-role-agent { justify-content:flex-start; }
151
+ .agent-bubble { padding:.75rem .95rem; border:1px solid rgba(112,168,228,.2); border-radius:.8rem; color:#dcecff; background:linear-gradient(145deg, rgba(13,35,67,.5), rgba(10,17,40,.5)); font-size:.86rem; line-height:1.7; white-space:pre-wrap; overflow-wrap:anywhere; word-break:break-word; box-shadow:0 14px 42px rgba(0,0,0,.14); }
152
+ .agent-row-user .agent-bubble { border-color:rgba(84,183,255,.4); background:linear-gradient(145deg, rgba(22,70,122,.5), rgba(46,41,112,.42)); color:#eaf7ff; box-shadow:inset 0 1px rgba(255,255,255,.06), 0 14px 42px rgba(0,0,0,.16); }
153
+ .agent-msg pre { margin:0; }
154
+
155
+ .agent-tool { border:1px solid rgba(112,168,228,.2); border-radius:.8rem; background:rgba(8,25,48,.7); box-shadow:inset 0 1px rgba(255,255,255,.04), 0 14px 42px rgba(0,0,0,.16); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; overflow:hidden; backdrop-filter:blur(12px); -webkit-backdrop-filter:blur(12px); }
156
+ .agent-tool-head { display:flex; align-items:center; gap:.5rem; padding:.5rem .8rem; border-bottom:1px solid rgba(112,168,228,.12); color:#e2e8f0; font-size:.7rem; cursor:pointer; user-select:none; flex-wrap:wrap; }
157
+ .agent-tool-head .agent-tool-name { flex:0 0 auto; }
158
+ .agent-tool-head .agent-tool-summary { min-width:80px; }
159
+ .agent-tool-dot { width:.42rem; height:.42rem; flex:0 0 auto; border-radius:50%; background:#54b7ff; box-shadow:0 0 10px rgba(84,183,255,.8); animation:agent-pulse 1s ease-in-out infinite; }
160
+ @keyframes agent-pulse { 0%,100% { opacity:1; } 50% { opacity:.3; } }
161
+ .agent-tool.ok .agent-tool-dot { background:#5ef0b3; box-shadow:0 0 10px rgba(94,240,179,.8); animation:none; }
162
+ .agent-tool.err .agent-tool-dot { background:#fb7185; box-shadow:0 0 10px rgba(244,63,94,.8); animation:none; }
163
+ .agent-tool-name { color:#5cbaff; font-weight:700; flex:0 0 auto; }
164
+ .agent-tool.err .agent-tool-name { color:#fda4af; }
165
+ .agent-tool-summary { flex:1; min-width:0; color:#cfe3fb; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.66rem; letter-spacing:.01em; }
166
+ .agent-tool.err .agent-tool-summary { color:#fda4af; }
167
+ .agent-tool-status { flex:0 0 auto; padding:.12rem .42rem; border-radius:.35rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.52rem; font-weight:800; letter-spacing:.06em; text-transform:uppercase; border:1px solid transparent; }
168
+ .agent-tool-status.running { color:#8ed6ff; background:rgba(84,183,255,.12); border-color:rgba(84,183,255,.25); }
169
+ .agent-tool-status.ok { color:#6df0bb; background:rgba(16,185,129,.12); border-color:rgba(52,211,153,.22); }
170
+ .agent-tool-status.err { color:#fda4af; background:rgba(244,63,94,.12); border-color:rgba(244,63,94,.22); }
171
+ .agent-tool-badge { display:inline-flex; align-items:center; gap:.28rem; padding:.18rem .46rem; border-radius:.4rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.54rem; font-weight:800; letter-spacing:.07em; text-transform:uppercase; border:1px solid; flex:0 0 auto; line-height:1; }
172
+ .agent-tool-badge i { font-style:normal; font-size:.62rem; opacity:.9; }
173
+ .badge-read { color:#8ed6ff; border-color:rgba(84,183,255,.32); background:rgba(84,183,255,.14); }
174
+ .badge-write { color:#c4b5fd; border-color:rgba(139,92,246,.32); background:rgba(139,92,246,.13); }
175
+ .badge-edit { color:#6df0bb; border-color:rgba(52,211,153,.32); background:rgba(16,185,129,.14); }
176
+ .badge-bash { color:#fcd34d; border-color:rgba(245,158,11,.3); background:rgba(245,158,11,.13); }
177
+ .badge-grep { color:#f59e0b; border-color:rgba(245,158,11,.22); background:rgba(245,158,11,.08); }
178
+ .badge-glob { color:#93c5fd; border-color:rgba(96,165,250,.22); background:rgba(59,130,246,.08); }
179
+ .badge-list { color:#94a3b8; border-color:rgba(148,163,184,.22); background:rgba(148,163,184,.08); }
180
+ .badge-search { color:#67e8f9; border-color:rgba(6,182,212,.22); background:rgba(6,182,212,.08); }
181
+ .badge-generic { color:#9fd4ff; border-color:rgba(84,183,255,.22); background:rgba(84,183,255,.08); }
182
+
183
+ .agent-badge { display:flex; flex-direction:column; border:1px solid rgba(112,168,228,.22); border-radius:999px; background:linear-gradient(160deg, rgba(16,38,70,.5), rgba(8,20,42,.58)); box-shadow:inset 0 1px rgba(255,255,255,.05), 0 10px 26px rgba(0,0,0,.2); overflow:hidden; animation:agent-rise .28s cubic-bezier(.22,1,.36,1) both; transition:border-color .15s, border-radius .15s, transform .15s; }
184
+ .agent-badge:hover { border-color:rgba(84,183,255,.45); transform:translateY(-1px); }
185
+ .agent-badge-head { display:flex; align-items:center; gap:.5rem; padding:.42rem .8rem; color:#e2e8f0; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.7rem; cursor:pointer; user-select:none; }
186
+ .agent-badge-dot { width:.42rem; height:.42rem; flex:0 0 auto; border-radius:50%; background:#54b7ff; box-shadow:0 0 8px rgba(84,183,255,.7); animation:agent-pulse 1s ease-in-out infinite; }
187
+ .agent-badge.ok .agent-badge-dot { background:#5ef0b3; box-shadow:0 0 8px rgba(94,240,179,.7); animation:none; }
188
+ .agent-badge.err .agent-badge-dot { background:#fb7185; box-shadow:0 0 8px rgba(244,63,94,.7); animation:none; }
189
+ .agent-badge-name { color:#9fd4ff; font-weight:700; flex:0 0 auto; letter-spacing:.04em; }
190
+ .agent-badge.err .agent-badge-name { color:#fda4af; }
191
+ .agent-badge-param { flex:1; min-width:0; color:#9fb3d0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
192
+ .agent-badge.err .agent-badge-param { color:#fda4af; }
193
+ .agent-badge.expanded { border-radius:.85rem; }
194
+ .agent-toggle { display:inline-flex; align-items:center; justify-content:center; width:1.35rem; height:1.35rem; flex:0 0 auto; border:1px solid rgba(112,168,228,.22); border-radius:.4rem; color:#8fb8e4; background:transparent; font-family:inherit; font-size:.6rem; line-height:1; cursor:pointer; transition:border-color .14s, color .14s, background .14s; }
195
+ .agent-toggle:hover { border-color:rgba(84,183,255,.5); color:#bfe9ff; background:rgba(84,183,255,.1); }
196
+ .agent-tool-code { position:relative; border-top:1px solid rgba(112,168,228,.1); background:rgba(0,0,0,.3); }
197
+ .agent-tool-code .agent-tool-output { border-top:0; padding-top:2rem; }
198
+ .agent-copy { position:absolute; top:.5rem; right:.6rem; z-index:2; padding:.22rem .5rem; border:1px solid rgba(112,168,228,.28); border-radius:.4rem; color:#8fb8e4; background:rgba(4,14,29,.8); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; cursor:pointer; transition:border-color .14s, color .14s; }
199
+ .agent-copy:hover { border-color:rgba(84,183,255,.55); color:#bfe9ff; }
200
+ .agent-diff { max-height:280px; overflow:auto; padding:2.2rem .6rem .6rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.7rem; line-height:1.6; }
201
+ .diff-line { display:flex; gap:.4rem; padding:.05rem 0; white-space:pre-wrap; word-break:break-word; }
202
+ .diff-marker { width:1ch; flex:0 0 auto; opacity:.7; }
203
+ .diff-line.diff-hunk { color:#67c8ff; background:rgba(84,183,255,.1); }
204
+ .diff-line.diff-add { color:#6df0bb; background:rgba(16,185,129,.16); }
205
+ .diff-line.diff-del { color:#fda4af; background:rgba(244,63,94,.16); }
206
+ .diff-line.diff-meta { color:#718ba7; }
207
+ .agent-timer { display:flex; align-items:center; gap:.45rem; padding:.4rem .85rem 0; }
208
+ .agent-timer-bar { height:.28rem; flex:0 0 auto; border-radius:999px; background:linear-gradient(90deg,#fbbf24,#f59e0b); box-shadow:0 0 8px rgba(245,158,11,.35); transition:width .25s linear; }
209
+ .agent-timer-label { color:#ffd479; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; }
210
+ .agent-tool-out { margin:0; padding:.55rem .85rem; border-top:1px solid rgba(112,168,228,.14); background:rgba(255,255,255,.035); color:#a6bfd8; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.72rem; line-height:1.65; white-space:pre-wrap; word-break:break-word; }
211
+ .agent-tool-output { margin:0; max-height:280px; overflow:auto; padding:.85rem .95rem; color:#e8f2ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.82rem; line-height:1.75; white-space:pre-wrap; word-break:break-word; }
212
+ .agent-tool-output .hljs { display:block; background:transparent; color:#e8f2ff; }
213
+ .agent-tool-output .hljs-keyword, .agent-tool-output .hljs-selector-tag, .agent-tool-output .hljs-meta .hljs-keyword { color:#c792ea; }
214
+ .agent-tool-output .hljs-string, .agent-tool-output .hljs-attr, .agent-tool-output .hljs-regexp, .agent-tool-output .hljs-template-string { color:#7fe0a8; }
215
+ .agent-tool-output .hljs-number, .agent-tool-output .hljs-literal, .agent-tool-output .hljs-symbol, .agent-tool-output .hljs-bullet, .agent-tool-output .hljs-params { color:#e2a76f; }
216
+ .agent-tool-output .hljs-comment, .agent-tool-output .hljs-quote { color:#6b85a3; font-style:italic; }
217
+ .agent-tool-output .hljs-title, .agent-tool-output .hljs-title.function_, .agent-tool-output .hljs-function .hljs-title, .agent-tool-output .hljs-section { color:#82c6ff; }
218
+ .agent-tool-output .hljs-built_in, .agent-tool-output .hljs-selector-class, .agent-tool-output .hljs-selector-id { color:#e5c07b; }
219
+ .agent-tool-output .hljs-tag, .agent-tool-output .hljs-name, .agent-tool-output .hljs-variable, .agent-tool-output .hljs-template-variable { color:#f18ac6; }
220
+ .agent-tool-output .hljs-meta, .agent-tool-output .hljs-doctag { color:#56b6c2; }
221
+
222
+ .agent-typing { display:inline-flex; align-items:center; gap:.4rem; color:#6e8aaa; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.66rem; }
223
+ .agent-typing .agent-cursor { display:inline-block; width:.5rem; height:1rem; background:#54b7ff; box-shadow:0 0 8px rgba(84,183,255,.7); animation:agent-blink 1s steps(1) infinite; }
224
+ @keyframes agent-blink { 50% { opacity:0; } }
225
+
226
+ .agent-error { width:calc(100% - 48px); max-width:1400px; margin:0 auto; padding:.5rem .2rem 0; color:#fda4af; font-size:.74rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; }
227
+ .agent-notice { width:calc(100% - 48px); max-width:1400px; margin:0 auto; padding:.5rem .2rem 0; color:#8fa5c0; font-size:.7rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-style:italic; }
228
+ .agent-footer { position:relative; z-index:20; flex:0 0 auto; border-top:1px solid rgba(112,168,228,.15); background:rgba(4,14,29,.62); backdrop-filter:blur(24px); -webkit-backdrop-filter:blur(24px); }
229
+ .agent-footer-bar { display:flex; align-items:center; gap:.9rem; flex-wrap:wrap; width:calc(100% - 48px); max-width:1400px; margin:0 auto; padding:.6rem 0 .15rem; }
230
+ .agent-footer-hint { margin-left:auto; color:#4d6378; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.58rem; letter-spacing:.04em; }
231
+ .agent-footer-inner { display:flex; align-items:flex-end; gap:.7rem; width:calc(100% - 48px); max-width:1400px; margin:0 auto; padding:.7rem 0 .95rem; }
232
+ .agent-input { flex:1; padding:.7rem .85rem; border:1px solid rgba(112,168,228,.24); border-radius:.6rem; outline:none; resize:none; color:#e8f2ff; background:rgba(255,255,255,.05); font:inherit; font-size:.84rem; line-height:1.55; transition:border-color .14s, box-shadow .14s, background .14s; }
233
+ .agent-input::placeholder { color:#5b7392; }
234
+ .agent-input:focus { border-color:rgba(84,183,255,.6); box-shadow:0 0 0 3px rgba(84,183,255,.14); background:rgba(255,255,255,.08); }
235
+ .agent-send { padding:.7rem 1.15rem; border:1px solid rgba(84,183,255,.55); border-radius:.6rem; color:#fff; background:linear-gradient(135deg, rgba(38,130,225,.75), rgba(90,67,183,.65)); box-shadow:0 8px 24px rgba(84,183,255,.28); font-size:.8rem; font-weight:800; cursor:pointer; transition:transform .15s, filter .15s, opacity .15s; }
236
+ .agent-send:hover:not(:disabled) { filter:brightness(1.1); transform:translateY(-1px); }
237
+ .agent-send:disabled { opacity:.4; cursor:not-allowed; }
238
+
239
+ /* ── Redesign additions — aurora glass, animations, todos, hero ─────── */
240
+ .agent-mode:active { transform:scale(.95); }
241
+ .agent-tool { background:linear-gradient(160deg, rgba(16,38,70,.55), rgba(8,20,42,.62)); border-color:rgba(112,168,228,.24); box-shadow:inset 0 1px rgba(255,255,255,.06), 0 18px 50px rgba(0,0,0,.28); backdrop-filter:blur(20px) saturate(140%); -webkit-backdrop-filter:blur(20px) saturate(140%); animation:agent-rise .3s cubic-bezier(.22,1,.36,1) both; transition:border-color .16s, transform .16s, box-shadow .16s; }
242
+ .agent-tool:hover { transform:translateY(-2px); border-color:rgba(84,183,255,.4); }
243
+ .agent-row-user, .agent-row-agent { animation:agent-rise .28s cubic-bezier(.22,1,.36,1) both; }
244
+ .agent-bubble { background:linear-gradient(160deg, rgba(16,38,70,.5), rgba(8,20,42,.56)); border-color:rgba(112,168,228,.22); box-shadow:inset 0 1px rgba(255,255,255,.05), 0 18px 50px rgba(0,0,0,.24); backdrop-filter:blur(18px) saturate(135%); -webkit-backdrop-filter:blur(18px) saturate(135%); }
245
+ .agent-row-user .agent-bubble { background:linear-gradient(160deg, rgba(22,70,122,.58), rgba(46,41,112,.5)); border-color:rgba(84,183,255,.42); }
246
+ .agent-tool-body { animation:agent-open .18s cubic-bezier(.22,1,.36,1); }
247
+ @keyframes agent-rise { from { opacity:0; transform:translateY(10px); filter:blur(2px); } to { opacity:1; transform:translateY(0); filter:blur(0); } }
248
+ @keyframes agent-open { from { opacity:0; transform:translateY(-4px); } to { opacity:1; transform:translateY(0); } }
249
+
250
+ .agent-side-section-head { cursor:pointer; user-select:none; transition:color .12s; }
251
+ .agent-side-section-head:hover { color:#dcecff; }
252
+ .agent-side-chevron { display:inline-block; font-size:.58rem; color:#45597a; transition:transform .16s; }
253
+ .agent-side-chevron.collapsed { transform:rotate(-90deg); }
254
+
255
+ .agent-todos-add { display:flex; gap:.4rem; }
256
+ .agent-todos-input { flex:1; min-width:0; padding:.42rem .55rem; border:1px solid rgba(112,168,228,.22); border-radius:.5rem; outline:none; color:#e5f4ff; background:rgba(20,46,79,.32); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; transition:border-color .14s, box-shadow .14s; }
257
+ .agent-todos-input::placeholder { color:#536c8c; }
258
+ .agent-todos-input:focus { border-color:rgba(84,183,255,.55); box-shadow:0 0 0 2px rgba(84,183,255,.15); }
259
+ .agent-todos-add-btn { flex:0 0 auto; width:1.9rem; border:1px solid rgba(84,183,255,.4); border-radius:.5rem; color:#bfe9ff; background:linear-gradient(135deg, rgba(38,130,225,.5), rgba(90,67,183,.45)); font-size:1rem; line-height:1; cursor:pointer; transition:filter .14s, transform .14s; }
260
+ .agent-todos-add-btn:hover { filter:brightness(1.15); }
261
+ .agent-todos-add-btn:active { transform:scale(.94); }
262
+ .agent-todos-add-btn:disabled { opacity:.4; cursor:not-allowed; }
263
+ .agent-todos-progress { display:flex; align-items:center; gap:.45rem; }
264
+ .agent-todos-progress-bar { flex:0 0 auto; height:.24rem; border-radius:999px; background:linear-gradient(90deg, #3f9bff, #6cd9ff); box-shadow:0 0 8px rgba(84,183,255,.5); transition:width .25s ease; }
265
+ .agent-todos-progress span { color:#6e8aaa; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; }
266
+ .agent-todo-row { display:flex; align-items:center; gap:.45rem; padding:.38rem .5rem; border:1px solid rgba(112,168,228,.16); border-radius:.5rem; background:rgba(8,25,48,.55); box-shadow:inset 0 1px rgba(255,255,255,.04); transition:border-color .14s, background .14s; }
267
+ .agent-todo-row:hover { border-color:rgba(84,183,255,.4); background:rgba(84,183,255,.08); }
268
+ .agent-todo-check { display:grid; place-items:center; width:1.05rem; height:1.05rem; flex:0 0 auto; border:1px solid rgba(112,168,228,.4); border-radius:.3rem; color:transparent; background:rgba(255,255,255,.05); font-size:.6rem; cursor:pointer; transition:all .14s; }
269
+ .agent-todo-check.on { border-color:rgba(52,211,153,.55); color:#0b241b; background:#5ef0b3; box-shadow:0 0 8px rgba(94,240,179,.5); }
270
+ .agent-todo-text { flex:1; min-width:0; color:#cfe3fb; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
271
+ .agent-todo-row.done .agent-todo-text { color:#5b7392; text-decoration:line-through; }
272
+ .agent-todo-del { flex:0 0 auto; width:1.2rem; height:1.2rem; border:0; border-radius:.3rem; color:#6e8aaa; background:transparent; font-size:.9rem; line-height:1; cursor:pointer; transition:color .12s, background .12s; }
273
+ .agent-todo-del:hover { color:#fecdd3; background:rgba(244,63,94,.16); }
274
+
275
+ .agent-hero { display:flex; flex-direction:column; align-items:center; gap:.6rem; margin:5vh auto 0; max-width:640px; padding:2.5rem 2rem; text-align:center; border:1px solid rgba(112,168,228,.2); border-radius:1.2rem; background:linear-gradient(160deg, rgba(16,38,70,.5), rgba(8,20,42,.55)); box-shadow:inset 0 1px rgba(255,255,255,.06), 0 24px 70px rgba(0,0,0,.3); backdrop-filter:blur(22px) saturate(140%); -webkit-backdrop-filter:blur(22px) saturate(140%); animation:agent-rise .4s cubic-bezier(.22,1,.36,1) both; }
276
+ .agent-hero-orb { position:relative; display:grid; place-items:center; width:74px; height:74px; margin-bottom:.4rem; border:1px solid rgba(84,183,255,.35); border-radius:50%; background:radial-gradient(circle, rgba(57,170,255,.4), rgba(56,58,179,.16) 46%, transparent 70%); box-shadow:0 0 34px rgba(58,149,255,.35), inset 0 0 24px rgba(94,119,255,.18); animation:agent-orbit-spin 14s linear infinite; }
277
+ .agent-hero-orb::before { position:absolute; width:70%; height:26%; border:1px solid rgba(112,206,255,.6); border-radius:50%; content:""; transform:rotate(-28deg); }
278
+ .agent-hero-orb span { width:6px; height:6px; border-radius:50%; background:#5ef0b3; box-shadow:0 0 12px #5ef0b3; z-index:1; }
279
+ @keyframes agent-orbit-spin { to { transform:rotate(360deg); } }
280
+ .agent-hero h2 { margin:.4rem 0 0; color:#f1f8ff; font-size:1.5rem; letter-spacing:-.03em; }
281
+ .agent-hero h2 em { color:#6fcaff; font-style:normal; text-shadow:0 0 24px rgba(80,183,255,.4); }
282
+ .agent-hero p { margin:0; color:#8fa5c0; font-size:.78rem; line-height:1.7; }
283
+ .agent-hero-chips { display:flex; flex-wrap:wrap; justify-content:center; gap:.5rem; margin-top:.9rem; }
284
+ .agent-hero-chip { padding:.5rem .8rem; border:1px solid rgba(112,168,228,.28); border-radius:999px; color:#a8d8ff; background:rgba(84,183,255,.08); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.64rem; cursor:pointer; transition:border-color .14s, background .14s, transform .14s; }
285
+ .agent-hero-chip:hover { border-color:rgba(84,183,255,.6); background:rgba(84,183,255,.16); transform:translateY(-2px); }
286
+ .agent-hero .agent-hint { margin-top:.6rem; }
287
+
288
+ .agent-suggest { position:fixed; z-index:70; left:50%; bottom:4.4rem; transform:translateX(-50%); display:flex; flex-direction:column; gap:.55rem; width:min(560px, calc(100vw - 32px)); padding:.95rem 1.1rem; border:1px solid rgba(255,196,107,.38); border-radius:.9rem; background:linear-gradient(160deg, rgba(48,34,10,.92), rgba(26,18,40,.9)); box-shadow:inset 0 1px rgba(255,255,255,.06), 0 24px 70px rgba(0,0,0,.5), 0 0 30px rgba(245,158,11,.14); backdrop-filter:blur(22px) saturate(140%); -webkit-backdrop-filter:blur(22px) saturate(140%); animation:agent-rise .25s cubic-bezier(.22,1,.36,1) both; }
289
+ .agent-suggest-close { position:absolute; top:.55rem; right:.55rem; width:1.4rem; height:1.4rem; display:grid; place-items:center; border:1px solid rgba(255,196,107,.28); border-radius:.4rem; color:#b98a3a; background:rgba(0,0,0,.25); font-size:.7rem; line-height:1; cursor:pointer; transition:color .14s, border-color .14s, background .14s; }
290
+ .agent-suggest-close:hover { color:#ffe4b3; border-color:rgba(255,196,107,.6); background:rgba(245,158,11,.2); }
291
+ .agent-suggest-head { display:flex; align-items:baseline; gap:.55rem; flex-wrap:wrap; padding-right:1.4rem; }
292
+ .agent-suggest-title { color:#ffd479; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; font-weight:800; letter-spacing:.14em; text-transform:uppercase; text-shadow:0 0 14px rgba(245,158,11,.35); }
293
+ .agent-suggest-sub { color:#8a7a58; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.58rem; }
294
+ .agent-suggest-chips { display:flex; flex-wrap:wrap; gap:.45rem; }
295
+ .agent-suggest-chips .agent-hero-chip { border-color:rgba(255,196,107,.38); color:#ffe3a3; background:rgba(245,158,11,.12); }
296
+ .agent-suggest-chips .agent-hero-chip:hover { border-color:rgba(255,196,107,.68); background:rgba(245,158,11,.22); transform:translateY(-2px); }
297
+
298
+ .agent-enhance { position:fixed; z-index:70; left:50%; bottom:4.4rem; transform:translateX(-50%); display:flex; flex-direction:column; gap:.6rem; width:min(560px, calc(100vw - 32px)); max-height:70vh; overflow:auto; padding:.95rem 1.1rem; border:1px solid rgba(99,189,255,.4); border-radius:.9rem; background:linear-gradient(160deg, rgba(14,42,78,.94), rgba(26,18,40,.92)); box-shadow:inset 0 1px rgba(255,255,255,.06), 0 24px 70px rgba(0,0,0,.5), 0 0 30px rgba(84,183,255,.16); backdrop-filter:blur(22px) saturate(140%); -webkit-backdrop-filter:blur(22px) saturate(140%); animation:agent-rise .25s cubic-bezier(.22,1,.36,1) both; }
299
+ .agent-enhance-head { display:flex; align-items:baseline; gap:.55rem; flex-wrap:wrap; padding-right:1.4rem; }
300
+ .agent-enhance-title { color:#8ed6ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; font-weight:800; letter-spacing:.14em; text-transform:uppercase; text-shadow:0 0 14px rgba(84,183,255,.4); }
301
+ .agent-enhance-sub { color:#6d8fb2; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.58rem; }
302
+ .agent-enhance-input { width:100%; padding:.6rem .75rem; border:1px solid rgba(112,168,228,.26); border-radius:.6rem; outline:none; resize:vertical; color:#e8f2ff; background:rgba(255,255,255,.06); font:inherit; font-size:.8rem; line-height:1.55; transition:border-color .14s, box-shadow .14s; }
303
+ .agent-enhance-input:focus { border-color:rgba(99,189,255,.6); box-shadow:0 0 0 3px rgba(84,183,255,.14); }
304
+ .agent-enhance-label { color:#5f7b9c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; letter-spacing:.13em; text-transform:uppercase; }
305
+ .agent-enhance-bubble { padding:.7rem .85rem; border:1px solid rgba(112,168,228,.22); border-radius:.7rem; color:#dcecff; background:linear-gradient(160deg, rgba(16,38,70,.5), rgba(8,20,42,.56)); font-size:.8rem; line-height:1.7; white-space:pre-wrap; overflow-wrap:anywhere; }
306
+ .agent-enhance-features { display:flex; flex-direction:column; gap:.5rem; }
307
+ .agent-enhance-chips { display:flex; flex-wrap:wrap; gap:.45rem; }
308
+ .agent-enhance-chip { padding:.42rem .7rem; border:1px solid rgba(112,168,228,.3); border-radius:999px; color:#a8d8ff; background:rgba(84,183,255,.08); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; cursor:pointer; transition:border-color .14s, background .14s, transform .14s; }
309
+ .agent-enhance-chip:hover { border-color:rgba(99,189,255,.6); background:rgba(84,183,255,.16); transform:translateY(-1px); }
310
+ .agent-enhance-chip.on { border-color:rgba(94,240,179,.55); color:#7ee8bd; background:rgba(16,185,129,.16); }
311
+ .agent-enhance-actions { display:flex; gap:.5rem; }
312
+ .agent-enhance-btn { padding:.5rem .95rem; border:1px solid rgba(99,189,255,.55); border-radius:.55rem; color:#eaf7ff; background:linear-gradient(135deg, rgba(38,130,225,.7), rgba(90,67,183,.6)); box-shadow:0 6px 18px rgba(84,183,255,.24); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.68rem; font-weight:800; cursor:pointer; transition:filter .15s, transform .15s, opacity .15s; }
313
+ .agent-enhance-btn:hover:not(:disabled) { filter:brightness(1.1); transform:translateY(-1px); }
314
+ .agent-enhance-btn:disabled { opacity:.45; cursor:not-allowed; }
315
+ .agent-enhance-btn.ghost { border-color:rgba(112,168,228,.3); color:#9fb3d0; background:rgba(84,183,255,.08); box-shadow:none; }
316
+ .agent-enhance-error { color:#fda4af; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.66rem; }
317
+ .agent-enhance-opt { display:flex; align-items:center; gap:.5rem; padding-top:.5rem; border-top:1px dashed rgba(112,168,228,.16); cursor:pointer; user-select:none; }
318
+ .agent-enhance-check { display:grid; place-items:center; width:1rem; height:1rem; flex:0 0 auto; border:1px solid rgba(112,168,228,.4); border-radius:.3rem; color:#0b241b; background:rgba(255,255,255,.05); font-size:.62rem; line-height:1; transition:border-color .14s, background .14s; }
319
+ .agent-enhance-check.on { border-color:rgba(94,240,179,.6); background:#5ef0b3; box-shadow:0 0 8px rgba(94,240,179,.45); }
320
+ .agent-enhance-opt-label { color:#7d94b2; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; }
321
+ .agent-enhance-toggle { display:inline-flex; align-items:center; gap:.42rem; padding:.4rem .7rem; border:1px solid rgba(112,168,228,.22); border-radius:.6rem; color:#9fd4ff; background:rgba(84,183,255,.08); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase; cursor:pointer; transition:border-color .14s, color .14s, background .14s, box-shadow .14s, transform .14s; }
322
+ .agent-enhance-toggle:hover:not(:disabled) { color:#dcecff; border-color:rgba(99,189,255,.5); transform:translateY(-1px); }
323
+ .agent-enhance-toggle.on { color:#9fe8ff; border-color:rgba(99,189,255,.6); background:linear-gradient(135deg, rgba(40,137,235,.3), rgba(90,67,183,.22)); box-shadow:0 0 14px rgba(84,183,255,.25); }
324
+ .agent-enhance-toggle:disabled { opacity:.4; cursor:not-allowed; }
325
+
326
+ .agent-settings-btn { display:grid; place-items:center; width:2.1rem; height:2.1rem; padding:0; border:1px solid rgba(112,168,228,.24); border-radius:.6rem; color:#8fb8e4; background:rgba(84,183,255,.08); font-size:.9rem; line-height:1; cursor:pointer; transition:border-color .15s, color .15s, background .15s, transform .15s; }
327
+ .agent-settings-btn:hover { border-color:rgba(84,183,255,.55); color:#bfe9ff; background:rgba(84,183,255,.16); transform:translateY(-1px); }
328
+ .agent-settings-btn.on { color:#9fe8ff; border-color:rgba(99,189,255,.6); background:linear-gradient(135deg, rgba(40,137,235,.3), rgba(90,67,183,.22)); box-shadow:0 0 14px rgba(84,183,255,.25); }
329
+
330
+ .agent-settings { position:fixed; z-index:65; top:0; right:0; bottom:0; width:min(340px, 92vw); display:flex; flex-direction:column; border-left:1px solid rgba(112,168,228,.2); background:linear-gradient(180deg, rgba(10,28,55,.97), rgba(6,15,34,.98)); box-shadow:-18px 0 60px rgba(0,0,0,.5); backdrop-filter:blur(22px) saturate(140%); -webkit-backdrop-filter:blur(22px) saturate(140%); animation:agent-fade .18s ease both; }
331
+ .agent-settings-head { display:flex; align-items:center; justify-content:space-between; padding:1rem 1.1rem; border-bottom:1px solid rgba(112,168,228,.14); }
332
+ .agent-settings-title { color:#8ed6ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.66rem; font-weight:800; letter-spacing:.14em; text-transform:uppercase; text-shadow:0 0 14px rgba(84,183,255,.4); }
333
+ .agent-settings-body { flex:1 1 auto; min-height:0; overflow-y:auto; padding:1rem 1.1rem 1.5rem; display:flex; flex-direction:column; gap:1.2rem; }
334
+ .agent-settings-section { display:flex; flex-direction:column; gap:.6rem; }
335
+ .agent-settings-row { display:flex; align-items:center; justify-content:space-between; gap:.5rem; padding:.55rem .7rem; border:1px solid rgba(112,168,228,.16); border-radius:.6rem; background:rgba(8,25,48,.55); cursor:pointer; user-select:none; transition:border-color .14s, background .14s; }
336
+ .agent-settings-row:hover { border-color:rgba(84,183,255,.4); background:rgba(84,183,255,.08); }
337
+ .agent-settings-row-label { color:#cfe3fb; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; }
338
+ .agent-settings-field { display:flex; flex-direction:column; gap:.3rem; }
339
+ .agent-settings-field span { color:#5f7b9c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; letter-spacing:.13em; text-transform:uppercase; }
340
+ .agent-settings-field .agent-select { width:100%; max-width:none; }
341
+ .agent-default-row { display:flex; align-items:center; gap:.5rem; margin-top:.2rem; }
342
+ .agent-default-btn { padding:.42rem .7rem; border:1px solid rgba(84,183,255,.34); border-radius:.5rem; color:#bfe9ff; background:linear-gradient(135deg, rgba(38,130,225,.28), rgba(90,67,183,.18)); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; font-weight:800; letter-spacing:.06em; cursor:pointer; transition:filter .14s, border-color .14s, background .14s, opacity .14s; }
343
+ .agent-default-btn:hover:not(:disabled) { filter:brightness(1.15); border-color:rgba(84,183,255,.55); }
344
+ .agent-default-btn:disabled { opacity:.45; cursor:default; }
345
+ .agent-default-btn.is-default { color:#6df0bb; border-color:rgba(52,211,153,.32); background:rgba(16,185,129,.12); }
346
+ .agent-default-hint { color:#5f7b9c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; }
347
+
348
+ .agent-thinking { border:1px dashed rgba(112,168,228,.28); border-radius:.85rem; background:rgba(8,22,45,.4); overflow:hidden; animation:agent-rise .3s cubic-bezier(.22,1,.36,1) both; }
349
+ .agent-thinking-head { display:flex; align-items:center; gap:.5rem; padding:.55rem .85rem; color:#8fa8c8; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; cursor:pointer; user-select:none; transition:background .14s; flex-wrap:wrap; }
350
+ .agent-thinking-head:hover { background:rgba(84,183,255,.07); }
351
+ .agent-thinking-dot { width:.42rem; height:.42rem; flex:0 0 auto; border-radius:50%; background:#54b7ff; box-shadow:0 0 8px rgba(84,183,255,.6); }
352
+ .agent-thinking-name { color:#9fd4ff; font-size:.62rem; font-weight:800; letter-spacing:.12em; text-transform:uppercase; }
353
+ .agent-thinking-summary { flex:0 1 auto; min-width:0; color:#5f7b9c; font-size:.6rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
354
+ .agent-thinking-current { display:inline-flex; align-items:center; gap:.3rem; flex:1 1 auto; min-width:0; padding:.14rem .42rem; border-radius:.4rem; background:rgba(84,183,255,.08); border:1px solid rgba(112,168,228,.14); font-size:.6rem; overflow:hidden; }
355
+ .agent-thinking-current-text { flex:1; min-width:0; color:#cfe3fb; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
356
+ .agent-thinking-current .agent-tool-badge { padding:.1rem .32rem; font-size:.48rem; }
357
+ .agent-thinking-live { color:#8ed6ff; font-size:.52rem; font-weight:800; animation:agent-pulse 1s ease-in-out infinite; }
358
+ .agent-thinking-more { flex:0 0 auto; padding:.14rem .46rem; border-radius:999px; color:#ffd479; background:rgba(245,158,11,.14); border:1px solid rgba(255,196,107,.3); font-size:.56rem; font-weight:800; }
359
+ .agent-thinking-preview { display:flex; align-items:center; gap:.4rem; padding:.42rem .75rem; border-top:1px dashed rgba(112,168,228,.16); background:rgba(8,25,48,.35); cursor:pointer; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; }
360
+ .agent-thinking-preview-dot { width:.34rem; height:.34rem; flex:0 0 auto; border-radius:50%; background:#54b7ff; box-shadow:0 0 6px rgba(84,183,255,.6); animation:agent-pulse 1s ease-in-out infinite; }
361
+ .agent-thinking-preview-summary { flex:1; min-width:0; color:#cfe3fb; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
362
+ .agent-thinking-preview-status { flex:0 0 auto; padding:.1rem .36rem; border-radius:.3rem; font-size:.52rem; font-weight:800; text-transform:uppercase; }
363
+ .agent-thinking-preview-status.running { color:#8ed6ff; background:rgba(84,183,255,.12); border:1px solid rgba(84,183,255,.22); }
364
+ .agent-thinking-preview-status.ok { color:#6df0bb; background:rgba(16,185,129,.1); border:1px solid rgba(52,211,153,.18); }
365
+ .agent-thinking-preview-status.err { color:#fda4af; background:rgba(244,63,94,.1); border:1px solid rgba(244,63,94,.18); }
366
+ .agent-thinking-body { display:flex; flex-direction:column; gap:.5rem; padding:.6rem .85rem .85rem; border-top:1px dashed rgba(112,168,228,.16); }
367
+ .agent-thinking-body .agent-tool { box-shadow:none; }
368
+ .agent-thinking.collapsed .agent-thinking-head { background:rgba(8,25,48,.2); }
369
+
370
+ .agent-team { display:flex; flex-direction:column; gap:.6rem; padding:.85rem 1rem; border:1px solid rgba(84,183,255,.32); border-radius:.85rem; background:linear-gradient(160deg, rgba(16,38,70,.55), rgba(26,16,64,.42)); box-shadow:inset 0 1px rgba(255,255,255,.05), 0 16px 44px rgba(0,0,0,.24); backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px); animation:agent-rise .3s cubic-bezier(.22,1,.36,1) both; }
371
+ .agent-team-head { display:flex; align-items:baseline; gap:.55rem; flex-wrap:wrap; }
372
+ .agent-team-title { color:#8ed6ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; font-weight:800; letter-spacing:.14em; text-transform:uppercase; text-shadow:0 0 14px rgba(84,183,255,.4); }
373
+ .agent-team-stage { color:#6d8fb2; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; }
374
+ .agent-team-grid { display:flex; flex-wrap:wrap; gap:.5rem; }
375
+ .agent-team-member { display:inline-flex; align-items:center; gap:.45rem; padding:.42rem .68rem; border:1px solid rgba(112,168,228,.18); border-radius:999px; background:rgba(8,25,48,.6); color:#9fb3d0; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; font-weight:600; transition:border-color .14s, color .14s; }
376
+ .agent-team-dot { width:.4rem; height:.4rem; flex:0 0 auto; border-radius:50%; background:#54b7ff; box-shadow:0 0 8px rgba(84,183,255,.7); animation:agent-pulse 1s ease-in-out infinite; }
377
+ .agent-team-member.done { color:#7ee8bd; border-color:rgba(52,211,153,.3); }
378
+ .agent-team-member.done .agent-team-dot { background:#5ef0b3; box-shadow:0 0 8px rgba(94,240,179,.8); animation:none; }
379
+ .agent-team-member.pending { opacity:.55; }
380
+ .agent-team-member.pending .agent-team-dot { animation:none; opacity:.4; }
381
+ .agent-team-spinner { width:.5rem; height:.5rem; flex:0 0 auto; border:2px solid rgba(84,183,255,.25); border-top-color:#54b7ff; border-radius:50%; animation:agent-spin .8s linear infinite; }
382
+ @keyframes agent-spin { to { transform:rotate(360deg); } }
383
+ .agent-team-toggle { display:inline-flex; align-items:center; gap:.42rem; padding:.4rem .7rem; border:1px solid rgba(112,168,228,.22); border-radius:.6rem; color:#7d94b2; background:rgba(20,46,79,.28); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase; cursor:pointer; transition:border-color .14s, color .14s, background .14s, box-shadow .14s, transform .14s; }
384
+ .agent-team-toggle:hover { color:#dcecff; border-color:rgba(84,183,255,.5); transform:translateY(-1px); }
385
+ .agent-team-toggle.on { color:#9fe8ff; border-color:rgba(84,183,255,.55); background:linear-gradient(135deg, rgba(40,137,235,.3), rgba(90,67,183,.22)); box-shadow:0 0 14px rgba(84,183,255,.25); }
386
+ .agent-team-toggle-dot { width:.4rem; height:.4rem; border-radius:50%; background:#4b647f; }
387
+ .agent-team-toggle.on .agent-team-toggle-dot { background:#5ef0b3; box-shadow:0 0 8px rgba(94,240,179,.9); }
388
+
389
+ .agent-typing { display:inline-flex; align-items:center; gap:.55rem; padding:.4rem .7rem; border:1px solid rgba(112,168,228,.16); border-radius:999px; color:#6e8aaa; background:rgba(8,25,48,.5); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; }
390
+ .agent-typing-label { letter-spacing:.08em; text-transform:uppercase; font-size:.56rem; }
391
+ .agent-dots { display:inline-flex; gap:.24rem; }
392
+ .agent-dots i { width:.32rem; height:.32rem; border-radius:50%; background:#54b7ff; box-shadow:0 0 8px rgba(84,183,255,.7); animation:agent-bounce 1.2s ease-in-out infinite; }
393
+ .agent-dots i:nth-child(2) { animation-delay:.16s; }
394
+ .agent-dots i:nth-child(3) { animation-delay:.32s; }
395
+ @keyframes agent-bounce { 0%,60%,100% { transform:translateY(0); opacity:.5; } 30% { transform:translateY(-4px); opacity:1; } }
396
+
397
+ .agent-toast { position:fixed; top:4.5rem; right:1.5rem; z-index:60; padding:.6rem .9rem; border:1px solid rgba(84,183,255,.35); border-radius:.6rem; color:#dcecff; background:linear-gradient(160deg, rgba(16,38,70,.85), rgba(8,20,42,.9)); box-shadow:0 14px 40px rgba(0,0,0,.4); backdrop-filter:blur(20px) saturate(140%); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.68rem; animation:agent-open .22s cubic-bezier(.22,1,.36,1); }
398
+
399
+ /* ── Alert toast (top-right) — success / error / info states ── */
400
+ .agent-alert { position:fixed; top:4.2rem; right:1.25rem; z-index:200; display:none; align-items:flex-start; gap:.6rem; max-width:340px; padding:.65rem .8rem; border:1px solid rgba(84,183,255,.35); border-radius:.7rem; color:#dcecff; background:linear-gradient(160deg, rgba(16,38,70,.94), rgba(8,20,42,.97)); box-shadow:0 14px 44px rgba(0,0,0,.5), inset 0 1px rgba(255,255,255,.06); backdrop-filter:blur(20px) saturate(140%); -webkit-backdrop-filter:blur(20px) saturate(140%); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; }
401
+ .agent-alert.show { display:flex; animation:agent-rise .24s cubic-bezier(.22,1,.36,1); }
402
+ .agent-alert-mark { flex:0 0 auto; display:grid; place-items:center; width:1.5rem; height:1.5rem; border-radius:.45rem; color:#6df0bb; font-size:.85rem; font-weight:800; border:1px solid rgba(52,211,153,.45); background:linear-gradient(135deg, rgba(16,185,129,.3), rgba(6,95,70,.22)); box-shadow:0 0 12px rgba(52,211,153,.25); }
403
+ .agent-alert-body { flex:1; min-width:0; display:flex; flex-direction:column; gap:.15rem; }
404
+ .agent-alert-title { color:#7ee8bd; font-size:.62rem; font-weight:800; letter-spacing:.1em; text-transform:uppercase; }
405
+ .agent-alert-msg { color:#cfe3fb; font-size:.64rem; line-height:1.5; word-break:break-word; }
406
+ .agent-alert-close { flex:0 0 auto; display:grid; place-items:center; width:1.2rem; height:1.2rem; border:0; border-radius:.35rem; color:#7d94b2; background:transparent; font-size:.9rem; line-height:1; cursor:pointer; transition:color .12s, background .12s; }
407
+ .agent-alert-close:hover { color:#fecdd3; background:rgba(244,63,94,.16); }
408
+ .agent-alert.hide { display:none; }
409
+ /* Error state */
410
+ .agent-alert.is-error { border-color:rgba(251,113,133,.5); }
411
+ .agent-alert.is-error .agent-alert-mark { color:#fda4af; border-color:rgba(251,113,133,.5); background:linear-gradient(135deg, rgba(244,63,94,.3), rgba(159,18,57,.22)); box-shadow:0 0 12px rgba(244,63,94,.28); }
412
+ .agent-alert.is-error .agent-alert-title { color:#fda4af; }
413
+ .agent-alert.is-error .agent-alert-msg { color:#fecdd3; }
414
+ /* Info state */
415
+ .agent-alert.is-info { border-color:rgba(84,183,255,.5); }
416
+ .agent-alert.is-info .agent-alert-mark { color:#8ed6ff; border-color:rgba(84,183,255,.5); background:linear-gradient(135deg, rgba(38,130,225,.3), rgba(90,67,183,.24)); box-shadow:0 0 12px rgba(84,183,255,.28); }
417
+ .agent-alert.is-info .agent-alert-title { color:#8ed6ff; }
418
+ .agent-alert.is-info .agent-alert-msg { color:#cfe3fb; }
419
+ .agent-scroll-down { position:fixed; right:1.6rem; bottom:6.5rem; z-index:55; display:grid; place-items:center; width:2.5rem; height:2.5rem; border:1px solid rgba(84,183,255,.4); border-radius:50%; color:#bfe9ff; background:linear-gradient(160deg, rgba(16,38,70,.85), rgba(8,20,42,.9)); box-shadow:0 10px 30px rgba(0,0,0,.35), 0 0 16px rgba(84,183,255,.2); backdrop-filter:blur(18px); font-size:1rem; cursor:pointer; transition:transform .14s, filter .14s; animation:agent-rise .2s cubic-bezier(.22,1,.36,1) both; }
420
+ .agent-scroll-down:hover { filter:brightness(1.15); transform:translateY(-2px); }
421
+ .agent-scroll-down:active { transform:scale(.92); }
422
+
423
+ .agent-explorer { position:fixed; inset:0; z-index:80; display:flex; align-items:center; justify-content:center; padding:1rem; background:rgba(2,8,20,.62); backdrop-filter:blur(3px); -webkit-backdrop-filter:blur(3px); animation:agent-fade .18s ease both; }
424
+ .agent-explorer-card { display:flex; flex-direction:column; width:min(600px, 100%); max-height:78vh; border:1px solid rgba(99,189,255,.28); border-radius:.9rem; background:linear-gradient(160deg, rgba(12,34,64,.96), rgba(6,16,36,.98)); box-shadow:inset 0 1px rgba(255,255,255,.06), 0 30px 90px rgba(0,0,0,.6), 0 0 40px rgba(84,183,255,.12); overflow:hidden; animation:agent-rise .22s cubic-bezier(.22,1,.36,1) both; }
425
+ .agent-explorer-head { display:flex; align-items:center; justify-content:space-between; padding:.85rem 1rem; border-bottom:1px solid rgba(112,168,228,.16); }
426
+ .agent-explorer-title { color:#8ed6ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.68rem; font-weight:800; letter-spacing:.14em; text-transform:uppercase; text-shadow:0 0 14px rgba(84,183,255,.4); }
427
+ .agent-explorer-note { margin:0; padding:.5rem 1rem 0; color:#5f7b9c; font-size:.6rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; }
428
+ .agent-explorer-bar { display:flex; align-items:center; gap:.5rem; padding:.6rem .75rem; border-bottom:1px solid rgba(112,168,228,.1); }
429
+ .agent-explorer-up { flex:0 0 auto; width:1.9rem; height:1.9rem; padding:0; border:1px solid rgba(112,168,228,.3); border-radius:.45rem; color:#9fd4ff; background:rgba(84,183,255,.1); font-size:.85rem; cursor:pointer; transition:border-color .12s, background .12s, color .12s, opacity .12s; }
430
+ .agent-explorer-up:hover:not(:disabled) { border-color:rgba(84,183,255,.65); color:#fff; background:rgba(84,183,255,.2); }
431
+ .agent-explorer-up:disabled { opacity:.35; cursor:default; }
432
+ .agent-explorer-crumbs { flex:1 1 auto; min-width:0; display:flex; align-items:center; flex-wrap:wrap; gap:.1rem; overflow:hidden; }
433
+ .agent-explorer-crumb { display:inline-flex; align-items:center; white-space:nowrap; color:#45597a; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; }
434
+ .agent-explorer-sep { margin:0 .1rem; opacity:.6; }
435
+ .agent-explorer-crumb-btn { padding:.16rem .34rem; border:1px solid transparent; border-radius:.35rem; color:#9fc3ea; background:transparent; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; cursor:pointer; transition:color .12s, background .12s, border-color .12s; }
436
+ .agent-explorer-crumb-btn:hover { color:#dcecff; background:rgba(84,183,255,.1); }
437
+ .agent-explorer-crumb-btn.on { color:#63bdff; background:rgba(40,137,235,.16); border-color:rgba(84,183,255,.3); }
438
+ .agent-explorer-roots { flex:0 0 auto; display:flex; gap:.3rem; }
439
+ .agent-explorer-root { max-width:180px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; padding:.18rem .5rem; border:1px solid rgba(245,158,11,.32); border-radius:.4rem; color:#ffd479; background:rgba(245,158,11,.1); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; cursor:pointer; transition:filter .12s, background .12s; }
440
+ .agent-explorer-root:hover { filter:brightness(1.15); background:rgba(245,158,11,.18); }
441
+ .agent-explorer-body { flex:1 1 auto; min-height:0; overflow-y:auto; padding:.4rem .5rem; }
442
+ .agent-explorer-list { display:flex; flex-direction:column; gap:.15rem; }
443
+ .agent-explorer-row { display:flex; align-items:center; gap:.5rem; padding:.28rem .45rem; border-radius:.5rem; transition:background .12s; }
444
+ .agent-explorer-row:hover { background:rgba(84,183,255,.07); }
445
+ .agent-explorer-name { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; padding:.22rem .4rem; border:1px solid transparent; border-radius:.4rem; color:#cfe3fb; background:transparent; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.72rem; text-align:left; cursor:pointer; transition:color .12s, background .12s, border-color .12s; }
446
+ .agent-explorer-name:hover { color:#fff; background:rgba(40,137,235,.14); border-color:rgba(84,183,255,.25); }
447
+ .agent-explorer-tag { flex:0 0 auto; padding:.1rem .42rem; border-radius:999px; color:#6df0bb; border:1px solid rgba(52,211,153,.32); background:rgba(16,185,129,.12); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.52rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; }
448
+ .agent-explorer-use { flex:0 0 auto; padding:.24rem .6rem; border:1px solid rgba(84,183,255,.4); border-radius:.4rem; color:#9fd4ff; background:rgba(84,183,255,.12); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; font-weight:700; cursor:pointer; transition:border-color .12s, background .12s, color .12s, transform .12s; }
449
+ .agent-explorer-use:hover { border-color:rgba(84,183,255,.75); color:#fff; background:rgba(40,137,235,.28); transform:translateY(-1px); }
450
+ .agent-explorer-empty, .agent-explorer-error { margin:0; padding:1rem .6rem; color:#45597a; font-size:.64rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; }
451
+ .agent-explorer-error { color:#fda4af; }
452
+ .agent-explorer-foot { display:flex; align-items:center; gap:.6rem; justify-content:space-between; padding:.7rem .9rem; border-top:1px solid rgba(112,168,228,.14); }
453
+ .agent-explorer-current { flex:1 1 auto; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; color:#6e8aaa; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; }
454
+ .agent-explorer-actions { flex:0 0 auto; display:flex; gap:.4rem; }
455
+ .agent-explorer-btn { padding:.4rem .8rem; border:1px solid rgba(84,183,255,.4); border-radius:.5rem; color:#9fd4ff; background:linear-gradient(135deg, rgba(40,137,235,.3), rgba(90,67,183,.22)); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; font-weight:700; cursor:pointer; transition:filter .14s, transform .14s, opacity .14s; }
456
+ .agent-explorer-btn:hover:not(:disabled) { filter:brightness(1.18); transform:translateY(-1px); }
457
+ .agent-explorer-btn:disabled { opacity:.4; cursor:default; }
458
+ .agent-explorer-btn.ghost { background:transparent; border-color:rgba(112,168,228,.25); color:#8fb8e4; }
459
+ .agent-explorer-browse { width:100%; margin-top:.45rem; padding:.4rem .6rem; border:1px dashed rgba(112,168,228,.3); border-radius:.5rem; color:#8fb8e4; background:rgba(84,183,255,.06); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; font-weight:700; cursor:pointer; transition:border-color .12s, background .12s, color .12s; }
460
+ .agent-explorer-browse:hover { border-color:rgba(84,183,255,.6); color:#bfe9ff; background:rgba(84,183,255,.12); }
461
+ .agent-workspace-btn { display:grid; place-items:center; padding:.4rem .55rem; border:1px solid rgba(112,168,228,.24); border-radius:.55rem; color:#8fb8e4; background:rgba(84,183,255,.08); font-size:.82rem; line-height:1; cursor:pointer; transition:border-color .14s, color .14s, background .14s, transform .14s; }
462
+ .agent-workspace-btn:hover { border-color:rgba(84,183,255,.55); color:#bfe9ff; background:rgba(84,183,255,.16); transform:translateY(-1px); }
463
+ .agent-workspace-btn.on { color:#9fe8ff; border-color:rgba(99,189,255,.6); background:rgba(40,137,235,.2); }
464
+
465
+ .agent-tabs { display:inline-flex; gap:.2rem; padding:.18rem; border:1px solid rgba(112,168,228,.18); border-radius:.6rem; background:rgba(8,25,48,.5); }
466
+ .agent-tab { padding:.32rem .7rem; border:1px solid transparent; border-radius:.45rem; color:#7d94b2; background:transparent; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; font-weight:700; letter-spacing:.08em; cursor:pointer; transition:color .14s, background .14s, border-color .14s; }
467
+ .agent-tab:hover { color:#dcecff; }
468
+ .agent-tab.on { color:#bfe9ff; background:linear-gradient(135deg, rgba(38,130,225,.4), rgba(90,67,183,.28)); border-color:rgba(84,183,255,.45); box-shadow:0 0 12px rgba(84,183,255,.22); }
469
+
470
+ .agent-output { display:flex; flex-direction:column; gap:.7rem; }
471
+ .agent-output-head { display:flex; align-items:center; gap:.6rem; padding:.5rem 0; border-bottom:1px solid rgba(112,168,228,.12); }
472
+ .agent-output-title { color:#63bdff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.66rem; font-weight:800; letter-spacing:.12em; text-transform:uppercase; }
473
+ .agent-output-count { color:#5f7b9c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.58rem; }
474
+ .agent-output-clear { margin-left:auto; padding:.3rem .6rem; border:1px solid rgba(112,168,228,.28); border-radius:.4rem; color:#8fb8e4; background:rgba(84,183,255,.08); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.58rem; cursor:pointer; transition:border-color .12s, background .12s; }
475
+ .agent-output-clear:hover { border-color:rgba(84,183,255,.5); background:rgba(84,183,255,.14); }
476
+ .agent-output-empty { color:#45597a; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.64rem; text-align:center; padding:2rem 1rem; }
477
+ .agent-output-list { display:flex; flex-direction:column; gap:.5rem; }
478
+ .agent-output-row { border:1px solid rgba(112,168,228,.2); border-radius:.7rem; background:rgba(8,25,48,.55); overflow:hidden; }
479
+ .agent-output-row.running { border-color:rgba(84,183,255,.4); }
480
+ .agent-output-row.ok { border-color:rgba(52,211,153,.25); }
481
+ .agent-output-row.err { border-color:rgba(251,113,133,.3); }
482
+ .agent-output-row-head { display:flex; align-items:center; gap:.5rem; padding:.5rem .7rem; cursor:pointer; }
483
+ .agent-output-dot { width:.42rem; height:.42rem; border-radius:50%; background:#5f7b9c; }
484
+ .agent-output-dot.running { background:#54b7ff; box-shadow:0 0 8px rgba(84,183,255,.7); animation:agent-pulse 1s ease-in-out infinite; }
485
+ .agent-output-name { color:#9fd4ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; font-weight:700; }
486
+ .agent-output-summary { flex:1; color:#9fb3d0; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
487
+ .agent-output-status { color:#5f7b9c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; text-transform:uppercase; }
488
+ .agent-output-body { border-top:1px solid rgba(112,168,228,.1); background:rgba(0,0,0,.2); padding:.5rem; }
489
+
490
+ .agent-preview { display:flex; flex-direction:column; gap:.6rem; height:100%; min-height:60vh; }
491
+ .agent-preview-bar { display:flex; align-items:center; gap:.5rem; flex-wrap:wrap; padding:.5rem .7rem; border:1px solid rgba(112,168,228,.2); border-radius:.7rem; background:rgba(8,25,48,.6); }
492
+ .agent-preview-label { color:#9fd4ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; font-weight:700; }
493
+ .agent-preview-badge { padding:.15rem .4rem; border-radius:999px; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; font-weight:700; text-transform:uppercase; }
494
+ .agent-preview-badge.running { color:#7ee8bd; background:rgba(16,185,129,.15); border:1px solid rgba(52,211,153,.3); }
495
+ .agent-preview-badge.building { color:#8ed6ff; background:rgba(84,183,255,.15); border:1px solid rgba(84,183,255,.3); }
496
+ .agent-preview-badge.error { color:#fecdd3; background:rgba(244,63,94,.15); border:1px solid rgba(251,113,133,.3); }
497
+ .agent-preview-badge.stopped, .agent-preview-badge.not_found { color:#ffd479; background:rgba(245,158,11,.12); border:1px solid rgba(255,196,107,.3); }
498
+ .agent-preview-actions { display:inline-flex; gap:.35rem; margin-left:auto; }
499
+ .agent-preview-btn, .agent-preview-link { padding:.3rem .6rem; border:1px solid rgba(84,183,255,.35); border-radius:.45rem; color:#9fd4ff; background:rgba(84,183,255,.1); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.58rem; font-weight:700; cursor:pointer; text-decoration:none; transition:filter .12s, background .12s; }
500
+ .agent-preview-btn:hover, .agent-preview-link:hover { filter:brightness(1.15); background:rgba(84,183,255,.18); }
501
+ .agent-preview-btn:disabled { opacity:.4; cursor:not-allowed; }
502
+ .agent-preview-btn.ghost { border-color:rgba(112,168,228,.25); color:#8fb8e4; background:transparent; }
503
+ .agent-preview-error { padding:.5rem .7rem; border:1px solid rgba(251,113,133,.3); border-radius:.5rem; color:#fecdd3; background:rgba(244,63,94,.1); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; white-space:pre-wrap; }
504
+ .agent-preview-empty { color:#6e8aaa; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.64rem; line-height:1.7; text-align:center; padding:2rem 1rem; border:1px dashed rgba(112,168,228,.2); border-radius:.7rem; background:rgba(8,25,48,.4); }
505
+ .agent-preview-empty b { color:#9fd4ff; }
506
+ .agent-preview-empty code { background:rgba(84,183,255,.12); padding:.1em .3em; border-radius:.3em; }
507
+ .agent-preview-hint { color:#4d6378; font-size:.6rem; margin-top:.6rem; }
508
+ .agent-preview-frame { flex:1 1 auto; width:100%; min-height:420px; border:1px solid rgba(112,168,228,.2); border-radius:.7rem; background:#fff; }
509
+ .agent-preview-note { color:#4d6378; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; text-align:center; }
510
+ .agent-preview-note a { color:#6fcaff; }
511
+
512
+ .agent-side-actions { display:inline-flex; gap:.3rem; margin-left:auto; }
513
+ .agent-side-action { padding:.18rem .5rem; border:1px solid rgba(112,168,228,.28); border-radius:.4rem; color:#8fb8e4; background:rgba(84,183,255,.08); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.54rem; cursor:pointer; transition:border-color .12s, background .12s, color .12s; }
514
+ .agent-side-action:hover { border-color:rgba(84,183,255,.6); color:#bfe9ff; background:rgba(84,183,255,.16); }
515
+
516
+ .agent-markdown { white-space:normal; overflow-wrap:break-word; font-family:system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; font-size:.85rem; line-height:1.72; color:#dcecff; }
517
+ .agent-markdown > :first-child { margin-top:0; }
518
+ .agent-markdown > :last-child { margin-bottom:0; }
519
+ .agent-markdown h1, .agent-markdown h2, .agent-markdown h3, .agent-markdown h4 { margin:1.1em 0 .5em; color:#eef8ff; line-height:1.3; letter-spacing:-.02em; }
520
+ .agent-markdown h1 { font-size:1.28rem; } .agent-markdown h2 { font-size:1.12rem; } .agent-markdown h3 { font-size:1rem; } .agent-markdown h4 { font-size:.92rem; }
521
+ .agent-markdown p { margin:.5em 0; }
522
+ .agent-markdown a { color:#6fcaff; text-decoration:none; border-bottom:1px solid rgba(111,202,255,.35); }
523
+ .agent-markdown a:hover { color:#bfe9ff; }
524
+ .agent-markdown ul, .agent-markdown ol { margin:.5em 0; padding-left:1.4em; }
525
+ .agent-markdown li { margin:.2em 0; }
526
+ .agent-markdown strong { color:#fff; font-weight:700; }
527
+ .agent-markdown em { color:#cfdfff; }
528
+ .agent-markdown blockquote { margin:.6em 0; padding:.25em .9em; border-left:3px solid #54b7ff; color:#8fa5c0; background:rgba(84,183,255,.06); border-radius:0 .5rem .5rem 0; }
529
+ .agent-markdown code { font-family:"Cascadia Code", ui-monospace, monospace; font-size:.8em; padding:.15em .35em; border-radius:.3em; background:rgba(84,183,255,.12); color:#9fd4ff; }
530
+ .agent-markdown pre { margin:.7em 0; padding:.8em .9em; overflow:auto; border:1px solid rgba(112,168,228,.18); border-radius:.6rem; background:rgba(0,0,0,.35); }
531
+ .agent-markdown pre code { padding:0; background:none; font-size:.78rem; color:#e8f2ff; }
532
+ .agent-markdown pre code.hljs { display:block; background:transparent; }
533
+ .agent-markdown table { width:100%; margin:.7em 0; border-collapse:collapse; font-size:.8rem; }
534
+ .agent-markdown th, .agent-markdown td { padding:.4em .6em; border:1px solid rgba(112,168,228,.18); text-align:left; }
535
+ .agent-markdown th { background:rgba(84,183,255,.08); color:#bfe9ff; }
536
+ .agent-markdown hr { margin:1em 0; border:0; height:1px; background:rgba(112,168,228,.15); }
537
+ .agent-markdown .hljs { display:block; background:transparent; color:#e8f2ff; }
538
+ .agent-markdown .hljs-keyword, .agent-markdown .hljs-selector-tag, .agent-markdown .hljs-meta .hljs-keyword { color:#c792ea; }
539
+ .agent-markdown .hljs-string, .agent-markdown .hljs-attr, .agent-markdown .hljs-regexp, .agent-markdown .hljs-template-string { color:#7fe0a8; }
540
+ .agent-markdown .hljs-number, .agent-markdown .hljs-literal, .agent-markdown .hljs-symbol, .agent-markdown .hljs-bullet, .agent-markdown .hljs-params { color:#e2a76f; }
541
+ .agent-markdown .hljs-comment, .agent-markdown .hljs-quote { color:#6b85a3; font-style:italic; }
542
+ .agent-markdown .hljs-title, .agent-markdown .hljs-title.function_, .agent-markdown .hljs-function .hljs-title, .agent-markdown .hljs-section { color:#82c6ff; }
543
+ .agent-markdown .hljs-built_in, .agent-markdown .hljs-selector-class, .agent-markdown .hljs-selector-id { color:#e5c07b; }
544
+ .agent-markdown .hljs-tag, .agent-markdown .hljs-name, .agent-markdown .hljs-variable, .agent-markdown .hljs-template-variable { color:#f18ac6; }
545
+ .agent-markdown .hljs-meta, .agent-markdown .hljs-doctag { color:#56b6c2; }
546
+
547
+ /* ── Two-pane split diff (edit old_string / new_string) ───────────────── */
548
+ .agent-split { display:flex; flex-direction:column; border-top:1px solid rgba(112,168,228,.12); background:rgba(0,0,0,.28); overflow:hidden; }
549
+ .agent-split-head { display:flex; align-items:center; gap:.5rem; padding:.45rem .7rem; border-bottom:1px solid rgba(112,168,228,.12); background:linear-gradient(180deg, rgba(16,38,70,.5), rgba(8,20,42,.55)); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; letter-spacing:.06em; text-transform:uppercase; }
550
+ .agent-split-head-left { flex:1; color:#fda4af; }
551
+ .agent-split-head-right { flex:1; color:#6df0bb; text-align:right; }
552
+ .split-badge { display:inline-block; padding:.05rem .35rem; border-radius:.3rem; font-size:.52rem; font-weight:800; letter-spacing:.08em; vertical-align:middle; margin:0 .25rem; }
553
+ .split-badge.del { color:#fecdd3; background:rgba(244,63,94,.22); border:1px solid rgba(244,63,94,.35); }
554
+ .split-badge.add { color:#a7f3d0; background:rgba(16,185,129,.22); border:1px solid rgba(16,185,129,.35); }
555
+ .agent-split-grid { display:grid; grid-template-columns:1fr 1fr; min-height:0; max-height:420px; }
556
+ .agent-split-pane { position:relative; min-width:0; overflow:auto; background:rgba(0,0,0,.18); scrollbar-width:thin; scrollbar-color:rgba(112,168,228,.3) transparent; }
557
+ .agent-split-pane.pane-left { border-right:1px solid rgba(112,168,228,.12); }
558
+ .agent-split-pane .agent-copy { position:sticky; top:.4rem; float:right; margin:.4rem .4rem 0 0; z-index:3; }
559
+ .split-pane-label { position:sticky; top:0; z-index:2; padding:.28rem .6rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.52rem; letter-spacing:.1em; text-transform:uppercase; backdrop-filter:blur(8px); }
560
+ .pane-left .split-pane-label { color:#fda4af; background:rgba(244,63,94,.1); border-bottom:1px solid rgba(244,63,94,.18); }
561
+ .pane-right .split-pane-label { color:#6df0bb; background:rgba(16,185,129,.1); border-bottom:1px solid rgba(16,185,129,.18); }
562
+ .split-lines { padding:.5rem 0 .6rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.7rem; line-height:1.65; }
563
+ .split-line { display:flex; gap:.35rem; padding:.02rem .5rem; white-space:pre-wrap; word-break:break-word; }
564
+ .split-line.del { color:#fecdd3; background:rgba(244,63,94,.14); }
565
+ .split-line.add { color:#a7f3d0; background:rgba(16,185,129,.14); }
566
+ .split-line.context { color:#cfe3fb; }
567
+ .split-line.hunk { color:#67c8ff; background:rgba(84,183,255,.08); font-size:.62rem; letter-spacing:.02em; border-top:1px dashed rgba(84,183,255,.22); border-bottom:1px dashed rgba(84,183,255,.22); margin:.25rem 0; padding:.2rem .5rem; }
568
+ .split-line.empty { background:rgba(112,168,228,.04); min-height:1.15em; }
569
+ .split-num { flex:0 0 2.2rem; text-align:right; color:#3e5573; font-size:.62rem; user-select:none; }
570
+ .split-marker { flex:0 0 1ch; text-align:center; opacity:.7; }
571
+ .split-line.del .split-marker { color:#fb7185; }
572
+ .split-line.add .split-marker { color:#34d399; }
573
+ .split-text { flex:1 1 auto; min-width:0; }
574
+ .split-text .hljs { background:transparent; }
575
+ .split-hunk { opacity:.9; }
576
+ @media (max-width:760px) { .agent-split-grid { grid-template-columns:1fr; max-height:none; } .agent-split-pane.pane-left { border-right:0; border-bottom:1px solid rgba(112,168,228,.12); } .agent-split-pane { max-height:260px; } }
577
+
578
+ @media (max-width:1100px) {
579
+ .agent-side { flex-basis:320px; }
580
+ .agent-bubble { max-width:100%; }
581
+ }
582
+
583
+ @media (max-width:1024px) {
584
+ .agent-side { position:fixed; top:0; right:0; bottom:0; z-index:50; width:min(340px, 88vw); border-left:1px solid rgba(112,168,228,.2); background:linear-gradient(180deg, rgba(10,28,55,.98), rgba(6,15,34,.98)); box-shadow:-18px 0 60px rgba(0,0,0,.5); backdrop-filter:blur(22px) saturate(140%); -webkit-backdrop-filter:blur(22px) saturate(140%); transform:translateX(100%); transition:transform .24s cubic-bezier(.22,1,.36,1); }
585
+ .agent-side.open { transform:translateX(0); }
586
+ .agent-side-toggle { display:grid; }
587
+ .agent-main { padding-right:1.4rem; }
588
+
589
+ .agent-shell.agent-side-on > .agent-workspace { z-index:60; }
590
+ .agent-shell.agent-side-on > .agent-workspace .agent-side { top:3.8rem; height:calc(100dvh - 3.8rem); }
591
+ .agent-shell.agent-side-on > .agent-header { z-index:63; }
592
+ }
593
+
594
+ @media (max-width:860px) {
595
+ .agent-header-inner, .agent-workspace, .agent-error, .agent-notice, .agent-footer-inner, .agent-footer-bar { width:100%; max-width:none; }
596
+ .agent-header-inner { padding:.6rem .9rem; }
597
+ .agent-workspace { padding:0; }
598
+ .agent-main { padding:1.2rem .9rem; }
599
+ .agent-brand-sub, .agent-status { display:none; }
600
+ .agent-select { max-width:150px; }
601
+ .agent-select-label { display:none; }
602
+ .agent-footer-inner, .agent-footer-bar { padding:.75rem .9rem; }
603
+ .agent-footer-bar { padding-bottom:.2rem; }
604
+ .agent-footer-hint { display:none; }
605
+ .agent-modes { flex-wrap:wrap; }
606
+ .agent-mode { padding:.4rem .55rem; font-size:.58rem; }
607
+ }
608
+
609
+ @media (max-width:640px) {
610
+ .agent-main { padding:1rem .75rem; }
611
+ .agent-msg { max-width:100%; }
612
+ .agent-bubble { font-size:.82rem; padding:.65rem .8rem; }
613
+ .agent-row-user .agent-bubble, .agent-row-agent .agent-bubble { max-width:100%; }
614
+ .agent-tool-head { padding:.45rem .65rem; font-size:.66rem; }
615
+ .agent-badge-head { padding:.4rem .65rem; font-size:.66rem; }
616
+ .agent-list { gap:.8rem; }
617
+ .agent-hero { margin:2vh auto 0; padding:1.5rem 1rem; }
618
+ .agent-hero h2 { font-size:1.25rem; }
619
+ .agent-footer-bar { gap:.45rem; }
620
+ .agent-footer-inner { gap:.5rem; }
621
+ .agent-input { font-size:.8rem; }
622
+ .agent-send { padding:.65rem .9rem; font-size:.76rem; }
623
+ .agent-team-toggle, .agent-enhance-toggle { padding:.36rem .55rem; font-size:.56rem; }
624
+ .agent-workspace-btn { padding:.36rem .5rem; font-size:.72rem; }
625
+ .agent-enhance, .agent-suggest { bottom:3.9rem; width:calc(100vw - 16px); }
626
+ .agent-toast { right:.9rem; top:3.6rem; }
627
+ .agent-scroll-down { right:1rem; bottom:6rem; }
628
+ }
629
+
630
+ @media (max-width:480px) {
631
+ .agent-header-inner { padding:.5rem .7rem; }
632
+ .agent-brand-badge { width:1.9rem; height:1.9rem; }
633
+ .agent-brand-name { font-size:.68rem; }
634
+ .agent-brand-text { display:none; }
635
+ .agent-clear { padding:.45rem .6rem; font-size:.62rem; }
636
+ .agent-settings-btn, .agent-side-toggle { width:1.9rem; height:1.9rem; font-size:.8rem; }
637
+ .agent-settings { width:100vw; }
638
+ .agent-side { width:88vw; }
639
+ .agent-modes { width:100%; }
640
+ .agent-mode { flex:1; text-align:center; }
641
+ .agent-team-toggle, .agent-enhance-toggle { flex:1; justify-content:center; }
642
+ .agent-workspace-btn { flex:1; justify-content:center; }
643
+ .agent-footer-bar { display:flex; }
644
+ .agent-footer-inner { flex-wrap:nowrap; }
645
+ .agent-hero-chips { flex-direction:column; width:100%; }
646
+ .agent-hero-chip { width:100%; text-align:center; }
647
+ }`;
648
+
649
+ export interface ExplorerOptions {
650
+ endpoint?: string;
651
+ title?: string;
652
+ appName?: string;
653
+ sdl?: string;
654
+ introspection?: boolean;
655
+ }
656
+
657
+ export function getExplorerHtml(opts: ExplorerOptions = {}): string {
658
+ const endpoint = opts.endpoint ?? '/graphql';
659
+ const title = opts.title ?? 'BhooAI Nexus — GraphQL Sandbox';
660
+ const appName = opts.appName ?? 'backend';
661
+ const introspection = opts.introspection !== false;
662
+ const sdlPreview = opts.sdl ? opts.sdl.slice(0, 4000).replace(/`/g, '\\`').replace(/\$/g, '\\$') : '';
663
+ const rawSdl = opts.sdl ?? '';
664
+ const operations = extractOperations(rawSdl);
665
+ const defaultQuery = buildDefaultQuery(operations);
666
+
667
+ // CDN versions pinned to avoid breaking changes
668
+ const CDN = {
669
+ graphiqlCss: 'https://unpkg.com/graphiql@3.6.0/graphiql.min.css',
670
+ graphiqlJs: 'https://unpkg.com/graphiql@3.6.0/graphiql.min.js',
671
+ hljsCss: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/atom-one-dark.min.css',
672
+ hljsJs: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js',
673
+ react: 'https://unpkg.com/react@18/umd/react.production.min.js',
674
+ reactDom: 'https://unpkg.com/react-dom@18/umd/react-dom.production.min.js',
675
+ graphqlWs: 'https://unpkg.com/graphql-ws@5/umd/graphql-ws.min.js',
676
+ };
677
+
678
+ return `<!doctype html>
679
+ <html lang="en">
680
+ <head>
681
+ <meta charset="utf-8" />
682
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
683
+ <title>${escapeHtml(title)}</title>
684
+ <link rel="stylesheet" href="${CDN.graphiqlCss}" />
685
+ <link rel="stylesheet" href="${CDN.hljsCss}" />
686
+ <style>
687
+ :root{ color-scheme: dark light; }
688
+ *{box-sizing:border-box}
689
+ html,body{height:100%;margin:0;padding:0}
690
+ /* ── AURORA GLASS THEME — copied verbatim from bhooai-agent AGENT_CSS ── */
691
+ ${AURORA_CSS}
692
+ /* ── full-width overrides (explorer is edge-to-edge, not centered 1400px) ── */
693
+ .agent-header-inner, .agent-workspace { width:100%; max-width:none; margin:0; padding-inline:1rem; }
694
+ .agent-header::after { left:1rem; right:1rem; }
695
+ .agent-main { padding:.8rem 1rem 1rem; }
696
+ .agent-side { flex:0 0 380px; padding:1rem .8rem 1rem 1rem; }
697
+ @media (max-width: 960px){ .agent-side { display:none; } }
698
+ /* ── GraphiQL aurora theming (override its light-mode CDN defaults) ──
699
+ GraphiQL's CDN only applies its dark palette via body.graphiql-dark or
700
+ prefers-color-scheme — without that class everything renders light.
701
+ Our overrides target BOTH body classes AND the raw selectors so they
702
+ win the cascade over the CDN defaults for .graphiql-main, sidebar,
703
+ editors, toolbar, sessions, footer and doc-explorer. */
704
+ body.graphiql-dark .graphiql-container, body.graphiql-light .graphiql-container,
705
+ .graphiql-container,
706
+ .graphiql-container .CodeMirror-info,
707
+ .graphiql-container .CodeMirror-lint-tooltip,
708
+ .graphiql-dialog,
709
+ .graphiql-dialog-overlay,
710
+ .graphiql-tooltip {
711
+ /* GraphiQL HSL tokens → aurora palette */
712
+ --color-primary: 205, 100%, 66%; /* #54b7ff blue */
713
+ --color-secondary: 258, 100%, 77%; /* #9f7bff violet */
714
+ --color-tertiary: 188, 100%, 52%;
715
+ --color-info: 208, 100%, 56%;
716
+ --color-success: 158, 70%, 55%; /* #5ef0b3 mint */
717
+ --color-warning: 41, 100%, 63%;
718
+ --color-error: 352, 96%, 68%; /* #fb7185 rose */
719
+ --color-neutral: 215, 45%, 74%;
720
+ --color-base: 220, 60%, 6%; /* dark base: #040b18 */
721
+ --alpha-secondary: .85;
722
+ --alpha-tertiary: .55;
723
+ --alpha-background-heavy: .16;
724
+ --alpha-background-medium: .09;
725
+ --alpha-background-light: .05;
726
+ --font-family: ui-monospace, SFMono-Regular, Consolas, monospace;
727
+ --font-family-mono: ui-monospace, SFMono-Regular, Consolas, monospace;
728
+ --editor-background: rgba(8, 25, 48, .55);
729
+ --popover-box-shadow: 0 24px 70px rgba(0,0,0,.5), 0 0 30px rgba(84,183,255,.14);
730
+ --popover-border: 1px solid rgba(112,168,228,.24);
731
+ --session-header-height: 44px;
732
+ --sidebar-width: 48px;
733
+ --toolbar-width: 36px;
734
+ }
735
+ /* main editor surface: glass, translucent so aurora shows through */
736
+ .graphiql-container { background: transparent; height:100%; }
737
+ .graphiql-container .graphiql-main, .graphiql-container .graphiql-sessions { background: transparent; }
738
+ /* .graphiql-editors — the big white card holding query editor + result pane */
739
+ .graphiql-container .graphiql-editors {
740
+ background: linear-gradient(160deg, rgba(16,38,70,.55), rgba(8,20,42,.62));
741
+ border: 1px solid rgba(112,168,228,.18);
742
+ box-shadow: inset 0 1px rgba(255,255,255,.05), 0 18px 50px rgba(0,0,0,.28);
743
+ backdrop-filter: blur(18px) saturate(135%); -webkit-backdrop-filter: blur(18px) saturate(135%);
744
+ border-radius: .9rem;
745
+ }
746
+ /* query editor section (toolbar + codemirror) */
747
+ .graphiql-container .graphiql-query-editor { border-bottom-color: rgba(112,168,228,.14); background: transparent; }
748
+ /* left sidebar (icon rail: docs/history/plugins) */
749
+ .graphiql-container .graphiql-sidebar { background: linear-gradient(180deg, rgba(9,24,48,.6), rgba(4,14,29,.4)); border-right: 1px solid rgba(112,168,228,.14); }
750
+ .graphiql-container .graphiql-sidebar button { color: #6e8aaa; border-radius: .5rem; transition: color .14s, background .14s; }
751
+ .graphiql-container .graphiql-sidebar button:hover { color: #dcecff; background: rgba(84,183,255,.12); }
752
+ .graphiql-container .graphiql-sidebar button.active { color: #8ed6ff; background: rgba(84,183,255,.16); box-shadow: 0 0 12px rgba(84,183,255,.25); }
753
+ .graphiql-container .graphiql-sidebar button > svg { fill: currentColor; }
754
+ /* vertical toolbar next to query editor */
755
+ .graphiql-container .graphiql-toolbar { background: linear-gradient(180deg, rgba(9,24,48,.5), rgba(4,14,29,.3)); border-right: 1px solid rgba(112,168,228,.12); }
756
+ .graphiql-container .graphiql-toolbar button { color: #6e8aaa; border-radius: .45rem; }
757
+ .graphiql-container .graphiql-toolbar button:hover { color: #dcecff; background: rgba(84,183,255,.12); }
758
+ .graphiql-container .graphiql-toolbar button.active { color: #8ed6ff; background: rgba(84,183,255,.16); }
759
+ .graphiql-container .graphiql-toolbar-icon { color: currentColor; }
760
+ /* editor-tools row (Variables / Headers / Prettify toggles + drag handle) */
761
+ .graphiql-container .graphiql-editor-tools { background: rgba(4,14,29,.35); border-top: 1px solid rgba(112,168,228,.1); }
762
+ .graphiql-container .graphiql-editor-tools button { color: #6e8aaa; }
763
+ .graphiql-container .graphiql-editor-tools button:hover { color: #dcecff; background: rgba(84,183,255,.1); border-radius:.4rem; }
764
+ .graphiql-container .graphiql-editor-tools button.active { color: #8ed6ff; border-bottom-color: #54b7ff; }
765
+ /* session header (tabs + execute) */
766
+ .graphiql-container .graphiql-session-header { border-bottom:1px solid rgba(112,168,228,.14); background:linear-gradient(180deg, rgba(9,24,48,.55), rgba(4,14,29,.35)); backdrop-filter:blur(14px); -webkit-backdrop-filter:blur(14px); }
767
+ .graphiql-container .graphiql-session-header-right button, .graphiql-container .graphiql-toolbar button { color:#9fb3d0; }
768
+ .graphiql-container .graphiql-session-header-right button:hover, .graphiql-container .graphiql-toolbar button:hover { color:#dcecff; background:rgba(84,183,255,.14); }
769
+ /* response footer */
770
+ .graphiql-container .graphiql-footer { border-top-color: rgba(112,168,228,.14); background: rgba(4,14,29,.35); }
771
+ /* doc explorer panel (opens from sidebar) */
772
+ .graphiql-container .graphiql-doc-explorer { background: linear-gradient(160deg, rgba(16,38,70,.6), rgba(8,20,42,.66)); backdrop-filter: blur(18px) saturate(135%); -webkit-backdrop-filter: blur(18px) saturate(135%); border-left: 1px solid rgba(112,168,228,.14); }
773
+ .graphiql-container .graphiql-doc-explorer-header, .graphiql-container .graphiql-doc-explorer-section-title { color: #9fd4ff; border-color: rgba(112,168,228,.14); background: transparent; }
774
+ .graphiql-container .graphiql-doc-explorer-section-content, .graphiql-container .graphiql-doc-explorer-item { color: #cfe3fb; background: transparent; }
775
+ .graphiql-container .graphiql-doc-explorer-item:hover { background: rgba(84,183,255,.1); }
776
+ .graphiql-container .graphiql-doc-explorer-field-name { color: #8ed6ff; }
777
+ .graphiql-container .graphiql-doc-explorer-type-name { color: #c4b5fd; }
778
+ .graphiql-container .graphiql-doc-explorer-argument-name { color: #7fe0a8; }
779
+ .graphiql-container .graphiql-doc-explorer-search-input, .graphiql-container .graphiql-doc-explorer-search input[type=text], .graphiql-container .graphiql-doc-explorer-search input { background: rgba(255,255,255,.06); border:1px solid rgba(112,168,228,.22); color:#e8f2ff; }
780
+ .graphiql-container .graphiql-doc-explorer-back { color: #9fd4ff; }
781
+ /* history panel inside graphiql */
782
+ .graphiql-container .graphiql-history-item { color:#cfe3fb; border-color: rgba(112,168,228,.14); background: rgba(8,25,48,.55); }
783
+ .graphiql-container .graphiql-history-item:hover { background: rgba(84,183,255,.1); }
784
+ .graphiql-container .graphiql-history-header { color: #5f7b9c; border-color: rgba(112,168,228,.14); }
785
+ /* dropdown menus + buttons */
786
+ .graphiql-container .graphiql-dropdown-content { background: linear-gradient(160deg, rgba(12,34,64,.97), rgba(6,16,36,.98)); border:1px solid rgba(99,189,255,.3); box-shadow: 0 16px 40px rgba(0,0,0,.5); }
787
+ .graphiql-container .graphiql-dropdown-item { color: #cfe3fb; }
788
+ .graphiql-container .graphiql-dropdown-item:hover { background: rgba(84,183,255,.15); color:#fff; }
789
+ .graphiql-container .graphiql-button { border-color: rgba(112,168,228,.24); color: #9fd4ff; background: rgba(84,183,255,.1); }
790
+ .graphiql-container .graphiql-button:hover { border-color: rgba(84,183,255,.55); color:#fff; background: rgba(84,183,255,.18); }
791
+ /* result pane */
792
+ .graphiql-container .graphiql-response-result, .graphiql-container pre.result-window, .graphiql-container .result-window {
793
+ font-family:var(--font-family-mono, ui-monospace, monospace);
794
+ }
795
+ .graphiql-container .result-window, .graphiql-container .result-window * { background: transparent; }
796
+ /* docs sidebar inside GraphiQL */
797
+ .graphiql-container .graphiql-docs { background:linear-gradient(160deg, rgba(16,38,70,.6), rgba(8,20,42,.66)); backdrop-filter:blur(18px) saturate(135%); -webkit-backdrop-filter:blur(18px) saturate(135%); color:#dcecff; }
798
+ .graphiql-container .graphiql-docs .graphiql-docs-description, .graphiql-container .graphiql-docs-section, .graphiql-container .graphiql-docs-category-item { color:#cfe3fb; background:transparent; border-color:rgba(112,168,228,.14); }
799
+ .graphiql-container .graphiql-docs .graphiql-docs-category-item:hover { background:rgba(84,183,255,.1); }
800
+ .graphiql-container .graphiql-docs .graphiql-docs-type { color:#8ed6ff; }
801
+ .graphiql-container .graphiql-docs .doc-category-item .field-name { color:#8ed6ff; }
802
+ .graphiql-container .graphiql-docs .doc-category-item .type-name { color:#c4b5fd; }
803
+ /* editor panes + CodeMirror */
804
+ .graphiql-container .CodeMirror, .graphiql-container .result-window, .graphiql-container .graphiql-editor, .graphiql-container pre.CodeMirror-code { background: rgba(8,25,48,.35); }
805
+ .graphiql-container .cm-s-graphiql { background: transparent !important; color:#cfe3fb; }
806
+ .graphiql-container .cm-s-graphiql .CodeMirror-gutters { background:rgba(4,14,29,.4); border-right:1px solid rgba(112,168,228,.12); }
807
+ .graphiql-container .cm-s-graphiql .CodeMirror-linenumber { color:#45597a; }
808
+ .graphiql-container .cm-s-graphiql .CodeMirror-cursor { border-left:2px solid #54b7ff; }
809
+ .graphiql-container .cm-s-graphiql .CodeMirror-selected, .graphiql-container .cm-s-graphiql .CodeMirror-focused .CodeMirror-selected { background:rgba(84,183,255,.22); }
810
+ .graphiql-container .cm-s-graphiql .CodeMirror-matchingbracket { color:#5ef0b3 !important; border-bottom:1px solid #5ef0b3; }
811
+ .graphiql-container .cm-s-graphiql .CodeMirror-activeline-background { background:rgba(84,183,255,.07); }
812
+ /* CodeMirror syntax colors → aurora (match hljs theme) */
813
+ .graphiql-container .cm-s-graphiql .cm-keyword { color:#c792ea; }
814
+ .graphiql-container .cm-s-graphiql .cm-def { color:#82c6ff; }
815
+ .graphiql-container .cm-s-graphiql .cm-property, .graphiql-container .cm-s-graphiql .cm-variable { color:#e8f2ff; }
816
+ .graphiql-container .cm-s-graphiql .cm-variable-2 { color:#7fe0a8; }
817
+ .graphiql-container .cm-s-graphiql .cm-punctuation, .graphiql-container .cm-s-graphiql .cm-operator { color:#8fa8c8; }
818
+ .graphiql-container .cm-s-graphiql .cm-string, .graphiql-container .cm-s-graphiql .cm-string-2 { color:#7fe0a8; }
819
+ .graphiql-container .cm-s-graphiql .cm-number, .graphiql-container .cm-s-graphiql .cm-atom { color:#e2a76f; }
820
+ .graphiql-container .cm-s-graphiql .cm-comment { color:#6b85a3; font-style:italic; }
821
+ .graphiql-container .cm-s-graphiql .cm-attribute { color:#e5c07b; }
822
+ .graphiql-container .cm-s-graphiql .cm-qualifier, .graphiql-container .cm-s-graphiql .cm-builtin { color:#56b6c2; }
823
+ /* toolbar / tabs / buttons */
824
+ .graphiql-container .graphiql-tab, .graphiql-container .graphiql-tab-button, .graphiql-container .graphiql-tab.active { border-color:rgba(112,168,228,.18); background:rgba(8,25,48,.5); color:#9fb3d0; }
825
+ .graphiql-container .graphiql-tab.active { color:#8ed6ff; border-bottom-color:rgba(84,183,255,.6); background:rgba(84,183,255,.1); }
826
+ .graphiql-container .graphiql-tab:hover { color:#dcecff; }
827
+ .graphiql-container button.graphiql-toolbar-button, .graphiql-container .graphiql-toolbar { background:transparent; }
828
+ .graphiql-container .graphiql-execute-button { background:linear-gradient(135deg, rgba(38,130,225,.75), rgba(90,67,183,.65)) !important; border:1px solid rgba(84,183,255,.55); box-shadow:0 0 14px rgba(84,183,255,.35); }
829
+ .graphiql-container .graphiql-execute-button:hover { filter:brightness(1.15); }
830
+ /* dialogs + tooltips + autocomplete */
831
+ .graphiql-dialog, .graphiql-dialog-overlay { background:rgba(2,8,20,.62); }
832
+ .graphiql-dialog-container { background:linear-gradient(160deg, rgba(23,55,96,.97), rgba(14,32,62,.98)) !important; border:1px solid rgba(99,189,255,.4); box-shadow:0 30px 90px rgba(0,0,0,.55); backdrop-filter:blur(22px); }
833
+ .graphiql-dialog-close { display:grid; place-items:center; width:1.9rem; height:1.9rem; border:1px solid rgba(251,113,133,.55); border-radius:.55rem; background:linear-gradient(135deg, rgba(244,63,94,.85), rgba(159,18,57,.8)); color:#fff !important; cursor:pointer; box-shadow:0 6px 18px rgba(244,63,94,.4); transition:filter .14s, transform .14s, box-shadow .14s; }
834
+ .graphiql-dialog-close:hover { filter:brightness(1.15); transform:rotate(90deg); box-shadow:0 8px 22px rgba(244,63,94,.55); }
835
+ .graphiql-dialog-close svg { fill:none; stroke:currentColor; stroke-width:2; }
836
+ .graphiql-dialog-title { color:#bfe9ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.7rem; font-weight:800; letter-spacing:.12em; text-transform:uppercase; }
837
+ .graphiql-dialog-section-title { color:#bfe9ff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.62rem; font-weight:700; letter-spacing:.08em; text-transform:uppercase; }
838
+ .graphiql-container .CodeMirror-hints { background:linear-gradient(160deg, rgba(12,34,64,.97), rgba(6,16,36,.98)); border:1px solid rgba(99,189,255,.3); box-shadow:0 16px 40px rgba(0,0,0,.5); }
839
+ .graphiql-container .CodeMirror-hint { color:#cfe3fb; }
840
+ .graphiql-container .CodeMirror-hint-active { background:rgba(84,183,255,.22); color:#fff; }
841
+ .graphiql-tooltip { background:linear-gradient(160deg, rgba(10,28,55,.97), rgba(6,16,36,.98)); color:#dcecff; border:1px solid rgba(112,168,228,.28); border-radius:.45rem; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; font-weight:600; letter-spacing:.03em; line-height:1.4; padding:.35rem .6rem; box-shadow:0 12px 32px rgba(0,0,0,.4), inset 0 1px rgba(255,255,255,.06); backdrop-filter:blur(18px) saturate(140%); -webkit-backdrop-filter:blur(18px) saturate(140%); }
842
+ /* GraphiQL variables/editor inputs */
843
+ .graphiql-container input[type=text], .graphiql-container input[type=search], .graphiql-container textarea { background:rgba(255,255,255,.05); border-color:rgba(112,168,228,.24); color:#e8f2ff; }
844
+ .graphiql-container input:focus, .graphiql-container textarea:focus { border-color:rgba(84,183,255,.6); box-shadow:0 0 0 3px rgba(84,183,255,.14); }
845
+ /* light theme: GraphiQL back to light vars + light glass surfaces */
846
+ [data-theme="light"] .graphiql-container,
847
+ [data-theme="light"] .graphiql-container .CodeMirror-info,
848
+ [data-theme="light"] .graphiql-dialog,
849
+ [data-theme="light"] .graphiql-tooltip {
850
+ --color-base: 216, 40%, 98%;
851
+ --color-neutral: 219, 28%, 32%;
852
+ --alpha-background-light: .6;
853
+ --editor-background: rgba(255,255,255,.8);
854
+ --popover-box-shadow: 0 14px 40px rgba(20,50,100,.14);
855
+ --popover-border: 1px solid rgba(60,110,180,.18);
856
+ }
857
+ [data-theme="light"] .graphiql-tooltip { background:linear-gradient(160deg, rgba(255,255,255,.98), rgba(238,245,255,.98)); color:#0b1220; border-color:rgba(60,110,180,.24); box-shadow:0 12px 32px rgba(20,50,100,.16), inset 0 1px rgba(255,255,255,.7); }
858
+ [data-theme="light"] .graphiql-dialog-close { color:#fff !important; border-color:rgba(225,29,72,.55); background:linear-gradient(135deg, rgba(225,29,72,.85), rgba(159,18,57,.8)); box-shadow:0 6px 18px rgba(225,29,72,.35); }
859
+ [data-theme="light"] .graphiql-dialog-close:hover { filter:brightness(1.12); }
860
+ [data-theme="light"] .graphiql-dialog-title, [data-theme="light"] .graphiql-dialog-section-title { color:#1d6fd0; }
861
+ [data-theme="light"] .graphiql-container .graphiql-editors { background: rgba(255,255,255,.72); border-color: rgba(60,110,180,.16); box-shadow: inset 0 1px rgba(255,255,255,.6), 0 18px 50px rgba(20,50,100,.1); }
862
+ [data-theme="light"] .graphiql-container .graphiql-sidebar { background: rgba(255,255,255,.6); border-right-color: rgba(60,110,180,.14); }
863
+ [data-theme="light"] .graphiql-container .graphiql-toolbar { background: rgba(255,255,255,.55); border-right-color: rgba(60,110,180,.12); }
864
+ [data-theme="light"] .graphiql-container .graphiql-sidebar button, [data-theme="light"] .graphiql-container .graphiql-toolbar button, [data-theme="light"] .graphiql-container .graphiql-editor-tools button { color:#5a6b84; }
865
+ [data-theme="light"] .graphiql-container .graphiql-sidebar button.active, [data-theme="light"] .graphiql-container .graphiql-toolbar button.active { color:#1d6fd0; background:rgba(29,111,208,.14); }
866
+ [data-theme="light"] .graphiql-container .graphiql-editor-tools { background: rgba(240,246,255,.7); border-top-color: rgba(60,110,180,.12); }
867
+ [data-theme="light"] .graphiql-container .graphiql-session-header { background:linear-gradient(180deg, rgba(255,255,255,.85), rgba(235,242,252,.7)); border-bottom-color:rgba(60,110,180,.14); }
868
+ [data-theme="light"] .graphiql-container .graphiql-doc-explorer, [data-theme="light"] .graphiql-container .graphiql-docs { background:rgba(255,255,255,.82); color:#16233c; border-left-color:rgba(60,110,180,.14); }
869
+ [data-theme="light"] .graphiql-container .graphiql-doc-explorer-header, [data-theme="light"] .graphiql-container .graphiql-doc-explorer-section-title { color:#1d6fd0; }
870
+ [data-theme="light"] .graphiql-container .graphiql-doc-explorer-section-content, [data-theme="light"] .graphiql-container .graphiql-doc-explorer-item { color:#3a4c68; }
871
+ [data-theme="light"] .graphiql-container .graphiql-history-item { color:#3a4c68; background:rgba(255,255,255,.7); border-color:rgba(60,110,180,.12); }
872
+ [data-theme="light"] .graphiql-container .graphiql-footer { background: rgba(240,246,255,.7); border-top-color:rgba(60,110,180,.12); }
873
+ [data-theme="light"] .graphiql-container .graphiql-docs .graphiql-docs-section, [data-theme="light"] .graphiql-container .graphiql-docs .graphiql-docs-description { color:#3a4c68; }
874
+ [data-theme="light"] .graphiql-container .CodeMirror, [data-theme="light"] .graphiql-container pre.CodeMirror-code { background:rgba(255,255,255,.85); }
875
+ [data-theme="light"] .graphiql-container .cm-s-graphiql { color:#1c2a44; }
876
+ [data-theme="light"] .graphiql-container .cm-s-graphiql .CodeMirror-gutters { background:rgba(230,240,252,.9); border-right-color:rgba(60,110,180,.12); }
877
+ [data-theme="light"] .graphiql-container .cm-s-graphiql .CodeMirror-linenumber { color:#7a8db0; }
878
+ [data-theme="light"] .graphiql-container .graphiql-tab, [data-theme="light"] .graphiql-container .graphiql-tab.active { background:rgba(255,255,255,.8); color:#3a4c68; border-color:rgba(60,110,180,.14); }
879
+ [data-theme="light"] .graphiql-container .graphiql-tab.active { color:#1d6fd0; border-bottom-color:rgba(29,111,208,.6); }
880
+ [data-theme="light"] .graphiql-container input[type=text], [data-theme="light"] .graphiql-container textarea { background:rgba(255,255,255,.9); color:#16233c; border-color:rgba(60,110,180,.2); }
881
+ /* ── explorer-specific glass (reuses agent tokens) ── */
882
+ .graphiql-panel { display:flex; flex-direction:column; min-width:0; min-height:0; border:1px solid rgba(112,168,228,.18); border-radius:.9rem; background:linear-gradient(160deg, rgba(16,38,70,.45), rgba(8,20,42,.5)); box-shadow:inset 0 1px rgba(255,255,255,.05), 0 18px 50px rgba(0,0,0,.24); backdrop-filter:blur(18px) saturate(135%); -webkit-backdrop-filter:blur(18px) saturate(135%); overflow:hidden; animation:agent-rise .3s cubic-bezier(.22,1,.36,1) both; }
883
+ #graphiql{flex:1; min-height:0; min-width:0; overflow:hidden}
884
+ .graphiql-container{height:100% !important; width:100%; min-width:0; overflow:hidden}
885
+ .graphiql-container .graphiql-editors{min-width:0}
886
+ /* Hide GraphiQL/CodeMirror off-screen measurement nodes (left:-1000px) that
887
+ bleed over the sidebar and block the History toggle button. */
888
+ #graphiql [style*="left: -1000px"], #graphiql [style*="left:-1000px"],
889
+ #graphiql .CodeMirror-measure, #graphiql .CodeMirror-measure *{pointer-events:none !important}
890
+ #graphiql [style*="left: -1000px"], #graphiql [style*="left:-1000px"]{visibility:hidden !important}
891
+ .panel-head{padding:.6rem .85rem; font-size:.6rem; letter-spacing:.13em; text-transform:uppercase; color:#5f7b9c; border-bottom:1px solid rgba(112,168,228,.12); display:flex; justify-content:space-between; align-items:center; font-family:ui-monospace, SFMono-Regular, Consolas, monospace}
892
+ .ai-hint{font-size:.6rem; color:#5f7b9c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace}
893
+ .ops{padding:.6rem .7rem; display:flex; flex-direction:column; gap:.4rem}
894
+ .ops .op{padding:.5rem .65rem; border:1px solid rgba(112,168,228,.17); border-radius:.55rem; background:rgba(8,25,48,.6); box-shadow:inset 0 1px rgba(255,255,255,.04); cursor:pointer; display:flex; justify-content:space-between; align-items:center; gap:.5rem; transition:border-color .14s, background .14s, transform .14s; animation:agent-rise .25s cubic-bezier(.22,1,.36,1) both}
895
+ .ops .op:hover{border-color:rgba(84,183,255,.5); background:rgba(84,183,255,.1); transform:translateY(-1px)}
896
+ .ops .op b{font-size:.66rem; color:#dcecff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-weight:600}
897
+ .ops .op > span{font-size:.52rem; padding:.14rem .45rem; border-radius:999px; background:rgba(84,183,255,.15); color:#8ed6ff; border:1px solid rgba(84,183,255,.25); font-weight:700; letter-spacing:.06em; text-transform:uppercase; flex:0 0 auto}
898
+ .ops .op.mutation > span{background:rgba(243,110,184,.15); color:#fda4c7; border-color:rgba(243,110,184,.25)}
899
+ .history{padding:.5rem .7rem; border-top:1px solid rgba(112,168,228,.12); max-height:9rem; overflow:auto}
900
+ .history div{font-size:.6rem; padding:.35rem .5rem; border-radius:.45rem; cursor:pointer; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; color:#9fb3d0; font-family:ui-monospace, SFMono-Regular, Consolas, monospace}
901
+ .history div:hover{background:rgba(84,183,255,.1)}
902
+ .graphiql-history-clear{border:0; background:transparent; color:#5f7b9c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; cursor:pointer; padding:.1rem .3rem; border-radius:.35rem; transition:color .12s, background .12s}
903
+ .graphiql-history-clear:hover{color:#fda4af; background:rgba(244,63,94,.12)}
904
+ .panel-head-actions{display:inline-flex; align-items:center; gap:.25rem}
905
+ .graphiql-history-btn{border:1px solid rgba(112,168,228,.22); background:rgba(84,183,255,.08); color:#8fb8e4; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.56rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; cursor:pointer; padding:.12rem .4rem; border-radius:.4rem; transition:color .12s, border-color .12s, background .12s}
906
+ .graphiql-history-btn:hover{color:#bfe9ff; border-color:rgba(84,183,255,.55); background:rgba(84,183,255,.16)}
907
+ .graphiql-history-btn.active{color:#8ed6ff; border-color:rgba(84,183,255,.6); background:rgba(84,183,255,.2); box-shadow:0 0 8px rgba(84,183,255,.25)}
908
+ /* Type details */
909
+ .type-details{padding:0 .7rem .7rem; display:flex; flex-direction:column; gap:.5rem; min-width:0}
910
+ .type-details details{border:1px solid rgba(112,168,228,.17); border-radius:.55rem; background:rgba(8,25,48,.6); box-shadow:inset 0 1px rgba(255,255,255,.04); overflow:hidden; transition:border-color .14s, background .14s, transform .14s}
911
+ .type-details details:hover{border-color:rgba(84,183,255,.5); background:rgba(84,183,255,.1); transform:translateY(-1px)}
912
+ .type-details summary{cursor:pointer; padding:.5rem .65rem; list-style:none; display:flex; justify-content:space-between; align-items:center; gap:.6rem; font-size:.66rem; color:#dcecff; font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-weight:700; transition:background .14s}
913
+ .type-details summary::-webkit-details-marker{display:none}
914
+ .type-details summary:hover{background:rgba(84,183,255,.1)}
915
+ .type-details summary .type-name{min-width:0; display:inline-flex; align-items:center; gap:.45rem; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
916
+ .type-details summary .type-name b{overflow:hidden; text-overflow:ellipsis}
917
+ .type-details .type-icon{flex:0 0 auto; display:grid; place-items:center; width:1.25rem; height:1.25rem; border-radius:.4rem; font-size:.55rem; font-weight:800; letter-spacing:.04em; border:1px solid rgba(84,183,255,.35); background:linear-gradient(135deg, rgba(38,130,225,.3), rgba(90,67,183,.26)); color:#9fd4ff; box-shadow:0 0 10px rgba(84,183,255,.18)}
918
+ .type-details .type-icon.kind-input{color:#c4b5fd; border-color:rgba(139,92,246,.4); background:linear-gradient(135deg, rgba(124,58,237,.3), rgba(90,67,183,.26))}
919
+ .type-details .type-icon.kind-enum{color:#ffd479; border-color:rgba(245,158,11,.4); background:linear-gradient(135deg, rgba(245,158,11,.26), rgba(180,83,9,.2))}
920
+ .type-details .type-icon.kind-scalar{color:#6df0bb; border-color:rgba(52,211,153,.4); background:linear-gradient(135deg, rgba(16,185,129,.26), rgba(6,95,70,.2))}
921
+ .type-details .type-kind{flex:0 0 auto; font-size:.5rem; padding:.12rem .4rem; border-radius:999px; background:rgba(159,123,255,.15); color:#c4b5fd; border:1px solid rgba(139,92,246,.3); font-weight:800; letter-spacing:.08em; text-transform:uppercase}
922
+ .type-details .type-chevron{flex:0 0 auto; display:grid; place-items:center; width:1.1rem; height:1.1rem; border-radius:.35rem; color:#5f7b9c; font-size:.6rem; transition:transform .18s, color .14s, background .14s}
923
+ .type-details summary:hover .type-chevron{color:#9fd4ff; background:rgba(84,183,255,.14)}
924
+ .type-details details[open] .type-chevron{transform:rotate(90deg)}
925
+ .type-details .type-body{padding:.6rem .7rem .7rem .85rem; display:flex; flex-direction:column; gap:.5rem}
926
+ .type-details .type-desc{margin:0; font-size:.58rem; color:#5f7b9c; line-height:1.55; padding:.35rem .6rem; border-radius:.45rem; background:rgba(84,183,255,.05); border-left:2px solid rgba(84,183,255,.3)}
927
+ .type-details .type-subhead{font-size:.5rem; letter-spacing:.13em; text-transform:uppercase; color:#5f7b9c; font-weight:800; padding-left:.15rem}
928
+ .type-details .type-fields{display:flex; flex-direction:column; gap:.4rem; min-width:0}
929
+ .type-details .type-field{font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.6rem; padding:.34rem .55rem; border-radius:.45rem; background:rgba(8,25,48,.6); color:#dcecff; display:flex; justify-content:space-between; align-items:center; gap:.5rem; min-width:0; border:1px solid rgba(112,168,228,.17); box-shadow:inset 0 1px rgba(255,255,255,.04); transition:border-color .14s, transform .14s, background .14s}
930
+ .type-details .type-field:hover{border-color:rgba(84,183,255,.5); transform:translateY(-1px); background:rgba(84,183,255,.1)}
931
+ .type-details .type-field > span{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
932
+ .type-details .type-field code.hljs{display:inline; background:transparent; padding:0; color:#e8f2ff; white-space:nowrap}
933
+ .type-details .type-field b{color:#8ed6ff; font-weight:600}
934
+ .type-details .type-field .tok-arg{color:#ffd479}
935
+ .type-details .type-field .tok-type{color:#c4b5fd}
936
+ .type-details .type-field-arrow{flex:0 0 auto; display:inline-flex; align-items:center; gap:.28rem; font-size:.54rem; font-weight:800; letter-spacing:.06em; text-transform:uppercase; color:#9fd4ff; cursor:pointer; padding:.22rem .45rem; border-radius:.4rem; border:1px solid rgba(84,183,255,.35); background:rgba(84,183,255,.1); transition:border-color .12s, background .12s, color .12s, transform .12s}
937
+ .type-details .type-field-arrow:hover{color:#eaf7ff; border-color:rgba(84,183,255,.65); background:rgba(40,137,235,.24); transform:translateX(2px)}
938
+ .type-filter{margin:.45rem .7rem 0; padding:.42rem .6rem; border-radius:.5rem; border:1px solid rgba(112,168,228,.22); background:rgba(20,46,79,.32); color:#e5f4ff; font-size:.62rem; width:calc(100% - 1.4rem); outline:none; transition:border-color .14s, box-shadow .14s}
939
+ .type-filter::placeholder{color:#536c8c}
940
+ .type-filter:focus{border-color:rgba(84,183,255,.55); box-shadow:0 0 0 2px rgba(84,183,255,.15)}
941
+ /* FAB + chat popup (agent glass) */
942
+ .fab{position:fixed; right:1.25rem; bottom:1.25rem; width:3.4rem; height:3.4rem; border-radius:50%; border:1px solid rgba(84,183,255,.42); background:linear-gradient(135deg, rgba(38,130,225,.75), rgba(90,67,183,.65)); color:#fff; font-size:1.25rem; font-weight:800; cursor:pointer; box-shadow:0 0 24px rgba(58,149,255,.4), 0 10px 30px rgba(0,0,0,.4); display:grid; place-items:center; z-index:30; transition:transform .15s, filter .15s; animation:agent-rise .3s cubic-bezier(.22,1,.36,1) both}
943
+ .fab:hover{transform:translateY(-2px); filter:brightness(1.12)}
944
+ .fab:active{transform:scale(.94)}
945
+ .ai-popup{position:fixed; right:1.25rem; bottom:5.4rem; width:24rem; max-width:calc(100vw - 2rem); height:32rem; max-height:70vh; border:1px solid rgba(99,189,255,.28); border-radius:.9rem; background:linear-gradient(160deg, rgba(12,34,64,.96), rgba(6,16,36,.98)); box-shadow:inset 0 1px rgba(255,255,255,.06), 0 30px 90px rgba(0,0,0,.6), 0 0 40px rgba(84,183,255,.12); display:flex; flex-direction:column; overflow:hidden; z-index:30; backdrop-filter:blur(22px) saturate(140%); -webkit-backdrop-filter:blur(22px) saturate(140%); animation:agent-rise .25s cubic-bezier(.22,1,.36,1) both}
946
+ .ai-popup[hidden]{display:none !important}
947
+ .ai-popup-head{padding:.6rem .8rem; display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid rgba(112,168,228,.14); font-size:.62rem; letter-spacing:.12em; text-transform:uppercase; color:#5f7b9c; font-family:ui-monospace, SFMono-Regular, Consolas, monospace}
948
+ .ai-popup-head button{border:1px solid rgba(112,168,228,.24); background:rgba(84,183,255,.08); color:#9fd4ff; width:1.7rem; height:1.7rem; border-radius:.45rem; cursor:pointer; transition:border-color .14s, color .14s}
949
+ .ai-popup-head button:hover{border-color:rgba(84,183,255,.55); color:#fff}
950
+ .ai-chat{flex:1; overflow:auto; padding:.75rem; display:flex; flex-direction:column; gap:.55rem}
951
+ .ai-chat .msg{display:flex; flex-direction:column; max-width:88%; gap:.3rem; animation:agent-rise .25s cubic-bezier(.22,1,.36,1) both}
952
+ .ai-chat .msg.user{align-self:flex-end; align-items:flex-end}
953
+ .ai-chat .msg.ai{align-self:flex-start; align-items:flex-start}
954
+ .ai-chat .bubble{padding:.6rem .8rem; border:1px solid rgba(112,168,228,.22); border-radius:.8rem; color:#dcecff; background:linear-gradient(160deg, rgba(16,38,70,.5), rgba(8,20,42,.56)); font-size:.78rem; line-height:1.65; white-space:pre-wrap; overflow-wrap:anywhere; word-break:break-word; box-shadow:inset 0 1px rgba(255,255,255,.05), 0 14px 42px rgba(0,0,0,.2); backdrop-filter:blur(18px) saturate(135%); -webkit-backdrop-filter:blur(18px) saturate(135%)}
955
+ .ai-chat .user .bubble{border-color:rgba(84,183,255,.42); background:linear-gradient(160deg, rgba(22,70,122,.58), rgba(46,41,112,.5)); color:#eaf7ff}
956
+ .ai-chat .bubble pre{margin:.4rem 0 0; padding:.55rem .7rem; border-radius:.55rem; background:#000; border:1px solid rgba(112,168,228,.12); font-family:ui-monospace, SFMono-Regular, Consolas, monospace; font-size:.64rem; overflow:auto; white-space:pre-wrap}
957
+ .ai-chat .bubble pre .hljs{background:transparent; padding:0; color:#e8f2ff}
958
+ .ai-chat .insert{margin-top:.4rem; padding:.28rem .6rem; border-radius:.45rem; border:1px solid rgba(84,183,255,.4); background:rgba(84,183,255,.12); color:#9fd4ff; font-size:.58rem; font-weight:700; cursor:pointer; transition:border-color .14s, background .14s, transform .14s; font-family:ui-monospace, SFMono-Regular, Consolas, monospace}
959
+ .ai-chat .insert:hover{border-color:rgba(84,183,255,.75); color:#fff; background:rgba(40,137,235,.28); transform:translateY(-1px)}
960
+ .ai-chat .typing{font-size:.6rem; color:#6e8aaa; font-style:italic}
961
+ .ai-form{padding:.65rem; border-top:1px solid rgba(112,168,228,.14); display:flex; gap:.5rem; align-items:flex-end}
962
+ .ai-form textarea{flex:1; min-height:2.4rem; max-height:6rem; border-radius:.55rem; border:1px solid rgba(112,168,228,.24); background:rgba(255,255,255,.05); color:#e8f2ff; padding:.5rem .65rem; font-size:.76rem; resize:none; outline:none; transition:border-color .14s, box-shadow .14s}
963
+ .ai-form textarea::placeholder{color:#5b7392}
964
+ .ai-form textarea:focus{border-color:rgba(84,183,255,.6); box-shadow:0 0 0 3px rgba(84,183,255,.14)}
965
+ .ai-form button{padding:.55rem 1rem; border:1px solid rgba(84,183,255,.55); border-radius:.55rem; color:#fff; background:linear-gradient(135deg, rgba(38,130,225,.75), rgba(90,67,183,.65)); box-shadow:0 8px 24px rgba(84,183,255,.28); font-size:.7rem; font-weight:800; cursor:pointer; white-space:nowrap; transition:transform .15s, filter .15s}
966
+ .ai-form button:hover:not(:disabled){filter:brightness(1.1); transform:translateY(-1px)}
967
+ .ai-form button:disabled{opacity:.4; cursor:not-allowed}
968
+ /* Theme (dark only) */
969
+ /* Light theme overrides */
970
+ [data-theme="light"] body{background:#eef3fb; color:#0b1220}
971
+ [data-theme="light"] .agent-shell{background:#eef3fb}
972
+ [data-theme="light"] .agent-shell::before{opacity:.25; background-image:linear-gradient(rgba(30,80,160,.06) 1px, transparent 1px), linear-gradient(90deg, rgba(30,80,160,.06) 1px, transparent 1px)}
973
+ [data-theme="light"] .agent-aurora i{opacity:.22; mix-blend-mode:multiply}
974
+ [data-theme="light"] .agent-header{background:linear-gradient(180deg, rgba(255,255,255,.9), rgba(235,242,252,.8)); border-bottom-color:rgba(60,110,180,.18)}
975
+ [data-theme="light"] .agent-brand-name{color:#0b1220}
976
+ [data-theme="light"] .agent-brand-sub{color:#5a6b84}
977
+ [data-theme="light"] .graphiql-panel{background:linear-gradient(160deg, rgba(255,255,255,.7), rgba(240,246,255,.75)); border-color:rgba(60,110,180,.16); box-shadow:inset 0 1px rgba(255,255,255,.6), 0 18px 50px rgba(20,50,100,.12)}
978
+ [data-theme="light"] .panel-head{color:#4a5c78; border-bottom-color:rgba(60,110,180,.14)}
979
+ [data-theme="light"] .ops .op{background:rgba(255,255,255,.72); border-color:rgba(60,110,180,.16); box-shadow:inset 0 1px rgba(255,255,255,.6)}
980
+ [data-theme="light"] .ops .op b{color:#0b1220}
981
+ [data-theme="light"] .ops .op:hover{background:rgba(84,183,255,.14)}
982
+ [data-theme="light"] .type-details details{background:rgba(255,255,255,.72); border-color:rgba(60,110,180,.16); box-shadow:inset 0 1px rgba(255,255,255,.6)}
983
+ [data-theme="light"] .type-details details:hover{background:rgba(84,183,255,.14); border-color:rgba(60,110,180,.3)}
984
+ [data-theme="light"] .type-details summary{color:#0b1220}
985
+ [data-theme="light"] .type-details summary:hover{background:rgba(84,183,255,.14)}
986
+ [data-theme="light"] .type-details .type-desc{color:#5a6b84; background:rgba(60,110,180,.06); border-left-color:rgba(60,110,180,.35)}
987
+ [data-theme="light"] .type-details .type-field{background:rgba(255,255,255,.72); color:#0b1220; border-color:rgba(60,110,180,.16); box-shadow:inset 0 1px rgba(255,255,255,.6)}
988
+ [data-theme="light"] .type-details .type-field:hover{background:rgba(84,183,255,.14); border-color:rgba(60,110,180,.3)}
989
+ [data-theme="light"] .type-details .type-field b{color:#1d6fd0}
990
+ [data-theme="light"] .type-details .type-field .hljs{color:#0b1220}
991
+ [data-theme="light"] .ai-hint, [data-theme="light"] .type-details .type-desc{color:#5a6b84}
992
+ [data-theme="light"] .history div{color:#3a4c68}
993
+ [data-theme="light"] .ai-popup{background:linear-gradient(160deg, rgba(255,255,255,.96), rgba(238,245,255,.97)); border-color:rgba(60,110,180,.2)}
994
+ [data-theme="light"] .ai-chat .bubble{background:rgba(240,246,255,.8); color:#16233c; border-color:rgba(60,110,180,.18)}
995
+ [data-theme="light"] .ai-chat .user .bubble{background:linear-gradient(160deg, rgba(84,183,255,.35), rgba(120,110,230,.3)); color:#0b1220}
996
+ [data-theme="light"] .ai-chat .bubble pre{background:#000; border-color:rgba(112,168,228,.15)}
997
+ [data-theme="light"] .ai-chat .bubble pre .hljs{color:#e8f2ff}
998
+ [data-theme="light"] .type-filter{background:rgba(255,255,255,.8); color:#0b1220; border-color:rgba(60,110,180,.2)}
999
+ @media (max-width: 960px){ .ai-popup{right:.75rem; left:.75rem; width:auto} }
1000
+ </style>
1001
+ </head>
1002
+ <body class="graphiql-dark">
1003
+ <div class="agent-shell">
1004
+ <div class="agent-aurora"><i></i><i></i><i></i></div>
1005
+
1006
+ <header class="agent-header">
1007
+ <div class="agent-header-inner">
1008
+ <span class="agent-brand">
1009
+ <span class="agent-brand-badge"><span class="agent-brand-dot"></span></span>
1010
+ <span class="agent-brand-text">
1011
+ <span class="agent-brand-name">${escapeHtml(appName)} <em>GraphQL</em></span>
1012
+ <span class="agent-brand-sub">${escapeHtml(endpoint)} · ${introspection ? 'introspection on' : 'introspection off'}</span>
1013
+ </span>
1014
+ </span>
1015
+ <span class="agent-spacer"></span>
1016
+ <span class="agent-status"><span class="agent-status-dot"></span>Live</span>
1017
+ <span class="agent-select-wrap"><span class="agent-select-label">POST</span><span class="agent-select-label" style="color:#9fd4ff">${escapeHtml(endpoint)}</span></span>
1018
+ </div>
1019
+ <div class="agent-urlbar">
1020
+ <span class="agent-urlbar-lock" title="Secure connection">🔒</span>
1021
+ <span class="agent-urlbar-input">
1022
+ <input class="agent-urlbar-field" id="urlbar" type="text" aria-label="GraphQL endpoint URL" spellcheck="false" />
1023
+ </span>
1024
+ <button class="agent-urlbar-btn" id="urlbar-copy" aria-label="Copy URL" title="Copy URL"><svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button>
1025
+ <button class="agent-urlbar-btn" id="urlbar-refresh" aria-label="Reload explorer" title="Reload">↻</button>
1026
+ <span class="agent-urlbar-note">POST</span>
1027
+ </div>
1028
+ </header>
1029
+
1030
+ <main class="agent-workspace">
1031
+ <section class="agent-main graphiql-panel">
1032
+ <div class="panel-head"><span>Explorer</span><span style="opacity:.6">GraphiQL 3</span></div>
1033
+ <div id="graphiql">Loading…</div>
1034
+ </section>
1035
+
1036
+ <aside class="agent-side">
1037
+ <div class="panel-head" style="border-radius:.6rem .6rem 0 0"><span>Available Operations</span><span style="opacity:.6">${operations.length ? operations.length + ' fields' : 'no schema'}</span></div>
1038
+ <div class="ops" id="ops">
1039
+ ${operations.length ? operations.map(op => `
1040
+ <div class="op ${op.type === 'Mutation' ? 'mutation' : ''}" data-query="${escapeHtml(op.example)}">
1041
+ <b>${escapeHtml(op.field)}${op.args ? `<span style="font-weight:400; opacity:.7">(${escapeHtml(op.args)})</span>` : ''}</b>
1042
+ <span>${op.type}</span>
1043
+ </div>`).join('') : `<div class="ai-hint" style="padding:8px">No typedefs discovered yet. <b>hello</b> is always available — try <code>{ hello }</code> below.<br>Add more: <code>npx nexus make:subgraph post --app backend</code> (creates a real Post model).<br><br>SDL preview:<br><pre style="white-space:pre-wrap; font-size:11px; opacity:.7">${escapeHtml(rawSdl.slice(0,600) || 'empty')}</pre></div>`}
1044
+ </div>
1045
+ <div class="ai-hint" style="padding:0 .8rem .6rem">Click a field to insert its example. Open <b>Docs</b> in GraphiQL (left) to browse full schema. Builtin: <code>hello</code> + <code>ping(message)</code> always visible; added subgraphs appear live via introspection.</div>
1046
+
1047
+ <div class="panel-head" style="margin-top:.4rem; border-radius:.6rem .6rem 0 0"><span>History</span><span class="panel-head-actions"><button id="history-clear" class="graphiql-history-clear" title="Clear history">Clear</button><button id="history-toggle" class="graphiql-history-btn" title="Toggle history">Show</button></span></div>
1048
+ <div class="history" id="history" hidden><div class="ai-hint" style="padding:8px">No history yet</div></div>
1049
+
1050
+ <div class="panel-head" style="margin-top:.4rem; border-radius:.6rem .6rem 0 0"><span>Type Details</span><span style="opacity:.6" id="types-count">loading…</span></div>
1051
+ <input class="type-filter" id="type-filter" placeholder="Filter types/fields…" />
1052
+ <div class="type-details" id="types"><div class="ai-hint" style="padding:8px">Loading complete schema via introspection…</div></div>
1053
+
1054
+ </aside>
1055
+ </main>
1056
+ </div>
1057
+
1058
+ <!-- Alert toast (top-right corner) — shows URL copied / query copied / success / failure -->
1059
+ <div class="agent-alert hide" id="agent-alert" role="status">
1060
+ <div class="agent-alert-mark" id="agent-alert-mark">✓</div>
1061
+ <div class="agent-alert-body">
1062
+ <strong class="agent-alert-title" id="agent-alert-title">Success</strong>
1063
+ <span class="agent-alert-msg" id="agent-alert-msg"></span>
1064
+ </div>
1065
+ <button class="agent-alert-close" id="agent-alert-close" aria-label="Dismiss" title="Dismiss">×</button>
1066
+ </div>
1067
+
1068
+ <!-- AI Assistant FAB + Chat Popup -->
1069
+ <button id="ai-fab" class="fab" aria-label="AI Assistant" title="AI Assistant">✦</button>
1070
+ <div id="ai-popup" class="ai-popup" hidden>
1071
+ <div class="ai-popup-head"><span>AI Assistant <span style="opacity:.6" id="ai-model-label"></span></span><button id="ai-close" aria-label="Close">×</button></div>
1072
+ <div id="ai-chat" class="ai-chat"><div class="ai-hint" style="padding:8px">Hi! Describe what you want in GraphQL and I’ll generate a query from your live schema. Try: “Show posts with authors”.</div></div>
1073
+ <form id="ai-form" class="ai-form">
1074
+ <textarea id="ai-prompt" placeholder="Ask about your schema, e.g. 'Show the 5 latest posts with author names'" rows="2"></textarea>
1075
+ <button type="submit" id="ai-send">Send</button>
1076
+ </form>
1077
+ <div id="ai-status" class="ai-hint" style="padding:6px 12px"></div>
1078
+ </div>
1079
+
1080
+ <script src="${CDN.hljsJs}"></script>
1081
+ <script crossorigin src="${CDN.react}"></script>
1082
+ <script crossorigin src="${CDN.reactDom}"></script>
1083
+ <script src="${CDN.graphiqlJs}"></script>
1084
+ <script>
1085
+ const endpoint = ${JSON.stringify(endpoint)};
1086
+ const sdlPreview = ${JSON.stringify(sdlPreview)};
1087
+ const rawSdlClient = ${JSON.stringify(rawSdl.slice(0,4000))};
1088
+ const STORAGE_KEY = 'nexus-graphql-history';
1089
+
1090
+ // \u2192 Unified tooltips: convert every native title to a styled data-tip
1091
+ // so all tooltips share one look (header, urlbar, history, FAB, fields...).
1092
+ function initTooltips(root){
1093
+ (root || document).querySelectorAll('[title]').forEach(function(el){
1094
+ if (el.hasAttribute('data-tip') || el.getAttribute('title') === '') return;
1095
+ el.setAttribute('data-tip', el.getAttribute('title'));
1096
+ el.removeAttribute('title');
1097
+ });
1098
+ }
1099
+ initTooltips(document);
1100
+
1101
+ // \u2192 Alert toast (top-right) — show success / error / info messages.
1102
+ const agentAlert = document.getElementById('agent-alert');
1103
+ const agentAlertClose = document.getElementById('agent-alert-close');
1104
+ const agentAlertMark = document.getElementById('agent-alert-mark');
1105
+ const agentAlertTitle = document.getElementById('agent-alert-title');
1106
+ const agentAlertMsg = document.getElementById('agent-alert-msg');
1107
+ let agentAlertTimer = null;
1108
+ function showAlert(title, msg, kind){
1109
+ if (!agentAlert || !agentAlertTitle || !agentAlertMsg) return;
1110
+ kind = kind || 'success';
1111
+ agentAlert.classList.remove('is-error', 'is-info');
1112
+ if (kind === 'error') agentAlert.classList.add('is-error');
1113
+ else if (kind === 'info') agentAlert.classList.add('is-info');
1114
+ agentAlertMark.textContent = kind === 'error' ? '!' : kind === 'info' ? 'i' : '✓';
1115
+ agentAlertTitle.textContent = title;
1116
+ agentAlertMsg.textContent = msg;
1117
+ agentAlert.classList.remove('hide');
1118
+ agentAlert.classList.add('show');
1119
+ if (agentAlertTimer) clearTimeout(agentAlertTimer);
1120
+ agentAlertTimer = setTimeout(function(){
1121
+ agentAlert.classList.remove('show');
1122
+ agentAlert.classList.add('hide');
1123
+ }, 3500);
1124
+ }
1125
+ if (agentAlertClose) {
1126
+ agentAlertClose.addEventListener('click', function(){
1127
+ agentAlert.classList.remove('show');
1128
+ agentAlert.classList.add('hide');
1129
+ if (agentAlertTimer) clearTimeout(agentAlertTimer);
1130
+ });
1131
+ }
1132
+
1133
+ // \u2192 Editable/copyable URL bar (below the header) — shows the live GraphQL endpoint.
1134
+ const urlbar = document.getElementById('urlbar');
1135
+ const copyBtn = document.getElementById('urlbar-copy');
1136
+ const refreshBtn = document.getElementById('urlbar-refresh');
1137
+ if (urlbar) {
1138
+ const fullUrl = window.location.origin + endpoint;
1139
+ urlbar.value = fullUrl;
1140
+ urlbar.addEventListener('focus', function () { this.select(); });
1141
+ if (copyBtn) {
1142
+ copyBtn.addEventListener('click', function () {
1143
+ const val = urlbar.value;
1144
+ function done() {
1145
+ copyBtn.classList.add('copied');
1146
+ copyBtn.innerHTML = '<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="20 6 9 17 4 12"/></svg>';
1147
+ showAlert('URL copied', 'GraphQL endpoint copied to clipboard.', 'success');
1148
+ setTimeout(function () {
1149
+ copyBtn.classList.remove('copied');
1150
+ copyBtn.innerHTML = '<svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';
1151
+ }, 1200);
1152
+ }
1153
+ function fail() {
1154
+ showAlert('Copy failed', 'Could not copy the URL to your clipboard.', 'error');
1155
+ }
1156
+ if (navigator.clipboard && navigator.clipboard.writeText) {
1157
+ navigator.clipboard.writeText(val).then(done, function () { urlbar.select(); try { document.execCommand('copy'); done(); } catch (e) { fail(); } });
1158
+ } else {
1159
+ urlbar.select();
1160
+ try { document.execCommand('copy'); done(); } catch (e) { fail(); }
1161
+ }
1162
+ });
1163
+ }
1164
+ if (refreshBtn) refreshBtn.addEventListener('click', function () { location.reload(); });
1165
+ // After executing a query, append it (URL-encoded) so the bar stays in sync.
1166
+ // Mutations also append a fresh csrf token so the copied URL works when the
1167
+ // nexus_csrf cookie is present (same browser/device).
1168
+ window.__updateUrlbar = function (q, token) {
1169
+ if (!urlbar || !q || !q.trim()) return;
1170
+ if (q.indexOf('__schema') !== -1 || q.indexOf('__type') !== -1) return; // ignore introspection
1171
+ let url = window.location.origin + endpoint + '?query=' + encodeURIComponent(q);
1172
+ if (token && /^\s*mutation\b/.test(q)) url += '&csrf=' + encodeURIComponent(token);
1173
+ urlbar.value = url;
1174
+ };
1175
+ }
1176
+
1177
+ let csrfToken = null;
1178
+
1179
+ // \u2192 Dark-only theme — force GraphiQL's dark palette (its CDN ignores
1180
+ // [data-theme] unless body.graphiql-dark is present).
1181
+ document.documentElement.setAttribute('data-theme', 'dark');
1182
+ document.body.classList.add('graphiql-dark');
1183
+
1184
+ // ── highlight.js helper (mirrors Agent.tsx highlightCode) ──
1185
+ function escapeHtml(s){ return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); }
1186
+ function highlightCode(code, lang){
1187
+ try{
1188
+ var hl = window.hljs;
1189
+ if(hl){
1190
+ if(lang && hl.getLanguage(lang)) return hl.highlight(code, { language: lang }).value;
1191
+ return hl.highlightAuto(code).value;
1192
+ }
1193
+ }catch(e){}
1194
+ return escapeHtml(code);
1195
+ }
1196
+ async function ensureCsrf(){
1197
+ if(csrfToken) return csrfToken;
1198
+ try{
1199
+ const r = await fetch('/csrf-token', { credentials: 'include' });
1200
+ if(r.ok){ const j = await r.json(); if(j && j.token) csrfToken = j.token; }
1201
+ if(!csrfToken){
1202
+ const m = document.cookie.match(/(?:^|; )csrf_token=([^;]+)/);
1203
+ if(m) csrfToken = decodeURIComponent(m[1]);
1204
+ }
1205
+ if(!csrfToken){
1206
+ const m2 = document.cookie.match(/(?:^|; )XSRF-TOKEN=([^;]+)/);
1207
+ if(m2) csrfToken = decodeURIComponent(m2[1]);
1208
+ }
1209
+ }catch(e){}
1210
+ return csrfToken;
1211
+ }
1212
+ // prefetch csrf in background
1213
+ ensureCsrf();
1214
+
1215
+ async function fetcher(params, opts) {
1216
+ try {
1217
+ const token = await ensureCsrf();
1218
+ const headers = { 'Content-Type': 'application/json', ...(opts && opts.headers ? opts.headers : {}) };
1219
+ if(token) headers['X-CSRF-Token'] = token;
1220
+ // Mutations require a CSRF token passed as an argument (body.csrf).
1221
+ const payload = Object.assign({}, params);
1222
+ if (token && params && params.query && /^\s*mutation\b/.test(params.query)) {
1223
+ payload.csrf = token;
1224
+ if (payload.variables && typeof payload.variables === 'object') {
1225
+ const vars = Object.assign({}, payload.variables);
1226
+ vars.csrf = token;
1227
+ payload.variables = vars;
1228
+ }
1229
+ }
1230
+ return fetch(endpoint, {
1231
+ method: 'POST',
1232
+ credentials: 'include',
1233
+ headers: headers,
1234
+ body: JSON.stringify(payload),
1235
+ }).then(function(r){
1236
+ if(!r.ok) throw new Error('GraphiQL request failed: ' + r.status);
1237
+ if (typeof window.__updateUrlbar === 'function' && params && params.query) window.__updateUrlbar(params.query, token);
1238
+ return r.json();
1239
+ }).then(function(json){
1240
+ if (json && json.errors && json.errors.length) {
1241
+ showAlert('Query error', (json.errors[0] && json.errors[0].message) || 'The query returned errors.', 'error');
1242
+ } else if (params && params.query && params.query.indexOf('__schema') === -1) {
1243
+ showAlert('Success', 'Query executed successfully.', 'success');
1244
+ }
1245
+ return json;
1246
+ });
1247
+ } catch(e) {
1248
+ console.error('GraphiQL fetcher error:', e);
1249
+ showAlert('Request failed', (e && e.message) || 'Could not reach the GraphQL endpoint.', 'error');
1250
+ return Promise.reject(e);
1251
+ }
1252
+ }
1253
+
1254
+ function saveHistory(query) {
1255
+ if (!query || !query.trim()) return;
1256
+ try {
1257
+ const list = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
1258
+ const next = [query, ...list.filter(q => q !== query)].slice(0, 20);
1259
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(next));
1260
+ renderHistory();
1261
+ } catch {}
1262
+ }
1263
+ function renderHistory() {
1264
+ const el = document.getElementById('history');
1265
+ if (!el) return;
1266
+ try {
1267
+ const list = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
1268
+ el.innerHTML = list.length ? list.map(q => \`<div data-tip="\${q.replace(/"/g,'&quot;')}" title="\${q.replace(/"/g,'&quot;')}">\${q.slice(0,80)}</div>\`).join('') : '<div style="opacity:.5">No history yet</div>';
1269
+ el.querySelectorAll('div').forEach(div => div.addEventListener('click', () => {
1270
+ const q = div.getAttribute('title');
1271
+ if (window._graphiql) window._graphiql.setQuery(q);
1272
+ }));
1273
+ } catch {}
1274
+ }
1275
+
1276
+ const historyClearBtn = document.getElementById('history-clear');
1277
+ if (historyClearBtn) {
1278
+ historyClearBtn.addEventListener('click', () => {
1279
+ try { localStorage.removeItem(STORAGE_KEY); } catch {}
1280
+ renderHistory();
1281
+ });
1282
+ }
1283
+
1284
+ const historyToggleBtn = document.getElementById('history-toggle');
1285
+ const historyPanel = document.getElementById('history');
1286
+ if (historyToggleBtn && historyPanel) {
1287
+ const sync = () => {
1288
+ historyToggleBtn.textContent = historyPanel.hidden ? 'Show' : 'Hide';
1289
+ historyToggleBtn.classList.toggle('active', !historyPanel.hidden);
1290
+ };
1291
+ sync();
1292
+ historyToggleBtn.addEventListener('click', () => {
1293
+ historyPanel.hidden = !historyPanel.hidden;
1294
+ sync();
1295
+ });
1296
+ }
1297
+
1298
+
1299
+ // Mount GraphiQL
1300
+ const defaultQuery = ${JSON.stringify(defaultQuery)};
1301
+ const root = ReactDOM.createRoot(document.getElementById('graphiql'));
1302
+ const graphiql = React.createElement(GraphiQL, {
1303
+ fetcher,
1304
+ defaultQuery,
1305
+ onEditQuery: (q) => saveHistory(q),
1306
+ isHeadersEditorEnabled: true,
1307
+ shouldPersistHeaders: true,
1308
+ });
1309
+ root.render(graphiql);
1310
+ // Expose for AI/history/ops
1311
+ window._graphiql = {
1312
+ setQuery: (q) => {
1313
+ try { localStorage.setItem('graphiql:query', q); location.reload(); } catch { alert(q); }
1314
+ }
1315
+ };
1316
+ // Click operation → insert example
1317
+ function bindOps() {
1318
+ document.querySelectorAll('#ops .op').forEach(el => {
1319
+ el.addEventListener('click', () => {
1320
+ const q = el.getAttribute('data-query');
1321
+ if (q) {
1322
+ try { localStorage.setItem('graphiql:query', q); location.reload(); } catch {}
1323
+ }
1324
+ });
1325
+ });
1326
+ }
1327
+ bindOps();
1328
+ renderHistory();
1329
+
1330
+ // Live introspection refresh — discovers hello + any added subgraph and renders full type details
1331
+ (function refreshOpsFromIntrospection(){
1332
+ const INTROSPECTION_QUERY = '{ __schema { queryType { name fields { name description args { name description type { name kind ofType { name kind ofType { name kind } } } } type { name kind ofType { name kind ofType { name kind } } } } } mutationType { name fields { name description args { name description type { name kind ofType { name kind } } } type { name kind ofType { name kind } } } } subscriptionType { name fields { name description args { name description type { name kind ofType { name kind } } } type { name kind ofType { name kind } } } } types { name kind description fields(includeDeprecated:false) { name description args { name description type { name kind ofType { name kind } } } type { name kind ofType { name kind ofType { name kind } } } } inputFields { name description type { name kind ofType { name kind } } } enumValues { name description } } } }';
1333
+ function typeToString(t){
1334
+ if(!t) return '';
1335
+ if(t.kind==='NON_NULL') return typeToString(t.ofType) + '!';
1336
+ if(t.kind==='LIST') return '[' + typeToString(t.ofType) + ']';
1337
+ return t.name || '';
1338
+ }
1339
+ function escapeTd(s){ return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;'); }
1340
+ ensureCsrf().then(function(token){
1341
+ const headers = {'Content-Type':'application/json'};
1342
+ if(token) headers['X-CSRF-Token'] = token;
1343
+ return fetch(endpoint, { method:'POST', credentials:'include', headers: headers, body: JSON.stringify({ query: INTROSPECTION_QUERY }) });
1344
+ })
1345
+ .then(function(r){ return r.ok ? r.json() : null; })
1346
+ .then(function(json){
1347
+ const schema = json && json.data && json.data.__schema;
1348
+ if (!schema) return;
1349
+ const qFields = (schema.queryType && schema.queryType.fields) || [];
1350
+ const mFields = (schema.mutationType && schema.mutationType.fields) || [];
1351
+ const sFields = (schema.subscriptionType && schema.subscriptionType.fields) || [];
1352
+ // Ops panel
1353
+ if (qFields.length || mFields.length || sFields.length){
1354
+ const opsEl = document.getElementById('ops');
1355
+ if (opsEl){
1356
+ const currentCount = opsEl.querySelectorAll('.op').length;
1357
+ const total = qFields.length + mFields.length + sFields.length;
1358
+ if (total > currentCount){
1359
+ function fieldToExample(type, name, args){
1360
+ const argStr = args && args.length ? '(' + args.map(function(a){ return a.name + ': "demo"'; }).join(', ') + ')' : '';
1361
+ if (type==='Query'){ if (name==='hello') return 'query Demo {\\n hello\\n}'; if (name==='ping') return 'query Demo {\\n ping(message: "hi")\\n}'; return 'query Demo {\\n ' + name + argStr + '\\n}'; }
1362
+ if (type==='Mutation') return 'mutation Demo {\\n ' + name + argStr + '\\n}';
1363
+ return 'subscription Demo {\\n ' + name + argStr + '\\n}';
1364
+ }
1365
+ const rows = [];
1366
+ qFields.forEach(function(f){ rows.push({type:'Query', field:f.name, args:(f.args||[]).map(function(a){return a.name;}).join(', '), typeStr: typeToString(f.type), desc: f.description, example: fieldToExample('Query', f.name, f.args)}); });
1367
+ mFields.forEach(function(f){ rows.push({type:'Mutation', field:f.name, args:(f.args||[]).map(function(a){return a.name;}).join(', '), typeStr: typeToString(f.type), desc: f.description, example: fieldToExample('Mutation', f.name, f.args)}); });
1368
+ sFields.forEach(function(f){ rows.push({type:'Subscription', field:f.name, args:(f.args||[]).map(function(a){return a.name;}).join(', '), typeStr: typeToString(f.type), desc: f.description, example: fieldToExample('Subscription', f.name, f.args)}); });
1369
+ const head = opsEl.previousElementSibling;
1370
+ if (head) head.lastElementChild.textContent = rows.length + ' fields';
1371
+ opsEl.innerHTML = rows.map(function(op){
1372
+ const ret = op.typeStr ? '<span style="opacity:.6; font-weight:400">: ' + escapeTd(op.typeStr) + '</span>' : '';
1373
+ const desc = op.desc ? '<div style="font-size:10px; opacity:.6; margin-top:2px">' + escapeTd(op.desc.slice(0,120)) + '</div>' : '';
1374
+ return '<div class="op ' + (op.type==='Mutation'?'mutation':'') + '" data-query="' + op.example.replace(/"/g,'&quot;') + '"><div><b>' + escapeTd(op.field) + (op.args ? '<span style="font-weight:400; opacity:.7">(' + escapeTd(op.args) + ')</span>' : '') + ret + '</b>' + desc + '</div><span>' + op.type + '</span></div>';
1375
+ }).join('');
1376
+ bindOps();
1377
+ const hint = document.querySelector('.ops + .ai-hint');
1378
+ if (hint) hint.textContent = 'Live from introspection — includes hello + discovered subgraphs (posts, etc.). Click to insert.';
1379
+ }
1380
+ }
1381
+ }
1382
+ // Type details panel
1383
+ const typesEl = document.getElementById('types');
1384
+ const countEl = document.getElementById('types-count');
1385
+ const filterEl = document.getElementById('type-filter');
1386
+ if (!typesEl || !schema.types) return;
1387
+ const ignore = ['String','Int','Float','Boolean','ID','__Schema','__Type','__TypeKind','__Field','__InputValue','__EnumValue','__Directive','_Any','_Entity','_Service'];
1388
+ const userTypes = schema.types.filter(function(t){ return !t.name.startsWith('__') && !t.name.startsWith('_') && ignore.indexOf(t.name)===-1; });
1389
+ userTypes.sort(function(a,b){ return a.name.localeCompare(b.name); });
1390
+ if (countEl) countEl.textContent = userTypes.length + ' types';
1391
+ function renderTypes(filter){
1392
+ const q = (filter||'').toLowerCase();
1393
+ const filtered = q ? userTypes.filter(function(t){ return t.name.toLowerCase().indexOf(q)!==-1 || (t.fields && t.fields.some(function(f){ return f.name.toLowerCase().indexOf(q)!==-1; })); }) : userTypes;
1394
+ if (!filtered.length){ typesEl.innerHTML = '<div class="ai-hint" style="padding:8px">No types match “' + escapeTd(filter) + '”.</div>'; return; }
1395
+ typesEl.innerHTML = filtered.map(function(t){
1396
+ const kind = t.kind || 'OBJECT';
1397
+ const kindIcon = kind==='INPUT_OBJECT' ? '( )' : kind==='ENUM' ? 'A-Z' : kind==='SCALAR' ? 'S' : 'T';
1398
+ const iconCls = kind==='INPUT_OBJECT' ? 'kind-input' : kind==='ENUM' ? 'kind-enum' : kind==='SCALAR' ? 'kind-scalar' : '';
1399
+ const kindLabel = kind.replace(/_/g,' ').toLowerCase();
1400
+ const desc = t.description ? '<div class="type-desc">' + escapeTd(t.description.slice(0,300)) + '</div>' : '';
1401
+ function fieldSig(f){
1402
+ const fType = typeToString(f.type);
1403
+ const fArgs = f.args && f.args.length ? '(' + f.args.map(function(a){ return '<span class="tok-arg">' + escapeTd(a.name) + '</span>: ' + '<span class="tok-type">' + escapeTd(typeToString(a.type)) + '</span>'; }).join(', ') + ')' : '';
1404
+ return escapeTd(f.name) + fArgs + ': ' + '<span class="tok-type">' + escapeTd(fType) + '</span>';
1405
+ }
1406
+ let fieldsHtml = '';
1407
+ if (t.fields && t.fields.length){
1408
+ fieldsHtml = '<span class="type-subhead">Fields</span><div class="type-fields">' + t.fields.map(function(f){
1409
+ const fDesc = f.description ? '<span style="opacity:.6"> — ' + escapeTd(f.description.slice(0,70)) + '</span>' : '';
1410
+ return '<div class="type-field"><span><code class="hljs">' + fieldSig(f) + '</code>' + fDesc + '</span><span class="type-field-arrow" data-field-query="' + escapeTd(f.name) + '" title="Insert ' + escapeTd(f.name) + '">Insert →</span></div>';
1411
+ }).join('') + '</div>';
1412
+ } else if (t.inputFields && t.inputFields.length){
1413
+ fieldsHtml = '<span class="type-subhead">Input Fields</span><div class="type-fields">' + t.inputFields.map(function(f){
1414
+ const fType = typeToString(f.type);
1415
+ return '<div class="type-field"><span><code class="hljs">' + escapeTd(f.name) + ': ' + '<span class="tok-type">' + escapeTd(fType) + '</span></code></span></div>';
1416
+ }).join('') + '</div>';
1417
+ } else if (t.enumValues && t.enumValues.length){
1418
+ fieldsHtml = '<span class="type-subhead">Enum Values</span><div class="type-fields">' + t.enumValues.map(function(v){
1419
+ return '<div class="type-field"><span><b>' + escapeTd(v.name) + '</b>' + (v.description ? '<span style="opacity:.6"> — ' + escapeTd(v.description.slice(0,50)) + '</span>' : '') + '</span></div>';
1420
+ }).join('') + '</div>';
1421
+ }
1422
+ const open = (t.name==='Query' || t.name==='Post' || t.name==='Message') ? ' open' : '';
1423
+ return '<details' + open + '><summary><span class="type-name"><span class="type-icon ' + iconCls + '">' + kindIcon + '</span><b>' + escapeTd(t.name) + '</b></span><span style="display:inline-flex;align-items:center;gap:.35rem;flex:0 0 auto"><span class="type-kind">' + escapeTd(kindLabel) + '</span><span class="type-chevron">›</span></span></summary><div class="type-body">' + desc + fieldsHtml + '</div></details>';
1424
+ }).join('');
1425
+ initTooltips(typesEl);
1426
+ }
1427
+ renderTypes('');
1428
+ // Insert a field's name into the editor when its chip is clicked
1429
+ // (delegated so re-renders after filtering keep working).
1430
+ typesEl.addEventListener('click', function(ev){
1431
+ var t = ev.target;
1432
+ if (!t || !t.classList) return;
1433
+ if (t.classList.contains('type-field-arrow')){
1434
+ var name = t.getAttribute('data-field-query');
1435
+ if (name && window._graphiql){
1436
+ window._graphiql.setQuery('{ ' + name + ' }');
1437
+ showAlert('Query copied', 'Inserted { ' + name + ' } into the editor.', 'success');
1438
+ }
1439
+ }
1440
+ });
1441
+ if (filterEl){
1442
+ filterEl.addEventListener('input', function(){ renderTypes(filterEl.value); });
1443
+ }
1444
+ }).catch(function(){
1445
+ const el=document.getElementById('types'); if(el) el.innerHTML='<div class="ai-hint" style="padding:8px">Introspection failed. SDL preview:<pre style="white-space:pre-wrap; font-size:11px; opacity:.7">' + escapeTd(rawSdlClient.slice(0,800) || 'empty') + '</pre></div>';
1446
+ const c=document.getElementById('types-count'); if(c) c.textContent='—';
1447
+ });
1448
+ })();
1449
+
1450
+ // AI Assistant — FAB + chat popup (replaces old single-button generate)
1451
+ const aiFab = document.getElementById('ai-fab');
1452
+ const aiPopup = document.getElementById('ai-popup');
1453
+ const aiClose = document.getElementById('ai-close');
1454
+ const aiForm = document.getElementById('ai-form');
1455
+ const aiPrompt = document.getElementById('ai-prompt');
1456
+ const aiChat = document.getElementById('ai-chat');
1457
+ const aiStatus = document.getElementById('ai-status');
1458
+ const aiModelLabel = document.getElementById('ai-model-label');
1459
+ const CHAT_KEY = 'nexus-ai-chat';
1460
+ let aiProvider = 'auto';
1461
+ let aiModel = '';
1462
+ function loadChat(){ try{ return JSON.parse(localStorage.getItem(CHAT_KEY) || '[]'); }catch{ return []; } }
1463
+ function saveChat(list){ try{ localStorage.setItem(CHAT_KEY, JSON.stringify(list.slice(-20))); }catch{} }
1464
+ function escapeChatHtml(s){ return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); }
1465
+ function extractQuery(text){
1466
+ if(!text) return null;
1467
+ const m = text.match(/\`\`\`graphql([\\s\\S]*?)\`\`\`/) || text.match(/\`\`\`([\\s\\S]*?)\`\`\`/) || text.match(/\\{[\\s\\S]*\\}/);
1468
+ return m ? (m[1] || m[0]).trim() : (text.includes('{') ? text.trim() : null);
1469
+ }
1470
+ function renderChat(){
1471
+ const list = loadChat();
1472
+ if(!list.length){
1473
+ aiChat.innerHTML = '<div class="ai-hint" style="padding:8px">Hi! I can see your live schema. Ask me to generate queries, explain types, or debug errors.</div>';
1474
+ return;
1475
+ }
1476
+ aiChat.innerHTML = list.map(function(it){
1477
+ const isUser = it.role==='user';
1478
+ const safe = escapeChatHtml(it.content);
1479
+ const hasCode = !isUser && it.content.includes('{');
1480
+ const code = hasCode ? '<pre><code class="hljs">' + highlightCode((extractQuery(it.content) || it.content).slice(0,2000), 'graphql') + '</code></pre>' : '';
1481
+ const btn = hasCode ? '<button class="insert" data-query="' + escapeChatHtml(extractQuery(it.content) || '').replace(/"/g,'&quot;') + '">Insert query</button>' : '';
1482
+ return '<div class="msg ' + (isUser?'user':'ai') + '"><div class="bubble">' + (isUser? safe : safe.replace(/\\n/g,'<br>')) + code + btn + '</div></div>';
1483
+ }).join('');
1484
+ aiChat.querySelectorAll('.insert').forEach(function(b){
1485
+ b.addEventListener('click', function(){
1486
+ const q = b.getAttribute('data-query');
1487
+ if(q){ try{ localStorage.setItem('graphiql:query', q); location.reload(); }catch{ alert(q); } }
1488
+ });
1489
+ });
1490
+ aiChat.scrollTop = aiChat.scrollHeight;
1491
+ }
1492
+ renderChat();
1493
+ async function resolveAiConfig(){
1494
+ try{
1495
+ const s = await fetch('/admin/ai/status', {credentials:'include'}).then(function(r){ return r.ok ? r.json() : null; });
1496
+ if(s){ aiProvider = s.defaultProvider || s.autoResolvesTo || 'auto'; aiModel = s.schemaModel || ''; if(!aiModel){ const p = await fetch('/admin/ai/providers', {credentials:'include'}).then(function(r){ return r.ok ? r.json() : null; }); const en = p && p.providers && p.providers.find(function(x){ return x.enabled && x.defaultModel; }); if(en && en.defaultModel) aiModel = en.defaultModel; } }
1497
+ }catch(e){}
1498
+ if(!aiModel) aiModel = 'llama3.1:8b';
1499
+ if(aiModelLabel) aiModelLabel.textContent = '(' + aiProvider + '/' + aiModel + ')';
1500
+ }
1501
+ resolveAiConfig();
1502
+ if(aiFab && aiPopup){
1503
+ aiFab.addEventListener('click', function(){ aiPopup.hidden = !aiPopup.hidden; if(!aiPopup.hidden) { renderChat(); aiPrompt.focus(); } });
1504
+ if(aiClose) aiClose.addEventListener('click', function(){ aiPopup.hidden = true; });
1505
+ }
1506
+ function setChatTyping(on){
1507
+ let el = document.getElementById('ai-typing');
1508
+ if(on){
1509
+ if(!el){ el = document.createElement('div'); el.id='ai-typing'; el.className='typing'; el.textContent='AI is thinking…'; aiChat.appendChild(el); }
1510
+ aiChat.scrollTop = aiChat.scrollHeight;
1511
+ } else if(el){ el.remove(); }
1512
+ }
1513
+ if(aiForm){
1514
+ aiForm.addEventListener('submit', async function(e){
1515
+ e.preventDefault();
1516
+ const prompt = aiPrompt.value.trim();
1517
+ if(!prompt) return;
1518
+ const history = loadChat();
1519
+ history.push({ role:'user', content: prompt, ts: Date.now() });
1520
+ saveChat(history);
1521
+ renderChat();
1522
+ aiPrompt.value = '';
1523
+ const btn = document.getElementById('ai-send');
1524
+ if(btn) btn.disabled = true;
1525
+ if(aiStatus) aiStatus.textContent = 'Thinking…';
1526
+ setChatTyping(true);
1527
+ try{
1528
+ await resolveAiConfig();
1529
+ const messages = [{ role:'system', content:'You are a helpful GraphQL assistant. You have the live schema SDL (preview: ' + sdlPreview.slice(0,2000) + '). Answer concisely. When asked to generate a query, return the query in a \`\`\`graphql code block and briefly explain.' }];
1530
+ const recent = history.slice(-8);
1531
+ recent.forEach(function(m){ messages.push({ role: m.role, content: m.content }); });
1532
+ const csrf = await ensureCsrf();
1533
+ const aiHeaders = {'Content-Type':'application/json'};
1534
+ if(csrf) aiHeaders['X-CSRF-Token'] = csrf;
1535
+ const res = await fetch('/ai/chat/completions', { method:'POST', credentials: 'include', headers: aiHeaders, body: JSON.stringify({ model: aiModel, provider: aiProvider, messages: messages, stream:false }) });
1536
+ let text = '';
1537
+ if(res.ok){
1538
+ const data = await res.json();
1539
+ text = (data.choices && data.choices[0] && data.choices[0].message && data.choices[0].message.content) || data.content || data.query || '';
1540
+ } else {
1541
+ const errText = await res.text().catch(function(){ return ''; });
1542
+ throw new Error(errText || 'AI not configured');
1543
+ }
1544
+ if(!text) text = 'I could not generate a response. Try rephrasing.';
1545
+ history.push({ role:'assistant', content: text, ts: Date.now() });
1546
+ saveChat(history);
1547
+ renderChat();
1548
+ if(aiStatus) aiStatus.textContent = 'Responded (' + aiProvider + '/' + aiModel + ')';
1549
+ // auto offer insert if contains query
1550
+ const q = extractQuery(text);
1551
+ if(q && q.includes('{') && !text.includes('I could not')){
1552
+ // highlight that query is insertable via button in bubble
1553
+ }
1554
+ } catch(err){
1555
+ const fallback = 'query AiDemo {\\n # Fallback for: ' + prompt.replace(/\\n/g,' ') + '\\n __typename\\n}';
1556
+ const msg = 'AI unavailable: ' + (err && err.message ? err.message : 'error') + '\\n\\nFallback query:\\n\`\`\`graphql\\n' + fallback + '\\n\`\`\`' ;
1557
+ history.push({ role:'assistant', content: msg, ts: Date.now() });
1558
+ saveChat(history);
1559
+ renderChat();
1560
+ if(aiStatus) aiStatus.textContent = 'AI unavailable — inserted fallback. Configure provider in Admin → AI Agents.';
1561
+ } finally {
1562
+ setChatTyping(false);
1563
+ if(btn) btn.disabled = false;
1564
+ if(aiStatus) setTimeout(function(){ aiStatus.textContent=''; }, 6000);
1565
+ }
1566
+ });
1567
+ }
1568
+ </script>
1569
+ </body>
1570
+ </html>`;
1571
+ }
1572
+
1573
+ function extractOperations(sdl: string): Array<{ type: string; field: string; args: string; example: string }> {
1574
+ const ops: Array<{ type: string; field: string; args: string; example: string }> = [];
1575
+ // Support both `type Query` and `extend type Query`, and strip federation noise like @key/@link
1576
+ const cleaned = sdl
1577
+ .replace(/extend\s+schema\s*@\s*link[^\n]*/g, '')
1578
+ .replace(/@\s*key\s*\([^)]*\)/g, '')
1579
+ .replace(/@\s*extends\b/g, '')
1580
+ .replace(/@\s*external\b/g, '');
1581
+ const typeRegex = /(?:extend\s+)?type\s+(Query|Mutation|Subscription)\s*\{([^}]*)\}/g;
1582
+ let m: RegExpExecArray | null;
1583
+ while ((m = typeRegex.exec(cleaned))) {
1584
+ const type = m[1]!;
1585
+ const body = m[2]!;
1586
+ const fieldRegex = /(\w+)\s*(\([^)]*\))?\s*:/g;
1587
+ let f: RegExpExecArray | null;
1588
+ while ((f = fieldRegex.exec(body))) {
1589
+ const field = f[1]!;
1590
+ if (field.startsWith('_')) continue;
1591
+ const args = (f[2] ?? '').replace(/\s+/g, ' ').trim();
1592
+ let example = '';
1593
+ if (type === 'Query') {
1594
+ if (field === 'hello') example = 'query Demo {\n hello\n}';
1595
+ else if (field === 'ping') example = 'query Demo {\n ping(message: "hi")\n}';
1596
+ else example = `query Demo {\n ${field}${args ? `(${args.replace(/:\s*[^,)]+/g, ': "demo"').replace(/[()]/g, '')})` : ''}\n}`;
1597
+ if (args && !['hello', 'ping'].includes(field)) {
1598
+ const demoArgs = args.replace(/(\w+)\s*:\s*[^,)]+/g, '$1: "demo"');
1599
+ example = `query Demo {\n ${field}${demoArgs}\n}`;
1600
+ }
1601
+ } else if (type === 'Mutation') {
1602
+ if (field === 'echo') example = 'mutation Demo {\n echo(input: "hello")\n}';
1603
+ else example = `mutation Demo {\n ${field}${args ? `(${args.replace(/(\w+)\s*:\s*[^,)]+/g, '$1: "demo"')})` : ''}\n}`;
1604
+ } else {
1605
+ example = `subscription Demo {\n ${field}${args ? `(${args.replace(/(\w+)\s*:\s*[^,)]+/g, '$1: "demo"')})` : ''}\n}`;
1606
+ }
1607
+ ops.push({ type, field, args: args.replace(/[()]/g, ''), example });
1608
+ }
1609
+ }
1610
+ if (ops.length === 0 && sdl.includes('hello')) {
1611
+ ops.push({ type: 'Query', field: 'hello', args: '', example: 'query Demo {\n hello\n}' });
1612
+ if (sdl.includes('ping')) ops.push({ type: 'Query', field: 'ping', args: 'message: String', example: 'query Demo {\n ping(message: "hi")\n}' });
1613
+ }
1614
+ // De-dupe by field name, keep first occurrence
1615
+ const seen = new Set<string>();
1616
+ const uniq: typeof ops = [];
1617
+ for (const o of ops) if (!seen.has(o.field)) { seen.add(o.field); uniq.push(o); }
1618
+ return uniq.slice(0, 30);
1619
+ }
1620
+
1621
+ function buildDefaultQuery(ops: ReturnType<typeof extractOperations>): string {
1622
+ if (!ops.length) return '# No schema found — try { hello } — add a subgraph with: npx nexus make:subgraph demo --app backend\n\nquery Demo {\n hello\n ping(message: "hi")\n}';
1623
+ const lines = ops.map(o => {
1624
+ if (o.field === 'hello') return ' hello';
1625
+ if (o.field === 'ping') return ' ping(message: "hi")';
1626
+ if (o.type === 'Mutation') return ` # ${o.field} — use as mutation`;
1627
+ if (o.type === 'Subscription') return ` # ${o.field} — use as subscription`;
1628
+ return ` ${o.field}`;
1629
+ });
1630
+ return `# Welcome to Nexus GraphQL Sandbox
1631
+ # Available: ${ops.map(o => o.field).join(', ')}
1632
+ # Click any operation on the right or Docs ← to explore
1633
+ # Press Ctrl+Enter to run
1634
+
1635
+ query Demo {
1636
+ ${lines.join('\n')}
1637
+ }`;
1638
+ }
1639
+
1640
+ function escapeHtml(s: string): string {
1641
+ return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
1642
+ }