@specbook/ui 0.0.0-stage → 0.2.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 (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -2
  3. package/dist-viewer/THIRD-PARTY-NOTICES.txt +581 -0
  4. package/dist-viewer/apple-touch-icon.png +0 -0
  5. package/dist-viewer/assets/Host-CSrM9wY1.js +37 -0
  6. package/dist-viewer/assets/faker-B3c03STC.js +11 -0
  7. package/dist-viewer/assets/index-Ds6DZpGP.css +1 -0
  8. package/dist-viewer/assets/index-ez9c20v3.js +1 -0
  9. package/dist-viewer/assets/main-38QGGpNT.js +14 -0
  10. package/dist-viewer/assets/mount-CGL2tOpN.js +2 -0
  11. package/dist-viewer/assets/panel-C-vBZrep.css +1 -0
  12. package/dist-viewer/assets/panel-C8Ve3LeS.js +1 -0
  13. package/dist-viewer/assets/registry-ChKCFBt1.js +2 -0
  14. package/dist-viewer/assets/worker-ClGb0tE1.js +181 -0
  15. package/dist-viewer/favicon.svg +1 -0
  16. package/dist-viewer/index.html +19 -0
  17. package/dist-viewer/specbook.js +1 -0
  18. package/index.html +12 -0
  19. package/package.json +61 -3
  20. package/src/app.tsx +368 -0
  21. package/src/assets/mark.svg +1 -0
  22. package/src/badge.ts +14 -0
  23. package/src/branding.ts +92 -0
  24. package/src/components/Catalog.tsx +324 -0
  25. package/src/components/EnvBadge.tsx +48 -0
  26. package/src/components/EnvironmentMenu.tsx +262 -0
  27. package/src/components/Fields.tsx +220 -0
  28. package/src/components/GitHubStar.tsx +22 -0
  29. package/src/components/ListResizer.tsx +70 -0
  30. package/src/components/ModeHint.tsx +17 -0
  31. package/src/components/Palette.tsx +85 -0
  32. package/src/components/PoweredBy.tsx +15 -0
  33. package/src/components/ShareMenu.tsx +94 -0
  34. package/src/components/ThemeToggle.tsx +52 -0
  35. package/src/embed/panel.tsx +115 -0
  36. package/src/embed/styles.ts +27 -0
  37. package/src/embed.ts +65 -0
  38. package/src/engine.ts +574 -0
  39. package/src/extension.ts +101 -0
  40. package/src/fielddoc.ts +83 -0
  41. package/src/main.tsx +24 -0
  42. package/src/markdown.ts +133 -0
  43. package/src/nav.ts +118 -0
  44. package/src/oauth-callback.ts +87 -0
  45. package/src/oauth.ts +194 -0
  46. package/src/panel/Body.tsx +182 -0
  47. package/src/panel/BodyEditor.tsx +92 -0
  48. package/src/panel/CodeSample.tsx +238 -0
  49. package/src/panel/Combo.tsx +124 -0
  50. package/src/panel/ControlsGrid.tsx +189 -0
  51. package/src/panel/FieldDoc.tsx +42 -0
  52. package/src/panel/FieldTable.tsx +113 -0
  53. package/src/panel/Host.tsx +100 -0
  54. package/src/panel/OAuthSignIn.tsx +163 -0
  55. package/src/panel/OperationDocs.tsx +181 -0
  56. package/src/panel/Panel.tsx +197 -0
  57. package/src/panel/ParamGrid.tsx +396 -0
  58. package/src/panel/RequestPanel.tsx +627 -0
  59. package/src/panel/RequestView.tsx +108 -0
  60. package/src/panel/ResponseView.tsx +182 -0
  61. package/src/panel/SecretsBar.tsx +189 -0
  62. package/src/panel/SequenceDocs.tsx +132 -0
  63. package/src/panel/SequencePanel.tsx +247 -0
  64. package/src/panel/StepExchange.tsx +118 -0
  65. package/src/panel/completions.ts +114 -0
  66. package/src/panel/draft.ts +106 -0
  67. package/src/panel/fieldnotes-split.ts +55 -0
  68. package/src/panel/fieldnotes.ts +40 -0
  69. package/src/panel/graphql.ts +31 -0
  70. package/src/panel/icons.tsx +85 -0
  71. package/src/panel/jsonCursor.ts +115 -0
  72. package/src/panel/stepnotes-split.ts +38 -0
  73. package/src/panel/stepnotes.ts +58 -0
  74. package/src/routing.ts +120 -0
  75. package/src/runtime.ts +32 -0
  76. package/src/schema.ts +359 -0
  77. package/src/secrets.ts +61 -0
  78. package/src/status.ts +27 -0
  79. package/src/store.ts +12 -0
  80. package/src/styles/app.css +821 -0
  81. package/src/styles/panel.css +1939 -0
  82. package/src/styles/tokens.css +122 -0
  83. package/src/theme.ts +37 -0
  84. package/src/viewer/Opening.tsx +43 -0
  85. package/src/viewer/bundles.ts +74 -0
  86. package/src/viewer/client.ts +54 -0
  87. package/src/viewer/embed.ts +83 -0
  88. package/src/viewer/faker-en.ts +3 -0
  89. package/src/viewer/main.tsx +289 -0
  90. package/src/viewer/mount.ts +52 -0
  91. package/src/viewer/protocol.ts +54 -0
  92. package/src/viewer/recent.ts +22 -0
  93. package/src/viewer/registry-data.ts +8 -0
  94. package/src/viewer/registry.ts +163 -0
  95. package/src/viewer/share.ts +134 -0
  96. package/src/viewer/site.ts +3 -0
  97. package/src/viewer/uploads.ts +53 -0
  98. package/src/viewer/viewer.css +184 -0
  99. package/src/viewer/worker-factory.ts +14 -0
  100. package/src/viewer/worker.ts +176 -0
  101. package/src/virtual.d.ts +104 -0
@@ -0,0 +1,1939 @@
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
+ flex-wrap: wrap;
719
+ align-items: center;
720
+ gap: 6px;
721
+ min-width: 0;
722
+ max-width: 100%;
723
+ }
724
+ .needs-var input {
725
+ width: 130px;
726
+ min-width: 0;
727
+ }
728
+ /* the pasted value looks like the client id field beside it */
729
+ .needs-var input[type="password"] {
730
+ padding: 5px 8px;
731
+ border: 1px solid var(--sb-border);
732
+ border-radius: var(--sb-radius-control);
733
+ background: var(--sb-surface);
734
+ }
735
+ /* Sign in: its own row inside the credential, so the client id, the button, the scopes and the status
736
+ wrap under each other on a narrow screen instead of running off the edge */
737
+ .oauth-signin {
738
+ flex: 1 1 100%;
739
+ }
740
+ .oauth-signin input[type="text"] {
741
+ flex: 1 1 140px;
742
+ width: auto;
743
+ max-width: 360px;
744
+ }
745
+ .oauth-signin details {
746
+ flex: 1 1 100%;
747
+ min-width: 0;
748
+ }
749
+ .oauth-signin input[type="checkbox"] {
750
+ flex: 0 0 auto;
751
+ width: auto;
752
+ }
753
+ .oauth-signin details label {
754
+ display: flex;
755
+ align-items: center;
756
+ gap: 6px;
757
+ min-height: 28px;
758
+ overflow-wrap: anywhere;
759
+ }
760
+ .oauth-status {
761
+ flex: 1 1 100%;
762
+ min-width: 0;
763
+ overflow-wrap: anywhere;
764
+ }
765
+ .rq-meta {
766
+ display: flex;
767
+ align-items: center;
768
+ gap: var(--sb-space-3);
769
+ padding: var(--sb-space-1) var(--sb-space-4) var(--sb-space-3);
770
+ font-size: 12px;
771
+ }
772
+ .edited {
773
+ font-size: 11px;
774
+ font-weight: 600;
775
+ color: var(--sb-warning);
776
+ background: var(--sb-warning-subtle);
777
+ border-radius: 999px;
778
+ padding: 1px 8px;
779
+ }
780
+ .rq-tabs {
781
+ display: flex;
782
+ gap: var(--sb-space-1);
783
+ padding: 0 var(--sb-space-4);
784
+ border-bottom: 1px solid var(--sb-border);
785
+ }
786
+ .rq-tabs[hidden] {
787
+ display: none;
788
+ }
789
+ .rq-tab {
790
+ display: inline-flex;
791
+ align-items: center;
792
+ gap: 6px;
793
+ padding: 8px 10px;
794
+ margin-bottom: -1px;
795
+ border: 0;
796
+ border-bottom: 2px solid transparent;
797
+ background: none;
798
+ color: var(--sb-text-muted);
799
+ font-weight: 500;
800
+ cursor: pointer;
801
+ }
802
+ .rq-tab:hover {
803
+ color: var(--sb-text);
804
+ }
805
+ .rq-tab.on {
806
+ color: var(--sb-text);
807
+ border-bottom-color: var(--sb-accent);
808
+ }
809
+ .rq-tab .count {
810
+ margin: 0;
811
+ padding: 0 6px;
812
+ border-radius: 999px;
813
+ background: var(--sb-surface-raised);
814
+ font-size: 11px;
815
+ font-weight: 600;
816
+ opacity: 1;
817
+ }
818
+ .rq-tab .count.bad {
819
+ background: var(--sb-danger-subtle);
820
+ color: var(--sb-danger);
821
+ }
822
+ .rq-pane {
823
+ flex: 1;
824
+ min-height: 0;
825
+ display: flex;
826
+ flex-direction: column;
827
+ padding: var(--sb-space-3) var(--sb-space-4) var(--sb-space-4);
828
+ }
829
+ /* one tab at a time, filling the panel: the page itself never scrolls */
830
+ .tab-pane {
831
+ flex: 1;
832
+ min-height: 0;
833
+ overflow: auto;
834
+ display: flex;
835
+ flex-direction: column;
836
+ }
837
+ .tab-pane[hidden] {
838
+ display: none;
839
+ }
840
+ .tab-pane > section + section {
841
+ margin-top: var(--sb-space-4);
842
+ }
843
+ .tab-gap {
844
+ flex: 1;
845
+ }
846
+ .state-dot {
847
+ padding: 0 6px;
848
+ border-radius: 999px;
849
+ font-size: 11px;
850
+ font-weight: 700;
851
+ }
852
+ .state-dot.s2 {
853
+ background: var(--sb-success-subtle);
854
+ color: var(--sb-success);
855
+ }
856
+ .state-dot.s3 {
857
+ background: var(--sb-surface-raised);
858
+ }
859
+ .state-dot.s4,
860
+ .state-dot.s5 {
861
+ background: var(--sb-warning-subtle);
862
+ color: var(--sb-warning);
863
+ }
864
+ .tab-pane > .body {
865
+ flex: 1;
866
+ min-height: 0;
867
+ display: flex;
868
+ flex-direction: column;
869
+ }
870
+ .tab-pane .body .body-editor {
871
+ flex: 1;
872
+ min-height: 120px;
873
+ max-height: none;
874
+ }
875
+ .sent-view {
876
+ display: flex;
877
+ flex-direction: column;
878
+ gap: var(--sb-space-2);
879
+ min-height: 0;
880
+ }
881
+ .sent-view .rq-bar {
882
+ padding: 0;
883
+ }
884
+ .sent-view table.headers th {
885
+ width: 200px;
886
+ font-family: var(--sb-font-mono);
887
+ font-size: 12.5px;
888
+ }
889
+ .sent-view h3 {
890
+ margin: var(--sb-space-2) 0 0;
891
+ font-size: 11px;
892
+ text-transform: uppercase;
893
+ letter-spacing: 0.06em;
894
+ color: var(--sb-text-muted);
895
+ }
896
+
897
+ /* ---- response */
898
+ .response {
899
+ flex: 1;
900
+ min-height: 0;
901
+ display: flex;
902
+ flex-direction: column;
903
+ background: var(--sb-surface);
904
+ }
905
+ .rs-head {
906
+ display: flex;
907
+ align-items: center;
908
+ gap: var(--sb-space-3);
909
+ padding: 0 0 var(--sb-space-2);
910
+ }
911
+ .rs-head h3 {
912
+ margin: 0;
913
+ font-size: 11px;
914
+ text-transform: uppercase;
915
+ letter-spacing: 0.06em;
916
+ color: var(--sb-text-muted);
917
+ }
918
+ .rs-stat {
919
+ font-size: 12px;
920
+ color: var(--sb-text-muted);
921
+ }
922
+ .sent {
923
+ margin: 0;
924
+ padding: 0 0 var(--sb-space-2);
925
+ font-size: 12px;
926
+ overflow: hidden;
927
+ text-overflow: ellipsis;
928
+ white-space: nowrap;
929
+ }
930
+ .rs-pane {
931
+ flex: 1;
932
+ min-height: 0;
933
+ display: flex;
934
+ flex-direction: column;
935
+ padding: var(--sb-space-3) 0 0;
936
+ }
937
+ .rs-pane > div {
938
+ flex: 1;
939
+ min-height: 0;
940
+ overflow: auto;
941
+ display: flex;
942
+ flex-direction: column;
943
+ }
944
+ .rs-pane > div[hidden] {
945
+ display: none;
946
+ }
947
+ .rs-pane .body-editor {
948
+ flex: 1;
949
+ min-height: 120px;
950
+ max-height: none;
951
+ }
952
+ .response .rq-tabs {
953
+ padding: 0;
954
+ }
955
+ .rs-empty {
956
+ flex: 1;
957
+ display: grid;
958
+ place-content: center;
959
+ justify-items: center;
960
+ gap: var(--sb-space-2);
961
+ padding: var(--sb-space-6);
962
+ color: var(--sb-text-muted);
963
+ }
964
+ .rs-empty strong {
965
+ color: var(--sb-text);
966
+ }
967
+ .response .checks {
968
+ margin: 0;
969
+ padding: 0;
970
+ border: 0;
971
+ }
972
+
973
+ /* ---- shared small controls */
974
+ .link {
975
+ background: none;
976
+ border: 0;
977
+ padding: 0;
978
+ color: var(--sb-accent);
979
+ cursor: pointer;
980
+ }
981
+ .link:hover {
982
+ text-decoration: underline;
983
+ }
984
+ .icon {
985
+ display: inline-grid;
986
+ place-items: center;
987
+ width: 24px;
988
+ height: 24px;
989
+ padding: 0;
990
+ background: none;
991
+ border: 0;
992
+ border-radius: 4px;
993
+ cursor: pointer;
994
+ color: var(--sb-text-muted);
995
+ font-size: 16px;
996
+ line-height: 1;
997
+ }
998
+ .icon:hover {
999
+ background: var(--sb-surface-raised);
1000
+ color: var(--sb-text);
1001
+ }
1002
+ .small {
1003
+ font-size: 12px;
1004
+ }
1005
+
1006
+ /* ---- grid: a spreadsheet for keys and values */
1007
+ .grid table {
1008
+ width: 100%;
1009
+ border-collapse: separate;
1010
+ border-spacing: 0;
1011
+ table-layout: fixed;
1012
+ font-size: 13px;
1013
+ border: 1px solid var(--sb-border);
1014
+ border-radius: var(--sb-radius-control);
1015
+ overflow: hidden;
1016
+ }
1017
+ .grid th {
1018
+ padding: 6px 8px;
1019
+ text-align: left;
1020
+ font-size: 11px;
1021
+ font-weight: 600;
1022
+ letter-spacing: 0.04em;
1023
+ text-transform: uppercase;
1024
+ color: var(--sb-text-muted);
1025
+ background: var(--sb-surface-raised);
1026
+ border-bottom: 1px solid var(--sb-border);
1027
+ }
1028
+ .grid td {
1029
+ padding: 0;
1030
+ height: 32px;
1031
+ border-bottom: 1px solid var(--sb-border);
1032
+ vertical-align: middle;
1033
+ background: var(--sb-surface);
1034
+ }
1035
+ .grid tbody tr:last-child td {
1036
+ border-bottom: 0;
1037
+ }
1038
+ .grid td + td,
1039
+ .grid th + th {
1040
+ border-left: 1px solid var(--sb-border);
1041
+ }
1042
+ .grid tbody tr:hover td {
1043
+ background: color-mix(in srgb, var(--sb-accent) 4%, var(--sb-surface));
1044
+ }
1045
+ .grid tr.bad td {
1046
+ background: var(--sb-danger-subtle);
1047
+ }
1048
+ .g-check {
1049
+ text-align: center;
1050
+ }
1051
+ .grid th {
1052
+ position: relative;
1053
+ }
1054
+ /* a thin grab area on a header's right edge, like a spreadsheet column border */
1055
+ .col-resizer {
1056
+ position: absolute;
1057
+ top: 0;
1058
+ right: -4px;
1059
+ bottom: 0;
1060
+ width: 8px;
1061
+ z-index: 2;
1062
+ cursor: col-resize;
1063
+ touch-action: none;
1064
+ }
1065
+ .col-resizer::after {
1066
+ content: "";
1067
+ position: absolute;
1068
+ inset: 4px 3px;
1069
+ border-radius: 1px;
1070
+ background: transparent;
1071
+ }
1072
+ .col-resizer:hover::after,
1073
+ .col-resizer:focus-visible::after,
1074
+ body.resizing .col-resizer::after {
1075
+ background: var(--sb-accent);
1076
+ }
1077
+ .g-check input {
1078
+ accent-color: var(--sb-accent);
1079
+ margin: 0;
1080
+ vertical-align: middle;
1081
+ }
1082
+ .g-act {
1083
+ white-space: nowrap;
1084
+ text-align: right;
1085
+ padding-right: 4px;
1086
+ }
1087
+ .g-act .icon {
1088
+ opacity: 0;
1089
+ }
1090
+ .grid tr:hover .g-act .icon,
1091
+ .grid tr:focus-within .g-act .icon {
1092
+ opacity: 1;
1093
+ }
1094
+ .g-key .key {
1095
+ display: flex;
1096
+ align-items: baseline;
1097
+ gap: 2px;
1098
+ padding: 0 8px;
1099
+ }
1100
+ .g-key code {
1101
+ font-size: 12.5px;
1102
+ }
1103
+ .g-doc {
1104
+ padding: 0 8px;
1105
+ color: var(--sb-text-muted);
1106
+ white-space: nowrap;
1107
+ overflow: hidden;
1108
+ text-overflow: ellipsis;
1109
+ }
1110
+ .grid tr.off td:not(.g-check):not(.g-act) {
1111
+ color: var(--sb-text-muted);
1112
+ }
1113
+ .grid tr.off .cell,
1114
+ .grid tr.off code {
1115
+ opacity: 0.6;
1116
+ }
1117
+ .cell {
1118
+ display: block;
1119
+ width: 100%;
1120
+ height: 31px;
1121
+ padding: 0 8px;
1122
+ border: 0;
1123
+ border-radius: 0;
1124
+ background: transparent;
1125
+ font: inherit;
1126
+ color: var(--sb-text);
1127
+ outline: none;
1128
+ }
1129
+ .cell::placeholder {
1130
+ color: color-mix(in srgb, var(--sb-text-muted) 70%, transparent);
1131
+ }
1132
+ .cell:focus,
1133
+ .file-cell:focus-within {
1134
+ background: var(--sb-surface);
1135
+ box-shadow: inset 0 0 0 2px var(--sb-accent);
1136
+ }
1137
+ .grid tr.ghost td {
1138
+ background: color-mix(in srgb, var(--sb-surface-raised) 50%, var(--sb-surface));
1139
+ }
1140
+ .file-cell {
1141
+ display: flex;
1142
+ align-items: center;
1143
+ height: 31px;
1144
+ padding: 0 8px;
1145
+ cursor: pointer;
1146
+ overflow: hidden;
1147
+ white-space: nowrap;
1148
+ text-overflow: ellipsis;
1149
+ }
1150
+ .file-cell input {
1151
+ position: absolute;
1152
+ width: 1px;
1153
+ height: 1px;
1154
+ opacity: 0;
1155
+ }
1156
+
1157
+ /* ---- enum dropdown inside a cell */
1158
+ .combo {
1159
+ position: relative;
1160
+ }
1161
+ .combo .cell {
1162
+ padding-right: 26px;
1163
+ }
1164
+ .combo-toggle {
1165
+ position: absolute;
1166
+ inset: 0 0 0 auto;
1167
+ width: 26px;
1168
+ border: 0;
1169
+ background: none;
1170
+ color: var(--sb-text-muted);
1171
+ cursor: pointer;
1172
+ }
1173
+ .combo-list {
1174
+ position: fixed;
1175
+ z-index: 30;
1176
+ margin: 0;
1177
+ padding: 4px;
1178
+ max-height: 220px;
1179
+ overflow: auto;
1180
+ background: var(--sb-surface);
1181
+ border: 1px solid var(--sb-border);
1182
+ border-radius: var(--sb-radius-control);
1183
+ box-shadow: 0 8px 24px color-mix(in srgb, var(--sb-text) 16%, transparent);
1184
+ }
1185
+ .combo-list button {
1186
+ display: block;
1187
+ width: 100%;
1188
+ padding: 5px 8px;
1189
+ border: 0;
1190
+ border-radius: 4px;
1191
+ background: none;
1192
+ text-align: left;
1193
+ cursor: pointer;
1194
+ font-family: var(--sb-font-mono);
1195
+ font-size: 12.5px;
1196
+ }
1197
+ .combo-list button:hover,
1198
+ .combo-list button.at {
1199
+ background: var(--sb-surface-raised);
1200
+ }
1201
+ .combo-list button.on {
1202
+ color: var(--sb-accent);
1203
+ font-weight: 600;
1204
+ }
1205
+
1206
+ /* ---- segmented switch, e.g. JSON | Grid for form bodies */
1207
+ .doc-project {
1208
+ margin-top: var(--sb-space-3);
1209
+ }
1210
+ .field-note {
1211
+ margin-top: var(--sb-space-2);
1212
+ padding-left: 8px;
1213
+ border-left: 2px solid var(--sb-accent);
1214
+ font-size: 12.5px;
1215
+ }
1216
+ .field-note > :first-child {
1217
+ margin-top: 0;
1218
+ }
1219
+ .field-note > :last-child {
1220
+ margin-bottom: 0;
1221
+ }
1222
+ .step-note-row td {
1223
+ padding-top: 0;
1224
+ border-top: 0;
1225
+ }
1226
+ .step-note {
1227
+ font-size: 13px;
1228
+ color: var(--sb-text-muted);
1229
+ }
1230
+ .step-note > :first-child {
1231
+ margin-top: 0;
1232
+ }
1233
+ .step-note > :last-child {
1234
+ margin-bottom: 0;
1235
+ }
1236
+ .step-about {
1237
+ margin: var(--sb-space-2) 0;
1238
+ padding: 6px 10px;
1239
+ border: 1px solid var(--sb-border);
1240
+ border-left: 3px solid var(--sb-accent);
1241
+ border-radius: var(--sb-radius-control);
1242
+ font-size: 13px;
1243
+ }
1244
+ .step-about summary {
1245
+ cursor: pointer;
1246
+ font-weight: 600;
1247
+ }
1248
+ .step-about .doc-custom {
1249
+ margin-top: var(--sb-space-2);
1250
+ }
1251
+ .code-sample {
1252
+ display: flex;
1253
+ flex-direction: column;
1254
+ gap: var(--sb-space-2);
1255
+ padding: var(--sb-space-3);
1256
+ }
1257
+ .code-head {
1258
+ display: flex;
1259
+ align-items: center;
1260
+ gap: var(--sb-space-2);
1261
+ }
1262
+ .code-block {
1263
+ margin: 0;
1264
+ padding: var(--sb-space-3);
1265
+ overflow-x: auto;
1266
+ border: 1px solid var(--sb-border);
1267
+ border-radius: var(--sb-radius-control);
1268
+ background: var(--sb-surface-raised);
1269
+ font: 12.5px / 1.55 var(--sb-font-mono);
1270
+ user-select: text;
1271
+ }
1272
+ fieldset.seg {
1273
+ margin: 0;
1274
+ padding: 0;
1275
+ min-width: 0;
1276
+ display: inline-flex;
1277
+ border: 1px solid var(--sb-border);
1278
+ border-radius: var(--sb-radius-control);
1279
+ overflow: hidden;
1280
+ }
1281
+ .seg-btn {
1282
+ padding: 2px 10px;
1283
+ border: 0;
1284
+ background: var(--sb-surface);
1285
+ color: var(--sb-text-muted);
1286
+ font-size: 12px;
1287
+ font-weight: 600;
1288
+ cursor: pointer;
1289
+ }
1290
+ .seg-btn + .seg-btn {
1291
+ border-left: 1px solid var(--sb-border);
1292
+ }
1293
+ .seg-btn.on {
1294
+ background: var(--sb-surface-raised);
1295
+ color: var(--sb-text);
1296
+ }
1297
+
1298
+ /* ---- editor */
1299
+ .body-editor {
1300
+ display: grid;
1301
+ border: 1px solid var(--sb-border);
1302
+ border-radius: var(--sb-radius-control);
1303
+ max-height: 420px;
1304
+ overflow: auto;
1305
+ background: var(--sb-code-bg);
1306
+ }
1307
+ .body-editor .prism-code-editor {
1308
+ --pce-bg: var(--sb-code-bg);
1309
+ --pce-cursor: var(--sb-text);
1310
+ --pce-selection: var(--sb-focus-ring);
1311
+ --pce-bg-highlight: var(--sb-code-line);
1312
+ --pce-line-number: var(--sb-text-muted);
1313
+ --pce-selection-match: transparent;
1314
+ --pce-widget-bg: var(--sb-surface);
1315
+ --pce-widget-border: var(--sb-border);
1316
+ --pce-widget-color-active: var(--sb-text);
1317
+ --pce-ac-match: var(--sb-accent);
1318
+ font: 12.5px / 1.6 var(--sb-font-mono);
1319
+ min-height: 3.2em;
1320
+ }
1321
+ .body-editor [class*="language-"],
1322
+ .body-editor .token.punctuation,
1323
+ .body-editor .token.operator {
1324
+ color: var(--sb-code-punct);
1325
+ }
1326
+ .body-editor .token.property,
1327
+ .body-editor .token.attr-name {
1328
+ color: var(--sb-code-key);
1329
+ }
1330
+ .body-editor .token.string {
1331
+ color: var(--sb-code-string);
1332
+ }
1333
+ .body-editor .token.number {
1334
+ color: var(--sb-code-number);
1335
+ }
1336
+ .body-editor .token.boolean,
1337
+ .body-editor .token.null,
1338
+ .body-editor .token.constant {
1339
+ color: var(--sb-code-literal);
1340
+ }
1341
+ .body-editor .token.keyword,
1342
+ .body-editor .token.class-name,
1343
+ .body-editor .token.function {
1344
+ color: var(--sb-code-keyword);
1345
+ }
1346
+ .body-editor .token.comment {
1347
+ color: var(--sb-code-comment);
1348
+ }
1349
+
1350
+ /* ---- field documentation under the editor */
1351
+ .field-doc {
1352
+ min-height: 4.5em;
1353
+ margin-top: var(--sb-space-2);
1354
+ padding: var(--sb-space-2) var(--sb-space-3);
1355
+ border-left: 3px solid var(--sb-accent);
1356
+ background: var(--sb-surface);
1357
+ font-size: 13px;
1358
+ }
1359
+ /* docked to the bottom of whatever scrolls it, so a short window never leaves it below the fold */
1360
+ .tab-pane > .field-doc,
1361
+ .tab-pane .body > .field-doc,
1362
+ .sent-view > .field-doc,
1363
+ .rs-pane > div > .field-doc {
1364
+ position: sticky;
1365
+ bottom: 0;
1366
+ z-index: 1;
1367
+ }
1368
+ .field-doc.empty {
1369
+ border-left-color: var(--sb-border);
1370
+ color: var(--sb-text-muted);
1371
+ }
1372
+ .field-doc p {
1373
+ margin: 4px 0 0;
1374
+ }
1375
+ .field-doc-text {
1376
+ max-height: 11em;
1377
+ overflow: auto;
1378
+ margin-top: 4px;
1379
+ }
1380
+ .field-doc-text :is(p, ul, ol, pre) {
1381
+ margin: 0 0 var(--sb-space-2);
1382
+ }
1383
+ .field-doc-text :is(ul, ol) {
1384
+ padding-left: 1.3em;
1385
+ }
1386
+ .field-doc-text pre {
1387
+ padding: var(--sb-space-2);
1388
+ background: var(--sb-surface-raised);
1389
+ border-radius: var(--sb-radius-control);
1390
+ overflow: auto;
1391
+ }
1392
+ .field-doc-text :is(h2, h3, h4, h5) {
1393
+ margin: var(--sb-space-2) 0 var(--sb-space-1);
1394
+ font-size: 13px;
1395
+ text-transform: none;
1396
+ letter-spacing: 0;
1397
+ color: var(--sb-text);
1398
+ }
1399
+ .doc-inline a,
1400
+ .field-doc-text a {
1401
+ color: var(--sb-accent);
1402
+ }
1403
+ .doc-inline code,
1404
+ .field-doc-text code {
1405
+ padding: 0 4px;
1406
+ border-radius: 3px;
1407
+ background: var(--sb-surface-raised);
1408
+ }
1409
+ .field-doc-head {
1410
+ display: flex;
1411
+ align-items: center;
1412
+ gap: var(--sb-space-2);
1413
+ flex-wrap: wrap;
1414
+ }
1415
+ .field-doc-enum code {
1416
+ margin-right: 6px;
1417
+ }
1418
+ .issues {
1419
+ margin-top: var(--sb-space-2);
1420
+ font-size: 12px;
1421
+ }
1422
+
1423
+ /* ---- sequence panel: |timeline|exchange| */
1424
+ .sequence-panel {
1425
+ display: grid;
1426
+ grid-template-columns: minmax(300px, 4fr) minmax(0, 7fr);
1427
+ height: 100%;
1428
+ min-height: 0;
1429
+ }
1430
+ @media (max-width: 900px) {
1431
+ .sequence-panel {
1432
+ grid-template-columns: minmax(0, 1fr);
1433
+ overflow: auto;
1434
+ }
1435
+ }
1436
+ .seq-left {
1437
+ min-height: 0;
1438
+ overflow: auto;
1439
+ padding: var(--sb-space-4);
1440
+ background: var(--sb-bg);
1441
+ border-right: 1px solid var(--sb-border);
1442
+ }
1443
+ .controls-grid {
1444
+ container-type: inline-size;
1445
+ margin-bottom: var(--sb-space-3);
1446
+ }
1447
+ .controls-grid col.c-key {
1448
+ width: 30%;
1449
+ }
1450
+ .controls-grid col.c-val {
1451
+ width: 40%;
1452
+ }
1453
+ @container (max-width: 520px) {
1454
+ .controls-grid .g-doc,
1455
+ .controls-grid th.g-doc {
1456
+ display: none;
1457
+ }
1458
+ .controls-grid col.c-key {
1459
+ width: 40%;
1460
+ }
1461
+ .controls-grid col.c-val {
1462
+ width: 60%;
1463
+ }
1464
+ }
1465
+ .multi-cell {
1466
+ display: flex;
1467
+ flex-wrap: wrap;
1468
+ gap: 4px 12px;
1469
+ padding: 6px 8px;
1470
+ }
1471
+ .multi-cell label {
1472
+ display: inline-flex;
1473
+ align-items: center;
1474
+ gap: 4px;
1475
+ }
1476
+ .cell.mono {
1477
+ font-family: var(--sb-font-mono);
1478
+ font-size: 12.5px;
1479
+ }
1480
+ .doc-tags {
1481
+ display: flex;
1482
+ gap: var(--sb-space-1);
1483
+ margin: 0 0 var(--sb-space-3);
1484
+ }
1485
+ .doc .link {
1486
+ text-align: left;
1487
+ }
1488
+ .pause .controls-grid {
1489
+ margin: var(--sb-space-2) 0;
1490
+ }
1491
+ .step-exchange {
1492
+ display: flex;
1493
+ flex-direction: column;
1494
+ height: 100%;
1495
+ min-height: 0;
1496
+ }
1497
+ .seq-left .controls {
1498
+ padding: var(--sb-space-3) var(--sb-space-4);
1499
+ margin-bottom: var(--sb-space-3);
1500
+ background: var(--sb-surface);
1501
+ border: 1px solid var(--sb-border);
1502
+ border-radius: var(--sb-radius-card);
1503
+ }
1504
+ .seq-left .controls h3 {
1505
+ margin: 0 0 var(--sb-space-2);
1506
+ font-size: 11px;
1507
+ text-transform: uppercase;
1508
+ letter-spacing: 0.06em;
1509
+ color: var(--sb-text-muted);
1510
+ }
1511
+ .seq-run {
1512
+ display: flex;
1513
+ align-items: center;
1514
+ gap: var(--sb-space-3);
1515
+ flex-wrap: wrap;
1516
+ margin-bottom: var(--sb-space-4);
1517
+ }
1518
+ .seq-left .journey {
1519
+ padding: var(--sb-space-1) 0;
1520
+ }
1521
+ .seq-left .jhead {
1522
+ font-size: 13px;
1523
+ }
1524
+ .seq-right {
1525
+ min-height: 0;
1526
+ display: flex;
1527
+ flex-direction: column;
1528
+ overflow: auto;
1529
+ background: var(--sb-surface);
1530
+ }
1531
+ .seq-right .response {
1532
+ padding: var(--sb-space-3) var(--sb-space-4) 0;
1533
+ }
1534
+ .seq-req {
1535
+ flex: 0 0 auto;
1536
+ border-bottom: 1px solid var(--sb-border);
1537
+ }
1538
+ .seq-req .rq-bar {
1539
+ padding-bottom: var(--sb-space-3);
1540
+ }
1541
+ .seq-req .rq-pane {
1542
+ padding-top: 0;
1543
+ }
1544
+ .seq-req .body-editor {
1545
+ max-height: 200px;
1546
+ }
1547
+ .jstep.picked .jhead .jname {
1548
+ text-decoration: underline;
1549
+ text-underline-offset: 3px;
1550
+ }
1551
+
1552
+ /* ---- environment settings (header) */
1553
+ .envmenu {
1554
+ position: relative;
1555
+ }
1556
+ .envmenu-btn {
1557
+ display: inline-flex;
1558
+ align-items: center;
1559
+ gap: 6px;
1560
+ white-space: nowrap;
1561
+ }
1562
+ .badge-missing {
1563
+ min-width: 18px;
1564
+ padding: 0 5px;
1565
+ border-radius: 999px;
1566
+ background: var(--sb-danger);
1567
+ color: var(--sb-text-on-danger);
1568
+ font-size: 11px;
1569
+ font-weight: 700;
1570
+ text-align: center;
1571
+ }
1572
+ .envmenu-pop {
1573
+ position: absolute;
1574
+ right: 0;
1575
+ top: calc(100% + 8px);
1576
+ z-index: 40;
1577
+ width: min(460px, 92vw);
1578
+ max-height: min(70vh, 640px);
1579
+ overflow: auto;
1580
+ display: grid;
1581
+ gap: var(--sb-space-3);
1582
+ padding: var(--sb-space-3) var(--sb-space-4);
1583
+ background: var(--sb-surface);
1584
+ border: 1px solid var(--sb-border);
1585
+ border-radius: var(--sb-radius-card);
1586
+ box-shadow: 0 12px 32px color-mix(in srgb, var(--sb-text) 20%, transparent);
1587
+ }
1588
+ .envmenu-head {
1589
+ display: flex;
1590
+ align-items: center;
1591
+ gap: var(--sb-space-3);
1592
+ }
1593
+ .envmenu-pop h3 {
1594
+ margin: 0 0 var(--sb-space-1);
1595
+ font-size: 11px;
1596
+ text-transform: uppercase;
1597
+ letter-spacing: 0.06em;
1598
+ color: var(--sb-text-muted);
1599
+ }
1600
+ .envmenu-pop p {
1601
+ margin: 0;
1602
+ }
1603
+ .envmenu-warn {
1604
+ padding: var(--sb-space-2) var(--sb-space-3);
1605
+ border-radius: var(--sb-radius-control);
1606
+ background: var(--sb-warning-subtle);
1607
+ color: var(--sb-warning);
1608
+ font-size: 12.5px;
1609
+ }
1610
+ .envrow {
1611
+ display: flex;
1612
+ align-items: center;
1613
+ gap: var(--sb-space-2);
1614
+ margin-top: var(--sb-space-2);
1615
+ }
1616
+ .envrow input,
1617
+ .envrow select {
1618
+ flex: 1;
1619
+ min-width: 0;
1620
+ padding: 5px 8px;
1621
+ border: 1px solid var(--sb-border);
1622
+ border-radius: var(--sb-radius-control);
1623
+ background: var(--sb-surface);
1624
+ }
1625
+ .envrow code {
1626
+ flex: 0 0 38%;
1627
+ overflow: hidden;
1628
+ text-overflow: ellipsis;
1629
+ }
1630
+ .secretrow {
1631
+ margin-top: var(--sb-space-3);
1632
+ }
1633
+ .secretrow-head {
1634
+ display: flex;
1635
+ align-items: baseline;
1636
+ gap: var(--sb-space-2);
1637
+ font-size: 13px;
1638
+ }
1639
+ .secretrow-head .src {
1640
+ margin-left: auto;
1641
+ padding: 0 8px;
1642
+ border-radius: 999px;
1643
+ font-size: 11px;
1644
+ font-weight: 600;
1645
+ }
1646
+ .src.set {
1647
+ background: var(--sb-success-subtle);
1648
+ color: var(--sb-success);
1649
+ }
1650
+ .src.missing {
1651
+ background: var(--sb-danger-subtle);
1652
+ color: var(--sb-danger);
1653
+ }
1654
+ .op-lock {
1655
+ display: inline-block;
1656
+ margin-left: 6px;
1657
+ color: var(--sb-text-muted);
1658
+ vertical-align: -1px;
1659
+ }
1660
+
1661
+ /* ---- list resizer: straddles the edge between the list and the stage/panel */
1662
+ .list-resizer {
1663
+ position: fixed;
1664
+ z-index: 25;
1665
+ top: var(--sb-header-h, 53px);
1666
+ bottom: 0;
1667
+ left: calc(var(--sb-list-w) - 4px);
1668
+ width: 8px;
1669
+ cursor: col-resize;
1670
+ touch-action: none;
1671
+ }
1672
+ .list-resizer::after {
1673
+ content: "";
1674
+ position: absolute;
1675
+ inset: 0 3px;
1676
+ background: transparent;
1677
+ transition: background 120ms;
1678
+ }
1679
+ .list-resizer:hover::after,
1680
+ .list-resizer:focus-visible::after,
1681
+ body.resizing .list-resizer::after {
1682
+ background: var(--sb-accent);
1683
+ }
1684
+ body.resizing {
1685
+ cursor: col-resize;
1686
+ user-select: none;
1687
+ }
1688
+ @media (max-width: 900px) {
1689
+ .list-resizer {
1690
+ display: none;
1691
+ }
1692
+ }
1693
+ }
1694
+
1695
+ @layer components {
1696
+ /* a phone: the panel is a full-screen sheet over the list, not a column beside it */
1697
+ @media (max-width: 820px) {
1698
+ .panel,
1699
+ .panel.docked {
1700
+ inset: 0;
1701
+ width: 100%;
1702
+ min-width: 0;
1703
+ /* under the browser's address bar; iOS pans the keyboard's cover over it rather than resizing */
1704
+ height: 100dvh;
1705
+ border-left: 0;
1706
+ box-shadow: none;
1707
+ }
1708
+ /* iOS zooms the page when a field under 16px is focused; the code editors included */
1709
+ input,
1710
+ select,
1711
+ textarea,
1712
+ .body-editor .prism-code-editor,
1713
+ .body-editor .prism-code-editor textarea {
1714
+ font-size: 16px;
1715
+ }
1716
+ .body-editor .prism-code-editor {
1717
+ line-height: 1.5;
1718
+ }
1719
+ .panel-head {
1720
+ padding: var(--sb-space-2) var(--sb-space-3);
1721
+ gap: var(--sb-space-2);
1722
+ }
1723
+ /* one row: the title (two lines at most) and the stepper and close beside it */
1724
+ .panel-head {
1725
+ flex-wrap: nowrap;
1726
+ }
1727
+ .panel-title {
1728
+ flex: 1 1 0;
1729
+ min-width: 0;
1730
+ }
1731
+ .panel-head h2 {
1732
+ display: -webkit-box;
1733
+ -webkit-box-orient: vertical;
1734
+ -webkit-line-clamp: 2;
1735
+ line-clamp: 2;
1736
+ overflow: hidden;
1737
+ overflow-wrap: anywhere;
1738
+ line-height: 1.25;
1739
+ }
1740
+ .panel-title > .muted {
1741
+ overflow: hidden;
1742
+ text-overflow: ellipsis;
1743
+ white-space: nowrap;
1744
+ }
1745
+ .panel-head .spacer {
1746
+ display: none;
1747
+ }
1748
+ .panel-head label.row > .muted {
1749
+ display: none;
1750
+ }
1751
+ .panel-head select {
1752
+ max-width: 34%;
1753
+ }
1754
+ .stepper {
1755
+ gap: 0;
1756
+ }
1757
+ .panel-head .icon {
1758
+ min-width: 36px;
1759
+ min-height: 36px;
1760
+ }
1761
+ .panel-main.scroll {
1762
+ padding: var(--sb-space-3);
1763
+ }
1764
+ .doc-intro {
1765
+ flex-wrap: wrap;
1766
+ }
1767
+ /* a long path breaks inside its box instead of pushing the page wider */
1768
+ .doc-intro code {
1769
+ flex: 1 1 0;
1770
+ min-width: 0;
1771
+ overflow-wrap: anywhere;
1772
+ }
1773
+ .doc-intro .spacer {
1774
+ display: none;
1775
+ }
1776
+ /* anything else wide in the docs scrolls on its own, never the whole panel */
1777
+ .doc pre,
1778
+ .doc-custom pre {
1779
+ max-width: 100%;
1780
+ overflow-x: auto;
1781
+ }
1782
+ .doc img {
1783
+ max-width: 100%;
1784
+ height: auto;
1785
+ }
1786
+ .doc-custom table {
1787
+ display: block;
1788
+ max-width: 100%;
1789
+ overflow-x: auto;
1790
+ }
1791
+ .panel-main.scroll {
1792
+ overflow-x: hidden;
1793
+ }
1794
+ /* Environment settings: a sheet over the whole viewport rather than a popover beside its button */
1795
+ .envmenu {
1796
+ position: static;
1797
+ }
1798
+ .envmenu-pop {
1799
+ position: fixed;
1800
+ inset: var(--sb-space-2);
1801
+ width: auto;
1802
+ max-height: none;
1803
+ z-index: 40;
1804
+ }
1805
+ .envrow {
1806
+ flex-wrap: wrap;
1807
+ }
1808
+ .envrow input,
1809
+ .envrow select {
1810
+ min-width: 0;
1811
+ max-width: 100%;
1812
+ }
1813
+ /* wide tables scroll sideways inside the panel instead of being cut off */
1814
+ table.fields {
1815
+ display: block;
1816
+ max-width: 100%;
1817
+ overflow-x: auto;
1818
+ }
1819
+ /* descriptions keep to a line or two and the table scrolls sideways rather than stacking words */
1820
+ table.fields td:last-child {
1821
+ min-width: 440px;
1822
+ }
1823
+ table.fields td:first-child {
1824
+ white-space: nowrap;
1825
+ }
1826
+ .rq-meta {
1827
+ flex-wrap: wrap;
1828
+ padding-inline: var(--sb-space-3);
1829
+ }
1830
+ /* the credentials note is in the chip's tooltip; not worth a line of a phone screen. The redirect
1831
+ address to register is a desktop job too; a problem or a wait is still shown */
1832
+ .secrets-note,
1833
+ .oauth-hint {
1834
+ display: none;
1835
+ }
1836
+ .secrets-folded,
1837
+ .needs-vars {
1838
+ margin-inline: var(--sb-space-3);
1839
+ }
1840
+ .rq-example {
1841
+ display: flex;
1842
+ align-items: center;
1843
+ gap: var(--sb-space-2);
1844
+ flex: 1 1 100%;
1845
+ min-width: 0;
1846
+ }
1847
+ .rq-example > label.row {
1848
+ flex: 1 1 0;
1849
+ min-width: 0;
1850
+ }
1851
+ .rq-example > label.row select {
1852
+ flex: 1 1 0;
1853
+ min-width: 0;
1854
+ text-overflow: ellipsis;
1855
+ }
1856
+ /* "Respond with" sits under Example like a small form: same label width, so the two selects start at
1857
+ the same edge, and the second fills the row. It comes before any Edited / Reset / Save links. */
1858
+ .rq-status {
1859
+ order: 1;
1860
+ flex: 1 1 100%;
1861
+ min-width: 0;
1862
+ /* the same gap as the Example row's label, or the selects start a few pixels apart */
1863
+ gap: var(--sb-space-3);
1864
+ }
1865
+ .rq-status > select {
1866
+ flex: 1 1 0;
1867
+ min-width: 0;
1868
+ text-overflow: ellipsis;
1869
+ }
1870
+ .rq-example > label.row > .muted,
1871
+ .rq-status > .muted {
1872
+ flex: 0 0 84px;
1873
+ }
1874
+ .rq-meta > .edited,
1875
+ .rq-meta > .spacer,
1876
+ .rq-meta > .link {
1877
+ order: 2;
1878
+ }
1879
+ .rq-meta select {
1880
+ max-width: 100%;
1881
+ min-width: 0;
1882
+ }
1883
+ button,
1884
+ select,
1885
+ input:not([type="checkbox"]):not([type="radio"]) {
1886
+ min-height: 36px;
1887
+ }
1888
+ }
1889
+ }
1890
+
1891
+ @layer components {
1892
+ .sheet-close {
1893
+ display: none;
1894
+ }
1895
+ /* a phone: the selected step's request and response rise from the bottom of the visible screen */
1896
+ @media (max-width: 820px) {
1897
+ .sequence-panel {
1898
+ overflow: auto;
1899
+ /* room under the last step, so the sheet never hides it */
1900
+ padding-bottom: 8px;
1901
+ }
1902
+ /* with the sheet up, the timeline can still scroll its last steps above it */
1903
+ .sequence-panel.sheet-open .seq-left {
1904
+ padding-bottom: 62vh;
1905
+ }
1906
+ .seq-right {
1907
+ display: none;
1908
+ }
1909
+ .seq-right.sheet-open {
1910
+ display: flex;
1911
+ position: absolute;
1912
+ inset: auto 0 0 0;
1913
+ height: min(62%, 520px);
1914
+ z-index: 5;
1915
+ border-top: 1px solid var(--sb-border);
1916
+ border-radius: 14px 14px 0 0;
1917
+ box-shadow: 0 -12px 32px color-mix(in srgb, var(--sb-text) 22%, transparent);
1918
+ overflow: auto;
1919
+ overscroll-behavior: contain;
1920
+ }
1921
+ .seq-right .sheet-close {
1922
+ display: flex;
1923
+ align-items: center;
1924
+ gap: var(--sb-space-2);
1925
+ position: sticky;
1926
+ top: 0;
1927
+ z-index: 2;
1928
+ flex: 0 0 auto;
1929
+ min-height: 44px;
1930
+ padding: 0 var(--sb-space-4);
1931
+ border: 0;
1932
+ border-bottom: 1px solid var(--sb-border);
1933
+ background: var(--sb-surface);
1934
+ font-weight: 600;
1935
+ text-align: left;
1936
+ color: var(--sb-text);
1937
+ }
1938
+ }
1939
+ }