aidevops 3.21.12 → 3.22.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 (34) hide show
  1. package/README.md +1 -1
  2. package/VERSION +1 -1
  3. package/aidevops.sh +3 -2
  4. package/bun.lock +573 -0
  5. package/package.json +12 -1
  6. package/packages/gui-api/package.json +9 -0
  7. package/packages/gui-api/src/app.ts +49 -0
  8. package/packages/gui-api/src/file-adapter.ts +207 -0
  9. package/packages/gui-api/src/server.ts +12 -0
  10. package/packages/gui-api/src/status-adapter-utils.ts +108 -0
  11. package/packages/gui-api/src/status-adapter.ts +484 -0
  12. package/packages/gui-api/src/status-local-repos.ts +239 -0
  13. package/packages/gui-desktop/package.json +6 -0
  14. package/packages/gui-desktop/scripts/install-macos-app.sh +1020 -0
  15. package/packages/gui-shared/package.json +9 -0
  16. package/packages/gui-shared/src/contracts.ts +341 -0
  17. package/packages/gui-shared/src/fixtures.ts +250 -0
  18. package/packages/gui-shared/src/index.ts +2 -0
  19. package/packages/gui-web/index.html +24 -0
  20. package/packages/gui-web/package.json +25 -0
  21. package/packages/gui-web/src/App.tsx +269 -0
  22. package/packages/gui-web/src/AppNavigation.tsx +379 -0
  23. package/packages/gui-web/src/AppWorkspace.tsx +114 -0
  24. package/packages/gui-web/src/FileExplorerSurface.tsx +153 -0
  25. package/packages/gui-web/src/InventorySurfaces.tsx +117 -0
  26. package/packages/gui-web/src/PathActions.tsx +17 -0
  27. package/packages/gui-web/src/StatusSurfaces.tsx +396 -0
  28. package/packages/gui-web/src/app-model.ts +546 -0
  29. package/packages/gui-web/src/dashboard.ts +79 -0
  30. package/packages/gui-web/src/main.tsx +24 -0
  31. package/packages/gui-web/src/status-client.ts +93 -0
  32. package/packages/gui-web/src/styles.css +1540 -0
  33. package/packages/gui-web/vite.config.ts +14 -0
  34. package/setup.sh +78 -3
