smriti 0.5.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 (124) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +168 -0
  4. data/Rakefile +15 -0
  5. data/app/assets/images/smriti/android-chrome-192x192.png +0 -0
  6. data/app/assets/images/smriti/android-chrome-512x512.png +0 -0
  7. data/app/assets/images/smriti/apple-touch-icon.png +0 -0
  8. data/app/assets/images/smriti/favicon-16x16.png +0 -0
  9. data/app/assets/images/smriti/favicon-32x32.png +0 -0
  10. data/app/assets/images/smriti/favicon-48x48.png +0 -0
  11. data/app/assets/images/smriti/favicon.ico +0 -0
  12. data/app/assets/images/smriti/favicon.svg +18 -0
  13. data/app/assets/images/smriti/logo.svg +18 -0
  14. data/app/assets/images/smriti/mask-icon.svg +5 -0
  15. data/app/assets/stylesheets/smriti/application.css +1040 -0
  16. data/app/controllers/smriti/admin/application_controller.rb +135 -0
  17. data/app/controllers/smriti/admin/dashboard_controller.rb +32 -0
  18. data/app/controllers/smriti/admin/mat_view_definitions_controller.rb +372 -0
  19. data/app/controllers/smriti/admin/mat_view_runs_controller.rb +185 -0
  20. data/app/controllers/smriti/admin/preferences_controller.rb +91 -0
  21. data/app/helpers/smriti/admin/datatable_helper.rb +249 -0
  22. data/app/helpers/smriti/admin/localized_digit_helper.rb +70 -0
  23. data/app/helpers/smriti/admin/ui_helper.rb +539 -0
  24. data/app/javascript/smriti/application.js +8 -0
  25. data/app/javascript/smriti/controllers/application.js +10 -0
  26. data/app/javascript/smriti/controllers/body_setup_controller.js +120 -0
  27. data/app/javascript/smriti/controllers/datatable_controller.js +351 -0
  28. data/app/javascript/smriti/controllers/details_controller.js +200 -0
  29. data/app/javascript/smriti/controllers/drawer_controller.js +470 -0
  30. data/app/javascript/smriti/controllers/flash_controller.js +112 -0
  31. data/app/javascript/smriti/controllers/index.js +10 -0
  32. data/app/javascript/smriti/controllers/mv_confirm_controller.js +435 -0
  33. data/app/javascript/smriti/controllers/tabs_controller.js +184 -0
  34. data/app/javascript/smriti/controllers/tooltip_controller.js +525 -0
  35. data/app/javascript/smriti/controllers/turbo_frame_lifecycle_controller.js +342 -0
  36. data/app/jobs/smriti/application_job.rb +144 -0
  37. data/app/jobs/smriti/create_view_job.rb +87 -0
  38. data/app/jobs/smriti/delete_view_job.rb +89 -0
  39. data/app/jobs/smriti/refresh_view_job.rb +94 -0
  40. data/app/models/concerns/smriti_i18n.rb +139 -0
  41. data/app/models/concerns/smriti_paginate.rb +70 -0
  42. data/app/models/concerns/smriti_query_helper.rb +36 -0
  43. data/app/models/smriti/application_record.rb +39 -0
  44. data/app/models/smriti/mat_view_definition.rb +254 -0
  45. data/app/models/smriti/mat_view_run.rb +275 -0
  46. data/app/views/layouts/smriti/_footer.html.erb +47 -0
  47. data/app/views/layouts/smriti/_header.html.erb +25 -0
  48. data/app/views/layouts/smriti/admin.html.erb +47 -0
  49. data/app/views/layouts/smriti/turbo_frame.html.erb +3 -0
  50. data/app/views/smriti/admin/dashboard/index.html.erb +38 -0
  51. data/app/views/smriti/admin/mat_view_definitions/_definition_actions.html.erb +94 -0
  52. data/app/views/smriti/admin/mat_view_definitions/_dt-index-empty-row.html.erb +11 -0
  53. data/app/views/smriti/admin/mat_view_definitions/_dt-index-row.html.erb +27 -0
  54. data/app/views/smriti/admin/mat_view_definitions/empty.html.erb +1 -0
  55. data/app/views/smriti/admin/mat_view_definitions/form.html.erb +79 -0
  56. data/app/views/smriti/admin/mat_view_definitions/index.html.erb +10 -0
  57. data/app/views/smriti/admin/mat_view_definitions/show.html.erb +40 -0
  58. data/app/views/smriti/admin/mat_view_runs/_dt-index-empty-row.html.erb +11 -0
  59. data/app/views/smriti/admin/mat_view_runs/_dt-index-row.html.erb +41 -0
  60. data/app/views/smriti/admin/mat_view_runs/index.html.erb +1 -0
  61. data/app/views/smriti/admin/mat_view_runs/show.html.erb +64 -0
  62. data/app/views/smriti/admin/preferences/show.html.erb +49 -0
  63. data/app/views/smriti/admin/ui/_card.html.erb +15 -0
  64. data/app/views/smriti/admin/ui/_datatable.html.erb +34 -0
  65. data/app/views/smriti/admin/ui/_datatable_filters.html.erb +45 -0
  66. data/app/views/smriti/admin/ui/_datatable_tbody.html.erb +11 -0
  67. data/app/views/smriti/admin/ui/_datatable_tfoot.html.erb +70 -0
  68. data/app/views/smriti/admin/ui/_datatable_thead.html.erb +105 -0
  69. data/app/views/smriti/admin/ui/_details.html.erb +10 -0
  70. data/app/views/smriti/admin/ui/_flash.html.erb +6 -0
  71. data/app/views/smriti/admin/ui/_table.html.erb +8 -0
  72. data/config/importmap.rb +9 -0
  73. data/config/locales/ar.yml +223 -0
  74. data/config/locales/de.yml +230 -0
  75. data/config/locales/en-AU-ocker.yml +223 -0
  76. data/config/locales/en-AU.yml +202 -0
  77. data/config/locales/en-BORK.yml +225 -0
  78. data/config/locales/en-CA.yml +223 -0
  79. data/config/locales/en-GB.yml +223 -0
  80. data/config/locales/en-LOL.yml +219 -0
  81. data/config/locales/en-SCOT.yml +223 -0
  82. data/config/locales/en-SHAKESPEARE.yml +225 -0
  83. data/config/locales/en-US-pirate.yml +222 -0
  84. data/config/locales/en-US.yml +225 -0
  85. data/config/locales/en-YODA.yml +221 -0
  86. data/config/locales/en.yml +223 -0
  87. data/config/locales/es.yml +226 -0
  88. data/config/locales/fa.yml +223 -0
  89. data/config/locales/fr-CA.yml +227 -0
  90. data/config/locales/fr.yml +227 -0
  91. data/config/locales/he.yml +218 -0
  92. data/config/locales/hi.yml +223 -0
  93. data/config/locales/it.yml +225 -0
  94. data/config/locales/ja-JP.yml +215 -0
  95. data/config/locales/pt.yml +225 -0
  96. data/config/locales/ru.yml +228 -0
  97. data/config/locales/ur.yml +225 -0
  98. data/config/locales/zh-CN.yml +214 -0
  99. data/config/locales/zh-TW.yml +214 -0
  100. data/config/routes.rb +36 -0
  101. data/lib/ext/exception.rb +20 -0
  102. data/lib/generators/smriti/install/install_generator.rb +86 -0
  103. data/lib/generators/smriti/install/templates/create_mat_view_definitions.rb +29 -0
  104. data/lib/generators/smriti/install/templates/create_mat_view_runs.rb +32 -0
  105. data/lib/generators/smriti/install/templates/smriti_initializer.rb +23 -0
  106. data/lib/smriti/admin/auth_bridge.rb +93 -0
  107. data/lib/smriti/admin/default_auth.rb +62 -0
  108. data/lib/smriti/configuration.rb +58 -0
  109. data/lib/smriti/engine.rb +82 -0
  110. data/lib/smriti/helpers/ui_test_ids.rb +49 -0
  111. data/lib/smriti/jobs/adapter.rb +81 -0
  112. data/lib/smriti/service_response.rb +75 -0
  113. data/lib/smriti/services/base_service.rb +471 -0
  114. data/lib/smriti/services/check_matview_exists.rb +76 -0
  115. data/lib/smriti/services/concurrent_refresh.rb +94 -0
  116. data/lib/smriti/services/create_view.rb +173 -0
  117. data/lib/smriti/services/delete_view.rb +111 -0
  118. data/lib/smriti/services/regular_refresh.rb +90 -0
  119. data/lib/smriti/services/swap_refresh.rb +181 -0
  120. data/lib/smriti/version.rb +21 -0
  121. data/lib/smriti.rb +64 -0
  122. data/lib/tasks/helpers.rb +185 -0
  123. data/lib/tasks/smriti_tasks.rake +151 -0
  124. metadata +206 -0
