serialbench 0.1.0 → 0.1.2

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/benchmark.yml +181 -30
  3. data/.github/workflows/ci.yml +3 -3
  4. data/.github/workflows/docker.yml +272 -0
  5. data/.github/workflows/rake.yml +15 -0
  6. data/.github/workflows/release.yml +25 -0
  7. data/Gemfile +6 -30
  8. data/README.adoc +381 -415
  9. data/Rakefile +0 -55
  10. data/config/benchmarks/full.yml +29 -0
  11. data/config/benchmarks/short.yml +26 -0
  12. data/config/environments/asdf-ruby-3.2.yml +8 -0
  13. data/config/environments/asdf-ruby-3.3.yml +8 -0
  14. data/config/environments/docker-ruby-3.0.yml +9 -0
  15. data/config/environments/docker-ruby-3.1.yml +9 -0
  16. data/config/environments/docker-ruby-3.2.yml +9 -0
  17. data/config/environments/docker-ruby-3.3.yml +9 -0
  18. data/config/environments/docker-ruby-3.4.yml +9 -0
  19. data/docker/Dockerfile.alpine +33 -0
  20. data/docker/Dockerfile.ubuntu +32 -0
  21. data/docker/README.md +214 -0
  22. data/exe/serialbench +1 -1
  23. data/lib/serialbench/benchmark_runner.rb +270 -350
  24. data/lib/serialbench/cli/base_cli.rb +51 -0
  25. data/lib/serialbench/cli/benchmark_cli.rb +380 -0
  26. data/lib/serialbench/cli/environment_cli.rb +181 -0
  27. data/lib/serialbench/cli/resultset_cli.rb +215 -0
  28. data/lib/serialbench/cli/ruby_build_cli.rb +238 -0
  29. data/lib/serialbench/cli.rb +59 -410
  30. data/lib/serialbench/config_manager.rb +140 -0
  31. data/lib/serialbench/models/benchmark_config.rb +63 -0
  32. data/lib/serialbench/models/benchmark_result.rb +45 -0
  33. data/lib/serialbench/models/environment_config.rb +71 -0
  34. data/lib/serialbench/models/platform.rb +59 -0
  35. data/lib/serialbench/models/result.rb +53 -0
  36. data/lib/serialbench/models/result_set.rb +71 -0
  37. data/lib/serialbench/models/result_store.rb +108 -0
  38. data/lib/serialbench/models.rb +54 -0
  39. data/lib/serialbench/ruby_build_manager.rb +153 -0
  40. data/lib/serialbench/runners/asdf_runner.rb +296 -0
  41. data/lib/serialbench/runners/base.rb +32 -0
  42. data/lib/serialbench/runners/docker_runner.rb +142 -0
  43. data/lib/serialbench/serializers/base_serializer.rb +8 -16
  44. data/lib/serialbench/serializers/json/base_json_serializer.rb +4 -4
  45. data/lib/serialbench/serializers/json/json_serializer.rb +0 -2
  46. data/lib/serialbench/serializers/json/oj_serializer.rb +0 -2
  47. data/lib/serialbench/serializers/json/rapidjson_serializer.rb +50 -0
  48. data/lib/serialbench/serializers/json/yajl_serializer.rb +6 -4
  49. data/lib/serialbench/serializers/toml/base_toml_serializer.rb +5 -3
  50. data/lib/serialbench/serializers/toml/toml_rb_serializer.rb +0 -2
  51. data/lib/serialbench/serializers/toml/tomlib_serializer.rb +0 -2
  52. data/lib/serialbench/serializers/toml/tomlrb_serializer.rb +56 -0
  53. data/lib/serialbench/serializers/xml/base_xml_serializer.rb +4 -9
  54. data/lib/serialbench/serializers/xml/libxml_serializer.rb +0 -2
  55. data/lib/serialbench/serializers/xml/nokogiri_serializer.rb +21 -5
  56. data/lib/serialbench/serializers/xml/oga_serializer.rb +0 -2
  57. data/lib/serialbench/serializers/xml/ox_serializer.rb +0 -2
  58. data/lib/serialbench/serializers/xml/rexml_serializer.rb +32 -4
  59. data/lib/serialbench/serializers/yaml/base_yaml_serializer.rb +59 -0
  60. data/lib/serialbench/serializers/yaml/psych_serializer.rb +54 -0
  61. data/lib/serialbench/serializers/yaml/syck_serializer.rb +102 -0
  62. data/lib/serialbench/serializers.rb +34 -6
  63. data/lib/serialbench/site_generator.rb +105 -0
  64. data/lib/serialbench/templates/assets/css/benchmark_report.css +535 -0
  65. data/lib/serialbench/templates/assets/css/format_based.css +526 -0
  66. data/lib/serialbench/templates/assets/css/themes.css +588 -0
  67. data/lib/serialbench/templates/assets/js/chart_helpers.js +381 -0
  68. data/lib/serialbench/templates/assets/js/dashboard.js +796 -0
  69. data/lib/serialbench/templates/assets/js/navigation.js +142 -0
  70. data/lib/serialbench/templates/base.liquid +49 -0
  71. data/lib/serialbench/templates/format_based.liquid +279 -0
  72. data/lib/serialbench/templates/partials/chart_section.liquid +4 -0
  73. data/lib/serialbench/version.rb +1 -1
  74. data/lib/serialbench.rb +2 -31
  75. data/serialbench.gemspec +28 -17
  76. metadata +192 -55
  77. data/lib/serialbench/chart_generator.rb +0 -821
  78. data/lib/serialbench/result_formatter.rb +0 -182
  79. data/lib/serialbench/result_merger.rb +0 -1201
  80. data/lib/serialbench/serializers/xml/base_parser.rb +0 -69
  81. data/lib/serialbench/serializers/xml/libxml_parser.rb +0 -98
  82. data/lib/serialbench/serializers/xml/nokogiri_parser.rb +0 -111
  83. data/lib/serialbench/serializers/xml/oga_parser.rb +0 -85
  84. data/lib/serialbench/serializers/xml/ox_parser.rb +0 -64
  85. data/lib/serialbench/serializers/xml/rexml_parser.rb +0 -129
