repoview 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/CONTRIBUTING.md +4 -3
  3. package/DEVELOPMENT.md +70 -16
  4. package/README.md +36 -5
  5. package/dist/api.js +58 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli.js +224 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/csv.js +64 -0
  10. package/dist/csv.js.map +1 -0
  11. package/dist/format.js +25 -0
  12. package/dist/format.js.map +1 -0
  13. package/dist/git.js +67 -0
  14. package/dist/git.js.map +1 -0
  15. package/dist/gitignore.js +34 -0
  16. package/dist/gitignore.js.map +1 -0
  17. package/dist/linkcheck.js +310 -0
  18. package/dist/linkcheck.js.map +1 -0
  19. package/dist/markdown.js +493 -0
  20. package/dist/markdown.js.map +1 -0
  21. package/dist/net.js +10 -0
  22. package/dist/net.js.map +1 -0
  23. package/dist/paths.js +59 -0
  24. package/dist/paths.js.map +1 -0
  25. package/dist/reload.js +36 -0
  26. package/dist/reload.js.map +1 -0
  27. package/dist/repo-context.js +73 -0
  28. package/dist/repo-context.js.map +1 -0
  29. package/dist/repo-router.js +801 -0
  30. package/dist/repo-router.js.map +1 -0
  31. package/dist/review-cli.js +228 -0
  32. package/dist/review-cli.js.map +1 -0
  33. package/dist/server.js +116 -0
  34. package/dist/server.js.map +1 -0
  35. package/dist/session.js +86 -0
  36. package/dist/session.js.map +1 -0
  37. package/dist/types.js +2 -0
  38. package/dist/types.js.map +1 -0
  39. package/dist/views.js +633 -0
  40. package/dist/views.js.map +1 -0
  41. package/package.json +22 -6
  42. package/public/app.css +842 -0
  43. package/public/app.js +35 -2
  44. package/public/review.js +587 -0
  45. package/public/session.js +61 -0
  46. package/src/cli.js +0 -73
  47. package/src/gitignore.js +0 -34
  48. package/src/linkcheck.js +0 -312
  49. package/src/markdown.js +0 -364
  50. package/src/server.js +0 -760
  51. package/src/views.js +0 -479
package/public/app.css CHANGED
@@ -418,6 +418,17 @@ a {
418
418
  background: var(--subtleBg);
419
419
  }
420
420
 
