sidekiq 7.3.0 → 8.0.5

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 (115) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +158 -0
  3. data/README.md +16 -13
  4. data/bin/sidekiqload +31 -22
  5. data/bin/webload +69 -0
  6. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +120 -0
  7. data/lib/generators/sidekiq/job_generator.rb +2 -0
  8. data/lib/sidekiq/api.rb +184 -71
  9. data/lib/sidekiq/capsule.rb +11 -9
  10. data/lib/sidekiq/cli.rb +16 -20
  11. data/lib/sidekiq/client.rb +28 -11
  12. data/lib/sidekiq/component.rb +62 -2
  13. data/lib/sidekiq/config.rb +42 -18
  14. data/lib/sidekiq/deploy.rb +2 -0
  15. data/lib/sidekiq/embedded.rb +4 -1
  16. data/lib/sidekiq/iterable_job.rb +3 -0
  17. data/lib/sidekiq/job/interrupt_handler.rb +2 -0
  18. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +3 -3
  19. data/lib/sidekiq/job/iterable.rb +82 -7
  20. data/lib/sidekiq/job_logger.rb +15 -27
  21. data/lib/sidekiq/job_retry.rb +17 -5
  22. data/lib/sidekiq/job_util.rb +7 -1
  23. data/lib/sidekiq/launcher.rb +3 -2
  24. data/lib/sidekiq/logger.rb +19 -70
  25. data/lib/sidekiq/manager.rb +0 -1
  26. data/lib/sidekiq/metrics/query.rb +73 -45
  27. data/lib/sidekiq/metrics/shared.rb +23 -9
  28. data/lib/sidekiq/metrics/tracking.rb +22 -12
  29. data/lib/sidekiq/middleware/current_attributes.rb +12 -4
  30. data/lib/sidekiq/middleware/modules.rb +2 -0
  31. data/lib/sidekiq/monitor.rb +2 -1
  32. data/lib/sidekiq/paginator.rb +14 -1
  33. data/lib/sidekiq/processor.rb +26 -19
  34. data/lib/sidekiq/profiler.rb +72 -0
  35. data/lib/sidekiq/rails.rb +44 -55
  36. data/lib/sidekiq/redis_client_adapter.rb +0 -1
  37. data/lib/sidekiq/redis_connection.rb +22 -4
  38. data/lib/sidekiq/ring_buffer.rb +2 -0
  39. data/lib/sidekiq/systemd.rb +2 -0
  40. data/lib/sidekiq/testing.rb +7 -7
  41. data/lib/sidekiq/version.rb +6 -2
  42. data/lib/sidekiq/web/action.rb +124 -69
  43. data/lib/sidekiq/web/application.rb +355 -377
  44. data/lib/sidekiq/web/config.rb +120 -0
  45. data/lib/sidekiq/web/helpers.rb +64 -33
  46. data/lib/sidekiq/web/router.rb +61 -74
  47. data/lib/sidekiq/web.rb +52 -150
  48. data/lib/sidekiq.rb +5 -4
  49. data/sidekiq.gemspec +6 -6
  50. data/web/assets/javascripts/application.js +6 -13
  51. data/web/assets/javascripts/base-charts.js +30 -16
  52. data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
  53. data/web/assets/javascripts/dashboard-charts.js +2 -0
  54. data/web/assets/javascripts/dashboard.js +7 -1
  55. data/web/assets/javascripts/metrics.js +16 -34
  56. data/web/assets/stylesheets/style.css +766 -0
  57. data/web/locales/ar.yml +1 -0
  58. data/web/locales/cs.yml +1 -0
  59. data/web/locales/da.yml +1 -0
  60. data/web/locales/de.yml +1 -0
  61. data/web/locales/el.yml +1 -0
  62. data/web/locales/en.yml +9 -1
  63. data/web/locales/es.yml +24 -2
  64. data/web/locales/fa.yml +1 -0
  65. data/web/locales/fr.yml +1 -1
  66. data/web/locales/gd.yml +1 -1
  67. data/web/locales/he.yml +1 -0
  68. data/web/locales/hi.yml +1 -0
  69. data/web/locales/it.yml +40 -1
  70. data/web/locales/ja.yml +1 -1
  71. data/web/locales/ko.yml +1 -0
  72. data/web/locales/lt.yml +1 -0
  73. data/web/locales/nb.yml +1 -0
  74. data/web/locales/nl.yml +1 -0
  75. data/web/locales/pl.yml +1 -0
  76. data/web/locales/{pt-br.yml → pt-BR.yml} +3 -3
  77. data/web/locales/pt.yml +1 -0
  78. data/web/locales/ru.yml +1 -0
  79. data/web/locales/sv.yml +1 -0
  80. data/web/locales/ta.yml +1 -0
  81. data/web/locales/tr.yml +2 -2
  82. data/web/locales/uk.yml +25 -1
  83. data/web/locales/ur.yml +1 -0
  84. data/web/locales/vi.yml +1 -0
  85. data/web/locales/{zh-cn.yml → zh-CN.yml} +85 -74
  86. data/web/locales/{zh-tw.yml → zh-TW.yml} +2 -2
  87. data/web/views/_footer.erb +31 -34
  88. data/web/views/_job_info.erb +91 -89
  89. data/web/views/_metrics_period_select.erb +13 -10
  90. data/web/views/_nav.erb +14 -21
  91. data/web/views/_paging.erb +23 -21
  92. data/web/views/_poll_link.erb +2 -2
  93. data/web/views/_summary.erb +16 -16
  94. data/web/views/busy.erb +124 -122
  95. data/web/views/dashboard.erb +63 -64
  96. data/web/views/dead.erb +31 -27
  97. data/web/views/filtering.erb +3 -4
  98. data/web/views/layout.erb +13 -29
  99. data/web/views/metrics.erb +75 -82
  100. data/web/views/metrics_for_job.erb +45 -46
  101. data/web/views/morgue.erb +61 -70
  102. data/web/views/profiles.erb +43 -0
  103. data/web/views/queue.erb +54 -52
  104. data/web/views/queues.erb +43 -41
  105. data/web/views/retries.erb +66 -75
  106. data/web/views/retry.erb +32 -27
  107. data/web/views/scheduled.erb +59 -55
  108. data/web/views/scheduled_job_info.erb +1 -1
  109. metadata +27 -29
  110. data/web/assets/stylesheets/application-dark.css +0 -147
  111. data/web/assets/stylesheets/application-rtl.css +0 -163
  112. data/web/assets/stylesheets/application.css +0 -758
  113. data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
  114. data/web/assets/stylesheets/bootstrap.css +0 -5
  115. data/web/views/_status.erb +0 -4
