rubyllm-observ 0.5.1 → 0.6.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +54 -6
  3. data/app/assets/stylesheets/observ/_annotations.scss +114 -103
  4. data/app/assets/stylesheets/observ/_card.scss +58 -49
  5. data/app/assets/stylesheets/observ/_chat.scss +247 -155
  6. data/app/assets/stylesheets/observ/_components.scss +622 -340
  7. data/app/assets/stylesheets/observ/_dashboard.scss +31 -28
  8. data/app/assets/stylesheets/observ/_datasets.scss +494 -547
  9. data/app/assets/stylesheets/observ/_drawer.scss +250 -228
  10. data/app/assets/stylesheets/observ/_filters.scss +139 -0
  11. data/app/assets/stylesheets/observ/_json_viewer.scss +103 -97
  12. data/app/assets/stylesheets/observ/_layout.scss +443 -178
  13. data/app/assets/stylesheets/observ/_metrics.scss +79 -76
  14. data/app/assets/stylesheets/observ/_namespace.scss +18 -0
  15. data/app/assets/stylesheets/observ/_observations.scss +122 -119
  16. data/app/assets/stylesheets/observ/_pagination.scss +129 -112
  17. data/app/assets/stylesheets/observ/_prompts.scss +485 -269
  18. data/app/assets/stylesheets/observ/_reset.scss +249 -0
  19. data/app/assets/stylesheets/observ/_table.scss +46 -38
  20. data/app/assets/stylesheets/observ/_variables.scss +54 -0
  21. data/app/assets/stylesheets/observ/application.scss +3 -0
  22. data/app/controllers/observ/dataset_run_items_controller.rb +0 -1
  23. data/app/controllers/observ/review_queue_controller.rb +154 -0
  24. data/app/controllers/observ/scores_controller.rb +64 -0
  25. data/app/controllers/observ/sessions_controller.rb +23 -0
  26. data/app/helpers/observ/application_helper.rb +1 -0
  27. data/app/helpers/observ/reviews_helper.rb +33 -0
  28. data/app/models/concerns/observ/json_queryable.rb +138 -0
  29. data/app/models/concerns/observ/reviewable.rb +41 -0
  30. data/app/models/concerns/observ/scoreable.rb +34 -0
  31. data/app/models/observ/dataset_run_item.rb +3 -13
  32. data/app/models/observ/review_item.rb +48 -0
  33. data/app/models/observ/score.rb +38 -6
  34. data/app/models/observ/session.rb +5 -1
  35. data/app/models/observ/trace.rb +3 -0
  36. data/app/services/observ/evaluators/base_evaluator.rb +0 -1
  37. data/app/services/observ/guardrail_service.rb +128 -0
  38. data/app/views/kaminari/_first_page.html.erb +1 -1
  39. data/app/views/kaminari/_gap.html.erb +1 -1
  40. data/app/views/kaminari/_last_page.html.erb +1 -1
  41. data/app/views/kaminari/_next_page.html.erb +1 -1
  42. data/app/views/kaminari/_page.html.erb +1 -1
  43. data/app/views/kaminari/_paginator.html.erb +1 -1
  44. data/app/views/kaminari/_prev_page.html.erb +1 -1
  45. data/app/views/kaminari/observ/_first_page.html.erb +1 -1
  46. data/app/views/kaminari/observ/_gap.html.erb +1 -1
  47. data/app/views/kaminari/observ/_last_page.html.erb +1 -1
  48. data/app/views/kaminari/observ/_next_page.html.erb +1 -1
  49. data/app/views/kaminari/observ/_page.html.erb +1 -1
  50. data/app/views/kaminari/observ/_paginator.html.erb +1 -1
  51. data/app/views/kaminari/observ/_prev_page.html.erb +1 -1
  52. data/app/views/layouts/observ/application.html.erb +96 -58
  53. data/app/views/observ/annotations/_form.html.erb +5 -5
  54. data/app/views/observ/annotations/index.html.erb +4 -4
  55. data/app/views/observ/annotations/sessions_index.html.erb +9 -9
  56. data/app/views/observ/annotations/traces_index.html.erb +9 -9
  57. data/app/views/observ/chats/_form.html.erb +7 -7
  58. data/app/views/observ/datasets/index.html.erb +6 -6
  59. data/app/views/observ/messages/_form.html.erb +11 -12
  60. data/app/views/observ/observations/index.html.erb +3 -4
  61. data/app/views/observ/prompts/_form.html.erb +37 -38
  62. data/app/views/observ/prompts/_new_form.html.erb +37 -38
  63. data/app/views/observ/prompts/compare.html.erb +59 -55
  64. data/app/views/observ/prompts/edit.html.erb +3 -3
  65. data/app/views/observ/prompts/index.html.erb +9 -9
  66. data/app/views/observ/prompts/new.html.erb +3 -3
  67. data/app/views/observ/prompts/show.html.erb +2 -2
  68. data/app/views/observ/prompts/versions.html.erb +22 -22
  69. data/app/views/observ/review_queue/_item.html.erb +39 -0
  70. data/app/views/observ/review_queue/_stats.html.erb +18 -0
  71. data/app/views/observ/review_queue/index.html.erb +49 -0
  72. data/app/views/observ/review_queue/show.html.erb +76 -0
  73. data/app/views/observ/review_queue/stats.html.erb +100 -0
  74. data/app/views/observ/scores/_form.html.erb +39 -0
  75. data/app/views/observ/scores/create.turbo_stream.erb +10 -0
  76. data/app/views/observ/sessions/_chat.html.erb +59 -0
  77. data/app/views/observ/sessions/_metadata.html.erb +17 -0
  78. data/app/views/observ/sessions/_metrics.html.erb +81 -0
  79. data/app/views/observ/sessions/_traces.html.erb +92 -0
  80. data/app/views/observ/sessions/annotations_drawer.turbo_stream.erb +8 -1
  81. data/app/views/observ/sessions/index.html.erb +60 -4
  82. data/app/views/observ/sessions/show.html.erb +4 -217
  83. data/app/views/observ/traces/_details.html.erb +47 -0
  84. data/app/views/observ/traces/_input.html.erb +10 -0
  85. data/app/views/observ/traces/_metadata.html.erb +10 -0
  86. data/app/views/observ/traces/_observations.html.erb +172 -0
  87. data/app/views/observ/traces/_output.html.erb +10 -0
  88. data/app/views/observ/traces/annotations_drawer.turbo_stream.erb +8 -1
  89. data/app/views/observ/traces/index.html.erb +3 -4
  90. data/app/views/observ/traces/show.html.erb +5 -232
  91. data/config/routes.rb +14 -0
  92. data/db/migrate/015_refactor_scores_to_polymorphic.rb +27 -0
  93. data/db/migrate/016_create_observ_review_items.rb +25 -0
  94. data/lib/observ/version.rb +1 -1
  95. metadata +30 -1
