coplan-engine 0.1.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 (84) hide show
  1. checksums.yaml +7 -0
  2. data/app/assets/stylesheets/coplan/application.css +956 -0
  3. data/app/controllers/coplan/api/v1/base_controller.rb +75 -0
  4. data/app/controllers/coplan/api/v1/comments_controller.rb +135 -0
  5. data/app/controllers/coplan/api/v1/leases_controller.rb +62 -0
  6. data/app/controllers/coplan/api/v1/operations_controller.rb +298 -0
  7. data/app/controllers/coplan/api/v1/plans_controller.rb +129 -0
  8. data/app/controllers/coplan/api/v1/sessions_controller.rb +92 -0
  9. data/app/controllers/coplan/application_controller.rb +78 -0
  10. data/app/controllers/coplan/automated_reviews_controller.rb +29 -0
  11. data/app/controllers/coplan/comment_threads_controller.rb +148 -0
  12. data/app/controllers/coplan/comments_controller.rb +40 -0
  13. data/app/controllers/coplan/dashboard_controller.rb +6 -0
  14. data/app/controllers/coplan/plan_versions_controller.rb +29 -0
  15. data/app/controllers/coplan/plans_controller.rb +53 -0
  16. data/app/controllers/coplan/settings/tokens_controller.rb +37 -0
  17. data/app/helpers/coplan/application_helper.rb +4 -0
  18. data/app/helpers/coplan/comments_helper.rb +20 -0
  19. data/app/helpers/coplan/markdown_helper.rb +36 -0
  20. data/app/javascript/controllers/coplan/dropdown_controller.js +25 -0
  21. data/app/javascript/controllers/coplan/line_selection_controller.js +112 -0
  22. data/app/javascript/controllers/coplan/tabs_controller.js +18 -0
  23. data/app/javascript/controllers/coplan/text_selection_controller.js +376 -0
  24. data/app/jobs/coplan/application_job.rb +4 -0
  25. data/app/jobs/coplan/automated_review_job.rb +71 -0
  26. data/app/jobs/coplan/commit_expired_session_job.rb +29 -0
  27. data/app/jobs/coplan/notification_job.rb +10 -0
  28. data/app/models/coplan/api_token.rb +50 -0
  29. data/app/models/coplan/application_record.rb +14 -0
  30. data/app/models/coplan/automated_plan_reviewer.rb +62 -0
  31. data/app/models/coplan/comment.rb +24 -0
  32. data/app/models/coplan/comment_thread.rb +151 -0
  33. data/app/models/coplan/current.rb +5 -0
  34. data/app/models/coplan/edit_lease.rb +57 -0
  35. data/app/models/coplan/edit_session.rb +61 -0
  36. data/app/models/coplan/plan.rb +28 -0
  37. data/app/models/coplan/plan_collaborator.rb +12 -0
  38. data/app/models/coplan/plan_version.rb +23 -0
  39. data/app/models/coplan/user.rb +20 -0
  40. data/app/policies/coplan/application_policy.rb +14 -0
  41. data/app/policies/coplan/comment_thread_policy.rb +23 -0
  42. data/app/policies/coplan/plan_policy.rb +15 -0
  43. data/app/services/coplan/ai_providers/anthropic.rb +21 -0
  44. data/app/services/coplan/ai_providers/open_ai.rb +44 -0
  45. data/app/services/coplan/broadcaster.rb +32 -0
  46. data/app/services/coplan/plans/apply_operations.rb +128 -0
  47. data/app/services/coplan/plans/commit_session.rb +186 -0
  48. data/app/services/coplan/plans/create.rb +30 -0
  49. data/app/services/coplan/plans/operation_error.rb +5 -0
  50. data/app/services/coplan/plans/position_resolver.rb +191 -0
  51. data/app/services/coplan/plans/review_prompt_formatter.rb +25 -0
  52. data/app/services/coplan/plans/review_response_parser.rb +65 -0
  53. data/app/services/coplan/plans/transform_range.rb +99 -0
  54. data/app/services/coplan/plans/trigger_automated_reviews.rb +33 -0
  55. data/app/views/coplan/comment_threads/_new_comment_form.html.erb +17 -0
  56. data/app/views/coplan/comment_threads/_reply_form.html.erb +8 -0
  57. data/app/views/coplan/comment_threads/_thread.html.erb +47 -0
  58. data/app/views/coplan/comments/_comment.html.erb +9 -0
  59. data/app/views/coplan/dashboard/show.html.erb +8 -0
  60. data/app/views/coplan/plan_versions/index.html.erb +21 -0
  61. data/app/views/coplan/plan_versions/show.html.erb +29 -0
  62. data/app/views/coplan/plans/_header.html.erb +26 -0
  63. data/app/views/coplan/plans/edit.html.erb +15 -0
  64. data/app/views/coplan/plans/index.html.erb +35 -0
  65. data/app/views/coplan/plans/show.html.erb +56 -0
  66. data/app/views/coplan/settings/tokens/_form.html.erb +8 -0
  67. data/app/views/coplan/settings/tokens/_token_reveal.html.erb +7 -0
  68. data/app/views/coplan/settings/tokens/_token_row.html.erb +24 -0
  69. data/app/views/coplan/settings/tokens/create.turbo_stream.erb +11 -0
  70. data/app/views/coplan/settings/tokens/destroy.turbo_stream.erb +5 -0
  71. data/app/views/coplan/settings/tokens/index.html.erb +32 -0
  72. data/app/views/layouts/coplan/application.html.erb +42 -0
  73. data/config/importmap.rb +1 -0
  74. data/config/routes.rb +41 -0
  75. data/db/migrate/20260226200000_create_coplan_schema.rb +173 -0
  76. data/lib/coplan/configuration.rb +17 -0
  77. data/lib/coplan/engine.rb +34 -0
  78. data/lib/coplan/version.rb +3 -0
  79. data/lib/coplan.rb +15 -0
  80. data/lib/tasks/coplan.rake +4 -0
  81. data/prompts/reviewers/routing.md +14 -0
  82. data/prompts/reviewers/scalability.md +14 -0
  83. data/prompts/reviewers/security.md +14 -0
  84. metadata +245 -0
