@leftoff/cli 0.9.18-beta.9 → 0.9.18
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/CHANGELOG.md +25 -2
- package/bin/leftoff-statusline.js +7 -7
- package/bin/leftoff.js +792 -677
- package/docs/SECURITY.md +1 -1
- package/mod/.claude-plugin/plugin.json +1 -1
- package/mod/hooks/core.js +259 -17
- package/mod/hooks/register.js +18 -4
- package/package.json +1 -1
- package/ui/app.css +204 -5
- package/ui/app.js +621 -189
- package/ui/chip-fade.js +1 -1
- package/ui/cp-fold.js +42 -0
- package/ui/decisions.js +81 -21
- package/ui/digest-versions.js +57 -0
- package/ui/fs-side.js +29 -0
- package/ui/html-preview.html +12 -0
- package/ui/html-preview.js +136 -0
- package/ui/icons.js +1 -0
- package/ui/live-status.js +44 -3
- package/ui/live-view.js +36 -5
- package/ui/live-wake.js +47 -0
- package/ui/mcp-setup.js +26 -0
- package/ui/prs.js +28 -10
- package/ui/pull.js +30 -3
- package/ui/relay-client.js +2 -0
- package/ui/render-digest.js +98 -0
- package/ui/render-export.js +128 -0
- package/ui/semdiff.js +58 -27
- package/ui/session-title.js +88 -0
- package/ui/settings-nav.js +1 -1
- package/ui/sglyph.js +2 -2
- package/ui/slash-commands.js +89 -0
- package/ui/slash.js +82 -0
- package/ui/subagents-view.js +41 -0
- package/ui/summary-examples.js +1 -1
- package/ui/tabs.js +10 -3
- package/ui/viewport-fit.js +29 -3
- package/ui/walk-spots.js +35 -1
package/ui/app.css
CHANGED
|
@@ -435,6 +435,29 @@ h2 .count { color: var(--faint); font-weight: 500; }
|
|
|
435
435
|
.pagehead .actions { flex-wrap: wrap; }
|
|
436
436
|
}
|
|
437
437
|
.digest-meta { color: var(--faint); font-size: 12.5px; margin: -2px 0 12px; }
|
|
438
|
+
/* 2026-11-06: the digest's versions (ui/digest-versions.js): quiet, one line, a list on tap */
|
|
439
|
+
.dv-line { margin: -10px 0 8px; }
|
|
440
|
+
.dv { position: relative; display: inline-block; }
|
|
441
|
+
.dv-btn { min-height: 44px; padding: 0 10px; margin: 0 0 0 -10px; border: 0; background: transparent; color: var(--muted); font: inherit; font-size: 12.5px; cursor: pointer; border-radius: 8px; -webkit-tap-highlight-color: transparent; }
|
|
442
|
+
.dv-btn:hover, .dv-btn[aria-expanded="true"] { color: var(--text2); background: var(--bg2); }
|
|
443
|
+
.dv-btn:focus-visible { outline: 2px solid var(--accent, currentColor); outline-offset: 1px; }
|
|
444
|
+
.dv-list { position: absolute; z-index: 20; top: calc(100% + 4px); left: 0; min-width: 190px; margin: 0; padding: 4px; list-style: none; background: var(--card); border: 1px solid var(--line); border-radius: 10px; box-shadow: var(--card-shadow); }
|
|
445
|
+
.dv-list[hidden] { display: none; }
|
|
446
|
+
.dv-list a { display: flex; align-items: center; min-height: 44px; padding: 0 10px; border-radius: 7px; color: var(--text2); text-decoration: none; font-size: 13px; white-space: nowrap; }
|
|
447
|
+
.dv-list a:hover { background: var(--bg2); }
|
|
448
|
+
.dv-list a[aria-current="page"] { color: var(--text); font-weight: 600; }
|
|
449
|
+
.dv-old .btn { min-height: 44px; }
|
|
450
|
+
/* Settings → Digest → Let Claude search your notes (ui/mcp-setup.js) */
|
|
451
|
+
.form .full.mcp-box { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; justify-content: stretch; min-width: 0; }
|
|
452
|
+
.mcp-row { position: relative; display: flex; align-items: center; gap: 6px; padding: 6px 4px 6px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg2); }
|
|
453
|
+
.mcp-row code { flex: 1; min-width: 0; white-space: normal; overflow-wrap: anywhere; font-size: 12.5px; border: 0; background: transparent; padding: 0; }
|
|
454
|
+
.mcp-row .copy-float { flex: none; width: 44px; height: 44px; display: grid; place-items: center; padding: 0; border: 0; border-radius: 8px; background: transparent; color: var(--muted); cursor: pointer; }
|
|
455
|
+
.mcp-row .copy-float:hover, .mcp-row .copy-float.copied { color: var(--text); background: var(--card); }
|
|
456
|
+
.mcp-row .copy-float svg { width: 16px; height: 16px; }
|
|
457
|
+
.mcp-codex summary { min-height: 44px; display: flex; align-items: center; cursor: pointer; color: var(--text2); font-size: 13px; }
|
|
458
|
+
.mcp-codex pre { margin: 6px 0 0; padding: 8px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg2); font-size: 12px; overflow-x: auto; }
|
|
459
|
+
.mcp-states { display: flex; flex-wrap: wrap; gap: 6px 14px; font-size: 12.5px; color: var(--text2); }
|
|
460
|
+
.mcp-state.ok { color: var(--text); }
|
|
438
461
|
@media (max-width: 640px) {
|
|
439
462
|
/* the five status counts as one compact row that scrolls, not a 3-row grid */
|
|
440
463
|
.stats { display: flex; overflow-x: auto; scrollbar-width: none; gap: 8px; margin: 14px -14px 0; padding: 2px 14px; }
|
|
@@ -1578,6 +1601,7 @@ a.cpr:hover { border-color: var(--line-strong); }
|
|
|
1578
1601
|
.pr-ic[data-tip]::after { content: attr(data-tip); display: none; position: absolute; top: calc(100% - 4px); right: 0; width: max-content; max-width: min(260px, 70vw); padding: 4px 8px; border-radius: 7px; background: var(--card2); border: 1px solid var(--line-strong); box-shadow: var(--toast-shadow); color: var(--text2); font-size: 12px; line-height: 1.3; font-weight: 500; text-align: left; white-space: nowrap; letter-spacing: normal; pointer-events: none; z-index: 30; }
|
|
1579
1602
|
@media (hover: hover) and (pointer: fine) { .pr-ic[data-tip]:hover::after { display: block; animation: tip-in .12s ease-out .35s both; } }
|
|
1580
1603
|
.pr-ic[data-tip]:focus-visible::after, .pr-ic.copied[data-tip]::after { display: block; }
|
|
1604
|
+
.pr-ic[aria-expanded="true"][data-tip]::after { display: none !important; } /* 2026-11-06 Open's menu is up: its tip would cover the title */
|
|
1581
1605
|
@media (hover: hover) and (pointer: fine) { .pr-ic.copied[data-tip]:hover::after { animation: none; } }
|
|
1582
1606
|
@media (prefers-reduced-motion: reduce) { .pr-ic[data-tip]::after { animation: none !important; } }
|
|
1583
1607
|
.prlist { margin-bottom: 8px; }
|
|
@@ -1641,6 +1665,9 @@ a.cpr:hover { border-color: var(--line-strong); }
|
|
|
1641
1665
|
.prrow .pr-line1 { padding-right: 124px; min-height: 24px; }
|
|
1642
1666
|
.prrow:not(:has(.pr-unlink)) .pr-line1 { padding-right: 80px; }
|
|
1643
1667
|
.prrow:not(:has(.pr-ic)) .pr-line1 { padding-right: 0; }
|
|
1668
|
+
/* a closed compact row (the session panel) keeps its glyphs in the row, after the one-line title */
|
|
1669
|
+
.pr-compact .prrow:not(.open) .pr-actions { position: static; margin: 0 -2px 0 0; }
|
|
1670
|
+
.pr-compact .prrow:not(.open) { align-items: center; }
|
|
1644
1671
|
.pr-actions, .prrow.open .pr-actions { position: absolute; top: 0; right: 2px; margin: 0; }
|
|
1645
1672
|
}
|
|
1646
1673
|
|
|
@@ -1751,6 +1778,34 @@ html.dv-open, html.dv-open body { overflow: hidden; }
|
|
|
1751
1778
|
.dv-sub { padding: 6px 14px 0; }
|
|
1752
1779
|
.dv-dl .dl-word { display: none; }
|
|
1753
1780
|
}
|
|
1781
|
+
/* 2026-11-06 An HTML file: Preview · Code (ui/html-preview.js). Preview fills the sheet with the
|
|
1782
|
+
sandboxed page on white (a page with no background of its own is drawn on white, as in a browser);
|
|
1783
|
+
a line under the switch says what remote resources were blocked, with Show and Allow. */
|
|
1784
|
+
.hp-bar { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px; padding-bottom: 10px; }
|
|
1785
|
+
.hp-remote { display: flex; align-items: center; gap: 8px; flex: 1 1 320px; min-width: 0; font-size: 12.5px; color: var(--text2); }
|
|
1786
|
+
.hp-ric { flex: none; width: 15px; height: 15px; color: var(--muted); }
|
|
1787
|
+
.hp-remote.on .hp-ric { color: var(--accent); }
|
|
1788
|
+
.hp-rw { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
1789
|
+
.hp-rw b { font-weight: 600; color: var(--text); }
|
|
1790
|
+
.hp-remote .btn { flex: none; }
|
|
1791
|
+
.hp-remote.hp-words { margin-top: -4px; }
|
|
1792
|
+
.hp-list { flex-basis: 100%; margin: 0; padding: 8px 10px; list-style: none; border: 1px solid var(--line); border-radius: 10px; background: var(--bg2); max-height: 160px; overflow: auto; display: grid; gap: 4px; }
|
|
1793
|
+
.hp-list li { display: flex; gap: 8px; align-items: baseline; min-width: 0; font-size: 12px; }
|
|
1794
|
+
.hp-list code { font: 12px/1.4 var(--mono); color: var(--text); overflow-wrap: anywhere; }
|
|
1795
|
+
.hp-kind { flex: none; min-width: 42px; font-size: 11px; color: var(--muted); }
|
|
1796
|
+
.hp-note { flex-basis: 100%; margin: 0; font-size: 12px; }
|
|
1797
|
+
.dv-body.dv-hpv { display: flex; flex-direction: column; overflow: hidden; }
|
|
1798
|
+
.dv-hpv .hp-main { flex: 1; min-height: 0; display: flex; }
|
|
1799
|
+
.dv-hpv .hp-stopped { flex: 1; justify-content: center; }
|
|
1800
|
+
.hp-stopped .btn { margin-top: 10px; }
|
|
1801
|
+
.hp-frame { flex: 1; width: 100%; min-height: 0; border: 1px solid var(--line); border-radius: 10px; background: #fff; color-scheme: light; }
|
|
1802
|
+
@media (max-width: 599.98px) {
|
|
1803
|
+
.hp-seg { flex: 1 1 100%; display: flex; }
|
|
1804
|
+
.hp-seg button { flex: 1 1 0; height: 44px; }
|
|
1805
|
+
.hp-remote { flex-basis: 100%; }
|
|
1806
|
+
.hp-remote .btn { min-height: 44px; }
|
|
1807
|
+
.hp-hosts { display: none; }
|
|
1808
|
+
}
|
|
1754
1809
|
html.dv-open .lo-backdrop { z-index: 61; }
|
|
1755
1810
|
html.dv-open .lo-menu { z-index: 62; }
|
|
1756
1811
|
|
|
@@ -2491,6 +2546,20 @@ mark.tx, .co-snip mark, .tx-snip mark, .tx-msg-text mark { background: var(--tx-
|
|
|
2491
2546
|
|
|
2492
2547
|
/* 0.9.8 attachments: a paperclip beside ↑, chips above the words inside the box, thumbnails in your bubble */
|
|
2493
2548
|
.composer { flex-wrap: wrap; }
|
|
2549
|
+
/* "/" commands (ui/slash.js): a list above the composer; options 44px tall */
|
|
2550
|
+
.composer .slash-menu { position: absolute; left: 0; right: 0; bottom: calc(100% + 6px); z-index: 30; max-height: min(320px, 50vh); overflow-y: auto; overscroll-behavior: contain; padding: 4px; border: 1px solid var(--line-strong); border-radius: 14px; background: var(--card); box-shadow: 0 8px 24px rgba(0,0,0,.22); cursor: default; }
|
|
2551
|
+
.slash-h { padding: 6px 10px 2px; font: 600 11.5px/1.4 var(--mono); color: var(--muted); }
|
|
2552
|
+
.slash-opt { display: flex; align-items: baseline; gap: 10px; min-height: 44px; box-sizing: border-box; padding: 11px 10px; border-radius: 10px; cursor: pointer; }
|
|
2553
|
+
.slash-opt[aria-selected="true"] { background: var(--bg2); }
|
|
2554
|
+
@media (hover: hover) { .slash-opt:hover { background: var(--bg2); } }
|
|
2555
|
+
.slash-opt.off { cursor: not-allowed; opacity: .6; }
|
|
2556
|
+
.slash-l { flex: none; font: 500 13.5px/1.5 var(--mono); color: var(--text); }
|
|
2557
|
+
.slash-hint { color: var(--muted); font-weight: 400; }
|
|
2558
|
+
.slash-w { min-width: 0; font-size: 13px; line-height: 1.5; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
2559
|
+
/* a slash command's bubble: the command in mono, then what Claude Code printed */
|
|
2560
|
+
.lv-cmd code { font-size: 13.5px; background: none; border: 0; padding: 0; }
|
|
2561
|
+
.lv-cmd-out { margin: 6px 0 0; padding: 0; font: 12.5px/1.5 var(--mono); color: var(--text2); white-space: pre-wrap; overflow-wrap: anywhere; background: none; border: 0; max-height: 240px; overflow-y: auto; }
|
|
2562
|
+
.lv-cmd-done { font-family: inherit; color: var(--muted); }
|
|
2494
2563
|
.composer .att-chips { flex: 0 0 100%; order: -1; display: flex; flex-wrap: wrap; gap: 6px; padding: 8px 8px 2px 0; margin-left: -6px; }
|
|
2495
2564
|
.composer .att-chips[hidden] { display: none; }
|
|
2496
2565
|
.composer.att-drop { border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus); background: color-mix(in srgb, var(--accent) 7%, var(--card2)); }
|
|
@@ -2842,7 +2911,18 @@ mark.tx, .co-snip mark, .tx-snip mark, .tx-msg-text mark { background: var(--tx-
|
|
|
2842
2911
|
.tab:hover { color: var(--text); }
|
|
2843
2912
|
.tab:focus-visible, .tab-x:focus-visible, .tab-all:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
|
|
2844
2913
|
.tab-board { flex: none; border-right: 1px solid var(--line); }
|
|
2845
|
-
.tab-cell { position: relative; flex: 0 1 200px; min-width:
|
|
2914
|
+
.tab-cell { position: relative; flex: 0 1 200px; min-width: 140px; display: flex; align-items: stretch; border-right: 1px solid var(--line); }
|
|
2915
|
+
/* 0.9.18 a busy strip: the tab you're on keeps its full width (only the others shrink), the rest
|
|
2916
|
+
keep 140px and the strip scrolls with a fade at the edge that has more (ui/chip-fade.js);
|
|
2917
|
+
a pinned tab is its pin and its status shape, the name in its tip and label. */
|
|
2918
|
+
.tab-cell.on { flex-shrink: 0; }
|
|
2919
|
+
.tab-cell.pinned { flex: none; min-width: 0; }
|
|
2920
|
+
.tab-cell.pinned .tab-s { padding-right: 12px; }
|
|
2921
|
+
.tab-cell.pinned .tab-t { display: none; }
|
|
2922
|
+
.tab-cell.pinned .tab-pin { margin-right: 0; }
|
|
2923
|
+
#tabStrip .tab-scroll.fade-r { -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent); mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent); }
|
|
2924
|
+
#tabStrip .tab-scroll.fade-l { -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 32px), transparent); mask-image: linear-gradient(to left, #000 calc(100% - 32px), transparent); }
|
|
2925
|
+
#tabStrip .tab-scroll.fade-l.fade-r { -webkit-mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent); mask-image: linear-gradient(to right, transparent, #000 32px, #000 calc(100% - 32px), transparent); }
|
|
2846
2926
|
.tab-s { flex: 1; min-width: 0; padding-right: 0; }
|
|
2847
2927
|
.tab.on, .tab-cell.on { color: var(--text); background: var(--card); }
|
|
2848
2928
|
.tab-board.on, .tab-cell.on { box-shadow: inset 0 -2px 0 var(--accent); }
|
|
@@ -3075,6 +3155,26 @@ html.pv-open, html.pv-open body { overflow: hidden; }
|
|
|
3075
3155
|
.md .bi-title:hover { text-decoration: underline; text-underline-offset: 2px; }
|
|
3076
3156
|
.md .bi-tag { color: var(--faint); font-size: 12px; }
|
|
3077
3157
|
.md section.start-sec + .digest-hint, .md p.lede + .digest-hint { margin-top: 14px; }
|
|
3158
|
+
/* 2026-11-06: What you got done: per project, one fact a line, each led by a shape and its word (never colour alone) */
|
|
3159
|
+
.md section.done-sec { margin: 16px 0 4px; padding: 10px 14px 6px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--bg2); }
|
|
3160
|
+
.md section.done-sec h2 { margin: 2px 0 2px; font-size: 13px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
|
|
3161
|
+
.md section.done-sec h3 { margin: 12px 0 4px; font-size: 14px; color: var(--text); }
|
|
3162
|
+
.md ul.done, .cp ul:has(> li.dn) { list-style: none; margin: 0; padding: 0; }
|
|
3163
|
+
.md li.dn, .cp li.dn { position: relative; padding: 3px 0 3px 22px; line-height: 1.45; color: var(--text2); overflow-wrap: anywhere; }
|
|
3164
|
+
.md li.dn b { color: var(--text); font-weight: 600; }
|
|
3165
|
+
.md li.dn a { color: var(--text); text-decoration: underline; text-decoration-color: var(--line); text-underline-offset: 2px; }
|
|
3166
|
+
.md li.dn::before, .cp li.dn::before { position: absolute; left: 2px; top: 3px; width: 16px; text-align: center; font-weight: 700; color: var(--muted); }
|
|
3167
|
+
li.dn-merged::before { content: '✓'; }
|
|
3168
|
+
li.dn-opened::before { content: '○'; }
|
|
3169
|
+
li.dn-commit::before, li.dn-push::before { content: '•'; }
|
|
3170
|
+
li.dn-pass::before { content: '✓'; }
|
|
3171
|
+
li.dn-fail::before { content: '✗'; }
|
|
3172
|
+
li.dn-decided::before { content: '◆'; font-size: 11px; }
|
|
3173
|
+
li.dn-you::before { content: '!'; }
|
|
3174
|
+
li.dn-open::before { content: '→'; }
|
|
3175
|
+
li.dn-more::before { content: '+'; }
|
|
3176
|
+
.cp dd.cp-done { margin-bottom: 6px; }
|
|
3177
|
+
@media (max-width: 600px) { .md section.done-sec { padding: 8px 12px 4px; margin-left: -4px; margin-right: -4px; } }
|
|
3078
3178
|
.md section.start-sec ~ #digestSpaces { margin-top: 16px; }
|
|
3079
3179
|
.md .bi-say { display: block; color: var(--text2); line-height: 1.45; margin-top: 1px; }
|
|
3080
3180
|
.md details.fin { margin: 10px 0 4px; }
|
|
@@ -3573,11 +3673,16 @@ del.gd-x { background: var(--gd-del-word); }
|
|
|
3573
3673
|
|
|
3574
3674
|
html.live-full, html.live-full body { overflow: hidden; overscroll-behavior: none; }
|
|
3575
3675
|
.live-box.full { --lf-pl: max(12px, env(safe-area-inset-left)); --lf-pr: max(12px, env(safe-area-inset-right)); position: fixed; z-index: 32; left: 0; right: 0; top: var(--lf-top, 0); height: var(--lf-h, 100vh); height: var(--lf-h, 100dvh); margin: 0; border: 0; border-radius: 0; padding: 0 var(--lf-pr) max(10px, env(safe-area-inset-bottom)) var(--lf-pl); display: flex; flex-direction: column; background: var(--bg); box-sizing: border-box; }
|
|
3576
|
-
html.lf-kb .live-box.full { padding-bottom: 8px; }
|
|
3676
|
+
html.lf-kb .live-box.full { padding-bottom: 8px; } /* 2026-11-07: nothing kept for the keyboard's ^ v ✓ bar, it sits below the visual viewport (ui/viewport-fit.js) */
|
|
3577
3677
|
.live-box.full > * { flex: none; width: 100%; max-width: 860px; margin-left: auto; margin-right: auto; box-sizing: border-box; }
|
|
3578
3678
|
.live-fbar { display: flex; align-items: center; gap: 6px; min-height: 52px; padding-top: env(safe-area-inset-top); border-bottom: 1px solid var(--line); }
|
|
3579
3679
|
.live-box.full > .live-fbar { max-width: none; margin: 0 calc(-1 * var(--lf-pr)) 0 calc(-1 * var(--lf-pl)); width: auto; padding-left: max(4px, env(safe-area-inset-left)); padding-right: max(8px, env(safe-area-inset-right)); background: var(--bg); }
|
|
3580
3680
|
.live-fs-x { margin-left: 0; }
|
|
3681
|
+
/* 2026-11-05 session titles: the name on line one, folder@branch muted under it */
|
|
3682
|
+
.live-fbar .lf-tt { display: flex; flex-direction: column; justify-content: center; flex: 1 1 auto; min-width: 0; gap: 1px; }
|
|
3683
|
+
.live-fbar .lf-where { display: block; min-width: 0; font-size: 12px; line-height: 1.25; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
3684
|
+
.live-fbar .lf-where:empty { display: none; }
|
|
3685
|
+
.s-where { margin-top: 2px; font-size: 12px; line-height: 1.3; color: var(--muted); overflow-wrap: anywhere; }
|
|
3581
3686
|
.live-fbar .lf-title { display: block; flex: 1 1 auto; min-width: 0; margin: 0; font-size: 15px; font-weight: 650; line-height: 1.3; color: var(--text); text-transform: none; letter-spacing: normal; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
3582
3687
|
.lf-pills { flex: none; display: inline-flex; align-items: center; gap: 6px; }
|
|
3583
3688
|
.lf-stop { flex: none; min-height: 36px; }
|
|
@@ -4513,15 +4618,32 @@ html:not(.live-full) .fs-side { display: none; }
|
|
|
4513
4618
|
html.live-full.fs-on .live-box.full { height: calc(var(--lf-h, 100vh) - var(--fs-peek, 56px)); height: calc(var(--lf-h, 100dvh) - 56px - env(safe-area-inset-bottom)); padding-bottom: 6px; }
|
|
4514
4619
|
html.live-full.lf-kb .fs-side { display: none; }
|
|
4515
4620
|
html.live-full.lf-kb.fs-on .live-box.full { height: var(--lf-h, 100dvh); }
|
|
4621
|
+
/* 2026-11-06 typing outside the sheet: it steps aside whether or not a keyboard's height was measured (app.js fitSheetAside) */
|
|
4622
|
+
html.live-full.lf-typing .fs-side { display: none; }
|
|
4623
|
+
html.live-full.lf-typing.fs-on .live-box.full { height: var(--lf-h, 100dvh); }
|
|
4624
|
+
/* the sheet follows a finger (app.js); its peek is the handle, its content scrolls natively */
|
|
4625
|
+
.fs-side.dragging { transition: none; }
|
|
4626
|
+
.fs-peek { touch-action: none; }
|
|
4516
4627
|
}
|
|
4517
4628
|
@media (prefers-reduced-motion: reduce) { .fs-side { transition: none; } }
|
|
4518
4629
|
/* the tab strip: pinned tabs at the left (a pin), each tab's status as a shape AND a word, + New session */
|
|
4519
|
-
.tab-cell.pinned .tab-t { max-width: 10em; }
|
|
4520
4630
|
.tab-pin { display: inline-flex; flex: none; margin-right: 5px; color: var(--text2); }
|
|
4521
4631
|
.tab-pin .ic { width: 12px; height: 12px; }
|
|
4522
4632
|
.lf-tab .tab-pin { margin-right: 2px; }
|
|
4523
4633
|
.tab-st { display: inline-flex; align-items: center; gap: 3px; flex: none; margin-left: 6px; }
|
|
4524
4634
|
.tab-w { font-size: 11.5px; font-weight: 550; color: var(--text2); white-space: nowrap; }
|
|
4635
|
+
/* 0.9.18 the strip: a closable tab's shape sits in the ×'s place; the × on hover or keyboard focus.
|
|
4636
|
+
A pinned tab and a touch screen (no hover) keep the shape beside the title. */
|
|
4637
|
+
.tab-st:empty, .tab-st-touch { display: none; }
|
|
4638
|
+
.tab-x .tab-xsg { position: absolute; left: 50%; top: 50%; margin: -7px 0 0 -7px; }
|
|
4639
|
+
.tab-x.has-st .ic { opacity: 0; }
|
|
4640
|
+
.tab-cell:hover .tab-x.has-st .ic, .tab-x.has-st:focus-visible .ic { opacity: 1; }
|
|
4641
|
+
.tab-cell:hover .tab-x .tab-xsg, .tab-x:focus-visible .tab-xsg { visibility: hidden; }
|
|
4642
|
+
@media (hover: none), (pointer: coarse) {
|
|
4643
|
+
.tab-st-touch:not(:empty) { display: inline-flex; }
|
|
4644
|
+
.tab-x .tab-xsg { display: none; }
|
|
4645
|
+
.tab-x.has-st .ic { opacity: 1; }
|
|
4646
|
+
}
|
|
4525
4647
|
.tab-new { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 44px; color: var(--text2); border-radius: 8px; }
|
|
4526
4648
|
.tab-new .ic { width: 16px; height: 16px; }
|
|
4527
4649
|
@media (hover: hover) { .tab-new:hover { color: var(--text); background: var(--card2); } }
|
|
@@ -4589,6 +4711,7 @@ html:not(.live-full) .fs-side { display: none; }
|
|
|
4589
4711
|
.wt-seg::-webkit-scrollbar { display: none; }
|
|
4590
4712
|
.wt-seg button { display: inline-flex; align-items: center; justify-content: center; gap: 6px; height: 38px; padding: 1px 14px 0; box-sizing: border-box; border: 0; border-radius: 8px; background: none; color: var(--muted); font: inherit; font-size: 13px; font-weight: 550; line-height: 1; white-space: nowrap; cursor: pointer; }
|
|
4591
4713
|
.wt-seg button .ic { width: 14px; height: 14px; margin-top: -1px; }
|
|
4714
|
+
.wt-seg button .wt-seg-chev { width: 12px; height: 12px; margin: -1px -4px 0 -2px; opacity: .7; }
|
|
4592
4715
|
.wt-seg button[aria-pressed="true"] { background: var(--card2); color: var(--text); box-shadow: inset 0 0 0 1px var(--line-strong); }
|
|
4593
4716
|
.wt-seg button:disabled { opacity: .45; cursor: default; }
|
|
4594
4717
|
.wt-seg-sm button { height: 34px; padding: 1px 12px 0; }
|
|
@@ -4757,6 +4880,13 @@ details[open] > summary .wt-g-chev { transform: rotate(90deg); }
|
|
|
4757
4880
|
.wt-ask:has(.wt-ask-in:focus-visible) { border-color: var(--text2); }
|
|
4758
4881
|
.wt-ask-b { flex: none; width: 40px; height: 40px; display: grid; place-items: center; border: 0; border-radius: 10px; background: var(--card2); color: var(--text2); cursor: pointer; }
|
|
4759
4882
|
.wt-pnav { display: none; }
|
|
4883
|
+
/* 2026-11-06 the long page has a bar too when there's a spot to jump to (Next spot stays on screen) */
|
|
4884
|
+
.wt-pnav:has(.wt-spot) { flex: none; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 6px 14px; border-top: 1px solid var(--line); background: var(--bg); }
|
|
4885
|
+
.wt-pnav:has(.wt-spot) .btn { min-height: 32px; padding: 0 12px; display: inline-flex; align-items: center; gap: 4px; }
|
|
4886
|
+
/* the finish: every step reviewed, said on the overview */
|
|
4887
|
+
.wt-alldone { display: flex; align-items: center; gap: 8px; margin: 14px 0 0; padding: 10px 12px; border: 1px solid var(--line); border-radius: 10px; background: var(--card); color: var(--text); font-size: 13.5px; font-weight: 600; }
|
|
4888
|
+
.wt-alldone[hidden] { display: none; }
|
|
4889
|
+
.wt-alldone .ic { width: 16px; height: 16px; color: var(--green); }
|
|
4760
4890
|
.wt :is(button, a, summary):focus-visible, .fs-wt:focus-visible, .wt-since:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
4761
4891
|
@media (prefers-reduced-motion: no-preference) { .wt-st { transition: border-color .15s, box-shadow .15s; } details[open] > summary .wt-g-chev { transition: transform .12s; } }
|
|
4762
4892
|
@media (max-width: 1100px) { .wt.wt-big .wt-hw { grid-template-columns: minmax(0, 1fr); } .wt.wt-big .wt-fm { display: none; } .wt-big .wt-in { padding-left: 28px; } }
|
|
@@ -5199,6 +5329,14 @@ html.nav-drawer-open, html.nav-drawer-open body { overflow: hidden; }
|
|
|
5199
5329
|
.pr-compact .pr-title-btn { display: block; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; text-align: left; font-weight: 500; color: var(--text); }
|
|
5200
5330
|
.pr-compact .pr-meta { margin-top: 2px; font-size: 12px; }
|
|
5201
5331
|
.pr-compact .pr-actions { margin: 0 -2px 0 0; }
|
|
5332
|
+
/* open: the actions sit at the top right beside the title line, so the details below take the panel's full width */
|
|
5333
|
+
.pr-compact .prrow.open { position: relative; }
|
|
5334
|
+
.pr-compact .prrow.open.pr-acts-1 .pr-c1 { padding-right: 48px; }
|
|
5335
|
+
.pr-compact .prrow.open.pr-acts-2 .pr-c1 { padding-right: 92px; }
|
|
5336
|
+
.pr-compact .prrow.open.pr-acts-3 .pr-c1 { padding-right: 136px; }
|
|
5337
|
+
.pr-compact .prrow.open.pr-acts-4 .pr-c1 { padding-right: 180px; }
|
|
5338
|
+
.pr-compact .prrow.open .pr-actions { position: absolute; top: 8px; right: 4px; margin: 0; }
|
|
5339
|
+
@media (pointer: fine) { .pr-compact .prrow.open.pr-acts-1 .pr-c1 { padding-right: 40px; } .pr-compact .prrow.open.pr-acts-2 .pr-c1 { padding-right: 72px; } .pr-compact .prrow.open.pr-acts-3 .pr-c1 { padding-right: 104px; } .pr-compact .prrow.open.pr-acts-4 .pr-c1 { padding-right: 136px; } }
|
|
5202
5340
|
@media (pointer: fine) { .pr-compact .pr-actions .pr-ic { width: 32px; height: 32px; } }
|
|
5203
5341
|
.sprs .pr-unfold { margin: 0 0 8px; }
|
|
5204
5342
|
.sprs .pr-unfold > .pr-unsum { list-style: none; display: inline-flex; align-items: center; gap: 6px; height: 32px; line-height: 1; padding: 0 10px; border: 1px dashed var(--line-strong); border-radius: 999px; font-size: 12.5px; color: var(--muted); cursor: pointer; }
|
|
@@ -5345,8 +5483,23 @@ code .file-ref-off { font-size: inherit; }
|
|
|
5345
5483
|
.wt-spot .ic { width: 15px; height: 15px; }
|
|
5346
5484
|
.wt-spot-n { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
5347
5485
|
.wt-gd .wt-spot-on { position: relative; box-shadow: inset 4px 0 0 var(--text), inset 0 0 0 1px var(--line-strong); }
|
|
5348
|
-
|
|
5349
|
-
.
|
|
5486
|
+
/* 2026-11-06 every spot's chip at its line, all the time; the one Next spot is on is solid. The chip
|
|
5487
|
+
is a .tip-btn (ui/tips.js): hover, focus or a tap explains why it's a spot. A 20px pill in a hit
|
|
5488
|
+
area as tall as the row (44px on touch, by its padding) */
|
|
5489
|
+
.wt-spot-tag { position: absolute; right: 6px; top: 0; bottom: 0; z-index: 1; display: flex; align-items: center; pointer-events: none; }
|
|
5490
|
+
.wt-gd [data-ri]:has(> .wt-spot-tag) { position: relative; }
|
|
5491
|
+
.wt-spot-tag .tip-btn.wt-spot-chip { position: static; width: auto; height: 20px; display: inline-flex; align-items: center; gap: 4px; padding: 1px 7px 0; box-sizing: border-box; border: 1px dashed var(--line-strong); border-radius: 10px; background: var(--card); color: var(--muted); font-family: var(--sans, inherit); font-size: 11px; font-weight: 600; line-height: 1; white-space: nowrap; cursor: help; pointer-events: auto; }
|
|
5492
|
+
.wt-spot-tag.cur .tip-btn.wt-spot-chip { border-style: solid; color: var(--text); }
|
|
5493
|
+
.wt-spot-tag .tip-btn.wt-spot-chip:hover, .wt-spot-tag .tip-btn.wt-spot-chip[aria-expanded="true"] { color: var(--text); background: var(--card2); }
|
|
5494
|
+
.wt-spot-tag .tip-btn.wt-spot-chip .ic { width: 11px; height: 11px; }
|
|
5495
|
+
.wt-spot-tag .tip { font-family: var(--sans, system-ui, sans-serif); font-weight: 400; white-space: normal; pointer-events: auto; }
|
|
5496
|
+
@media (pointer: coarse) { .wt-spot-tag .tip-btn.wt-spot-chip { height: 28px; padding: 1px 9px 0; border-radius: 14px; } .wt-spot-tag .tip-btn.wt-spot-chip::after { content: ''; position: absolute; inset: -8px -4px; } .wt-spot-tag .tip-btn.wt-spot-chip { position: relative; } }
|
|
5497
|
+
/* Next spot in the bar under the reading (slides, and the long page) */
|
|
5498
|
+
.wt-dnav .btn.wt-spot { height: 44px; }
|
|
5499
|
+
@media (pointer: fine) { .wt-dnav .btn.wt-spot { height: 30px; min-height: 30px; } }
|
|
5500
|
+
@media (max-width: 699.98px) { .wt-dnav .btn.wt-spot { width: auto; padding: 0 10px; gap: 4px; } .wt-dnav .wt-spot-l { display: none; } }
|
|
5501
|
+
.wt-pnav .wt-spot { margin-left: auto; }
|
|
5502
|
+
.wt-pnav .wt-spot + .btn { margin-left: 0; }
|
|
5350
5503
|
/* the file list: folds to a slim rail, its edge drags */
|
|
5351
5504
|
.wt-railt { flex: none; display: grid; place-items: center; width: 32px; height: 32px; margin-left: auto; border: 0; border-radius: 8px; background: none; color: var(--muted); cursor: pointer; }
|
|
5352
5505
|
.wt-railt .ic { width: 16px; height: 16px; }
|
|
@@ -5457,6 +5610,24 @@ a.dec-rc:hover .dec-rc-w { text-decoration: underline; }
|
|
|
5457
5610
|
.dec-given-how { color: var(--text2); }
|
|
5458
5611
|
.dec-given code { font-size: 12px; }
|
|
5459
5612
|
.dec-open { display: inline-flex; align-items: center; min-height: 44px; font-size: 13px; }
|
|
5613
|
+
/* the panel's list: one quiet line (status · id · source), the decision, why; a hairline between rows */
|
|
5614
|
+
.dec-list { gap: 0; }
|
|
5615
|
+
.dec-list > .dec-row { padding: 10px 0; border-top: 1px solid var(--line); }
|
|
5616
|
+
.dec-list > .dec-row:first-child { border-top: 0; padding-top: 2px; }
|
|
5617
|
+
.dec-row-h { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 2px; font-size: 11.5px; line-height: 1.5; color: var(--text2); }
|
|
5618
|
+
.dec-row-h .dec-st { margin-left: 0; font-size: 11.5px; color: var(--text); }
|
|
5619
|
+
.dec-row-h .dec-id { font: 500 11px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--text2); opacity: .85; }
|
|
5620
|
+
.dec-row-h .dec-src { margin-top: 0; font-size: 11.5px; }
|
|
5621
|
+
.dec-auto { font-size: 11.5px; color: var(--text2); }
|
|
5622
|
+
.dec-dot { color: var(--text2); opacity: .6; }
|
|
5623
|
+
.dec-list .dec-text { font-size: 14px; font-weight: 500; line-height: 1.4; margin-top: 2px; overflow-wrap: anywhere; }
|
|
5624
|
+
.dec-row-rejected .dec-text { text-decoration: line-through; text-decoration-thickness: 1px; color: var(--text2); }
|
|
5625
|
+
.dec-row-superseded .dec-text { color: var(--text2); }
|
|
5626
|
+
.dec-list .dec-why, .dec-list .dec-alt { font-size: 12.5px; line-height: 1.4; }
|
|
5627
|
+
/* compact buttons: a small pill inside a 44px hit area */
|
|
5628
|
+
.dec-acts-panel { gap: 6px; margin-top: 8px; }
|
|
5629
|
+
.dec-acts.dec-acts-panel .btn { position: relative; min-height: 0; height: 28px; padding: 0 10px; font-size: 12.5px; border-radius: 7px; }
|
|
5630
|
+
.dec-acts.dec-acts-panel .btn::after { content: ''; position: absolute; inset: -8px -3px; }
|
|
5460
5631
|
|
|
5461
5632
|
.dec-page .dec-head h1 { margin: 4px 0 2px; }
|
|
5462
5633
|
.dec-tl { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 0; }
|
|
@@ -5496,6 +5667,7 @@ a.dec-rc:hover .dec-rc-w { text-decoration: underline; }
|
|
|
5496
5667
|
.dec-flash { background: color-mix(in srgb, var(--text2) 10%, transparent); transition: background .6s; }
|
|
5497
5668
|
@media (prefers-reduced-motion: reduce) { .dec-flash { transition: none; } }
|
|
5498
5669
|
.dec-proj p { margin: 4px 0 10px; }
|
|
5670
|
+
.dec-empty { margin: 6px 0 10px; } .dec-empty p, .dec-proj .dec-empty p { margin: 0 0 4px; max-width: 64ch; } /* 2026-11-05 where decisions come from, on an empty log */
|
|
5499
5671
|
|
|
5500
5672
|
.wt-decs { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0 2px; }
|
|
5501
5673
|
.wt-dec { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; min-height: 32px; padding: 4px 8px; font-weight: 400; }
|
|
@@ -5566,3 +5738,30 @@ a.tp-cite::after { content: ''; position: absolute; inset: -10px -4px; }
|
|
|
5566
5738
|
.prs-picks { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 12px; padding: 8px 12px; margin: 0 0 10px; border: 1px solid var(--line); border-radius: 10px; background: var(--bg); }
|
|
5567
5739
|
.prs-picks .btn, .prs-picks .linkish { min-height: 44px; }
|
|
5568
5740
|
.wt-dec .wt-dec-id { white-space: nowrap; flex: none; }
|
|
5741
|
+
|
|
5742
|
+
/* 2026-11-06 the quiet "Updated" after the board catches up on return (ui/app.js caughtUpCue): a check
|
|
5743
|
+
and a word, out of the way under the top row, no spinner; no slide under reduced motion */
|
|
5744
|
+
.caught-up { position: fixed; top: calc(var(--lf-top, 0px) + env(safe-area-inset-top, 0px) + 56px); left: 50%; transform: translate(-50%, -4px); z-index: 60; display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; border: 1px solid var(--line, rgba(127,127,127,.3)); background: var(--card, var(--bg, #fff)); color: var(--muted, inherit); font-size: 12.5px; pointer-events: none; opacity: 0; transition: opacity .2s ease, transform .2s ease; }
|
|
5745
|
+
.caught-up[hidden] { display: none; }
|
|
5746
|
+
.caught-up .ic { width: 14px; height: 14px; }
|
|
5747
|
+
.caught-up.in { opacity: 1; transform: translate(-50%, 0); }
|
|
5748
|
+
.caught-up.out { opacity: 0; }
|
|
5749
|
+
@media (prefers-reduced-motion: reduce) { .caught-up { transition: none; transform: translate(-50%, 0); } }
|
|
5750
|
+
|
|
5751
|
+
/* 2026-11-06 subagents working (ui/subagents-view.js): a spinner shape and words, in the status pill
|
|
5752
|
+
and as Live's line under the thread; the spinner stands still under reduced motion */
|
|
5753
|
+
.sub-spin { display: inline-block; width: 10px; height: 10px; border-radius: 50%; border: 2px solid currentColor; border-right-color: transparent; margin-right: 5px; vertical-align: -1px; animation: sub-spin 1s linear infinite; flex: none; }
|
|
5754
|
+
@keyframes sub-spin { to { transform: rotate(360deg); } }
|
|
5755
|
+
.lv-subs { display: flex; align-items: center; gap: 8px; min-height: 44px; margin: 6px 0 2px; padding: 6px 10px; border: 1px dashed var(--line-strong, var(--line)); border-radius: 10px; color: var(--text); font-size: 13px; }
|
|
5756
|
+
.lv-subs-what { display: flex; flex-direction: column; min-width: 0; flex: 1; }
|
|
5757
|
+
.lv-subs-step { color: var(--muted); font-family: var(--mono); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
5758
|
+
.lv-subs-when { font-size: 12px; flex: none; }
|
|
5759
|
+
@media (prefers-reduced-motion: reduce) { .sub-spin { animation: none; border-right-color: currentColor; border-style: dotted; } }
|
|
5760
|
+
|
|
5761
|
+
/* 2026-11-06 Save as HTML (digest, decision log; the walkthrough's is in its header): a quiet button,
|
|
5762
|
+
44px to a finger. The file is one self-contained .html (ui/render-export.js). */
|
|
5763
|
+
.digest-save { display: flex; justify-content: flex-end; margin: -8px 0 8px; }
|
|
5764
|
+
.btn.save-html { background: none; box-shadow: none; color: var(--muted); }
|
|
5765
|
+
.btn.save-html:hover { color: var(--text); }
|
|
5766
|
+
@media (pointer: coarse) { .btn.save-html { min-height: 44px; padding: 0 12px; } }
|
|
5767
|
+
@media (max-width: 600px) { .digest-save { justify-content: flex-start; margin: -6px 0 10px; } .btn.save-html { min-height: 44px; } }
|