source_monitor 0.13.1 → 0.14.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/.claude/skills/sm-configuration-setting/reference/settings-catalog.md +1 -0
  3. data/.claude/skills/sm-configure/SKILL.md +8 -1
  4. data/.claude/skills/sm-configure/reference/configuration-reference.md +11 -0
  5. data/.claude/skills/sm-host-setup/SKILL.md +13 -3
  6. data/.claude/skills/sm-host-setup/reference/initializer-template.md +11 -0
  7. data/.claude/skills/sm-host-setup/reference/setup-checklist.md +9 -1
  8. data/.claude/skills/sm-upgrade/reference/version-history.md +12 -0
  9. data/CHANGELOG.md +15 -0
  10. data/Gemfile.lock +1 -1
  11. data/README.md +3 -3
  12. data/VERSION +1 -1
  13. data/app/controllers/source_monitor/application_controller.rb +73 -14
  14. data/app/views/layouts/source_monitor/application.html.erb +6 -0
  15. data/docs/configuration.md +18 -1
  16. data/docs/deployment.md +1 -1
  17. data/docs/goals/engine-hardening/.goalbuddy-board/app.js +543 -0
  18. data/docs/goals/engine-hardening/.goalbuddy-board/goalbuddy-mark.png +0 -0
  19. data/docs/goals/engine-hardening/.goalbuddy-board/index.html +111 -0
  20. data/docs/goals/engine-hardening/.goalbuddy-board/styles.css +991 -0
  21. data/docs/goals/engine-hardening/goal.md +97 -0
  22. data/docs/goals/engine-hardening/notes/T001-spec-validation.md +37 -0
  23. data/docs/goals/engine-hardening/state.yaml +324 -0
  24. data/docs/setup.md +3 -3
  25. data/docs/upgrade.md +27 -0
  26. data/lib/generators/source_monitor/install/templates/source_monitor.rb.tt +10 -0
  27. data/lib/source_monitor/configuration/authentication_settings.rb +5 -1
  28. data/lib/source_monitor/security/authentication.rb +10 -0
  29. data/lib/source_monitor/version.rb +1 -1
  30. data/source_monitor.gemspec +7 -2
  31. metadata +8 -65
  32. data/.claude/agent-memory/vbw-vbw-debugger/MEMORY.md +0 -15
  33. data/.claude/agent-memory/vbw-vbw-dev/MEMORY.md +0 -34
  34. data/.claude/agent-memory/vbw-vbw-lead/MEMORY.md +0 -49
  35. data/.claude/agents/rails-concern.md +0 -464
  36. data/.claude/agents/rails-controller.md +0 -424
  37. data/.claude/agents/rails-hotwire.md +0 -446
  38. data/.claude/agents/rails-implement.md +0 -374
  39. data/.claude/agents/rails-job.md +0 -334
  40. data/.claude/agents/rails-lint.md +0 -294
  41. data/.claude/agents/rails-mailer.md +0 -371
  42. data/.claude/agents/rails-migration.md +0 -449
  43. data/.claude/agents/rails-model.md +0 -420
  44. data/.claude/agents/rails-policy.md +0 -443
  45. data/.claude/agents/rails-presenter.md +0 -427
  46. data/.claude/agents/rails-query.md +0 -412
  47. data/.claude/agents/rails-review.md +0 -490
  48. data/.claude/agents/rails-service.md +0 -458
  49. data/.claude/agents/rails-state-records.md +0 -465
  50. data/.claude/agents/rails-tdd.md +0 -314
  51. data/.claude/agents/rails-test.md +0 -441
  52. data/.claude/agents/rails-view-component.md +0 -418
  53. data/.claude/commands/rails-audit.md +0 -77
  54. data/.claude/commands/release.md +0 -366
  55. data/.claude/hooks/block-secrets.sh +0 -52
  56. data/.claude/settings.json +0 -85
  57. data/.claude/skills/action-cable-patterns/SKILL.md +0 -296
  58. data/.claude/skills/action-mailer-patterns/SKILL.md +0 -295
  59. data/.claude/skills/active-storage-setup/SKILL.md +0 -311
  60. data/.claude/skills/api-versioning/SKILL.md +0 -294
  61. data/.claude/skills/authentication-flow/SKILL.md +0 -335
  62. data/.claude/skills/authentication-flow/reference/current.md +0 -248
  63. data/.claude/skills/authentication-flow/reference/passwordless.md +0 -253
  64. data/.claude/skills/authentication-flow/reference/sessions.md +0 -201
  65. data/.claude/skills/authorization-pundit/SKILL.md +0 -462
  66. data/.claude/skills/caching-strategies/SKILL.md +0 -350
  67. data/.claude/skills/database-migrations/SKILL.md +0 -354
  68. data/.claude/skills/form-object-patterns/SKILL.md +0 -399
  69. data/.claude/skills/hotwire-patterns/SKILL.md +0 -247
  70. data/.claude/skills/hotwire-patterns/reference/stimulus.md +0 -307
  71. data/.claude/skills/hotwire-patterns/reference/tailwind-integration.md +0 -112
  72. data/.claude/skills/hotwire-patterns/reference/turbo-frames.md +0 -158
  73. data/.claude/skills/hotwire-patterns/reference/turbo-streams.md +0 -218
  74. data/.claude/skills/i18n-patterns/SKILL.md +0 -320
  75. data/.claude/skills/install/SKILL.md +0 -367
  76. data/.claude/skills/performance-optimization/SKILL.md +0 -311
  77. data/.claude/skills/rails-architecture/SKILL.md +0 -259
  78. data/.claude/skills/rails-architecture/reference/error-handling.md +0 -333
  79. data/.claude/skills/rails-architecture/reference/event-tracking.md +0 -142
  80. data/.claude/skills/rails-architecture/reference/layer-interactions.md +0 -417
  81. data/.claude/skills/rails-architecture/reference/multi-tenancy.md +0 -152
  82. data/.claude/skills/rails-architecture/reference/query-patterns.md +0 -342
  83. data/.claude/skills/rails-architecture/reference/service-patterns.md +0 -286
  84. data/.claude/skills/rails-architecture/reference/state-records.md +0 -250
  85. data/.claude/skills/rails-architecture/reference/testing-strategy.md +0 -326
  86. data/.claude/skills/rails-concern/SKILL.md +0 -399
  87. data/.claude/skills/rails-controller/SKILL.md +0 -336
  88. data/.claude/skills/rails-model-generator/SKILL.md +0 -321
  89. data/.claude/skills/rails-model-generator/reference/validations.md +0 -298
  90. data/.claude/skills/rails-presenter/SKILL.md +0 -274
  91. data/.claude/skills/rails-query-object/SKILL.md +0 -289
  92. data/.claude/skills/rails-service-object/SKILL.md +0 -349
  93. data/.claude/skills/solid-queue-setup/SKILL.md +0 -307
  94. data/.claude/skills/tdd-cycle/SKILL.md +0 -359
  95. data/.claude/skills/viewcomponent-patterns/SKILL.md +0 -333