@@ -0,0 +1,956 @@
1
+ /* CoPlan — Design Tokens + Base Styles */
2
+
3
+ :root {
4
+ /* Colors */
5
+ --color-bg: #fafafa;
6
+ --color-surface: #ffffff;
7
+ --color-text: #1a1a1a;
8
+ --color-text-muted: #6b7280;
9
+ --color-border: #e5e7eb;
10
+ --color-primary: #2563eb;
11
+ --color-primary-hover: #1d4ed8;
12
+ --color-primary-light: #eff6ff;
13
+ --color-success: #059669;
14
+ --color-warning: #d97706;
15
+ --color-danger: #dc2626;
16
+ --color-danger-hover: #b91c1c;
17
+
18
+ /* Status colors */
19
+ --color-status-brainstorm: #8b5cf6;
20
+ --color-status-considering: #f59e0b;
21
+ --color-status-developing: #3b82f6;
22
+ --color-status-live: #10b981;
23
+ --color-status-abandoned: #6b7280;
24
+
25
+ /* Spacing */
26
+ --space-xs: 0.25rem;
27
+ --space-sm: 0.5rem;
28
+ --space-md: 1rem;
29
+ --space-lg: 1.5rem;
30
+ --space-xl: 2rem;
31
+ --space-2xl: 3rem;
32
+
33
+ /* Typography */
34
+ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
35
+ --font-mono: "SF Mono", SFMono-Regular, ui-monospace, Menlo, monospace;
36
+ --text-sm: 0.875rem;
37
+ --text-base: 1rem;
38
+ --text-lg: 1.125rem;
39
+ --text-xl: 1.25rem;
40
+ --text-2xl: 1.5rem;
41
+
42
+ /* Layout */
43
+ --max-width: 72rem;
44
+ --nav-height: 3.5rem;
45
+ --radius: 0.375rem;
46
+ --shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
47
+ --shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.1);
48
+ }
49
+
50
+ /* Reset */
51
+ *, *::before, *::after {
52
+ box-sizing: border-box;
53
+ margin: 0;
54
+ padding: 0;
55
+ }
56
+
57
+ html {
58
+ font-family: var(--font-sans);
59
+ font-size: var(--text-base);
60
+ line-height: 1.6;
61
+ color: var(--color-text);
62
+ background-color: var(--color-bg);
63
+ -webkit-font-smoothing: antialiased;
64
+ }
65
+
66
+ body {
67
+ min-height: 100vh;
68
+ display: flex;
69
+ flex-direction: column;
70
+ }
71
+
72
+ a {
73
+ color: var(--color-primary);
74
+ text-decoration: none;
75
+ }
76
+
77
+ a:hover {
78
+ text-decoration: underline;
79
+ }
80
+
81
+ img, svg {
82
+ max-width: 100%;
83
+ display: block;
84
+ }
85
+
86
+ /* Navigation */
87
+ .site-nav {
88
+ background: var(--color-surface);
89
+ border-bottom: 1px solid var(--color-border);
90
+ height: var(--nav-height);
91
+ position: sticky;
92
+ top: 0;
93
+ z-index: 100;
94
+ }
95
+
96
+ .site-nav__inner {
97
+ max-width: var(--max-width);
98
+ margin: 0 auto;
99
+ padding: 0 var(--space-lg);
100
+ height: 100%;
101
+ display: flex;
102
+ align-items: center;
103
+ justify-content: space-between;
104
+ }
105
+
106
+ .site-nav__brand {
107
+ font-size: var(--text-lg);
108
+ font-weight: 700;
109
+ color: var(--color-text);
110
+ text-decoration: none;
111
+ display: flex;
112
+ align-items: center;
113
+ gap: var(--space-sm);
114
+ }
115
+
116
+ .site-nav__brand:hover {
117
+ text-decoration: none;
118
+ color: var(--color-primary);
119
+ }
120
+
121
+ .site-nav__links {
122
+ display: flex;
123
+ align-items: center;
124
+ gap: var(--space-lg);
125
+ list-style: none;
126
+ }
127
+
128
+ .site-nav__links a {
129
+ color: var(--color-text-muted);
130
+ font-size: var(--text-sm);
131
+ font-weight: 500;
132
+ transition: color 0.15s;
133
+ }
134
+
135
+ .site-nav__links a:hover {
136
+ color: var(--color-text);
137
+ text-decoration: none;
138
+ }
139
+
140
+ .site-nav__user {
141
+ display: flex;
142
+ align-items: center;
143
+ gap: var(--space-sm);
144
+ color: var(--color-text-muted);
145
+ font-size: var(--text-sm);
146
+ }
147
+
148
+ /* Main content */
149
+ .main-content {
150
+ flex: 1;
151
+ max-width: var(--max-width);
152
+ margin: 0 auto;
153
+ padding: var(--space-xl) var(--space-lg);
154
+ width: 100%;
155
+ }
156
+
157
+ /* Page header */
158
+ .page-header {
159
+ margin-bottom: var(--space-xl);
160
+ display: flex;
161
+ align-items: center;
162
+ justify-content: space-between;
163
+ }
164
+
165
+ .page-header h1 {
166
+ font-size: var(--text-2xl);
167
+ font-weight: 700;
168
+ }
169
+
170
+ /* Flash messages */
171
+ .flash {
172
+ padding: var(--space-md) var(--space-lg);
173
+ border-radius: var(--radius);
174
+ margin-bottom: var(--space-lg);
175
+ font-size: var(--text-sm);
176
+ }
177
+
178
+ .flash--notice {
179
+ background: var(--color-primary-light);
180
+ color: var(--color-primary);
181
+ border: 1px solid var(--color-primary);
182
+ }
183
+
184
+ .flash--alert {
185
+ background: #fef2f2;
186
+ color: var(--color-danger);
187
+ border: 1px solid var(--color-danger);
188
+ }
189
+
190
+ /* Buttons */
191
+ .btn {
192
+ display: inline-flex;
193
+ align-items: center;
194
+ gap: var(--space-xs);
195
+ padding: var(--space-sm) var(--space-md);
196
+ font-size: var(--text-sm);
197
+ font-weight: 500;
198
+ border-radius: var(--radius);
199
+ border: 1px solid transparent;
200
+ cursor: pointer;
201
+ transition: all 0.15s;
202
+ text-decoration: none;
203
+ line-height: 1.4;
204
+ }
205
+
206
+ .btn:hover {
207
+ text-decoration: none;
208
+ }
209
+
210
+ .btn--primary {
211
+ background: var(--color-primary);
212
+ color: #fff;
213
+ }
214
+
215
+ .btn--primary:hover {
216
+ background: var(--color-primary-hover);
217
+ color: #fff;
218
+ }
219
+
220
+ .btn--secondary {
221
+ background: var(--color-surface);
222
+ color: var(--color-text);
223
+ border-color: var(--color-border);
224
+ }
225
+
226
+ .btn--secondary:hover {
227
+ background: var(--color-bg);
228
+ }
229
+
230
+ .btn--danger {
231
+ background: var(--color-danger);
232
+ color: #fff;
233
+ }
234
+
235
+ .btn--danger:hover {
236
+ background: var(--color-danger-hover);
237
+ color: #fff;
238
+ }
239
+
240
+ /* Cards */
241
+ .card {
242
+ background: var(--color-surface);
243
+ border: 1px solid var(--color-border);
244
+ border-radius: var(--radius);
245
+ padding: var(--space-lg);
246
+ box-shadow: var(--shadow);
247
+ }
248
+
249
+ /* Status badges */
250
+ .badge {
251
+ display: inline-block;
252
+ padding: var(--space-xs) var(--space-sm);
253
+ font-size: 0.75rem;
254
+ font-weight: 600;
255
+ border-radius: 9999px;
256
+ text-transform: uppercase;
257
+ letter-spacing: 0.025em;
258
+ }
259
+
260
+ .badge--brainstorm { background: #ede9fe; color: var(--color-status-brainstorm); }
261
+ .badge--considering { background: #fef3c7; color: var(--color-status-considering); }
262
+ .badge--developing { background: #dbeafe; color: var(--color-status-developing); }
263
+ .badge--live { background: #d1fae5; color: var(--color-status-live); }
264
+ .badge--abandoned { background: #f3f4f6; color: var(--color-status-abandoned); }
265
+
266
+ /* Forms */
267
+ .form-group {
268
+ margin-bottom: var(--space-lg);
269
+ }
270
+
271
+ .form-group label {
272
+ display: block;
273
+ font-size: var(--text-sm);
274
+ font-weight: 500;
275
+ margin-bottom: var(--space-xs);
276
+ }
277
+
278
+ .form-group input[type="text"],
279
+ .form-group input[type="email"],
280
+ .form-group input[type="url"],
281
+ .form-group textarea,
282
+ .form-group select {
283
+ width: 100%;
284
+ padding: var(--space-sm) var(--space-md);
285
+ font-size: var(--text-base);
286
+ font-family: var(--font-sans);
287
+ border: 1px solid var(--color-border);
288
+ border-radius: var(--radius);
289
+ background: var(--color-surface);
290
+ transition: border-color 0.15s;
291
+ }
292
+
293
+ .form-group input:focus,
294
+ .form-group textarea:focus,
295
+ .form-group select:focus {
296
+ outline: none;
297
+ border-color: var(--color-primary);
298
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
299
+ }
300
+
301
+ .form-group textarea {
302
+ min-height: 8rem;
303
+ resize: vertical;
304
+ }
305
+
306
+ /* Empty states */
307
+ .empty-state {
308
+ text-align: center;
309
+ padding: var(--space-2xl);
310
+ color: var(--color-text-muted);
311
+ }
312
+
313
+ .empty-state p {
314
+ margin-bottom: var(--space-md);
315
+ }
316
+
317
+ /* Sign in page */
318
+ .sign-in-page {
319
+ display: flex;
320
+ align-items: center;
321
+ justify-content: center;
322
+ min-height: 60vh;
323
+ }
324
+
325
+ .sign-in-card {
326
+ width: 100%;
327
+ max-width: 24rem;
328
+ text-align: center;
329
+ }
330
+
331
+ .sign-in-card h1 {
332
+ font-size: var(--text-2xl);
333
+ margin-bottom: var(--space-xs);
334
+ }
335
+
336
+ .sign-in-form {
337
+ margin-top: var(--space-sm);
338
+ text-align: left;
339
+ }
340
+
341
+ .sign-in-submit {
342
+ width: 100%;
343
+ justify-content: center;
344
+ }
345
+
346
+ /* Status filters */
347
+ .status-filters {
348
+ display: flex;
349
+ gap: var(--space-sm);
350
+ margin-bottom: var(--space-xl);
351
+ flex-wrap: wrap;
352
+ }
353
+
354
+ .status-filter {
355
+ padding: var(--space-xs) var(--space-md);
356
+ font-size: var(--text-sm);
357
+ font-weight: 500;
358
+ border-radius: 9999px;
359
+ color: var(--color-text-muted);
360
+ border: 1px solid var(--color-border);
361
+ text-decoration: none;
362
+ transition: all 0.15s;
363
+ }
364
+
365
+ .status-filter:hover {
366
+ text-decoration: none;
367
+ border-color: var(--color-text-muted);
368
+ }
369
+
370
+ .status-filter--active {
371
+ background: var(--color-primary);
372
+ color: #fff;
373
+ border-color: var(--color-primary);
374
+ }
375
+
376
+ /* Plans list */
377
+ .plans-list {
378
+ display: flex;
379
+ flex-direction: column;
380
+ gap: var(--space-md);
381
+ }
382
+
383
+ .plans-list__header {
384
+ display: flex;
385
+ align-items: center;
386
+ gap: var(--space-sm);
387
+ margin-bottom: var(--space-xs);
388
+ }
389
+
390
+ .plans-list__title {
391
+ font-size: var(--text-lg);
392
+ font-weight: 600;
393
+ color: var(--color-text);
394
+ }
395
+
396
+ .plans-list__title:hover {
397
+ color: var(--color-primary);
398
+ }
399
+
400
+ .plans-list__meta {
401
+ margin-top: var(--space-xs);
402
+ }
403
+
404
+ /* Plan form */
405
+ .plan-form__actions {
406
+ display: flex;
407
+ gap: var(--space-sm);
408
+ margin-top: var(--space-md);
409
+ }
410
+
411
+ /* Plan content */
412
+ .plan-content pre {
413
+ font-family: var(--font-mono);
414
+ font-size: var(--text-sm);
415
+ line-height: 1.7;
416
+ white-space: pre-wrap;
417
+ word-wrap: break-word;
418
+ }
419
+
420
+ /* Page header actions */
421
+ .page-header__actions {
422
+ display: flex;
423
+ gap: var(--space-sm);
424
+ }
425
+
426
+ /* Version list */
427
+ .versions-list {
428
+ display: flex;
429
+ flex-direction: column;
430
+ gap: var(--space-md);
431
+ }
432
+
433
+ .versions-list__header {
434
+ display: flex;
435
+ align-items: center;
436
+ gap: var(--space-sm);
437
+ margin-bottom: var(--space-xs);
438
+ }
439
+
440
+ .versions-list__link {
441
+ font-weight: 600;
442
+ font-size: var(--text-lg);
443
+ }
444
+
445
+ /* Diff view */
446
+ .diff-view {
447
+ font-family: var(--font-mono);
448
+ font-size: var(--text-sm);
449
+ line-height: 1.6;
450
+ margin-top: var(--space-md);
451
+ overflow-x: auto;
452
+ }
453
+
454
+ .diff-view ul {
455
+ list-style: none;
456
+ padding: 0;
457
+ }
458
+
459
+ .diff-view li {
460
+ padding: 1px var(--space-sm);
461
+ white-space: pre-wrap;
462
+ }
463
+
464
+ .diff-view li.ins {
465
+ background: #d4edda;
466
+ color: #155724;
467
+ }
468
+
469
+ .diff-view li.del {
470
+ background: #f8d7da;
471
+ color: #721c24;
472
+ }
473
+
474
+ /* Utility */
475
+ .text-muted { color: var(--color-text-muted); }
476
+ .text-sm { font-size: var(--text-sm); }
477
+ .mt-md { margin-top: var(--space-md); }
478
+ .mb-md { margin-bottom: var(--space-md); }
479
+
480
+ /* Plan view toggle */
481
+ .plan-view-toggle {
482
+ display: flex;
483
+ gap: var(--space-xs);
484
+ margin-bottom: var(--space-md);
485
+ padding-bottom: var(--space-md);
486
+ border-bottom: 1px solid var(--color-border);
487
+ }
488
+
489
+ /* Rendered markdown */
490
+ .markdown-rendered h1,
491
+ .markdown-rendered h2,
492
+ .markdown-rendered h3,
493
+ .markdown-rendered h4,
494
+ .markdown-rendered h5,
495
+ .markdown-rendered h6 {
496
+ margin-top: var(--space-xl);
497
+ margin-bottom: var(--space-md);
498
+ font-weight: 700;
499
+ line-height: 1.3;
500
+ }
501
+
502
+ .markdown-rendered h1 { font-size: var(--text-2xl); }
503
+ .markdown-rendered h2 { font-size: var(--text-xl); }
504
+ .markdown-rendered h3 { font-size: var(--text-lg); }
505
+ .markdown-rendered h1:first-child,
506
+ .markdown-rendered h2:first-child,
507
+ .markdown-rendered h3:first-child { margin-top: 0; }
508
+
509
+ .markdown-rendered p {
510
+ margin-bottom: var(--space-md);
511
+ line-height: 1.7;
512
+ }
513
+
514
+ .markdown-rendered ul,
515
+ .markdown-rendered ol {
516
+ margin-bottom: var(--space-md);
517
+ padding-left: var(--space-xl);
518
+ }
519
+
520
+ .markdown-rendered li {
521
+ margin-bottom: var(--space-xs);
522
+ line-height: 1.7;
523
+ }
524
+
525
+ .markdown-rendered pre {
526
+ background: #f6f8fa;
527
+ border: 1px solid var(--color-border);
528
+ border-radius: var(--radius);
529
+ padding: var(--space-md);
530
+ overflow-x: auto;
531
+ margin-bottom: var(--space-md);
532
+ font-family: var(--font-mono);
533
+ font-size: var(--text-sm);
534
+ line-height: 1.5;
535
+ }
536
+
537
+ .markdown-rendered code {
538
+ font-family: var(--font-mono);
539
+ font-size: 0.875em;
540
+ }
541
+
542
+ .markdown-rendered :not(pre) > code {
543
+ background: #f6f8fa;
544
+ padding: 0.15em 0.35em;
545
+ border-radius: 3px;
546
+ }
547
+
548
+ .markdown-rendered blockquote {
549
+ border-left: 3px solid var(--color-border);
550
+ padding-left: var(--space-md);
551
+ color: var(--color-text-muted);
552
+ margin-bottom: var(--space-md);
553
+ }
554
+
555
+ .markdown-rendered table {
556
+ width: 100%;
557
+ border-collapse: collapse;
558
+ margin-bottom: var(--space-md);
559
+ }
560
+
561
+ .markdown-rendered th,
562
+ .markdown-rendered td {
563
+ border: 1px solid var(--color-border);
564
+ padding: var(--space-sm) var(--space-md);
565
+ text-align: left;
566
+ }
567
+
568
+ .markdown-rendered th {
569
+ background: var(--color-bg);
570
+ font-weight: 600;
571
+ }
572
+
573
+ .markdown-rendered hr {
574
+ border: none;
575
+ border-top: 1px solid var(--color-border);
576
+ margin: var(--space-xl) 0;
577
+ }
578
+
579
+ .markdown-rendered a {
580
+ color: var(--color-primary);
581
+ }
582
+
583
+ .markdown-rendered img {
584
+ max-width: 100%;
585
+ border-radius: var(--radius);
586
+ }
587
+
588
+ /* Comment popover (appears on text selection) */
589
+ .comment-popover {
590
+ position: absolute;
591
+ z-index: 10;
592
+ animation: popover-fade-in 0.15s ease-out;
593
+ }
594
+
595
+ @keyframes popover-fade-in {
596
+ from { opacity: 0; transform: translateY(-4px); }
597
+ to { opacity: 1; transform: translateY(0); }
598
+ }
599
+
600
+ /* Anchor text highlights */
601
+ .anchor-highlight {
602
+ background: rgba(255, 213, 79, 0.3);
603
+ border-bottom: 2px solid rgba(255, 179, 0, 0.5);
604
+ cursor: pointer;
605
+ transition: background 0.2s;
606
+ }
607
+
608
+ .anchor-highlight:hover {
609
+ background: rgba(255, 213, 79, 0.5);
610
+ }
611
+
612
+ .anchor-highlight--active {
613
+ background: rgba(255, 179, 0, 0.4);
614
+ border-bottom: 2px solid var(--color-warning);
615
+ outline: 2px solid rgba(255, 179, 0, 0.3);
616
+ outline-offset: 1px;
617
+ }
618
+
619
+ /* Comment form anchor quote */
620
+ .comment-form__anchor {
621
+ margin-bottom: var(--space-sm);
622
+ }
623
+
624
+ .comment-form__quote {
625
+ border-left: 3px solid var(--color-warning);
626
+ padding: var(--space-xs) var(--space-sm);
627
+ margin: var(--space-xs) 0 0 0;
628
+ font-size: var(--text-sm);
629
+ color: var(--color-text-muted);
630
+ background: rgba(255, 213, 79, 0.1);
631
+ border-radius: 0 var(--radius) var(--radius) 0;
632
+ }
633
+
634
+ .comment-form__actions {
635
+ display: flex;
636
+ gap: var(--space-sm);
637
+ }
638
+
639
+ /* Thread anchor quote */
640
+ .comment-thread__anchor-quote {
641
+ border-left: 3px solid var(--color-warning);
642
+ padding: var(--space-xs) var(--space-sm);
643
+ margin: var(--space-xs) 0 0 0;
644
+ font-size: var(--text-sm);
645
+ color: var(--color-text-muted);
646
+ background: rgba(255, 213, 79, 0.08);
647
+ border-radius: 0 var(--radius) var(--radius) 0;
648
+ }
649
+
650
+ /* Plan layout (content + sidebar) */
651
+ .plan-layout {
652
+ position: relative;
653
+ }
654
+
655
+ .plan-layout__content {
656
+ max-width: 60%;
657
+ position: relative;
658
+ }
659
+
660
+ .plan-layout__sidebar {
661
+ position: absolute;
662
+ top: 0;
663
+ right: 0;
664
+ width: 22rem;
665
+ }
666
+
667
+ @media (max-width: 900px) {
668
+ .plan-layout__content {
669
+ max-width: 100%;
670
+ }
671
+
672
+ .plan-layout__sidebar {
673
+ position: static;
674
+ width: 100%;
675
+ margin-top: var(--space-lg);
676
+ }
677
+ }
678
+ .sidebar-heading {
679
+ font-size: var(--text-lg);
680
+ font-weight: 700;
681
+ margin-bottom: var(--space-md);
682
+ }
683
+
684
+ /* Comment tabs */
685
+ .comment-tabs__nav {
686
+ display: flex;
687
+ gap: 0;
688
+ border-bottom: 2px solid var(--color-border);
689
+ margin-bottom: var(--space-md);
690
+ }
691
+
692
+ .comment-tab {
693
+ padding: var(--space-xs) var(--space-md);
694
+ font-size: var(--text-sm);
695
+ font-weight: 600;
696
+ color: var(--color-text-muted);
697
+ background: none;
698
+ border: none;
699
+ border-bottom: 2px solid transparent;
700
+ margin-bottom: -2px;
701
+ cursor: pointer;
702
+ }
703
+
704
+ .comment-tab:hover {
705
+ color: var(--color-text);
706
+ }
707
+
708
+ .comment-tab--active {
709
+ color: var(--color-primary);
710
+ border-bottom-color: var(--color-primary);
711
+ }
712
+
713
+ .comment-tab__count {
714
+ background: var(--color-border);
715
+ color: var(--color-text-muted);
716
+ font-size: 0.7rem;
717
+ padding: 1px 6px;
718
+ border-radius: 10px;
719
+ margin-left: 4px;
720
+ }
721
+
722
+ .comment-tab--active .comment-tab__count {
723
+ background: var(--color-primary);
724
+ color: white;
725
+ }
726
+
727
+ /* Comment form */
728
+ .comment-form {
729
+ margin-bottom: var(--space-md);
730
+ padding: var(--space-md);
731
+ }
732
+
733
+ .comment-form .form-group {
734
+ margin-bottom: var(--space-sm);
735
+ }
736
+
737
+ .comment-form textarea {
738
+ width: 100%;
739
+ padding: var(--space-sm);
740
+ font-family: var(--font-sans);
741
+ font-size: var(--text-sm);
742
+ border: 1px solid var(--color-border);
743
+ border-radius: var(--radius);
744
+ resize: vertical;
745
+ min-height: 4rem;
746
+ }
747
+
748
+ .comment-form textarea:focus {
749
+ outline: none;
750
+ border-color: var(--color-primary);
751
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
752
+ }
753
+
754
+ /* Comment threads list */
755
+ .comment-threads-list {
756
+ display: flex;
757
+ flex-direction: column;
758
+ gap: var(--space-md);
759
+ }
760
+
761
+ /* Comment thread */
762
+ .comment-thread {
763
+ padding: var(--space-md);
764
+ }
765
+
766
+ .comment-thread__header {
767
+ margin-bottom: var(--space-sm);
768
+ }
769
+
770
+ .comment-thread__meta {
771
+ display: flex;
772
+ gap: var(--space-xs);
773
+ flex-wrap: wrap;
774
+ align-items: center;
775
+ }
776
+
777
+ .comment-thread__comments {
778
+ display: flex;
779
+ flex-direction: column;
780
+ gap: var(--space-sm);
781
+ }
782
+
783
+ /* Individual comment */
784
+ .comment {
785
+ padding: var(--space-sm) 0;
786
+ border-bottom: 1px solid var(--color-border);
787
+ }
788
+
789
+ .comment:last-child {
790
+ border-bottom: none;
791
+ }
792
+
793
+ .comment__header {
794
+ margin-bottom: var(--space-xs);
795
+ }
796
+
797
+ .comment__body .markdown-rendered {
798
+ font-size: var(--text-sm);
799
+ }
800
+
801
+ .comment__body .markdown-rendered p:last-child {
802
+ margin-bottom: 0;
803
+ }
804
+
805
+ /* Comment thread reply */
806
+ .comment-thread__reply {
807
+ margin-top: var(--space-sm);
808
+ padding-top: var(--space-sm);
809
+ border-top: 1px solid var(--color-border);
810
+ }
811
+
812
+ .comment-thread__reply textarea {
813
+ width: 100%;
814
+ padding: var(--space-sm);
815
+ font-family: var(--font-sans);
816
+ font-size: var(--text-sm);
817
+ border: 1px solid var(--color-border);
818
+ border-radius: var(--radius);
819
+ resize: vertical;
820
+ min-height: 3rem;
821
+ }
822
+
823
+ .comment-thread__reply textarea:focus {
824
+ outline: none;
825
+ border-color: var(--color-primary);
826
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
827
+ }
828
+
829
+ .comment-thread__reply .form-group {
830
+ margin-bottom: var(--space-xs);
831
+ }
832
+
833
+ /* Comment thread actions */
834
+ .comment-thread__actions {
835
+ display: flex;
836
+ gap: var(--space-xs);
837
+ margin-top: var(--space-sm);
838
+ padding-top: var(--space-sm);
839
+ border-top: 1px solid var(--color-border);
840
+ }
841
+
842
+ /* Small button variant */
843
+ .btn--sm {
844
+ padding: var(--space-xs) var(--space-sm);
845
+ font-size: 0.75rem;
846
+ }
847
+
848
+ /* Token reveal */
849
+ .token-reveal {
850
+ background: var(--color-success);
851
+ color: white;
852
+ padding: var(--space-lg);
853
+ border-radius: var(--radius);
854
+ margin-bottom: var(--space-lg);
855
+ }
856
+
857
+ .token-reveal h3 {
858
+ margin: 0 0 var(--space-xs) 0;
859
+ }
860
+
861
+ .token-reveal p {
862
+ margin: 0 0 var(--space-sm) 0;
863
+ opacity: 0.9;
864
+ }
865
+
866
+ .token-reveal__value {
867
+ background: rgba(0, 0, 0, 0.2);
868
+ padding: var(--space-sm) var(--space-md);
869
+ border-radius: var(--radius);
870
+ font-family: var(--font-mono);
871
+ font-size: var(--text-sm);
872
+ word-break: break-all;
873
+ user-select: all;
874
+ }
875
+
876
+ .token-reveal__value code {
877
+ color: white;
878
+ background: none;
879
+ }
880
+
881
+ /* Data table */
882
+ .data-table {
883
+ width: 100%;
884
+ border-collapse: collapse;
885
+ }
886
+
887
+ .data-table th,
888
+ .data-table td {
889
+ padding: var(--space-sm) var(--space-md);
890
+ text-align: left;
891
+ border-bottom: 1px solid var(--color-border);
892
+ }
893
+
894
+ .data-table th {
895
+ font-weight: 600;
896
+ color: var(--color-text-muted);
897
+ font-size: var(--text-sm);
898
+ }
899
+
900
+ .data-table__row--muted td {
901
+ opacity: 0.5;
902
+ }
903
+
904
+ /* Form inline */
905
+ .form-inline {
906
+ display: flex;
907
+ align-items: flex-end;
908
+ gap: var(--space-md);
909
+ flex-wrap: wrap;
910
+ }
911
+
912
+ .form-inline .form-group {
913
+ flex: 1;
914
+ min-width: 200px;
915
+ }
916
+
917
+ /* Dropdown */
918
+ .dropdown {
919
+ position: relative;
920
+ display: inline-block;
921
+ }
922
+
923
+ .dropdown__menu {
924
+ position: absolute;
925
+ right: 0;
926
+ top: 100%;
927
+ margin-top: var(--space-xs);
928
+ background: var(--color-bg);
929
+ border: 1px solid var(--color-border);
930
+ border-radius: var(--radius);
931
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
932
+ min-width: 200px;
933
+ z-index: 100;
934
+ }
935
+
936
+ .dropdown__item {
937
+ display: block;
938
+ width: 100%;
939
+ padding: var(--space-sm) var(--space-md);
940
+ text-align: left;
941
+ background: none;
942
+ border: none;
943
+ cursor: pointer;
944
+ font-size: var(--font-sm);
945
+ color: var(--color-text);
946
+ }
947
+
948
+ .dropdown__item:hover {
949
+ background: var(--color-bg-muted);
950
+ }
951
+
952
+ /* Page header */
953
+ .page-header__subtitle {
954
+ color: var(--color-text-muted);
955
+ margin-top: var(--space-xs);
956
+ }