snap-ally 0.2.7-beta → 1.0.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 (76) hide show
  1. package/README.md +19 -12
  2. package/dist/A11yReportAssets.d.ts +5 -12
  3. package/dist/A11yReportAssets.js +16 -82
  4. package/dist/A11yScanner.d.ts +2 -21
  5. package/dist/A11yScanner.js +16 -22
  6. package/dist/A11yTimeUtils.js +11 -23
  7. package/dist/A11yVisualReporter.d.ts +50 -0
  8. package/dist/A11yVisualReporter.js +188 -0
  9. package/dist/AccessibilityReporterOptions.d.ts +24 -0
  10. package/dist/AccessibilityReporterOptions.js +5 -0
  11. package/dist/ResolvedColors.d.ts +15 -0
  12. package/dist/ResolvedColors.js +20 -0
  13. package/dist/SnapAllyReporter.d.ts +12 -72
  14. package/dist/SnapAllyReporter.js +212 -330
  15. package/dist/core/A11yHtmlRenderer.d.ts +17 -0
  16. package/dist/core/A11yHtmlRenderer.js +118 -0
  17. package/dist/core/A11yReportAssets.d.ts +30 -0
  18. package/dist/core/A11yReportAssets.js +127 -0
  19. package/dist/core/A11yScanner.d.ts +8 -0
  20. package/dist/core/A11yScanner.js +178 -0
  21. package/dist/core/A11yVisualReporter.d.ts +50 -0
  22. package/dist/core/A11yVisualReporter.js +188 -0
  23. package/dist/core/HtmlRenderer.d.ts +14 -0
  24. package/dist/core/HtmlRenderer.js +106 -0
  25. package/dist/core/ReportAssets.d.ts +29 -0
  26. package/dist/core/ReportAssets.js +126 -0
  27. package/dist/core/Scanner.d.ts +7 -0
  28. package/dist/core/Scanner.js +164 -0
  29. package/dist/core/VisualReporter.d.ts +54 -0
  30. package/dist/core/VisualReporter.js +192 -0
  31. package/dist/index.d.ts +6 -6
  32. package/dist/index.js +13 -12
  33. package/dist/models/A11yDataSource.d.ts +15 -0
  34. package/dist/models/A11yDataSource.js +2 -0
  35. package/dist/models/A11yError.d.ts +34 -0
  36. package/dist/models/A11yError.js +11 -0
  37. package/dist/models/A11yScannerOptions.d.ts +24 -0
  38. package/dist/models/A11yScannerOptions.js +2 -0
  39. package/dist/models/AccessibilityReporterOptions.d.ts +24 -0
  40. package/dist/models/AccessibilityReporterOptions.js +5 -0
  41. package/dist/models/DataSource.d.ts +15 -0
  42. package/dist/models/DataSource.js +2 -0
  43. package/dist/models/ImagePath.d.ts +5 -0
  44. package/dist/models/ImagePath.js +3 -0
  45. package/dist/models/ReportData.d.ts +24 -0
  46. package/dist/models/ReportData.js +2 -0
  47. package/dist/models/ReporterOptions.d.ts +34 -0
  48. package/dist/models/ReporterOptions.js +5 -0
  49. package/dist/models/ResolvedColors.d.ts +16 -0
  50. package/dist/models/ResolvedColors.js +24 -0
  51. package/dist/models/ScannerOptions.d.ts +30 -0
  52. package/dist/models/ScannerOptions.js +2 -0
  53. package/dist/models/Severity.d.ts +7 -0
  54. package/dist/models/Severity.js +11 -0
  55. package/dist/models/Target.d.ts +10 -0
  56. package/dist/models/Target.js +3 -0
  57. package/dist/models/TestResults.d.ts +41 -0
  58. package/dist/models/TestResults.js +2 -0
  59. package/dist/models/TestStatusIcon.d.ts +8 -0
  60. package/dist/models/TestStatusIcon.js +12 -0
  61. package/dist/models/TestSummary.d.ts +34 -0
  62. package/dist/models/TestSummary.js +2 -0
  63. package/dist/models/Violation.d.ts +13 -0
  64. package/dist/models/Violation.js +2 -0
  65. package/dist/models/index.d.ts +12 -113
  66. package/dist/models/index.js +26 -16
  67. package/dist/templates/accessibility-report.html +62 -95
  68. package/dist/templates/execution-summary.html +37 -103
  69. package/dist/templates/global-report-styles.css +400 -9
  70. package/dist/templates/report-app.js +174 -74
  71. package/dist/templates/test-execution-report.html +84 -121
  72. package/dist/utils/A11yTimeUtils.d.ts +13 -0
  73. package/dist/utils/A11yTimeUtils.js +40 -0
  74. package/dist/utils/TimeUtils.d.ts +13 -0
  75. package/dist/utils/TimeUtils.js +39 -0
  76. package/package.json +1 -1