@@ -1,365 +1,581 @@
1
1
  @import 'variables';
2
+ @import 'namespace';
3
+
4
+ @include observ-scoped {
5
+ // Prompts Table - Link Styling
6
+ .observ-prompts-table {
7
+ &__link {
8
+ font-weight: 500;
9
+ color: $observ-primary;
10
+ text-decoration: none;
11
+ transition: color 0.2s ease;
12
+
13
+ &:hover {
14
+ color: darken($observ-primary, 10%);
15
+ text-decoration: underline;
16
+ }
17
+ }
2
18
 
3
- // Prompts Index Page - Filters
4
- .observ-prompts-filters {
5
- margin-bottom: var(--spacing-lg, 1.5rem);
19
+ &__action-group {
20
+ display: flex;
21
+ gap: var(--spacing-sm, 0.5rem);
22
+ }
23
+ }
6
24
 
7
- &__form {
8
- display: flex;
9
- gap: var(--spacing-md, 1rem);
10
- align-items: flex-end;
25
+ // Prompts Pagination
26
+ .observ-prompts-pagination {
27
+ margin-top: var(--spacing-lg, 1.5rem);
11
28
  }
12
29
 
13
- &__field {
14
- display: flex;
15
- flex-direction: column;
30
+ // Empty State
31
+ .observ-card__empty-text {
32
+ margin-bottom: var(--spacing-md, 1rem);
33
+ }
16
34
 
17
- &--search {
18
- flex: 1;
19
- }
35
+ // Prompt Show Page - Version Details Layout
36
+ .prompt-details {
37
+ display: grid;
38
+ grid-template-columns: 300px 1fr;
39
+ gap: $observ-spacing-lg;
20
40
 
21
- &--state {
22
- width: 12rem;
41
+ @media (max-width: $observ-breakpoint-md) {
42
+ grid-template-columns: 1fr;
23
43
  }
24
44
  }
25
45
 
26
- &__label {
27
- display: block;
28
- margin-bottom: var(--spacing-xs, 0.5rem);
29
- font-weight: 500;
30
- color: $observ-gray-900;
31
- font-size: $observ-font-size-sm;
32
- }
46
+ // Prompt Versions Sidebar
47
+ .prompt-versions {
48
+ &__sidebar {
49
+ position: sticky;
50
+ top: $observ-spacing-md;
51
+ }
33
52
 
34
- &__input,
35
- &__select {
36
- width: 100%;
37
- padding: var(--spacing-sm, 0.5rem);
38
- border: 1px solid $observ-gray-300;
39
- border-radius: $observ-border-radius-sm;
40
- font-size: $observ-font-size-base;
41
- color: $observ-gray-900;
42
- transition: border-color 0.2s ease;
53
+ &__header {
54
+ padding: $observ-spacing-lg;
55
+ border-bottom: 1px solid $observ-border-subtle;
56
+ }
43
57
 
44
- &:focus {
45
- outline: none;
46
- border-color: $observ-primary;
47
- box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
58
+ &__title {
59
+ font-size: $observ-font-size-lg;
60
+ font-weight: 600;
61
+ margin: 0;
62
+ color: $observ-text-primary;
48
63
  }
49
64
 
50
- &::placeholder {
51
- color: $observ-gray-400;
65
+ &__list {
66
+ display: flex;
67
+ flex-direction: column;
68
+ padding: 0;
52
69
  }
53
- }
54
70
 
55
- &__actions {
56
- display: flex;
57
- gap: var(--spacing-sm, 0.5rem);
58
- }
59
- }
71
+ &__item {
72
+ display: block;
73
+ padding: 0.75rem $observ-spacing-md;
74
+ border-bottom: 1px solid $observ-border-subtle;
75
+ text-decoration: none;
76
+ color: inherit;
77
+ transition: $observ-transition;
78
+
79
+ &:hover {
80
+ background-color: $observ-bg-hover;
81
+ color: $observ-text-primary;
82
+ }
83
+
84
+ &--active {
85
+ background-color: rgba($observ-primary, 0.1);
86
+ border-left: 3px solid $observ-primary;
87
+ }
88
+ }
60
89
 
61
- // Prompts Table - Link Styling
62
- .observ-prompts-table {
63
- &__link {
64
- font-weight: 500;
65
- color: $observ-primary;
66
- text-decoration: none;
67
- transition: color 0.2s ease;
90
+ &__item-header {
91
+ display: flex;
92
+ align-items: center;
93
+ justify-content: space-between;
94
+ margin-bottom: $observ-spacing-xs;
95
+ }
68
96
 
69
- &:hover {
70
- color: darken($observ-primary, 10%);
71
- text-decoration: underline;
97
+ &__version-number {
98
+ font-weight: 500;
99
+ color: $observ-text-primary;
72
100
  }
73
- }
74
101
 
75
- &__action-group {
76
- display: flex;
77
- gap: var(--spacing-sm, 0.5rem);
102
+ &__commit-message {
103
+ font-size: $observ-font-size-xs;
104
+ color: $observ-text-muted;
105
+ margin: $observ-spacing-xs 0;
106
+ overflow: hidden;
107
+ text-overflow: ellipsis;
108
+ white-space: nowrap;
109
+ }
110
+
111
+ &__timestamp {
112
+ font-size: $observ-font-size-xs;
113
+ color: $observ-text-muted;
114
+ margin: $observ-spacing-xs 0 0;
115
+ }
116
+
117
+ &__footer {
118
+ padding: 0.75rem $observ-spacing-md;
119
+ }
78
120
  }
79
- }
80
121
 
81
- // Prompts Pagination
82
- .observ-prompts-pagination {
83
- margin-top: var(--spacing-lg, 1.5rem);
84
- }
122
+ // Prompt Details Panel
123
+ .prompt-detail {
124
+ &__header {
125
+ display: flex;
126
+ flex-direction: column;
127
+ gap: $observ-spacing-md;
128
+ }
85
129
 
86
- // Empty State
87
- .observ-card__empty-text {
88
- margin-bottom: var(--spacing-md, 1rem);
89
- }
130
+ &__header-section {
131
+ width: 100%;
132
+ padding-bottom: $observ-spacing-md;
133
+ border-bottom: 1px solid $observ-border-subtle;
90
134
 
91
- // Prompt Show Page - Version Details Layout
92
- .prompt-details {
93
- display: grid;
94
- grid-template-columns: 300px 1fr;
95
- gap: $observ-spacing-lg;
135
+ &:last-child {
136
+ border-bottom: none;
137
+ padding-bottom: 0;
138
+ }
139
+ }
96
140
 
97
- @media (max-width: $observ-breakpoint-md) {
98
- grid-template-columns: 1fr;
99
- }
100
- }
141
+ &__badges-row {
142
+ display: flex;
143
+ align-items: center;
144
+ justify-content: space-between;
145
+ width: 100%;
146
+ }
101
147
 
102
- // Prompt Versions Sidebar
103
- .prompt-versions {
104
- &__sidebar {
105
- position: sticky;
106
- top: $observ-spacing-md;
107
- }
148
+ &__badges {
149
+ display: flex;
150
+ align-items: center;
151
+ gap: $observ-spacing-sm;
152
+ }
108
153
 
109
- &__header {
110
- padding: $observ-spacing-lg;
111
- border-bottom: 1px solid $observ-gray-200;
112
- }
154
+ &__metadata {
155
+ display: grid;
156
+ grid-template-columns: repeat(4, 1fr);
157
+ gap: $observ-spacing-lg;
158
+ font-size: $observ-font-size-sm;
113
159
 
114
- &__title {
115
- font-size: $observ-font-size-lg;
116
- font-weight: 600;
117
- margin: 0;
118
- color: $observ-gray-900;
119
- }
160
+ @media (max-width: $observ-breakpoint-lg) {
161
+ grid-template-columns: repeat(2, 1fr);
162
+ }
120
163
 
121
- &__list {
122
- display: flex;
123
- flex-direction: column;
124
- padding: 0;
125
- }
164
+ @media (max-width: $observ-breakpoint-sm) {
165
+ grid-template-columns: 1fr;
166
+ }
167
+ }
126
168
 
127
- &__item {
128
- display: block;
129
- padding: 0.75rem $observ-spacing-md;
130
- border-bottom: 1px solid $observ-gray-200;
131
- text-decoration: none;
132
- color: inherit;
133
- transition: $observ-transition;
169
+ &__metadata-item {
170
+ display: flex;
171
+ flex-direction: column;
172
+ gap: $observ-spacing-xs;
173
+ }
134
174
 
135
- &:hover {
136
- background-color: $observ-gray-50;
175
+ &__metadata-label {
176
+ color: $observ-text-muted;
177
+ font-size: $observ-font-size-xs;
178
+ text-transform: uppercase;
179
+ letter-spacing: 0.05em;
180
+ font-weight: 600;
181
+ margin: 0;
137
182
  }
138
183
 
139
- &--active {
140
- background-color: #eff6ff;
141
- border-left: 3px solid $observ-primary;
184
+ &__metadata-value {
185
+ font-weight: 500;
186
+ color: $observ-text-primary;
187
+ margin: 0;
142
188
  }
143
- }
144
189
 
145
- &__item-header {
146
- display: flex;
147
- align-items: center;
148
- justify-content: space-between;
149
- margin-bottom: $observ-spacing-xs;
150
- }
190
+ &__commit {
191
+ padding: 0.75rem;
192
+ background-color: $observ-bg-elevated;
193
+ border-radius: $observ-border-radius-sm;
194
+ }
195
+
196
+ &__commit-title {
197
+ font-size: $observ-font-size-sm;
198
+ font-weight: 600;
199
+ margin: 0 0 $observ-spacing-xs 0;
200
+ color: $observ-text-primary;
201
+ }
202
+
203
+ &__commit-message {
204
+ font-size: $observ-font-size-sm;
205
+ color: $observ-text-secondary;
206
+ margin: 0;
207
+ }
208
+
209
+ &__section-title {
210
+ font-size: $observ-font-size-lg;
211
+ font-weight: 600;
212
+ margin: 0 0 0.75rem;
213
+ color: $observ-text-primary;
214
+ }
215
+
216
+ &__content-block {
217
+ background-color: $observ-bg-elevated;
218
+ padding: $observ-spacing-md;
219
+ border-radius: $observ-border-radius-sm;
220
+ overflow-x: auto;
221
+
222
+ pre {
223
+ margin: 0;
224
+ font-family: $observ-font-family-mono;
225
+ font-size: $observ-font-size-sm;
226
+ white-space: pre-wrap;
227
+ }
228
+ }
229
+
230
+ &__config-block {
231
+ background-color: $observ-bg-elevated;
232
+ padding: $observ-spacing-md;
233
+ border-radius: $observ-border-radius-sm;
234
+ overflow-x: auto;
235
+
236
+ pre {
237
+ font-size: $observ-font-size-sm;
238
+ margin: 0;
239
+ }
240
+ }
151
241
 
152
- &__version-number {
153
- font-weight: 500;
154
- color: $observ-gray-900;
242
+ &__no-config {
243
+ color: $observ-text-muted;
244
+ font-size: $observ-font-size-sm;
245
+ }
246
+
247
+ &__body-section {
248
+ border-bottom: 1px solid $observ-border-subtle;
249
+ }
155
250
  }
156
251
 
157
- &__commit-message {
158
- font-size: $observ-font-size-xs;
159
- color: $observ-gray-500;
160
- margin: $observ-spacing-xs 0;
161
- overflow: hidden;
162
- text-overflow: ellipsis;
163
- white-space: nowrap;
252
+ // Page Header Customizations for Prompts
253
+ .prompt-page-header {
254
+ &__back-link {
255
+ display: inline-block;
256
+ margin-bottom: $observ-spacing-sm;
257
+ color: $observ-primary;
258
+ text-decoration: none;
259
+ font-weight: 500;
260
+ transition: $observ-transition;
261
+
262
+ &:hover {
263
+ color: lighten($observ-primary, 10%);
264
+ }
265
+ }
266
+
267
+ &__subtitle {
268
+ color: $observ-text-muted;
269
+ margin-top: $observ-spacing-xs;
270
+ font-size: $observ-font-size-sm;
271
+ }
164
272
  }
165
273
 
166
- &__timestamp {
167
- font-size: $observ-font-size-xs;
168
- color: $observ-gray-400;
169
- margin: $observ-spacing-xs 0 0;
274
+ // Badge modifier for "default" state
275
+ .observ-badge--default {
276
+ background-color: $observ-bg-elevated;
277
+ color: $observ-text-secondary;
170
278
  }
171
279
 
172
- &__footer {
173
- padding: 0.75rem $observ-spacing-md;
280
+ // ==========================================================================
281
+ // PROMPT PAGE HEADER
282
+ // ==========================================================================
283
+ .observ-prompt-header {
284
+ &__subtitle {
285
+ color: $observ-text-muted;
286
+ margin-top: $observ-spacing-xs;
287
+ font-size: $observ-font-size-sm;
288
+ }
174
289
  }
175
- }
176
290
 
177
- // Prompt Details Panel
178
- .prompt-detail {
179
- &__header {
291
+ // ==========================================================================
292
+ // TIMELINE (for versions page)
293
+ // ==========================================================================
294
+ .observ-timeline {
180
295
  display: flex;
181
296
  flex-direction: column;
182
- gap: $observ-spacing-md;
183
- }
184
-
185
- &__header-section {
186
- width: 100%;
187
- padding-bottom: $observ-spacing-md;
188
- border-bottom: 1px solid $observ-gray-200;
189
-
190
- &:last-child {
191
- border-bottom: none;
192
- padding-bottom: 0;
193
- }
297
+ gap: $observ-spacing-lg;
194
298
  }
195
299
 
196
- &__badges-row {
300
+ .observ-timeline__item {
197
301
  display: flex;
198
- align-items: center;
199
- justify-content: space-between;
200
- width: 100%;
302
+ gap: $observ-spacing-md;
201
303
  }
202
304
 
203
- &__badges {
305
+ .observ-timeline__marker {
204
306
  display: flex;
307
+ flex-direction: column;
205
308
  align-items: center;
206
- gap: $observ-spacing-sm;
207
309
  }
208
310
 
209
- &__metadata {
210
- display: grid;
211
- grid-template-columns: repeat(4, 1fr);
212
- gap: $observ-spacing-lg;
213
- font-size: $observ-font-size-sm;
311
+ .observ-timeline__dot {
312
+ width: 1rem;
313
+ height: 1rem;
314
+ border-radius: 50%;
315
+ flex-shrink: 0;
214
316
 
215
- @media (max-width: $observ-breakpoint-lg) {
216
- grid-template-columns: repeat(2, 1fr);
317
+ &--success {
318
+ background-color: $observ-success;
217
319
  }
218
320
 
219
- @media (max-width: $observ-breakpoint-sm) {
220
- grid-template-columns: 1fr;
321
+ &--warning {
322
+ background-color: $observ-warning;
221
323
  }
222
- }
223
324
 
224
- &__metadata-item {
225
- display: flex;
226
- flex-direction: column;
227
- gap: $observ-spacing-xs;
325
+ &--muted {
326
+ background-color: $observ-text-muted;
327
+ }
228
328
  }
229
329
 
230
- &__metadata-label {
231
- color: $observ-gray-500;
232
- font-size: $observ-font-size-xs;
233
- text-transform: uppercase;
234
- letter-spacing: 0.05em;
235
- font-weight: 600;
236
- margin: 0;
330
+ .observ-timeline__line {
331
+ width: 2px;
332
+ flex: 1;
333
+ background-color: $observ-border-color;
334
+ margin: $observ-spacing-xs 0;
237
335
  }
238
336
 
239
- &__metadata-value {
240
- font-weight: 500;
241
- color: $observ-gray-900;
242
- margin: 0;
337
+ .observ-timeline__content {
338
+ flex: 1;
339
+ padding-bottom: $observ-spacing-lg;
243
340
  }
244
341
 
245
- &__commit {
246
- padding: 0.75rem;
247
- background-color: $observ-gray-50;
248
- border-radius: $observ-border-radius-sm;
249
- }
342
+ // ==========================================================================
343
+ // VERSION CARD (for timeline items)
344
+ // ==========================================================================
345
+ .observ-version-card {
346
+ border: 1px solid $observ-border-color;
347
+ border-radius: $observ-border-radius;
348
+ padding: $observ-spacing-md;
349
+ transition: border-color 0.2s ease;
250
350
 
251
- &__commit-title {
252
- font-size: $observ-font-size-sm;
253
- font-weight: 600;
254
- margin: 0 0 $observ-spacing-xs 0;
255
- color: $observ-gray-900;
256
- }
351
+ &:hover {
352
+ border-color: $observ-border-strong;
353
+ }
257
354
 
258
- &__commit-message {
259
- font-size: $observ-font-size-sm;
260
- color: $observ-gray-700;
261
- margin: 0;
262
- }
355
+ &__header {
356
+ display: flex;
357
+ align-items: flex-start;
358
+ justify-content: space-between;
359
+ margin-bottom: $observ-spacing-sm;
360
+ }
263
361
 
264
- &__section-title {
265
- font-size: $observ-font-size-lg;
266
- font-weight: 600;
267
- margin: 0 0 0.75rem;
268
- color: $observ-gray-900;
269
- }
362
+ &__title-row {
363
+ display: flex;
364
+ align-items: center;
365
+ gap: $observ-spacing-sm;
366
+ margin-bottom: $observ-spacing-xs;
367
+ }
270
368
 
271
- &__content-block {
272
- background-color: $observ-gray-50;
273
- padding: $observ-spacing-md;
274
- border-radius: $observ-border-radius-sm;
275
- overflow-x: auto;
369
+ &__title {
370
+ font-size: $observ-font-size-lg;
371
+ font-weight: 600;
372
+ margin: 0;
373
+ color: $observ-text-primary;
374
+ }
276
375
 
277
- pre {
376
+ &__meta {
377
+ font-size: $observ-font-size-sm;
378
+ color: $observ-text-muted;
278
379
  margin: 0;
380
+ }
381
+
382
+ &__author {
383
+ font-weight: 500;
384
+ }
385
+
386
+ &__commit {
387
+ font-size: $observ-font-size-sm;
388
+ color: $observ-text-secondary;
389
+ margin: $observ-spacing-sm 0 0;
390
+ font-style: italic;
391
+ }
392
+
393
+ &__actions {
394
+ display: flex;
395
+ gap: $observ-spacing-sm;
396
+ }
397
+
398
+ &__preview {
399
+ margin-top: $observ-spacing-sm;
400
+ padding: $observ-spacing-sm;
401
+ background-color: $observ-bg-elevated;
402
+ border-radius: $observ-border-radius-sm;
279
403
  font-family: $observ-font-family-mono;
280
404
  font-size: $observ-font-size-sm;
281
- white-space: pre-wrap;
405
+ overflow: hidden;
406
+ text-overflow: ellipsis;
407
+ white-space: nowrap;
408
+ color: $observ-text-secondary;
282
409
  }
283
410
  }
284
411
 
285
- &__config-block {
286
- background-color: $observ-gray-50;
287
- padding: $observ-spacing-md;
288
- border-radius: $observ-border-radius-sm;
289
- overflow-x: auto;
412
+ // ==========================================================================
413
+ // COMPARE PAGE
414
+ // ==========================================================================
415
+ .observ-compare {
416
+ &__selector {
417
+ display: flex;
418
+ gap: $observ-spacing-md;
419
+ align-items: flex-end;
420
+ }
290
421
 
291
- pre {
292
- font-size: $observ-font-size-sm;
422
+ &__field {
423
+ flex: 1;
424
+ }
425
+
426
+ &__grid {
427
+ display: grid;
428
+ grid-template-columns: repeat(2, 1fr);
429
+ border-top: 1px solid $observ-border-subtle;
430
+
431
+ @media (max-width: $observ-breakpoint-md) {
432
+ grid-template-columns: 1fr;
433
+ }
434
+ }
435
+
436
+ &__panel {
437
+ padding: $observ-spacing-lg;
438
+
439
+ &--left {
440
+ border-right: 1px solid $observ-border-subtle;
441
+
442
+ @media (max-width: $observ-breakpoint-md) {
443
+ border-right: none;
444
+ border-bottom: 1px solid $observ-border-subtle;
445
+ }
446
+ }
447
+ }
448
+
449
+ &__version-header {
450
+ display: flex;
451
+ align-items: center;
452
+ gap: $observ-spacing-sm;
453
+ margin-bottom: $observ-spacing-md;
454
+ }
455
+
456
+ &__version-title {
457
+ font-size: $observ-font-size-xl;
458
+ font-weight: 600;
293
459
  margin: 0;
460
+ color: $observ-text-primary;
294
461
  }
295
- }
296
462
 
297
- &__no-config {
298
- color: $observ-gray-500;
299
- font-size: $observ-font-size-sm;
300
- }
463
+ &__metadata {
464
+ display: flex;
465
+ flex-direction: column;
466
+ gap: $observ-spacing-sm;
467
+ font-size: $observ-font-size-sm;
468
+ }
301
469
 
302
- &__body-section {
303
- border-bottom: 1px solid $observ-gray-200;
304
- }
305
- }
470
+ &__metadata-item {
471
+ dt {
472
+ color: $observ-text-muted;
473
+ margin: 0;
474
+ }
475
+
476
+ dd {
477
+ font-weight: 500;
478
+ margin: $observ-spacing-xs 0 0;
479
+ color: $observ-text-primary;
480
+
481
+ &--italic {
482
+ font-style: italic;
483
+ }
484
+ }
485
+ }
306
486
 
307
- // Page Header Customizations for Prompts
308
- .prompt-page-header {
309
- &__back-link {
310
- display: inline-block;
311
- margin-bottom: $observ-spacing-sm;
312
- color: $observ-primary;
313
- text-decoration: none;
314
- font-weight: 500;
315
- transition: $observ-transition;
487
+ &__content-block {
488
+ background-color: $observ-bg-elevated;
489
+ padding: $observ-spacing-md;
490
+ border-radius: $observ-border-radius-sm;
491
+ overflow-x: auto;
492
+
493
+ pre {
494
+ margin: 0;
495
+ font-family: $observ-font-family-mono;
496
+ font-size: $observ-font-size-sm;
497
+ white-space: pre-wrap;
498
+ }
499
+ }
316
500
 
317
- &:hover {
318
- color: darken($observ-primary, 10%);
501
+ &__section-title {
502
+ font-size: $observ-font-size-xl;
503
+ font-weight: 600;
504
+ margin: 0;
505
+ color: $observ-text-primary;
319
506
  }
320
507
  }
321
508
 
322
- &__subtitle {
323
- color: $observ-gray-500;
324
- margin-top: $observ-spacing-xs;
325
- font-size: $observ-font-size-sm;
509
+ // ==========================================================================
510
+ // PROMPT FORM ENHANCEMENTS
511
+ // ==========================================================================
512
+ .observ-prompt-form {
513
+ &__variable-preview {
514
+ margin-top: $observ-spacing-sm;
515
+ padding: $observ-spacing-sm;
516
+ background-color: rgba($observ-info, 0.1);
517
+ border-radius: $observ-border-radius-sm;
518
+ display: none;
519
+
520
+ &--visible {
521
+ display: block;
522
+ }
523
+ }
524
+
525
+ &__variable-title {
526
+ font-size: $observ-font-size-sm;
527
+ font-weight: 500;
528
+ color: $observ-info;
529
+ margin: 0 0 $observ-spacing-sm;
530
+ }
531
+
532
+ &__variable-list {
533
+ display: flex;
534
+ flex-wrap: wrap;
535
+ gap: $observ-spacing-sm;
536
+ }
537
+
326
538
  }
327
- }
328
539
 
329
- // Badge modifier for "default" state
330
- .observ-badge--default {
331
- background-color: $observ-gray-100;
332
- color: $observ-gray-600;
333
- }
540
+ // Form actions with space-between layout
541
+ .observ-form__actions--between {
542
+ justify-content: space-between;
543
+ }
334
544
 
335
- // Prompt Actions Component
336
- .prompt-actions {
337
- display: flex;
338
- gap: $observ-spacing-sm;
339
- align-items: center;
340
-
341
- // Ensure button_to forms display inline and don't affect layout
342
- form {
343
- display: inline-flex;
344
- margin: 0;
345
- padding: 0;
346
- border: none;
347
- background: none;
545
+ .observ-form__actions-group {
546
+ display: flex;
547
+ gap: $observ-spacing-sm;
348
548
  }
349
549
 
350
- // Ensure all buttons (both links and actual buttons) have same height
351
- .observ-button,
352
- button.observ-button {
353
- display: inline-flex;
550
+ // Prompt Actions Component
551
+ .prompt-actions {
552
+ display: flex;
553
+ gap: $observ-spacing-sm;
354
554
  align-items: center;
355
- justify-content: center;
356
- line-height: 1;
357
- white-space: nowrap;
358
- }
359
555
 
360
- // Reset button element defaults
361
- button.observ-button {
362
- border: 1px solid $observ-gray-300;
363
- font-family: inherit;
556
+ // Ensure button_to forms display inline and don't affect layout
557
+ form {
558
+ display: inline-flex;
559
+ margin: 0;
560
+ padding: 0;
561
+ border: none;
562
+ background: none;
563
+ }
564
+
565
+ // Ensure all buttons (both links and actual buttons) have same height
566
+ .observ-button,
567
+ button.observ-button {
568
+ display: inline-flex;
569
+ align-items: center;
570
+ justify-content: center;
571
+ line-height: 1;
572
+ white-space: nowrap;
573
+ }
574
+
575
+ // Reset button element defaults
576
+ button.observ-button {
577
+ border: 1px solid $observ-border-color;
578
+ font-family: inherit;
579
+ }
364
580
  }
365
581
  }