@@ -0,0 +1,1540 @@
1
+ :root {
2
+ --accent-hue: 123;
3
+ --accent: hsl(var(--accent-hue) 50% 36%);
4
+ --accent-strong: hsl(var(--accent-hue) 56% 28%);
5
+ --bg-primary: #ffffff;
6
+ --bg-secondary: #f8f8f8;
7
+ --bg-tertiary: #f0f0f0;
8
+ --border: color-mix(in srgb, rgb(0 0 0 / 13%) 62%, rgb(255 255 255 / 54%));
9
+ --border-hover: color-mix(in srgb, rgb(0 0 0 / 24%) 64%, rgb(255 255 255 / 48%));
10
+ --code-bg: hsl(var(--accent-hue) 55% 91%);
11
+ --desktop-titlebar-height: 0px;
12
+ --font-family-app: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
13
+ --font-size-app: 16px;
14
+ --glass-panel-shadow: inset 0 1px 0 rgb(255 255 255 / 58%), inset 0 -1px 0 rgb(0 0 0 / 3%), var(--shadow-soft);
15
+ --shell-gutter: 8px;
16
+ --shadow-soft: 0 18px 56px rgb(15 23 42 / 9%);
17
+ --surface-elevated: #ffffff;
18
+ --surface-muted: #f0f0f0;
19
+ --success-bg: hsl(var(--accent-hue) 50% 36% / 14%);
20
+ --success-text: var(--accent-strong);
21
+ --text-muted: rgb(17 17 17 / 55%);
22
+ --text-primary: #111111;
23
+ --text-secondary: rgb(17 17 17 / 75%);
24
+ background: var(--bg-secondary);
25
+ color: var(--text-primary);
26
+ color-scheme: light;
27
+ font-family: var(--font-family-app);
28
+ }
29
+
30
+ :root[data-desktop-shell="macos"] {
31
+ --desktop-titlebar-height: 22px;
32
+ }
33
+
34
+ :root[data-theme="dark"] {
35
+ --accent: hsl(var(--accent-hue) 74% 66%);
36
+ --accent-strong: hsl(var(--accent-hue) 75% 72%);
37
+ --bg-primary: #0a0a0a;
38
+ --bg-secondary: #111111;
39
+ --bg-tertiary: #1a1a1a;
40
+ --border: color-mix(in srgb, rgb(255 255 255 / 11%) 76%, rgb(255 255 255 / 30%));
41
+ --border-hover: color-mix(in srgb, rgb(255 255 255 / 22%) 74%, rgb(255 255 255 / 40%));
42
+ --code-bg: hsl(var(--accent-hue) 18% 6%);
43
+ --glass-panel-shadow: inset 0 1px 0 rgb(255 255 255 / 10%), inset 0 -1px 0 rgb(0 0 0 / 24%), var(--shadow-soft);
44
+ --shadow-soft: 0 24px 80px rgb(0 0 0 / 40%);
45
+ --surface-elevated: #151515;
46
+ --surface-muted: #202020;
47
+ --success-bg: hsl(var(--accent-hue) 74% 66% / 12%);
48
+ --success-text: var(--accent);
49
+ --text-muted: rgb(255 255 255 / 40%);
50
+ --text-primary: #ffffff;
51
+ --text-secondary: rgb(255 255 255 / 70%);
52
+ color-scheme: dark;
53
+ }
54
+
55
+ :root[data-borders="hidden"] {
56
+ --border: transparent;
57
+ --border-hover: transparent;
58
+ --glass-panel-shadow: var(--shadow-soft);
59
+ }
60
+
61
+ *,
62
+ *::before,
63
+ *::after {
64
+ box-sizing: border-box;
65
+ }
66
+
67
+ body {
68
+ background:
69
+ radial-gradient(ellipse at top left, color-mix(in srgb, var(--accent) 16%, transparent) 0%, transparent 36%),
70
+ var(--bg-secondary);
71
+ color: var(--text-primary);
72
+ line-height: 1.6;
73
+ margin: 0;
74
+ font-size: var(--font-size-app);
75
+ }
76
+
77
+ button,
78
+ input,
79
+ select {
80
+ font: inherit;
81
+ }
82
+
83
+ button {
84
+ cursor: pointer;
85
+ }
86
+
87
+ button:disabled {
88
+ cursor: not-allowed;
89
+ opacity: 0.45;
90
+ }
91
+
92
+ code {
93
+ background: var(--code-bg);
94
+ border-radius: 6px;
95
+ color: var(--accent-strong);
96
+ font-size: 0.82em;
97
+ padding: 2px 5px;
98
+ }
99
+
100
+ .app-shell {
101
+ display: grid;
102
+ gap: 8px;
103
+ grid-template-columns: 72px 302px minmax(0, 1fr);
104
+ grid-template-rows: minmax(0, 1fr) auto;
105
+ height: 100vh;
106
+ padding: calc(var(--shell-gutter) + var(--desktop-titlebar-height)) var(--shell-gutter) var(--shell-gutter);
107
+ }
108
+
109
+ .app-shell.machine-rail-collapsed {
110
+ grid-template-columns: 302px minmax(0, 1fr);
111
+ }
112
+
113
+ .desktop-titlebar-tagline {
114
+ display: none;
115
+ }
116
+
117
+ :root[data-desktop-shell="macos"] .desktop-titlebar-tagline {
118
+ align-items: center;
119
+ color: var(--accent);
120
+ display: flex;
121
+ font-family: var(--font-family-app);
122
+ font-size: 0.875rem;
123
+ font-style: italic;
124
+ font-weight: 600;
125
+ height: 24px;
126
+ justify-content: center;
127
+ left: 136px;
128
+ line-height: 1;
129
+ pointer-events: none;
130
+ position: fixed;
131
+ right: 116px;
132
+ top: 0;
133
+ transform: translateY(3.5px);
134
+ z-index: 20;
135
+ }
136
+
137
+ .machine-rail,
138
+ .app-sidebar,
139
+ .app-inset {
140
+ background: color-mix(in srgb, var(--surface-elevated) 96%, transparent);
141
+ backdrop-filter: saturate(180%) blur(22px);
142
+ border: 1px solid var(--border);
143
+ border-radius: 18px;
144
+ box-shadow: var(--glass-panel-shadow);
145
+ min-height: 0;
146
+ -webkit-backdrop-filter: saturate(180%) blur(22px);
147
+ }
148
+
149
+ .machine-rail,
150
+ .app-sidebar,
151
+ .app-inset {
152
+ grid-row: 1;
153
+ }
154
+
155
+ .machine-rail {
156
+ align-content: start;
157
+ display: grid;
158
+ gap: 10px;
159
+ justify-items: center;
160
+ padding: 12px 8px;
161
+ }
162
+
163
+ .machine-orb,
164
+ .client-folder-orb {
165
+ align-items: center;
166
+ background: var(--surface-muted);
167
+ border: 1px solid transparent;
168
+ border-radius: 16px;
169
+ color: var(--text-secondary);
170
+ display: inline-flex;
171
+ height: 48px;
172
+ justify-content: center;
173
+ padding: 0;
174
+ width: 48px;
175
+ }
176
+
177
+ .machine-orb span {
178
+ font-weight: 800;
179
+ letter-spacing: -0.04em;
180
+ }
181
+
182
+ .machine-orb.active {
183
+ background: color-mix(in srgb, var(--accent) 18%, transparent);
184
+ border-color: color-mix(in srgb, var(--accent) 42%, transparent);
185
+ color: var(--accent);
186
+ }
187
+
188
+ .client-folder-orb {
189
+ border-radius: 14px;
190
+ font-size: 1.35rem;
191
+ }
192
+
193
+ .app-sidebar {
194
+ display: grid;
195
+ grid-template-rows: auto minmax(0, 1fr) auto;
196
+ overflow: hidden;
197
+ }
198
+
199
+ .sidebar-header,
200
+ .sidebar-footer {
201
+ display: grid;
202
+ gap: 12px;
203
+ padding: 16px;
204
+ }
205
+
206
+ .brand-lockup,
207
+ .sidebar-titlebar,
208
+ .sidebar-history-controls,
209
+ .sidebar-mode-tabs,
210
+ .theme-control-heading,
211
+ .appearance-panel-tab,
212
+ .header-title,
213
+ .header-actions,
214
+ .workspace-search,
215
+ .version-pill,
216
+ .surface-link,
217
+ .object-list li,
218
+ .path-actions,
219
+ .file-entry,
220
+ .file-entry-row,
221
+ .preview-header,
222
+ .toggle-row,
223
+ .install-row {
224
+ align-items: center;
225
+ display: flex;
226
+ }
227
+
228
+ .brand-lockup {
229
+ gap: 12px;
230
+ padding: 2px 4px;
231
+ }
232
+
233
+ .sidebar-titlebar {
234
+ gap: 10px;
235
+ justify-content: space-between;
236
+ min-width: 0;
237
+ }
238
+
239
+ .brand-lockup strong {
240
+ display: block;
241
+ font-size: 1.45rem;
242
+ font-weight: 900;
243
+ letter-spacing: -0.05em;
244
+ }
245
+
246
+ .terminal-mark {
247
+ align-items: center;
248
+ background: color-mix(in srgb, var(--accent) 15%, #0a0a0a);
249
+ border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
250
+ border-radius: 11px;
251
+ box-shadow: inset 0 1px 0 color-mix(in srgb, var(--accent) 28%, transparent);
252
+ color: var(--accent);
253
+ display: inline-flex;
254
+ font-size: 1.2rem;
255
+ font-weight: 900;
256
+ height: 44px;
257
+ justify-content: center;
258
+ width: 44px;
259
+ }
260
+
261
+ .sidebar-history-controls {
262
+ background: color-mix(in srgb, var(--surface-muted) 72%, transparent);
263
+ border: 1px solid var(--border);
264
+ border-radius: 999px;
265
+ gap: 2px;
266
+ padding: 2px;
267
+ }
268
+
269
+ .sidebar-history-controls button {
270
+ align-items: center;
271
+ background: transparent;
272
+ border: 0;
273
+ border-radius: 999px;
274
+ color: var(--text-secondary);
275
+ display: inline-flex;
276
+ height: 26px;
277
+ justify-content: center;
278
+ padding: 0;
279
+ width: 26px;
280
+ }
281
+
282
+ .sidebar-history-controls button:hover:not(:disabled),
283
+ .sidebar-history-controls button:focus-visible {
284
+ background: var(--surface-elevated);
285
+ color: var(--text-primary);
286
+ outline: none;
287
+ }
288
+
289
+ .sidebar-history-controls svg {
290
+ height: 18px;
291
+ stroke-width: 2.4;
292
+ width: 18px;
293
+ }
294
+
295
+ .sidebar-content {
296
+ overflow: auto;
297
+ padding: 0 10px 12px;
298
+ }
299
+
300
+ .sidebar-mode-tabs {
301
+ background: var(--surface-muted);
302
+ border: 1px solid var(--border);
303
+ border-radius: 999px;
304
+ gap: 4px;
305
+ margin: 0 6px 12px;
306
+ padding: 4px;
307
+ }
308
+
309
+ .sidebar-mode-tabs button {
310
+ background: transparent;
311
+ border: 0;
312
+ border-radius: 999px;
313
+ color: var(--text-muted);
314
+ flex: 1 1 0;
315
+ font-size: 0.78rem;
316
+ font-weight: 900;
317
+ padding: 8px 10px;
318
+ text-transform: uppercase;
319
+ }
320
+
321
+ .sidebar-mode-tabs button.active,
322
+ .sidebar-mode-tabs button:hover,
323
+ .sidebar-mode-tabs button:focus-visible {
324
+ background: var(--surface-elevated);
325
+ color: var(--accent);
326
+ outline: none;
327
+ }
328
+
329
+ .sidebar-group {
330
+ margin-bottom: 14px;
331
+ }
332
+
333
+ .sidebar-group h2,
334
+ .sidebar-footer p,
335
+ .eyebrow {
336
+ color: var(--text-muted);
337
+ font-size: 0.76rem;
338
+ font-weight: 900;
339
+ letter-spacing: 0.08em;
340
+ margin: 11px 8px 5px;
341
+ text-transform: uppercase;
342
+ }
343
+
344
+ .sidebar-top-link,
345
+ .sidebar-group ul,
346
+ .object-list,
347
+ .tag-list {
348
+ list-style: none;
349
+ margin: 0;
350
+ padding: 0;
351
+ }
352
+
353
+ .surface-link {
354
+ background: transparent;
355
+ border: 0;
356
+ border-radius: 8px;
357
+ color: var(--text-secondary);
358
+ gap: 9px;
359
+ min-height: 32px;
360
+ padding: 5px 8px;
361
+ text-align: left;
362
+ width: 100%;
363
+ }
364
+
365
+ .surface-link:hover,
366
+ .surface-link:focus-visible {
367
+ background: color-mix(in srgb, var(--surface-muted) 82%, transparent);
368
+ outline: none;
369
+ }
370
+
371
+ .surface-link.active {
372
+ background: color-mix(in srgb, var(--accent) 15%, transparent);
373
+ color: var(--text-primary);
374
+ }
375
+
376
+ .surface-link.active:hover,
377
+ .surface-link.active:focus-visible {
378
+ background: color-mix(in srgb, var(--accent) 19%, transparent);
379
+ }
380
+
381
+ .surface-icon {
382
+ align-items: center;
383
+ color: var(--accent);
384
+ display: inline-flex;
385
+ flex: 0 0 auto;
386
+ height: 20px;
387
+ justify-content: center;
388
+ width: 20px;
389
+ }
390
+
391
+ .surface-icon svg {
392
+ height: 17px;
393
+ stroke-width: 2.25;
394
+ width: 17px;
395
+ }
396
+
397
+ .surface-copy {
398
+ display: grid;
399
+ flex: 1;
400
+ min-width: 0;
401
+ }
402
+
403
+ .surface-title-row {
404
+ align-items: baseline;
405
+ display: flex;
406
+ gap: 5px;
407
+ min-width: 0;
408
+ }
409
+
410
+ .surface-copy small,
411
+ .metric-card small,
412
+ .planned-home small,
413
+ .install-row small,
414
+ .file-entry small {
415
+ color: var(--text-muted);
416
+ }
417
+
418
+ .surface-copy strong {
419
+ font-size: 1em;
420
+ font-weight: 500;
421
+ overflow: hidden;
422
+ text-overflow: ellipsis;
423
+ white-space: nowrap;
424
+ }
425
+
426
+ .surface-count {
427
+ color: var(--text-muted);
428
+ flex: 0 0 auto;
429
+ font-size: 0.84em;
430
+ font-weight: 700;
431
+ }
432
+
433
+ .sidebar-group h2 {
434
+ font-size: max(12.5px, 0.84em);
435
+ }
436
+
437
+ .surface-link.active .surface-copy strong {
438
+ font-weight: 700;
439
+ }
440
+
441
+ .surface-link em {
442
+ background: var(--surface-muted);
443
+ border-radius: 999px;
444
+ color: var(--text-muted);
445
+ font-size: 0.74rem;
446
+ font-style: normal;
447
+ font-weight: 900;
448
+ padding: 3px 7px;
449
+ }
450
+
451
+ .sidebar-footer {
452
+ border-top: 1px solid var(--border);
453
+ padding-top: 12px;
454
+ }
455
+
456
+ .theme-control.compact {
457
+ background: var(--surface-muted);
458
+ border: 0;
459
+ border-radius: 12px;
460
+ display: grid;
461
+ gap: 4px;
462
+ grid-template-columns: repeat(3, 1fr);
463
+ margin: 0;
464
+ min-inline-size: 0;
465
+ padding: 4px;
466
+ }
467
+
468
+ .theme-option {
469
+ background: transparent;
470
+ border: 0;
471
+ border-radius: 9px;
472
+ color: var(--text-muted);
473
+ font-size: 0.72rem;
474
+ font-weight: 900;
475
+ padding: 7px 6px;
476
+ text-transform: uppercase;
477
+ }
478
+
479
+ .theme-option:hover,
480
+ .theme-option.active {
481
+ background: var(--surface-elevated);
482
+ color: var(--accent);
483
+ }
484
+
485
+ .appearance-panel {
486
+ background: var(--surface-muted);
487
+ border: 1px solid var(--border);
488
+ border-radius: 14px;
489
+ display: grid;
490
+ overflow: hidden;
491
+ }
492
+
493
+ .appearance-panel-tab {
494
+ background: transparent;
495
+ border: 0;
496
+ color: var(--text-secondary);
497
+ gap: 8px;
498
+ justify-content: center;
499
+ padding: 8px 10px;
500
+ text-transform: uppercase;
501
+ width: 100%;
502
+ }
503
+
504
+ .appearance-chevron {
505
+ color: var(--accent);
506
+ height: 20px;
507
+ stroke-width: 2.6;
508
+ width: 20px;
509
+ }
510
+
511
+ .appearance-panel-tab:hover,
512
+ .appearance-panel-tab:focus-visible {
513
+ background: color-mix(in srgb, var(--accent) 10%, transparent);
514
+ outline: none;
515
+ }
516
+
517
+ .appearance-panel-body {
518
+ border-top: 1px solid var(--border);
519
+ display: grid;
520
+ gap: 12px;
521
+ padding: 12px;
522
+ }
523
+
524
+ .appearance-panel.collapsed .appearance-panel-tab {
525
+ border-radius: 14px;
526
+ }
527
+
528
+ .theme-hue-control,
529
+ .font-size-control,
530
+ .font-control {
531
+ display: grid;
532
+ gap: 8px;
533
+ }
534
+
535
+ .theme-control-heading {
536
+ gap: 8px;
537
+ justify-content: space-between;
538
+ }
539
+
540
+ .hue-label-row {
541
+ align-items: center;
542
+ display: flex;
543
+ gap: 8px;
544
+ min-width: 0;
545
+ }
546
+
547
+ .theme-control-heading label,
548
+ .font-size-control label,
549
+ .font-control span {
550
+ color: var(--text-muted);
551
+ font-size: 0.74rem;
552
+ font-weight: 900;
553
+ letter-spacing: 0.08em;
554
+ text-transform: uppercase;
555
+ }
556
+
557
+ .hue-number-input {
558
+ background: var(--surface-elevated);
559
+ border: 1px solid var(--border);
560
+ border-radius: 9px;
561
+ color: var(--text-primary);
562
+ font-size: 0.78rem;
563
+ font-weight: 800;
564
+ min-width: 0;
565
+ padding: 5px 6px;
566
+ width: 58px;
567
+ }
568
+
569
+ .icon-reset-button {
570
+ align-items: center;
571
+ background: var(--surface-muted);
572
+ border: 1px solid var(--border);
573
+ border-radius: 10px;
574
+ color: var(--text-secondary);
575
+ display: inline-flex;
576
+ height: 28px;
577
+ justify-content: center;
578
+ padding: 0;
579
+ width: 28px;
580
+ }
581
+
582
+ .icon-reset-button svg {
583
+ height: 15px;
584
+ width: 15px;
585
+ }
586
+
587
+ .theme-hue-control input[type="range"],
588
+ .font-size-control input[type="range"] {
589
+ accent-color: var(--accent);
590
+ width: 100%;
591
+ }
592
+
593
+ .range-labels {
594
+ color: var(--text-muted);
595
+ display: grid;
596
+ font-size: 0.7rem;
597
+ font-weight: 900;
598
+ grid-template-columns: repeat(5, 1fr);
599
+ text-transform: uppercase;
600
+ }
601
+
602
+ .range-labels span {
603
+ text-align: center;
604
+ }
605
+
606
+ .range-labels span:first-child {
607
+ text-align: left;
608
+ }
609
+
610
+ .range-labels span:last-child {
611
+ text-align: right;
612
+ }
613
+
614
+ .range-labels .active {
615
+ color: var(--accent);
616
+ }
617
+
618
+ .font-control select {
619
+ appearance: none;
620
+ background: var(--surface-muted);
621
+ border: 1px solid var(--border);
622
+ border-radius: 12px;
623
+ color: var(--text-primary);
624
+ min-width: 0;
625
+ padding: 9px 10px;
626
+ width: 100%;
627
+ }
628
+
629
+ .app-inset {
630
+ display: grid;
631
+ grid-template-rows: auto minmax(0, 1fr);
632
+ overflow: hidden;
633
+ }
634
+
635
+ .workspace-header {
636
+ align-items: center;
637
+ background: color-mix(in srgb, var(--surface-elevated) 94%, transparent);
638
+ border-bottom: 1px solid var(--border);
639
+ display: flex;
640
+ gap: 16px;
641
+ min-height: 58px;
642
+ padding: 10px 14px;
643
+ position: sticky;
644
+ top: 0;
645
+ z-index: 2;
646
+ }
647
+
648
+ .header-title {
649
+ flex: 0 0 auto;
650
+ gap: 10px;
651
+ min-width: 0;
652
+ }
653
+
654
+ .header-title p {
655
+ color: var(--text-muted);
656
+ font-size: 0.76rem;
657
+ font-weight: 900;
658
+ margin: 0;
659
+ text-transform: uppercase;
660
+ }
661
+
662
+ .header-title h1 {
663
+ font-size: 1rem;
664
+ margin: 0;
665
+ }
666
+
667
+ .path-actions button,
668
+ .secondary-action {
669
+ background: var(--surface-muted);
670
+ border: 1px solid transparent;
671
+ border-radius: 10px;
672
+ color: var(--text-secondary);
673
+ }
674
+
675
+ .workspace-surface-icon {
676
+ align-items: center;
677
+ color: var(--accent);
678
+ display: inline-flex;
679
+ height: 34px;
680
+ justify-content: center;
681
+ width: 34px;
682
+ }
683
+
684
+ .workspace-surface-icon svg {
685
+ height: 24px;
686
+ stroke-width: 2.2;
687
+ width: 24px;
688
+ }
689
+
690
+ .header-actions {
691
+ flex: 1 1 auto;
692
+ gap: 10px;
693
+ justify-content: flex-end;
694
+ min-width: 0;
695
+ }
696
+
697
+ .workspace-search {
698
+ background: var(--surface-muted);
699
+ border-radius: 999px;
700
+ flex: 1 1 auto;
701
+ gap: 8px;
702
+ min-width: 160px;
703
+ padding: 8px 12px;
704
+ }
705
+
706
+ .workspace-search span,
707
+ .workspace-search input {
708
+ color: var(--text-muted);
709
+ }
710
+
711
+ .workspace-search input {
712
+ background: transparent;
713
+ border: 0;
714
+ min-width: 0;
715
+ outline: none;
716
+ width: 100%;
717
+ }
718
+
719
+ .version-pill {
720
+ background: var(--surface-muted);
721
+ border-radius: 999px;
722
+ color: var(--text-secondary);
723
+ font-size: 0.82rem;
724
+ font-weight: 900;
725
+ padding: 8px 11px;
726
+ white-space: nowrap;
727
+ }
728
+
729
+ .workspace-scroll {
730
+ display: grid;
731
+ gap: 16px;
732
+ overflow: auto;
733
+ padding: 18px;
734
+ }
735
+
736
+ .surface-page {
737
+ display: grid;
738
+ gap: 16px;
739
+ }
740
+
741
+ .hero-panel,
742
+ .panel,
743
+ .metric-card,
744
+ .planned-home {
745
+ background: var(--surface-elevated);
746
+ border: 1px solid var(--border);
747
+ border-radius: 20px;
748
+ box-shadow: var(--glass-panel-shadow);
749
+ }
750
+
751
+ .hero-panel {
752
+ background:
753
+ linear-gradient(135deg, color-mix(in srgb, var(--accent) 16%, transparent), transparent 58%),
754
+ var(--surface-elevated);
755
+ padding: clamp(24px, 5vw, 42px);
756
+ }
757
+
758
+ .compact-hero h2 {
759
+ font-size: clamp(3rem, 10vw, 5rem);
760
+ letter-spacing: -0.08em;
761
+ line-height: 0.95;
762
+ margin: 0;
763
+ }
764
+
765
+ .metric-grid,
766
+ .planned-home-grid {
767
+ display: grid;
768
+ gap: 12px;
769
+ grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
770
+ }
771
+
772
+ .metric-card,
773
+ .planned-home,
774
+ .panel {
775
+ padding: 18px;
776
+ }
777
+
778
+ .metric-card span,
779
+ .planned-home span,
780
+ .data-row.header-row,
781
+ .editable-row.header-row {
782
+ color: var(--accent);
783
+ display: block;
784
+ font-size: 0.76rem;
785
+ font-weight: 900;
786
+ text-transform: uppercase;
787
+ }
788
+
789
+ .metric-card strong {
790
+ display: block;
791
+ font-size: 1.7rem;
792
+ letter-spacing: -0.05em;
793
+ margin: 8px 0 4px;
794
+ }
795
+
796
+ .planned-home {
797
+ display: grid;
798
+ gap: 8px;
799
+ }
800
+
801
+ .section-heading {
802
+ margin-bottom: 18px;
803
+ max-width: 860px;
804
+ }
805
+
806
+ .section-heading h2 {
807
+ font-size: 1.7rem;
808
+ letter-spacing: -0.05em;
809
+ line-height: 1.04;
810
+ margin: 6px 0 8px;
811
+ }
812
+
813
+ .section-heading p,
814
+ .empty-state {
815
+ color: var(--text-secondary);
816
+ }
817
+
818
+ .split-heading {
819
+ align-items: flex-start;
820
+ display: flex;
821
+ gap: 16px;
822
+ justify-content: space-between;
823
+ max-width: none;
824
+ }
825
+
826
+ .object-list {
827
+ display: grid;
828
+ gap: 10px;
829
+ }
830
+
831
+ .object-list li {
832
+ background: var(--surface-muted);
833
+ border-radius: 14px;
834
+ flex-wrap: wrap;
835
+ gap: 10px;
836
+ padding: 12px;
837
+ }
838
+
839
+ .object-list li span:not(.path-actions) {
840
+ background: color-mix(in srgb, var(--accent) 14%, transparent);
841
+ border-radius: 999px;
842
+ color: var(--accent);
843
+ font-size: 0.78rem;
844
+ font-weight: 900;
845
+ padding: 4px 9px;
846
+ }
847
+
848
+ .object-list li small {
849
+ color: var(--text-muted);
850
+ }
851
+
852
+ .path-actions {
853
+ gap: 4px;
854
+ margin-left: auto;
855
+ }
856
+
857
+ .path-actions button {
858
+ height: 30px;
859
+ width: 30px;
860
+ }
861
+
862
+ .explorer-panel {
863
+ min-height: calc(100vh - 116px);
864
+ }
865
+
866
+ .file-workspace {
867
+ display: grid;
868
+ gap: 14px;
869
+ grid-template-columns: auto minmax(0, 1fr);
870
+ }
871
+
872
+ .file-list-pane,
873
+ .file-list,
874
+ .file-preview,
875
+ .data-table,
876
+ .editable-table,
877
+ .installation-list {
878
+ background: var(--surface-muted);
879
+ border: 1px solid var(--border);
880
+ border-radius: 16px;
881
+ }
882
+
883
+ .file-list-pane {
884
+ max-height: 68vh;
885
+ min-width: 260px;
886
+ overflow: auto;
887
+ resize: horizontal;
888
+ width: clamp(280px, 24vw, 460px);
889
+ }
890
+
891
+ .file-list {
892
+ align-content: start;
893
+ display: grid;
894
+ gap: 4px;
895
+ height: 100%;
896
+ list-style: none;
897
+ margin: 0;
898
+ min-height: 100%;
899
+ overflow: auto;
900
+ padding: 8px;
901
+ }
902
+
903
+ .file-entry-row {
904
+ gap: 6px;
905
+ }
906
+
907
+ .file-entry {
908
+ background: transparent;
909
+ border: 0;
910
+ border-radius: 10px;
911
+ color: var(--text-secondary);
912
+ flex: 1;
913
+ gap: 8px;
914
+ min-width: 0;
915
+ padding: 8px;
916
+ text-align: left;
917
+ }
918
+
919
+ .file-entry:hover {
920
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
921
+ color: var(--text-primary);
922
+ }
923
+
924
+ .file-entry strong {
925
+ flex: 1;
926
+ overflow: hidden;
927
+ text-overflow: ellipsis;
928
+ white-space: nowrap;
929
+ }
930
+
931
+ .parent-entry {
932
+ border: 1px dashed var(--border);
933
+ }
934
+
935
+ .file-preview {
936
+ display: grid;
937
+ grid-template-rows: auto minmax(0, 1fr);
938
+ max-height: 68vh;
939
+ min-width: 0;
940
+ overflow: hidden;
941
+ }
942
+
943
+ .empty-preview {
944
+ align-content: center;
945
+ color: var(--text-muted);
946
+ justify-content: center;
947
+ padding: 24px;
948
+ }
949
+
950
+ .preview-header {
951
+ border-bottom: 1px solid var(--border);
952
+ gap: 16px;
953
+ justify-content: space-between;
954
+ padding: 12px;
955
+ }
956
+
957
+ .preview-header strong {
958
+ word-break: break-word;
959
+ }
960
+
961
+ .toggle-row {
962
+ color: var(--text-secondary);
963
+ gap: 8px;
964
+ white-space: nowrap;
965
+ }
966
+
967
+ .code-preview,
968
+ .markdown-preview {
969
+ margin: 0;
970
+ overflow: auto;
971
+ padding: 16px;
972
+ }
973
+
974
+ .code-preview {
975
+ background: var(--code-bg);
976
+ color: var(--text-secondary);
977
+ }
978
+
979
+ .code-preview code {
980
+ background: transparent;
981
+ color: inherit;
982
+ padding: 0;
983
+ }
984
+
985
+ .markdown-preview h2,
986
+ .markdown-preview h3,
987
+ .markdown-preview h4,
988
+ .markdown-preview p {
989
+ margin: 0 0 0.75rem;
990
+ }
991
+
992
+ .markdown-preview h2,
993
+ .markdown-preview h3,
994
+ .markdown-preview h4 {
995
+ color: var(--text-primary);
996
+ letter-spacing: -0.04em;
997
+ }
998
+
999
+ .markdown-bullet {
1000
+ color: var(--text-secondary);
1001
+ padding-left: 1rem;
1002
+ }
1003
+
1004
+ .notice,
1005
+ .empty-state {
1006
+ border-radius: 14px;
1007
+ margin: 0;
1008
+ padding: 12px 14px;
1009
+ }
1010
+
1011
+ .notice {
1012
+ background: var(--success-bg);
1013
+ color: var(--success-text);
1014
+ }
1015
+
1016
+ .compact-notice {
1017
+ margin-bottom: 12px;
1018
+ }
1019
+
1020
+ .data-table,
1021
+ .editable-table,
1022
+ .installation-list {
1023
+ display: grid;
1024
+ overflow: hidden;
1025
+ }
1026
+
1027
+ .data-row,
1028
+ .editable-row {
1029
+ display: grid;
1030
+ gap: 8px;
1031
+ grid-template-columns: repeat(4, minmax(0, 1fr));
1032
+ padding: 12px;
1033
+ }
1034
+
1035
+ .data-row + .data-row,
1036
+ .editable-row + .editable-row,
1037
+ .install-row + .install-row {
1038
+ border-top: 1px solid var(--border);
1039
+ }
1040
+
1041
+ .data-row span,
1042
+ .editable-row span {
1043
+ min-width: 0;
1044
+ overflow: hidden;
1045
+ text-overflow: ellipsis;
1046
+ white-space: nowrap;
1047
+ }
1048
+
1049
+ .editable-row input {
1050
+ background: var(--surface-elevated);
1051
+ border: 1px solid var(--border);
1052
+ border-radius: 10px;
1053
+ color: var(--text-primary);
1054
+ min-width: 0;
1055
+ padding: 9px 10px;
1056
+ }
1057
+
1058
+ .secondary-action {
1059
+ padding: 9px 12px;
1060
+ }
1061
+
1062
+ .installation-list {
1063
+ margin-bottom: 12px;
1064
+ }
1065
+
1066
+ .install-row {
1067
+ gap: 12px;
1068
+ justify-content: space-between;
1069
+ padding: 12px;
1070
+ }
1071
+
1072
+ .install-row div {
1073
+ display: grid;
1074
+ flex: 1;
1075
+ }
1076
+
1077
+ .toggle-pill {
1078
+ border: 1px solid var(--border);
1079
+ border-radius: 999px;
1080
+ color: var(--text-muted);
1081
+ font-size: 0.76rem;
1082
+ font-weight: 900;
1083
+ padding: 6px 10px;
1084
+ text-transform: uppercase;
1085
+ }
1086
+
1087
+ .toggle-pill.checked {
1088
+ background: color-mix(in srgb, var(--accent) 14%, transparent);
1089
+ border-color: color-mix(in srgb, var(--accent) 50%, transparent);
1090
+ color: var(--accent);
1091
+ }
1092
+
1093
+ .pill-tabs {
1094
+ background: var(--surface-muted);
1095
+ border: 1px solid var(--border);
1096
+ border-radius: 999px;
1097
+ display: flex;
1098
+ gap: 4px;
1099
+ padding: 5px;
1100
+ width: min(100%, 520px);
1101
+ }
1102
+
1103
+ .pill-tabs button {
1104
+ background: transparent;
1105
+ border: 0;
1106
+ border-radius: 999px;
1107
+ color: var(--text-secondary);
1108
+ flex: 1 1 0;
1109
+ font-weight: 800;
1110
+ min-height: 38px;
1111
+ padding: 9px 14px;
1112
+ }
1113
+
1114
+ .pill-tabs button.active,
1115
+ .pill-tabs button:hover,
1116
+ .pill-tabs button:focus-visible {
1117
+ background: var(--surface-elevated);
1118
+ color: var(--text-primary);
1119
+ outline: none;
1120
+ }
1121
+
1122
+ .count-pill,
1123
+ .repo-summary-strip span {
1124
+ background: color-mix(in srgb, var(--accent) 14%, transparent);
1125
+ border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
1126
+ border-radius: 999px;
1127
+ color: var(--accent);
1128
+ font-size: 0.78rem;
1129
+ font-weight: 900;
1130
+ padding: 6px 10px;
1131
+ white-space: nowrap;
1132
+ }
1133
+
1134
+ .repo-summary-strip {
1135
+ display: flex;
1136
+ flex-wrap: wrap;
1137
+ gap: 8px;
1138
+ margin-bottom: 14px;
1139
+ }
1140
+
1141
+ .repo-card-grid,
1142
+ .provider-grid,
1143
+ .setup-card-grid,
1144
+ .ai-app-grid {
1145
+ display: grid;
1146
+ gap: 14px;
1147
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
1148
+ }
1149
+
1150
+ .repo-setup-card,
1151
+ .provider-card,
1152
+ .setup-target-card,
1153
+ .ai-app-card {
1154
+ background: var(--surface-muted);
1155
+ border: 1px solid var(--border);
1156
+ border-radius: 18px;
1157
+ display: grid;
1158
+ gap: 14px;
1159
+ min-width: 0;
1160
+ padding: 14px;
1161
+ }
1162
+
1163
+ .repo-setup-card header,
1164
+ .provider-card header,
1165
+ .setup-target-card header,
1166
+ .ai-app-card header,
1167
+ .repo-card-footer {
1168
+ align-items: flex-start;
1169
+ display: flex;
1170
+ gap: 10px;
1171
+ justify-content: space-between;
1172
+ min-width: 0;
1173
+ }
1174
+
1175
+ .repo-setup-card h3,
1176
+ .provider-card h3,
1177
+ .setup-target-card h3,
1178
+ .ai-app-card h3 {
1179
+ font-size: 1rem;
1180
+ margin: 0 0 5px;
1181
+ }
1182
+
1183
+ .repo-setup-card code,
1184
+ .repo-remotes code,
1185
+ .setup-path-row code {
1186
+ background: var(--surface-elevated);
1187
+ border: 1px solid var(--border);
1188
+ border-radius: 9px;
1189
+ color: var(--text-secondary);
1190
+ display: block;
1191
+ font-size: 0.78rem;
1192
+ overflow-wrap: anywhere;
1193
+ padding: 5px 7px;
1194
+ }
1195
+
1196
+ .repo-card-meta {
1197
+ display: grid;
1198
+ gap: 8px;
1199
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
1200
+ }
1201
+
1202
+ .repo-card-meta span {
1203
+ background: var(--surface-elevated);
1204
+ border-radius: 12px;
1205
+ display: grid;
1206
+ gap: 4px;
1207
+ padding: 9px;
1208
+ }
1209
+
1210
+ .repo-card-meta small,
1211
+ .repo-remotes span,
1212
+ .provider-account-list small,
1213
+ .setup-path-row small {
1214
+ color: var(--text-muted);
1215
+ font-size: 0.74rem;
1216
+ font-weight: 900;
1217
+ text-transform: uppercase;
1218
+ }
1219
+
1220
+ .repo-card-meta strong,
1221
+ .provider-account-list strong {
1222
+ overflow: hidden;
1223
+ text-overflow: ellipsis;
1224
+ white-space: nowrap;
1225
+ }
1226
+
1227
+ .repo-remotes {
1228
+ display: grid;
1229
+ gap: 6px;
1230
+ }
1231
+
1232
+ .setup-path-list {
1233
+ display: grid;
1234
+ gap: 8px;
1235
+ }
1236
+
1237
+ .setup-path-row {
1238
+ align-items: center;
1239
+ display: grid;
1240
+ gap: 8px;
1241
+ grid-template-columns: auto minmax(0, 1fr) auto;
1242
+ }
1243
+
1244
+ .setup-path-row code {
1245
+ min-width: 0;
1246
+ }
1247
+
1248
+ .status-pill {
1249
+ background: color-mix(in srgb, var(--accent) 14%, transparent);
1250
+ border: 1px solid color-mix(in srgb, var(--accent) 38%, transparent);
1251
+ border-radius: 999px;
1252
+ color: var(--accent);
1253
+ font-size: 0.75rem;
1254
+ font-weight: 900;
1255
+ padding: 5px 9px;
1256
+ text-transform: uppercase;
1257
+ white-space: nowrap;
1258
+ }
1259
+
1260
+ .status-pill.warn {
1261
+ background: color-mix(in srgb, #d97706 16%, transparent);
1262
+ border-color: color-mix(in srgb, #d97706 42%, transparent);
1263
+ color: #b45309;
1264
+ }
1265
+
1266
+ .repo-tags {
1267
+ display: flex;
1268
+ flex-wrap: wrap;
1269
+ gap: 6px;
1270
+ }
1271
+
1272
+ .repo-tags span {
1273
+ background: var(--surface-elevated);
1274
+ border-radius: 999px;
1275
+ color: var(--text-secondary);
1276
+ font-size: 0.75rem;
1277
+ padding: 5px 8px;
1278
+ }
1279
+
1280
+ .switch-control {
1281
+ align-items: center;
1282
+ color: var(--text-secondary);
1283
+ display: inline-flex;
1284
+ gap: 8px;
1285
+ }
1286
+
1287
+ .appearance-switch {
1288
+ display: flex;
1289
+ justify-content: space-between;
1290
+ width: 100%;
1291
+ }
1292
+
1293
+ .appearance-switch strong {
1294
+ color: var(--text-muted);
1295
+ font-size: 0.74rem;
1296
+ font-weight: 900;
1297
+ letter-spacing: 0.08em;
1298
+ margin-right: auto;
1299
+ text-transform: uppercase;
1300
+ }
1301
+
1302
+ .desktop-status-bar {
1303
+ align-items: center;
1304
+ background: color-mix(in srgb, var(--surface-elevated) 96%, transparent);
1305
+ backdrop-filter: saturate(180%) blur(22px);
1306
+ border: 1px solid var(--border);
1307
+ border-radius: 14px;
1308
+ box-shadow: var(--glass-panel-shadow);
1309
+ color: var(--text-muted);
1310
+ display: flex;
1311
+ font-size: 0.78rem;
1312
+ font-variant-numeric: tabular-nums;
1313
+ font-weight: 800;
1314
+ gap: 10px;
1315
+ grid-column: 1 / -1;
1316
+ grid-row: 2;
1317
+ height: 30px;
1318
+ justify-content: center;
1319
+ line-height: 1;
1320
+ overflow: hidden;
1321
+ padding: 0 12px;
1322
+ white-space: nowrap;
1323
+ -webkit-backdrop-filter: saturate(180%) blur(22px);
1324
+ }
1325
+
1326
+ .desktop-status-bar strong {
1327
+ align-items: center;
1328
+ color: var(--text-secondary);
1329
+ display: inline-flex;
1330
+ line-height: 1;
1331
+ transform: translateY(3px);
1332
+ }
1333
+
1334
+ .desktop-status-bar span:not(.status-dot) {
1335
+ align-items: center;
1336
+ display: inline-flex;
1337
+ line-height: 1;
1338
+ transform: translateY(3px);
1339
+ }
1340
+
1341
+ .desktop-status-bar span:not(.status-dot)::before {
1342
+ color: var(--border-hover);
1343
+ content: "•";
1344
+ margin-right: 10px;
1345
+ }
1346
+
1347
+ .desktop-status-bar .status-dot + strong + span::before {
1348
+ content: "";
1349
+ margin-right: 0;
1350
+ }
1351
+
1352
+ .status-dot {
1353
+ background: var(--accent);
1354
+ border-radius: 999px;
1355
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 16%, transparent);
1356
+ flex: 0 0 auto;
1357
+ height: 8px;
1358
+ width: 8px;
1359
+ }
1360
+
1361
+ .status-dot.warn {
1362
+ background: #d97706;
1363
+ box-shadow: 0 0 0 3px color-mix(in srgb, #d97706 16%, transparent);
1364
+ }
1365
+
1366
+ .switch-control input {
1367
+ inline-size: 0;
1368
+ opacity: 0;
1369
+ position: absolute;
1370
+ }
1371
+
1372
+ .switch-control span {
1373
+ background: var(--surface-elevated);
1374
+ border: 1px solid var(--border);
1375
+ border-radius: 999px;
1376
+ display: inline-flex;
1377
+ height: 24px;
1378
+ position: relative;
1379
+ width: 44px;
1380
+ }
1381
+
1382
+ .switch-control span::after {
1383
+ background: var(--text-muted);
1384
+ border-radius: 999px;
1385
+ content: "";
1386
+ height: 18px;
1387
+ left: 3px;
1388
+ position: absolute;
1389
+ top: 2px;
1390
+ transition: transform 0.16s ease;
1391
+ width: 18px;
1392
+ }
1393
+
1394
+ .switch-control input:checked + span {
1395
+ background: color-mix(in srgb, var(--accent) 22%, transparent);
1396
+ border-color: color-mix(in srgb, var(--accent) 52%, transparent);
1397
+ }
1398
+
1399
+ .switch-control input:checked + span::after {
1400
+ background: var(--accent);
1401
+ transform: translateX(18px);
1402
+ }
1403
+
1404
+ .provider-card > header > strong {
1405
+ color: var(--accent);
1406
+ font-size: 1.8rem;
1407
+ letter-spacing: -0.06em;
1408
+ }
1409
+
1410
+ .provider-actions {
1411
+ border: 0;
1412
+ display: flex;
1413
+ flex-wrap: wrap;
1414
+ gap: 8px;
1415
+ margin: 0;
1416
+ padding: 0;
1417
+ }
1418
+
1419
+ .provider-actions button,
1420
+ .provider-account-list button {
1421
+ background: var(--surface-elevated);
1422
+ border: 1px solid var(--border);
1423
+ border-radius: 999px;
1424
+ color: var(--text-muted);
1425
+ padding: 7px 10px;
1426
+ }
1427
+
1428
+ .provider-account-list {
1429
+ display: grid;
1430
+ gap: 8px;
1431
+ list-style: none;
1432
+ margin: 0;
1433
+ padding: 0;
1434
+ }
1435
+
1436
+ .provider-account-list li {
1437
+ align-items: center;
1438
+ background: var(--surface-elevated);
1439
+ border-radius: 12px;
1440
+ display: grid;
1441
+ gap: 6px;
1442
+ grid-template-columns: minmax(0, 1.5fr) auto auto auto auto;
1443
+ padding: 10px;
1444
+ }
1445
+
1446
+ .provider-account-list span {
1447
+ background: color-mix(in srgb, var(--accent) 14%, transparent);
1448
+ border-radius: 999px;
1449
+ color: var(--accent);
1450
+ font-size: 0.75rem;
1451
+ font-weight: 900;
1452
+ padding: 4px 8px;
1453
+ }
1454
+
1455
+ .compact-empty {
1456
+ padding: 10px;
1457
+ }
1458
+
1459
+ @media (max-width: 1100px) {
1460
+ .file-workspace {
1461
+ grid-template-columns: 1fr;
1462
+ }
1463
+ }
1464
+
1465
+ @media (max-width: 980px) {
1466
+ .app-shell {
1467
+ grid-template-columns: 1fr;
1468
+ height: auto;
1469
+ min-height: 100vh;
1470
+ }
1471
+
1472
+ .app-shell.machine-rail-collapsed {
1473
+ grid-template-columns: 1fr;
1474
+ }
1475
+
1476
+ .machine-rail,
1477
+ .app-sidebar,
1478
+ .app-inset,
1479
+ .desktop-status-bar {
1480
+ grid-column: 1;
1481
+ grid-row: auto;
1482
+ }
1483
+
1484
+ .desktop-status-bar {
1485
+ flex-wrap: wrap;
1486
+ white-space: normal;
1487
+ }
1488
+
1489
+ .app-sidebar,
1490
+ .app-inset {
1491
+ min-height: auto;
1492
+ }
1493
+
1494
+ .workspace-header,
1495
+ .header-actions,
1496
+ .split-heading {
1497
+ align-items: stretch;
1498
+ flex-direction: column;
1499
+ }
1500
+
1501
+ .workspace-search {
1502
+ min-width: 0;
1503
+ width: 100%;
1504
+ }
1505
+ }
1506
+
1507
+ @media (max-width: 720px) {
1508
+ .app-shell {
1509
+ --shell-gutter: 0px;
1510
+ }
1511
+
1512
+ .app-sidebar,
1513
+ .app-inset {
1514
+ border-radius: 0;
1515
+ }
1516
+
1517
+ .data-row,
1518
+ .editable-row,
1519
+ .provider-account-list li {
1520
+ grid-template-columns: 1fr;
1521
+ }
1522
+
1523
+ .pill-tabs {
1524
+ width: 100%;
1525
+ }
1526
+
1527
+ .repo-setup-card header,
1528
+ .provider-card header,
1529
+ .setup-target-card header,
1530
+ .ai-app-card header,
1531
+ .setup-path-row,
1532
+ .repo-card-footer {
1533
+ align-items: stretch;
1534
+ flex-direction: column;
1535
+ }
1536
+
1537
+ .setup-path-row {
1538
+ grid-template-columns: 1fr;
1539
+ }
1540
+ }