@@ -23,37 +23,27 @@
23
23
  </head>
24
24
 
25
25
  <body>
26
- <header>
27
- <a href="#" class="brand" style="cursor: default">
28
- <div class="brand-icon">
29
- <span class="material-symbols-outlined" style="font-size: 22px"
26
+ <a href="#report-summary-root" class="skip-link">Skip to main content</a>
27
+ <header role="banner">
28
+ <div class="brand">
29
+ <div class="brand-icon" aria-hidden="true">
30
+ <span class="material-symbols-outlined fs-6"
30
31
  >fact_check</span
31
32
  >
32
33
  </div>
33
34
  <h1>Snap Ally Test Summary</h1>
34
- </a>
35
+ </div>
35
36
  </header>
36
37
 
37
- <div class="container" id="report-summary-root" style="display: none">
38
+ <main class="container hidden" id="report-summary-root">
38
39
  <!-- Hero Section -->
39
40
  <div class="summary-hero">
40
- <div style="display: flex; align-items: center; gap: 16px; margin-bottom: 8px">
41
- <h2
42
- style="
43
- margin: 0;
44
- font-weight: 600;
45
- font-size: 1.4rem;
46
- color: var(--text-main);
47
- "
48
- >
41
+ <div class="d-flex-align-center gap-16 mb-2">
42
+ <h2 class="m-0 fw-semibold fs-4 text-main">
49
43
  Test Execution Summary
50
44
  </h2>
51
45
  <div class="status-badge" id="summary-status-badge">
52
- <span
53
- class="material-symbols-outlined"
54
- id="summary-status-icon"
55
- style="font-size: 16px"
56
- ></span>
46
+ <span class="material-symbols-outlined fs-6" id="summary-status-icon"></span>
57
47
  <span id="summary-status-text"></span>
58
48
  </div>
59
49
  </div>
@@ -79,12 +69,10 @@
79
69
  <!-- Global Tab Content -->
80
70
  <div id="tab-global" class="tab-content active">
81
71
  <!-- Global Success -->
82
- <div class="success-verified-card" id="global-success-card" style="display: none">
72
+ <div class="success-verified-card hidden" id="global-success-card">
83
73
  <div class="success-content-layout">
84
74
  <div class="success-icon-container">
85
- <span class="material-symbols-outlined" id="global-success-icon"
86
- >check_circle</span
87
- >
75
+ <span class="material-symbols-outlined" id="global-success-icon">check_circle</span>
88
76
  <div class="icon-pulse"></div>
89
77
  </div>
90
78
  <div class="success-text-group">
@@ -96,40 +84,26 @@
96
84
  your audited application.
97
85
  </p>
98
86
  <div class="success-badges">
99
- <span class="success-msg-badge"
100
- ><span class="material-symbols-outlined">verified</span> 0
101
- Violations Found</span
102
- >
103
- <span class="success-msg-badge"
104
- ><span class="material-symbols-outlined"
105
- >health_and_safety</span
106
- >
107
- 100% Compliant</span
108
- >
87
+ <span class="success-msg-badge"><span class="material-symbols-outlined">verified</span> 0
88
+ Violations Found</span>
89
+ <span class="success-msg-badge"><span class="material-symbols-outlined">health_and_safety</span>
90
+ 100% Compliant</span>
109
91
  </div>
110
92
  </div>
111
93
  </div>
112
94
  </div>
113
95
 
114
96
  <!-- Global Errors -->
115
- <div id="global-errors-container" style="display: none">
97
+ <div id="global-errors-container" class="hidden">
116
98
  <div class="metrics-grid" id="global-metrics-grid"></div>
