pyhttp-app 2.0.1__py3-none-any.whl

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,630 @@
1
+ /* Styles for the Postman-features round: code editor, response viewer, auth/tests
2
+ tabs, request tabs, history, cookies, settings, reorder. Loaded after style.css. */
3
+
4
+ /* ============================================================ code editor */
5
+ :root { --editor-font: 13px; }
6
+ .code-editor { display: flex; border: 1px solid var(--border); border-radius: 6px; background: var(--bg-3); overflow: hidden; min-height: 180px; height: 320px; resize: vertical; }
7
+ .code-editor:focus-within { border-color: var(--primary); }
8
+ .code-gutter { flex: none; width: 44px; padding: 7px 0; text-align: right; color: var(--muted); font-family: var(--mono); font-size: var(--editor-font); line-height: 1.5; user-select: none; background: var(--bg-2); border-right: 1px solid var(--border); overflow: hidden; will-change: transform; }
9
+ .code-gutter span { display: block; padding-right: 8px; }
10
+ .code-gutter span.err { color: #fff; background: var(--danger); border-radius: 3px 0 0 3px; }
11
+ .code-editor .code-input { flex: 1; min-width: 0; border: none; border-radius: 0; background: transparent; resize: none; margin: 0; padding: 7px 10px; font-family: var(--mono); font-size: var(--editor-font); line-height: 1.5; white-space: pre; overflow: auto; tab-size: 2; height: auto; min-height: 0; }
12
+ .code-editor .code-input:focus { border: none; }
13
+ .code-status { font-size: 12px; min-height: 18px; padding: 3px 2px; color: var(--muted); }
14
+ .code-status.ok { color: var(--accent); }
15
+ .code-status.err { color: var(--danger); cursor: pointer; }
16
+ .body-hint { margin-top: 2px; }
17
+ .gql { display: grid; grid-template-columns: 3fr 2fr; gap: 10px; }
18
+ .gql .code-editor { height: 240px; }
19
+ #binary-info.ok { color: var(--accent); } #binary-info.err { color: var(--danger); }
20
+ .tab-n { font-size: 10px; margin-left: 5px; padding: 0 5px; border-radius: 999px; background: var(--bg-4); color: var(--muted); vertical-align: 1px; }
21
+ .tab-n:empty { display: none; }
22
+ .tab-n.pass { background: rgba(34,197,94,.18); color: #86efac; } .tab-n.fail { background: rgba(239,68,68,.2); color: #fca5a5; }
23
+ .tabs button.active .tab-n { color: var(--text); }
24
+ .code-btn { font-family: var(--mono); font-weight: 700; color: var(--muted); padding: 6px 8px; }
25
+ .code-btn:hover { color: var(--text); }
26
+
27
+ /* ---------------------------------------------------------------- auth */
28
+ .field .fl { width: 90px; color: var(--muted); font-size: 13px; flex: none; }
29
+ #auth-panel .field input, #auth-panel .field select { max-width: 520px; }
30
+ .inherited { background: var(--bg-2); border: 1px dashed var(--border); border-radius: 6px; padding: 6px 10px; margin-bottom: 8px; }
31
+ .inh-row { display: grid; grid-template-columns: minmax(120px, max-content) 1fr; gap: 12px; font-size: 12px; padding: 2px 0; }
32
+ .inh-row .k { color: #93c5fd; } .inh-row .v { color: var(--muted); word-break: break-all; }
33
+ .path-vars { margin-top: 10px; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
34
+ .path-vars .chip.ok { border-color: var(--accent); color: var(--accent); cursor: default; }
35
+
36
+ /* --------------------------------------------------------------- tests */
37
+ .tests-section { margin-bottom: 18px; }
38
+ .ts-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
39
+ .ts-head h4 { margin: 0; font-size: 12px; text-transform: uppercase; letter-spacing: .4px; color: var(--muted); }
40
+ .rows { display: flex; flex-direction: column; gap: 4px; }
41
+ .test-row { display: grid; grid-template-columns: 22px 130px minmax(120px, 1.2fr) 150px minmax(100px, 1fr) minmax(90px, .8fr) 28px; gap: 6px; align-items: center; }
42
+ .test-row input, .test-row select, .extract-row input, .extract-row select, .prevar-row input, .prevar-row select { padding: 5px 8px; min-width: 0; }
43
+ .extract-row { display: grid; grid-template-columns: 22px auto minmax(100px, 1fr) 150px auto 150px minmax(120px, 1.4fr) 28px; gap: 6px; align-items: center; }
44
+ .prevar-row { display: grid; grid-template-columns: 22px minmax(100px, 1fr) minmax(160px, 2fr) 170px 28px; gap: 6px; align-items: center; }
45
+ .test-results { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 3px; }
46
+ .test-results li { display: grid; grid-template-columns: 20px auto 1fr; gap: 8px; align-items: baseline; padding: 6px 10px; border-radius: 6px; background: var(--bg-2); border: 1px solid var(--border); }
47
+ .test-results li.pass .mark { color: var(--ok); } .test-results li.fail .mark { color: var(--danger); }
48
+ .test-results li.fail { border-color: rgba(239,68,68,.4); background: rgba(239,68,68,.06); }
49
+ .test-results .note { text-align: right; word-break: break-word; }
50
+ .tests-badge { font-size: 12px; padding: 2px 8px; border-radius: 999px; }
51
+ .tests-badge.pass { background: rgba(34,197,94,.18); color: #86efac; } .tests-badge.fail { background: rgba(239,68,68,.2); color: #fca5a5; }
52
+ .rt-h { margin: 14px 0 6px; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; }
53
+ .result-item .tcount { font-size: 11px; } .result-item .tcount.pass { color: var(--ok); } .result-item .tcount.fail { color: var(--danger); }
54
+ .result-item.failed { border-color: rgba(239,68,68,.35); }
55
+ .result-item .iter { font-size: 10px; color: var(--muted); margin-right: 4px; }
56
+ .ok-text { color: var(--ok); } .err-text { color: var(--danger); }
57
+ .failed-filter { display: flex; align-items: center; gap: 5px; color: var(--muted); }
58
+
59
+ /* ------------------------------------------------------- response panels */
60
+ .response-head .tabs.small { flex-wrap: wrap; }
61
+ .r-panel { min-height: 120px; }
62
+ .htable { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 12px; }
63
+ .htable th { text-align: left; color: var(--muted); font-weight: 500; padding: 4px 8px; border-bottom: 1px solid var(--border); font-family: var(--sans); }
64
+ .htable td { padding: 4px 8px; border-bottom: 1px solid rgba(45,52,64,.5); vertical-align: top; word-break: break-all; }
65
+ .htable td.k { color: #93c5fd; white-space: nowrap; width: 1%; }
66
+ .htable input { width: 100%; padding: 2px 6px; font-size: 12px; }
67
+ kbd { font-family: var(--mono); font-size: 11px; background: var(--bg-4); border: 1px solid var(--border); border-bottom-width: 2px; border-radius: 4px; padding: 1px 6px; }
68
+ .hops { margin-top: 10px; } .hop { font-size: 12px; padding: 2px 0; }
69
+ .req-sent .line { margin-bottom: 6px; word-break: break-all; }
70
+ .warn-box { margin: 8px 0; padding: 6px 10px; border: 1px solid var(--warn); border-radius: 6px; color: var(--warn); font-family: var(--sans); font-size: 12px; }
71
+
72
+ /* ----------------------------------------------------------- viewer */
73
+ .rv { display: flex; flex-direction: column; min-height: 0; }
74
+ .rv-bar { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-bottom: 6px; }
75
+ .seg.tiny { padding: 2px; gap: 2px; } .seg.tiny button { padding: 3px 10px; font-size: 12px; }
76
+ .seg.tiny button:disabled { opacity: .4; }
77
+ .rv-btn { padding: 3px 8px; font-size: 12px; background: none; border: 1px solid var(--border); color: var(--muted); }
78
+ .rv-btn.on, .rv-btn:hover { color: var(--text); background: var(--bg-3); }
79
+ .rv-filter { width: 260px; padding: 4px 8px; font-size: 12px; }
80
+ .rv-search-box { display: flex; align-items: center; gap: 4px; }
81
+ .rv-search { width: 170px; padding: 4px 8px; font-size: 12px; }
82
+ .rv-count.none { color: var(--danger); }
83
+ .rv-body { background: var(--bg-2); border: 1px solid var(--border); border-radius: 6px; padding: 8px 10px; overflow: auto; max-height: 60vh; min-height: 80px; font-family: var(--mono); font-size: var(--editor-font); line-height: 1.5; }
84
+ .rv-body.v-preview { padding: 0; }
85
+ .rv-pre { margin: 0; background: none; border: none; padding: 0; max-height: none; white-space: pre; overflow: visible; }
86
+ .rv-body.wrap .rv-pre, .rv-body.wrap .jv { white-space: pre-wrap; word-break: break-word; }
87
+ .rv-body:not(.wrap) .jv .jv-line { white-space: nowrap; }
88
+ .rv-empty { padding: 20px; text-align: center; font-family: var(--sans); }
89
+ .rv-note { margin-top: 8px; font-family: var(--sans); }
90
+ .rv-img { max-width: 100%; display: block; margin: 10px auto; background: repeating-conic-gradient(var(--bg-4) 0 25%, transparent 0 50%) 0 0/16px 16px; }
91
+ .rv-frame { width: 100%; height: 55vh; border: none; background: #fff; border-radius: 6px; }
92
+ mark.rv-m { background: rgba(245,158,11,.45); color: inherit; border-radius: 2px; padding: 0; }
93
+ mark.rv-m.cur { background: var(--warn); color: #111; outline: 2px solid var(--warn); }
94
+ .jv { white-space: pre; }
95
+ .jv-children { padding-left: 18px; border-left: 1px solid rgba(139,148,163,.18); margin-left: 5px; }
96
+ .jv-node.collapsed > .jv-children, .jv-node.collapsed > .jv-closing { display: none; }
97
+ .jv-node:not(.collapsed) > .jv-line > .jv-summary, .jv-node:not(.collapsed) > .jv-line > .jv-close-inline { display: none; }
98
+ .jv-line { cursor: default; border-radius: 3px; }
99
+ .jv-node:not(.leaf) > .jv-line { cursor: pointer; }
100
+ .jv-line:hover { background: rgba(59,130,246,.08); }
101
+ .jv-toggle { display: inline-block; width: 14px; color: var(--muted); font-size: 10px; user-select: none; }
102
+ .jv-node.collapsed > .jv-line > .jv-toggle { transform: rotate(-90deg); }
103
+ .jv-toggle.blank { visibility: hidden; }
104
+ .jv-k { color: #93c5fd; cursor: copy; } .jv-k.idx { color: var(--muted); }
105
+ .jv-k:hover { text-decoration: underline; }
106
+ .jv-s { color: #86efac; } .jv-s a { color: inherit; } .jv-n { color: #fbbf24; } .jv-b { color: #c084fc; } .jv-null { color: var(--muted); font-style: italic; }
107
+ .jv-p { color: var(--text); } .jv-summary { color: var(--muted); font-size: 11px; margin: 0 6px; font-family: var(--sans); }
108
+ .x-t { color: #93c5fd; } .x-a { color: #c084fc; } .x-v { color: #86efac; } .x-c { color: var(--muted); font-style: italic; } .x-p { color: var(--muted); } .x-pi, .x-d { color: #fbbf24; }
109
+ :root[data-theme="light"] .jv-k, :root[data-theme="light"] .x-t, :root[data-theme="light"] .htable td.k, :root[data-theme="light"] .inh-row .k { color: #1d4ed8; }
110
+ :root[data-theme="light"] .jv-s, :root[data-theme="light"] .x-v { color: #15803d; }
111
+ :root[data-theme="light"] .jv-n, :root[data-theme="light"] .x-pi, :root[data-theme="light"] .x-d { color: #b45309; }
112
+ :root[data-theme="light"] .jv-b, :root[data-theme="light"] .x-a { color: #7e22ce; }
113
+ :root[data-theme="light"] .tab-n.pass, :root[data-theme="light"] .tests-badge.pass { color: #15803d; }
114
+ :root[data-theme="light"] .tab-n.fail, :root[data-theme="light"] .tests-badge.fail { color: #b91c1c; }
115
+ .c-viewer .rv-body { max-height: 320px; }
116
+ .c-viewer .rv-bar { margin-left: 14px; }
117
+ .c-viewer { margin: 4px 0 6px; }
118
+ .snippet { max-height: 55vh; white-space: pre; }
119
+
120
+ /* ------------------------------------------------------------ side tabs */
121
+ .side-panel { display: flex; flex-direction: column; min-height: 0; }
122
+ .history-list .h-item { grid-template-columns: 58px 54px 1fr 36px 28px; }
123
+ .history-list .h-time { font-size: 11px; white-space: nowrap; }
124
+ .history-list .h-code { font-family: var(--mono); font-size: 11px; font-weight: 700; text-align: right; }
125
+ .h-code.ok { color: var(--ok); } .h-code.warn { color: var(--warn); } .h-code.err { color: var(--danger); }
126
+ .h-day { padding: 8px 12px 2px; font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .4px; }
127
+ .h-item .more { opacity: 0; }
128
+ .h-item:hover .more, .h-item.menu-open .more { opacity: 1; }
129
+ .req-item .bn { color: var(--accent); }
130
+
131
+ /* ----------------------------------------------------------- request tabs */
132
+ .req-tabs { display: flex; align-items: flex-end; gap: 2px; overflow-x: auto; border-bottom: 1px solid var(--border); margin: -4px 0 10px; flex: none; user-select: none; }
133
+ .req-tab { display: flex; align-items: center; gap: 6px; padding: 5px 5px 5px 10px; border: 1px solid transparent; border-bottom: none; border-radius: 6px 6px 0 0; color: var(--muted); font-size: 13px; max-width: 240px; cursor: pointer; flex: none; margin-bottom: -1px; }
134
+ .req-tab:hover { background: var(--bg-3); color: var(--text); }
135
+ .req-tab.active { background: var(--bg-2); border-color: var(--border); color: var(--text); box-shadow: inset 0 2px 0 var(--primary); }
136
+ .req-tab .rt-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
137
+ .req-tab .rt-dot { color: var(--warn); font-size: 11px; }
138
+ .req-tab .rt-close {
139
+ display: inline-flex; align-items: center; justify-content: center; flex: none; width: 22px; height: 22px;
140
+ padding: 0; background: none; border: none; border-radius: 5px; color: var(--muted); font-size: 15px; line-height: 1; opacity: .55;
141
+ }
142
+ .req-tab:hover .rt-close, .req-tab.active .rt-close { opacity: 1; }
143
+ .req-tab .rt-close:hover { color: var(--danger); background: var(--bg-4); }
144
+ .rt-add { background: none; border: none; color: var(--muted); padding: 4px 10px; font-size: 19px; line-height: 1; }
145
+ .rt-add:hover { color: var(--text); background: none; }
146
+ .editor-request { display: flex; flex-direction: column; }
147
+
148
+ /* ------------------------------------------------------------ layout mode */
149
+
150
+ /* --------------------------------------------------------------- import */
151
+ .import-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 12px; }
152
+ .import-card { display: flex; flex-direction: column; gap: 4px; text-align: left; padding: 14px; white-space: normal; }
153
+ .import-card.on { border-color: var(--primary); }
154
+ .cookie-domain { margin-bottom: 14px; }
155
+ .cd-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
156
+ .cert-row { display: grid; grid-template-columns: 1fr 1.5fr 1.5fr 28px; gap: 6px; margin-bottom: 4px; }
157
+ .cert-row input { padding: 5px 8px; }
158
+ .update-pill { background: rgba(16,185,129,.18); border-color: var(--accent); color: var(--accent); font-weight: 600; padding: 5px 10px; }
159
+ .update-pill:hover { background: rgba(16,185,129,.3); }
160
+ .upd-progress { margin: 10px 0; }
161
+ .upd-progress .progress { height: 8px; margin-bottom: 6px; }
162
+ .upd-msg { min-height: 18px; }
163
+ .upd-log { margin-top: 8px; max-height: 180px; font-size: 11px; white-space: pre-wrap; }
164
+ .upd-cmds { font-family: var(--mono); font-size: 12px; max-height: 160px; user-select: text; }
165
+ .tabs.small.set-tabs { margin-bottom: 18px; border-bottom: 1px solid var(--border); }
166
+ .set-field .seg { align-self: flex-start; }
167
+ /* Settings: sections with air between them, switches in a list, fields on a grid with the label above */
168
+ #set-panels .set-section { margin-bottom: 22px; }
169
+ #set-panels .set-section:last-child { margin-bottom: 6px; }
170
+ #set-panels .set-section h4 { margin-bottom: 12px; }
171
+ .switch-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
172
+ .switch-list .ssl-warn { margin: -2px 0 2px 12px; }
173
+ .set-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px 18px; }
174
+ .set-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
175
+ .set-field.wide { grid-column: 1 / -1; }
176
+ .set-label { font-size: 12px; font-weight: 600; color: var(--muted); }
177
+ .set-field input, .set-field select { width: 100%; min-width: 0; }
178
+ .set-field input[type=number] { width: 110px; }
179
+ .set-unit { display: flex; align-items: center; gap: 8px; }
180
+ .set-hint { line-height: 1.4; }
181
+ .set-intro { margin: 0 0 10px; }
182
+ .set-actions { display: flex; align-items: center; gap: 10px; margin: 16px 0 8px; }
183
+ .cert-head { display: grid; grid-template-columns: 1fr 1.5fr 1.5fr 28px; gap: 6px; margin-bottom: 4px; padding: 0 2px; }
184
+ #set-certs .cert-row { margin-bottom: 6px; }
185
+ .md { font-size: 13px; line-height: 1.5; padding: 8px 10px; background: var(--bg-2); border: 1px solid var(--border); border-radius: 6px; }
186
+ .md h2, .md h3, .md h4, .md h5 { margin: 8px 0 4px; font-size: 14px; } .md h2 { font-size: 16px; }
187
+ .md p { margin: 4px 0; } .md ul, .md ol { margin: 4px 0; padding-left: 22px; } .md pre { margin: 6px 0; }
188
+ .md a { color: var(--primary); }
189
+
190
+ /* ------------------------------------------------------------- scripts */
191
+ .scripts-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
192
+ .scripts-grid .code-editor { height: 160px; min-height: 100px; }
193
+ .script-log { background: var(--bg-2); border: 1px solid var(--border); border-radius: 6px; padding: 6px 10px; margin-top: 4px; }
194
+ @media (max-width: 1100px) { .scripts-grid { grid-template-columns: 1fr; } }
195
+
196
+ /* ------------------------------------------------------------- reorder */
197
+ .req-item.drop-before, .folder-item.drop-before { box-shadow: inset 0 2px 0 var(--primary); }
198
+ .req-item.drop-after, .folder-item.drop-after { box-shadow: inset 0 -2px 0 var(--primary); }
199
+
200
+ /* ------------------------------------------------------------ CodeMirror */
201
+ :root { --cm-key: #93c5fd; --cm-string: #86efac; --cm-number: #fbbf24; --cm-keyword: #c084fc; --cm-func: #60a5fa; }
202
+ :root[data-theme="light"] { --cm-key: #1d4ed8; --cm-string: #15803d; --cm-number: #b45309; --cm-keyword: #7e22ce; --cm-func: #1d4ed8; }
203
+ .code-editor { display: block; height: 320px; min-height: 120px; resize: vertical; overflow: hidden; }
204
+ .code-editor .cm-editor { height: 100%; }
205
+ .scripts-grid .code-editor { height: 180px; }
206
+ .gql .code-editor { height: 240px; }
207
+
208
+ /* ------------------------------------------------------- settings panels */
209
+ /* the same height on every tab; the tab row stays put and only the content below it scrolls */
210
+ .modal-body:has(> #set-tabs) { display: flex; flex-direction: column; overflow: hidden; min-height: 0; }
211
+ #set-tabs { flex: none; }
212
+ #set-panels { height: min(660px, 76vh); min-height: 0; flex: 0 1 auto; overflow-y: auto; padding-right: 4px; }
213
+ #set-panels .tab-panel { min-height: 0; }
214
+ .spin { display: inline-block; width: 14px; height: 14px; border: 2px solid var(--border); border-top-color: var(--primary); border-radius: 50%; animation: spin .8s linear infinite; vertical-align: -2px; margin-right: 6px; }
215
+ @keyframes spin { to { transform: rotate(360deg); } }
216
+
217
+ /* ------------------------------------------------ runs panel show / hide */
218
+ /* the ✕ is pinned to the corner and the tabs wrap, so nothing hides when the panel is dragged narrow */
219
+ .tabs-close { position: absolute; right: 4px; top: 3px; margin: 0; padding: 2px 8px; color: var(--muted); }
220
+ .layout.no-runs { grid-template-columns: var(--side-w, 320px) minmax(480px, 1fr); }
221
+ .layout.no-runs .runs { display: none; }
222
+ @media (max-width: 1180px) { .layout.no-runs { grid-template-columns: var(--side-w, 280px) minmax(380px, 1fr); } }
223
+ .status-btn.on { color: var(--text); }
224
+
225
+ /* ----------------------------------------------- response collapse / max */
226
+ .copy-btn.icon-only { display: inline-flex; align-items: center; justify-content: center; min-width: 30px; height: 30px; padding: 4px 7px; font-size: 16px; line-height: 1; }
227
+ .response.collapsed #resp-panels, .response.collapsed #resp-bodies { display: none !important; }
228
+ .response.collapsed { min-height: 0; }
229
+ #editor-form.resp-max .editor-request { display: none !important; }
230
+ #editor-form.resp-max .response { margin-top: 0; border-top: none; padding-top: 0; }
231
+ .editor.beside #editor-form.resp-max:not([hidden]) { grid-template-columns: 1fr; }
232
+
233
+ /* ------------------------------------------------------- tab reordering */
234
+ .req-tab.drag-src { opacity: .4; }
235
+ .req-tab.drop-left { box-shadow: inset 3px 0 0 var(--primary); }
236
+ .req-tab.drop-right { box-shadow: inset -3px 0 0 var(--primary); }
237
+
238
+ /* ------------------------------------------------------------ send/cancel */
239
+ #btn-send.cancel { background: var(--danger); border-color: var(--danger); color: #fff; }
240
+ #btn-send.cancel:hover { background: #dc2626; }
241
+
242
+ /* ------------------------------------------- response head in narrow space */
243
+ .response-head { flex-wrap: wrap; row-gap: 4px; }
244
+ .response-head > #r-status, .response-head > #r-time, .response-head > #r-size, .response-head > #r-tests-badge { white-space: nowrap; flex: none; }
245
+
246
+ /* ------------------------------------------------------- resizable panels */
247
+ .resizer { position: absolute; top: 0; bottom: 0; width: 7px; cursor: col-resize; z-index: 5; touch-action: none; }
248
+ .resizer::after { content: ""; position: absolute; top: 0; bottom: 0; left: 3px; width: 1px; background: transparent; transition: background .12s; }
249
+ .resizer:hover::after, .resizer.dragging::after { background: var(--primary); width: 2px; left: 2px; }
250
+ .sidebar > .resizer { right: -4px; }
251
+ .runs > .resizer { left: -4px; }
252
+ body.resizing, body.resizing * { cursor: col-resize !important; user-select: none !important; }
253
+ @media (max-width: 960px) { .resizer { display: none !important; } }
254
+
255
+ /* --------------------------------------------- request history extras */
256
+ .h-filters { display: flex; gap: 4px; padding: 6px 12px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
257
+ .h-filters button { padding: 2px 9px; font-size: 11px; border-radius: 999px; background: none; border: 1px solid var(--border); color: var(--muted); }
258
+ .h-filters button.ok-text, .h-filters button.warn-text, .h-filters button.err-text { color: var(--muted); }
259
+ .h-filters button:hover { color: var(--text); }
260
+ .h-filters button.on { background: var(--bg-4); color: var(--text); border-color: var(--primary); }
261
+ .h-compare { display: flex; align-items: center; gap: 8px; padding: 6px 12px; font-size: 12px; background: var(--bg-3); border-bottom: 1px solid var(--border); }
262
+ .h-compare span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
263
+ .history-list .h-item { grid-template-columns: 58px 54px 1fr 36px 26px 28px !important; }
264
+ .h-item .h-resend {
265
+ display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0;
266
+ background: none; border: none; border-radius: 6px; color: var(--muted); font-size: 17px; line-height: 1; opacity: 0;
267
+ }
268
+ .h-item:hover .h-resend { opacity: 1; }
269
+ .h-item .h-resend:hover { color: var(--primary); }
270
+ .h-resend.spinning { opacity: 1 !important; animation: spin .8s linear infinite; }
271
+ .h-item.compare-base { box-shadow: inset 3px 0 0 var(--accent); background: var(--bg-3); }
272
+ @media (hover: none) { .h-item .h-resend { opacity: 1; } }
273
+ .warn-text { color: var(--warn); }
274
+ .cmp-table { width: 100%; border-collapse: collapse; margin-bottom: 8px; font-size: 13px; }
275
+ .cmp-table th, .cmp-table td { text-align: left; padding: 5px 8px; border-bottom: 1px solid var(--border); vertical-align: middle; }
276
+ .cmp-table tr > th:first-child { max-width: 260px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
277
+ .cmp-a > th:first-child { color: var(--danger); } .cmp-b > th:first-child { color: var(--ok); }
278
+ .diff { background: var(--bg-2); border: 1px solid var(--border); border-radius: 6px; padding: 6px 0; max-height: 46vh; overflow: auto; font-size: 12px; line-height: 1.5; }
279
+ .d-line { white-space: pre-wrap; word-break: break-word; padding: 0 10px 0 4px; }
280
+ .d-mark { display: inline-block; width: 16px; color: var(--muted); user-select: none; }
281
+ .d-add { background: rgba(34, 197, 94, .13); } .d-add .d-mark { color: var(--ok); }
282
+ .d-del { background: rgba(239, 68, 68, .13); } .d-del .d-mark { color: var(--danger); }
283
+ .d-skip { color: var(--muted); padding: 2px 20px; font-style: italic; }
284
+ /* OAuth 2.0 token row */
285
+ .oa-token { display: flex; align-items: center; gap: 8px; margin: 4px 0 8px; padding: 8px 10px; background: var(--bg-3); border: 1px solid var(--border); border-radius: 6px; }
286
+ .oa-token .oa-status { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
287
+ /* secret variables */
288
+ .kv-row.with-secret { grid-template-columns: 22px 1fr 2fr 28px 28px; }
289
+ .kv.no-enable .kv-row.with-secret { grid-template-columns: 1fr 2fr 28px 28px; }
290
+ .kv-row .kv-secret {
291
+ display: inline-flex; align-items: center; justify-content: center; width: 26px; height: 26px; padding: 0;
292
+ background: none; border: none; border-radius: 6px; font-size: 15px; line-height: 1; opacity: .55;
293
+ }
294
+ .kv-row.secret .kv-secret, .kv-row .kv-secret:hover { opacity: 1; }
295
+
296
+
297
+ /* ------------------------------------------------ split panes: request / response
298
+ The request editor and the response are two panes that each scroll on their own, so the
299
+ URL row, the tabs and the response status stay in view. Drag the edge between them to
300
+ resize (double-click resets); the ratio is remembered per layout. */
301
+ .editor { overflow: hidden; }
302
+ #editor-form:not([hidden]) { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
303
+ .editor-request { flex: var(--req-grow, 1) 1 0; min-height: 0; }
304
+ #editor-panels { flex: 1 1 auto; min-height: 0; overflow: auto; padding-right: 2px; }
305
+ .response { flex: var(--resp-grow, 1) 1 0; min-height: 0; margin-top: 10px; padding-top: 8px; position: relative; }
306
+ #resp-panels { flex: 1 1 auto; min-height: 0; overflow: auto; }
307
+ /* the body tabs (scroll container) and the header must never be squeezed by a tall response */
308
+ #resp-bodies, .response > .response-head, #resp-pending { flex: none; }
309
+ #resp-panels .rv-body { max-height: none; }
310
+ .response.collapsed { flex: 0 0 auto; }
311
+ #editor-form.resp-max .response { flex: 1 1 auto; }
312
+ .editor.beside #editor-form:not([hidden]) { flex-direction: row; gap: 16px; }
313
+ .editor.beside .response { margin-top: 0; border-top: none; border-left: 1px solid var(--border); padding: 0 0 0 16px; }
314
+ .response > .resizer { display: block; top: -6px; bottom: auto; left: 0; right: 0; width: auto; height: 11px; cursor: row-resize; }
315
+ .response > .resizer::after { top: 5px; bottom: auto; left: 0; right: 0; width: auto; height: 1px; }
316
+ .response > .resizer:hover::after, .response > .resizer.dragging::after { height: 2px; top: 4px; width: auto; left: 0; }
317
+ .editor.beside .response > .resizer { top: 0; bottom: 0; left: -6px; right: auto; width: 11px; height: auto; cursor: col-resize; }
318
+ .editor.beside .response > .resizer::after { top: 0; bottom: 0; left: 5px; right: auto; width: 1px; height: auto; }
319
+ .editor.beside .response > .resizer:hover::after, .editor.beside .response > .resizer.dragging::after { width: 2px; left: 4px; height: auto; top: 0; }
320
+ body.resizing.rows, body.resizing.rows * { cursor: row-resize !important; }
321
+
322
+ /* errors never need a horizontal scrollbar: wrap them */
323
+ .rv-pre.err-text { white-space: pre-wrap; word-break: break-word; }
324
+
325
+ /* sidebar toggle (hamburger in the top bar, Ctrl+\) */
326
+ .hamburger { width: 30px; height: 30px; padding: 0; display: inline-flex; align-items: center; justify-content: center; flex: none; background: none; border-color: transparent; color: var(--muted); margin-right: -6px; }
327
+ .hamburger:hover, .hamburger.on { color: var(--text); background: var(--bg-4); }
328
+ .layout.no-side { grid-template-columns: minmax(480px, 1fr) var(--runs-w, 380px); }
329
+ .layout.no-side.no-runs { grid-template-columns: 1fr; }
330
+ .layout.no-side .sidebar { display: none; }
331
+
332
+ /* layout control: "Response: below | right" in the status bar, and a toggle in the response head */
333
+ .sb-seg { display: inline-flex; align-items: center; color: var(--muted); }
334
+ .sb-seg-label { margin-right: 6px; }
335
+ .sb-seg button { display: inline-flex; align-items: center; gap: 5px; height: 24px; padding: 0 9px; font-size: 12px; background: none; border: 1px solid var(--border); color: var(--muted); border-radius: 0; }
336
+ .sb-seg button:first-of-type { border-radius: 5px 0 0 5px; }
337
+ .sb-seg button:last-of-type { border-radius: 0 5px 5px 0; margin-left: -1px; }
338
+ .sb-seg button:hover { color: var(--text); background: var(--bg-3); }
339
+ .sb-seg button.on { background: var(--bg-4); color: var(--text); }
340
+ .sb-seg svg, #r-layout svg { width: 15px; height: 15px; fill: currentColor; display: block; }
341
+
342
+ /* Scripts tab: Pre-request and Post-response sections; tests can be scoped to one body */
343
+ .ts-sub { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: 12px 0 6px; font-weight: 600; font-size: 13px; }
344
+ .ts-sub .muted { font-weight: 400; }
345
+ .tests-section .code-editor { height: 150px; min-height: 90px; }
346
+ .script-lang { margin-bottom: 4px; flex-wrap: wrap; }
347
+ .script-lang select { flex: none; }
348
+ .row.wrap { flex-wrap: wrap; row-gap: 6px; }
349
+ .row.wrap .chip { white-space: nowrap; }
350
+ .script-scope-wrap { display: inline-flex; align-items: center; gap: 6px; font-weight: 400; }
351
+ .script-scope-wrap select { flex: none; width: auto; min-width: 110px; padding: 2px 6px; font-size: 12px; }
352
+ .script-scope-hint { font-weight: 400; }
353
+ #tests-list.scoped .test-row { grid-template-columns: 22px 118px minmax(100px, 1.1fr) 128px minmax(90px, 1fr) minmax(80px, .8fr) minmax(104px, .8fr) 28px; }
354
+ #tests-list:not(.scoped) .t-body { display: none !important; }
355
+ /* a test field that does not apply keeps its grid cell, so the columns line up across rows */
356
+ .test-row .t-blank { visibility: hidden; pointer-events: none; }
357
+ .files { flex-direction: column; gap: 6px; }
358
+ .file-row { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
359
+ .file-row a { white-space: nowrap; }
360
+
361
+ /* Sidebar at any width: the search box keeps room, the selection bar wraps instead of clipping its buttons */
362
+ .sidebar { container: sidebar / inline-size; }
363
+ .sidebar-head input { min-width: 90px; }
364
+ .sidebar-head #btn-new { flex: none; white-space: nowrap; }
365
+ .select-bar { flex-wrap: wrap; row-gap: 6px; }
366
+ .select-bar label, .select-bar #selected-count, .select-bar #btn-clear-sel { white-space: nowrap; }
367
+ .select-bar .run-group { display: flex; gap: 4px; margin-left: auto; min-width: 0; }
368
+ .select-bar #btn-run { margin-left: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
369
+ .select-bar #btn-run-now { flex: none; }
370
+ @container sidebar (max-width: 300px) {
371
+ .sidebar-head #btn-new .btn-text { display: none; }
372
+ .select-bar .run-group { width: 100%; margin-left: 0; }
373
+ .select-bar #btn-run { flex: 1 1 auto; }
374
+ }
375
+ .select-bar .run-group { align-items: stretch; }
376
+ .select-bar #btn-run-now { height: auto; padding: 0 9px; line-height: 1; }
377
+
378
+ /* run dialog: the order choice sits at the top */
379
+ .run-order { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 4px 0 6px; }
380
+ .run-order .seg button { padding: 5px 12px; }
381
+ .run-conc { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; }
382
+ .run-conc input { width: 64px; }
383
+ #run-order-hint { margin-bottom: 8px; }
384
+
385
+ /* Send ×N with a caret that picks in order / in parallel */
386
+ .send-group { display: inline-flex; flex: none; }
387
+ .send-group #btn-send { flex: none; }
388
+ .send-group #btn-send-mode { padding: 0 7px; margin-left: 1px; border-top-left-radius: 0; border-bottom-left-radius: 0; }
389
+ .send-group:has(#btn-send-mode:not([hidden])) #btn-send { border-top-right-radius: 0; border-bottom-right-radius: 0; }
390
+ .send-group #btn-send-mode[hidden] { display: none; }
391
+
392
+ /* Responses of several bodies / iterations: wrapped chips with a summary line, never a sideways scroll.
393
+ The panes must not take their minimum width from the chips (min-width: 0), or the response pane
394
+ grows past the window in the side-by-side layout. */
395
+ .response, .editor-request { min-width: 0; }
396
+ .editor.beside .response, .editor.beside .editor-request { min-width: 0; } /* no overflow:hidden here: the drag handle hangs outside the response box */
397
+ #resp-bodies.resp-bodies { flex-wrap: wrap; align-items: center; gap: 6px; overflow: visible; padding-bottom: 10px; margin-bottom: 8px; }
398
+ #resp-bodies .rb-tab { flex: none; margin: 0; padding: 4px 10px; gap: 6px; border: 1px solid var(--border); border-radius: 999px; background: var(--bg-3); color: var(--muted); box-shadow: none; max-width: 100%; }
399
+ #resp-bodies .rb-tab:hover { color: var(--text); background: var(--bg-4); }
400
+ #resp-bodies .rb-tab.active { color: var(--text); background: var(--bg-2); border-color: var(--primary); box-shadow: inset 0 0 0 1px var(--primary); }
401
+ #resp-bodies .rb-tab.pending { opacity: .55; }
402
+ #resp-bodies .rb-tab .rb-ms { font-size: 11px; }
403
+ #resp-bodies .rb-run { order: -1; flex: 1 1 100%; margin-left: 0; padding: 0 0 2px; }
404
+
405
+ /* Press feel: every enabled button dips when clicked; the ⚡ "Run now" button flashes and sends out a ring */
406
+ button { transition: transform .08s ease, box-shadow .15s ease, background-color .15s ease, border-color .15s ease; }
407
+ button:not(:disabled):active { transform: translateY(1px) scale(.96); }
408
+ #btn-run-now { background: #f5b300; color: #1a1200; border-color: #d99e00; position: relative; display: inline-grid; place-items: center; padding: 0 10px; }
409
+ #btn-run-now svg { display: block; width: 17px; height: 17px; }
410
+ #btn-run-now.zap svg { animation: zap-icon .55s ease-out; }
411
+ @keyframes zap-icon { 0% { transform: scale(1.5) rotate(-8deg); } 40% { transform: scale(.85) rotate(6deg); } 100% { transform: none; } }
412
+ #btn-run-now:not(:disabled):hover { background: #ffc940; border-color: #ffc940; box-shadow: 0 0 0 3px rgba(245, 179, 0, .22), 0 0 16px rgba(245, 179, 0, .45); }
413
+ #btn-run-now:disabled { background: var(--bg-3); color: var(--muted); border-color: var(--border); opacity: .6; }
414
+ #btn-run-now.zap { animation: zap-flash .55s ease-out; }
415
+ #btn-run-now.zap::after { content: ""; position: absolute; inset: -2px; border-radius: inherit; pointer-events: none; animation: zap-ring .6s ease-out forwards; }
416
+ @keyframes zap-flash {
417
+ 0% { background: #fff4bf; color: #1a1200; border-color: #fff4bf; transform: scale(1.22); box-shadow: 0 0 26px rgba(255, 230, 120, 1); }
418
+ 35% { background: #ffe066; transform: scale(.92); }
419
+ 100% { background: #f5b300; color: #1a1200; border-color: #d99e00; transform: scale(1); box-shadow: none; }
420
+ }
421
+ @keyframes zap-ring {
422
+ 0% { box-shadow: 0 0 0 0 rgba(255, 211, 77, .7); opacity: 1; }
423
+ 100% { box-shadow: 0 0 0 16px rgba(255, 211, 77, 0); opacity: 0; }
424
+ }
425
+ @media (prefers-reduced-motion: reduce) {
426
+ button, #btn-run-now.zap, #btn-run-now.zap::after { animation: none !important; transition: none !important; }
427
+ .toast, .modal, .modal-backdrop, .menu, .dialog, .dialog-backdrop, .resp-live { animation: none !important; }
428
+ }
429
+
430
+ /* the chip that says what happened to the request this one depends on */
431
+ .dep-badge { font-size: 12px; padding: 2px 8px; border-radius: 999px; background: var(--bg-3); color: var(--muted); white-space: nowrap; }
432
+ .dep-badge.fail { background: rgba(239,68,68,.2); color: #fca5a5; }
433
+ :root[data-theme="light"] .dep-badge.fail { color: #b91c1c; }
434
+ #f-dep { max-width: 520px; }
435
+
436
+ /* The Body tab fills the request pane: the body list and the editor stretch to the bottom, and grow when the
437
+ response is collapsed or moved to the side. Only the Body tab is laid out this way; other tabs flow as before. */
438
+ #editor-panels { display: flex; flex-direction: column; }
439
+ #editor-panels > .tab-panel { flex: 0 0 auto; }
440
+ #editor-panels > .tab-panel[data-panel="body"]:not([hidden]) { flex: 1 1 auto; display: flex; flex-direction: column; min-height: 0; }
441
+ .tab-panel[data-panel="body"] .bodies { flex: 1 1 auto; min-height: 0; grid-template-rows: minmax(0, 1fr); }
442
+ .bodies-side .body-list { flex: 1 1 auto; min-height: 48px; max-height: none; }
443
+ .bodies-main { display: flex; flex-direction: column; min-height: 0; }
444
+ #body-editor:not([hidden]) { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
445
+ #body-text-wrap:not([hidden]) { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }
446
+ #body-text-wrap > .code-editor { flex: 1 1 auto; height: auto; min-height: 200px; resize: none; }
447
+ #body-text-wrap > .body-hint { flex: none; }
448
+ /* A narrow request pane (response beside it, or a small window): the body list sits above the editor instead of squeezing it */
449
+ .editor-request { container: reqpane / inline-size; }
450
+ @container reqpane (max-width: 680px) {
451
+ .tab-panel[data-panel="body"] .bodies { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr); gap: 8px; }
452
+ .bodies-side { border-right: none; border-bottom: 1px solid var(--border); padding: 0 0 8px; max-height: 190px; }
453
+ .bodies-side .body-list { min-height: 40px; }
454
+ .bodies .row.tight { flex-wrap: wrap; row-gap: 6px; }
455
+ #body-name { flex: 1 1 140px; min-width: 120px; }
456
+ #bodies-hint { flex-basis: 100%; }
457
+ #editor-tabs { flex-wrap: wrap; } /* Params … Settings never paint over the response pane */
458
+ }
459
+ /* the drag handle between request and response: wide enough to grab, above the editors */
460
+ .response > .resizer { z-index: 8; }
461
+ .editor.beside .response > .resizer { left: -8px; width: 14px; }
462
+ .editor.beside .response > .resizer::after { left: 6px; }
463
+
464
+ /* response collapsed: the request pane takes all the freed space, whatever the saved divider position */
465
+ #editor-form:has(> .response.collapsed) > .editor-request { flex-grow: 1; }
466
+
467
+ /* key-value editors: select all / unselect all, lined up with the row checkboxes */
468
+ .kv-all { display: flex; align-items: center; gap: 8px; padding: 0 0 4px 3px; cursor: pointer; user-select: none; width: max-content; }
469
+ .kv-all input { margin: 0; }
470
+
471
+ /* the Pretty / Raw / Preview bar stays put while the response body scrolls under it */
472
+ #resp-panels #r-body.rv > .rv-bar { position: sticky; top: 0; z-index: 3; background: var(--bg); margin-bottom: 0; padding-bottom: 6px; }
473
+
474
+ /* {{variable}} dropdown under the auth fields */
475
+ .var-suggest { overflow-y: auto; z-index: 80; }
476
+ .var-suggest button { display: grid; grid-template-columns: auto 1fr auto; gap: 10px; align-items: baseline; padding: 6px 8px; }
477
+ .var-suggest button.cur { background: var(--bg-4); }
478
+ .var-suggest .vs-k { color: var(--primary); white-space: nowrap; }
479
+ .var-suggest .vs-v { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
480
+ .var-suggest .vs-s { white-space: nowrap; }
481
+ .var-suggest .vs-empty { padding: 8px 10px; }
482
+
483
+ /* response label when it belongs to a body other than the one on screen */
484
+ #r-body-name.other { background: rgba(245,158,11,.18); color: var(--warn); border-color: var(--warn); }
485
+ #r-body-name.other::before { content: "⚠ response of "; font-weight: normal; }
486
+
487
+ /* "Tip: try POST" under a failed GET */
488
+ .r-tip { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; flex: none; margin: 6px 0 2px; padding: 6px 10px; border: 1px solid var(--border); border-left: 3px solid var(--warn); border-radius: 6px; background: var(--bg-2); }
489
+ .r-tip[hidden] { display: none; }
490
+ .r-tip .r-tip-m { font-weight: 600; font-family: var(--mono); }
491
+ .r-tip .r-tip-x { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; padding: 0; border-radius: 6px; color: var(--muted); font-size: 15px; line-height: 1; }
492
+ .r-tip .r-tip-x:hover { color: var(--text); background: var(--bg-3); text-decoration: none; }
493
+ .response.collapsed .r-tip { display: none; }
494
+
495
+ /* ------------------------------------------------ request in flight (non-blocking)
496
+ A sliding bar under the URL row, a live strip with the elapsed time above the response,
497
+ the previous response dimmed but still usable, a shimmer on the first send, and spinners
498
+ on the request's tab and sidebar entry. */
499
+ .url-row { position: relative; }
500
+ .url-row.sending::after {
501
+ content: ''; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px; border-radius: 2px; pointer-events: none;
502
+ background: linear-gradient(90deg, transparent, var(--primary), var(--accent), transparent) no-repeat;
503
+ background-size: 35% 100%; animation: send-slide 1.15s cubic-bezier(.45,.05,.55,.95) infinite;
504
+ }
505
+ @keyframes send-slide { from { background-position: -40% 0; } to { background-position: 140% 0; } }
506
+
507
+ #btn-send.cancel::before {
508
+ content: ''; display: inline-block; width: 11px; height: 11px; margin-right: 7px; vertical-align: -1px;
509
+ border: 2px solid rgba(255,255,255,.35); border-top-color: #fff; border-radius: 50%; animation: spin .7s linear infinite;
510
+ }
511
+
512
+ .resp-live {
513
+ flex: none; display: flex; align-items: center; gap: 10px; flex-wrap: wrap; position: relative; overflow: hidden;
514
+ margin-bottom: 8px; padding: 8px 12px; border: 1px solid color-mix(in srgb, var(--primary) 45%, var(--border));
515
+ border-radius: 8px; background: color-mix(in srgb, var(--primary) 9%, var(--bg-2)); animation: fade-in .18s ease-out;
516
+ }
517
+ .resp-live::after { /* thin progress shimmer along the bottom edge */
518
+ content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px;
519
+ background: linear-gradient(90deg, transparent, var(--primary), transparent) no-repeat; background-size: 30% 100%;
520
+ animation: send-slide 1.4s ease-in-out infinite;
521
+ }
522
+ .resp-live .rl-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--primary); flex: none; animation: rl-pulse 1.2s ease-out infinite; }
523
+ @keyframes rl-pulse {
524
+ 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary) 60%, transparent); }
525
+ 100% { box-shadow: 0 0 0 9px transparent; }
526
+ }
527
+ .resp-live .rl-text { font-size: 13px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
528
+ .resp-live .rl-time { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
529
+ .resp-live .rl-skeleton { display: none; }
530
+ .response.first-send .resp-live .rl-skeleton { display: flex; flex-direction: column; gap: 9px; flex: 1 1 100%; padding: 10px 2px 6px; }
531
+ .rl-skeleton i {
532
+ display: block; height: 10px; border-radius: 5px;
533
+ background: linear-gradient(90deg, var(--bg-3) 25%, var(--bg-4) 50%, var(--bg-3) 75%); background-size: 300% 100%;
534
+ animation: rl-shimmer 1.3s ease-in-out infinite;
535
+ }
536
+ .rl-skeleton i:nth-child(2) { animation-delay: .08s; } .rl-skeleton i:nth-child(3) { animation-delay: .16s; }
537
+ .rl-skeleton i:nth-child(4) { animation-delay: .24s; } .rl-skeleton i:nth-child(5) { animation-delay: .32s; }
538
+ @keyframes rl-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }
539
+ /* first send: nothing to show yet but the live strip */
540
+ .response.first-send > .response-head, .response.first-send #resp-panels, .response.first-send #resp-bodies, .response.first-send .r-tip { display: none !important; }
541
+ /* later sends: the previous response stays readable and scrollable, just quieter */
542
+ .response.is-sending:not(.first-send) #resp-panels, .response.is-sending:not(.first-send) > .response-head > :not(#resp-tabs):not(.copy-btn) { opacity: .55; transition: opacity .2s; }
543
+
544
+ .req-tab.sending .method, .req-item.sending .method { position: relative; }
545
+ .req-tab.sending .method::after, .req-item.sending .method::after {
546
+ content: ''; position: absolute; left: -12px; top: 50%; width: 7px; height: 7px; margin-top: -5px;
547
+ border: 1.5px solid var(--primary); border-right-color: transparent; border-radius: 50%; animation: spin .7s linear infinite;
548
+ }
549
+
550
+ /* tab: spinner left of the method (room made with padding); sidebar: the method label pulses */
551
+ .req-tab.sending { padding-left: 22px; }
552
+ .req-item.sending .method::after { display: none; }
553
+ .req-item.sending .method { animation: method-pulse .8s ease-in-out infinite alternate; }
554
+ @keyframes method-pulse { from { opacity: 1; } to { opacity: .3; } }
555
+
556
+ @media (prefers-reduced-motion: reduce) {
557
+ .url-row.sending::after, .resp-live::after, .resp-live .rl-dot, .rl-skeleton i, #btn-send.cancel::before,
558
+ .req-tab.sending .method::after, .req-item.sending .method { animation-duration: 3s; }
559
+ }
560
+
561
+ /* ------------------------------------------------------------- monitors */
562
+ .mon-bar { display: flex; align-items: center; gap: 14px; margin-bottom: 12px; }
563
+ .mon-list { overflow: auto; max-height: 56vh; display: flex; flex-direction: column; gap: 8px; }
564
+ #btn-monitors { position: relative; }
565
+ #btn-monitors .tab-n { margin-left: 6px; }
566
+ .mon-item { background: var(--bg-3); border: 1px solid transparent; border-radius: 8px; padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; }
567
+ .mon-item:hover { border-color: var(--border); }
568
+ .mon-item.off { opacity: .65; }
569
+ .mon-head { display: flex; align-items: center; gap: 10px; }
570
+ .mon-name { font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
571
+ .mon-spark { display: flex; align-items: flex-end; gap: 2px; height: 26px; }
572
+ .mon-spark i { display: block; width: 7px; min-height: 4px; border-radius: 2px; background: var(--accent); opacity: .75; }
573
+ .mon-spark i.bad { background: var(--danger); opacity: 1; }
574
+ .mon-actions { display: flex; align-items: center; gap: 2px; }
575
+ .mon-fails { color: var(--danger); }
576
+ .mon-pick { max-height: 240px; overflow: auto; border: 1px solid var(--border); border-radius: 6px; padding: 4px; display: flex; flex-direction: column; }
577
+ .mon-pick-row { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 5px; cursor: pointer; }
578
+ .mon-pick-row:hover { background: var(--bg-3); }
579
+ .mon-pick-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
580
+
581
+ /* ---------------------------------------------------------- mock servers */
582
+ #btn-mocks { position: relative; }
583
+ #btn-mocks .tab-n { margin-left: 6px; }
584
+ .mock-item .mock-url {
585
+ align-self: flex-start; max-width: 100%; display: flex; align-items: center; gap: 8px;
586
+ padding: 3px 8px; font-size: 12px; background: var(--bg-2); border: 1px solid var(--border);
587
+ border-radius: 6px; color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
588
+ }
589
+ .mock-item .mock-url:hover { border-color: var(--primary); }
590
+ .mock-copy { color: var(--muted); font-family: var(--sans); font-size: 10px; text-transform: uppercase; letter-spacing: .4px; }
591
+ .m-ANY { color: var(--accent); }
592
+ .mock-routes, .mock-calls { width: 100%; }
593
+ /* only the path column may wrap; the narrow ones must not be broken up */
594
+ .mock-routes td, .mock-calls td { vertical-align: middle; white-space: nowrap; word-break: normal; }
595
+ .mock-routes .mock-path, .mock-calls .mock-path { white-space: normal; word-break: break-all; width: 99%; }
596
+ .mock-route.off { opacity: .55; }
597
+ .mock-acts { white-space: nowrap; text-align: right; }
598
+ .mock-acts button[disabled] { opacity: .3; }
599
+ .mock-call { cursor: pointer; }
600
+ .mock-call:hover { background: var(--bg-3); }
601
+ .mock-call.unmatched td { background: color-mix(in srgb, var(--danger) 8%, transparent); }
602
+ .switch.tiny { width: 30px; height: 18px; margin-top: 0; }
603
+ .switch.tiny span::after { width: 12px; height: 12px; }
604
+ .switch.tiny input:checked + span::after { transform: translateX(12px); }
605
+ .mock-row { gap: 18px; flex-wrap: wrap; }
606
+ .mock-row label { display: flex; align-items: center; gap: 8px; }
607
+ .mock-label { margin: 10px 0 4px; }
608
+ .mock-hint { margin: -4px 0 10px; line-height: 1.7; }
609
+ .mock-hint code { word-break: break-all; }
610
+ .mock-body { width: 100%; resize: vertical; font-size: var(--editor-font); line-height: 1.5; }
611
+ .mock-pre {
612
+ margin: 0 0 4px; padding: 8px 10px; max-height: 180px; overflow: auto; background: var(--bg-2);
613
+ border: 1px solid var(--border); border-radius: 6px; font-size: 12px; white-space: pre-wrap; word-break: break-word;
614
+ user-select: text; -webkit-user-select: text;
615
+ }
616
+
617
+ /* ----------------------------------------------- streaming response (SSE) */
618
+ /* while a "Stream the response live" send runs, the body pane is a live tail */
619
+ .response.streaming #resp-panels, .response.streaming #resp-bodies, .response.streaming .r-tip { display: none !important; }
620
+ #r-stream-live {
621
+ flex: 1 1 auto; min-height: 120px; margin: 0; overflow: auto; max-height: none;
622
+ font-family: var(--mono); font-size: var(--editor-font); line-height: 1.5;
623
+ background: var(--bg-2); border: 1px solid color-mix(in srgb, var(--primary) 40%, var(--border));
624
+ border-radius: 6px; padding: 10px; white-space: pre-wrap; word-break: break-word;
625
+ }
626
+
627
+ /* --------------------------------------------------- Settings > AI (MCP) */
628
+ .set-code { display: flex; align-items: flex-start; gap: 8px; }
629
+ .set-code pre { flex: 1 1 auto; min-width: 0; margin: 0; padding: 10px 12px; font-size: 12px; line-height: 1.6; max-height: 180px; user-select: text; -webkit-user-select: text; }
630
+ .set-code .copy-btn { flex: none; margin-top: 2px; }