@@ -0,0 +1,1040 @@
1
+ /*!
2
+ * Copyright (c) Codevedas Inc. 2025–present
3
+ * This source code is licensed under the MIT license found in the
4
+ * LICENSE file in the root directory of this source tree.
5
+ */
6
+ /*
7
+ *= require_tree .
8
+ *= require_self
9
+ */
10
+
11
+ :root {
12
+ --font-base: 14px/1.4 Inter, system-ui;
13
+ --font-head: "Space Grotesk";
14
+ --font-mono: "JetBrains Mono", monospace;
15
+
16
+ /* Spacing */
17
+ --spacing-xs: 0.25rem;
18
+ --spacing-sm: 0.5rem;
19
+ --spacing-md: 0.75rem;
20
+ --spacing-lg: 1rem;
21
+ --spacing-xl: 1.25rem;
22
+ --spacing-2xl: 2rem;
23
+
24
+ /* Border radius */
25
+ --radius-sm: 6px;
26
+ --radius-md: 8px;
27
+ --radius-lg: 10px;
28
+ --radius-xl: 12px;
29
+
30
+ /* Font weights */
31
+ --font-weight-light: 300;
32
+ --font-weight-medium: 500;
33
+ --font-weight-semibold: 600;
34
+ --font-weight-bold: 700;
35
+ --font-weight-black: 900;
36
+
37
+ /* Font sizes */
38
+ --font-xs: 0.7rem;
39
+ --font-sm: 0.75rem;
40
+ --font-md: 0.8rem;
41
+ --font-lg: 0.85rem;
42
+ --font-xl: 0.9rem;
43
+ --font-2xl: 1.1rem;
44
+ --font-3xl: 1.25rem;
45
+
46
+ /* Heights */
47
+ --height-sm: 28px;
48
+ --height-md: 32px;
49
+ --height-lg: 36px;
50
+ --height-xl: 44px;
51
+
52
+ /* Max widths */
53
+ --max-width-container: 72rem;
54
+ --max-width-drawer: 32rem;
55
+ --max-width-confirm: 260px;
56
+
57
+ /* Z-index */
58
+ --z-drawer: 60;
59
+ --z-tooltip: 9999;
60
+
61
+ /* Transitions */
62
+ --transition-fast: 0.15s ease;
63
+ --transition-normal: 0.18s ease;
64
+ --transition-slow: 0.22s ease;
65
+ --transition-chevron: 200ms ease;
66
+
67
+ /* Shadows */
68
+ --shadow-sm: 0 1px 2px;
69
+ --shadow-md: 0 4px 16px;
70
+ --shadow-drawer: -8px 0 24px;
71
+ --shadow-drawer-rtl: 8px 0 24px;
72
+
73
+ /* Border widths */
74
+ --border-width-sm: 1px;
75
+ --border-width-md: 2px;
76
+
77
+ /* Line heights */
78
+ --line-height-tight: 1.2;
79
+ --line-height-normal: 1.4;
80
+
81
+ /* Letter spacing */
82
+ --letter-spacing-tight: 0.02em;
83
+
84
+ /* Opacity values */
85
+ --opacity-visible: 1;
86
+ --opacity-hidden: 0;
87
+
88
+ /* Percentage values */
89
+ --percent-full: 100%;
90
+ --percent-90: 90vw;
91
+ --percent-50: 50%;
92
+
93
+ /* Specific measurements */
94
+ --arrow-size: 8px;
95
+ --arrow-size-lg: 10px;
96
+ --arrow-negative-half: -4px;
97
+ --arrow-negative-half-lg: -5px;
98
+ --min-height-textarea: 10rem;
99
+ --min-height-cell: 2.25rem;
100
+
101
+ /* Rotation values */
102
+ --rotate-90: 90deg;
103
+ --rotate-neg-90: -90deg;
104
+ --rotate-45: 45deg;
105
+ --rotate-neg-45: -45deg;
106
+ --rotate-135: 135deg;
107
+ --rotate-225: 225deg;
108
+ }
109
+
110
+ :root[data-applied-theme="light"] {
111
+ --color-text: #0f172a;
112
+ --color-sub: #475569;
113
+ --color-ghost: #495567;
114
+ --color-muted: #cbc6c6;
115
+ --color-bg: #f8fafc;
116
+ --color-surface: #ffffff;
117
+ --color-elev-shadow: rgba(15, 23, 42, 0.04);
118
+ --color-white: #ffffff;
119
+ --color-border: #e2e8f0;
120
+ --color-border-light: #f1f5f9;
121
+ --color-border-mid: #cbd5e1;
122
+ --color-dark: #111827;
123
+ --color-primary: #0f172a;
124
+ --color-danger: #dc2626;
125
+ --color-danger-dark: #b91c1c;
126
+ --color-success-bg: #ecfdf5;
127
+ --color-success: #047857;
128
+ --color-success-border: #a7f3d0;
129
+ --color-running-bg: #fffbeb;
130
+ --color-running: #92400e;
131
+ --color-running-border: #fde68a;
132
+ --color-failed-bg: #fef2f2;
133
+ --color-failed: #b91c1c;
134
+ --color-failed-border: #fecaca;
135
+ --color-link: #3b82f6;
136
+ --color-annotation-text: #f8fafc;
137
+ --color-annotation-bg: #0f172a;
138
+ --card-surface: var(--color-surface);
139
+ --table-head-bg: #f1f5f9;
140
+ --table-filter-bg: #f1f5f9;
141
+ --btn-ghost-hover: #eef2f7;
142
+ --btn-secondary-hover: #f1f5f9;
143
+ --overlay-scrim: rgba(15, 23, 42, 0.35);
144
+ --tooltip-bg: #0f172a;
145
+ --tooltip-shadow: rgba(2, 6, 23, 0.2);
146
+ --elev-shadow-lg: rgba(15, 23, 42, 0.1);
147
+
148
+ /* Additional colors for light theme */
149
+ --color-white-pure: #fff;
150
+ --color-success-dark: #065f46;
151
+ --color-status-missing: #dc2626;
152
+ --color-status-ok: #16a34a;
153
+ --color-mv-missing: #92400e;
154
+ --tooltip-arrow-shadow: rgba(2, 6, 23, 0.08);
155
+ --confirm-arrow-shadow: rgba(2, 6, 23, 0.08);
156
+
157
+ color-scheme: light;
158
+ }
159
+
160
+ :root[data-applied-theme="dark"] {
161
+ --color-text: #e5e7eb;
162
+ --color-sub: #94a3b8;
163
+ --color-ghost: #9da8b8;
164
+ --color-muted: #546071;
165
+ --color-bg: #0b1020;
166
+ --color-surface: #0f172a;
167
+ --color-elev-shadow: rgba(0, 0, 0, 0.25);
168
+ --color-white: #0f172a;
169
+ --color-border: #1f2937;
170
+ --color-border-light: #111827;
171
+ --color-border-mid: #334155;
172
+ --color-dark: #f8fafc;
173
+ --color-primary: #e5e7eb;
174
+ --color-danger: #ef4444;
175
+ --color-danger-dark: #dc2626;
176
+ --color-success-bg: #052e25;
177
+ --color-success: #34d399;
178
+ --color-success-border: #065f46;
179
+ --color-running-bg: #3a2a03;
180
+ --color-running: #fbbf24;
181
+ --color-running-border: #854d0e;
182
+ --color-failed-bg: #3a0d0d;
183
+ --color-failed: #fca5a5;
184
+ --color-failed-border: #7f1d1d;
185
+ --color-link: #60a5fa;
186
+ --card-surface: var(--color-surface);
187
+ --table-head-bg: #1e293b;
188
+ --table-filter-bg: #1e293b;
189
+ --btn-ghost-hover: #0f172a;
190
+ --btn-secondary-hover: #111827;
191
+ --overlay-scrim: rgba(3, 7, 18, 0.55);
192
+ --tooltip-bg: #0b1222;
193
+ --tooltip-shadow: rgba(0, 0, 0, 0.35);
194
+ --color-annotation-text: #e5e7eb;
195
+ --color-annotation-bg: #334155;
196
+
197
+ /* Additional colors for dark theme */
198
+ --color-white-pure: #fff;
199
+ --color-success-dark: #065f46;
200
+ --color-status-missing: #dc2626;
201
+ --color-status-ok: #16a34a;
202
+ --color-mv-missing: #92400e;
203
+ --tooltip-arrow-shadow: rgba(0, 0, 0, 0.25);
204
+ --confirm-arrow-shadow: rgba(0, 0, 0, 0.25);
205
+ --color-btn-primary-dark: #0b1020;
206
+
207
+ color-scheme: dark;
208
+ }
209
+
210
+ /* ─────────────────────────────────────────────────────────────────────────────
211
+ BASE
212
+ ─────────────────────────────────────────────────────────────────────────── */
213
+
214
+ html,
215
+ body {
216
+ height: 100%;
217
+ }
218
+ body {
219
+ display: flex;
220
+ flex-direction: column;
221
+ min-height: 100vh;
222
+ font: var(--font-base);
223
+ color: var(--color-text);
224
+ background: var(--color-bg);
225
+ }
226
+ h1,
227
+ h2,
228
+ h3,
229
+ h4,
230
+ h5,
231
+ h6 {
232
+ font-weight: var(--font-weight-black);
233
+ color: var(--color-text);
234
+ font-family: var(--font-head);
235
+ }
236
+ code,
237
+ pre {
238
+ font-family: var(--font-mono);
239
+ font-size: var(--font-md);
240
+ color: var(--color-ghost);
241
+ }
242
+ a {
243
+ color: var(--color-link);
244
+ text-decoration: none;
245
+ }
246
+ a:hover {
247
+ text-decoration: underline;
248
+ }
249
+ pre {
250
+ background: var(--card-surface);
251
+ border: 1px solid var(--color-border);
252
+ border-radius: var(--radius-md);
253
+ box-shadow: var(--shadow-sm) var(--color-elev-shadow);
254
+ padding: var(--spacing-md);
255
+ overflow: auto;
256
+ margin: 0;
257
+ white-space: pre-wrap;
258
+ }
259
+
260
+ /* ─────────────────────────────────────────────────────────────────────────────
261
+ LAYOUT
262
+ ─────────────────────────────────────────────────────────────────────────── */
263
+
264
+ .mv-main {
265
+ flex: 1 1 auto;
266
+ }
267
+ .mv-container {
268
+ background: transparent;
269
+ margin: 0 auto;
270
+ max-width: var(--max-width-container);
271
+ padding: var(--spacing-lg) var(--spacing-xl);
272
+ }
273
+ .mv-header {
274
+ background: var(--card-surface);
275
+ border-bottom: 1px solid var(--color-border);
276
+ color: var(--color-sub);
277
+ font-size: var(--font-xl);
278
+ padding: var(--spacing-lg) 0;
279
+ }
280
+ .mv-header-row {
281
+ display: flex;
282
+ flex-wrap: wrap;
283
+ gap: var(--spacing-md);
284
+ justify-content: space-between;
285
+ }
286
+ .mv-header-row.even {
287
+ justify-content: space-evenly;
288
+ }
289
+ .mv-brand {
290
+ align-items: center;
291
+ color: var(--color-text);
292
+ display: flex;
293
+ font-weight: 600;
294
+ gap: 0.6rem;
295
+ text-decoration: none;
296
+ }
297
+ .mv-logo {
298
+ height: var(--height-sm);
299
+ width: var(--height-sm);
300
+ }
301
+ .mv-footer {
302
+ background: var(--card-surface);
303
+ border-top: 1px solid var(--color-border);
304
+ color: var(--color-sub);
305
+ font-size: var(--font-xl);
306
+ margin-top: auto;
307
+ padding-top: var(--spacing-lg);
308
+ }
309
+ .mv-footer-row {
310
+ display: flex;
311
+ flex-wrap: wrap;
312
+ gap: var(--spacing-md);
313
+ justify-content: space-between;
314
+ }
315
+ .row-item {
316
+ display: flex;
317
+ align-items: center;
318
+ gap: var(--spacing-sm);
319
+ }
320
+
321
+ /* ─────────────────────────────────────────────────────────────────────────────
322
+ CARDS
323
+ ─────────────────────────────────────────────────────────────────────────── */
324
+
325
+ .mv-card {
326
+ background: var(--card-surface);
327
+ border: 1px solid var(--color-border);
328
+ border-radius: var(--radius-xl);
329
+ box-shadow: var(--shadow-sm) var(--color-elev-shadow);
330
+ }
331
+ .mv-card-b {
332
+ padding: var(--spacing-lg);
333
+ }
334
+ .mv-card-h {
335
+ border-bottom: 1px solid var(--color-border);
336
+ font-family: var(--font-head);
337
+ font-weight: 600;
338
+ padding: var(--spacing-md) var(--spacing-lg);
339
+ }
340
+ .mv-card-f {
341
+ border-top: 1px solid var(--color-border);
342
+ padding: var(--spacing-sm) var(--spacing-lg);
343
+ text-align: right;
344
+ font-size: var(--font-lg);
345
+ }
346
+
347
+ /* ─────────────────────────────────────────────────────────────────────────────
348
+ TOOLBAR
349
+ ─────────────────────────────────────────────────────────────────────────── */
350
+ .mv-toolbar {
351
+ display: flex;
352
+ justify-content: flex-end;
353
+ margin: var(--spacing-sm) 0;
354
+ }
355
+ .mv-toolbar.start {
356
+ justify-content: flex-start;
357
+ }
358
+ .mv-toolbar.center {
359
+ justify-content: center;
360
+ flex: 1;
361
+ }
362
+ /* ─────────────────────────────────────────────────────────────────────────────
363
+ BUTTONS
364
+ ─────────────────────────────────────────────────────────────────────────── */
365
+
366
+ .mv-btn {
367
+ align-items: center;
368
+ border: var(--border-width-sm) solid transparent;
369
+ border-radius: var(--radius-md);
370
+ box-sizing: border-box;
371
+ cursor: pointer;
372
+ display: inline-flex;
373
+ font-weight: var(--font-weight-medium);
374
+ gap: var(--spacing-sm);
375
+ padding: 0.4rem 0.7rem;
376
+ text-decoration: none;
377
+ }
378
+ .mv-btn:disabled {
379
+ background: var(--color-border);
380
+ border-color: var(--color-border);
381
+ color: var(--color-muted);
382
+ cursor: not-allowed;
383
+ }
384
+
385
+ .mv-btn:disabled:hover {
386
+ background: var(--color-border);
387
+ border-color: var(--color-border);
388
+ color: var(--color-muted);
389
+ cursor: not-allowed;
390
+ }
391
+
392
+ .mv-btn.has-annotation {
393
+ gap: 0.1rem;
394
+ }
395
+ .mv-btn--ghost {
396
+ background: transparent;
397
+ color: var(--color-ghost);
398
+ }
399
+ .mv-btn--ghost:hover {
400
+ background: var(--btn-ghost-hover);
401
+ }
402
+ .mv-btn--lg {
403
+ font-size: var(--font-xl);
404
+ height: var(--height-xl);
405
+ max-height: var(--height-xl);
406
+ padding: 0.8rem;
407
+ }
408
+ .mv-btn--md {
409
+ font-size: var(--font-md);
410
+ height: var(--height-lg);
411
+ max-height: var(--height-lg);
412
+ padding: 0.55rem;
413
+ }
414
+ .mv-btn--sm {
415
+ font-size: var(--font-xs);
416
+ height: var(--height-md);
417
+ max-height: var(--height-md);
418
+ padding: 0.45rem;
419
+ }
420
+ .mv-btn--no-padding {
421
+ padding: 0;
422
+ }
423
+ .mv-btn--negative {
424
+ background: var(--color-danger);
425
+ color: var(--color-white-pure);
426
+ }
427
+ .mv-btn--negative:hover {
428
+ background: var(--color-danger-dark);
429
+ }
430
+ .mv-btn--primary {
431
+ background: var(--color-primary);
432
+ color: var(--color-white-pure);
433
+ }
434
+
435
+ .mv-btn--primary:hover {
436
+ background: var(--color-dark);
437
+ }
438
+ .mv-btn--secondary {
439
+ background: var(--card-surface);
440
+ border-color: var(--color-border-mid);
441
+ color: var(--color-primary);
442
+ }
443
+ .mv-btn--secondary:hover {
444
+ background: var(--btn-secondary-hover);
445
+ }
446
+ .mv-btn.underline {
447
+ text-decoration: underline;
448
+ }
449
+
450
+ /* ─────────────────────────────────────────────────────────────────────────────
451
+ TABLES
452
+ ─────────────────────────────────────────────────────────────────────────── */
453
+
454
+ .mv-table {
455
+ width: var(--percent-full);
456
+ border: var(--border-width-sm) solid var(--color-border);
457
+ border-radius: var(--radius-lg);
458
+ background: var(--card-surface);
459
+ border-collapse: separate;
460
+ border-spacing: 0;
461
+ overflow: hidden;
462
+ }
463
+ .mv-table.with-filters {
464
+ border-radius: 0, 0, var(--radius-lg), var(--radius-lg);
465
+ }
466
+
467
+ .mv-th {
468
+ background: var(--table-head-bg);
469
+ color: var(--color-sub);
470
+ font-family: var(--font-head);
471
+ font-weight: var(--font-weight-semibold);
472
+ border-bottom: var(--border-width-sm) solid var(--color-border);
473
+ vertical-align: middle;
474
+ text-align: start;
475
+ padding: 0;
476
+ }
477
+ .mv-td {
478
+ border-bottom: var(--border-width-sm) solid var(--color-border-light);
479
+ vertical-align: middle;
480
+ padding: 0;
481
+ }
482
+ .mv-tr:last-child .mv-td {
483
+ border-bottom: none;
484
+ }
485
+ .dt-filter-section {
486
+ background: var(--table-filter-bg);
487
+ display: flex;
488
+ justify-content: space-between;
489
+ padding: var(--spacing-sm);
490
+ }
491
+ .dt-pagination-section {
492
+ background: var(--table-filter-bg);
493
+ display: flex;
494
+ align-items: center;
495
+ justify-content: end;
496
+ gap: var(--spacing-sm);
497
+ padding: var(--spacing-sm);
498
+ }
499
+ .mv-input-group {
500
+ display: flex;
501
+ position: relative;
502
+ align-items: center;
503
+ gap: var(--spacing-sm);
504
+ padding: 0 var(--spacing-sm);
505
+ width: var(--percent-full);
506
+ }
507
+
508
+ .mv-input {
509
+ font-size: var(--font-lg);
510
+ height: var(--height-lg);
511
+ max-height: var(--height-lg);
512
+ }
513
+
514
+ .mv-btn.btn-clear {
515
+ height: var(--height-lg);
516
+ max-height: var(--height-lg);
517
+ position: absolute;
518
+ right: var(--spacing-lg);
519
+ background: transparent;
520
+ border: none;
521
+ }
522
+
523
+ .mv-input.mv-input--full-width {
524
+ width: var(--percent-full);
525
+ }
526
+
527
+ .mv-cell {
528
+ display: flex;
529
+ align-items: center;
530
+ justify-content: flex-start;
531
+ gap: 0.4rem;
532
+ padding: var(--spacing-sm) var(--spacing-md);
533
+ min-height: var(--min-height-cell);
534
+ }
535
+ .mv-td-actions .mv-cell {
536
+ justify-content: flex-end;
537
+ text-align: end;
538
+ }
539
+
540
+ /* ─────────────────────────────────────────────────────────────────────────────
541
+ BADGES
542
+ ─────────────────────────────────────────────────────────────────────────── */
543
+
544
+ .mv-chip {
545
+ border: var(--border-width-sm) solid transparent;
546
+ border-radius: var(--radius-sm);
547
+ display: inline-block;
548
+ font-size: var(--font-sm);
549
+ font-weight: var(--font-weight-semibold);
550
+ padding: 0.15rem 0.4rem;
551
+ }
552
+ .mv-chip--failed {
553
+ background: var(--color-failed-bg);
554
+ border-color: var(--color-failed-border);
555
+ color: var(--color-failed);
556
+ }
557
+ .mv-chip--running {
558
+ background: var(--color-running-bg);
559
+ border-color: var(--color-running-border);
560
+ color: var(--color-running);
561
+ }
562
+ .mv-chip--success {
563
+ background: var(--color-success-bg);
564
+ border-color: var(--color-success-border);
565
+ color: var(--color-success);
566
+ }
567
+
568
+ /* ─────────────────────────────────────────────────────────────────────────────
569
+ Details/Summary
570
+ ─────────────────────────────────────────────────────────────────────────── */
571
+ details summary {
572
+ cursor: pointer;
573
+ }
574
+ details summary:focus {
575
+ outline: none;
576
+ }
577
+ .mv-details summary::-webkit-details-marker {
578
+ display: none;
579
+ }
580
+ .mv-details summary {
581
+ display: inline-flex;
582
+ align-items: center;
583
+ gap: var(--spacing-sm);
584
+ cursor: pointer;
585
+ }
586
+ .mv-chevron {
587
+ flex: 0 0 auto;
588
+ transition: transform var(--transition-chevron);
589
+ transform-origin: 50% 50%;
590
+ }
591
+ .mv-details[open] .mv-chevron {
592
+ transform: rotate(var(--rotate-90));
593
+ }
594
+ .mv-details__content {
595
+ overflow: hidden;
596
+ will-change: height;
597
+ margin: 0;
598
+ }
599
+ [dir="rtl"] .mv-details[open] .mv-chevron {
600
+ transform: rotate(var(--rotate-neg-90));
601
+ }
602
+
603
+ /* ─────────────────────────────────────────────────────────────────────────────
604
+ TABS
605
+ ─────────────────────────────────────────────────────────────────────────── */
606
+
607
+ .mv-tabs {
608
+ border-bottom: var(--border-width-sm) solid var(--color-border);
609
+ display: flex;
610
+ gap: var(--spacing-lg);
611
+ margin: var(--spacing-lg) 0;
612
+ }
613
+ .mv-tab {
614
+ border-bottom: var(--border-width-md) solid transparent;
615
+ color: var(--color-ghost);
616
+ font-family: var(--font-head);
617
+ padding: var(--spacing-sm) var(--spacing-sm);
618
+ text-decoration: none;
619
+ }
620
+ .mv-tab--on {
621
+ border-color: var(--color-primary);
622
+ }
623
+ .mv-tab:hover {
624
+ border-color: var(--color-border-mid);
625
+ }
626
+
627
+ /* ─────────────────────────────────────────────────────────────────────────────
628
+ FORMS
629
+ ─────────────────────────────────────────────────────────────────────────── */
630
+
631
+ .mv-form {
632
+ display: block;
633
+ padding: 0 var(--spacing-lg);
634
+ max-width: 100%;
635
+ }
636
+ .mv-form--no-pad {
637
+ padding: 0;
638
+ }
639
+ .mv-field {
640
+ display: flex;
641
+ flex-direction: column;
642
+ gap: var(--spacing-xs);
643
+ margin: var(--spacing-md) 0;
644
+ }
645
+ .mv-field-inline-row {
646
+ display: inline-flex;
647
+ flex-direction: row;
648
+ align-items: center;
649
+ gap: var(--spacing-md);
650
+ margin: var(--spacing-lg) 0;
651
+ }
652
+ .mv-field-inline {
653
+ display: inline-flex;
654
+ flex-direction: row;
655
+ align-items: center;
656
+ gap: var(--spacing-sm);
657
+ }
658
+ .mv-input,
659
+ .mv-textarea,
660
+ .mv-select {
661
+ background: var(--card-surface);
662
+ border: var(--border-width-sm) solid var(--color-border-mid);
663
+ border-radius: var(--radius-md);
664
+ padding: 0.45rem 0.6rem;
665
+ color: var(--color-text);
666
+ }
667
+ .mv-label {
668
+ color: var(--color-ghost);
669
+ font-size: var(--font-xl);
670
+ font-weight: var(--font-weight-semibold);
671
+ }
672
+ .mv-label--sublabel {
673
+ font-weight: var(--font-weight-light);
674
+ margin: 0;
675
+ font-size: var(--font-lg);
676
+ }
677
+ .mv-textarea {
678
+ min-height: var(--min-height-textarea);
679
+ resize: vertical;
680
+ }
681
+ .mv-hint {
682
+ color: var(--color-sub);
683
+ font-size: var(--font-sm);
684
+ }
685
+
686
+ /* ─────────────────────────────────────────────────────────────────────────────
687
+ FLASH
688
+ ─────────────────────────────────────────────────────────────────────────── */
689
+
690
+ .mv-flash {
691
+ border-radius: var(--radius-lg);
692
+ font-size: var(--font-xl);
693
+ margin: var(--spacing-sm) 0;
694
+ padding: var(--spacing-sm) var(--spacing-md);
695
+ }
696
+ .mv-flash--err {
697
+ background: var(--color-failed-bg);
698
+ border: var(--border-width-sm) solid var(--color-failed-border);
699
+ color: var(--color-failed);
700
+ }
701
+ .mv-flash--ok {
702
+ background: var(--color-success-bg);
703
+ border: var(--border-width-sm) solid var(--color-success-border);
704
+ color: var(--color-success-dark);
705
+ }
706
+
707
+ /* ─────────────────────────────────────────────────────────────────────────────
708
+ UTILS
709
+ ─────────────────────────────────────────────────────────────────────────── */
710
+
711
+ .mv-text-right {
712
+ text-align: end;
713
+ }
714
+ .mv-text-muted {
715
+ color: var(--color-muted);
716
+ }
717
+
718
+ .mv-td-actions {
719
+ text-align: end;
720
+ }
721
+ .mv-actions {
722
+ display: inline-flex;
723
+ flex-wrap: wrap;
724
+ gap: var(--spacing-md);
725
+ justify-content: flex-end;
726
+ }
727
+ .mv-action-group {
728
+ background: var(--card-surface);
729
+ border: var(--border-width-sm) solid var(--color-border);
730
+ border-radius: var(--radius-xl);
731
+ box-shadow: var(--shadow-sm) var(--color-elev-shadow);
732
+ display: inline-flex;
733
+ flex-direction: column;
734
+ padding: 10px var(--spacing-md);
735
+ }
736
+ .mv-action-title {
737
+ align-items: center;
738
+ color: var(--color-sub);
739
+ display: flex;
740
+ font-size: 0.72rem;
741
+ font-weight: var(--font-weight-semibold);
742
+ gap: var(--spacing-sm);
743
+ letter-spacing: var(--letter-spacing-tight);
744
+ margin-bottom: var(--spacing-sm);
745
+ text-transform: uppercase;
746
+ }
747
+ .mv-buttons {
748
+ align-items: center;
749
+ display: inline-flex;
750
+ flex-direction: column;
751
+ gap: var(--spacing-sm);
752
+ align-items: stretch;
753
+ }
754
+ .mv-buttons .mv-btn {
755
+ width: var(--percent-full);
756
+ justify-content: center;
757
+ }
758
+ .mv-icon {
759
+ margin-inline-end: 0.05rem;
760
+ margin-inline-start: 0.05rem;
761
+ }
762
+ .mv-icon.active {
763
+ color: var(--color-text);
764
+ }
765
+ .mv-icon.muted {
766
+ color: var(--color-muted);
767
+ }
768
+ .mv-icon.hidden {
769
+ display: none;
770
+ }
771
+ .mv-mv-missing {
772
+ align-items: center;
773
+ color: var(--color-mv-missing);
774
+ display: inline-flex;
775
+ font-size: 0.88rem;
776
+ gap: var(--spacing-sm);
777
+ }
778
+ .mv-status-icon {
779
+ align-items: center;
780
+ display: inline-flex;
781
+ }
782
+ .mv-status-missing {
783
+ color: var(--color-status-missing);
784
+ }
785
+ .mv-status-ok {
786
+ color: var(--color-status-ok);
787
+ }
788
+ .mv-annotation {
789
+ display: inline;
790
+ white-space: nowrap;
791
+ font-size: var(--font-2xl);
792
+ background-color: var(--color-annotation-bg);
793
+ color: var(--color-annotation-text);
794
+ border-radius: var(--radius-xl);
795
+ }
796
+ .mv-annotation.hidden {
797
+ display: none;
798
+ }
799
+
800
+ /* ─────────────────────────────────────────────────────────────────────────────
801
+ DRAWER
802
+ ─────────────────────────────────────────────────────────────────────────── */
803
+
804
+ .mv-drawer-root {
805
+ inset: 0;
806
+ pointer-events: none;
807
+ position: fixed;
808
+ z-index: var(--z-drawer);
809
+ }
810
+ .mv-drawer-root.is-open {
811
+ pointer-events: auto;
812
+ }
813
+ .mv-drawer-overlay {
814
+ background: var(--overlay-scrim);
815
+ inset: 0;
816
+ opacity: 0;
817
+ position: absolute;
818
+ transition: opacity var(--transition-normal);
819
+ }
820
+ .mv-drawer-root.is-open .mv-drawer-overlay {
821
+ opacity: 1;
822
+ }
823
+ .mv-drawer {
824
+ background: var(--card-surface);
825
+ border-left: var(--border-width-sm) solid var(--color-border);
826
+ box-shadow: var(--shadow-drawer) var(--elev-shadow-lg);
827
+ display: flex;
828
+ flex-direction: column;
829
+ height: var(--percent-full);
830
+ max-width: var(--percent-90);
831
+ position: absolute;
832
+ right: 0;
833
+ top: 0;
834
+ transform: translateX(100%);
835
+ transition: transform var(--transition-slow);
836
+ width: var(--max-width-drawer);
837
+ }
838
+ .mv-drawer-root.is-open .mv-drawer {
839
+ transform: translateX(0);
840
+ }
841
+ .mv-drawer-body {
842
+ height: var(--percent-full);
843
+ overflow: auto;
844
+ padding: 0;
845
+ }
846
+ .mv-drawer-body .mv-card {
847
+ border-left: 0;
848
+ border-radius: 0;
849
+ border-right: 0;
850
+ }
851
+ .mv-drawer-action {
852
+ background: transparent;
853
+ border: 0;
854
+ color: var(--color-ghost);
855
+ cursor: pointer;
856
+ font-size: var(--font-3xl);
857
+ }
858
+ .mv-drawer-head {
859
+ align-items: center;
860
+ border-bottom: var(--border-width-sm) solid var(--color-border);
861
+ display: flex;
862
+ justify-content: space-between;
863
+ padding: var(--spacing-md) var(--spacing-lg);
864
+ font-family: var(--font-head);
865
+ }
866
+ .mv-drawer-head h2 {
867
+ margin: 0;
868
+ }
869
+
870
+ /* ─────────────────────────────────────────────────────────────────────────────
871
+ TOOLTIP + CONFIRM
872
+ ─────────────────────────────────────────────────────────────────────────── */
873
+
874
+ .mv-tooltip {
875
+ background: var(--tooltip-bg);
876
+ border-radius: var(--radius-sm);
877
+ box-shadow: var(--shadow-md) var(--tooltip-shadow);
878
+ color: var(--color-white-pure);
879
+ font-size: 12px;
880
+ line-height: var(--line-height-tight);
881
+ opacity: var(--opacity-hidden);
882
+ padding: var(--spacing-sm) 8px;
883
+ transition: opacity var(--transition-fast);
884
+ z-index: var(--z-tooltip);
885
+ }
886
+ .mv-tooltip[data-show="true"] {
887
+ opacity: var(--opacity-visible);
888
+ }
889
+ .mv-tooltip__arrow {
890
+ background: var(--tooltip-bg);
891
+ box-shadow: -1px -1px 1px var(--tooltip-arrow-shadow);
892
+ height: var(--arrow-size);
893
+ position: absolute;
894
+ transform: rotate(var(--rotate-45));
895
+ width: var(--arrow-size);
896
+ }
897
+ .mv-tooltip__content {
898
+ display: block;
899
+ white-space: nowrap;
900
+ }
901
+ .mv-tooltip--bottom .mv-tooltip__arrow {
902
+ left: var(--percent-50);
903
+ margin-left: var(--arrow-negative-half);
904
+ top: var(--arrow-negative-half);
905
+ }
906
+ .mv-tooltip--left .mv-tooltip__arrow {
907
+ right: var(--arrow-negative-half);
908
+ top: var(--percent-50);
909
+ margin-top: var(--arrow-negative-half);
910
+ }
911
+ .mv-tooltip--right .mv-tooltip__arrow {
912
+ left: var(--arrow-negative-half);
913
+ top: var(--percent-50);
914
+ margin-top: var(--arrow-negative-half);
915
+ }
916
+ .mv-tooltip--top .mv-tooltip__arrow {
917
+ bottom: var(--arrow-negative-half);
918
+ left: var(--percent-50);
919
+ margin-left: var(--arrow-negative-half);
920
+ }
921
+
922
+ .mv-confirm {
923
+ background: var(--card-surface);
924
+ border: var(--border-width-sm) solid var(--color-border);
925
+ border-radius: var(--radius-md);
926
+ box-shadow: var(--shadow-md) var(--tooltip-shadow);
927
+ font-size: var(--font-lg);
928
+ max-width: var(--max-width-confirm);
929
+ opacity: var(--opacity-hidden);
930
+ padding: var(--spacing-md);
931
+ transition: opacity var(--transition-fast);
932
+ z-index: var(--z-tooltip);
933
+ }
934
+ .mv-confirm[data-show="true"] {
935
+ opacity: var(--opacity-visible);
936
+ }
937
+ .mv-confirm__content {
938
+ margin-bottom: var(--spacing-sm);
939
+ color: var(--color-text);
940
+ }
941
+ .mv-confirm__buttons {
942
+ display: flex;
943
+ gap: var(--spacing-sm);
944
+ justify-content: flex-end;
945
+ }
946
+ .mv-confirm__arrow {
947
+ background: var(--card-surface);
948
+ border-left: var(--border-width-sm) solid var(--color-border);
949
+ border-top: var(--border-width-sm) solid var(--color-border);
950
+ box-shadow: -1px -1px 1px var(--confirm-arrow-shadow);
951
+ width: var(--arrow-size-lg);
952
+ height: var(--arrow-size-lg);
953
+ position: absolute;
954
+ transform: rotate(var(--rotate-45));
955
+ }
956
+ .mv-confirm--bottom .mv-confirm__arrow {
957
+ top: var(--arrow-negative-half-lg);
958
+ left: var(--percent-50);
959
+ margin-left: var(--arrow-negative-half-lg);
960
+ }
961
+ .mv-confirm--top .mv-confirm__arrow {
962
+ bottom: var(--arrow-negative-half-lg);
963
+ left: var(--percent-50);
964
+ margin-left: var(--arrow-negative-half-lg);
965
+ transform: rotate(var(--rotate-225));
966
+ }
967
+ .mv-confirm--left .mv-confirm__arrow {
968
+ right: var(--arrow-negative-half-lg);
969
+ top: var(--percent-50);
970
+ margin-top: var(--arrow-negative-half-lg);
971
+ transform: rotate(var(--rotate-135));
972
+ }
973
+ .mv-confirm--right .mv-confirm__arrow {
974
+ left: var(--arrow-negative-half-lg);
975
+ top: var(--percent-50);
976
+ margin-top: var(--arrow-negative-half-lg);
977
+ transform: rotate(var(--rotate-neg-45));
978
+ }
979
+
980
+ /* ─────────────────────────────────────────────────────────────────────────────
981
+ RTL SUPPORT (no class changes; flip where needed)
982
+ ─────────────────────────────────────────────────────────────────────────── */
983
+
984
+ [dir="rtl"] .mv-brand {
985
+ flex-direction: row-reverse;
986
+ }
987
+ [dir="rtl"] .mv-status-icon {
988
+ margin-inline-start: 0;
989
+ margin-inline-end: var(--spacing-sm);
990
+ }
991
+ [dir="rtl"] .mv-mv-missing {
992
+ margin-inline-end: 0;
993
+ margin-inline-start: var(--spacing-sm);
994
+ }
995
+ [dir="rtl"] .mv-th {
996
+ text-align: end;
997
+ }
998
+ [dir="rtl"] .mv-td-actions .mv-cell {
999
+ justify-content: flex-start;
1000
+ }
1001
+
1002
+ /* Drawer opens from the *left* in RTL */
1003
+ [dir="rtl"] .mv-drawer {
1004
+ left: 0;
1005
+ right: auto;
1006
+ border-left: 0;
1007
+ border-right: var(--border-width-sm) solid var(--color-border);
1008
+ box-shadow: var(--shadow-drawer-rtl) var(--elev-shadow-lg);
1009
+ transform: translateX(-100%);
1010
+ }
1011
+ [dir="rtl"] .mv-drawer-root.is-open .mv-drawer {
1012
+ transform: translateX(0);
1013
+ }
1014
+
1015
+ /* Tooltip/Confirm arrow horizontal flip in RTL */
1016
+ [dir="rtl"] .mv-tooltip--left .mv-tooltip__arrow {
1017
+ left: var(--arrow-negative-half);
1018
+ right: auto;
1019
+ }
1020
+ [dir="rtl"] .mv-tooltip--right .mv-tooltip__arrow {
1021
+ right: var(--arrow-negative-half);
1022
+ left: auto;
1023
+ }
1024
+ [dir="rtl"] .mv-confirm--left .mv-confirm__arrow {
1025
+ left: var(--arrow-negative-half-lg);
1026
+ right: auto;
1027
+ transform: rotate(var(--rotate-neg-45));
1028
+ }
1029
+ [dir="rtl"] .mv-confirm--right .mv-confirm__arrow {
1030
+ right: var(--arrow-negative-half-lg);
1031
+ left: auto;
1032
+ transform: rotate(var(--rotate-135));
1033
+ }
1034
+
1035
+ /* ____________________________________________________________
1036
+ Overrides
1037
+ ____________________________________________________________________________ */
1038
+ [data-applied-theme="dark"] .mv-btn--primary {
1039
+ color: var(--color-btn-primary-dark);
1040
+ }