@@ -0,0 +1,588 @@
1
+ /* Modern Dark Marine/Orange Theme with Light/Dark Mode Support */
2
+
3
+ /* CSS Custom Properties for Theme System */
4
+ :root {
5
+ /* Dark Marine Theme (Default) */
6
+ --bg-primary: #0F172A;
7
+ --bg-secondary: #1E293B;
8
+ --bg-tertiary: #334155;
9
+ --bg-card: #1E293B;
10
+ --bg-hover: #334155;
11
+
12
+ /* Orange Accent Colors */
13
+ --accent-primary: #F97316;
14
+ --accent-secondary: #EA580C;
15
+ --accent-tertiary: #FB923C;
16
+ --accent-light: #FED7AA;
17
+
18
+ /* Text Colors */
19
+ --text-primary: #F8FAFC;
20
+ --text-secondary: #CBD5E1;
21
+ --text-muted: #64748B;
22
+ --text-inverse: #0F172A;
23
+
24
+ /* Border Colors */
25
+ --border-primary: #475569;
26
+ --border-secondary: #334155;
27
+ --border-accent: #F97316;
28
+
29
+ /* Status Colors */
30
+ --success: #10B981;
31
+ --warning: #F59E0B;
32
+ --error: #EF4444;
33
+ --info: #3B82F6;
34
+
35
+ /* Shadows */
36
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.3);
37
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4);
38
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
39
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.6);
40
+
41
+ /* Gradients */
42
+ --gradient-primary: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary));
43
+ --gradient-secondary: linear-gradient(135deg, var(--bg-secondary), var(--bg-tertiary));
44
+ --gradient-accent: linear-gradient(135deg, var(--accent-tertiary), var(--accent-primary));
45
+
46
+ /* Spacing */
47
+ --space-xs: 0.25rem;
48
+ --space-sm: 0.5rem;
49
+ --space-md: 1rem;
50
+ --space-lg: 1.5rem;
51
+ --space-xl: 2rem;
52
+ --space-2xl: 3rem;
53
+
54
+ /* Border Radius */
55
+ --radius-sm: 0.375rem;
56
+ --radius-md: 0.5rem;
57
+ --radius-lg: 0.75rem;
58
+ --radius-xl: 1rem;
59
+ --radius-full: 9999px;
60
+
61
+ /* Typography */
62
+ --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
63
+ --font-mono: 'JetBrains Mono', 'Fira Code', Consolas, monospace;
64
+
65
+ /* Transitions */
66
+ --transition-fast: 0.15s ease-in-out;
67
+ --transition-normal: 0.3s ease-in-out;
68
+ --transition-slow: 0.5s ease-in-out;
69
+ }
70
+
71
+ /* Light Theme Override */
72
+ [data-theme="light"] {
73
+ --bg-primary: #FFFFFF;
74
+ --bg-secondary: #F8FAFC;
75
+ --bg-tertiary: #E2E8F0;
76
+ --bg-card: #FFFFFF;
77
+ --bg-hover: #F1F5F9;
78
+
79
+ --text-primary: #0F172A;
80
+ --text-secondary: #334155;
81
+ --text-muted: #64748B;
82
+ --text-inverse: #FFFFFF;
83
+
84
+ --border-primary: #E2E8F0;
85
+ --border-secondary: #CBD5E1;
86
+
87
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
88
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
89
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
90
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
91
+ }
92
+
93
+ /* Base Styles */
94
+ * {
95
+ box-sizing: border-box;
96
+ }
97
+
98
+ html {
99
+ font-family: var(--font-family);
100
+ line-height: 1.6;
101
+ -webkit-font-smoothing: antialiased;
102
+ -moz-osx-font-smoothing: grayscale;
103
+ }
104
+
105
+ body {
106
+ margin: 0;
107
+ padding: 0;
108
+ background: var(--bg-primary);
109
+ color: var(--text-primary);
110
+ transition: background-color var(--transition-normal), color var(--transition-normal);
111
+ min-height: 100vh;
112
+ }
113
+
114
+ /* Navigation Bar */
115
+ .navbar {
116
+ background: var(--bg-secondary);
117
+ border-bottom: 1px solid var(--border-primary);
118
+ box-shadow: var(--shadow-md);
119
+ position: sticky;
120
+ top: 0;
121
+ z-index: 1000;
122
+ backdrop-filter: blur(10px);
123
+ }
124
+
125
+ .navbar-container {
126
+ max-width: 1400px;
127
+ margin: 0 auto;
128
+ padding: 0 var(--space-lg);
129
+ }
130
+
131
+ .navbar-header {
132
+ display: flex;
133
+ justify-content: space-between;
134
+ align-items: center;
135
+ padding: var(--space-md) 0;
136
+ }
137
+
138
+ .navbar-brand {
139
+ display: flex;
140
+ align-items: center;
141
+ gap: var(--space-sm);
142
+ font-size: 1.5rem;
143
+ font-weight: 700;
144
+ color: var(--text-primary);
145
+ text-decoration: none;
146
+ }
147
+
148
+ .navbar-brand-icon {
149
+ width: 32px;
150
+ height: 32px;
151
+ background: var(--gradient-primary);
152
+ border-radius: var(--radius-md);
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: center;
156
+ color: white;
157
+ }
158
+
159
+ .navbar-controls {
160
+ display: flex;
161
+ align-items: center;
162
+ gap: var(--space-md);
163
+ }
164
+
165
+ /* Theme Toggle */
166
+ .theme-toggle {
167
+ background: var(--bg-tertiary);
168
+ border: 1px solid var(--border-primary);
169
+ border-radius: var(--radius-full);
170
+ padding: var(--space-sm);
171
+ cursor: pointer;
172
+ transition: all var(--transition-fast);
173
+ display: flex;
174
+ align-items: center;
175
+ justify-content: center;
176
+ width: 40px;
177
+ height: 40px;
178
+ }
179
+
180
+ .theme-toggle:hover {
181
+ background: var(--bg-hover);
182
+ transform: scale(1.05);
183
+ }
184
+
185
+ .theme-toggle svg {
186
+ width: 20px;
187
+ height: 20px;
188
+ color: var(--text-secondary);
189
+ transition: color var(--transition-fast);
190
+ }
191
+
192
+ /* Filter Bar */
193
+ .filter-bar {
194
+ /* background: var(--bg-tertiary); */
195
+ border-bottom: 1px solid var(--border-primary);
196
+ padding: var(--space-md) 0;
197
+ }
198
+
199
+ .filter-container {
200
+ display: flex;
201
+ align-items: center;
202
+ gap: var(--space-lg);
203
+ flex-wrap: wrap;
204
+ }
205
+
206
+ .filter-group {
207
+ display: flex;
208
+ align-items: center;
209
+ gap: var(--space-sm);
210
+ }
211
+
212
+ .filter-label {
213
+ font-size: 0.875rem;
214
+ font-weight: 600;
215
+ color: var(--text-secondary);
216
+ white-space: nowrap;
217
+ }
218
+
219
+ /* Custom Select Styling */
220
+ .custom-select {
221
+ position: relative;
222
+ min-width: 150px;
223
+ }
224
+
225
+ .custom-select select {
226
+ width: 100%;
227
+ padding: var(--space-sm) var(--space-md);
228
+ background: var(--bg-card);
229
+ border: 1px solid var(--border-primary);
230
+ border-radius: var(--radius-md);
231
+ color: var(--text-primary);
232
+ font-size: 0.875rem;
233
+ cursor: pointer;
234
+ transition: all var(--transition-fast);
235
+ appearance: none;
236
+ background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
237
+ background-position: right var(--space-sm) center;
238
+ background-repeat: no-repeat;
239
+ background-size: 16px;
240
+ padding-right: 2.5rem;
241
+ }
242
+
243
+ .custom-select select:focus {
244
+ outline: none;
245
+ border-color: var(--accent-primary);
246
+ box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.1);
247
+ }
248
+
249
+ .custom-select select:hover {
250
+ border-color: var(--border-accent);
251
+ }
252
+
253
+ /* Format Tabs */
254
+ .format-tabs {
255
+ display: flex;
256
+ gap: var(--space-xs);
257
+ margin-left: auto;
258
+ }
259
+
260
+ .format-tab {
261
+ padding: var(--space-sm) var(--space-lg);
262
+ background: transparent;
263
+ border: 1px solid var(--border-primary);
264
+ border-radius: var(--radius-md);
265
+ color: var(--text-secondary);
266
+ font-size: 0.875rem;
267
+ font-weight: 600;
268
+ cursor: pointer;
269
+ transition: all var(--transition-fast);
270
+ text-transform: uppercase;
271
+ letter-spacing: 0.05em;
272
+ }
273
+
274
+ .format-tab:hover {
275
+ background: var(--bg-hover);
276
+ color: var(--text-primary);
277
+ transform: translateY(-1px);
278
+ }
279
+
280
+ .format-tab.active {
281
+ background: var(--gradient-primary);
282
+ border-color: var(--accent-primary);
283
+ color: white;
284
+ box-shadow: var(--shadow-md);
285
+ }
286
+
287
+ /* Main Content */
288
+ .main-content {
289
+ max-width: 1400px;
290
+ margin: 0 auto;
291
+ padding: var(--space-xl) var(--space-lg);
292
+ }
293
+
294
+ /* Dashboard Grid */
295
+ .dashboard-grid {
296
+ display: grid;
297
+ grid-template-columns: repeat(2, 1fr);
298
+ gap: var(--space-xl);
299
+ margin-bottom: var(--space-2xl);
300
+ }
301
+
302
+ /* Chart Cards */
303
+ .chart-card {
304
+ background: var(--bg-card);
305
+ border: 1px solid var(--border-primary);
306
+ border-radius: var(--radius-lg);
307
+ padding: var(--space-xl);
308
+ box-shadow: var(--shadow-md);
309
+ transition: all var(--transition-normal);
310
+ position: relative;
311
+ overflow: hidden;
312
+ }
313
+
314
+ .chart-card::before {
315
+ content: '';
316
+ position: absolute;
317
+ top: 0;
318
+ left: 0;
319
+ right: 0;
320
+ height: 3px;
321
+ background: var(--gradient-primary);
322
+ }
323
+
324
+ .chart-card:hover {
325
+ transform: translateY(-2px);
326
+ box-shadow: var(--shadow-lg);
327
+ }
328
+
329
+ .chart-header {
330
+ display: flex;
331
+ justify-content: between;
332
+ align-items: center;
333
+ margin-bottom: var(--space-lg);
334
+ }
335
+
336
+ .chart-title {
337
+ font-size: 1.25rem;
338
+ font-weight: 700;
339
+ color: var(--text-primary);
340
+ margin: 0;
341
+ }
342
+
343
+ .chart-subtitle {
344
+ font-size: 0.875rem;
345
+ color: var(--text-muted);
346
+ margin: var(--space-xs) 0 0 0;
347
+ }
348
+
349
+ .chart-container {
350
+ position: relative;
351
+ height: 300px;
352
+ margin-bottom: var(--space-md);
353
+ }
354
+
355
+ .chart-container canvas {
356
+ max-width: 100%;
357
+ height: auto;
358
+ }
359
+
360
+ /* Loading and Error States */
361
+ .chart-loading,
362
+ .chart-error {
363
+ display: flex;
364
+ align-items: center;
365
+ justify-content: center;
366
+ height: 300px;
367
+ color: var(--text-muted);
368
+ font-style: italic;
369
+ }
370
+
371
+ .chart-error {
372
+ color: var(--error);
373
+ }
374
+
375
+ /* Summary Section */
376
+ .summary-section {
377
+ background: var(--bg-card);
378
+ border: 1px solid var(--border-primary);
379
+ border-radius: var(--radius-lg);
380
+ padding: var(--space-xl);
381
+ margin-bottom: var(--space-2xl);
382
+ box-shadow: var(--shadow-md);
383
+ }
384
+
385
+ .summary-title {
386
+ font-size: 1.5rem;
387
+ font-weight: 700;
388
+ color: var(--text-primary);
389
+ margin-bottom: var(--space-lg);
390
+ }
391
+
392
+ .summary-grid {
393
+ display: grid;
394
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
395
+ gap: var(--space-lg);
396
+ }
397
+
398
+ .summary-card {
399
+ background: var(--bg-secondary);
400
+ border: 1px solid var(--border-secondary);
401
+ border-radius: var(--radius-md);
402
+ padding: var(--space-lg);
403
+ transition: all var(--transition-fast);
404
+ }
405
+
406
+ .summary-card:hover {
407
+ transform: translateY(-1px);
408
+ box-shadow: var(--shadow-md);
409
+ }
410
+
411
+ .summary-card-title {
412
+ font-size: 1.125rem;
413
+ font-weight: 600;
414
+ color: var(--accent-primary);
415
+ margin-bottom: var(--space-md);
416
+ }
417
+
418
+ /* Environment Section */
419
+ .environment-section {
420
+ background: var(--bg-card);
421
+ border: 1px solid var(--border-primary);
422
+ border-radius: var(--radius-lg);
423
+ padding: var(--space-xl);
424
+ box-shadow: var(--shadow-md);
425
+ }
426
+
427
+ .environment-grid {
428
+ display: grid;
429
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
430
+ gap: var(--space-lg);
431
+ }
432
+
433
+ .environment-card {
434
+ background: var(--bg-secondary);
435
+ border: 1px solid var(--border-secondary);
436
+ border-radius: var(--radius-md);
437
+ padding: var(--space-lg);
438
+ transition: all var(--transition-fast);
439
+ }
440
+
441
+ .environment-card:hover {
442
+ transform: translateY(-1px);
443
+ box-shadow: var(--shadow-md);
444
+ }
445
+
446
+ .environment-card-title {
447
+ font-size: 1.125rem;
448
+ font-weight: 600;
449
+ color: var(--text-primary);
450
+ margin-bottom: var(--space-md);
451
+ }
452
+
453
+ /* Responsive Design */
454
+ @media (max-width: 1024px) {
455
+ .dashboard-grid {
456
+ grid-template-columns: 1fr;
457
+ }
458
+
459
+ .filter-container {
460
+ flex-direction: column;
461
+ align-items: stretch;
462
+ gap: var(--space-md);
463
+ }
464
+
465
+ .format-tabs {
466
+ margin-left: 0;
467
+ justify-content: center;
468
+ }
469
+ }
470
+
471
+ @media (max-width: 768px) {
472
+ .navbar-header {
473
+ flex-direction: column;
474
+ gap: var(--space-md);
475
+ }
476
+
477
+ .navbar-controls {
478
+ order: -1;
479
+ align-self: flex-end;
480
+ }
481
+
482
+ .main-content {
483
+ padding: var(--space-lg) var(--space-md);
484
+ }
485
+
486
+ .chart-card {
487
+ padding: var(--space-lg);
488
+ }
489
+
490
+ .chart-container {
491
+ height: 250px;
492
+ }
493
+ }
494
+
495
+ @media (max-width: 480px) {
496
+ .format-tabs {
497
+ flex-direction: column;
498
+ width: 100%;
499
+ }
500
+
501
+ .format-tab {
502
+ width: 100%;
503
+ text-align: center;
504
+ }
505
+
506
+ .summary-grid,
507
+ .environment-grid {
508
+ grid-template-columns: 1fr;
509
+ }
510
+ }
511
+
512
+ /* Animations */
513
+ @keyframes fadeInUp {
514
+ from {
515
+ opacity: 0;
516
+ transform: translateY(20px);
517
+ }
518
+ to {
519
+ opacity: 1;
520
+ transform: translateY(0);
521
+ }
522
+ }
523
+
524
+ @keyframes slideInRight {
525
+ from {
526
+ opacity: 0;
527
+ transform: translateX(20px);
528
+ }
529
+ to {
530
+ opacity: 1;
531
+ transform: translateX(0);
532
+ }
533
+ }
534
+
535
+ .fade-in-up {
536
+ animation: fadeInUp 0.6s ease-out;
537
+ }
538
+
539
+ .slide-in-right {
540
+ animation: slideInRight 0.4s ease-out;
541
+ }
542
+
543
+ /* Utility Classes */
544
+ .hidden {
545
+ display: none !important;
546
+ }
547
+
548
+ .sr-only {
549
+ position: absolute;
550
+ width: 1px;
551
+ height: 1px;
552
+ padding: 0;
553
+ margin: -1px;
554
+ overflow: hidden;
555
+ clip: rect(0, 0, 0, 0);
556
+ white-space: nowrap;
557
+ border: 0;
558
+ }
559
+
560
+ /* Focus Styles for Accessibility */
561
+ *:focus {
562
+ outline: 2px solid var(--accent-primary);
563
+ outline-offset: 2px;
564
+ }
565
+
566
+ button:focus,
567
+ select:focus {
568
+ outline-offset: 0;
569
+ }
570
+
571
+ /* High Contrast Mode Support */
572
+ @media (prefers-contrast: high) {
573
+ :root {
574
+ --border-primary: var(--text-primary);
575
+ --border-secondary: var(--text-secondary);
576
+ }
577
+ }
578
+
579
+ /* Reduced Motion Support */
580
+ @media (prefers-reduced-motion: reduce) {
581
+ *,
582
+ *::before,
583
+ *::after {
584
+ animation-duration: 0.01ms !important;
585
+ animation-iteration-count: 1 !important;
586
+ transition-duration: 0.01ms !important;
587
+ }
588
+ }