@@ -0,0 +1,991 @@
1
+ :root {
2
+ color-scheme: light;
3
+ --canvas: #f7f6f3;
4
+ --surface: #ffffff;
5
+ --surface-muted: #fbfbfa;
6
+ --ink: #111111;
7
+ --muted: #787774;
8
+ --line: #eaeaea;
9
+ --blue-bg: #e1f3fe;
10
+ --blue-text: #1f6c9f;
11
+ --green-bg: #edf3ec;
12
+ --green-text: #346538;
13
+ --red-bg: #fdebec;
14
+ --red-text: #9f2f2d;
15
+ --yellow-bg: #fbf3db;
16
+ --yellow-text: #956400;
17
+ --active-surface: #fbfdfe;
18
+ font-family: "SF Pro Display", "Geist Sans", "Helvetica Neue", Arial, sans-serif;
19
+ }
20
+
21
+ :root[data-theme="dark"] {
22
+ color-scheme: dark;
23
+ --canvas: #07101f;
24
+ --surface: #101a2d;
25
+ --surface-muted: #0c1525;
26
+ --ink: #f7f9fc;
27
+ --muted: #9aa7bf;
28
+ --line: #26334a;
29
+ --blue-bg: #173653;
30
+ --blue-text: #9ed8ff;
31
+ --green-bg: #143929;
32
+ --green-text: #a6e8bf;
33
+ --red-bg: #3a1d22;
34
+ --red-text: #ffb2b9;
35
+ --yellow-bg: #3a3014;
36
+ --yellow-text: #f6d878;
37
+ --active-surface: #0f2031;
38
+ }
39
+
40
+ @media (prefers-color-scheme: dark) {
41
+ :root[data-theme="system"] {
42
+ color-scheme: dark;
43
+ --canvas: #07101f;
44
+ --surface: #101a2d;
45
+ --surface-muted: #0c1525;
46
+ --ink: #f7f9fc;
47
+ --muted: #9aa7bf;
48
+ --line: #26334a;
49
+ --blue-bg: #173653;
50
+ --blue-text: #9ed8ff;
51
+ --green-bg: #143929;
52
+ --green-text: #a6e8bf;
53
+ --red-bg: #3a1d22;
54
+ --red-text: #ffb2b9;
55
+ --yellow-bg: #3a3014;
56
+ --yellow-text: #f6d878;
57
+ --active-surface: #0f2031;
58
+ }
59
+
60
+ :root[data-theme="system"] .topbar {
61
+ border-color: rgba(61, 76, 108, 0.86);
62
+ background: rgba(13, 23, 41, 0.84);
63
+ box-shadow: 0 18px 48px rgba(0, 0, 0, 0.28);
64
+ }
65
+
66
+ :root[data-theme="system"] .brand {
67
+ color: var(--ink);
68
+ }
69
+
70
+ :root[data-theme="system"] .board-switcher select,
71
+ :root[data-theme="system"] .github-stars,
72
+ :root[data-theme="system"] .settings-button {
73
+ border-color: rgba(61, 76, 108, 0.9);
74
+ background: rgba(16, 26, 45, 0.78);
75
+ color: var(--ink);
76
+ }
77
+
78
+ :root[data-theme="system"] .settings-popover {
79
+ border-color: rgba(61, 76, 108, 0.96);
80
+ background: rgba(16, 26, 45, 0.96);
81
+ box-shadow: 0 24px 64px rgba(0, 0, 0, 0.28);
82
+ }
83
+
84
+ :root[data-theme="system"] .setting-row select {
85
+ background: var(--surface);
86
+ color: var(--ink);
87
+ }
88
+
89
+ :root[data-theme="system"] .goal-tranche,
90
+ :root[data-theme="system"] .task-title,
91
+ :root[data-theme="system"] .setting-row select {
92
+ color: var(--ink);
93
+ }
94
+
95
+ :root[data-theme="system"] .task-card.is-active {
96
+ background: linear-gradient(var(--active-surface), var(--active-surface)) padding-box,
97
+ linear-gradient(110deg, #78d7ff, #6c63ff, #78f2b9, #78d7ff) border-box;
98
+ }
99
+
100
+ :root[data-theme="system"] .task-card.is-active::after {
101
+ background: var(--active-surface);
102
+ }
103
+ }
104
+
105
+ * { box-sizing: border-box; }
106
+
107
+ body {
108
+ margin: 0;
109
+ min-height: 100vh;
110
+ background: var(--canvas);
111
+ color: var(--ink);
112
+ }
113
+
114
+ button,
115
+ input,
116
+ textarea {
117
+ font: inherit;
118
+ }
119
+
120
+ a {
121
+ color: inherit;
122
+ text-decoration: none;
123
+ }
124
+
125
+ select,
126
+ button {
127
+ font: inherit;
128
+ }
129
+
130
+ .topbar {
131
+ position: sticky;
132
+ top: 16px;
133
+ z-index: 10;
134
+ display: flex;
135
+ align-items: center;
136
+ justify-content: space-between;
137
+ gap: 16px;
138
+ width: min(1392px, calc(100% - 48px));
139
+ min-height: 64px;
140
+ margin: 0 auto;
141
+ padding: 10px 12px 10px 18px;
142
+ border: 1px solid rgba(219, 226, 240, 0.86);
143
+ border-radius: 999px;
144
+ background: rgba(255, 255, 255, 0.78);
145
+ box-shadow: 0 18px 48px rgba(30, 40, 72, 0.1);
146
+ backdrop-filter: blur(22px);
147
+ }
148
+
149
+ :root[data-theme="dark"] .topbar {
150
+ border-color: rgba(61, 76, 108, 0.86);
151
+ background: rgba(13, 23, 41, 0.84);
152
+ box-shadow: 0 18px 48px rgba(0, 0, 0, 0.28);
153
+ }
154
+
155
+ .topbar-primary {
156
+ display: inline-flex;
157
+ align-items: center;
158
+ gap: 24px;
159
+ min-width: 0;
160
+ }
161
+
162
+ .brand {
163
+ display: inline-flex;
164
+ align-items: center;
165
+ gap: 10px;
166
+ color: #071236;
167
+ font-weight: 800;
168
+ min-width: fit-content;
169
+ }
170
+
171
+ :root[data-theme="dark"] .brand {
172
+ color: var(--ink);
173
+ }
174
+
175
+ .brand-mark {
176
+ display: block;
177
+ width: 38px;
178
+ height: 38px;
179
+ filter: drop-shadow(0 8px 13px rgba(87, 76, 210, 0.18));
180
+ }
181
+
182
+ .brand-name {
183
+ font-size: 18px;
184
+ letter-spacing: 0;
185
+ }
186
+
187
+ .board-switcher {
188
+ display: flex;
189
+ align-items: center;
190
+ justify-content: flex-start;
191
+ gap: 8px;
192
+ min-width: 0;
193
+ }
194
+
195
+ .board-switcher label {
196
+ color: var(--muted);
197
+ font-size: 11px;
198
+ font-weight: 700;
199
+ letter-spacing: 0.08em;
200
+ text-transform: uppercase;
201
+ }
202
+
203
+ .board-switcher select {
204
+ width: min(280px, 100%);
205
+ min-width: 0;
206
+ min-height: 38px;
207
+ border: 1px solid rgba(219, 226, 240, 0.9);
208
+ border-radius: 999px;
209
+ padding: 0 34px 0 14px;
210
+ background: rgba(255, 255, 255, 0.72);
211
+ color: #2f3c59;
212
+ font-weight: 700;
213
+ font-size: 14px;
214
+ }
215
+
216
+ :root[data-theme="dark"] .board-switcher select,
217
+ :root[data-theme="dark"] .github-stars,
218
+ :root[data-theme="dark"] .settings-button {
219
+ border-color: rgba(61, 76, 108, 0.9);
220
+ background: rgba(16, 26, 45, 0.78);
221
+ color: var(--ink);
222
+ }
223
+
224
+ .board-switcher.is-empty {
225
+ display: none;
226
+ }
227
+
228
+ .header-tools {
229
+ display: inline-flex;
230
+ align-items: center;
231
+ justify-content: flex-end;
232
+ gap: 10px;
233
+ min-width: fit-content;
234
+ }
235
+
236
+ .github-stars,
237
+ .settings-button {
238
+ display: inline-flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ min-height: 44px;
242
+ border: 1px solid rgba(219, 226, 240, 0.9);
243
+ border-radius: 999px;
244
+ background: rgba(255, 255, 255, 0.72);
245
+ color: #2f3c59;
246
+ font-weight: 800;
247
+ transition: transform 180ms ease, color 180ms ease, border-color 180ms ease, background 180ms ease;
248
+ }
249
+
250
+ .github-stars {
251
+ gap: 7px;
252
+ padding: 0 15px;
253
+ font-size: 14px;
254
+ white-space: nowrap;
255
+ }
256
+
257
+ .github-stars:hover,
258
+ .settings-button:hover {
259
+ transform: translateY(-2px);
260
+ color: #071236;
261
+ border-color: rgba(79, 70, 216, 0.26);
262
+ background: #fff;
263
+ }
264
+
265
+ .github-stars svg {
266
+ width: 16px;
267
+ height: 16px;
268
+ color: #4f46d8;
269
+ fill: currentColor;
270
+ }
271
+
272
+ .settings-wrap {
273
+ position: relative;
274
+ }
275
+
276
+ .settings-button {
277
+ position: relative;
278
+ gap: 8px;
279
+ width: 44px;
280
+ padding: 0;
281
+ cursor: pointer;
282
+ }
283
+
284
+ .settings-button svg {
285
+ width: 18px;
286
+ height: 18px;
287
+ fill: none;
288
+ stroke: currentColor;
289
+ stroke-width: 1.8;
290
+ stroke-linejoin: round;
291
+ }
292
+
293
+ .live-dot {
294
+ width: 8px;
295
+ height: 8px;
296
+ border: 2px solid #fff;
297
+ border-radius: 999px;
298
+ background: #1f9d69;
299
+ box-shadow: 0 0 0 4px rgba(31, 157, 105, 0.12);
300
+ }
301
+
302
+ .live-dot.offline {
303
+ background: var(--yellow-text);
304
+ box-shadow: 0 0 0 4px rgba(149, 100, 0, 0.12);
305
+ }
306
+
307
+ .settings-popover {
308
+ position: absolute;
309
+ top: calc(100% + 10px);
310
+ right: 0;
311
+ width: min(320px, calc(100vw - 32px));
312
+ padding: 16px;
313
+ border: 1px solid rgba(219, 226, 240, 0.96);
314
+ border-radius: 18px;
315
+ background: rgba(255, 255, 255, 0.96);
316
+ box-shadow: 0 24px 64px rgba(30, 40, 72, 0.16);
317
+ backdrop-filter: blur(20px);
318
+ }
319
+
320
+ :root[data-theme="dark"] .settings-popover {
321
+ border-color: rgba(61, 76, 108, 0.96);
322
+ background: rgba(16, 26, 45, 0.96);
323
+ box-shadow: 0 24px 64px rgba(0, 0, 0, 0.28);
324
+ }
325
+
326
+ .settings-popover[hidden] {
327
+ display: none;
328
+ }
329
+
330
+ .settings-heading {
331
+ margin-bottom: 12px;
332
+ }
333
+
334
+ .settings-heading .eyebrow {
335
+ margin-bottom: 6px;
336
+ }
337
+
338
+ .settings-heading h2 {
339
+ margin: 0;
340
+ font-size: 20px;
341
+ letter-spacing: 0;
342
+ }
343
+
344
+ .setting-row {
345
+ display: grid;
346
+ gap: 6px;
347
+ margin-top: 12px;
348
+ }
349
+
350
+ .setting-row label {
351
+ color: var(--muted);
352
+ font-size: 12px;
353
+ font-weight: 800;
354
+ }
355
+
356
+ .setting-row select {
357
+ min-height: 38px;
358
+ border: 1px solid var(--line);
359
+ border-radius: 8px;
360
+ padding: 0 10px;
361
+ background: #fff;
362
+ color: #2f3437;
363
+ }
364
+
365
+ :root[data-theme="dark"] .setting-row select {
366
+ background: var(--surface);
367
+ color: var(--ink);
368
+ }
369
+
370
+ .visually-hidden {
371
+ position: absolute;
372
+ width: 1px;
373
+ height: 1px;
374
+ overflow: hidden;
375
+ clip: rect(0 0 0 0);
376
+ white-space: nowrap;
377
+ }
378
+
379
+ .badge {
380
+ display: inline-flex;
381
+ align-items: center;
382
+ width: fit-content;
383
+ border-radius: 999px;
384
+ padding: 4px 8px;
385
+ font-size: 11px;
386
+ font-weight: 700;
387
+ letter-spacing: 0.05em;
388
+ text-transform: uppercase;
389
+ background: var(--blue-bg);
390
+ color: var(--blue-text);
391
+ }
392
+
393
+ .live-state.offline {
394
+ background: var(--yellow-bg);
395
+ color: var(--yellow-text);
396
+ }
397
+
398
+ .shell {
399
+ width: min(1440px, 100%);
400
+ margin: 0 auto;
401
+ padding: 28px 24px 40px;
402
+ }
403
+
404
+ .goal-header {
405
+ display: grid;
406
+ grid-template-columns: minmax(0, 1fr) auto;
407
+ gap: 24px;
408
+ align-items: end;
409
+ padding: 8px 0 24px;
410
+ border-bottom: 1px solid var(--line);
411
+ }
412
+
413
+ .eyebrow {
414
+ margin: 0 0 8px;
415
+ color: var(--muted);
416
+ font-size: 11px;
417
+ font-weight: 700;
418
+ letter-spacing: 0.08em;
419
+ text-transform: uppercase;
420
+ }
421
+
422
+ h1,
423
+ h2,
424
+ h3,
425
+ p {
426
+ margin-top: 0;
427
+ }
428
+
429
+ h1 {
430
+ margin-bottom: 10px;
431
+ max-width: 900px;
432
+ font-size: clamp(34px, 5vw, 68px);
433
+ line-height: 0.95;
434
+ letter-spacing: 0;
435
+ }
436
+
437
+ .goal-tranche {
438
+ max-width: 860px;
439
+ margin-bottom: 0;
440
+ color: #2f3437;
441
+ line-height: 1.55;
442
+ }
443
+
444
+ :root[data-theme="dark"] .goal-tranche,
445
+ :root[data-theme="dark"] .task-title,
446
+ :root[data-theme="dark"] .setting-row select {
447
+ color: var(--ink);
448
+ }
449
+
450
+ .goal-meta {
451
+ display: grid;
452
+ grid-template-columns: repeat(3, minmax(94px, auto));
453
+ gap: 1px;
454
+ overflow: hidden;
455
+ margin: 0;
456
+ border: 1px solid var(--line);
457
+ border-radius: 8px;
458
+ background: var(--line);
459
+ }
460
+
461
+ .goal-meta div {
462
+ min-width: 0;
463
+ padding: 12px 14px;
464
+ background: var(--surface);
465
+ }
466
+
467
+ .goal-meta dt {
468
+ margin-bottom: 6px;
469
+ color: var(--muted);
470
+ font-size: 11px;
471
+ text-transform: uppercase;
472
+ letter-spacing: 0.05em;
473
+ }
474
+
475
+ .goal-meta dd {
476
+ margin: 0;
477
+ max-width: 180px;
478
+ overflow: hidden;
479
+ text-overflow: ellipsis;
480
+ white-space: nowrap;
481
+ font-size: 14px;
482
+ }
483
+
484
+ .board {
485
+ display: grid;
486
+ grid-template-columns: repeat(4, minmax(0, 1fr));
487
+ gap: 16px;
488
+ padding-top: 18px;
489
+ }
490
+
491
+ .column {
492
+ min-width: 0;
493
+ border: 1px solid var(--line);
494
+ border-radius: 8px;
495
+ background: var(--surface-muted);
496
+ }
497
+
498
+ .column-header {
499
+ display: flex;
500
+ align-items: start;
501
+ justify-content: space-between;
502
+ gap: 12px;
503
+ padding: 16px;
504
+ border-bottom: 1px solid var(--line);
505
+ }
506
+
507
+ .column-header h2 {
508
+ margin: 0 0 4px;
509
+ font-size: 16px;
510
+ line-height: 1.2;
511
+ }
512
+
513
+ .column-header p {
514
+ margin: 0;
515
+ color: var(--muted);
516
+ font-size: 13px;
517
+ line-height: 1.4;
518
+ }
519
+
520
+ .column-count {
521
+ color: var(--muted);
522
+ font-family: "Geist Mono", "SF Mono", monospace;
523
+ font-size: 13px;
524
+ }
525
+
526
+ .card-list {
527
+ display: grid;
528
+ gap: 10px;
529
+ padding: 12px;
530
+ }
531
+
532
+ .task-card {
533
+ position: relative;
534
+ width: 100%;
535
+ min-height: 138px;
536
+ display: flex;
537
+ flex-direction: column;
538
+ gap: 12px;
539
+ padding: 14px;
540
+ border: 1px solid var(--line);
541
+ border-radius: 8px;
542
+ background: var(--surface);
543
+ color: inherit;
544
+ text-align: left;
545
+ cursor: pointer;
546
+ overflow: hidden;
547
+ transition: transform 160ms ease, border-color 160ms ease;
548
+ will-change: transform, opacity;
549
+ }
550
+
551
+ .task-card > * {
552
+ position: relative;
553
+ z-index: 1;
554
+ }
555
+
556
+ .task-card:hover {
557
+ border-color: #d1d0cc;
558
+ transform: translateY(-1px);
559
+ }
560
+
561
+ .task-card:focus-visible,
562
+ .icon-button:focus-visible {
563
+ outline: 2px solid #2f3437;
564
+ outline-offset: 2px;
565
+ }
566
+
567
+ .task-card.is-active {
568
+ border-color: transparent;
569
+ background: linear-gradient(#fbfdfe, #fbfdfe) padding-box,
570
+ linear-gradient(110deg, #78d7ff, #4f46d8, #78f2b9, #78d7ff) border-box;
571
+ box-shadow: 0 14px 38px rgba(31, 108, 159, 0.12);
572
+ }
573
+
574
+ .task-card.is-active::before {
575
+ position: absolute;
576
+ inset: -2px;
577
+ z-index: 0;
578
+ content: "";
579
+ background: conic-gradient(from 0deg, transparent 0 58%, rgba(79, 70, 216, 0.28), rgba(120, 215, 255, 0.44), transparent 78% 100%);
580
+ opacity: 0.86;
581
+ animation: active-card-orbit 2.8s linear infinite;
582
+ }
583
+
584
+ .task-card.is-active::after {
585
+ position: absolute;
586
+ inset: 2px;
587
+ z-index: 0;
588
+ content: "";
589
+ border-radius: 6px;
590
+ background: #fbfdfe;
591
+ }
592
+
593
+ :root[data-theme="dark"] .task-card.is-active {
594
+ background: linear-gradient(var(--active-surface), var(--active-surface)) padding-box,
595
+ linear-gradient(110deg, #78d7ff, #6c63ff, #78f2b9, #78d7ff) border-box;
596
+ }
597
+
598
+ :root[data-theme="dark"] .task-card.is-active::after {
599
+ background: var(--active-surface);
600
+ }
601
+
602
+ :root[data-density="compact"] .shell {
603
+ padding-top: 20px;
604
+ }
605
+
606
+ :root[data-density="compact"] .board {
607
+ gap: 12px;
608
+ }
609
+
610
+ :root[data-density="compact"] .column-header {
611
+ padding: 12px;
612
+ }
613
+
614
+ :root[data-density="compact"] .card-list {
615
+ gap: 8px;
616
+ padding: 10px;
617
+ }
618
+
619
+ :root[data-density="compact"] .task-card {
620
+ min-height: 110px;
621
+ gap: 9px;
622
+ padding: 11px;
623
+ }
624
+
625
+ :root[data-density="compact"] .task-title {
626
+ font-size: 14px;
627
+ }
628
+
629
+ :root[data-completed-visibility="collapse"] .column[data-column-id="completed"] .card-list {
630
+ display: none;
631
+ }
632
+
633
+ :root[data-completed-visibility="collapse"] .column[data-column-id="completed"] {
634
+ max-height: 80px;
635
+ overflow: hidden;
636
+ }
637
+
638
+ @keyframes active-card-orbit {
639
+ to { transform: rotate(360deg); }
640
+ }
641
+
642
+ .task-card.is-moving {
643
+ border-color: #c2b8ff;
644
+ }
645
+
646
+ .card-topline {
647
+ display: flex;
648
+ align-items: center;
649
+ justify-content: space-between;
650
+ gap: 8px;
651
+ }
652
+
653
+ .task-id {
654
+ color: var(--muted);
655
+ font-family: "Geist Mono", "SF Mono", monospace;
656
+ font-size: 12px;
657
+ }
658
+
659
+ .task-title {
660
+ margin: 0;
661
+ color: #2f3437;
662
+ font-size: 15px;
663
+ line-height: 1.35;
664
+ }
665
+
666
+ .card-footer {
667
+ display: flex;
668
+ flex-wrap: wrap;
669
+ gap: 6px;
670
+ margin-top: auto;
671
+ }
672
+
673
+ .badge.status-active,
674
+ .badge.status-queued { background: var(--blue-bg); color: var(--blue-text); }
675
+ .badge.status-done { background: var(--green-bg); color: var(--green-text); }
676
+ .badge.status-blocked { background: var(--red-bg); color: var(--red-text); }
677
+ .badge.role { background: var(--yellow-bg); color: var(--yellow-text); }
678
+ .badge.subgoal { background: #ece8ff; color: #5c43c6; }
679
+ .badge.subgoal.status-blocked { background: var(--red-bg); color: var(--red-text); }
680
+ .badge.subgoal.status-done { background: var(--green-bg); color: var(--green-text); }
681
+
682
+ :root[data-theme="dark"] .badge.subgoal {
683
+ background: #263052;
684
+ color: #c7d2ff;
685
+ }
686
+
687
+ .empty {
688
+ padding: 18px;
689
+ color: var(--muted);
690
+ font-size: 14px;
691
+ }
692
+
693
+ .board-error {
694
+ grid-column: 1 / -1;
695
+ padding: 18px;
696
+ border: 1px solid var(--red-border);
697
+ border-radius: 8px;
698
+ background: var(--red-bg);
699
+ color: var(--text);
700
+ }
701
+
702
+ .board-error h2 {
703
+ margin: 0 0 8px;
704
+ font-size: 16px;
705
+ }
706
+
707
+ .board-error p {
708
+ margin: 0;
709
+ color: var(--muted);
710
+ }
711
+
712
+ @media (prefers-reduced-motion: reduce) {
713
+ .github-stars,
714
+ .settings-button,
715
+ .task-card {
716
+ transition: none;
717
+ }
718
+
719
+ .task-card.is-active::before {
720
+ animation: none;
721
+ opacity: 0.26;
722
+ }
723
+ }
724
+
725
+ :root[data-motion="reduce"] .github-stars,
726
+ :root[data-motion="reduce"] .settings-button,
727
+ :root[data-motion="reduce"] .task-card {
728
+ transition: none;
729
+ }
730
+
731
+ :root[data-motion="reduce"] .task-card.is-active::before {
732
+ animation: none;
733
+ opacity: 0.26;
734
+ }
735
+
736
+ .modal[hidden] {
737
+ display: none;
738
+ }
739
+
740
+ .modal {
741
+ position: fixed;
742
+ inset: 0;
743
+ z-index: 30;
744
+ display: grid;
745
+ place-items: center;
746
+ padding: 24px;
747
+ }
748
+
749
+ .modal-scrim {
750
+ position: absolute;
751
+ inset: 0;
752
+ border: 0;
753
+ background: rgba(17, 17, 17, 0.32);
754
+ }
755
+
756
+ .modal-panel {
757
+ position: relative;
758
+ width: min(1080px, 100%);
759
+ max-height: min(760px, calc(100vh - 48px));
760
+ overflow: auto;
761
+ border: 1px solid var(--line);
762
+ border-radius: 8px;
763
+ background: var(--surface);
764
+ }
765
+
766
+ .modal-header {
767
+ position: sticky;
768
+ top: 0;
769
+ display: flex;
770
+ align-items: start;
771
+ justify-content: space-between;
772
+ gap: 16px;
773
+ padding: 20px;
774
+ border-bottom: 1px solid var(--line);
775
+ background: var(--surface);
776
+ }
777
+
778
+ .modal-header h2 {
779
+ margin: 0;
780
+ font-size: 24px;
781
+ line-height: 1.15;
782
+ letter-spacing: 0;
783
+ }
784
+
785
+ .icon-button {
786
+ width: 32px;
787
+ height: 32px;
788
+ border: 1px solid var(--line);
789
+ border-radius: 6px;
790
+ background: var(--surface);
791
+ color: #2f3437;
792
+ cursor: pointer;
793
+ }
794
+
795
+ .modal-body {
796
+ display: grid;
797
+ gap: 18px;
798
+ padding: 20px;
799
+ }
800
+
801
+ .detail-grid {
802
+ display: grid;
803
+ grid-template-columns: repeat(2, minmax(0, 1fr));
804
+ gap: 1px;
805
+ overflow: hidden;
806
+ border: 1px solid var(--line);
807
+ border-radius: 8px;
808
+ background: var(--line);
809
+ }
810
+
811
+ .detail-item {
812
+ min-width: 0;
813
+ padding: 12px;
814
+ background: var(--surface-muted);
815
+ }
816
+
817
+ .detail-item dt {
818
+ margin-bottom: 6px;
819
+ color: var(--muted);
820
+ font-size: 11px;
821
+ text-transform: uppercase;
822
+ letter-spacing: 0.05em;
823
+ }
824
+
825
+ .detail-item dd {
826
+ margin: 0;
827
+ line-height: 1.45;
828
+ }
829
+
830
+ .detail-section {
831
+ border-top: 1px solid var(--line);
832
+ padding-top: 14px;
833
+ }
834
+
835
+ .detail-section h3 {
836
+ margin: 0 0 10px;
837
+ font-size: 14px;
838
+ }
839
+
840
+ .detail-section ul {
841
+ margin: 0;
842
+ padding-left: 18px;
843
+ color: var(--ink);
844
+ line-height: 1.55;
845
+ }
846
+
847
+ .detail-section li {
848
+ color: var(--ink);
849
+ }
850
+
851
+ .subgoal-section {
852
+ border: 1px solid var(--line);
853
+ border-radius: 8px;
854
+ padding: 14px;
855
+ background: var(--surface-muted);
856
+ }
857
+
858
+ .subgoal-header {
859
+ display: flex;
860
+ align-items: start;
861
+ justify-content: space-between;
862
+ gap: 12px;
863
+ margin-bottom: 12px;
864
+ }
865
+
866
+ .subgoal-title {
867
+ margin: 0 0 4px;
868
+ font-size: 15px;
869
+ }
870
+
871
+ .subgoal-meta {
872
+ margin: 0;
873
+ color: var(--muted);
874
+ font-size: 12px;
875
+ line-height: 1.45;
876
+ }
877
+
878
+ .subgoal-board {
879
+ display: grid;
880
+ grid-template-columns: repeat(4, minmax(0, 1fr));
881
+ gap: 10px;
882
+ }
883
+
884
+ .subgoal-column {
885
+ min-width: 0;
886
+ border: 1px solid var(--line);
887
+ border-radius: 8px;
888
+ background: var(--surface);
889
+ }
890
+
891
+ .subgoal-column-header {
892
+ display: flex;
893
+ align-items: center;
894
+ justify-content: space-between;
895
+ gap: 8px;
896
+ padding: 10px;
897
+ border-bottom: 1px solid var(--line);
898
+ }
899
+
900
+ .subgoal-column-header h4 {
901
+ margin: 0;
902
+ font-size: 12px;
903
+ }
904
+
905
+ .subgoal-card-list {
906
+ display: grid;
907
+ gap: 8px;
908
+ padding: 8px;
909
+ }
910
+
911
+ .subgoal-task-card {
912
+ min-height: 74px;
913
+ border: 1px solid var(--line);
914
+ border-radius: 7px;
915
+ padding: 9px;
916
+ background: var(--surface);
917
+ }
918
+
919
+ .subgoal-task-card.is-active {
920
+ border-color: #8e9cff;
921
+ background: var(--active-surface);
922
+ }
923
+
924
+ .subgoal-task-title {
925
+ margin: 6px 0 0;
926
+ color: var(--ink);
927
+ font-size: 12px;
928
+ line-height: 1.35;
929
+ }
930
+
931
+ pre.note {
932
+ overflow: auto;
933
+ margin: 0;
934
+ padding: 14px;
935
+ border: 1px solid var(--line);
936
+ border-radius: 8px;
937
+ background: var(--canvas);
938
+ color: var(--ink);
939
+ font-family: "Geist Mono", "SF Mono", monospace;
940
+ font-size: 12px;
941
+ line-height: 1.55;
942
+ white-space: pre-wrap;
943
+ }
944
+
945
+ @media (max-width: 980px) {
946
+ .goal-header {
947
+ grid-template-columns: 1fr;
948
+ }
949
+
950
+ .goal-meta {
951
+ grid-template-columns: repeat(3, minmax(0, 1fr));
952
+ }
953
+
954
+ .board {
955
+ grid-template-columns: 1fr;
956
+ }
957
+
958
+ .subgoal-board {
959
+ grid-template-columns: 1fr;
960
+ }
961
+ }
962
+
963
+ @media (max-width: 640px) {
964
+ .topbar {
965
+ align-items: flex-start;
966
+ }
967
+
968
+ .topbar-primary {
969
+ flex: 1;
970
+ flex-wrap: wrap;
971
+ gap: 10px 14px;
972
+ }
973
+
974
+ .board-switcher select {
975
+ width: 100%;
976
+ }
977
+
978
+ .shell {
979
+ padding-left: 14px;
980
+ padding-right: 14px;
981
+ }
982
+
983
+ .goal-meta,
984
+ .detail-grid {
985
+ grid-template-columns: 1fr;
986
+ }
987
+
988
+ h1 {
989
+ font-size: 38px;
990
+ }
991
+ }