@specbook/ui 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -2
  3. package/dist-viewer/apple-touch-icon.png +0 -0
  4. package/dist-viewer/assets/Host-DdTTHeXU.js +37 -0
  5. package/dist-viewer/assets/faker-B3c03STC.js +11 -0
  6. package/dist-viewer/assets/index-DnYdlDXQ.js +1 -0
  7. package/dist-viewer/assets/index-Ds6DZpGP.css +1 -0
  8. package/dist-viewer/assets/main-uV4JzQPd.js +14 -0
  9. package/dist-viewer/assets/mount-B-qFOcWp.js +2 -0
  10. package/dist-viewer/assets/panel-CoQ6iQpX.js +1 -0
  11. package/dist-viewer/assets/panel-Coi9H1nv.css +1 -0
  12. package/dist-viewer/assets/registry-DI74Wtj8.js +2 -0
  13. package/dist-viewer/assets/worker-Dw3Ps3hk.js +181 -0
  14. package/dist-viewer/favicon.svg +1 -0
  15. package/dist-viewer/index.html +19 -0
  16. package/dist-viewer/specbook.js +1 -0
  17. package/index.html +12 -0
  18. package/package.json +60 -3
  19. package/src/app.tsx +363 -0
  20. package/src/assets/mark.svg +1 -0
  21. package/src/badge.ts +14 -0
  22. package/src/branding.ts +92 -0
  23. package/src/components/Catalog.tsx +324 -0
  24. package/src/components/EnvBadge.tsx +46 -0
  25. package/src/components/EnvironmentMenu.tsx +262 -0
  26. package/src/components/Fields.tsx +220 -0
  27. package/src/components/GitHubStar.tsx +22 -0
  28. package/src/components/ListResizer.tsx +70 -0
  29. package/src/components/ModeHint.tsx +17 -0
  30. package/src/components/Palette.tsx +85 -0
  31. package/src/components/PoweredBy.tsx +15 -0
  32. package/src/components/ShareMenu.tsx +94 -0
  33. package/src/components/ThemeToggle.tsx +52 -0
  34. package/src/embed/panel.tsx +114 -0
  35. package/src/embed/styles.ts +27 -0
  36. package/src/embed.ts +65 -0
  37. package/src/engine.ts +432 -0
  38. package/src/extension.ts +101 -0
  39. package/src/fielddoc.ts +83 -0
  40. package/src/main.tsx +16 -0
  41. package/src/markdown.ts +133 -0
  42. package/src/nav.ts +118 -0
  43. package/src/panel/Body.tsx +182 -0
  44. package/src/panel/BodyEditor.tsx +92 -0
  45. package/src/panel/CodeSample.tsx +237 -0
  46. package/src/panel/Combo.tsx +124 -0
  47. package/src/panel/ControlsGrid.tsx +189 -0
  48. package/src/panel/FieldDoc.tsx +42 -0
  49. package/src/panel/FieldTable.tsx +113 -0
  50. package/src/panel/Host.tsx +100 -0
  51. package/src/panel/OperationDocs.tsx +181 -0
  52. package/src/panel/Panel.tsx +193 -0
  53. package/src/panel/ParamGrid.tsx +396 -0
  54. package/src/panel/RequestPanel.tsx +625 -0
  55. package/src/panel/RequestView.tsx +108 -0
  56. package/src/panel/ResponseView.tsx +182 -0
  57. package/src/panel/SecretsBar.tsx +156 -0
  58. package/src/panel/SequenceDocs.tsx +132 -0
  59. package/src/panel/SequencePanel.tsx +247 -0
  60. package/src/panel/StepExchange.tsx +118 -0
  61. package/src/panel/completions.ts +114 -0
  62. package/src/panel/draft.ts +106 -0
  63. package/src/panel/fieldnotes-split.ts +55 -0
  64. package/src/panel/fieldnotes.ts +40 -0
  65. package/src/panel/graphql.ts +31 -0
  66. package/src/panel/icons.tsx +85 -0
  67. package/src/panel/jsonCursor.ts +115 -0
  68. package/src/panel/stepnotes-split.ts +38 -0
  69. package/src/panel/stepnotes.ts +58 -0
  70. package/src/routing.ts +120 -0
  71. package/src/runtime.ts +32 -0
  72. package/src/schema.ts +359 -0
  73. package/src/secrets.ts +61 -0
  74. package/src/status.ts +27 -0
  75. package/src/store.ts +10 -0
  76. package/src/styles/app.css +821 -0
  77. package/src/styles/panel.css +1897 -0
  78. package/src/styles/tokens.css +122 -0
  79. package/src/theme.ts +37 -0
  80. package/src/viewer/Opening.tsx +43 -0
  81. package/src/viewer/bundles.ts +74 -0
  82. package/src/viewer/client.ts +54 -0
  83. package/src/viewer/embed.ts +78 -0
  84. package/src/viewer/faker-en.ts +3 -0
  85. package/src/viewer/main.tsx +285 -0
  86. package/src/viewer/mount.ts +52 -0
  87. package/src/viewer/protocol.ts +51 -0
  88. package/src/viewer/recent.ts +22 -0
  89. package/src/viewer/registry-data.ts +4 -0
  90. package/src/viewer/registry.ts +154 -0
  91. package/src/viewer/share.ts +134 -0
  92. package/src/viewer/site.ts +3 -0
  93. package/src/viewer/uploads.ts +53 -0
  94. package/src/viewer/viewer.css +184 -0
  95. package/src/viewer/worker-factory.ts +14 -0
  96. package/src/viewer/worker.ts +171 -0
  97. package/src/virtual.d.ts +104 -0