117
99
  <div class="chart-box">
118
100
  <div class="chart-title">
119
101
  Global Violation Distribution
120
102
  <div class="chart-legend">
121
- <span class="legend-item"
122
- ><span class="legend-dot critical"></span> Critical</span
123
- >
124
- <span class="legend-item"
125
- ><span class="legend-dot serious"></span> Serious</span
126
- >
127
- <span class="legend-item"
128
- ><span class="legend-dot moderate"></span> Moderate</span
129
- >
130
- <span class="legend-item"
131
- ><span class="legend-dot minor"></span> Minor</span
132
- >
103
+ <span class="legend-item"><span class="legend-dot critical"></span> Critical</span>
104
+ <span class="legend-item"><span class="legend-dot serious"></span> Serious</span>
105
+ <span class="legend-item"><span class="legend-dot moderate"></span> Moderate</span>
106
+ <span class="legend-item"><span class="legend-dot minor"></span> Minor</span>
133
107
  </div>
134
108
  </div>
135
109
  <div id="chart-global-violations"></div>
@@ -143,24 +117,16 @@
143
117
  <template id="browser-tab-content-template">
144
118
  <div class="tab-content">
145
119
  <!-- Error State -->
146
- <div class="browser-errors-container" style="display: none">
120
+ <div class="browser-errors-container hidden">
147
121
  <div class="metrics-grid browser-metrics-grid"></div>
148
122
  <div class="chart-box">
149
123
  <div class="chart-title">
150
124
  <span class="browser-chart-title"></span> Violations by Rule
151
125
  <div class="chart-legend">
152
- <span class="legend-item"
153
- ><span class="legend-dot critical"></span> Critical</span
154
- >
155
- <span class="legend-item"
156
- ><span class="legend-dot serious"></span> Serious</span
157
- >
158
- <span class="legend-item"
159
- ><span class="legend-dot moderate"></span> Moderate</span
160
- >
161
- <span class="legend-item"
162
- ><span class="legend-dot minor"></span> Minor</span
163
- >
126
+ <span class="legend-item"><span class="legend-dot critical"></span> Critical</span>
127
+ <span class="legend-item"><span class="legend-dot serious"></span> Serious</span>
128
+ <span class="legend-item"><span class="legend-dot moderate"></span> Moderate</span>
129
+ <span class="legend-item"><span class="legend-dot minor"></span> Minor</span>
164
130
  </div>
165
131
  </div>
166
132
  <div class="browser-chart-container"></div>
@@ -168,15 +134,10 @@
168
134
  </div>
169
135
 
170
136
  <!-- Success State -->
171
- <div
172
- class="success-verified-card browser-success-container"
173
- style="display: none"
174
- >
137
+ <div class="success-verified-card browser-success-container hidden">
175
138
  <div class="success-content-layout">
176
139
  <div class="success-icon-container">
177
- <span class="material-symbols-outlined success-hero-icon"
178
- >verified_user</span
179
- >
140
+ <span class="material-symbols-outlined success-hero-icon">verified_user</span>
180
141
  <div class="icon-pulse"></div>
181
142
  </div>
182
143
  <div class="success-text-group">
@@ -200,14 +161,12 @@
200
161
  <span class="metric-rule"></span>
201
162
  <span class="metric-sev"></span>
202
163
  </div>
203
- <div class="metric-desc" style="display: none"></div>
164
+ <div class="metric-desc hidden"></div>
204
165
  </div>
205
166
  <div class="metric-footer">
206
167
  <div class="metric-count"></div>
207
- <a target="_blank" class="btn-guide" style="display: none">
208
- <span class="material-symbols-outlined" style="font-size: 16px"
209
- >menu_book</span
210
- >
168
+ <a target="_blank" class="btn-guide hidden">
169
+ <span class="material-symbols-outlined fs-16">menu_book</span>
211
170
  Guide
212
171
  </a>
213
172
  </div>
@@ -215,15 +174,8 @@
215
174
  </template>
216
175
 
217
176
  <!-- Test Suite Details Accordion -->
218
- <div class="results-list" style="margin-top: 40px">
219
- <h2
220
- style="
221
- font-family: 'Outfit', sans-serif;
222
- font-size: 1.25rem;
223
- margin-bottom: 24px;
224
- color: var(--text-main);
225
- "
226
- >
177
+ <div class="results-list mt-5">
178
+ <h2 class="section-heading-lg mb-4 text-main">
227
179
  Test Suite Details
