@happy-nut/monacori 0.1.21 → 0.1.22

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.
package/dist/viewer.css CHANGED
@@ -69,8 +69,9 @@ html, body { margin: 0; min-height: 100%; }
69
69
  /* Reserve the scrollbar gutter so collapsing/expanding a file does not shift the layout. */
70
70
  html { scrollbar-gutter: stable; }
71
71
  body {
72
+ --rail-width: 46px;
72
73
  display: grid;
73
- grid-template-columns: var(--sidebar-width, 280px) minmax(0, 1fr);
74
+ grid-template-columns: var(--rail-width) var(--sidebar-width, 280px) minmax(0, 1fr);
74
75
  /* Row 1 = content, row 2 = the integrated terminal. The terminal is a real grid row (not a fixed
75
76
  overlay), so content shrinks above it and the caret can never scroll behind it. When the terminal
76
77
  is .hidden (display:none) the auto row collapses to 0 and content fills the viewport. */
@@ -82,6 +83,7 @@ body {
82
83
  }
83
84
  .sidebar {
84
85
  grid-row: 1 / -1; /* full height, left of both the content and terminal rows */
86
+ grid-column: 2;
85
87
  height: 100vh;
86
88
  display: flex;
87
89
  flex-direction: column;
@@ -98,7 +100,7 @@ body {
98
100
  .sidebar-resizer {
99
101
  position: fixed;
100
102
  top: 0;
101
- left: var(--sidebar-width, 280px);
103
+ left: calc(var(--rail-width, 46px) + var(--sidebar-width, 280px));
102
104
  width: 9px;
103
105
  height: 100vh;
104
106
  margin-left: -5px;
@@ -150,9 +152,61 @@ body {
150
152
  text-overflow: ellipsis;
151
153
  }
152
154
  .tabs { display: none; }
155
+ /* ===== IntelliJ-style activity rail: icon-per-view column, hover tooltip with the shortcut. ===== */
156
+ .activity-rail {
157
+ grid-row: 1 / -1;
158
+ grid-column: 1;
159
+ display: flex;
160
+ flex-direction: column;
161
+ align-items: center;
162
+ padding: 8px 0;
163
+ background: var(--sidebar);
164
+ border-right: 1px solid var(--border);
165
+ overflow: visible; /* let tooltips escape to the right, over the sidebar */
166
+ z-index: 32;
167
+ }
168
+ .rail-group { display: flex; flex-direction: column; align-items: center; gap: 2px; }
169
+ .rail-bottom { margin-top: auto; } /* pin terminal + settings to the bottom */
170
+ .rail-btn {
171
+ position: relative;
172
+ flex: none;
173
+ width: 34px; height: 34px;
174
+ display: flex; align-items: center; justify-content: center;
175
+ border: 0; border-radius: 7px;
176
+ background: transparent; color: var(--muted);
177
+ cursor: pointer; padding: 0;
178
+ }
179
+ .rail-btn:hover { color: var(--text); background: color-mix(in srgb, var(--active) 12%, transparent); }
180
+ .rail-btn.is-active { color: var(--active); background: color-mix(in srgb, var(--active) 16%, transparent); }
181
+ /* Left accent bar at the rail edge marks the active view (like IntelliJ). */
182
+ .rail-btn.is-active::before {
183
+ content: ""; position: absolute; left: -6px; top: 5px; bottom: 5px; width: 2px;
184
+ background: var(--active); border-radius: 0 2px 2px 0;
185
+ }
186
+ .rail-gear { font-size: 16px; line-height: 1; }
187
+ .rail-tip {
188
+ position: absolute; left: calc(100% + 10px); top: 50%; transform: translateY(-50%);
189
+ display: flex; align-items: center; gap: 8px; white-space: nowrap;
190
+ background: var(--panel); color: var(--text);
191
+ border: 1px solid var(--border); border-radius: 6px;
192
+ padding: 5px 9px; font-size: 12px;
193
+ box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
194
+ opacity: 0; pointer-events: none; transition: opacity .12s ease;
195
+ z-index: 90;
196
+ }
197
+ .rail-btn:hover .rail-tip, .rail-btn:focus-visible .rail-tip { opacity: 1; }
198
+ .rail-tip kbd {
199
+ font: 11px Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
200
+ color: var(--muted); background: var(--bg);
201
+ border: 1px solid var(--border); border-radius: 4px; padding: 1px 5px;
202
+ }
203
+ /* Current branch chip under the project name in the sidebar header. */
204
+ .brand-branch { display: inline-flex; align-items: center; gap: 5px; margin-top: 3px; min-width: 0; color: var(--muted); font-size: 12px; }
205
+ .brand-branch-icon { flex: none; opacity: 0.8; }
206
+ .brand-branch-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums; }
153
207
  .tab, .plain-button {
154
208
  border: 1px solid var(--border);
155
- border-radius: 6px;
209
+ border-radius: 0;
156
210
  padding: 6px 9px;
157
211
  color: var(--text);
158
212
  background: var(--panel);
@@ -186,7 +240,7 @@ body {
186
240
  .settings-btn {
187
241
  flex: none;
188
242
  border: 1px solid transparent;
189
- border-radius: 6px;
243
+ border-radius: 0;
190
244
  background: transparent;
191
245
  color: var(--muted);
192
246
  font-size: 14px;
@@ -206,7 +260,7 @@ body {
206
260
  overflow: auto;
207
261
  padding: 12px;
208
262
  border: 1px solid var(--border);
209
- border-radius: 10px;
263
+ border-radius: 0;
210
264
  background: var(--panel);
211
265
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
212
266
  font-size: 12px;
@@ -231,7 +285,7 @@ body {
231
285
  .settings-panel {
232
286
  display: flex;
233
287
  width: 980px; max-width: 90vw; height: 700px; max-height: 88vh;
234
- background: var(--panel); border: 1px solid var(--border); border-radius: 12px;
288
+ background: var(--panel); border: 1px solid var(--border); border-radius: 0;
235
289
  overflow: hidden; box-shadow: 0 12px 48px rgba(0, 0, 0, 0.55);
236
290
  }
237
291
  .settings-nav {
@@ -240,7 +294,7 @@ body {
240
294
  display: flex; flex-direction: column; gap: 4px;
241
295
  }
242
296
  .settings-nav-title { font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); padding: 4px 10px 8px; }
243
- .settings-cat { text-align: left; border: 0; background: transparent; color: var(--text); padding: 7px 10px; border-radius: 6px; font-size: 13px; cursor: pointer; }
297
+ .settings-cat { text-align: left; border: 0; background: transparent; color: var(--text); padding: 7px 10px; border-radius: 0; font-size: 13px; cursor: pointer; }
244
298
  .settings-cat:hover { background: color-mix(in srgb, var(--active) 12%, transparent); }
245
299
  .settings-cat.active { background: color-mix(in srgb, var(--active) 20%, transparent); color: var(--active); font-weight: 600; }
246
300
  .settings-body { flex: 1 1 auto; min-width: 0; padding: 24px 28px; overflow: auto; }
@@ -251,14 +305,14 @@ body {
251
305
  .settings-textarea {
252
306
  width: 100%; box-sizing: border-box; resize: vertical; min-height: 70px;
253
307
  background: var(--bg); color: var(--text);
254
- border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px;
308
+ border: 1px solid var(--border); border-radius: 0; padding: 10px 12px;
255
309
  font: 12px/1.55 ui-sans-serif, system-ui, sans-serif;
256
310
  }
257
311
  .settings-textarea:focus { outline: none; border-color: var(--active); }
258
312
  .settings-select {
259
313
  width: auto; box-sizing: border-box;
260
314
  background: var(--bg); color: var(--text);
261
- border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px;
315
+ border: 1px solid var(--border); border-radius: 0; padding: 8px 12px;
262
316
  font: 12px/1.55 ui-sans-serif, system-ui, sans-serif;
263
317
  }
264
318
  .settings-select:focus { outline: none; border-color: var(--active); }
@@ -274,11 +328,11 @@ body {
274
328
  .keys-grid { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 5px 10px; align-items: center; margin-bottom: 2px; }
275
329
  .keys-grid kbd {
276
330
  justify-self: start;
277
- font: 10px Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
331
+ font: 12.5px Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
278
332
  background: var(--bg);
279
333
  border: 1px solid var(--border);
280
- border-radius: 4px;
281
- padding: 2px 5px;
334
+ border-radius: 0;
335
+ padding: 3px 7px;
282
336
  color: var(--text);
283
337
  white-space: nowrap;
284
338
  }
@@ -308,7 +362,7 @@ body {
308
362
  flex: none;
309
363
  padding: 3px 10px;
310
364
  border: 1px solid var(--border);
311
- border-radius: 999px;
365
+ border-radius: 0;
312
366
  color: var(--muted);
313
367
  background: var(--panel);
314
368
  font-size: 11px;
@@ -325,7 +379,7 @@ body {
325
379
  width: 13px;
326
380
  height: 13px;
327
381
  border: 1px solid currentColor;
328
- border-radius: 4px;
382
+ border-radius: 0;
329
383
  opacity: 0.75;
330
384
  }
331
385
  .diff-viewed-toggle.is-viewed {
@@ -431,7 +485,7 @@ td.d2h-del:not(.d2h-code-side-linenumber) { color: #d8e0e8; }
431
485
  .d2h-ins .d2h-change { background: var(--add-strong); }
432
486
  .d2h-code-line-ctn ins, .d2h-code-line-ctn del {
433
487
  text-decoration: none;
434
- border-radius: 2px;
488
+ border-radius: 0;
435
489
  padding: 0 1px;
436
490
  box-decoration-break: clone;
437
491
  -webkit-box-decoration-break: clone;
@@ -446,10 +500,10 @@ td.d2h-del:not(.d2h-code-side-linenumber) { color: #d8e0e8; }
446
500
  }
447
501
  .d2h-diff-table tr.diff-active-row td { background: rgba(74, 136, 199, 0.16) !important; }
448
502
  .d2h-diff-table tr.diff-active-row td.d2h-code-side-linenumber { box-shadow: inset 2px 0 0 var(--active); }
449
- .review-status .ws-ignored { color: var(--token-tag); border: 1px solid color-mix(in srgb, var(--token-tag) 45%, transparent); border-radius: 999px; padding: 0 7px; }
450
- .index-progress { display: inline-flex; width: 54px; height: 4px; border-radius: 999px; background: color-mix(in srgb, var(--muted) 30%, transparent); overflow: hidden; vertical-align: middle; }
503
+ .review-status .ws-ignored { color: var(--token-tag); border: 1px solid color-mix(in srgb, var(--token-tag) 45%, transparent); border-radius: 0; padding: 0 7px; }
504
+ .index-progress { display: inline-flex; width: 54px; height: 4px; border-radius: 0; background: color-mix(in srgb, var(--muted) 30%, transparent); overflow: hidden; vertical-align: middle; }
451
505
  .index-progress.hidden { display: none; }
452
- .index-progress-bar { width: 0; height: 100%; background: var(--active); border-radius: 999px; transition: width 0.18s ease; }
506
+ .index-progress-bar { width: 0; height: 100%; background: var(--active); border-radius: 0; transition: width 0.18s ease; }
453
507
  .d2h-file-collapse {
454
508
  display: inline-flex;
455
509
  align-items: center;
@@ -457,7 +511,7 @@ td.d2h-del:not(.d2h-code-side-linenumber) { color: #d8e0e8; }
457
511
  margin-left: 8px;
458
512
  padding: 3px 10px;
459
513
  border: 1px solid var(--border);
460
- border-radius: 999px;
514
+ border-radius: 0;
461
515
  color: var(--muted);
462
516
  background: var(--panel);
463
517
  font-size: 11px;
@@ -475,7 +529,7 @@ td.d2h-del:not(.d2h-code-side-linenumber) { color: #d8e0e8; }
475
529
  width: 13px;
476
530
  height: 13px;
477
531
  border: 1px solid currentColor;
478
- border-radius: 4px;
532
+ border-radius: 0;
479
533
  opacity: 0.75;
480
534
  }
481
535
  .d2h-file-collapse-input { display: none; }
@@ -507,7 +561,7 @@ td.d2h-del:not(.d2h-code-side-linenumber) { color: #d8e0e8; }
507
561
  min-height: 18px;
508
562
  padding: 1px 5px 1px calc(7px + (var(--depth) * 14px));
509
563
  color: var(--text);
510
- border-radius: 6px;
564
+ border-radius: 0;
511
565
  cursor: default;
512
566
  list-style: none;
513
567
  }
@@ -526,7 +580,7 @@ td.d2h-del:not(.d2h-code-side-linenumber) { color: #d8e0e8; }
526
580
  .file-link.tree-file { padding-left: calc(8px + (var(--depth) * 14px)); }
527
581
  /* Arrow-key focus in the tree (changes/files) matches the active-file highlight — a tinted fill + accent
528
582
  border — so navigating the file tree reads the same as the diff-side selection (not a faint 1px outline). */
529
- .tree-focus { background: color-mix(in srgb, var(--active) 20%, transparent); border-radius: 6px; }
583
+ .tree-focus { background: color-mix(in srgb, var(--active) 20%, transparent); border-radius: 0; }
530
584
  .file-link.tree-focus { border-color: var(--active); }
531
585
  summary.tree-focus { background: color-mix(in srgb, var(--active) 20%, transparent); }
532
586
  .file-link {
@@ -538,7 +592,7 @@ summary.tree-focus { background: color-mix(in srgb, var(--active) 20%, transpare
538
592
  padding: 1px 6px;
539
593
  color: var(--text);
540
594
  text-decoration: none;
541
- border-radius: 6px;
595
+ border-radius: 0;
542
596
  border: 1px solid transparent;
543
597
  background: transparent;
544
598
  width: 100%;
@@ -565,7 +619,7 @@ summary.tree-focus { background: color-mix(in srgb, var(--active) 20%, transpare
565
619
  justify-content: center;
566
620
  min-width: 16px;
567
621
  height: 16px;
568
- border-radius: 4px;
622
+ border-radius: 0;
569
623
  padding: 0 3px;
570
624
  font-size: 9px;
571
625
  font-weight: 700;
@@ -580,7 +634,7 @@ summary.tree-focus { background: color-mix(in srgb, var(--active) 20%, transpare
580
634
  .status-deleted { background: var(--del); color: #cf222e; }
581
635
  .status-renamed { background: #fff8c5; color: #9a6700; }
582
636
  .status-source { background: var(--line); color: var(--muted); }
583
- .content { min-width: 0; padding: 0; display: flex; flex-direction: column; min-height: 0; overflow: hidden; grid-column: 2; grid-row: 1; }
637
+ .content { min-width: 0; padding: 0; display: flex; flex-direction: column; min-height: 0; overflow: hidden; grid-column: 3; grid-row: 1; }
584
638
  /* Pin the diff's horizontal scrollbar to the viewport bottom instead of letting it float
585
639
  mid-screen when a file's diff is short: fill the content column vertically so the last
586
640
  file's diff body extends all the way down. */
@@ -595,7 +649,7 @@ summary.tree-focus { background: color-mix(in srgb, var(--active) 20%, transpare
595
649
  scrolls naturally inside .diff2html-container. */
596
650
  /* Slimmer scrollbars — the default overlay bars read as chunky on the dark UI. */
597
651
  ::-webkit-scrollbar { width: 9px; height: 9px; }
598
- ::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 32%, transparent); border-radius: 5px; }
652
+ ::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--muted) 32%, transparent); border-radius: 0; }
599
653
  ::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--muted) 52%, transparent); }
600
654
  ::-webkit-scrollbar-track { background: transparent; }
601
655
  .toolbar {
@@ -638,7 +692,7 @@ h1 { margin: 0; font-size: 18px; }
638
692
  .toolbar p { margin: 4px 0 0; color: var(--muted); font-size: 12px; }
639
693
  .empty { padding: 24px; color: var(--muted); }
640
694
  .source-viewer { min-height: 0; } /* grid sizes this; a 100vh min would overflow the content row */
641
- .source-toolbar { margin-bottom: 0; }
695
+ .source-toolbar { flex: none; margin-bottom: 0; padding: 4px 12px; } /* flex:none (don't shrink, same crush as the tabs); compact: the file-meta row needs far less height than the diff toolbar */
642
696
  .source-file-meta {
643
697
  display: flex;
644
698
  flex: 1;
@@ -665,12 +719,17 @@ h1 { margin: 0; font-size: 18px; }
665
719
  /* Files-mode tabs: one row of tabs above the source toolbar (open files, click to switch, × to close). */
666
720
  .source-tabs {
667
721
  display: flex;
722
+ /* NEVER shrink: #source-viewer is a flex column whose source-body holds a tall (min-content) code
723
+ table, so a shrinkable header row got crushed (the bar collapsed to ~7px and clipped the tabs in
724
+ half). flex:none keeps the bar at its natural height; the body absorbs the overflow and scrolls. */
725
+ flex: none;
668
726
  overflow-x: auto;
669
727
  gap: 1px;
670
- margin-bottom: 8px;
728
+ /* Breathing room from the window's top edge so the first row of tabs isn't flush against it. */
729
+ margin: 6px 8px 6px;
671
730
  background: var(--sidebar);
672
731
  border: 1px solid var(--border);
673
- border-radius: 8px;
732
+ border-radius: 0;
674
733
  scrollbar-width: thin;
675
734
  }
676
735
  .source-tab {
@@ -687,19 +746,21 @@ h1 { margin: 0; font-size: 18px; }
687
746
  cursor: pointer;
688
747
  white-space: nowrap;
689
748
  }
690
- .source-tab:first-child { border-top-left-radius: 8px; border-bottom-left-radius: 8px; }
749
+ .source-tab:first-child { border-top-left-radius: 0; border-bottom-left-radius: 0; }
691
750
  .source-tab:hover { color: var(--text); }
692
751
  .source-tab.active { color: var(--text); background: var(--bg); box-shadow: inset 0 -2px 0 var(--active); }
693
752
  .source-tab-name { overflow: hidden; text-overflow: ellipsis; }
694
753
  .source-tab-close {
695
754
  flex: none; border: 0; background: transparent; color: var(--muted);
696
- font-size: 14px; line-height: 1; padding: 0 3px; cursor: pointer; border-radius: 3px;
755
+ font-size: 14px; line-height: 1; padding: 0 3px; cursor: pointer; border-radius: 0;
697
756
  }
698
757
  .source-tab-close:hover { background: var(--line); color: var(--text); }
699
- /* Scrolloff: keep the caret / focused row near the vertical middle while navigating, so holding an arrow
700
- key scrolls the view CONTINUOUSLY instead of leaving it still until the caret reaches the viewport edge
701
- (the "stutter every ~viewport" the user reported). Applies to the source body, the diff, and the sidebar. */
702
- .source-body, #diff2html-container, .sidebar-scroll { scroll-padding-block: 35vh; }
758
+ /* Scrolloff for the sidebar tree only. NOTE: this is deliberately NOT on the source-body or the diff
759
+ container. Chromium insets the text-selection autoscroll region by scroll-padding, so a 35vh inset made
760
+ a drag-select rocket-scroll the moment the pointer left the middle band (runaway scroll + the selection
761
+ flying to the file end). Those two panes get their caret/F7 scroll-off from manual scrollTop math
762
+ (scheduleSourceReveal / scrolloffReveal), so they don't need — and must not have — scroll-padding. */
763
+ .sidebar-scroll { scroll-padding-block: 35vh; }
703
764
  .source-body {
704
765
  border: 1px solid var(--border);
705
766
  overflow: auto;
@@ -815,7 +876,7 @@ h1 { margin: 0; font-size: 18px; }
815
876
  .source-type-icon { display: inline-flex; align-items: center; flex: none; margin-right: 2px; }
816
877
  .source-type-icon .ftype { width: 16px; height: 16px; display: block; }
817
878
  .mc-file-badge { display: inline-flex; gap: 4px; align-items: center; }
818
- .mc-fb { font-size: 10px; line-height: 1; padding: 1px 6px; border-radius: 999px; font-weight: 700; font-variant-numeric: tabular-nums; border: 1px solid transparent; }
879
+ .mc-fb { font-size: 10px; line-height: 1; padding: 1px 6px; border-radius: 0; font-weight: 700; font-variant-numeric: tabular-nums; border: 1px solid transparent; }
819
880
  .mc-fb-q { color: var(--token-number); background: color-mix(in srgb, var(--token-number) 16%, transparent); border-color: color-mix(in srgb, var(--token-number) 38%, transparent); }
820
881
  .mc-fb-c { color: var(--token-tag); background: color-mix(in srgb, var(--token-tag) 16%, transparent); border-color: color-mix(in srgb, var(--token-tag) 38%, transparent); }
821
882
  /* Lines kept highlighted while composing a comment on a drag selection */
@@ -828,7 +889,7 @@ h1 { margin: 0; font-size: 18px; }
828
889
  .source-table .mc-thread-cell { padding: 4px 12px 8px 66px; }
829
890
  .mc-card {
830
891
  border: 1px solid var(--border);
831
- border-radius: 8px; background: var(--panel); margin: 8px 0; max-width: 760px;
892
+ border-radius: 0; background: var(--panel); margin: 8px 0; max-width: 760px;
832
893
  font: 12px/1.5 Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
833
894
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.28);
834
895
  overflow: hidden;
@@ -851,12 +912,12 @@ body:has(.dock-panel:focus-within) .code-cursor,
851
912
  body:has(#settings-modal:not(.hidden)) .code-cursor { display: none; }
852
913
  .mc-kind {
853
914
  font-weight: 700; font-size: 10px; letter-spacing: 0.05em; text-transform: uppercase;
854
- padding: 2px 8px; border-radius: 999px;
915
+ padding: 2px 8px; border-radius: 0;
855
916
  color: var(--muted); background: color-mix(in srgb, var(--muted) 16%, transparent);
856
917
  }
857
918
  .mc-card.mc-q .mc-kind { color: var(--token-number); background: color-mix(in srgb, var(--token-number) 18%, transparent); }
858
919
  .mc-card.mc-c .mc-kind { color: var(--token-tag); background: color-mix(in srgb, var(--token-tag) 18%, transparent); }
859
- .mc-del { margin-left: auto; background: transparent; border: 0; color: var(--muted); cursor: pointer; font-size: 15px; line-height: 1; padding: 1px 5px; border-radius: 5px; }
920
+ .mc-del { margin-left: auto; background: transparent; border: 0; color: var(--muted); cursor: pointer; font-size: 15px; line-height: 1; padding: 1px 5px; border-radius: 0; }
860
921
  .mc-del:hover { color: var(--del-strong); background: color-mix(in srgb, var(--del-strong) 16%, transparent); }
861
922
  .mc-card-body { padding: 2px 12px 11px; color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
862
923
  .mc-input {
@@ -867,13 +928,13 @@ body:has(#settings-modal:not(.hidden)) .code-cursor { display: none; }
867
928
  view uses a fake .code-cursor). caret-color inherits, so restore it here — a focused textarea must show
868
929
  its real caret. The single-caret rule hides the FILE caret while composing, not the textarea's own. */
869
930
  caret-color: var(--text);
870
- border: 1px solid var(--border); border-radius: 7px; padding: 9px 11px;
931
+ border: 1px solid var(--border); border-radius: 0; padding: 9px 11px;
871
932
  font: 12px/1.55 Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
872
933
  transition: border-color 120ms ease, box-shadow 120ms ease;
873
934
  }
874
935
  .mc-input:focus { outline: none; border-color: var(--active); box-shadow: 0 0 0 3px color-mix(in srgb, var(--active) 22%, transparent); }
875
936
  .mc-actions { display: flex; align-items: center; gap: 8px; padding: 0 10px 9px; }
876
- .mc-btn { background: var(--active); color: #fff; border: 0; border-radius: 6px; padding: 5px 12px; font-size: 12px; cursor: pointer; }
937
+ .mc-btn { background: var(--active); color: #fff; border: 0; border-radius: 0; padding: 5px 12px; font-size: 12px; cursor: pointer; }
877
938
  .mc-btn:hover { filter: brightness(1.1); }
878
939
  .mc-btn.mc-ghost { background: transparent; border: 1px solid var(--border); color: var(--text); }
879
940
  /* Terminal-send buttons in the merged modal: green to read as "send to the live session", with a clear
@@ -883,18 +944,21 @@ body:has(#settings-modal:not(.hidden)) .code-cursor { display: none; }
883
944
  .mc-hint { color: var(--muted); font-size: 11px; }
884
945
  .mc-modal { position: fixed; inset: 0; z-index: 60; display: grid; place-items: start center; padding-top: min(10vh, 80px); background: color-mix(in srgb, #000 32%, transparent); }
885
946
  .mc-modal.hidden { display: none; }
886
- .mc-modal-panel { width: min(900px, calc(100vw - 40px)); height: 80vh; max-height: 80vh; display: grid; grid-template-rows: auto minmax(0, 1fr); border: 1px solid var(--border); border-radius: 10px; background: var(--panel); overflow: hidden; }
947
+ .mc-modal-panel { width: min(900px, calc(100vw - 40px)); height: 80vh; max-height: 80vh; display: grid; grid-template-rows: auto minmax(0, 1fr); border: 1px solid var(--border); border-radius: 0; background: var(--panel); overflow: hidden; }
887
948
  .mc-modal-head { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-bottom: 1px solid var(--border); color: var(--text); font-weight: 650; }
888
949
  .mc-modal-head span { margin-right: auto; }
889
950
  .mc-modal-text { width: 100%; height: 100%; box-sizing: border-box; resize: none; border: 0; padding: 12px; background: var(--bg); color: var(--text); caret-color: var(--text); font: 12px/1.55 Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
890
951
  .mc-modal-text:focus { outline: none; }
891
- .mc-dropdown { position: fixed; z-index: 70; min-width: 0; background: var(--panel); border: 1px solid var(--border); border-radius: 6px; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4); padding: 3px; }
892
- .mc-dropdown-item { display: block; width: 100%; text-align: left; padding: 4px 10px; border: 0; background: transparent; color: var(--text); border-radius: 4px; font-size: 12px; line-height: 1.5; cursor: pointer; white-space: nowrap; }
952
+ .mc-dropdown { position: fixed; z-index: 70; min-width: 0; background: var(--panel); border: 1px solid var(--border); border-radius: 0; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4); padding: 3px; }
953
+ .mc-dropdown-item { display: block; width: 100%; text-align: left; padding: 4px 10px; border: 0; background: transparent; color: var(--text); border-radius: 0; font-size: 12px; line-height: 1.5; cursor: pointer; white-space: nowrap; }
893
954
  .mc-dropdown-item.active, .mc-dropdown-item:hover { background: var(--active); color: #fff; }
894
955
  #mc-toasts { position: fixed; left: 16px; bottom: 16px; z-index: 80; display: flex; flex-direction: column; gap: 8px; max-width: 360px; pointer-events: none; }
895
- .mc-toast { background: var(--panel); color: var(--text); border: 1px solid var(--border); border-left: 3px solid var(--active); border-radius: 8px; padding: 10px 14px; font-size: 13px; line-height: 1.45; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); opacity: 0; transform: translateY(8px); transition: opacity .25s ease, transform .25s ease; }
956
+ .mc-toast { background: var(--panel); color: var(--text); border: 1px solid var(--border); border-left: 3px solid var(--active); border-radius: 0; padding: 10px 14px; font-size: 13px; line-height: 1.45; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4); opacity: 0; transform: translateY(8px); transition: opacity .25s ease, transform .25s ease; }
896
957
  .mc-toast.show { opacity: 1; transform: translateY(0); }
897
958
  .mc-toast.hide { opacity: 0; transform: translateY(8px); }
959
+ /* Inline hint anchored just under the diff caret (F7 "last change" boundary announcement); fades on its own. */
960
+ .mc-caret-hint { position: fixed; z-index: 75; max-width: 460px; background: var(--panel); color: var(--text); border: 1px solid var(--border); border-left: 3px solid var(--active); border-radius: 0; padding: 5px 10px; font-size: 12px; line-height: 1.4; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4); opacity: 0; transform: translateY(-4px); pointer-events: none; transition: opacity .16s ease, transform .16s ease; }
961
+ .mc-caret-hint.show { opacity: 1; transform: translateY(0); }
898
962
  /* Prompt memo: split editor | live Markdown preview inside the standard modal shell. */
899
963
  .mc-memo-body { display: grid; grid-template-columns: 1fr 1fr; min-height: 0; height: 100%; }
900
964
  .mc-memo-edit { height: 100%; border-right: 1px solid var(--border); }
@@ -921,7 +985,7 @@ body:has(#settings-modal:not(.hidden)) .code-cursor { display: none; }
921
985
  color: var(--text); font-weight: 650; font-size: 12px;
922
986
  }
923
987
  .dock-title { margin-right: auto; letter-spacing: 0.02em; }
924
- .dock-btn { border: 0; background: transparent; color: var(--muted); cursor: pointer; padding: 2px 7px; border-radius: 5px; font: inherit; font-weight: 500; }
988
+ .dock-btn { border: 0; background: transparent; color: var(--muted); cursor: pointer; padding: 2px 7px; border-radius: 0; font: inherit; font-weight: 500; }
925
989
  .dock-btn:hover { color: var(--text); background: color-mix(in srgb, var(--muted) 22%, transparent); }
926
990
  .dock-max { font-size: 14px; line-height: 1; }
927
991
  .dock-body { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
@@ -951,13 +1015,16 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
951
1015
  padding-top: min(12vh, 96px);
952
1016
  background: color-mix(in srgb, #000 24%, transparent);
953
1017
  }
1018
+ /* Usages popup anchored under the caret: drop the dim backdrop and centering; JS sets panel left/top. */
1019
+ .quick-open.anchored { display: block; padding: 0; background: transparent; }
1020
+ .quick-open.anchored .quick-open-panel { position: absolute; max-height: none; }
954
1021
  .quick-open-panel {
955
1022
  width: min(720px, calc(100vw - 32px));
956
1023
  max-height: min(680px, calc(100vh - 64px));
957
1024
  display: grid;
958
1025
  grid-template-rows: auto auto minmax(0, 1fr);
959
1026
  border: 1px solid var(--border);
960
- border-radius: 8px;
1027
+ border-radius: 0;
961
1028
  background: var(--panel);
962
1029
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.28);
963
1030
  overflow: hidden;
@@ -972,6 +1039,13 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
972
1039
  font-size: 12px;
973
1040
  }
974
1041
  .quick-open-hint { font-family: Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
1042
+ /* Recent files: no search box — typed letters filter the list (speed search). */
1043
+ .quick-open.quick-recent #quick-open-input { display: none; }
1044
+ .quick-open-filter { font-size: 12px; }
1045
+ .quick-open-filter.is-hint { color: var(--muted); opacity: 0.7; font-style: italic; }
1046
+ .quick-open-filter.has-filter { color: var(--active); font-family: Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
1047
+ .quick-open-filter.has-filter::after { content: "\258F"; opacity: 0.7; animation: mc-caret-blink 1.1s steps(1) infinite; }
1048
+ @keyframes mc-caret-blink { 50% { opacity: 0; } }
975
1049
  #quick-open-input {
976
1050
  width: 100%;
977
1051
  border: 0;
@@ -983,7 +1057,9 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
983
1057
  font: 15px Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
984
1058
  }
985
1059
  .quick-open-results { overflow: auto; padding: 6px; max-height: 232px; }
986
- .usage-item { display: flex; align-items: baseline; gap: 10px; }
1060
+ /* Compound selector beats the later `.quick-open-item { display: grid }` (equal specificity, source order)
1061
+ that would otherwise drop the loc/code columns onto each other. */
1062
+ .quick-open-item.usage-item { display: flex; align-items: baseline; gap: 10px; }
987
1063
  .usage-loc { flex: none; color: var(--active); font-variant-numeric: tabular-nums; white-space: nowrap; font-size: 12px; }
988
1064
  .usage-code { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); font: 12px Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
989
1065
  .quick-open-main { min-width: 0; display: flex; align-items: baseline; gap: 8px; }
@@ -1015,7 +1091,7 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1015
1091
  width: 100%;
1016
1092
  min-height: 24px;
1017
1093
  border: 1px solid transparent;
1018
- border-radius: 5px;
1094
+ border-radius: 0;
1019
1095
  padding: 2px 8px;
1020
1096
  background: transparent;
1021
1097
  color: var(--text);
@@ -1043,11 +1119,17 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1043
1119
  .quick-open-badge { align-self: center; color: var(--muted); font-size: 12px; }
1044
1120
  .quick-open-empty { padding: 28px 14px; color: var(--muted); font-size: 13px; }
1045
1121
  @media (max-width: 900px) {
1046
- body { grid-template-columns: 1fr; grid-template-rows: auto minmax(0, 1fr) auto; }
1047
- .sidebar { grid-row: 1; grid-column: 1; height: auto; border-right: 0; border-bottom: 1px solid var(--border); }
1048
- .content { grid-row: 2; grid-column: 1; padding: 16px; }
1049
- .terminal-panel { grid-column: 1; grid-row: 3; }
1050
- .dock-panel { grid-column: 1; grid-row: 3; }
1122
+ body { grid-template-columns: 1fr; grid-template-rows: auto auto minmax(0, 1fr) auto; }
1123
+ /* Rail becomes a horizontal strip at the top; tooltips drop below the icon. */
1124
+ .activity-rail { grid-row: 1; grid-column: 1; width: auto; height: auto; flex-direction: row; padding: 4px 8px; border-right: 0; border-bottom: 1px solid var(--border); }
1125
+ .activity-rail .rail-group { flex-direction: row; }
1126
+ .activity-rail .rail-bottom { margin-left: auto; margin-top: 0; }
1127
+ .rail-tip { left: 50%; top: calc(100% + 8px); transform: translateX(-50%); }
1128
+ .rail-btn.is-active::before { left: 5px; right: 5px; top: auto; bottom: -4px; width: auto; height: 2px; }
1129
+ .sidebar { grid-row: 2; grid-column: 1; height: auto; border-right: 0; border-bottom: 1px solid var(--border); }
1130
+ .content { grid-row: 3; grid-column: 1; padding: 16px; }
1131
+ .terminal-panel { grid-column: 1; grid-row: 4; }
1132
+ .dock-panel { grid-column: 1; grid-row: 4; }
1051
1133
  .toolbar { margin: -16px -16px 16px; padding: 12px 16px; }
1052
1134
  .d2h-files-diff { grid-template-columns: 1fr; }
1053
1135
  .d2h-file-side-diff:first-child { border-right: 0; border-bottom: 1px solid var(--border); }
@@ -1057,7 +1139,7 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1057
1139
  background: var(--panel);
1058
1140
  color: var(--fg);
1059
1141
  border: 1px solid var(--border);
1060
- border-radius: 6px;
1142
+ border-radius: 0;
1061
1143
  padding: 3px 8px;
1062
1144
  font-size: 12px;
1063
1145
  }
@@ -1071,7 +1153,7 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1071
1153
  margin-right: 4px;
1072
1154
  padding: 0;
1073
1155
  border: 0;
1074
- border-radius: 3px;
1156
+ border-radius: 0;
1075
1157
  background: transparent;
1076
1158
  color: #59a869;
1077
1159
  font-size: 10px;
@@ -1083,14 +1165,14 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1083
1165
  .http-request-line .source-code { font-weight: 600; }
1084
1166
  .http-method { color: var(--token-keyword); font-weight: 700; }
1085
1167
  .http-sep { color: var(--muted); }
1086
- .http-var { border-radius: 3px; padding: 0 1px; }
1168
+ .http-var { border-radius: 0; padding: 0 1px; }
1087
1169
  .http-var.known { color: var(--token-string); background: color-mix(in srgb, var(--token-string) 15%, transparent); }
1088
1170
  .http-var.unknown { color: #e06c75; background: color-mix(in srgb, #e06c75 16%, transparent); text-decoration: underline dotted; }
1089
1171
  .http-response-row td { padding: 0 14px 0 0; border: 0; background: transparent; }
1090
1172
  .http-response {
1091
1173
  margin: 6px 0 12px;
1092
1174
  border: 1px solid var(--border);
1093
- border-radius: 8px;
1175
+ border-radius: 0;
1094
1176
  background: color-mix(in srgb, var(--active) 5%, var(--panel));
1095
1177
  overflow: hidden;
1096
1178
  font-size: 12px;
@@ -1113,7 +1195,7 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1113
1195
  margin-left: auto;
1114
1196
  background: transparent;
1115
1197
  border: 1px solid var(--border);
1116
- border-radius: 6px;
1198
+ border-radius: 0;
1117
1199
  color: var(--fg);
1118
1200
  padding: 2px 8px;
1119
1201
  font-size: 11px;
@@ -1152,7 +1234,7 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1152
1234
  max-height: calc(100vh - 230px);
1153
1235
  object-fit: contain;
1154
1236
  border: 1px solid var(--border);
1155
- border-radius: 6px;
1237
+ border-radius: 0;
1156
1238
  background: repeating-conic-gradient(#3a3a3a 0% 25%, #2f2f2f 0% 50%) 50% / 20px 20px;
1157
1239
  cursor: zoom-in;
1158
1240
  }
@@ -1193,16 +1275,16 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1193
1275
  .md-cell del { color: var(--muted); }
1194
1276
  .md-cell code {
1195
1277
  font: 0.86em Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
1196
- background: var(--line); border: 1px solid var(--border); border-radius: 4px; padding: 0.1em 0.4em;
1278
+ background: var(--line); border: 1px solid var(--border); border-radius: 0; padding: 0.1em 0.4em;
1197
1279
  }
1198
- .md-code { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; overflow: auto; margin: 0.3em 0; }
1280
+ .md-code { background: var(--panel); border: 1px solid var(--border); border-radius: 0; padding: 10px 12px; overflow: auto; margin: 0.3em 0; }
1199
1281
  .md-code code { font: 12px/1.5 Monaco, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; background: none; border: 0; padding: 0; white-space: pre; }
1200
1282
  .md-quote { margin: 0.3em 0; padding: 2px 14px; color: var(--muted); border-left: 3px solid var(--border); }
1201
1283
  .md-quote p { margin: 0.3em 0; }
1202
1284
  .md-list { margin: 0.2em 0; padding-left: 1.5em; }
1203
1285
  .md-list li { margin: 0.15em 0; }
1204
1286
  .md-hr { border: 0; border-top: 1px solid var(--border); margin: 0.5em 0; }
1205
- .md-img { max-width: 100%; border-radius: 6px; }
1287
+ .md-img { max-width: 100%; border-radius: 0; }
1206
1288
  /* Embedded raw HTML in Markdown (README <div>/<img>/<table>/…). Minimal styling so it reads sanely. */
1207
1289
  .md-html { overflow-x: auto; }
1208
1290
  .md-html img { max-width: 100%; height: auto; }
@@ -1225,15 +1307,14 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1225
1307
  /* --- Integrated terminal panel (Electron only): fixed to the content column's bottom, height-resizable.
1226
1308
  The active border-top marks it as the merged-prompt send target ("highlighted while it's open"). --- */
1227
1309
  .terminal-panel {
1228
- grid-column: 2;
1310
+ grid-column: 3;
1229
1311
  grid-row: 2;
1230
1312
  min-height: 0;
1231
1313
  height: var(--terminal-height, 320px);
1232
1314
  display: flex;
1233
1315
  flex-direction: column;
1234
1316
  background: var(--bg);
1235
- border-top: 2px solid var(--active);
1236
- box-shadow: 0 -10px 28px rgba(0, 0, 0, 0.45);
1317
+ border-top: 1px solid var(--border);
1237
1318
  }
1238
1319
  .terminal-resizer { flex: none; height: 6px; margin-top: -3px; cursor: row-resize; }
1239
1320
  .terminal-resizer:hover, .terminal-resizer.resizing { background: var(--active); }
@@ -1257,7 +1338,12 @@ body.dock-maximized .terminal-panel:not(.hidden) { grid-row: 1 / 3; height: auto
1257
1338
  .terminal-pane-label:hover { color: var(--text); }
1258
1339
  .terminal-pane-label[contenteditable="true"] { color: var(--text); background: var(--bg); outline: none; }
1259
1340
  .terminal-pane.is-active .terminal-pane-label { color: var(--text); }
1260
- .terminal-pane-host { flex: 1 1 auto; min-width: 0; min-height: 0; padding: 4px 0 4px 8px; }
1341
+ .terminal-pane-host { flex: 1 1 auto; min-width: 0; min-height: 0; padding: 4px 8px; } /* right padding too, so xterm's last column isn't clipped against the pane edge */
1342
+ /* Bell badge: a small dot on a pane's label when its TUI rang the bell while you were looking elsewhere. */
1343
+ .terminal-pane-label.has-bell::after { content: "\25CF"; margin-left: 6px; color: var(--active); font-size: 9px; vertical-align: middle; }
1344
+ /* Settings on/off row (terminal-bell notification toggle). */
1345
+ .settings-check { display: flex; align-items: center; gap: 8px; margin-top: 12px; color: var(--text); font-size: 13px; cursor: pointer; }
1346
+ .settings-check input { accent-color: var(--active); margin: 0; }
1261
1347
  /* No border on the active pane — the inactive panes dim back instead, so the focused one stands out
1262
1348
  cleanly without an outline. Only applies with 2+ panes (a lone pane is never dimmed; see setActive). */
1263
1349
  .terminal-pane { transition: opacity 120ms ease; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happy-nut/monacori",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
4
4
  "description": "Validation control plane for AI-generated code changes.",
5
5
  "type": "module",
6
6
  "main": "dist/app-main.js",
@@ -53,6 +53,7 @@
53
53
  "@electron/packager": "^20.0.1",
54
54
  "@types/node": "^22.15.21",
55
55
  "jsdom": "^29.1.1",
56
+ "terser": "^5.48.0",
56
57
  "typescript": "^5.8.3"
57
58
  },
58
59
  "engines": {