@@ -0,0 +1,1897 @@
1
+ /* Documentation pages, the side panel and its editor. Tokens only. */
2
+ @layer components {
3
+ /* ---- docs */
4
+ .doc {
5
+ max-width: 900px;
6
+ margin: 0 auto;
7
+ line-height: 1.6;
8
+ }
9
+ .doc-head {
10
+ display: flex;
11
+ align-items: center;
12
+ justify-content: space-between;
13
+ gap: var(--sb-space-4);
14
+ }
15
+ .doc h1 {
16
+ margin: 0;
17
+ font-size: 26px;
18
+ letter-spacing: -0.02em;
19
+ }
20
+ .doc h2 {
21
+ margin: var(--sb-space-6) 0 var(--sb-space-2);
22
+ font-size: 11px;
23
+ text-transform: uppercase;
24
+ letter-spacing: 0.06em;
25
+ color: var(--sb-text-muted);
26
+ }
27
+ .doc .endpoint {
28
+ display: flex;
29
+ align-items: center;
30
+ gap: var(--sb-space-3);
31
+ margin: var(--sb-space-3) 0 var(--sb-space-4);
32
+ padding: 8px var(--sb-space-3);
33
+ border: 1px solid var(--sb-border);
34
+ border-radius: var(--sb-radius-control);
35
+ background: var(--sb-surface);
36
+ }
37
+ .doc .endpoint .method {
38
+ font-size: 12px;
39
+ }
40
+ .doc .btn.primary {
41
+ height: 36px;
42
+ padding: 0 18px;
43
+ }
44
+ .doc-custom blockquote {
45
+ margin: var(--sb-space-3) 0;
46
+ padding: var(--sb-space-1) var(--sb-space-3);
47
+ border-left: 3px solid var(--sb-border);
48
+ color: var(--sb-text-muted);
49
+ }
50
+ .doc-custom :is(h1, h2, h3) {
51
+ margin-top: var(--sb-space-4);
52
+ }
53
+ .doc-custom pre,
54
+ .doc code {
55
+ font-family: var(--sb-font-mono);
56
+ font-size: 12.5px;
57
+ }
58
+ table.fields {
59
+ width: 100%;
60
+ border-collapse: separate;
61
+ border-spacing: 0;
62
+ font-size: 13px;
63
+ border: 1px solid var(--sb-border);
64
+ border-radius: var(--sb-radius-control);
65
+ overflow: hidden;
66
+ background: var(--sb-surface);
67
+ }
68
+ table.fields th {
69
+ text-align: left;
70
+ color: var(--sb-text-muted);
71
+ font-weight: 600;
72
+ font-size: 11px;
73
+ letter-spacing: 0.04em;
74
+ text-transform: uppercase;
75
+ padding: 7px 12px;
76
+ background: var(--sb-surface-raised);
77
+ border-bottom: 1px solid var(--sb-border);
78
+ }
79
+ table.fields td {
80
+ padding: 8px 12px;
81
+ border-bottom: 1px solid var(--sb-border);
82
+ vertical-align: top;
83
+ }
84
+ table.fields tr:last-child td {
85
+ border-bottom: 0;
86
+ }
87
+ .statuses,
88
+ .examples,
89
+ .steps {
90
+ margin: 0;
91
+ padding-left: var(--sb-space-4);
92
+ }
93
+ .statuses {
94
+ list-style: none;
95
+ padding: 0;
96
+ }
97
+ .req {
98
+ color: var(--sb-danger);
99
+ margin-left: 2px;
100
+ }
101
+ .chip {
102
+ display: inline-block;
103
+ padding: 0 6px;
104
+ border-radius: 4px;
105
+ background: var(--sb-surface-raised);
106
+ color: var(--sb-text-muted);
107
+ font: 11px var(--sb-font-mono);
108
+ }
109
+ .chip.req {
110
+ background: var(--sb-danger-subtle);
111
+ color: var(--sb-danger);
112
+ margin: 0;
113
+ }
114
+ .chip.warn {
115
+ background: var(--sb-warning-subtle);
116
+ color: var(--sb-warning);
117
+ }
118
+ .link {
119
+ background: none;
120
+ border: 0;
121
+ padding: 0;
122
+ color: var(--sb-accent);
123
+ cursor: pointer;
124
+ }
125
+ .icon {
126
+ background: none;
127
+ border: 0;
128
+ cursor: pointer;
129
+ color: var(--sb-text-muted);
130
+ font-size: 16px;
131
+ line-height: 1;
132
+ padding: 2px 6px;
133
+ }
134
+ .small {
135
+ font-size: 12px;
136
+ }
137
+
138
+ /* ---- panel */
139
+ .panel-backdrop {
140
+ position: fixed;
141
+ inset: 0;
142
+ border: 0;
143
+ padding: 0;
144
+ background: color-mix(in srgb, var(--sb-text) 35%, transparent);
145
+ cursor: default;
146
+ z-index: 20;
147
+ }
148
+ .panel {
149
+ position: fixed;
150
+ inset: 0 0 0 auto;
151
+ width: 75vw;
152
+ min-width: min(560px, 100vw);
153
+ display: flex;
154
+ flex-direction: column;
155
+ background: var(--sb-surface);
156
+ border-left: 1px solid var(--sb-border);
157
+ box-shadow: -12px 0 32px color-mix(in srgb, var(--sb-text) 18%, transparent);
158
+ z-index: 21;
159
+ animation: panel-in 160ms ease-out;
160
+ }
161
+ @keyframes panel-in {
162
+ from {
163
+ transform: translateX(24px);
164
+ opacity: 0;
165
+ }
166
+ }
167
+ @media (prefers-reduced-motion: reduce) {
168
+ .panel {
169
+ animation: none;
170
+ }
171
+ }
172
+ .panel-head {
173
+ display: flex;
174
+ align-items: center;
175
+ gap: var(--sb-space-3);
176
+ padding: var(--sb-space-3) var(--sb-space-4);
177
+ border-bottom: 1px solid var(--sb-border);
178
+ background: var(--sb-surface);
179
+ }
180
+ .panel-title {
181
+ min-width: 0;
182
+ }
183
+ .panel-head h2 {
184
+ margin: 0;
185
+ font-size: 15px;
186
+ font-weight: 650;
187
+ letter-spacing: 0;
188
+ text-transform: none;
189
+ color: var(--sb-text);
190
+ }
191
+ .panel-head .method {
192
+ font-size: 12px;
193
+ padding: 3px 8px;
194
+ }
195
+ .panel-body {
196
+ flex: 1;
197
+ min-height: 0;
198
+ overflow: auto;
199
+ overscroll-behavior: contain;
200
+ padding: var(--sb-space-4);
201
+ background: var(--sb-bg);
202
+ }
203
+ .panel-body.flush {
204
+ padding: 0;
205
+ overflow: hidden;
206
+ background: var(--sb-surface);
207
+ }
208
+ .section-head {
209
+ display: flex;
210
+ align-items: center;
211
+ gap: var(--sb-space-3);
212
+ flex-wrap: wrap;
213
+ margin-bottom: var(--sb-space-2);
214
+ }
215
+ .section-head h3,
216
+ .grid h3 {
217
+ margin: 0 0 var(--sb-space-2);
218
+ font-size: 11px;
219
+ text-transform: uppercase;
220
+ letter-spacing: 0.06em;
221
+ color: var(--sb-text-muted);
222
+ }
223
+ .section-head h3 {
224
+ margin: 0;
225
+ }
226
+ .saved-note {
227
+ display: flex;
228
+ align-items: flex-start;
229
+ gap: var(--sb-space-2);
230
+ margin: 0 var(--sb-space-4) var(--sb-space-3);
231
+ padding: var(--sb-space-2) var(--sb-space-3);
232
+ border-radius: var(--sb-radius-control);
233
+ background: var(--sb-success-subtle);
234
+ color: var(--sb-success);
235
+ font-size: 12.5px;
236
+ }
237
+ .saved-note span {
238
+ flex: 1;
239
+ }
240
+ .saved-note code {
241
+ background: none;
242
+ font-weight: 600;
243
+ word-break: break-all;
244
+ }
245
+ .naming {
246
+ padding: 0 var(--sb-space-4) var(--sb-space-3);
247
+ }
248
+ .lock {
249
+ margin: 0;
250
+ padding: 0 var(--sb-space-4) var(--sb-space-3);
251
+ }
252
+
253
+ /* ---- docked panel (standalone site): the list stays usable beside it */
254
+ .panel.docked {
255
+ inset: var(--sb-header-h, 53px) 0 0 var(--sb-list-w);
256
+ width: auto;
257
+ min-width: 0;
258
+ box-shadow: -8px 0 24px color-mix(in srgb, var(--sb-text) 10%, transparent);
259
+ animation: none;
260
+ }
261
+ .stepper {
262
+ display: inline-flex;
263
+ }
264
+ .stepper .icon:disabled {
265
+ opacity: 0.35;
266
+ cursor: default;
267
+ }
268
+ .panel-split {
269
+ display: flex;
270
+ flex-direction: column;
271
+ height: 100%;
272
+ min-height: 0;
273
+ }
274
+ .panel-tabs {
275
+ flex: 0 0 auto;
276
+ background: var(--sb-surface);
277
+ }
278
+ .panel-main {
279
+ flex: 1;
280
+ min-height: 0;
281
+ overflow: hidden;
282
+ }
283
+ .panel-main.scroll {
284
+ overflow: auto;
285
+ overscroll-behavior: contain;
286
+ padding: var(--sb-space-4) var(--sb-space-6) var(--sb-space-6);
287
+ }
288
+ .doc-intro {
289
+ display: flex;
290
+ align-items: center;
291
+ gap: var(--sb-space-3);
292
+ margin-bottom: var(--sb-space-4);
293
+ padding: 8px var(--sb-space-3);
294
+ border: 1px solid var(--sb-border);
295
+ border-radius: var(--sb-radius-control);
296
+ background: var(--sb-surface);
297
+ }
298
+ .doc-intro .method {
299
+ font-size: 12px;
300
+ }
301
+
302
+ /* ---- catalog: what the API can do, as a list */
303
+ .catalog {
304
+ container-type: inline-size;
305
+ }
306
+ .cat-top {
307
+ display: grid;
308
+ gap: var(--sb-space-3);
309
+ margin-bottom: var(--sb-space-3);
310
+ }
311
+ .pills {
312
+ display: flex;
313
+ flex-wrap: wrap;
314
+ gap: var(--sb-space-2);
315
+ }
316
+ .pill {
317
+ display: inline-flex;
318
+ align-items: center;
319
+ gap: 6px;
320
+ padding: 3px 11px;
321
+ border: 1px solid var(--sb-border);
322
+ border-radius: 999px;
323
+ background: var(--sb-surface);
324
+ color: var(--sb-text);
325
+ font-size: 13px;
326
+ cursor: pointer;
327
+ }
328
+ .pill:hover {
329
+ border-color: var(--sb-text-muted);
330
+ }
331
+ .pill.on {
332
+ background: var(--sb-accent);
333
+ border-color: var(--sb-accent);
334
+ color: var(--sb-text-on-accent);
335
+ }
336
+ .pill .count {
337
+ margin: 0;
338
+ font-size: 11px;
339
+ }
340
+ .cat-filter-wrap {
341
+ position: relative;
342
+ }
343
+ .cat-filter {
344
+ width: 100%;
345
+ padding-right: 34px;
346
+ }
347
+ .cat-hint {
348
+ position: absolute;
349
+ right: 8px;
350
+ top: 50%;
351
+ transform: translateY(-50%);
352
+ pointer-events: none;
353
+ }
354
+ .group-head.static {
355
+ cursor: default;
356
+ padding-left: 20px;
357
+ color: var(--sb-text-muted);
358
+ font-size: 11px;
359
+ letter-spacing: 0.06em;
360
+ text-transform: uppercase;
361
+ }
362
+ .method.flow {
363
+ color: var(--sb-accent);
364
+ }
365
+ /* flows are the differentiator: one tinted block above the operations, badge once */
366
+ .flows {
367
+ margin-bottom: var(--sb-space-4);
368
+ border: 1px solid color-mix(in srgb, var(--sb-accent) 28%, var(--sb-border));
369
+ border-left: 3px solid var(--sb-accent);
370
+ border-radius: var(--sb-radius-control);
371
+ background: color-mix(in srgb, var(--sb-accent) 6%, transparent);
372
+ overflow: hidden;
373
+ }
374
+ .flows-title {
375
+ display: flex;
376
+ align-items: center;
377
+ gap: var(--sb-space-2);
378
+ padding: 8px;
379
+ }
380
+ .flows-title .count {
381
+ margin-left: auto;
382
+ font-size: 12px;
383
+ color: var(--sb-text-muted);
384
+ }
385
+ .flows .flow-head {
386
+ padding-left: 8px;
387
+ font-size: 12px;
388
+ color: var(--sb-text-muted);
389
+ }
390
+ .flows .op-row:last-child {
391
+ border-bottom: 0;
392
+ }
393
+ .flow-play {
394
+ font-size: 10px;
395
+ text-align: center;
396
+ color: var(--sb-accent);
397
+ }
398
+ .overview {
399
+ display: grid;
400
+ place-content: center;
401
+ justify-items: center;
402
+ gap: var(--sb-space-2);
403
+ min-height: 100%;
404
+ padding-bottom: 8vh;
405
+ text-align: center;
406
+ color: var(--sb-text-muted);
407
+ }
408
+ .overview .overview-name {
409
+ margin: 0;
410
+ font-size: 12px;
411
+ font-weight: 700;
412
+ letter-spacing: 0.1em;
413
+ text-transform: uppercase;
414
+ color: var(--sb-accent);
415
+ }
416
+ .overview h1 {
417
+ margin: 0 0 var(--sb-space-2);
418
+ font-size: 26px;
419
+ letter-spacing: -0.02em;
420
+ color: var(--sb-text);
421
+ }
422
+ .overview p {
423
+ margin: 0;
424
+ max-width: 52ch;
425
+ }
426
+ .overview-logo {
427
+ max-height: 72px;
428
+ max-width: 240px;
429
+ width: auto;
430
+ margin-bottom: var(--sb-space-3);
431
+ object-fit: contain;
432
+ }
433
+ .overview .tagline {
434
+ font-size: 16px;
435
+ color: var(--sb-text);
436
+ }
437
+ .overview-links {
438
+ display: flex;
439
+ flex-wrap: wrap;
440
+ justify-content: center;
441
+ gap: var(--sb-space-2) var(--sb-space-4);
442
+ margin-top: var(--sb-space-2);
443
+ }
444
+ .overview-links a {
445
+ color: var(--sb-accent);
446
+ text-decoration: none;
447
+ font-weight: 600;
448
+ }
449
+ .overview-links a:hover {
450
+ text-decoration: underline;
451
+ }
452
+ .op-group {
453
+ margin-bottom: var(--sb-space-3);
454
+ }
455
+ .group-head {
456
+ display: flex;
457
+ align-items: center;
458
+ gap: 6px;
459
+ width: 100%;
460
+ padding: 6px 8px;
461
+ border: 0;
462
+ border-bottom: 1px solid var(--sb-border);
463
+ background: none;
464
+ text-align: left;
465
+ font-weight: 600;
466
+ cursor: pointer;
467
+ }
468
+ .group-head .caret {
469
+ width: 12px;
470
+ color: var(--sb-text-muted);
471
+ }
472
+ .group-head .count {
473
+ font-size: 12px;
474
+ }
475
+ .op-row {
476
+ display: grid;
477
+ grid-template-columns: 52px minmax(0, 1fr) auto;
478
+ align-items: center;
479
+ gap: var(--sb-space-3);
480
+ width: 100%;
481
+ padding: 7px 8px;
482
+ border: 0;
483
+ border-bottom: 1px solid color-mix(in srgb, var(--sb-border) 60%, transparent);
484
+ background: none;
485
+ text-align: left;
486
+ cursor: pointer;
487
+ }
488
+ .op-row:hover,
489
+ .op-row:focus-visible {
490
+ background: var(--sb-surface-raised);
491
+ }
492
+ .op-row.active {
493
+ background: color-mix(in srgb, var(--sb-accent) 10%, var(--sb-surface));
494
+ box-shadow: inset 3px 0 0 var(--sb-accent);
495
+ }
496
+ .op-row .method {
497
+ justify-self: start;
498
+ min-width: 0;
499
+ padding: 1px 5px;
500
+ font-size: 10px;
501
+ text-align: center;
502
+ }
503
+ /* long titles share their opening words, so wrap them instead of cutting the part that differs */
504
+ .op-title {
505
+ display: -webkit-box;
506
+ -webkit-line-clamp: 2;
507
+ -webkit-box-orient: vertical;
508
+ overflow: hidden;
509
+ line-height: 1.35;
510
+ overflow-wrap: anywhere;
511
+ }
512
+ .op-path {
513
+ max-width: 46%;
514
+ overflow: hidden;
515
+ text-overflow: ellipsis;
516
+ white-space: nowrap;
517
+ font: 12px var(--sb-font-mono);
518
+ color: var(--sb-text-muted);
519
+ }
520
+ @container (max-width: 520px) {
521
+ .op-path {
522
+ display: none;
523
+ }
524
+ .op-row {
525
+ grid-template-columns: 52px minmax(0, 1fr);
526
+ }
527
+ }
528
+ .cat-empty {
529
+ padding: var(--sb-space-4) 0;
530
+ }
531
+
532
+ /* ---- request: bar, tabs, grid; response below a draggable divider */
533
+ .request-panel {
534
+ display: flex;
535
+ flex-direction: column;
536
+ height: 100%;
537
+ min-height: 0;
538
+ }
539
+ .rq {
540
+ display: flex;
541
+ flex-direction: column;
542
+ flex: 1;
543
+ min-height: 0;
544
+ }
545
+ .rq-bar {
546
+ display: flex;
547
+ align-items: center;
548
+ gap: var(--sb-space-2);
549
+ padding: var(--sb-space-3) var(--sb-space-4) var(--sb-space-2);
550
+ }
551
+ .rq-bar .method {
552
+ font-size: 12px;
553
+ padding: 7px 10px;
554
+ border: 1px solid var(--sb-border);
555
+ }
556
+ .rq-url {
557
+ flex: 1;
558
+ min-width: 0;
559
+ display: flex;
560
+ align-items: center;
561
+ gap: var(--sb-space-2);
562
+ height: 34px;
563
+ padding: 0 var(--sb-space-3);
564
+ border: 1px solid var(--sb-border);
565
+ border-radius: var(--sb-radius-control);
566
+ background: var(--sb-surface-raised);
567
+ }
568
+ .rq-url code {
569
+ flex: 1;
570
+ min-width: 0;
571
+ overflow: hidden;
572
+ text-overflow: ellipsis;
573
+ white-space: nowrap;
574
+ font-size: 13px;
575
+ }
576
+ .rq-url mark {
577
+ background: var(--sb-warning-subtle);
578
+ color: var(--sb-warning);
579
+ border-radius: 3px;
580
+ padding: 0 2px;
581
+ }
582
+ /* the example picker and the environment badge travel together: one line on a phone */
583
+ .rq-example {
584
+ display: contents;
585
+ }
586
+ .env-badge {
587
+ flex: 0 0 auto;
588
+ font: 600 10px var(--sb-font-sans);
589
+ letter-spacing: 0.06em;
590
+ text-transform: uppercase;
591
+ color: var(--sb-text-muted);
592
+ border: 1px solid var(--sb-border);
593
+ border-radius: 4px;
594
+ padding: 1px 6px;
595
+ white-space: nowrap;
596
+ }
597
+ /* a native select laid invisibly over the label: a tap opens the platform picker, no zoom (16px) */
598
+ .env-badge {
599
+ position: relative;
600
+ display: inline-flex;
601
+ align-items: center;
602
+ }
603
+ .env-badge.switch {
604
+ cursor: pointer;
605
+ }
606
+ .env-badge.switch > .env-name::after {
607
+ content: " ▾";
608
+ opacity: 0.7;
609
+ }
610
+ .env-badge select {
611
+ position: absolute;
612
+ inset: 0;
613
+ width: 100%;
614
+ height: 100%;
615
+ min-height: 0;
616
+ opacity: 0;
617
+ cursor: pointer;
618
+ }
619
+ .env-badge.live {
620
+ color: var(--sb-warning);
621
+ border-color: color-mix(in srgb, var(--sb-warning) 45%, var(--sb-border));
622
+ background: var(--sb-warning-subtle);
623
+ }
624
+ .env-badge.prod {
625
+ color: var(--sb-danger);
626
+ border-color: color-mix(in srgb, var(--sb-danger) 45%, var(--sb-border));
627
+ background: var(--sb-danger-subtle);
628
+ }
629
+ .result-chip {
630
+ flex: 0 0 auto;
631
+ display: inline-flex;
632
+ align-items: center;
633
+ height: 34px;
634
+ padding: 0 12px;
635
+ border: 0;
636
+ border-radius: 999px;
637
+ font-size: 12px;
638
+ font-weight: 600;
639
+ white-space: nowrap;
640
+ cursor: pointer;
641
+ }
642
+ .result-chip.s2 {
643
+ background: var(--sb-success-subtle);
644
+ color: var(--sb-success);
645
+ }
646
+ .result-chip.s3 {
647
+ background: var(--sb-surface-raised);
648
+ color: var(--sb-text);
649
+ }
650
+ .result-chip.s4,
651
+ .result-chip.s5 {
652
+ background: var(--sb-warning-subtle);
653
+ color: var(--sb-warning);
654
+ }
655
+ .rq-status {
656
+ display: flex;
657
+ align-items: center;
658
+ gap: var(--sb-space-2);
659
+ font-size: 12px;
660
+ white-space: nowrap;
661
+ }
662
+ .request-panel select,
663
+ .panel-head select,
664
+ .header select {
665
+ appearance: none;
666
+ padding-right: 26px;
667
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' fill='none' stroke='%2394a3b8' stroke-width='1.6'%3E%3Cpath d='M1 1l4 4 4-4'/%3E%3C/svg%3E");
668
+ background-repeat: no-repeat;
669
+ background-position: right 9px center;
670
+ }
671
+ .rq-bar .send {
672
+ display: inline-grid;
673
+ place-items: center;
674
+ height: 34px;
675
+ padding: 0 18px;
676
+ }
677
+ kbd.icon-key {
678
+ display: inline-grid;
679
+ place-items: center;
680
+ vertical-align: middle;
681
+ }
682
+ .needs-vars {
683
+ min-width: 0;
684
+ display: flex;
685
+ flex-wrap: wrap;
686
+ align-items: center;
687
+ gap: var(--sb-space-2) var(--sb-space-3);
688
+ margin: 0 var(--sb-space-4) var(--sb-space-2);
689
+ padding: var(--sb-space-2) var(--sb-space-3);
690
+ border: 1px solid color-mix(in srgb, var(--sb-warning) 35%, var(--sb-border));
691
+ border-radius: var(--sb-radius-control);
692
+ background: var(--sb-warning-subtle);
693
+ font-size: 12.5px;
694
+ }
695
+ .needs-vars.ok {
696
+ border-color: var(--sb-border);
697
+ background: var(--sb-surface);
698
+ }
699
+ .secrets-folded {
700
+ margin: 0 var(--sb-space-4) var(--sb-space-2);
701
+ }
702
+ .secrets-chip {
703
+ max-width: 100%;
704
+ overflow: hidden;
705
+ text-overflow: ellipsis;
706
+ white-space: nowrap;
707
+ border: 1px solid var(--sb-border);
708
+ border-radius: 999px;
709
+ background: var(--sb-surface);
710
+ color: var(--sb-text-muted);
711
+ font-size: 12px;
712
+ line-height: 1.4;
713
+ padding: 1px 10px;
714
+ cursor: pointer;
715
+ }
716
+ .needs-var {
717
+ display: inline-flex;
718
+ align-items: center;
719
+ gap: 6px;
720
+ }
721
+ .needs-var input {
722
+ width: 130px;
723
+ min-width: 0;
724
+ }
725
+ .rq-meta {
726
+ display: flex;
727
+ align-items: center;
728
+ gap: var(--sb-space-3);
729
+ padding: var(--sb-space-1) var(--sb-space-4) var(--sb-space-3);
730
+ font-size: 12px;
731
+ }
732
+ .edited {
733
+ font-size: 11px;
734
+ font-weight: 600;
735
+ color: var(--sb-warning);
736
+ background: var(--sb-warning-subtle);
737
+ border-radius: 999px;
738
+ padding: 1px 8px;
739
+ }
740
+ .rq-tabs {
741
+ display: flex;
742
+ gap: var(--sb-space-1);
743
+ padding: 0 var(--sb-space-4);
744
+ border-bottom: 1px solid var(--sb-border);
745
+ }
746
+ .rq-tabs[hidden] {
747
+ display: none;
748
+ }
749
+ .rq-tab {
750
+ display: inline-flex;
751
+ align-items: center;
752
+ gap: 6px;
753
+ padding: 8px 10px;
754
+ margin-bottom: -1px;
755
+ border: 0;
756
+ border-bottom: 2px solid transparent;
757
+ background: none;
758
+ color: var(--sb-text-muted);
759
+ font-weight: 500;
760
+ cursor: pointer;
761
+ }
762
+ .rq-tab:hover {
763
+ color: var(--sb-text);
764
+ }
765
+ .rq-tab.on {
766
+ color: var(--sb-text);
767
+ border-bottom-color: var(--sb-accent);
768
+ }
769
+ .rq-tab .count {
770
+ margin: 0;
771
+ padding: 0 6px;
772
+ border-radius: 999px;
773
+ background: var(--sb-surface-raised);
774
+ font-size: 11px;
775
+ font-weight: 600;
776
+ opacity: 1;
777
+ }
778
+ .rq-tab .count.bad {
779
+ background: var(--sb-danger-subtle);
780
+ color: var(--sb-danger);
781
+ }
782
+ .rq-pane {
783
+ flex: 1;
784
+ min-height: 0;
785
+ display: flex;
786
+ flex-direction: column;
787
+ padding: var(--sb-space-3) var(--sb-space-4) var(--sb-space-4);
788
+ }
789
+ /* one tab at a time, filling the panel: the page itself never scrolls */
790
+ .tab-pane {
791
+ flex: 1;
792
+ min-height: 0;
793
+ overflow: auto;
794
+ display: flex;
795
+ flex-direction: column;
796
+ }
797
+ .tab-pane[hidden] {
798
+ display: none;
799
+ }
800
+ .tab-pane > section + section {
801
+ margin-top: var(--sb-space-4);
802
+ }
803
+ .tab-gap {
804
+ flex: 1;
805
+ }
806
+ .state-dot {
807
+ padding: 0 6px;
808
+ border-radius: 999px;
809
+ font-size: 11px;
810
+ font-weight: 700;
811
+ }
812
+ .state-dot.s2 {
813
+ background: var(--sb-success-subtle);
814
+ color: var(--sb-success);
815
+ }
816
+ .state-dot.s3 {
817
+ background: var(--sb-surface-raised);
818
+ }
819
+ .state-dot.s4,
820
+ .state-dot.s5 {
821
+ background: var(--sb-warning-subtle);
822
+ color: var(--sb-warning);
823
+ }
824
+ .tab-pane > .body {
825
+ flex: 1;
826
+ min-height: 0;
827
+ display: flex;
828
+ flex-direction: column;
829
+ }
830
+ .tab-pane .body .body-editor {
831
+ flex: 1;
832
+ min-height: 120px;
833
+ max-height: none;
834
+ }
835
+ .sent-view {
836
+ display: flex;
837
+ flex-direction: column;
838
+ gap: var(--sb-space-2);
839
+ min-height: 0;
840
+ }
841
+ .sent-view .rq-bar {
842
+ padding: 0;
843
+ }
844
+ .sent-view table.headers th {
845
+ width: 200px;
846
+ font-family: var(--sb-font-mono);
847
+ font-size: 12.5px;
848
+ }
849
+ .sent-view h3 {
850
+ margin: var(--sb-space-2) 0 0;
851
+ font-size: 11px;
852
+ text-transform: uppercase;
853
+ letter-spacing: 0.06em;
854
+ color: var(--sb-text-muted);
855
+ }
856
+
857
+ /* ---- response */
858
+ .response {
859
+ flex: 1;
860
+ min-height: 0;
861
+ display: flex;
862
+ flex-direction: column;
863
+ background: var(--sb-surface);
864
+ }
865
+ .rs-head {
866
+ display: flex;
867
+ align-items: center;
868
+ gap: var(--sb-space-3);
869
+ padding: 0 0 var(--sb-space-2);
870
+ }
871
+ .rs-head h3 {
872
+ margin: 0;
873
+ font-size: 11px;
874
+ text-transform: uppercase;
875
+ letter-spacing: 0.06em;
876
+ color: var(--sb-text-muted);
877
+ }
878
+ .rs-stat {
879
+ font-size: 12px;
880
+ color: var(--sb-text-muted);
881
+ }
882
+ .sent {
883
+ margin: 0;
884
+ padding: 0 0 var(--sb-space-2);
885
+ font-size: 12px;
886
+ overflow: hidden;
887
+ text-overflow: ellipsis;
888
+ white-space: nowrap;
889
+ }
890
+ .rs-pane {
891
+ flex: 1;
892
+ min-height: 0;
893
+ display: flex;
894
+ flex-direction: column;
895
+ padding: var(--sb-space-3) 0 0;
896
+ }
897
+ .rs-pane > div {
898
+ flex: 1;
899
+ min-height: 0;
900
+ overflow: auto;
901
+ display: flex;
902
+ flex-direction: column;
903
+ }
904
+ .rs-pane > div[hidden] {
905
+ display: none;
906
+ }
907
+ .rs-pane .body-editor {
908
+ flex: 1;
909
+ min-height: 120px;
910
+ max-height: none;
911
+ }
912
+ .response .rq-tabs {
913
+ padding: 0;
914
+ }
915
+ .rs-empty {
916
+ flex: 1;
917
+ display: grid;
918
+ place-content: center;
919
+ justify-items: center;
920
+ gap: var(--sb-space-2);
921
+ padding: var(--sb-space-6);
922
+ color: var(--sb-text-muted);
923
+ }
924
+ .rs-empty strong {
925
+ color: var(--sb-text);
926
+ }
927
+ .response .checks {
928
+ margin: 0;
929
+ padding: 0;
930
+ border: 0;
931
+ }
932
+
933
+ /* ---- shared small controls */
934
+ .link {
935
+ background: none;
936
+ border: 0;
937
+ padding: 0;
938
+ color: var(--sb-accent);
939
+ cursor: pointer;
940
+ }
941
+ .link:hover {
942
+ text-decoration: underline;
943
+ }
944
+ .icon {
945
+ display: inline-grid;
946
+ place-items: center;
947
+ width: 24px;
948
+ height: 24px;
949
+ padding: 0;
950
+ background: none;
951
+ border: 0;
952
+ border-radius: 4px;
953
+ cursor: pointer;
954
+ color: var(--sb-text-muted);
955
+ font-size: 16px;
956
+ line-height: 1;
957
+ }
958
+ .icon:hover {
959
+ background: var(--sb-surface-raised);
960
+ color: var(--sb-text);
961
+ }
962
+ .small {
963
+ font-size: 12px;
964
+ }
965
+
966
+ /* ---- grid: a spreadsheet for keys and values */
967
+ .grid table {
968
+ width: 100%;
969
+ border-collapse: separate;
970
+ border-spacing: 0;
971
+ table-layout: fixed;
972
+ font-size: 13px;
973
+ border: 1px solid var(--sb-border);
974
+ border-radius: var(--sb-radius-control);
975
+ overflow: hidden;
976
+ }
977
+ .grid th {
978
+ padding: 6px 8px;
979
+ text-align: left;
980
+ font-size: 11px;
981
+ font-weight: 600;
982
+ letter-spacing: 0.04em;
983
+ text-transform: uppercase;
984
+ color: var(--sb-text-muted);
985
+ background: var(--sb-surface-raised);
986
+ border-bottom: 1px solid var(--sb-border);
987
+ }
988
+ .grid td {
989
+ padding: 0;
990
+ height: 32px;
991
+ border-bottom: 1px solid var(--sb-border);
992
+ vertical-align: middle;
993
+ background: var(--sb-surface);
994
+ }
995
+ .grid tbody tr:last-child td {
996
+ border-bottom: 0;
997
+ }
998
+ .grid td + td,
999
+ .grid th + th {
1000
+ border-left: 1px solid var(--sb-border);
1001
+ }
1002
+ .grid tbody tr:hover td {
1003
+ background: color-mix(in srgb, var(--sb-accent) 4%, var(--sb-surface));
1004
+ }
1005
+ .grid tr.bad td {
1006
+ background: var(--sb-danger-subtle);
1007
+ }
1008
+ .g-check {
1009
+ text-align: center;
1010
+ }
1011
+ .grid th {
1012
+ position: relative;
1013
+ }
1014
+ /* a thin grab area on a header's right edge, like a spreadsheet column border */
1015
+ .col-resizer {
1016
+ position: absolute;
1017
+ top: 0;
1018
+ right: -4px;
1019
+ bottom: 0;
1020
+ width: 8px;
1021
+ z-index: 2;
1022
+ cursor: col-resize;
1023
+ touch-action: none;
1024
+ }
1025
+ .col-resizer::after {
1026
+ content: "";
1027
+ position: absolute;
1028
+ inset: 4px 3px;
1029
+ border-radius: 1px;
1030
+ background: transparent;
1031
+ }
1032
+ .col-resizer:hover::after,
1033
+ .col-resizer:focus-visible::after,
1034
+ body.resizing .col-resizer::after {
1035
+ background: var(--sb-accent);
1036
+ }
1037
+ .g-check input {
1038
+ accent-color: var(--sb-accent);
1039
+ margin: 0;
1040
+ vertical-align: middle;
1041
+ }
1042
+ .g-act {
1043
+ white-space: nowrap;
1044
+ text-align: right;
1045
+ padding-right: 4px;
1046
+ }
1047
+ .g-act .icon {
1048
+ opacity: 0;
1049
+ }
1050
+ .grid tr:hover .g-act .icon,
1051
+ .grid tr:focus-within .g-act .icon {
1052
+ opacity: 1;
1053
+ }
1054
+ .g-key .key {
1055
+ display: flex;
1056
+ align-items: baseline;
1057
+ gap: 2px;
1058
+ padding: 0 8px;
1059
+ }
1060
+ .g-key code {
1061
+ font-size: 12.5px;
1062
+ }
1063
+ .g-doc {
1064
+ padding: 0 8px;
1065
+ color: var(--sb-text-muted);
1066
+ white-space: nowrap;
1067
+ overflow: hidden;
1068
+ text-overflow: ellipsis;
1069
+ }
1070
+ .grid tr.off td:not(.g-check):not(.g-act) {
1071
+ color: var(--sb-text-muted);
1072
+ }
1073
+ .grid tr.off .cell,
1074
+ .grid tr.off code {
1075
+ opacity: 0.6;
1076
+ }
1077
+ .cell {
1078
+ display: block;
1079
+ width: 100%;
1080
+ height: 31px;
1081
+ padding: 0 8px;
1082
+ border: 0;
1083
+ border-radius: 0;
1084
+ background: transparent;
1085
+ font: inherit;
1086
+ color: var(--sb-text);
1087
+ outline: none;
1088
+ }
1089
+ .cell::placeholder {
1090
+ color: color-mix(in srgb, var(--sb-text-muted) 70%, transparent);
1091
+ }
1092
+ .cell:focus,
1093
+ .file-cell:focus-within {
1094
+ background: var(--sb-surface);
1095
+ box-shadow: inset 0 0 0 2px var(--sb-accent);
1096
+ }
1097
+ .grid tr.ghost td {
1098
+ background: color-mix(in srgb, var(--sb-surface-raised) 50%, var(--sb-surface));
1099
+ }
1100
+ .file-cell {
1101
+ display: flex;
1102
+ align-items: center;
1103
+ height: 31px;
1104
+ padding: 0 8px;
1105
+ cursor: pointer;
1106
+ overflow: hidden;
1107
+ white-space: nowrap;
1108
+ text-overflow: ellipsis;
1109
+ }
1110
+ .file-cell input {
1111
+ position: absolute;
1112
+ width: 1px;
1113
+ height: 1px;
1114
+ opacity: 0;
1115
+ }
1116
+
1117
+ /* ---- enum dropdown inside a cell */
1118
+ .combo {
1119
+ position: relative;
1120
+ }
1121
+ .combo .cell {
1122
+ padding-right: 26px;
1123
+ }
1124
+ .combo-toggle {
1125
+ position: absolute;
1126
+ inset: 0 0 0 auto;
1127
+ width: 26px;
1128
+ border: 0;
1129
+ background: none;
1130
+ color: var(--sb-text-muted);
1131
+ cursor: pointer;
1132
+ }
1133
+ .combo-list {
1134
+ position: fixed;
1135
+ z-index: 30;
1136
+ margin: 0;
1137
+ padding: 4px;
1138
+ max-height: 220px;
1139
+ overflow: auto;
1140
+ background: var(--sb-surface);
1141
+ border: 1px solid var(--sb-border);
1142
+ border-radius: var(--sb-radius-control);
1143
+ box-shadow: 0 8px 24px color-mix(in srgb, var(--sb-text) 16%, transparent);
1144
+ }
1145
+ .combo-list button {
1146
+ display: block;
1147
+ width: 100%;
1148
+ padding: 5px 8px;
1149
+ border: 0;
1150
+ border-radius: 4px;
1151
+ background: none;
1152
+ text-align: left;
1153
+ cursor: pointer;
1154
+ font-family: var(--sb-font-mono);
1155
+ font-size: 12.5px;
1156
+ }
1157
+ .combo-list button:hover,
1158
+ .combo-list button.at {
1159
+ background: var(--sb-surface-raised);
1160
+ }
1161
+ .combo-list button.on {
1162
+ color: var(--sb-accent);
1163
+ font-weight: 600;
1164
+ }
1165
+
1166
+ /* ---- segmented switch, e.g. JSON | Grid for form bodies */
1167
+ .doc-project {
1168
+ margin-top: var(--sb-space-3);
1169
+ }
1170
+ .field-note {
1171
+ margin-top: var(--sb-space-2);
1172
+ padding-left: 8px;
1173
+ border-left: 2px solid var(--sb-accent);
1174
+ font-size: 12.5px;
1175
+ }
1176
+ .field-note > :first-child {
1177
+ margin-top: 0;
1178
+ }
1179
+ .field-note > :last-child {
1180
+ margin-bottom: 0;
1181
+ }
1182
+ .step-note-row td {
1183
+ padding-top: 0;
1184
+ border-top: 0;
1185
+ }
1186
+ .step-note {
1187
+ font-size: 13px;
1188
+ color: var(--sb-text-muted);
1189
+ }
1190
+ .step-note > :first-child {
1191
+ margin-top: 0;
1192
+ }
1193
+ .step-note > :last-child {
1194
+ margin-bottom: 0;
1195
+ }
1196
+ .step-about {
1197
+ margin: var(--sb-space-2) 0;
1198
+ padding: 6px 10px;
1199
+ border: 1px solid var(--sb-border);
1200
+ border-left: 3px solid var(--sb-accent);
1201
+ border-radius: var(--sb-radius-control);
1202
+ font-size: 13px;
1203
+ }
1204
+ .step-about summary {
1205
+ cursor: pointer;
1206
+ font-weight: 600;
1207
+ }
1208
+ .step-about .doc-custom {
1209
+ margin-top: var(--sb-space-2);
1210
+ }
1211
+ .code-sample {
1212
+ display: flex;
1213
+ flex-direction: column;
1214
+ gap: var(--sb-space-2);
1215
+ padding: var(--sb-space-3);
1216
+ }
1217
+ .code-head {
1218
+ display: flex;
1219
+ align-items: center;
1220
+ gap: var(--sb-space-2);
1221
+ }
1222
+ .code-block {
1223
+ margin: 0;
1224
+ padding: var(--sb-space-3);
1225
+ overflow-x: auto;
1226
+ border: 1px solid var(--sb-border);
1227
+ border-radius: var(--sb-radius-control);
1228
+ background: var(--sb-surface-raised);
1229
+ font: 12.5px / 1.55 var(--sb-font-mono);
1230
+ user-select: text;
1231
+ }
1232
+ fieldset.seg {
1233
+ margin: 0;
1234
+ padding: 0;
1235
+ min-width: 0;
1236
+ display: inline-flex;
1237
+ border: 1px solid var(--sb-border);
1238
+ border-radius: var(--sb-radius-control);
1239
+ overflow: hidden;
1240
+ }
1241
+ .seg-btn {
1242
+ padding: 2px 10px;
1243
+ border: 0;
1244
+ background: var(--sb-surface);
1245
+ color: var(--sb-text-muted);
1246
+ font-size: 12px;
1247
+ font-weight: 600;
1248
+ cursor: pointer;
1249
+ }
1250
+ .seg-btn + .seg-btn {
1251
+ border-left: 1px solid var(--sb-border);
1252
+ }
1253
+ .seg-btn.on {
1254
+ background: var(--sb-surface-raised);
1255
+ color: var(--sb-text);
1256
+ }
1257
+
1258
+ /* ---- editor */
1259
+ .body-editor {
1260
+ display: grid;
1261
+ border: 1px solid var(--sb-border);
1262
+ border-radius: var(--sb-radius-control);
1263
+ max-height: 420px;
1264
+ overflow: auto;
1265
+ background: var(--sb-code-bg);
1266
+ }
1267
+ .body-editor .prism-code-editor {
1268
+ --pce-bg: var(--sb-code-bg);
1269
+ --pce-cursor: var(--sb-text);
1270
+ --pce-selection: var(--sb-focus-ring);
1271
+ --pce-bg-highlight: var(--sb-code-line);
1272
+ --pce-line-number: var(--sb-text-muted);
1273
+ --pce-selection-match: transparent;
1274
+ --pce-widget-bg: var(--sb-surface);
1275
+ --pce-widget-border: var(--sb-border);
1276
+ --pce-widget-color-active: var(--sb-text);
1277
+ --pce-ac-match: var(--sb-accent);
1278
+ font: 12.5px / 1.6 var(--sb-font-mono);
1279
+ min-height: 3.2em;
1280
+ }
1281
+ .body-editor [class*="language-"],
1282
+ .body-editor .token.punctuation,
1283
+ .body-editor .token.operator {
1284
+ color: var(--sb-code-punct);
1285
+ }
1286
+ .body-editor .token.property,
1287
+ .body-editor .token.attr-name {
1288
+ color: var(--sb-code-key);
1289
+ }
1290
+ .body-editor .token.string {
1291
+ color: var(--sb-code-string);
1292
+ }
1293
+ .body-editor .token.number {
1294
+ color: var(--sb-code-number);
1295
+ }
1296
+ .body-editor .token.boolean,
1297
+ .body-editor .token.null,
1298
+ .body-editor .token.constant {
1299
+ color: var(--sb-code-literal);
1300
+ }
1301
+ .body-editor .token.keyword,
1302
+ .body-editor .token.class-name,
1303
+ .body-editor .token.function {
1304
+ color: var(--sb-code-keyword);
1305
+ }
1306
+ .body-editor .token.comment {
1307
+ color: var(--sb-code-comment);
1308
+ }
1309
+
1310
+ /* ---- field documentation under the editor */
1311
+ .field-doc {
1312
+ min-height: 4.5em;
1313
+ margin-top: var(--sb-space-2);
1314
+ padding: var(--sb-space-2) var(--sb-space-3);
1315
+ border-left: 3px solid var(--sb-accent);
1316
+ background: var(--sb-surface);
1317
+ font-size: 13px;
1318
+ }
1319
+ /* docked to the bottom of whatever scrolls it, so a short window never leaves it below the fold */
1320
+ .tab-pane > .field-doc,
1321
+ .tab-pane .body > .field-doc,
1322
+ .sent-view > .field-doc,
1323
+ .rs-pane > div > .field-doc {
1324
+ position: sticky;
1325
+ bottom: 0;
1326
+ z-index: 1;
1327
+ }
1328
+ .field-doc.empty {
1329
+ border-left-color: var(--sb-border);
1330
+ color: var(--sb-text-muted);
1331
+ }
1332
+ .field-doc p {
1333
+ margin: 4px 0 0;
1334
+ }
1335
+ .field-doc-text {
1336
+ max-height: 11em;
1337
+ overflow: auto;
1338
+ margin-top: 4px;
1339
+ }
1340
+ .field-doc-text :is(p, ul, ol, pre) {
1341
+ margin: 0 0 var(--sb-space-2);
1342
+ }
1343
+ .field-doc-text :is(ul, ol) {
1344
+ padding-left: 1.3em;
1345
+ }
1346
+ .field-doc-text pre {
1347
+ padding: var(--sb-space-2);
1348
+ background: var(--sb-surface-raised);
1349
+ border-radius: var(--sb-radius-control);
1350
+ overflow: auto;
1351
+ }
1352
+ .field-doc-text :is(h2, h3, h4, h5) {
1353
+ margin: var(--sb-space-2) 0 var(--sb-space-1);
1354
+ font-size: 13px;
1355
+ text-transform: none;
1356
+ letter-spacing: 0;
1357
+ color: var(--sb-text);
1358
+ }
1359
+ .doc-inline a,
1360
+ .field-doc-text a {
1361
+ color: var(--sb-accent);
1362
+ }
1363
+ .doc-inline code,
1364
+ .field-doc-text code {
1365
+ padding: 0 4px;
1366
+ border-radius: 3px;
1367
+ background: var(--sb-surface-raised);
1368
+ }
1369
+ .field-doc-head {
1370
+ display: flex;
1371
+ align-items: center;
1372
+ gap: var(--sb-space-2);
1373
+ flex-wrap: wrap;
1374
+ }
1375
+ .field-doc-enum code {
1376
+ margin-right: 6px;
1377
+ }
1378
+ .issues {
1379
+ margin-top: var(--sb-space-2);
1380
+ font-size: 12px;
1381
+ }
1382
+
1383
+ /* ---- sequence panel: |timeline|exchange| */
1384
+ .sequence-panel {
1385
+ display: grid;
1386
+ grid-template-columns: minmax(300px, 4fr) minmax(0, 7fr);
1387
+ height: 100%;
1388
+ min-height: 0;
1389
+ }
1390
+ @media (max-width: 900px) {
1391
+ .sequence-panel {
1392
+ grid-template-columns: minmax(0, 1fr);
1393
+ overflow: auto;
1394
+ }
1395
+ }
1396
+ .seq-left {
1397
+ min-height: 0;
1398
+ overflow: auto;
1399
+ padding: var(--sb-space-4);
1400
+ background: var(--sb-bg);
1401
+ border-right: 1px solid var(--sb-border);
1402
+ }
1403
+ .controls-grid {
1404
+ container-type: inline-size;
1405
+ margin-bottom: var(--sb-space-3);
1406
+ }
1407
+ .controls-grid col.c-key {
1408
+ width: 30%;
1409
+ }
1410
+ .controls-grid col.c-val {
1411
+ width: 40%;
1412
+ }
1413
+ @container (max-width: 520px) {
1414
+ .controls-grid .g-doc,
1415
+ .controls-grid th.g-doc {
1416
+ display: none;
1417
+ }
1418
+ .controls-grid col.c-key {
1419
+ width: 40%;
1420
+ }
1421
+ .controls-grid col.c-val {
1422
+ width: 60%;
1423
+ }
1424
+ }
1425
+ .multi-cell {
1426
+ display: flex;
1427
+ flex-wrap: wrap;
1428
+ gap: 4px 12px;
1429
+ padding: 6px 8px;
1430
+ }
1431
+ .multi-cell label {
1432
+ display: inline-flex;
1433
+ align-items: center;
1434
+ gap: 4px;
1435
+ }
1436
+ .cell.mono {
1437
+ font-family: var(--sb-font-mono);
1438
+ font-size: 12.5px;
1439
+ }
1440
+ .doc-tags {
1441
+ display: flex;
1442
+ gap: var(--sb-space-1);
1443
+ margin: 0 0 var(--sb-space-3);
1444
+ }
1445
+ .doc .link {
1446
+ text-align: left;
1447
+ }
1448
+ .pause .controls-grid {
1449
+ margin: var(--sb-space-2) 0;
1450
+ }
1451
+ .step-exchange {
1452
+ display: flex;
1453
+ flex-direction: column;
1454
+ height: 100%;
1455
+ min-height: 0;
1456
+ }
1457
+ .seq-left .controls {
1458
+ padding: var(--sb-space-3) var(--sb-space-4);
1459
+ margin-bottom: var(--sb-space-3);
1460
+ background: var(--sb-surface);
1461
+ border: 1px solid var(--sb-border);
1462
+ border-radius: var(--sb-radius-card);
1463
+ }
1464
+ .seq-left .controls h3 {
1465
+ margin: 0 0 var(--sb-space-2);
1466
+ font-size: 11px;
1467
+ text-transform: uppercase;
1468
+ letter-spacing: 0.06em;
1469
+ color: var(--sb-text-muted);
1470
+ }
1471
+ .seq-run {
1472
+ display: flex;
1473
+ align-items: center;
1474
+ gap: var(--sb-space-3);
1475
+ flex-wrap: wrap;
1476
+ margin-bottom: var(--sb-space-4);
1477
+ }
1478
+ .seq-left .journey {
1479
+ padding: var(--sb-space-1) 0;
1480
+ }
1481
+ .seq-left .jhead {
1482
+ font-size: 13px;
1483
+ }
1484
+ .seq-right {
1485
+ min-height: 0;
1486
+ display: flex;
1487
+ flex-direction: column;
1488
+ overflow: auto;
1489
+ background: var(--sb-surface);
1490
+ }
1491
+ .seq-right .response {
1492
+ padding: var(--sb-space-3) var(--sb-space-4) 0;
1493
+ }
1494
+ .seq-req {
1495
+ flex: 0 0 auto;
1496
+ border-bottom: 1px solid var(--sb-border);
1497
+ }
1498
+ .seq-req .rq-bar {
1499
+ padding-bottom: var(--sb-space-3);
1500
+ }
1501
+ .seq-req .rq-pane {
1502
+ padding-top: 0;
1503
+ }
1504
+ .seq-req .body-editor {
1505
+ max-height: 200px;
1506
+ }
1507
+ .jstep.picked .jhead .jname {
1508
+ text-decoration: underline;
1509
+ text-underline-offset: 3px;
1510
+ }
1511
+
1512
+ /* ---- environment settings (header) */
1513
+ .envmenu {
1514
+ position: relative;
1515
+ }
1516
+ .envmenu-btn {
1517
+ display: inline-flex;
1518
+ align-items: center;
1519
+ gap: 6px;
1520
+ white-space: nowrap;
1521
+ }
1522
+ .badge-missing {
1523
+ min-width: 18px;
1524
+ padding: 0 5px;
1525
+ border-radius: 999px;
1526
+ background: var(--sb-danger);
1527
+ color: var(--sb-text-on-danger);
1528
+ font-size: 11px;
1529
+ font-weight: 700;
1530
+ text-align: center;
1531
+ }
1532
+ .envmenu-pop {
1533
+ position: absolute;
1534
+ right: 0;
1535
+ top: calc(100% + 8px);
1536
+ z-index: 40;
1537
+ width: min(460px, 92vw);
1538
+ max-height: min(70vh, 640px);
1539
+ overflow: auto;
1540
+ display: grid;
1541
+ gap: var(--sb-space-3);
1542
+ padding: var(--sb-space-3) var(--sb-space-4);
1543
+ background: var(--sb-surface);
1544
+ border: 1px solid var(--sb-border);
1545
+ border-radius: var(--sb-radius-card);
1546
+ box-shadow: 0 12px 32px color-mix(in srgb, var(--sb-text) 20%, transparent);
1547
+ }
1548
+ .envmenu-head {
1549
+ display: flex;
1550
+ align-items: center;
1551
+ gap: var(--sb-space-3);
1552
+ }
1553
+ .envmenu-pop h3 {
1554
+ margin: 0 0 var(--sb-space-1);
1555
+ font-size: 11px;
1556
+ text-transform: uppercase;
1557
+ letter-spacing: 0.06em;
1558
+ color: var(--sb-text-muted);
1559
+ }
1560
+ .envmenu-pop p {
1561
+ margin: 0;
1562
+ }
1563
+ .envmenu-warn {
1564
+ padding: var(--sb-space-2) var(--sb-space-3);
1565
+ border-radius: var(--sb-radius-control);
1566
+ background: var(--sb-warning-subtle);
1567
+ color: var(--sb-warning);
1568
+ font-size: 12.5px;
1569
+ }
1570
+ .envrow {
1571
+ display: flex;
1572
+ align-items: center;
1573
+ gap: var(--sb-space-2);
1574
+ margin-top: var(--sb-space-2);
1575
+ }
1576
+ .envrow input,
1577
+ .envrow select {
1578
+ flex: 1;
1579
+ min-width: 0;
1580
+ padding: 5px 8px;
1581
+ border: 1px solid var(--sb-border);
1582
+ border-radius: var(--sb-radius-control);
1583
+ background: var(--sb-surface);
1584
+ }
1585
+ .envrow code {
1586
+ flex: 0 0 38%;
1587
+ overflow: hidden;
1588
+ text-overflow: ellipsis;
1589
+ }
1590
+ .secretrow {
1591
+ margin-top: var(--sb-space-3);
1592
+ }
1593
+ .secretrow-head {
1594
+ display: flex;
1595
+ align-items: baseline;
1596
+ gap: var(--sb-space-2);
1597
+ font-size: 13px;
1598
+ }
1599
+ .secretrow-head .src {
1600
+ margin-left: auto;
1601
+ padding: 0 8px;
1602
+ border-radius: 999px;
1603
+ font-size: 11px;
1604
+ font-weight: 600;
1605
+ }
1606
+ .src.set {
1607
+ background: var(--sb-success-subtle);
1608
+ color: var(--sb-success);
1609
+ }
1610
+ .src.missing {
1611
+ background: var(--sb-danger-subtle);
1612
+ color: var(--sb-danger);
1613
+ }
1614
+ .op-lock {
1615
+ display: inline-block;
1616
+ margin-left: 6px;
1617
+ color: var(--sb-text-muted);
1618
+ vertical-align: -1px;
1619
+ }
1620
+
1621
+ /* ---- list resizer: straddles the edge between the list and the stage/panel */
1622
+ .list-resizer {
1623
+ position: fixed;
1624
+ z-index: 25;
1625
+ top: var(--sb-header-h, 53px);
1626
+ bottom: 0;
1627
+ left: calc(var(--sb-list-w) - 4px);
1628
+ width: 8px;
1629
+ cursor: col-resize;
1630
+ touch-action: none;
1631
+ }
1632
+ .list-resizer::after {
1633
+ content: "";
1634
+ position: absolute;
1635
+ inset: 0 3px;
1636
+ background: transparent;
1637
+ transition: background 120ms;
1638
+ }
1639
+ .list-resizer:hover::after,
1640
+ .list-resizer:focus-visible::after,
1641
+ body.resizing .list-resizer::after {
1642
+ background: var(--sb-accent);
1643
+ }
1644
+ body.resizing {
1645
+ cursor: col-resize;
1646
+ user-select: none;
1647
+ }
1648
+ @media (max-width: 900px) {
1649
+ .list-resizer {
1650
+ display: none;
1651
+ }
1652
+ }
1653
+ }
1654
+
1655
+ @layer components {
1656
+ /* a phone: the panel is a full-screen sheet over the list, not a column beside it */
1657
+ @media (max-width: 820px) {
1658
+ .panel,
1659
+ .panel.docked {
1660
+ inset: 0;
1661
+ width: 100%;
1662
+ min-width: 0;
1663
+ /* under the browser's address bar; iOS pans the keyboard's cover over it rather than resizing */
1664
+ height: 100dvh;
1665
+ border-left: 0;
1666
+ box-shadow: none;
1667
+ }
1668
+ /* iOS zooms the page when a field under 16px is focused; the code editors included */
1669
+ input,
1670
+ select,
1671
+ textarea,
1672
+ .body-editor .prism-code-editor,
1673
+ .body-editor .prism-code-editor textarea {
1674
+ font-size: 16px;
1675
+ }
1676
+ .body-editor .prism-code-editor {
1677
+ line-height: 1.5;
1678
+ }
1679
+ .panel-head {
1680
+ padding: var(--sb-space-2) var(--sb-space-3);
1681
+ gap: var(--sb-space-2);
1682
+ }
1683
+ /* one row: the title (two lines at most) and the stepper and close beside it */
1684
+ .panel-head {
1685
+ flex-wrap: nowrap;
1686
+ }
1687
+ .panel-title {
1688
+ flex: 1 1 0;
1689
+ min-width: 0;
1690
+ }
1691
+ .panel-head h2 {
1692
+ display: -webkit-box;
1693
+ -webkit-box-orient: vertical;
1694
+ -webkit-line-clamp: 2;
1695
+ line-clamp: 2;
1696
+ overflow: hidden;
1697
+ overflow-wrap: anywhere;
1698
+ line-height: 1.25;
1699
+ }
1700
+ .panel-title > .muted {
1701
+ overflow: hidden;
1702
+ text-overflow: ellipsis;
1703
+ white-space: nowrap;
1704
+ }
1705
+ .panel-head .spacer {
1706
+ display: none;
1707
+ }
1708
+ .panel-head label.row > .muted {
1709
+ display: none;
1710
+ }
1711
+ .panel-head select {
1712
+ max-width: 34%;
1713
+ }
1714
+ .stepper {
1715
+ gap: 0;
1716
+ }
1717
+ .panel-head .icon {
1718
+ min-width: 36px;
1719
+ min-height: 36px;
1720
+ }
1721
+ .panel-main.scroll {
1722
+ padding: var(--sb-space-3);
1723
+ }
1724
+ .doc-intro {
1725
+ flex-wrap: wrap;
1726
+ }
1727
+ /* a long path breaks inside its box instead of pushing the page wider */
1728
+ .doc-intro code {
1729
+ flex: 1 1 0;
1730
+ min-width: 0;
1731
+ overflow-wrap: anywhere;
1732
+ }
1733
+ .doc-intro .spacer {
1734
+ display: none;
1735
+ }
1736
+ /* anything else wide in the docs scrolls on its own, never the whole panel */
1737
+ .doc pre,
1738
+ .doc-custom pre {
1739
+ max-width: 100%;
1740
+ overflow-x: auto;
1741
+ }
1742
+ .doc img {
1743
+ max-width: 100%;
1744
+ height: auto;
1745
+ }
1746
+ .doc-custom table {
1747
+ display: block;
1748
+ max-width: 100%;
1749
+ overflow-x: auto;
1750
+ }
1751
+ .panel-main.scroll {
1752
+ overflow-x: hidden;
1753
+ }
1754
+ /* Environment settings: a sheet over the whole viewport rather than a popover beside its button */
1755
+ .envmenu {
1756
+ position: static;
1757
+ }
1758
+ .envmenu-pop {
1759
+ position: fixed;
1760
+ inset: var(--sb-space-2);
1761
+ width: auto;
1762
+ max-height: none;
1763
+ z-index: 40;
1764
+ }
1765
+ .envrow {
1766
+ flex-wrap: wrap;
1767
+ }
1768
+ .envrow input,
1769
+ .envrow select {
1770
+ min-width: 0;
1771
+ max-width: 100%;
1772
+ }
1773
+ /* wide tables scroll sideways inside the panel instead of being cut off */
1774
+ table.fields {
1775
+ display: block;
1776
+ max-width: 100%;
1777
+ overflow-x: auto;
1778
+ }
1779
+ /* descriptions keep to a line or two and the table scrolls sideways rather than stacking words */
1780
+ table.fields td:last-child {
1781
+ min-width: 440px;
1782
+ }
1783
+ table.fields td:first-child {
1784
+ white-space: nowrap;
1785
+ }
1786
+ .rq-meta {
1787
+ flex-wrap: wrap;
1788
+ padding-inline: var(--sb-space-3);
1789
+ }
1790
+ /* the credentials note is in the chip's tooltip; not worth a line of a phone screen */
1791
+ .secrets-note {
1792
+ display: none;
1793
+ }
1794
+ .secrets-folded,
1795
+ .needs-vars {
1796
+ margin-inline: var(--sb-space-3);
1797
+ }
1798
+ .rq-example {
1799
+ display: flex;
1800
+ align-items: center;
1801
+ gap: var(--sb-space-2);
1802
+ flex: 1 1 100%;
1803
+ min-width: 0;
1804
+ }
1805
+ .rq-example > label.row {
1806
+ flex: 1 1 0;
1807
+ min-width: 0;
1808
+ }
1809
+ .rq-example > label.row select {
1810
+ flex: 1 1 0;
1811
+ min-width: 0;
1812
+ text-overflow: ellipsis;
1813
+ }
1814
+ /* "Respond with" sits under Example like a small form: same label width, so the two selects start at
1815
+ the same edge, and the second fills the row. It comes before any Edited / Reset / Save links. */
1816
+ .rq-status {
1817
+ order: 1;
1818
+ flex: 1 1 100%;
1819
+ min-width: 0;
1820
+ /* the same gap as the Example row's label, or the selects start a few pixels apart */
1821
+ gap: var(--sb-space-3);
1822
+ }
1823
+ .rq-status > select {
1824
+ flex: 1 1 0;
1825
+ min-width: 0;
1826
+ text-overflow: ellipsis;
1827
+ }
1828
+ .rq-example > label.row > .muted,
1829
+ .rq-status > .muted {
1830
+ flex: 0 0 84px;
1831
+ }
1832
+ .rq-meta > .edited,
1833
+ .rq-meta > .spacer,
1834
+ .rq-meta > .link {
1835
+ order: 2;
1836
+ }
1837
+ .rq-meta select {
1838
+ max-width: 100%;
1839
+ min-width: 0;
1840
+ }
1841
+ button,
1842
+ select,
1843
+ input:not([type="checkbox"]):not([type="radio"]) {
1844
+ min-height: 36px;
1845
+ }
1846
+ }
1847
+ }
1848
+
1849
+ @layer components {
1850
+ .sheet-close {
1851
+ display: none;
1852
+ }
1853
+ /* a phone: the selected step's request and response rise from the bottom of the visible screen */
1854
+ @media (max-width: 820px) {
1855
+ .sequence-panel {
1856
+ overflow: auto;
1857
+ /* room under the last step, so the sheet never hides it */
1858
+ padding-bottom: 8px;
1859
+ }
1860
+ /* with the sheet up, the timeline can still scroll its last steps above it */
1861
+ .sequence-panel.sheet-open .seq-left {
1862
+ padding-bottom: 62vh;
1863
+ }
1864
+ .seq-right {
1865
+ display: none;
1866
+ }
1867
+ .seq-right.sheet-open {
1868
+ display: flex;
1869
+ position: absolute;
1870
+ inset: auto 0 0 0;
1871
+ height: min(62%, 520px);
1872
+ z-index: 5;
1873
+ border-top: 1px solid var(--sb-border);
1874
+ border-radius: 14px 14px 0 0;
1875
+ box-shadow: 0 -12px 32px color-mix(in srgb, var(--sb-text) 22%, transparent);
1876
+ overflow: auto;
1877
+ overscroll-behavior: contain;
1878
+ }
1879
+ .seq-right .sheet-close {
1880
+ display: flex;
1881
+ align-items: center;
1882
+ gap: var(--sb-space-2);
1883
+ position: sticky;
1884
+ top: 0;
1885
+ z-index: 2;
1886
+ flex: 0 0 auto;
1887
+ min-height: 44px;
1888
+ padding: 0 var(--sb-space-4);
1889
+ border: 0;
1890
+ border-bottom: 1px solid var(--sb-border);
1891
+ background: var(--sb-surface);
1892
+ font-weight: 600;
1893
+ text-align: left;
1894
+ color: var(--sb-text);
1895
+ }
1896
+ }
1897
+ }