228
180
  </h2>
229
181
  <div id="accordion-container"></div>
@@ -248,36 +200,18 @@
248
200
  <span class="browser-chip"></span>
249
201
  </div>
250
202
  <div class="test-meta">
251
- <span
252
- class="err-badge"
253
- style="
254
- display: none;
255
- background: #fee2e2;
256
- color: #ef4444;
257
- font-size: 0.7rem;
258
- font-weight: 800;
259
- padding: 2px 8px;
260
- border-radius: 6px;
261
- "
262
- ></span>
263
- <div
264
- class="test-dur"
265
- style="
266
- font-size: 0.8rem;
267
- color: var(--text-muted);
268
- font-weight: 700;
269
- "
270
- ></div>
203
+ <span class="err-badge hidden"></span>
204
+ <div class="test-dur text-muted-sm fw-bold"></div>
271
205
  </div>
272
206
  </div>
273
207
  </a>
274
208
  </template>
275
- </div>
209
+ </main>
276
210
 
277
211
  <footer>
278
212
  <div class="powered-by">Generated by <span class="badge-tool">Snap Ally</span></div>
279
213
  <div>
280
- <span style="opacity: 0.7">&copy; <span id="year"></span> Snap Ally</span>
214
+ <span class="opacity-75">&copy; <span id="year"></span> Snap Ally</span>
281
215
  </div>
282
216
  </footer>
283
217
 
@@ -13,17 +13,153 @@
13
13
  --skipped: #6366f1;
14
14
 
15
15
  /* Default Severity Colors - These can be overridden via JS dynamically */
16
- --critical: #ff00ff;
17
- --serious: #e67700;
18
- --moderate: #ca8a04;
19
- --minor: #0891b2;
16
+ --critical: #dc2626;
17
+ --serious: #ea580c;
18
+ --moderate: #f59e0b;
19
+ --minor: #f0f06f;
20
20
 
21
21
  --glass-bg: rgba(255, 255, 255, 0.85);
22
22
  --glass-border: rgba(255, 255, 255, 0.6);
23
23
  --glass-shadow: 0 12px 40px rgba(0, 0, 0, 0.08);
24
24
  --card-radius: 24px;
25
+ --focus-ring: 0 0 0 3px rgba(99, 102, 241, 0.4);
25
26
  }
26
27
 