@@ -0,0 +1,766 @@
1
+ :root {
2
+ --color-primary: oklch(48% 0.2 13);
3
+ --color-bg: oklch(99% 0.005 256);
4
+ --color-elevated: oklch(100% 0 256);
5
+ --color-border: oklch(95% 0.005 256);
6
+ --color-input-border: oklch(90% 0.005 256);
7
+ --color-selected: oklch(93% 0.005 256);
8
+ --color-table-bg-alt: oklch(99% 0.005 256);
9
+ --color-shadow: oklch(27% 0.005 256 / 5%);
10
+ --color-text: oklch(27% 0.005 256);
11
+ --color-text-light: oklch(52% 0.005 256);
12
+ --color-success: oklch(from var(--color-primary) calc(l + 0.35) c calc(h + 120));
13
+ --color-info: oklch(from var(--color-primary) calc(l + 0.35) c calc(h - 120));
14
+ --color-danger: oklch(from var(--color-primary) calc(l + 0.35) c h);
15
+ --color-warning: oklch(from var(--color-primary) calc(l + 0.35) c calc(h + 75));
16
+
17
+ --space-1-2: 4px;
18
+ --space: 8px;
19
+ --space-2x: 16px;
20
+ --space-3x: 24px;
21
+ --space-4x: 32px;
22
+
23
+ --font-sans: system-ui, sans-serif;
24
+ --font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Consolas, 'DejaVu Sans Mono', monospace;
25
+ --font-size: 16px;
26
+ --font-size-large: 1.728rem;
27
+ --font-size-small: 0.833rem;
28
+ }
29
+
30
+ *, *::before, *::after { box-sizing: border-box; }
31
+
32
+ ::selection { background: var(--color-selected); }
33
+
34
+ :focus-visible {
35
+ outline: 1px solid oklch(from var(--color-primary) l c h / 50%);
36
+ }
37
+
38
+ .sr-only {
39
+ border: 0 !important;
40
+ clip: rect(1px, 1px, 1px, 1px) !important;
41
+ -webkit-clip-path: inset(50%) !important;
42
+ clip-path: inset(50%) !important;
43
+ height: 1px !important;
44
+ margin: -1px !important;
45
+ overflow: hidden !important;
46
+ padding: 0 !important;
47
+ position: absolute !important;
48
+ width: 1px !important;
49
+ white-space: nowrap !important;
50
+ }
51
+
52
+ html {
53
+ font-family: var(--font-sans);
54
+ font-size: var(--font-size);
55
+ font-weight: normal;
56
+ line-height: 1.5;
57
+ }
58
+
59
+ body {
60
+ background: var(--color-bg);
61
+ color: var(--color-text);
62
+ font-variant-numeric: tabular-nums;
63
+ margin: 0;
64
+ overflow-x: hidden;
65
+ padding: 64px 0;
66
+ position: relative;
67
+ -webkit-font-smoothing: antialiased;
68
+ }
69
+
70
+ .container {
71
+ margin: 0 auto;
72
+ /* max-width: 1440px; */
73
+ padding: var(--space-2x);
74
+ }
75
+
76
+ h1, h2, h3 {
77
+ font-size: var(--font-size-large);
78
+ font-weight: normal;
79
+ overflow-wrap: break-word;
80
+ margin: var(--space-3x) 0 var(--space);
81
+ padding: 0;
82
+ }
83
+
84
+ code {
85
+ background-color: var(--color-bg);
86
+ border-radius: 2px;
87
+ box-shadow: 0 0 0 1px var(--color-border);
88
+ color: var(--color-text-light);
89
+ display: inline-block;
90
+ font-family: var(--font-mono);
91
+ font-size: var(--font-size-small);
92
+ padding: var(--space-1-2);
93
+ word-wrap: anywhere;
94
+ }
95
+
96
+ time { color: var(--color-text-light); }
97
+
98
+ :any-link time { color: inherit; }
99
+
100
+ /* links and buttons */
101
+ :any-link { color: inherit; }
102
+
103
+ :any-link:hover { color: oklch(from var(--color-primary) calc(l + 0.06) c h); }
104
+
105
+ .btn,
106
+ .btn-primary,
107
+ input[type="submit"] {
108
+ background: linear-gradient(oklch(from var(--color-text) calc(l + 0.06) c h), var(--color-text));
109
+ border: none;
110
+ border-radius: var(--space-1-2);
111
+ box-shadow: 0 1px 1px 1px var(--color-shadow);
112
+ color: var(--color-bg);
113
+ cursor: pointer;
114
+ display: inline-block;
115
+ font-size: var(--font-size-small);
116
+ font-weight: 700;
117
+ line-height: var(--space-3x);
118
+ padding: var(--space) var(--space-2x);
119
+ text-decoration: none;
120
+ white-space: nowrap;
121
+ }
122
+
123
+ .btn:hover,
124
+ input[type="submit"]:hover {
125
+ background: linear-gradient(oklch(from var(--color-text) calc(l + 0.16) c h), oklch(from var(--color-text) calc(l + 0.1) c h));
126
+ color: var(--color-bg);
127
+ }
128
+
129
+ .btn-danger,
130
+ input[type="submit"].btn-danger {
131
+ background: linear-gradient(oklch(from var(--color-primary) calc(l + 0.06) c h), var(--color-primary));
132
+ }
133
+
134
+ .btn-danger:hover,
135
+ input[type="submit"].btn-danger:hover {
136
+ background: linear-gradient(oklch(from var(--color-primary) calc(l + 0.16) c h), oklch(from var(--color-primary) calc(l + 0.1) c h));
137
+ color: var(--color-bg);
138
+ }
139
+
140
+ .btn-warn,
141
+ input[type="submit"].btn-warn {
142
+ background: linear-gradient(oklch(from var(--color-primary) calc(l + 0.06) c calc(h + 75)), oklch(from var(--color-primary) l c calc(h + 90)));
143
+ }
144
+
145
+ .btn-warn:hover,
146
+ input[type="submit"].btn-warn:hover {
147
+ background: linear-gradient(oklch(from var(--color-primary) calc(l + 0.16) c calc(h + 75)), oklch(from var(--color-primary) calc(l + 0.1) c calc(h + 90)));
148
+ color: var(--color-bg);
149
+ }
150
+
151
+ .btn-inverse {
152
+ background: transparent;
153
+ box-shadow: 0 0 0 1px var(--color-input-border) inset;
154
+ color: inherit;
155
+ }
156
+
157
+ .btn-inverse:hover {
158
+ background: transparent;
159
+ box-shadow: 0 0 0 1px oklch(from var(--color-input-border) calc(l - 0.1) c h) inset;
160
+ color: var(--color-primary);
161
+ }
162
+
163
+ .live-poll { display: none; }
164
+
165
+ .live-poll.active {
166
+ display: inline-block;
167
+ }
168
+
169
+ /* nav */
170
+ .nav {
171
+ display: flex;
172
+ align-items: center;
173
+ list-style-type: none;
174
+ margin: 0;
175
+ padding: 0;
176
+ width: 100%;
177
+ }
178
+
179
+ .nav p { margin: 0; }
180
+
181
+ body > header {
182
+ background: var(--color-elevated);
183
+ box-shadow: 0 2px 4px 0 var(--color-shadow);
184
+ height: 56px;
185
+ overflow: hidden;
186
+ position: fixed;
187
+ left: 0;
188
+ right: 0;
189
+ top: 0;
190
+ overflow-x: auto;
191
+ z-index: 10;
192
+ }
193
+
194
+ body > header .container {
195
+ display: flex;
196
+ padding: var(--space) var(--space-2x)
197
+ }
198
+
199
+ .navbar-header {
200
+ display: flex;
201
+ gap: var(--space);
202
+ position: relative;
203
+ }
204
+
205
+ .navbar-toggle,
206
+ .navbar-header .navbar-livereload {
207
+ display: none;
208
+ }
209
+
210
+ .navbar-brand {
211
+ color: var(--color-primary);
212
+ font-size: 1.125rem;
213
+ line-height: 24px;
214
+ font-weight: 700;
215
+ margin: var(--space) var(--space-2x) 0 0;
216
+ text-decoration: none;
217
+ }
218
+
219
+ body > header .nav li {
220
+ padding: 0 var(--space);
221
+ line-height: 40px;
222
+ white-space: nowrap;
223
+ }
224
+
225
+ body > header .nav li.active {
226
+ border-radius: var(--space-1-2);
227
+ background: var(--color-selected);
228
+ }
229
+
230
+ body > header .nav li :any-link:not(.btn) {
231
+ color: inherit;
232
+ text-decoration: none;
233
+ }
234
+
235
+ body > header .nav li :any-link:not(.btn):hover { color: oklch(from var(--color-primary) calc(l + 0.06) c h); }
236
+
237
+ body > header .nav li.navbar-livereload {
238
+ margin-left: auto;
239
+ padding-right: 0;
240
+ }
241
+
242
+ .navbar-collapse { flex: 1; }
243
+
244
+ /* main */
245
+ section + section {
246
+ margin-top: var(--space-3x);
247
+ }
248
+
249
+ section > header {
250
+ display: flex;
251
+ align-items: center;
252
+ gap: var(--space);
253
+ margin: var(--space-3x) 0 var(--space);
254
+ }
255
+
256
+ section + section > header {
257
+ margin-top: 0;
258
+ }
259
+
260
+ section > header h1,
261
+ section > header h2,
262
+ section > header h3 {
263
+ margin: 0;
264
+ }
265
+
266
+ section > header .filter { margin-left: auto; }
267
+
268
+ section > header .filter:has(.history-graph) { display: inline-flex; }
269
+
270
+ .beacon {
271
+ background-color: var(--color-border);
272
+ border-radius: 50%;
273
+ display: inline-block;
274
+ height: 8px;
275
+ width: 8px;
276
+ transition: all 0.1s;
277
+ }
278
+
279
+ .pulse {
280
+ animation: pulse-animation 2s infinite;
281
+ background-color: var(--color-primary);
282
+ }
283
+
284
+ .info-circle {
285
+ background: var(--color-border);
286
+ border-radius: 50%;
287
+ display: inline-block;
288
+ font-size: var(--font-size-small);
289
+ line-height: 16px;
290
+ height: 16px;
291
+ width: 16px;
292
+ text-align: center;
293
+ }
294
+
295
+ @keyframes pulse-animation {
296
+ 0% { box-shadow: 0 0 0 0px oklch(from var(--color-primary) l c h / 20%); }
297
+ 100% { box-shadow: 0 0 0 8px rgba(0, 0, 0, 0); }
298
+ }
299
+
300
+ .history-graph {
301
+ border-radius: 4px;
302
+ font-size: var(--font-size-small);
303
+ padding: 4px 8px;
304
+ text-decoration: none;
305
+ }
306
+
307
+ .history-graph.active {
308
+ background: var(--color-selected);
309
+ color: var(--color-text);
310
+ }
311
+
312
+ form label {
313
+ color: var(--color-text-light);
314
+ font-size: var(--font-size-small);
315
+ }
316
+
317
+ input,
318
+ select {
319
+ background-color: var(--color-elevated);
320
+ color: var(--color-text);
321
+ border-radius: 4px;
322
+ box-shadow: 0 0 0 1px var(--color-border);
323
+ }
324
+
325
+ input[type=search] {
326
+ border-radius: 1em;
327
+ }
328
+
329
+ select {
330
+ appearance: none;
331
+ font-weight: 700;
332
+ background-color: var(--color-selected);
333
+ box-shadow: 0 0 0 1px var(--color-input-border);
334
+ }
335
+
336
+ .form-control {
337
+ border: none;
338
+ border-radius: var(--space-1-2);
339
+ display: inline-block;
340
+ height: 24px;
341
+ line-height: var(--space-2x);
342
+ padding: var(--space-1-2) var(--space);
343
+ }
344
+
345
+ .form-control:hover {
346
+ box-shadow: 0 0 0 1px oklch(from var(--color-input-border) calc(l - 0.1) c h);
347
+ }
348
+
349
+ ::placeholder {
350
+ color: var(--color-text-light);
351
+ opacity: 0.6
352
+ }
353
+
354
+ .interval-slider {
355
+ color: var(--color-text-light);
356
+ font-size: var(--font-size-small);
357
+ text-align: right;
358
+ }
359
+
360
+ .interval-slider .current-interval {
361
+ color: var(--color-text);
362
+ font-weight: 700;
363
+ }
364
+
365
+ input[type="range"] {
366
+ appearance: none;
367
+ accent-color: var(--color-text);
368
+ width: 160px;
369
+ height: 0.5em;
370
+ }
371
+
372
+ #realtime-legend {
373
+ color: var(--color-text-light);
374
+ font-size: var(--font-size-small);
375
+ display: flex;
376
+ gap: var(--space);
377
+ }
378
+
379
+ #realtime-legend .swatch {
380
+ border-radius: 50%;
381
+ display: inline-block;
382
+ margin-right: 4px;
383
+ height: 8px;
384
+ width: 8px;
385
+ }
386
+
387
+ /* cards for stats */
388
+ .cards-container {
389
+ background: var(--color-border);
390
+ border: 1px solid var(--color-border);
391
+ box-shadow: 0 2px 4px 0 var(--color-shadow);
392
+ display: flex;
393
+ flex-wrap: wrap;
394
+ gap: 1px;
395
+ align-items: center;
396
+ justify-content: center;
397
+ list-style-type: none;
398
+ margin: 0;
399
+ padding: 0;
400
+ }
401
+
402
+ article {
403
+ background-color: var(--color-elevated);
404
+ font-size: var(--font-size-small);
405
+ flex: 1;
406
+ padding: var(--space);
407
+ text-align: center;
408
+ white-space: nowrap;
409
+ }
410
+
411
+ article h3 {
412
+ display: block;
413
+ font-size: var(--font-size-large);
414
+ line-height: 1.125;
415
+ margin: 0;
416
+ padding: 0;
417
+ white-space: nowrap;
418
+ }
419
+
420
+ article p {
421
+ margin: 0;
422
+ padding: 0;
423
+ white-space: nowrap;
424
+ }
425
+
426
+ article a {
427
+ color: inherit;
428
+ text-decoration: none;
429
+ }
430
+
431
+ article a .desc { text-decoration: underline; }
432
+
433
+ article .count {
434
+ color: var(--color-primary);
435
+ display: block;
436
+ font-size: var(--font-size);
437
+ font-weight: 700;
438
+ }
439
+
440
+ /* table */
441
+ .table_container {
442
+ overflow-x: auto;
443
+ margin-bottom: var(--space-2x);
444
+ }
445
+
446
+ .table_container + form,
447
+ .table_container + input,
448
+ canvas + .table_container {
449
+ margin-top: var(--space-4x);
450
+ }
451
+
452
+ .buttons-row {
453
+ margin-top: var(--space-3x);
454
+ display: flex;
455
+ flex-wrap: wrap;
456
+ gap: 8px;
457
+ }
458
+
459
+ table {
460
+ background-color: var(--color-elevated);
461
+ border: 1px solid var(--color-border);
462
+ border-collapse: collapse;
463
+ width: 100%;
464
+ box-shadow: 0 2px 4px 0 var(--color-shadow);
465
+ }
466
+
467
+ thead { border-bottom: 2px solid var(--color-border); }
468
+
469
+ th {
470
+ color: var(--color-text-light);
471
+ font-size: var(--font-size-small);
472
+ font-weight: bold;
473
+ text-align: left;
474
+ padding: var(--space);
475
+ }
476
+
477
+ tr { border-top: 1px solid var(--color-border); }
478
+
479
+ tbody tr:nth-child(odd) { background-color: var(--color-table-bg-alt); }
480
+
481
+ tbody tr:hover { background-color: var(--color-border); }
482
+
483
+ td { padding: var(--space); }
484
+
485
+ td .btn {
486
+ font-size: var(--font-size-small);
487
+ line-height: 1.5;
488
+ padding: var(--space-1-2) var(--space);
489
+ }
490
+
491
+ td .btn:hover { color: inherit; }
492
+
493
+ td.num {
494
+ color: var(--color-text-light);
495
+ font-size: var(--font-size-small);
496
+ }
497
+
498
+ td.num span {
499
+ color: var(--color-text);
500
+ font-size: 1rem;
501
+ font-weight: 700;
502
+ }
503
+
504
+ .label:not(:empty) {
505
+ border-radius: 4px;
506
+ box-shadow: 0 0 0 1px var(--color-shadow);
507
+ font-size: var(--font-size-small);
508
+ padding: 0 var(--space);
509
+ }
510
+
511
+ .label-default { background: var(--color-selected); }
512
+ .label-success { background: var(--color-success); }
513
+ .label-info { background: var(--color-info); }
514
+ .label-danger { background: var(--color-danger); }
515
+ .label-warning { background: var(--color-warning); }
516
+
517
+ input[type="checkbox"] { accent-color: var(--color-primary); }
518
+
519
+ .alert {
520
+ background-color: var(--color-table-bg-alt);
521
+ border: 1px solid var(--color-border);
522
+ border-radius: 2px;
523
+ color: var(--color-text-light);
524
+ padding: var(--space);
525
+ }
526
+
527
+ .pagination {
528
+ display: flex;
529
+ gap: var(--space);
530
+ list-style-type: none;
531
+ margin: 0;
532
+ padding: var(--space) 0 0;
533
+ }
534
+
535
+ .pagination a { text-decoration: none; }
536
+
537
+ .pagination .disabled { opacity: 0.3; }
538
+
539
+ div:has(.pagination.pull-right) { margin-left: auto; }
540
+
541
+ /* footer */
542
+ body > footer {
543
+ background: var(--color-elevated);
544
+ box-shadow: -1px 0 4px 2px var(--color-shadow);
545
+ height: 56px;
546
+ overflow: hidden;
547
+ position: fixed;
548
+ bottom: 0;
549
+ left: 0;
550
+ right: 0;
551
+ }
552
+
553
+ body > footer .nav {
554
+ align-items: center;
555
+ color: var(--color-text-light);
556
+ font-size: var(--font-size-small);
557
+ gap: var(--space-2x);
558
+ }
559
+
560
+ /* media queries */
561
+ @media (prefers-color-scheme: dark) {
562
+ :root {
563
+ /* --color-primary: oklch(65% 0.15 13); */
564
+ --color-primary: oklch(65% 0.22 13);
565
+ --color-bg: oklch(22% 0.01 256);
566
+ --color-elevated: oklch(19% 0.01 256);
567
+ --color-border: oklch(25% 0.01 256);
568
+ --color-input-border: oklch(31% 0.01 256);
569
+ --color-selected: oklch(27% 0.01 256);
570
+ --color-selected-text: oklch(55% 0.11 45);
571
+ --color-table-bg-alt: oklch(24% 0.01 256);
572
+ --color-shadow: oklch(9% 0.01 256 / 10%);
573
+ --color-text: oklch(75% 0.01 256);
574
+ --color-text-light: oklch(65% 0.01 256);
575
+ --color-success: oklch(from var(--color-primary) calc(l - 0.3) c calc(h + 120));
576
+ --color-info: oklch(from var(--color-primary) calc(l - 0.3) c calc(h - 120));
577
+ --color-danger: oklch(from var(--color-primary) calc(l - 0.3) c h);
578
+ --color-warning: oklch(55% 0.11 45);
579
+ }
580
+
581
+ .btn-danger,
582
+ input[type="submit"].btn-danger {
583
+ background: linear-gradient(oklch(from var(--color-primary) calc(l - 0.2) c h), oklch(from var(--color-primary) calc(l - 0.25) c h));
584
+ color: var(--color-text);
585
+ }
586
+
587
+ .btn-danger:hover,
588
+ input[type="submit"].btn-danger:hover {
589
+ background: linear-gradient(oklch(from var(--color-primary) calc(l - 0.15) c h), oklch(from var(--color-primary) calc(l - 0.2) c h));
590
+ color: var(--color-text);
591
+ }
592
+
593
+ .btn-warn,
594
+ input[type="submit"].btn-warn {
595
+ background: linear-gradient(oklch(from var(--color-primary) calc(l - 0.2) c calc(h + 75)), oklch(from var(--color-primary) calc(l - 0.25) c calc(h + 75)));
596
+ color: var(--color-text);
597
+ }
598
+
599
+ .btn-warn:hover,
600
+ input[type="submit"].btn-warn:hover {
601
+ background: linear-gradient(oklch(from var(--color-primary) calc(l - 0.15) c calc(h + 75)), oklch(from var(--color-primary) calc(l - 0.2) c calc(h + 75)));
602
+ color: var(--color-text);
603
+ }
604
+
605
+ .btn-inverse {
606
+ background: transparent;
607
+ box-shadow: 0 0 0 1px var(--color-input-border) inset;
608
+ color: inherit;
609
+ }
610
+
611
+ .btn-inverse:hover { box-shadow: 0 0 0 1px oklch(from var(--color-input-border) calc(l + 0.1) c h) inset; }
612
+
613
+ .form-control:hover { box-shadow: 0 0 0 1px oklch(from var(--color-input-border) calc(l + 0.1) c h); }
614
+
615
+ .label-success { background: var(--color-success); }
616
+ .label-info { background: var(--color-info); }
617
+ .label-danger { background: var(--color-danger); }
618
+ .label-warning { background: var(--color-warning); }
619
+
620
+ td.box::selection {
621
+ background-color: var(--color-selected-text);
622
+ }
623
+ }
624
+
625
+ @media (max-width: 800px) { :root { --font-size: 14px; } }
626
+
627
+ @media (max-width: 1000px) {
628
+ body { padding-bottom: 0; }
629
+
630
+ main {
631
+ min-height: calc(100vh - 256px);
632
+ padding: 0 0 32px;
633
+ }
634
+
635
+ body > header .container { flex-wrap: wrap; }
636
+
637
+ .nav { flex-direction: column; }
638
+
639
+ .navbar-toggle {
640
+ display: inline-flex;
641
+ align-items: center;
642
+ justify-content: center;
643
+ flex-direction: column;
644
+ gap: 4px;
645
+ min-height: 40px;
646
+ margin: 0;
647
+ padding: var(--space);
648
+ background: transparent;
649
+ box-shadow: 0 0 0 1px var(--color-border) inset;
650
+ }
651
+
652
+ .navbar-toggle .icon-bar {
653
+ display: inline-block;
654
+ width: 24px;
655
+ height: 2px;
656
+ background-color: var(--color-text-light);
657
+ }
658
+
659
+ .navbar-toggle:hover .icon-bar { background-color: var(--color-bg); }
660
+
661
+ .navbar-header .navbar-livereload { display: none; }
662
+
663
+ .navbar-collapse {
664
+ display: none;
665
+ position: fixed;
666
+ background-color: var(--color-bg);
667
+ border-bottom: 1px solid var(--color-border);
668
+ padding-top: var(--space);
669
+ top: 56px;
670
+ left: 0;
671
+ right: 0;
672
+ }
673
+
674
+ .navbar-collapse.is-open {
675
+ box-shadow: 0 2px 4px 0 var(--color-shadow);
676
+ display: flex;
677
+ padding-bottom: var(--space-2x);
678
+ max-height: calc(100svh - 56px);
679
+ overflow: auto;
680
+ }
681
+
682
+ body > header .nav li.navbar-livereload { margin: var(--space) 0 0; }
683
+
684
+ body > footer {
685
+ position: relative;
686
+ height: auto;
687
+ }
688
+ }
689
+
690
+ [dir="rtl"] {
691
+ .navbar-brand { margin: var(--space-2x) 0 0 var(--space-2x); }
692
+
693
+ body > header .nav li.navbar-livereload {
694
+ margin: 0 auto 0 0;
695
+ padding-left: 0;
696
+ }
697
+
698
+ section > header .filter {
699
+ margin-right: auto;
700
+ margin-left: 0;
701
+ }
702
+
703
+ th { text-align: right; }
704
+
705
+ #realtime-legend .swatch { margin: 0 0 0 4px; }
706
+
707
+ .interval-slider { text-align: left; }
708
+ }
709
+
710
+ /* progress bars */
711
+ @keyframes progress-bar-stripes {
712
+ from {
713
+ background-position: 40px 0;
714
+ }
715
+ to {
716
+ background-position: 0 0;
717
+ }
718
+ }
719
+ .progress {
720
+ width: 100%;
721
+ display: inline-block;
722
+ vertical-align: baseline;
723
+ height: 20px;
724
+ margin-bottom: 0px;
725
+ overflow: hidden;
726
+ background-color: #f5f5f5;
727
+ border-radius: 1em;
728
+ }
729
+ .progress-bar {
730
+ float: left;
731
+ width: 0;
732
+ height: 100%;
733
+ font-size: 12px;
734
+ line-height: 20px;
735
+ color: #fff;
736
+ text-align: center;
737
+ background-color: #337ab7;
738
+ }
739
+ .progress-striped .progress-bar,
740
+ .progress-bar-striped {
741
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
742
+ background-size: 40px 40px;
743
+ }
744
+ .bg-success {
745
+ background-color: var(--color-success);
746
+ }
747
+ .bg-warning {
748
+ background-color: var(--color-warning);
749
+ }
750
+ .bg-danger {
751
+ background-color: var(--color-danger);
752
+ }
753
+ .bg-info {
754
+ background-color: var(--color-info);
755
+ }
756
+
757
+ .w-50 {
758
+ width: 50%;
759
+ }
760
+
761
+ .flash {
762
+ width: 100%;
763
+ text-align: center;
764
+ padding: 20px;
765
+ background: var(--color-success);
766
+ }