421
+ .code-line-wrap {
422
+ display: inline;
423
+ }
424
+
425
+ .code-line-wrap.line-highlight {
426
+ background: color-mix(in srgb, var(--accent) 15%, transparent);
427
+ display: block;
428
+ margin: 0 -16px;
429
+ padding: 0 16px;
430
+ }
431
+
421
432
  .note {
422
433
  padding: 12px;
423
434
  border: 1px solid var(--border);
@@ -470,6 +481,110 @@ a {
470
481
  border-left-color: #cf222e;
471
482
  }
472
483
 
484
+ .markdown-body .md-frontmatter {
485
+ margin: 0 0 24px;
486
+ padding: 16px 18px 18px;
487
+ border: 1px solid var(--border);
488
+ border-radius: 8px;
489
+ background: var(--subtleBg);
490
+ }
491
+
492
+ .markdown-body .md-frontmatter > :first-child {
493
+ margin-top: 0;
494
+ }
495
+
496
+ .markdown-body .md-frontmatter > :last-child {
497
+ margin-bottom: 0;
498
+ }
499
+
500
+ .markdown-body .md-frontmatter-title {
501
+ margin: 0 0 6px;
502
+ padding: 0;
503
+ border: 0;
504
+ font-size: 1.6rem;
505
+ font-weight: 650;
506
+ line-height: 1.25;
507
+ }
508
+
509
+ .markdown-body .md-frontmatter-description {
510
+ margin: 0 0 12px;
511
+ color: var(--muted);
512
+ font-size: 0.95rem;
513
+ line-height: 1.5;
514
+ }
515
+
516
+ .markdown-body .md-frontmatter-meta {
517
+ display: flex;
518
+ flex-wrap: wrap;
519
+ align-items: center;
520
+ gap: 6px 12px;
521
+ font-size: 0.82rem;
522
+ color: var(--muted);
523
+ }
524
+
525
+ .markdown-body .md-frontmatter-meta + .md-frontmatter-extra {
526
+ margin-top: 12px;
527
+ }
528
+
529
+ .markdown-body .md-frontmatter-date,
530
+ .markdown-body .md-frontmatter-author {
531
+ display: inline-flex;
532
+ align-items: center;
533
+ gap: 4px;
534
+ }
535
+
536
+ .markdown-body .md-frontmatter-date::before {
537
+ content: "";
538
+ display: inline-block;
539
+ width: 12px;
540
+ height: 12px;
541
+ background: currentColor;
542
+ -webkit-mask-size: contain;
543
+ mask-size: contain;
544
+ -webkit-mask-repeat: no-repeat;
545
+ mask-repeat: no-repeat;
546
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='black' d='M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5h-11Zm11-1.5v-2.25a.25.25 0 0 0-.25-.25H2.75a.25.25 0 0 0-.25.25V6h11Z'/%3E%3C/svg%3E");
547
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='black' d='M4.75 0a.75.75 0 0 1 .75.75V2h5V.75a.75.75 0 0 1 1.5 0V2h1.25c.966 0 1.75.784 1.75 1.75v10.5A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25V3.75C1 2.784 1.784 2 2.75 2H4V.75A.75.75 0 0 1 4.75 0ZM2.5 7.5v6.75c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V7.5h-11Zm11-1.5v-2.25a.25.25 0 0 0-.25-.25H2.75a.25.25 0 0 0-.25.25V6h11Z'/%3E%3C/svg%3E");
548
+ }
549
+
550
+ .markdown-body .md-frontmatter-tags {
551
+ display: inline-flex;
552
+ flex-wrap: wrap;
553
+ gap: 6px;
554
+ margin: 0;
555
+ padding: 0;
556
+ list-style: none;
557
+ }
558
+
559
+ .markdown-body .md-frontmatter-tag {
560
+ display: inline-block;
561
+ padding: 1px 8px;
562
+ font-size: 0.78rem;
563
+ line-height: 1.5;
564
+ color: var(--accent);
565
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
566
+ border-radius: 999px;
567
+ }
568
+
569
+ .markdown-body .md-frontmatter-extra {
570
+ display: grid;
571
+ grid-template-columns: max-content 1fr;
572
+ gap: 4px 12px;
573
+ margin: 0;
574
+ font-size: 0.82rem;
575
+ }
576
+
577
+ .markdown-body .md-frontmatter-extra dt {
578
+ color: var(--muted);
579
+ font-weight: 600;
580
+ }
581
+
582
+ .markdown-body .md-frontmatter-extra dd {
583
+ margin: 0;
584
+ color: var(--text);
585
+ word-break: break-word;
586
+ }
587
+
473
588
  .markdown-body pre.mermaid {
474
589
  padding: 12px;
475
590
  border: 1px solid var(--border);
@@ -955,3 +1070,730 @@ a {
955
1070
  margin-bottom: 10px;
956
1071
  }
957
1072
  }
1073
+
1074
+ /* ===== Review Channel Styles (Mobile-First) ===== */
1075
+
1076
+ /* Thread list */
1077
+ .review-thread-list {
1078
+ display: flex;
1079
+ flex-direction: column;
1080
+ }
1081
+
1082
+ .review-thread-row {
1083
+ display: flex;
1084
+ align-items: center;
1085
+ gap: 12px;
1086
+ padding: 14px 16px;
1087
+ border-bottom: 1px solid var(--border);
1088
+ min-height: 44px;
1089
+ cursor: pointer;
1090
+ text-decoration: none;
1091
+ color: var(--text);
1092
+ }
1093
+
1094
+ .review-thread-row:last-child {
1095
+ border-bottom: none;
1096
+ }
1097
+
1098
+ .review-thread-row:hover {
1099
+ background: var(--subtleBg);
1100
+ }
1101
+
1102
+ .review-thread-info {
1103
+ display: flex;
1104
+ flex-direction: column;
1105
+ gap: 4px;
1106
+ min-width: 0;
1107
+ flex: 1;
1108
+ }
1109
+
1110
+ .review-thread-title {
1111
+ font-weight: 600;
1112
+ font-size: 15px;
1113
+ display: flex;
1114
+ align-items: center;
1115
+ gap: 8px;
1116
+ }
1117
+
1118
+ .review-thread-meta {
1119
+ font-size: 13px;
1120
+ color: var(--muted);
1121
+ }
1122
+
1123
+ .review-thread-arrow {
1124
+ font-size: 20px;
1125
+ color: var(--muted);
1126
+ flex-shrink: 0;
1127
+ }
1128
+
1129
+ .review-unread-badge {
1130
+ display: inline-flex;
1131
+ align-items: center;
1132
+ justify-content: center;
1133
+ min-width: 20px;
1134
+ height: 20px;
1135
+ padding: 0 6px;
1136
+ border-radius: 999px;
1137
+ background: var(--accent);
1138
+ color: #fff;
1139
+ font-size: 11px;
1140
+ font-weight: 700;
1141
+ }
1142
+
1143
+ .review-empty {
1144
+ padding: 24px 16px;
1145
+ text-align: center;
1146
+ color: var(--muted);
1147
+ }
1148
+
1149
+ /* Thread view */
1150
+ .review-thread-panel {
1151
+ overflow: visible;
1152
+ }
1153
+
1154
+ .review-thread-header {
1155
+ /* not sticky — let topbar handle stickiness to avoid overlap */
1156
+ flex-wrap: wrap;
1157
+ }
1158
+
1159
+ .review-thread-header .btn {
1160
+ flex-shrink: 0;
1161
+ }
1162
+
1163
+ .review-thread-title-text {
1164
+ font-weight: 600;
1165
+ font-size: 15px;
1166
+ min-width: 0;
1167
+ overflow: hidden;
1168
+ text-overflow: ellipsis;
1169
+ white-space: nowrap;
1170
+ }
1171
+
1172
+ @media (max-width: 560px) {
1173
+ .review-thread-title-text {
1174
+ white-space: normal;
1175
+ overflow: visible;
1176
+ font-size: 14px;
1177
+ }
1178
+ }
1179
+
1180
+ /* Messages */
1181
+ .review-messages {
1182
+ display: flex;
1183
+ flex-direction: column;
1184
+ gap: 0;
1185
+ }
1186
+
1187
+ .review-message {
1188
+ border-bottom: 1px solid var(--border);
1189
+ padding: 0;
1190
+ }
1191
+
1192
+ .review-message:last-child {
1193
+ border-bottom: none;
1194
+ }
1195
+
1196
+ .review-msg-header {
1197
+ display: flex;
1198
+ align-items: center;
1199
+ gap: 10px;
1200
+ padding: 10px 16px;
1201
+ background: var(--subtleBg);
1202
+ border-bottom: 1px solid var(--border);
1203
+ font-size: 13px;
1204
+ }
1205
+
1206
+ .review-msg-role {
1207
+ font-weight: 700;
1208
+ font-size: 13px;
1209
+ }
1210
+
1211
+ .review-msg-agent .review-msg-role {
1212
+ color: var(--accent);
1213
+ }
1214
+
1215
+ .review-msg-user .review-msg-role {
1216
+ color: #1a7f37;
1217
+ }
1218
+
1219
+ @media (prefers-color-scheme: dark) {
1220
+ .review-msg-user .review-msg-role {
1221
+ color: #3fb950;
1222
+ }
1223
+ }
1224
+
1225
+ .review-msg-time {
1226
+ color: var(--muted);
1227
+ font-size: 12px;
1228
+ margin-left: auto;
1229
+ }
1230
+
1231
+ .review-msg-content {
1232
+ padding: 16px;
1233
+ }
1234
+
1235
+ .review-msg-text {
1236
+ white-space: pre-wrap;
1237
+ font-size: 14px;
1238
+ line-height: 1.6;
1239
+ }
1240
+
1241
+ /* Inline comments */
1242
+ .review-inline-comments {
1243
+ padding: 8px 16px 16px;
1244
+ display: flex;
1245
+ flex-direction: column;
1246
+ gap: 8px;
1247
+ }
1248
+
1249
+ .review-comment-card {
1250
+ border: 1px solid var(--border);
1251
+ border-left: 3px solid var(--accent);
1252
+ border-radius: 6px;
1253
+ background: var(--subtleBg);
1254
+ padding: 10px 12px;
1255
+ font-size: 13px;
1256
+ }
1257
+
1258
+ .review-comment-card.resolved {
1259
+ opacity: 0.6;
1260
+ border-left-color: var(--muted);
1261
+ }
1262
+
1263
+ .review-comment-header {
1264
+ display: flex;
1265
+ align-items: center;
1266
+ gap: 8px;
1267
+ flex-wrap: wrap;
1268
+ margin-bottom: 6px;
1269
+ }
1270
+
1271
+ .review-comment-anchor {
1272
+ font-weight: 600;
1273
+ font-size: 12px;
1274
+ color: var(--accent);
1275
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1276
+ }
1277
+
1278
+ .review-comment-time {
1279
+ font-size: 11px;
1280
+ color: var(--muted);
1281
+ }
1282
+
1283
+ .review-comment-actions {
1284
+ margin-left: auto;
1285
+ display: flex;
1286
+ gap: 4px;
1287
+ }
1288
+
1289
+ .review-comment-body {
1290
+ line-height: 1.5;
1291
+ }
1292
+
1293
+ .review-resolved-label {
1294
+ font-size: 11px;
1295
+ color: var(--muted);
1296
+ font-style: italic;
1297
+ }
1298
+
1299
+ /* Comment count badge on blocks */
1300
+ .review-comment-badge {
1301
+ position: absolute;
1302
+ right: 4px;
1303
+ top: 2px;
1304
+ display: inline-flex;
1305
+ align-items: center;
1306
+ justify-content: center;
1307
+ min-width: 20px;
1308
+ height: 20px;
1309
+ padding: 0 5px;
1310
+ border-radius: 999px;
1311
+ background: var(--accent);
1312
+ color: #fff;
1313
+ font-size: 11px;
1314
+ font-weight: 700;
1315
+ font-family: ui-sans-serif, system-ui, sans-serif;
1316
+ cursor: pointer;
1317
+ z-index: 1;
1318
+ }
1319
+
1320
+ .review-comment-badge:hover {
1321
+ opacity: 0.85;
1322
+ }
1323
+
1324
+ /* Existing comments shown inline in thread form */
1325
+ .review-inline-thread {
1326
+ display: flex;
1327
+ flex-direction: column;
1328
+ gap: 6px;
1329
+ margin-bottom: 10px;
1330
+ }
1331
+
1332
+ .review-inline-thread .review-comment-card {
1333
+ font-size: 13px;
1334
+ }
1335
+
1336
+ /* Gutter comment button */
1337
+ .review-gutter-btn {
1338
+ position: absolute;
1339
+ left: -28px;
1340
+ top: 2px;
1341
+ width: 22px;
1342
+ height: 22px;
1343
+ min-width: 22px;
1344
+ min-height: 22px;
1345
+ border-radius: 50%;
1346
+ border: 1px solid var(--border);
1347
+ background: var(--btn);
1348
+ color: var(--accent);
1349
+ font-size: 16px;
1350
+ font-weight: 700;
1351
+ line-height: 1;
1352
+ cursor: pointer;
1353
+ display: flex;
1354
+ align-items: center;
1355
+ justify-content: center;
1356
+ opacity: 0;
1357
+ transition: opacity 0.15s ease;
1358
+ }
1359
+
1360
+ [data-source-line-start]:hover .review-gutter-btn,
1361
+ .review-gutter-btn:focus {
1362
+ opacity: 1;
1363
+ }
1364
+
1365
+ /* On mobile, hide gutter buttons — blocks are tappable instead */
1366
+ @media (max-width: 560px) {
1367
+ .review-gutter-btn {
1368
+ display: none;
1369
+ }
1370
+
1371
+ .review-msg-agent [data-source-line-start] {
1372
+ cursor: pointer;
1373
+ border-radius: 4px;
1374
+ transition: background 0.15s ease;
1375
+ }
1376
+
1377
+ .review-msg-agent [data-source-line-start]:active {
1378
+ background: color-mix(in srgb, var(--accent) 8%, transparent);
1379
+ }
1380
+ }
1381
+
1382
+ /* Inline comment form */
1383
+ .review-inline-form {
1384
+ margin: 8px 0;
1385
+ padding: 10px 12px;
1386
+ border: 1px solid var(--accent);
1387
+ border-radius: 6px;
1388
+ background: var(--panel);
1389
+ }
1390
+
1391
+ .review-inline-textarea {
1392
+ width: 100%;
1393
+ box-sizing: border-box;
1394
+ padding: 8px 10px;
1395
+ border: 1px solid var(--border);
1396
+ border-radius: 4px;
1397
+ background: var(--bg);
1398
+ color: var(--text);
1399
+ font-family: inherit;
1400
+ font-size: 14px;
1401
+ resize: vertical;
1402
+ min-height: 60px;
1403
+ }
1404
+
1405
+ .review-inline-actions {
1406
+ display: flex;
1407
+ gap: 8px;
1408
+ margin-top: 8px;
1409
+ justify-content: flex-end;
1410
+ }
1411
+
1412
+ /* Reply form */
1413
+ .review-reply-form {
1414
+ padding: 16px;
1415
+ border-top: 1px solid var(--border);
1416
+ background: var(--subtleBg);
1417
+ }
1418
+
1419
+ .review-reply-textarea {
1420
+ width: 100%;
1421
+ box-sizing: border-box;
1422
+ padding: 10px 12px;
1423
+ border: 1px solid var(--border);
1424
+ border-radius: 6px;
1425
+ background: var(--bg);
1426
+ color: var(--text);
1427
+ font-family: inherit;
1428
+ font-size: 14px;
1429
+ resize: vertical;
1430
+ min-height: 80px;
1431
+ }
1432
+
1433
+ .review-reply-textarea:focus {
1434
+ outline: none;
1435
+ border-color: var(--accent);
1436
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 20%, transparent);
1437
+ }
1438
+
1439
+ .review-reply-btn {
1440
+ margin-top: 10px;
1441
+ min-width: 120px;
1442
+ min-height: 44px;
1443
+ font-size: 15px;
1444
+ background: var(--accent);
1445
+ color: #fff;
1446
+ border-color: var(--accent);
1447
+ display: block;
1448
+ margin-left: auto;
1449
+ }
1450
+
1451
+ .review-reply-btn:hover {
1452
+ opacity: 0.9;
1453
+ background: var(--accent);
1454
+ }
1455
+
1456
+ .review-reply-btn:disabled {
1457
+ opacity: 0.5;
1458
+ cursor: not-allowed;
1459
+ }
1460
+
1461
+ /* Responsive - larger screens */
1462
+ @media (min-width: 720px) {
1463
+ .review-gutter-btn {
1464
+ left: -32px;
1465
+ width: 24px;
1466
+ height: 24px;
1467
+ }
1468
+
1469
+ .review-msg-content.markdown-body {
1470
+ padding-left: 40px;
1471
+ }
1472
+ }
1473
+
1474
+ /* ===== Code Reference Links ===== */
1475
+
1476
+ .code-ref {
1477
+ color: var(--accent);
1478
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1479
+ font-size: 0.9em;
1480
+ background: color-mix(in srgb, var(--accent) 8%, transparent);
1481
+ padding: 1px 5px;
1482
+ border-radius: 3px;
1483
+ cursor: pointer;
1484
+ text-decoration: none;
1485
+ white-space: nowrap;
1486
+ }
1487
+
1488
+ .code-ref:hover {
1489
+ background: color-mix(in srgb, var(--accent) 16%, transparent);
1490
+ text-decoration: underline;
1491
+ }
1492
+
1493
+ /* ===== Code Popup ===== */
1494
+
1495
+ .code-popup-overlay {
1496
+ position: fixed;
1497
+ inset: 0;
1498
+ z-index: 100;
1499
+ background: rgba(0, 0, 0, 0.5);
1500
+ display: flex;
1501
+ align-items: center;
1502
+ justify-content: center;
1503
+ padding: 16px;
1504
+ }
1505
+
1506
+ .code-popup {
1507
+ background: var(--panel);
1508
+ border: 1px solid var(--border);
1509
+ border-radius: 8px;
1510
+ width: 100%;
1511
+ max-width: 780px;
1512
+ height: 70vh;
1513
+ display: flex;
1514
+ flex-direction: column;
1515
+ box-shadow: 0 16px 48px rgba(0, 0, 0, 0.2);
1516
+ overflow: hidden;
1517
+ }
1518
+
1519
+ .code-popup-header {
1520
+ display: flex;
1521
+ align-items: center;
1522
+ gap: 8px;
1523
+ padding: 10px 14px;
1524
+ border-bottom: 1px solid var(--border);
1525
+ background: var(--subtleBg);
1526
+ flex-shrink: 0;
1527
+ flex-wrap: wrap;
1528
+ }
1529
+
1530
+ .code-popup-filepath {
1531
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1532
+ font-size: 13px;
1533
+ font-weight: 600;
1534
+ color: var(--accent);
1535
+ text-decoration: none;
1536
+ min-width: 0;
1537
+ overflow: hidden;
1538
+ text-overflow: ellipsis;
1539
+ white-space: nowrap;
1540
+ }
1541
+
1542
+ .code-popup-filepath:hover {
1543
+ text-decoration: underline;
1544
+ }
1545
+
1546
+ .code-popup-tab {
1547
+ font-size: 12px;
1548
+ padding: 3px 10px;
1549
+ }
1550
+
1551
+ .code-popup-tab.active {
1552
+ background: var(--accent);
1553
+ color: #fff;
1554
+ border-color: var(--accent);
1555
+ }
1556
+
1557
+ .code-popup-close {
1558
+ width: 28px;
1559
+ height: 28px;
1560
+ display: flex;
1561
+ align-items: center;
1562
+ justify-content: center;
1563
+ border: none;
1564
+ background: none;
1565
+ color: var(--muted);
1566
+ font-size: 20px;
1567
+ cursor: pointer;
1568
+ border-radius: 4px;
1569
+ flex-shrink: 0;
1570
+ }
1571
+
1572
+ .code-popup-close:hover {
1573
+ background: var(--btnHover);
1574
+ color: var(--text);
1575
+ }
1576
+
1577
+ .code-popup-body {
1578
+ overflow: auto;
1579
+ flex: 1 1 auto;
1580
+ min-height: 0;
1581
+ -webkit-overflow-scrolling: touch;
1582
+ -webkit-text-size-adjust: 100%;
1583
+ text-size-adjust: 100%;
1584
+ }
1585
+
1586
+ .code-popup-loading,
1587
+ .code-popup-empty {
1588
+ padding: 24px;
1589
+ text-align: center;
1590
+ color: var(--muted);
1591
+ font-size: 14px;
1592
+ }
1593
+
1594
+ /* Code table inside popup */
1595
+ .code-table {
1596
+ width: 100%;
1597
+ border-collapse: collapse;
1598
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
1599
+ font-size: 13px;
1600
+ line-height: 1.5;
1601
+ -webkit-text-size-adjust: 100%;
1602
+ text-size-adjust: 100%;
1603
+ }
1604
+
1605
+ .code-table .code-ln {
1606
+ width: 1px;
1607
+ padding: 0 12px 0 14px;
1608
+ text-align: right;
1609
+ color: var(--muted);
1610
+ user-select: none;
1611
+ white-space: nowrap;
1612
+ vertical-align: top;
1613
+ }
1614
+
1615
+ .code-table .code-content {
1616
+ padding: 0 14px 0 8px;
1617
+ white-space: pre;
1618
+ }
1619
+
1620
+ .code-table .diff-marker {
1621
+ width: 1px;
1622
+ padding: 0 4px;
1623
+ color: var(--muted);
1624
+ user-select: none;
1625
+ white-space: nowrap;
1626
+ vertical-align: top;
1627
+ }
1628
+
1629
+ .code-line.highlight {
1630
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
1631
+ }
1632
+
1633
+ .code-line.highlight .code-ln {
1634
+ color: var(--accent);
1635
+ font-weight: 600;
1636
+ }
1637
+
1638
+ /* Diff line colors */
1639
+ .diff-add {
1640
+ background: rgba(63, 185, 80, 0.08);
1641
+ }
1642
+
1643
+ .diff-add .diff-marker {
1644
+ color: #1a7f37;
1645
+ }
1646
+
1647
+ .diff-del {
1648
+ background: rgba(248, 81, 73, 0.08);
1649
+ }
1650
+
1651
+ .diff-del .diff-marker {
1652
+ color: #cf222e;
1653
+ }
1654
+
1655
+ .diff-hunk {
1656
+ background: var(--subtleBg);
1657
+ color: var(--muted);
1658
+ font-size: 12px;
1659
+ }
1660
+
1661
+ .diff-hunk td {
1662
+ padding: 4px 14px;
1663
+ }
1664
+
1665
+ .diff-add.highlight {
1666
+ background: rgba(63, 185, 80, 0.18);
1667
+ }
1668
+
1669
+ .diff-ctx.highlight {
1670
+ background: color-mix(in srgb, var(--accent) 12%, transparent);
1671
+ }
1672
+
1673
+ @media (prefers-color-scheme: dark) {
1674
+ .diff-add {
1675
+ background: rgba(63, 185, 80, 0.1);
1676
+ }
1677
+ .diff-add .diff-marker {
1678
+ color: #3fb950;
1679
+ }
1680
+ .diff-del {
1681
+ background: rgba(248, 81, 73, 0.1);
1682
+ }
1683
+ .diff-del .diff-marker {
1684
+ color: #f85149;
1685
+ }
1686
+ .diff-add.highlight {
1687
+ background: rgba(63, 185, 80, 0.2);
1688
+ }
1689
+ }
1690
+
1691
+ /* Mobile: popup goes full width */
1692
+ @media (max-width: 560px) {
1693
+ .code-popup-overlay {
1694
+ padding: 0;
1695
+ align-items: flex-end;
1696
+ }
1697
+
1698
+ .code-popup {
1699
+ max-width: 100%;
1700
+ height: 80vh;
1701
+ border-radius: 12px 12px 0 0;
1702
+ border-bottom: none;
1703
+ }
1704
+
1705
+ .code-table {
1706
+ font-size: 11px !important;
1707
+ }
1708
+
1709
+ .code-table .code-ln {
1710
+ padding: 0 6px 0 8px;
1711
+ font-size: 10px !important;
1712
+ }
1713
+
1714
+ .code-table .code-content {
1715
+ padding: 0 8px 0 4px;
1716
+ }
1717
+ }
1718
+
1719
+ /* Repo switcher dropdown (topbar) */
1720
+ .repo-switcher {
1721
+ position: relative;
1722
+ display: inline-block;
1723
+ }
1724
+ .repo-switcher summary {
1725
+ list-style: none;
1726
+ cursor: pointer;
1727
+ }
1728
+ .repo-switcher summary::-webkit-details-marker {
1729
+ display: none;
1730
+ }
1731
+ /* The switcher sits on the left of the topbar, so its panel grows rightward
1732
+ (the shared .menu-panel defaults to right:0 for the right-aligned More menu). */
1733
+ .repo-switcher .menu-panel {
1734
+ right: auto;
1735
+ left: 0;
1736
+ max-width: calc(100vw - 24px);
1737
+ }
1738
+ .menu-item.current {
1739
+ font-weight: 600;
1740
+ }
1741
+ .menu-item.manage {
1742
+ margin-top: 4px;
1743
+ border-top: 1px solid var(--border);
1744
+ border-radius: 0 0 6px 6px;
1745
+ }
1746
+
1747
+ /* Session management page */
1748
+ .card {
1749
+ border: 1px solid var(--border);
1750
+ border-radius: 8px;
1751
+ background: var(--panel);
1752
+ padding: 16px;
1753
+ margin: 16px 0;
1754
+ }
1755
+ .card-title {
1756
+ margin: 0 0 12px;
1757
+ font-size: 15px;
1758
+ }
1759
+ .muted {
1760
+ color: var(--muted);
1761
+ font-size: 13px;
1762
+ }
1763
+ .session-table {
1764
+ width: 100%;
1765
+ border-collapse: collapse;
1766
+ }
1767
+ .session-table th,
1768
+ .session-table td {
1769
+ text-align: left;
1770
+ padding: 8px 10px;
1771
+ border-bottom: 1px solid var(--border);
1772
+ vertical-align: middle;
1773
+ }
1774
+ .session-table th {
1775
+ font-size: 12px;
1776
+ color: var(--muted);
1777
+ text-transform: uppercase;
1778
+ letter-spacing: 0.03em;
1779
+ }
1780
+ .session-table tr:last-child td {
1781
+ border-bottom: none;
1782
+ }
1783
+ .session-path {
1784
+ color: var(--muted);
1785
+ word-break: break-all;
1786
+ }
1787
+ .session-add {
1788
+ display: flex;
1789
+ gap: 8px;
1790
+ }
1791
+ .session-add input {
1792
+ flex: 1;
1793
+ padding: 8px 10px;
1794
+ border: 1px solid var(--border);
1795
+ border-radius: 6px;
1796
+ background: var(--panel);
1797
+ color: var(--text);
1798
+ font: inherit;
1799
+ }