28
+ /* Accessibility Helpers */
29
+ .skip-link {
30
+ position: absolute;
31
+ top: -100px;
32
+ left: 40px;
33
+ background: var(--primary);
34
+ color: white;
35
+ padding: 8px 16px;
36
+ z-index: 2000;
37
+ border-radius: 0 0 8px 8px;
38
+ text-decoration: none;
39
+ font-weight: 700;
40
+ transition: top 0.2s;
41
+ }
42
+
43
+ .skip-link:focus {
44
+ top: 0;
45
+ outline: none;
46
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
47
+ }
48
+
49
+ /* Enhanced Focus */
50
+ a:focus-visible,
51
+ button:focus-visible,
52
+ input:focus-visible,
53
+ select:focus-visible {
54
+ outline: 2px solid var(--primary);
55
+ outline-offset: 3px;
56
+ }
57
+
58
+ /* Global Helper Classes */
59
+ .d-flex-between {
60
+ display: flex;
61
+ justify-content: space-between;
62
+ align-items: center;
63
+ }
64
+
65
+ .d-flex-align-center {
66
+ display: flex;
67
+ align-items: center;
68
+ }
69
+
70
+ .gap-8 {
71
+ gap: 8px;
72
+ }
73
+
74
+ .gap-12 {
75
+ gap: 12px;
76
+ }
77
+
78
+ .gap-16 {
79
+ gap: 16px;
80
+ }
81
+
82
+ .gap-24 {
83
+ gap: 24px;
84
+ }
85
+
86
+ .mt-16 {
87
+ margin-top: 16px;
88
+ }
89
+
90
+ .mb-4 {
91
+ margin-bottom: 4px;
92
+ }
93
+
94
+ .mb-12 {
95
+ margin-bottom: 12px;
96
+ }
97
+
98
+ .hidden {
99
+ display: none !important;
100
+ }
101
+
102
+ .max-w-75 {
103
+ max-width: 75%;
104
+ }
105
+
106
+ .text-muted-sm {
107
+ color: var(--text-muted);
108
+ font-size: 0.9rem;
109
+ }
110
+
111
+ .text-main-lg {
112
+ color: var(--text-main);
113
+ font-size: 1.1rem;
114
+ }
115
+
116
+ .cursor-default {
117
+ cursor: default;
118
+ }
119
+
120
+ .no-underline {
121
+ text-decoration: none;
122
+ }
123
+
124
+ .break-all {
125
+ word-break: break-all;
126
+ }
127
+
128
+ .section-heading-lg {
129
+ font-family: 'Outfit', sans-serif;
130
+ font-size: 1.25rem;
131
+ font-weight: 700;
132
+ }
133
+
134
+ .err-badge {
135
+ background: #fee2e2;
136
+ color: #ef4444;
137
+ font-size: 0.7rem;
138
+ font-weight: 800;
139
+ padding: 2px 8px;
140
+ border-radius: 6px;
141
+ white-space: nowrap;
142
+ border: 1px solid #fecdd3;
143
+ }
144
+
145
+ /* Sizing Helpers */
146
+ .fs-14 { font-size: 14px !important; }
147
+ .fs-16 { font-size: 16px !important; }
148
+ .fs-20 { font-size: 20px !important; }
149
+ .fs-24 { font-size: 24px !important; }
150
+ .fs-32 { font-size: 32px !important; }
151
+
152
+ /* Alignment Helpers */
153
+ .v-align-middle { vertical-align: middle !important; }
154
+
155
+ /* Styling Helpers */
156
+ .rounded-12 { border-radius: 12px !important; }
157
+ .min-h-150 { min-height: 150px !important; }
158
+ .fw-bold { font-weight: 700 !important; }
159
+ .text-primary { color: var(--primary) !important; }
160
+ .text-critical { color: #cc293d !important; }
161
+ .text-error-alt { color: #9f1239 !important; }
162
+
27
163
  * {
28
164
  box-sizing: border-box;
29
165
  margin: 0;
@@ -637,6 +773,73 @@ li::marker {
637
773
  border-radius: 6px;
638
774
  }
639
775
 
776
+ .duration-pill {
777
+ background: #f1f5f9;
778
+ padding: 6px 14px;
779
+ border-radius: 12px;
780
+ font-size: 0.85rem;
781
+ color: var(--text-muted);
782
+ display: flex;
783
+ align-items: center;
784
+ gap: 6px;
785
+ font-weight: 500;
786
+ }
787
+
788
+ .metadata-strip {
789
+ background: rgba(0, 0, 0, 0.03);
790
+ padding: 12px 20px;
791
+ border-radius: 16px;
792
+ margin-top: 4px;
793
+ }
794
+
795
+ .meta-item {
796
+ display: flex;
797
+ align-items: center;
798
+ gap: 8px;
799
+ }
800
+
801
+ .meta-icon {
802
+ font-size: 18px;
803
+ color: var(--text-muted);
804
+ opacity: 0.7;
805
+ }
806
+
807
+ .meta-text {
808
+ font-size: 0.9rem;
809
+ font-weight: 600;
810
+ color: var(--text-main);
811
+ }
812
+
813
+ .ms-auto {
814
+ margin-left: auto;
815
+ }
816
+
817
+ .a11y-audit-link {
818
+ color: var(--primary);
819
+ text-decoration: none;
820
+ font-weight: 700;
821
+ font-size: 0.85rem;
822
+ display: flex;
823
+ align-items: center;
824
+ gap: 6px;
825
+ padding: 6px 0;
826
+ transition: color 0.2s;
827
+ border-bottom: 2px solid transparent;
828
+ }
829
+
830
+ .a11y-audit-link:hover {
831
+ color: var(--primary-dark);
832
+ border-bottom-color: var(--primary);
833
+ }
834
+
835
+ .a11y-audit-link .link-arrow {
836
+ transition: transform 0.2s;
837
+ }
838
+
839
+ .a11y-audit-link:hover .link-arrow {
840
+ transform: translateX(3px);
841
+ }
842
+
640
843
  /* Images & Media */
641
844
  .screenshot-grid {
642
845
  display: grid;
@@ -785,16 +988,44 @@ video {
785
988
  color: var(--text-main);
786
989
  }
787
990
 
788
- .runtime-box {
789
- font-size: 0.9rem;
790
- color: var(--text-muted);
791
- }
792
-
793
991
  .runtime-val {
794
992
  color: var(--text-main);
795
993
  font-size: 1.1rem;
796
994
  }
797
995
 
996
+ /* Stat Pills (A11y Badges) */
997
+ .stat-pill {
998
+ display: flex;
999
+ align-items: center;
1000
+ gap: 8px;
1001
+ padding: 8px 16px;
1002
+ border-radius: 12px;
1003
+ font-weight: 700;
1004
+ font-size: 0.95rem;
1005
+ white-space: nowrap;
1006
+ background: #fff;
1007
+ border: 1px solid #e2e8f0;
1008
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.03);
1009
+ transition: all 0.2s ease;
1010
+ }
1011
+
1012
+ .stat-pill-passed {
1013
+ background: #f0fdf4;
1014
+ color: #166534;
1015
+ border-color: #bbf7d0;
1016
+ }
1017
+
1018
+ .stat-pill-failed {
1019
+ background: #fffafa;
1020
+ color: var(--failed);
1021
+ border-color: #fecdd3;
1022
+ box-shadow: 0 4px 12px rgba(239, 68, 68, 0.08);
1023
+ }
1024
+
1025
+ .stat-pill-icon {
1026
+ font-size: 20px !important;
1027
+ }
1028
+
798
1029
  /* Tabs */
799
1030
  .tabs-container {
800
1031
  display: flex;
@@ -1410,6 +1641,116 @@ video {
1410
1641
  vertical-align: middle;
1411
1642
  }
1412
1643
 
1644
+ /* Repro Preview — Enriched Bug Modal Sections */
1645
+ .repro-preview-root {
1646
+ font-family: 'Inter', sans-serif;
1647
+ font-size: 0.9rem;
1648
+ color: var(--text-main);
1649
+ line-height: 1.6;
1650
+ }
1651
+
1652
+ .repro-meta-pills {
1653
+ display: flex;
1654
+ gap: 8px;
1655
+ flex-wrap: wrap;
1656
+ margin-bottom: 16px;
1657
+ }
1658
+
1659
+ .repro-pill {
1660
+ display: inline-flex;
1661
+ align-items: center;
1662
+ padding: 3px 10px;
1663
+ border-radius: 20px;
1664
+ font-size: 0.78rem;
1665
+ font-weight: 700;
1666
+ letter-spacing: 0.3px;
1667
+ text-transform: uppercase;
1668
+ }
1669
+
1670
+ .repro-pill-id {
1671
+ background: var(--primary-soft);
1672
+ color: var(--primary-dark);
1673
+ border: 1px solid rgba(99, 102, 241, 0.2);
1674
+ }
1675
+
1676
+ .repro-pill-wcag {
1677
+ background: #f0fdf4;
1678
+ color: #166534;
1679
+ border: 1px solid #bbf7d0;
1680
+ }
1681
+
1682
+ .repro-pill-sev-critical { background: rgba(220,38,38,0.1); color: var(--critical); border: 1px solid rgba(220,38,38,0.2); }
1683
+ .repro-pill-sev-serious { background: rgba(234,88,12,0.1); color: var(--serious); border: 1px solid rgba(234,88,12,0.2); }
1684
+ .repro-pill-sev-moderate { background: rgba(245,158,11,0.1); color: var(--moderate); border: 1px solid rgba(245,158,11,0.2); }
1685
+ .repro-pill-sev-minor { background: rgba(14,165,233,0.1); color: var(--minor); border: 1px solid rgba(14,165,233,0.2); }
1686
+
1687
+ .repro-section {
1688
+ margin-bottom: 14px;
1689
+ }
1690
+
1691
+ .repro-section-label {
1692
+ font-size: 0.72rem;
1693
+ font-weight: 800;
1694
+ color: var(--text-muted);
1695
+ text-transform: uppercase;
1696
+ letter-spacing: 0.08em;
1697
+ margin-bottom: 6px;
1698
+ }
1699
+
1700
+ .repro-mono-box {
1701
+ font-family: 'JetBrains Mono', 'Fira Mono', monospace;
1702
+ background: #fffcf0;
1703
+ padding: 12px 14px;
1704
+ border: 1px solid #e2e8f0;
1705
+ border-radius: 10px;
1706
+ font-size: 0.83rem;
1707
+ color: #334155;
1708
+ line-height: 1.5;
1709
+ }
1710
+
1711
+ .repro-mono-box.repro-code {
1712
+ overflow-x: auto;
1713
+ white-space: pre-wrap;
1714
+ word-break: break-all;
1715
+ background: #f8fafc;
1716
+ }
1717
+
1718
+ .repro-hint-box {
1719
+ background: #f0fdf4;
1720
+ border: 1px solid #bbf7d0;
1721
+ padding: 12px 14px;
1722
+ border-radius: 10px;
1723
+ display: flex;
1724
+ gap: 10px;
1725
+ align-items: flex-start;
1726
+ color: #166534;
1727
+ }
1728
+
1729
+ .repro-hint-icon {
1730
+ font-size: 20px !important;
1731
+ color: #16a34a;
1732
+ flex-shrink: 0;
1733
+ margin-top: 1px;
1734
+ }
1735
+
1736
+ .repro-deque-link {
1737
+ display: inline-flex;
1738
+ align-items: center;
1739
+ gap: 4px;
1740
+ margin-top: 6px;
1741
+ color: #16a34a;
1742
+ font-weight: 600;
1743
+ font-size: 0.85rem;
1744
+ text-decoration: none;
1745
+ border-bottom: 1.5px solid rgba(22, 163, 74, 0.3);
1746
+ transition: border-color 0.2s;
1747
+ }
1748
+
1749
+ .repro-deque-link:hover {
1750
+ color: #15803d;
1751
+ border-bottom-color: #16a34a;
1752
+ }
1753
+
1413
1754
  /* ADO Modal Standardized */
1414
1755
  .ado-modal-premium .modal-content {
1415
1756
  border-radius: 20px;
@@ -1513,6 +1854,16 @@ select.ado-form-input {
1513
1854
  opacity: 0.1;
1514
1855
  }
1515
1856
 
1857
+ .ado-repro-env {
1858
+ font-size: 0.75rem;
1859
+ background: #fffcf0;
1860
+ border-color: #f9f0c3;
1861
+ padding: 12px;
1862
+ line-height: 1.5;
1863
+ border-radius: 12px;
1864
+ border: 1.5px solid #f9f0c3;
1865
+ }
1866
+
1516
1867
  .screenshot-thumb,
1517
1868
  .video-preview-player {
1518
1869
  width: 100%;
@@ -1593,3 +1944,43 @@ select.ado-form-input {
1593
1944
  color: var(--text-main);
1594
1945
  border: 1px solid #f1f5f9;
1595
1946
  }
1947
+
1948
+ /* Loader Styles */
1949
+ .loader-overlay {
1950
+ position: fixed;
1951
+ inset: 0;
1952
+ background: #fff;
1953
+ z-index: 10000;
1954
+ display: flex;
1955
+ flex-direction: column;
1956
+ justify-content: center;
1957
+ align-items: center;
1958
+ transition: opacity 0.5s ease;
1959
+ }
1960
+
1961
+ .loader-pulse {
1962
+ animation: pulseLoader 2s infinite ease-in-out;
1963
+ color: var(--primary);
1964
+ margin-bottom: 16px;
1965
+ }
1966
+
1967
+ @keyframes pulseLoader {
1968
+ 0%,
1969
+ 100% {
1970
+ transform: scale(1.1);
1971
+ opacity: 1;
1972
+ }
1973
+ 50% {
1974
+ transform: scale(0.9);
1975
+ opacity: 0.6;
1976
+ }
1977
+ }
1978
+
1979
+ .loader-text {
1980
+ font-family: 'Outfit', sans-serif;
1981
+ font-weight: 600;
1982
+ color: var(--text-muted);
1983
+ letter-spacing: 0.05em;
1984
+ text-transform: uppercase;
1985
+ font-size: 0.85rem;
1986
+ }