@@ -531,15 +561,16 @@ export function NotesModal({ text, onChange, onClose }: {
)
@@ -625,7 +656,7 @@ export function ContextMenu({ menu, onClose }: { menu: Menu | null; onClose: ()
{menu.note &&
{menu.note}
}
{menu.items.map((it, i) => it.sep ?
: (
-
setHi(i)}
onClick={() => { it.onClick?.(); onClose() }}>
{it.icon}
@@ -816,7 +847,7 @@ export function PassPopup({ x, y, refStr, code, onConfirm, onCancel }: {
const payload = buildPass(text, refStr, code)
return (
-
{Icon.spark()}Pass on to Agent esc
+
{Icon.spark()}Pass on to agent esc
setText(e.target.value)}
@@ -825,7 +856,7 @@ export function PassPopup({ x, y, refStr, code, onConfirm, onCancel }: {
else if (e.key === 'Escape') { e.preventDefault(); onCancel() }
}} />
inserts {payload}
-
↵ insert into agent · esc cancel
+
↵ insert into agent · esc cancel
)
}
@@ -885,7 +916,7 @@ export function NamePopup({ x, y, dir, kind = 'file', mode = 'create', initial =
else if (e.key === 'Escape') { e.preventDefault(); onCancel() }
}} />
{isRename ? 'renames to' : 'creates'} {trimmed ? target + (isFolder ? '/' : '') : '…'}
-
↵ {isRename ? 'rename' : 'create'} {noun} · esc cancel
+
↵ {isRename ? 'rename' : 'create'} {noun} · esc cancel
)
}
diff --git a/src/renderer/src/styles.css b/src/renderer/src/styles.css
index 234f9dc..8765c88 100644
--- a/src/renderer/src/styles.css
+++ b/src/renderer/src/styles.css
@@ -1,52 +1,75 @@
-/* ============ Helder — dark, charcoal-neutral (ported from design handoff) ============ */
+/* ============ Helder — Kade: four surfaces, one amber accent ============ */
+/* Palette, type and geometry come from docs/design (README + Helder IDE.dc.html).
+ Four surfaces only: editor · panel · raised · hover. Amber is reserved for
+ action, state and signal — never a decorative fill. */
:root {
- --bg-0:#2b2e34; /* editor surface (deepest) */
- --bg-1:#30343b; /* terminals */
- --bg-2:#373c44; /* sidebars */
- --bg-3:#40454e; /* headers / tabs strip */
- --hover:#4a505a;
- --active:#535a66;
- --sel:#49525f;
- --border:#474c55;
- --border-2:#535963;
- --fg-0:#fbfcfd;
- --fg-1:#dde1e7;
- --fg-2:#b0b6bf;
- --fg-3:#8f96a0;
- --accent:#f19f3f;
+ /* --- surfaces --- */
+ --bg-0:#101720; /* editor canvas, terminal, code blocks */
+ --bg-1:#101720; /* terminals share the editor ground */
+ --bg-2:#18202B; /* panels, title bar, status bar, overlays */
+ --bg-3:#18202B; /* headers / tab strips — same panel surface */
+ --hover:#1E2733; /* row hover fill, nothing else */
+ --active:#232C39;
+ --sel:#232C39; /* selected row */
+ --border:#232C39; /* every hairline */
+ --border-2:#232C39;
+ --raised:#232C39;
+ /* --- text on dark --- */
+ --fg-0:#F4F5F4; /* active file, dialog titles, selected row */
+ --fg-1:#E4E7E6; /* body copy, code plain text */
+ --fg-2:#BAC0C0; /* inactive rows, identifiers, secondary copy */
+ --fg-3:#6C7783; /* labels, paths, meta, comments */
+ --fg-4:#3A424C; /* line numbers, disabled */
+ /* --- amber, the only accent --- */
+ --accent:#E8913A;
+ --accent-deep:#C4741F;
+ --accent-lite:#F0B476;
+ --accent-soft:rgba(232,145,58,0.10); /* tint fill */
+ --accent-dim:rgba(232,145,58,0.35); /* keycap border on an active toggle */
+ --accent-line:rgba(232,145,58,0.35);
+ --accent-ring:rgba(232,145,58,0.22); /* the 2px focus ring */
+ --row-soft:#1E2733;
- --accent-soft:rgba(241,159,63,0.16);
- /* row states: the open row is --sel + a solid accent bar, focus/hover repeat
- both at 30%, so the weaker pair reads as an echo of the open row. */
- --row-soft:rgba(73,82,95,0.30);
- --accent-dim:rgba(241,159,63,0.30);
- --accent-line:rgba(241,159,63,0.55);
- --add:#5cbd6b;
- --del:#e0696a;
- --mod:#d8a85c;
- --ren:#5aa6d6;
- --add-bg:rgba(92,189,107,0.10);
- --del-bg:rgba(224,105,106,0.10);
- /* syntax */
- --t-key:#c98bdb;
- --t-str:#94c980;
- --t-num:#e0a06a;
- --t-fn:#6aa6f0;
- --t-com:#5f656e;
- --t-tag:#7fc6a0;
- --t-attr:#d8b15c;
- --t-punc:#9aa0a8;
- --t-var:#e6e8ea;
- --t-const:#e08b6a;
- --t-prop:#6ec0c0;
- --ui:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
- --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
+ /* --- diff: teal added, amber-deep removed. No green, no red. --- */
+ --add:#8FBFB4;
+ --del:#C4741F;
+ --mod:#F0B476;
+ --ren:#BAC0C0;
+ --add-bg:rgba(143,191,180,0.12);
+ --del-bg:rgba(196,116,31,0.14);
+
+ /* --- syntax: six colours, all muted, weight 400 everywhere --- */
+ --t-key:#C3A6CE; /* keyword · operator · pseudo-class */
+ --t-str:#8FBFB4; /* string · value · type path */
+ --t-num:#F0B476; /* number · tag · hex literal */
+ --t-fn:#E4E7E6; /* plain text · function name */
+ --t-com:#6C7783; /* comment */
+ --t-tag:#F0B476;
+ --t-attr:#BAC0C0;
+ --t-punc:#6C7783;
+ --t-var:#BAC0C0; /* variable · property */
+ --t-const:#F0B476;
+ --t-prop:#BAC0C0;
+
+ /* --- type --- */
+ --ui:"IBM Plex Sans",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
+ --mono:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
/* code surfaces (editor + terminals) — overridable from .helder/theme.css */
- --code-font:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
+ --code-font:"IBM Plex Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
--code-size:13px;
- --term-size:12.5px;
+ --term-size:12px;
+
+ /* --- geometry --- */
+ --r-sm:2px; /* buttons, inputs, tags, keycaps, code blocks */
+ --r-md:4px; /* panels, cards, menus */
+ --r-lg:8px; /* overlays only */
+ --bar-h:34px; /* the one top-bar height: commit box, Explorer head, view strip */
+ --shadow-menu:0 4px 16px rgba(23,28,34,.10);
+ --shadow-overlay:0 16px 48px rgba(23,28,34,.18);
+ /* Colour transitions only. Nothing lifts, scales or fades. */
+ --ease:cubic-bezier(0.22,1,0.36,1);
}
* { box-sizing:border-box; }
@@ -57,27 +80,27 @@ body {
overflow:hidden; -webkit-font-smoothing:antialiased;
}
#root { height:100vh; }
-::selection { background:rgba(241,159,63,0.30); }
+::selection { background:var(--accent-ring); color:var(--fg-0); }
/* One key chip, used by every shortcut hint in the app — title bar, modal
headers, empty editor, context hints. Components may only add layout
(flex, min-width, alignment) or a colour that their own surface demands. */
-kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3);
- background:transparent; border:1px solid var(--border-2); border-radius:4px; padding:1px 5px; }
+kbd { flex:0 0 auto; font-family:var(--mono); font-size:12px; font-weight:600; color:var(--accent);
+ background:transparent; border:1px solid var(--border-2); border-radius:var(--r-sm); padding:4px 6px; line-height:1; }
/* scrollbars */
::-webkit-scrollbar { width:11px; height:11px; }
-::-webkit-scrollbar-thumb { background:#393e46; border-radius:6px; border:3px solid transparent; background-clip:content-box; }
-::-webkit-scrollbar-thumb:hover { background:#4a505a; background-clip:content-box; }
+::-webkit-scrollbar-thumb { background:#232C39; border-radius:6px; border:3px solid transparent; background-clip:content-box; }
+::-webkit-scrollbar-thumb:hover { background:#2E3947; background-clip:content-box; }
::-webkit-scrollbar-corner { background:transparent; }
/* ============ shell ============ */
.app { display:flex; flex-direction:column; height:100vh; }
.titlebar {
- height:36px; flex:0 0 36px; display:flex; align-items:center; position:relative;
- background:var(--bg-3); border-bottom:1px solid var(--border);
- padding:0 12px; gap:14px; user-select:none;
+ height:44px; flex:0 0 44px; display:flex; align-items:center; position:relative;
+ background:var(--bg-2); border-bottom:1px solid var(--border);
+ padding:0 14px; gap:18px; user-select:none;
}
/* branch - repository, centered in the bar */
.tb-repo {
@@ -100,36 +123,51 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
.ff-card {
display:flex; align-items:center; gap:11px;
font-family:var(--mono); font-size:19px; line-height:1;
- padding:15px 22px; border-radius:4px;
- background:rgba(30,32,36,0.94); border:1px solid var(--border-2);
- border-left:3px solid var(--accent);
- backdrop-filter:blur(6px); box-shadow:0 16px 44px rgba(0,0,0,0.55);
+ padding:15px 22px; border-radius:var(--r-md);
+ background:var(--bg-2); border:1px solid var(--border);
+ border-left:2px solid var(--accent);
+ box-shadow:var(--shadow-overlay);
}
.ff-card svg { color:var(--accent); flex:0 0 auto; }
.ff-card .tb-repo-branch { color:var(--accent); }
/* The dash becomes a rule: same divider the rest of the chrome uses. */
.ff-card .tb-repo-sep { width:1px; height:17px; background:var(--border-2); font-size:0; margin:0 1px; }
.ff-card .tb-repo-name { font-weight:700; letter-spacing:-0.01em; }
-.traffic { display:flex; gap:8px; }
-.traffic i { width:12px; height:12px; border-radius:50%; display:block; }
-.traffic .r{background:#e0696a;} .traffic .y{background:#d8a85c;} .traffic .g{background:#5cbd6b;}
-.tb-title { font-size:12px; color:var(--fg-1); display:flex; align-items:center; gap:7px; }
-.tb-title b { color:var(--fg-0); font-weight:600; }
-.tb-crumb { color:var(--fg-3); font-size:11.5px; font-family:var(--mono); display:flex; align-items:center; gap:2px; }
-.tb-crumb .seg{color:var(--fg-2);}
-.tb-crumb .tb-dirty { color:var(--mod); font-size:10px; margin-left:4px; }
+.traffic { display:flex; gap:8px; flex:0 0 auto; }
+.traffic i { width:12px; height:12px; border-radius:9999px; display:block; }
+.traffic .r{background:var(--accent);} .traffic .y{background:var(--fg-3);} .traffic .g{background:var(--fg-4);}
+
+/* wordmark · project · branch — one baseline-aligned cluster */
+.tb-title { flex:0 0 auto; display:flex; align-items:baseline; gap:10px; font-family:var(--mono); }
+.tb-word { font-weight:700; font-size:13px; line-height:1; letter-spacing:.02em; color:var(--fg-0); }
+.tb-word i { font-style:normal; color:var(--accent); animation:blink 1.1s steps(1,end) infinite; }
+.tb-proj { font-size:12px; line-height:1; color:var(--fg-3); cursor:pointer; }
+.tb-proj:hover { color:var(--fg-1); }
+.tb-sep { font-size:12px; line-height:1; color:var(--fg-3); }
+.tb-branch { font-size:12px; line-height:1; font-weight:500; color:var(--accent); }
+
+.tb-crumb { flex:1 1 auto; min-width:0; color:var(--fg-3); font-size:12px; font-family:var(--mono);
+ display:flex; align-items:center; gap:7px; overflow:hidden; white-space:nowrap; }
+.tb-crumb .seg{color:var(--fg-3);}
+.tb-crumb .leaf { color:var(--fg-0); font-weight:600; }
+.tb-crumb .tb-dirty { color:var(--accent); font-size:10px; margin-left:4px; }
.tb-spacer { flex:1; }
-.tb-actions { display:flex; gap:6px; align-items:center; }
-/* Title-bar actions are borderless — the accent alone says "on", so no On/Off
- badge is needed. Hover is the only other surface they get. */
+.tb-actions { display:flex; gap:4px; align-items:center; flex:0 0 auto; }
+/* Toolbar toggle: label + keycap. Off = no fill. On = amber tint fill, the label
+ lifts to text-1 and the keycap border turns amber. The muted case (a toggle
+ that is off by meaning, not by focus) drops label and keycap to text-4. */
.tb-btn {
- font-size:11.5px; color:var(--fg-2); background:transparent; border:0;
- border-radius:6px; padding:4px 9px; cursor:pointer; display:flex; align-items:center; gap:6px;
+ font-family:var(--ui); font-size:12px; line-height:1; color:var(--fg-2);
+ background:transparent; border:0; border-radius:var(--r-sm);
+ padding:6px 9px; cursor:pointer; display:flex; align-items:center; gap:8px;
+ transition:color .12s var(--ease), background-color .12s var(--ease);
}
.tb-btn:hover { background:var(--hover); color:var(--fg-0); }
-.tb-toggle.on, .tb-toggle.on:hover { color:var(--accent); }
-.tb-toggle.on kbd { color:var(--accent); border-color:var(--accent-line); }
-.tb-toggle.on:hover { background:var(--accent-soft); }
+.tb-toggle.on, .tb-toggle.on:hover { background:var(--accent-soft); color:var(--fg-0); font-weight:500; }
+.tb-toggle.on kbd { border-color:var(--accent-dim); }
+/* Off by meaning (hidden files are hidden): the whole control steps back. */
+.tb-toggle.muted, .tb-toggle.muted kbd { color:var(--fg-3); }
+.tb-toggle.muted:hover { color:var(--fg-2); }
.workbench { flex:1; display:flex; min-height:0; }
@@ -138,125 +176,150 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
.col { display:flex; flex-direction:column; height:100%; min-width:0; --col-bg:var(--bg-2); background:var(--col-bg); }
/* Editor (C) shares the side panels' background (--bg-2), matching B (and A). */
.col.editor-col { flex:1; min-width:240px; }
-.col.right-col { --col-bg:var(--bg-1); background:var(--col-bg); }
-/* Active panel: subtle lighter-gray tint on the focused column. C uses the same
- tint as the side panels, so the file view stays in step with B in/out of focus. */
-.col.panel-active { --col-bg:#22252a; background:var(--col-bg); }
-.col.right-col.panel-active { --col-bg:#1e2024; background:var(--col-bg); }
+.col.right-col { --col-bg:var(--bg-2); background:var(--col-bg); }
+/* Active panel: one step of fill, nothing else. No lift, no shadow, no glow. */
+.col.panel-active { --col-bg:#1B242F; background:var(--col-bg); }
+.col.editor-col.panel-active { --col-bg:#131B25; background:var(--col-bg); }
+.col.right-col.panel-active { --col-bg:#1B242F; background:var(--col-bg); }
/* ⌘R refresh flash: A, B and C blink light grey and fade back. Two identical
animations (a/b) alternate so a second ⌘R replays it — a CSS animation only
restarts when the animation-name changes. */
.col.refresh-flash-a { animation:col-refresh-a 260ms ease-out; }
.col.refresh-flash-b { animation:col-refresh-b 260ms ease-out; }
-@keyframes col-refresh-a { 0% { background:#3a4048; } 100% { background:var(--col-bg); } }
-@keyframes col-refresh-b { 0% { background:#3a4048; } 100% { background:var(--col-bg); } }
+@keyframes col-refresh-a { 0% { background:#2A3542; } 100% { background:var(--col-bg); } }
+@keyframes col-refresh-b { 0% { background:#2A3542; } 100% { background:var(--col-bg); } }
@media (prefers-reduced-motion:reduce) {
.col.refresh-flash-a, .col.refresh-flash-b { animation-duration:180ms; animation-timing-function:steps(2); }
}
-.splitter { flex:0 0 5px; cursor:col-resize; background:transparent; position:relative; z-index:5; }
-.splitter::after { content:""; position:absolute; inset:0 2px; background:var(--border); transition:background .12s; }
-.splitter:hover::after, .splitter.drag::after { background:var(--accent-line); }
-.splitter.h { cursor:row-resize; flex:0 0 5px; width:100%; }
+/* Every divider is one hairline, like the rest of the chrome. The splitter is
+ 1px wide in layout; the ::after reaches past it on both sides to give the
+ pointer a 7px target, so the line stays thin without being hard to grab. */
+.splitter { flex:0 0 1px; cursor:col-resize; background:var(--border); position:relative; z-index:5;
+ transition:background .12s var(--ease); }
+.splitter::after { content:""; position:absolute; top:0; bottom:0; left:-3px; right:-3px; }
+.splitter:hover, .splitter.drag { background:var(--accent); }
+.splitter.h { cursor:row-resize; flex:0 0 1px; width:100%; }
+.splitter.h::after { left:0; right:0; top:-3px; bottom:-3px; }
/* panel header */
+/* Standard panel label: Mono 700 10px, .14em, uppercase, text-4. */
.phead {
- height:30px; flex:0 0 30px; display:flex; align-items:center; gap:8px;
- padding:0 10px 0 12px; font-size:10.5px; letter-spacing:.09em; text-transform:uppercase;
- color:var(--fg-2); border-bottom:1px solid var(--border); user-select:none;
+ height:var(--bar-h); flex:0 0 var(--bar-h); display:flex; align-items:center; gap:8px;
+ padding:0 12px; font-family:var(--mono); font-weight:700; font-size:10px; line-height:1;
+ letter-spacing:.14em; text-transform:uppercase;
+ color:var(--fg-3); border-bottom:1px solid var(--border); user-select:none;
}
-.phead .ct { margin-left:auto; font-size:10px; color:var(--fg-3); letter-spacing:.02em; text-transform:none;
- background:var(--bg-3); border:1px solid var(--border); border-radius:9px; padding:0 7px; line-height:16px; }
+.phead .ct { margin-left:auto; font-size:10px; color:var(--fg-3); letter-spacing:.14em; text-transform:uppercase;
+ background:transparent; border:0; padding:0; line-height:1; }
.phead .ico-btn { color:var(--fg-3); cursor:pointer; padding:2px; border-radius:4px; display:flex; }
.phead .ico-btn:hover { background:var(--hover); color:var(--fg-1); }
/* ============ git panel ============ */
-.commit-box { padding:9px 10px; border-bottom:1px solid var(--border); display:flex; gap:7px; align-items:flex-start; }
-.commit-input { flex:1; min-width:0; resize:none; background:var(--bg-0); border:1px solid var(--border-2); border-radius:7px; color:var(--fg-0); font-family:var(--ui); font-size:12px; line-height:16px; padding:7px 9px; outline:none; min-height:32px; }
-.commit-input:focus { border-color:var(--accent-line); }
+/* One line at rest, so this bar matches the Explorer head and the view strip.
+ Focus grows the box downward inside the git column only. */
+.commit-box { height:var(--bar-h); flex:0 0 auto; padding:0 12px; border-bottom:1px solid var(--border); display:flex; gap:8px; align-items:center; }
+.commit-box:focus-within { height:auto; padding:8px 12px; align-items:flex-start; }
+.commit-input { flex:1; min-width:0; resize:none; background:var(--bg-0); border:1px solid var(--border-2); border-radius:var(--r-sm); color:var(--fg-1); font-family:var(--ui); font-size:12px; line-height:1.5; padding:3px 9px; outline:none; height:26px; }
+/* Focus is the same everywhere: 2px amber border plus the 22% ring. */
+.commit-input:focus { border-color:var(--accent); border-width:2px; padding:6px 8px; box-shadow:0 0 0 2px var(--accent-ring); height:72px; }
.commit-input::placeholder { color:var(--fg-3); }
-.push-btn { flex:0 0 auto; display:flex; align-items:center; justify-content:center; width:32px; min-height:32px; align-self:stretch; background:var(--bg-0); border:1px solid var(--border-2); border-radius:7px; color:var(--fg-2); cursor:pointer; }
-.push-btn:hover { background:var(--hover); border-color:var(--accent-line); color:var(--accent); }
+.push-btn { flex:0 0 26px; display:flex; align-items:center; justify-content:center; width:26px; height:26px; background:transparent; border:1px solid var(--border-2); border-radius:var(--r-sm); color:var(--fg-2); cursor:pointer; }
+.push-btn:hover { background:var(--hover); color:var(--accent); }
.commit-btn { flex:0 0 auto; display:flex; align-items:center; gap:6px; background:var(--accent); color:#201608; border:0; border-radius:7px; font:inherit; font-size:12px; font-weight:600; padding:0 11px; height:32px; cursor:pointer; }
.commit-btn:hover:not(:disabled) { background:#f6b35f; }
.commit-btn:disabled { background:var(--bg-3); color:var(--fg-3); cursor:not-allowed; }
-.git-body { overflow:auto; flex:1; padding:4px 0 10px; }
-.git-group { padding:8px 12px 3px; font-size:10px; letter-spacing:.06em; text-transform:uppercase; color:var(--fg-3); display:flex; align-items:center; gap:6px; }
-.git-group .gc { color:var(--fg-3); }
-.git-group .grp-act { margin-left:auto; display:flex; opacity:0; background:transparent; border:0; color:var(--fg-2); padding:2px; border-radius:4px; cursor:pointer; }
+.git-body { overflow:auto; flex:1; padding:0 0 8px; }
+/* Group header: the standard 10px mono label, count right in amber. */
+.git-group { padding:14px 12px 6px; font-family:var(--mono); font-weight:700; font-size:10px; line-height:1;
+ letter-spacing:.14em; text-transform:uppercase; color:var(--fg-3); display:flex; align-items:center; gap:8px; }
+.git-group .gc { margin-left:auto; color:var(--accent); }
+.git-group .grp-act { display:flex; opacity:0; background:transparent; border:0; color:var(--fg-3); padding:2px; border-radius:var(--r-sm); cursor:pointer; }
.git-group:hover .grp-act { opacity:1; }
-.git-group .grp-act:hover { background:var(--hover); color:var(--fg-0); }
-.git-empty { display:flex; flex-direction:column; align-items:center; gap:9px; padding:30px 16px; color:var(--fg-3); font-size:12px; text-align:center; }
-.git-empty svg { color:var(--add); opacity:.7; }
-.git-none { padding:5px 14px 9px; font-size:11.5px; color:var(--fg-3); }
-.git-none .key { font-family:var(--mono); font-size:11px; color:var(--fg-2); border:1px solid var(--border-2); border-radius:4px; padding:0 5px; }
-.git-divider { height:1px; background:var(--border); margin:8px 12px 2px; }
+.git-group .grp-act:hover { color:var(--accent); }
+/* Empty state: one plain sentence starting with an em dash. No icon. */
+.git-empty { padding:14px 12px; color:var(--fg-3); font-size:12px; line-height:1.6; }
+.git-empty svg { display:none; }
+.git-none { padding:2px 12px 8px; font-size:12px; color:var(--fg-3); }
+.git-none .key { font-family:var(--mono); font-size:11px; color:var(--fg-2); border:1px solid var(--border-2); border-radius:var(--r-sm); padding:0 5px; }
+.git-divider { height:1px; background:var(--border); margin:16px 12px 0; }
.git-row {
- display:flex; align-items:center; gap:8px; padding:3px 12px 3px 14px; cursor:pointer; position:relative;
+ height:26px; display:flex; align-items:center; gap:8px; padding:0 12px 0 14px; cursor:pointer; position:relative;
}
+/* Where the changed file lives. One header per folder, above its rows, so a
+ name like index.blade.php is never ambiguous. */
+.git-dir-head { height:24px; display:flex; align-items:center; gap:8px; padding:0 12px 0 14px;
+ font-family:var(--mono); font-size:11px; line-height:1; color:var(--fg-3);
+ white-space:nowrap; overflow:hidden; }
+.git-dir-head .folder-ic { width:14px; height:14px; flex:0 0 14px; }
+.git-dir-head .gdh-path { overflow:hidden; text-overflow:ellipsis; direction:rtl; text-align:left; }
/* ===== Row states — one language for every list that offers a row to click ====
- hover / focus — "a click or ↵ acts here": --row-soft, 3px --accent-dim bar.
- open — the file the viewer shows: --sel, 3px solid --accent bar.
- Hover and focus look alike on purpose: the pointer moves the row cursor onto
- whatever it touches, so only one row ever carries the pair. Open wins over
- both, which is why its rules come last.
+ rest — no fill.
+ hover — one step of fill (--hover) and nothing else. No rule, no lift.
+ selected — --sel fill plus a 2px amber rule on the left; the label lifts to
+ text-1. The keyboard cursor and the open file are both "selected",
+ so they read the same: only one row in a list ever carries it.
Lists covered: Git, Explorer, Recent files, the search overlay (file names,
file headers, content lines), the project palette, the ⌘-click popup.
A context menu is deliberately left out — it is a menu, not a list of state. */
.git-row, .tree-row, .hist-row, .fres, .sr-file, .sr-line, .pres, .sym-row { position:relative; }
-.git-row:hover, .git-row.ctx, .git-row.kbd,
-.tree-row:hover, .tree-row.ctx, .tree-row.kbd,
-.hist-row:hover, .hist-row.sel,
-.fres:hover, .fres.sel,
-.sr-file:hover, .sr-line:hover, .sr-line.sel,
-.pres:hover, .pres.sel,
-.sym-row:hover, .sym-row.hi { background:var(--row-soft); }
-.git-row:hover::before, .git-row.ctx::before, .git-row.kbd::before,
-.tree-row:hover::before, .tree-row.ctx::before, .tree-row.kbd::before,
-.hist-row:hover::before, .hist-row.sel::before,
-.fres:hover::before, .fres.sel::before,
-.sr-file:hover::before, .sr-line:hover::before, .sr-line.sel::before,
-.pres:hover::before, .pres.sel::before,
-.sym-row:hover::before, .sym-row.hi::before {
- content:""; position:absolute; left:0; top:0; bottom:0; width:3px; background:var(--accent-dim);
-}
+.git-row:hover, .tree-row:hover, .hist-row:hover, .fres:hover,
+.sr-file:hover, .sr-line:hover, .pres:hover, .sym-row:hover { background:var(--hover); }
+.git-row.ctx, .git-row.kbd,
+.tree-row.ctx, .tree-row.kbd,
+.hist-row.sel, .fres.sel, .sr-line.sel, .pres.sel, .sym-row.hi,
.git-row.active, .tree-row.active { background:var(--sel); }
-.git-row.active::before, .tree-row.active::before { content:""; position:absolute; left:0; top:0; bottom:0; width:3px; background:var(--accent); }
+.git-row.ctx::before, .git-row.kbd::before,
+.tree-row.ctx::before, .tree-row.kbd::before,
+.hist-row.sel::before, .fres.sel::before, .sr-line.sel::before, .pres.sel::before, .sym-row.hi::before,
+.git-row.active::before, .tree-row.active::before {
+ content:""; position:absolute; left:0; top:0; bottom:0; width:2px; background:var(--accent);
+}
.git-row.ctx .git-act, .git-row.kbd .git-act { visibility:visible; }
-.git-stat { width:13px; text-align:center; font-family:var(--mono); font-size:11px; font-weight:600; flex:0 0 13px; }
-.git-stat.M{color:var(--mod);} .git-stat.A{color:var(--add);} .git-stat.D{color:var(--del);} .git-stat.R{color:var(--ren);} .git-stat.U{color:var(--add);}
-.git-name { font-size:12.5px; color:var(--fg-1); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
+/* Status letter: staged rows read teal, unstaged amber-soft. */
+.git-stat { width:12px; flex:0 0 12px; font-family:var(--mono); font-size:11px; font-weight:600; line-height:1; color:var(--mod); }
+.git-row.staged .git-stat { color:var(--add); }
+.git-stat.D{color:var(--del);} .git-stat.R{color:var(--ren);}
+.git-name { font-family:var(--ui); font-size:12px; color:var(--fg-2); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
/* Files in the root `tests/` or `cypress/` folder stay a step greyer, so real source changes read first. Git list only. */
.git-row.test .git-name { color:var(--fg-3); }
-.git-row.active .git-name { color:var(--fg-0); }
+.git-row.active .git-name, .git-row.kbd .git-name { color:var(--fg-0); font-weight:500; }
.git-name.del { text-decoration:line-through; color:var(--fg-3); }
-.git-dir { color:var(--fg-3); font-size:11px; margin-left:auto; padding-left:8px; white-space:nowrap; max-width:42%; overflow:hidden; text-overflow:ellipsis; direction:rtl; }
-.git-act { flex:0 0 auto; display:flex; visibility:hidden; align-items:center; justify-content:center; width:20px; height:20px; padding:0; background:transparent; border:0; border-radius:5px; color:var(--fg-2); cursor:pointer; margin-left:4px; }
+.git-dir { color:var(--fg-3); font-size:11px; font-family:var(--mono); margin-left:auto; padding-left:8px; white-space:nowrap; max-width:42%; overflow:hidden; text-overflow:ellipsis; direction:rtl; }
+.git-act { flex:0 0 auto; display:flex; visibility:hidden; align-items:center; justify-content:center; width:18px; height:18px; padding:0; background:transparent; border:0; border-radius:var(--r-sm); color:var(--fg-3); cursor:pointer; margin-left:4px; }
.git-act.push { margin-left:auto; } /* right-align when the dir column is hidden */
.git-row:hover .git-act { visibility:visible; }
-.git-act:hover { background:var(--active); color:var(--fg-0); }
-.git-foot { border-top:1px solid var(--border); padding:8px 12px; display:flex; align-items:center; gap:8px; font-size:11px; color:var(--fg-2); }
-.branch-chip { display:flex; align-items:center; gap:6px; color:var(--fg-1); }
-.branch-chip b { font-weight:600; color:var(--fg-0); }
+.git-act:hover { color:var(--accent); }
+.git-foot { border-top:1px solid var(--border); padding:12px; display:flex; align-items:center; gap:8px;
+ font-family:var(--mono); font-size:11px; line-height:1.5; color:var(--fg-3); }
+.branch-chip { display:flex; align-items:center; gap:6px; color:var(--fg-3); }
+.branch-chip svg { display:none; }
+.branch-chip b { font-weight:400; color:var(--fg-3); }
/* ============ file tree ============ */
-.tree-body { overflow:auto; flex:1; padding:4px 0 14px; }
-.tree-row { display:flex; align-items:center; gap:6px; padding:2px 10px 2px 0; cursor:pointer; white-space:nowrap; position:relative; height:23px; }
+.tree-body { overflow:auto; flex:1; padding:6px 0 14px; }
+.tree-row { display:flex; align-items:center; gap:7px; padding:0 12px 0 0; cursor:pointer; white-space:nowrap; position:relative; height:24px; }
/* A folder never reaches `active` — it opens in the tree, not in the viewer —
but it takes focus and hover like a file. See the row-state block above. */
-.tw { display:inline-flex; align-items:center; justify-content:center; width:14px; flex:0 0 14px; color:var(--fg-3); font-size:10px; }
-.tree-label { font-size:12.5px; color:var(--fg-1); overflow:hidden; text-overflow:ellipsis; }
-.tree-row.active .tree-label { color:var(--fg-0); }
-.tree-row.folder .tree-label { color:var(--fg-1); }
-.tree-badge { margin-left:auto; font-family:var(--mono); font-size:10px; font-weight:600; padding-left:8px; }
-.tree-badge.M{color:var(--mod);} .tree-badge.A{color:var(--add);} .tree-badge.D{color:var(--del);}
+.tw { display:inline-flex; align-items:center; justify-content:center; width:10px; flex:0 0 10px; color:var(--fg-3); font-size:11px; }
+/* An expanded folder is the one place a chevron turns amber: it marks the path
+ down to the open file. */
+.tree-row.folder.open .tw { color:var(--accent); }
+.tree-label { font-family:var(--ui); font-size:13px; color:var(--fg-2); overflow:hidden; text-overflow:ellipsis; }
+.tree-row.active .tree-label, .tree-row.kbd .tree-label { color:var(--fg-0); font-weight:500; }
+.tree-row.folder.open .tree-label { color:var(--fg-0); }
+.tree-badge { margin-left:auto; font-family:var(--mono); font-size:10px; font-weight:600; padding-left:8px; color:var(--add); }
+.tree-badge.M{color:var(--add);} .tree-badge.A{color:var(--add);} .tree-badge.D{color:var(--del);}
-/* file type monogram icon */
-.ficon { width:15px; height:15px; flex:0 0 15px; border-radius:3.5px; display:inline-flex; align-items:center; justify-content:center;
- font-family:var(--mono); font-size:7.5px; font-weight:700; color:#11131600; position:relative; }
-.ficon span { color:#0c0d0f; font-size:7.5px; line-height:1; letter-spacing:-.3px; }
-.folder-ic { width:15px; height:15px; flex:0 0 15px; display:inline-flex; align-items:center; justify-content:center; color:var(--fg-2); }
+/* File-type badge: ink text on a per-extension fill from the syntax palette.
+ Sized to be read at a glance, not to disappear next to the file name. */
+/* One fixed width for every badge (the longest label is four characters), so the
+ file names line up in a column instead of stepping in and out. */
+.ficon { flex:0 0 28px; width:28px; border-radius:var(--r-sm); padding:3px 0; display:inline-flex; align-items:center; justify-content:center;
+ font-family:var(--mono); font-size:10px; font-weight:600; line-height:1; overflow:hidden; }
+.ficon span { color:var(--bg-0); font-size:10px; line-height:1; letter-spacing:0; text-align:center; }
+.folder-ic { width:16px; height:16px; flex:0 0 16px; display:inline-flex; align-items:center; justify-content:center; color:var(--fg-3); }
/* ============ editor ============ */
@@ -270,23 +333,28 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
— a track only grows past its base into free space, and a scrolled pane has
none, so it would pin every row to the viewport width again.
align-content:start stops a short file from stretching rows vertically. */
-.editor { flex:1; overflow:auto; font-family:var(--code-font); font-size:var(--code-size); line-height:20px; padding:6px 0 40px;
- display:grid; grid-template-columns:minmax(max-content, 1fr); align-content:start; }
+.editor { flex:1; overflow:auto; font-family:var(--code-font); font-size:var(--code-size); font-weight:400; line-height:20px; padding:10px 0 40px;
+ display:grid; grid-template-columns:minmax(max-content, 1fr); align-content:start; background:var(--bg-0); }
.ln-row { display:flex; align-items:flex-start; min-height:20px; }
-.ln-row.cursor { background:rgba(255,255,255,0.035); }
-.ln-row.add { background:var(--add-bg); }
-.ln-row.del { background:var(--del-bg); }
+.ln-row.cursor { background:rgba(255,255,255,0.03); }
+/* A changed row: the fill plus a 2px rule on the left. The diff reads on shape
+ and on the rule, never on alarm colour. */
+.ln-row.add { background:var(--add-bg); box-shadow:inset 2px 0 0 var(--add); }
+.ln-row.del { background:var(--del-bg); box-shadow:inset 2px 0 0 var(--del); }
.ln-row.selrange { background:var(--accent-soft); }
-.ln-gutter { flex:0 0 54px; width:54px; text-align:right; padding-right:14px; color:var(--fg-3); user-select:none; cursor:pointer; font-size:12px; }
-.ln-row.cursor .ln-gutter { color:var(--fg-1); }
-.ln-gutter:hover { color:var(--fg-1); }
+.ln-gutter { flex:0 0 56px; width:56px; text-align:right; padding-right:14px; color:var(--fg-4); user-select:none; cursor:pointer; font-size:13px; }
+.ln-row.cursor .ln-gutter { color:var(--fg-2); }
+/* A changed line lifts its own number — never leave it at the disabled grey. */
+.ln-row.add .ln-gutter { color:var(--add); }
+.ln-row.del .ln-gutter { color:var(--del); }
+.ln-gutter:hover { color:var(--fg-2); }
.ln-sign { flex:0 0 14px; width:14px; text-align:center; user-select:none; color:var(--fg-3); }
.ln-row.add .ln-sign { color:var(--add); }
.ln-row.del .ln-sign { color:var(--del); }
/* flex-basis auto (not 0) so the line's real width counts towards the row's
intrinsic size. With basis 0 the grid track above collapses to the viewport
and the add/del background stops at the fold again. */
-.ln-code { flex:1 0 auto; white-space:pre; padding:0 16px 0 6px; min-width:0; }
+.ln-code { flex:1 0 auto; white-space:pre; padding:0 16px 0 0; min-width:0; }
.editor.diff .ln-code { padding-left:6px; }
/* Wrapped read-only view: the line folds inside its own column, so the number
column keeps its single number at the top of the block. The grid track must
@@ -294,87 +362,121 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
which would widen the row instead of breaking it. */
.editor.wrap { overflow-x:hidden; grid-template-columns:1fr; }
.editor.wrap .ln-code { flex:1 1 auto; white-space:pre-wrap; overflow-wrap:break-word; }
-.empty-ed { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; color:var(--fg-3); gap:14px; }
-.empty-ed .big { font-size:13px; }
-.empty-ed .klist { display:flex; flex-direction:column; gap:9px; font-size:12px; }
-.empty-ed .klist div { display:flex; gap:10px; align-items:center; justify-content:space-between; min-width:230px; }
+.empty-ed { flex:1; display:flex; flex-direction:column; align-items:center; justify-content:center; color:var(--fg-3); gap:18px; background:var(--bg-0); }
+.empty-ed svg { display:none; }
+.empty-ed .big { font-family:var(--ui); font-size:14px; line-height:1.7; color:var(--fg-3); }
+.empty-ed .klist { display:flex; flex-direction:column; gap:6px; font-size:13px; }
+.empty-ed .klist div { display:flex; gap:14px; align-items:center; justify-content:space-between; min-width:260px; padding:6px 0; color:var(--fg-1); }
-.diff-bar { height:26px; flex:0 0 26px; display:flex; align-items:center; gap:12px; padding:0 14px; background:var(--bg-3); border-bottom:1px solid var(--border); font-size:11px; color:var(--fg-2); }
-.diff-bar .a{color:var(--add);font-family:var(--mono);} .diff-bar .d{color:var(--del);font-family:var(--mono);}
+/* 34px strip: state label, the two counts, then the segmented view control. */
+.diff-bar { height:var(--bar-h); flex:0 0 var(--bar-h); display:flex; align-items:center; gap:14px; padding:0 14px; background:var(--bg-0); border-bottom:1px solid var(--border); font-size:11px; color:var(--fg-3); }
+.diff-bar .git-stat { width:auto; flex:0 0 auto; font-family:var(--mono); font-weight:700; font-size:10px; line-height:1;
+ letter-spacing:.14em; text-transform:uppercase; color:var(--fg-3); }
+.diff-bar .a{color:var(--add);font-family:var(--mono);font-weight:500;font-size:12px;}
+.diff-bar .d{color:var(--del);font-family:var(--mono);font-weight:500;font-size:12px;}
.diff-bar .toggle { margin-left:auto; display:flex; border:1px solid var(--border-2); border-radius:6px; overflow:hidden; }
.diff-bar .toggle button { background:transparent; border:0; color:var(--fg-2); font:inherit; font-size:11px; padding:2px 10px; cursor:pointer; }
.diff-bar .toggle button.on { background:var(--accent-soft); color:var(--fg-0); }
-/* four-segment view control */
-.diff-bar .seg { margin-left:auto; display:flex; border:1px solid var(--border-2); border-radius:7px; overflow:hidden; }
-.diff-bar .seg button { background:transparent; border:0; border-right:1px solid var(--border-2); color:var(--fg-2); font:inherit; font-size:11px; padding:3px 12px; cursor:pointer; display:flex; align-items:center; gap:6px; }
-.diff-bar .seg button:last-child { border-right:0; }
+/* four-segment view control — the active side is the amber fill with ink text */
+.diff-bar .seg { margin-left:auto; display:flex; border:1px solid var(--border-2); border-radius:var(--r-sm); overflow:hidden; }
+.diff-bar .seg button { background:transparent; border:0; border-left:1px solid var(--border-2); color:var(--fg-2);
+ font-family:var(--ui); font-size:11px; font-weight:400; line-height:1; padding:5px 12px; cursor:pointer; display:flex; align-items:center; gap:6px;
+ transition:color .12s var(--ease), background-color .12s var(--ease); }
+.diff-bar .seg button:first-child { border-left:0; }
.diff-bar .seg button:hover { color:var(--fg-0); background:var(--hover); }
-.diff-bar .seg button.on { background:var(--accent-soft); color:var(--fg-0); }
-.diff-bar .seg .split-btn svg { opacity:.85; }
-.diff-bar .db-lang { font-family:var(--mono); font-size:10.5px; color:var(--fg-3); letter-spacing:.02em; }
+.diff-bar .seg button.on, .diff-bar .seg button.on:hover { background:var(--accent); color:#171C22; font-weight:500; }
+.diff-bar .seg .split-btn svg { display:none; }
+.diff-bar .db-lang { font-family:var(--mono); font-weight:700; font-size:10px; color:var(--fg-3); letter-spacing:.14em; text-transform:uppercase; }
/* Which pair the diff compares. Only shown when a file is staged AND edited
again, so the two git rows can be told apart. */
.db-side {
- font-family:var(--mono); font-size:10px; color:var(--fg-3); letter-spacing:.02em;
- padding:1px 5px; border:1px solid var(--border); border-radius:4px; white-space:nowrap;
+ font-family:var(--mono); font-size:11px; color:var(--fg-3); letter-spacing:0;
+ padding:0; border:0; white-space:nowrap;
}
/* image preview (viewer shows a picture, not text) */
.img-view { flex:1; min-height:0; overflow:auto; display:flex; align-items:center; justify-content:center; padding:24px; background:var(--bg-0); }
.img-view-img {
- max-width:100%; max-height:100%; object-fit:contain; border-radius:6px;
+ max-width:100%; max-height:100%; object-fit:contain; border-radius:var(--r-sm);
/* Checkerboard so transparent PNGs/SVGs read clearly on the dark surface. */
- background-color:#2a2d33;
+ background-color:var(--bg-2);
background-image:
- linear-gradient(45deg, #232529 25%, transparent 25%), linear-gradient(-45deg, #232529 25%, transparent 25%),
- linear-gradient(45deg, transparent 75%, #232529 75%), linear-gradient(-45deg, transparent 75%, #232529 75%);
+ linear-gradient(45deg, #232C39 25%, transparent 25%), linear-gradient(-45deg, #232C39 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #232C39 75%), linear-gradient(-45deg, transparent 75%, #232C39 75%);
background-size:20px 20px;
background-position:0 0, 0 10px, 10px -10px, -10px 0;
- box-shadow:0 4px 24px rgba(0,0,0,.4);
+ border:1px solid var(--border);
}
/* rendered-markdown preview (Preview view option) */
-.md-view { flex:1; overflow:auto; padding:8px 0 48px; }
-.md-body { max-width:860px; margin:0 auto; padding:14px 40px 40px; color:var(--fg-1); font-family:var(--ui); font-size:14px; line-height:1.65; }
-.md-body h1, .md-body h2, .md-body h3, .md-body h4, .md-body h5, .md-body h6 { color:var(--fg-0); font-weight:600; line-height:1.3; margin:1.4em 0 .55em; }
-.md-body h1 { font-size:1.7em; padding-bottom:.3em; border-bottom:1px solid var(--border); }
-.md-body h2 { font-size:1.4em; padding-bottom:.25em; border-bottom:1px solid var(--border); }
-.md-body h3 { font-size:1.18em; } .md-body h4 { font-size:1.02em; }
+.md-view { flex:1; overflow:auto; padding:0 0 48px; background:var(--bg-0); }
+/* The reading surface: Sans body at 68ch, mono headings, amber list markers. */
+.md-body { max-width:68ch; margin:0; padding:18px 20px 48px; color:var(--fg-1); font-family:var(--ui); font-size:14px; line-height:1.7; text-wrap:pretty; }
+.md-body h1, .md-body h2, .md-body h3, .md-body h4, .md-body h5, .md-body h6 { color:var(--fg-0); font-family:var(--mono); font-weight:700; line-height:1.2; margin:1.6em 0 .6em; }
+.md-body h1 { font-size:24px; line-height:1.1; letter-spacing:-.03em; }
+.md-body h2 { font-size:24px; line-height:1.1; letter-spacing:-.03em; }
+.md-body h3 { font-size:17px; padding-bottom:8px; border-bottom:1px solid var(--border); }
+.md-body h4 { font-size:15px; }
.md-body h1:first-child, .md-body h2:first-child, .md-body h3:first-child { margin-top:.2em; }
-.md-body p { margin:.7em 0; }
-.md-body a { color:var(--accent); text-decoration:none; } .md-body a:hover { text-decoration:underline; }
-.md-body ul, .md-body ol { margin:.6em 0; padding-left:1.6em; } .md-body li { margin:.25em 0; }
-.md-body blockquote { margin:.8em 0; padding:.1em 1em; border-left:3px solid var(--border-2); color:var(--fg-2); }
-.md-body hr { border:0; border-top:1px solid var(--border); margin:1.4em 0; }
-.md-body img { max-width:100%; border-radius:6px; }
-.md-body code { font-family:var(--code-font); font-size:.88em; background:var(--bg-1); border:1px solid var(--border); border-radius:4px; padding:.1em .35em; }
-.md-body pre.md-code { background:var(--bg-1); border:1px solid var(--border); border-radius:8px; padding:12px 14px; overflow:auto; margin:.9em 0; }
-.md-body pre.md-code code { font-size:var(--code-size); background:none; border:0; padding:0; white-space:pre; }
+.md-body p { margin:1em 0; }
+.md-body a { color:var(--accent); text-decoration:none; border-bottom:1px solid var(--border); }
+.md-body a:hover { color:var(--fg-0); border-bottom-color:var(--accent); }
+/* An em dash marks a list item. Never a bullet, never an emoji. */
+.md-body ul { margin:1em 0; padding-left:0; list-style:none; }
+.md-body ol { margin:1em 0; padding-left:1.6em; }
+.md-body ul > li { position:relative; padding-left:22px; margin:.5em 0; }
+.md-body ul > li::before { content:"—"; position:absolute; left:0; color:var(--accent); }
+.md-body ol > li { margin:.5em 0; }
+.md-body ol > li::marker { color:var(--accent); }
+.md-body blockquote { margin:1.2em 0; padding:0 0 0 16px; border-left:2px solid var(--accent);
+ color:var(--accent-lite); font-style:italic; font-size:15px; }
+.md-body hr { border:0; border-top:1px solid var(--border); margin:1.6em 0; }
+.md-body img { max-width:100%; border-radius:var(--r-sm); }
+.md-body code { font-family:var(--code-font); font-size:13px; color:var(--accent-lite); background:var(--bg-2);
+ border:1px solid var(--border); border-radius:var(--r-sm); padding:1px 5px; }
+.md-body pre.md-code { background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-sm); padding:14px 16px; overflow:auto; margin:1.2em 0; }
+.md-body pre.md-code code { font-size:13px; line-height:20px; color:var(--fg-1); background:none; border:0; padding:0; white-space:pre; }
.md-body strong { color:var(--fg-0); font-weight:600; }
/* tables scroll on their own so a wide one never widens the whole preview */
-.md-body table.md-table { display:block; width:max-content; max-width:100%; overflow-x:auto; border-collapse:collapse; margin:.9em 0; font-size:.94em; }
-.md-body table.md-table th, .md-body table.md-table td { border:1px solid var(--border); padding:5px 10px; text-align:left; vertical-align:top; }
-.md-body table.md-table th { background:var(--bg-2); color:var(--fg-0); font-weight:600; white-space:nowrap; }
-.md-body table.md-table tbody tr:nth-child(even) { background:var(--bg-1); }
+.md-body table.md-table { display:block; width:max-content; max-width:100%; overflow-x:auto; border-collapse:collapse;
+ margin:1.2em 0; font-size:13px; border:1px solid var(--border); border-radius:var(--r-sm); }
+.md-body table.md-table th, .md-body table.md-table td { border-bottom:1px solid var(--border); padding:10px 14px; text-align:left; vertical-align:top; color:var(--fg-2); }
+.md-body table.md-table th { background:var(--bg-2); color:var(--fg-3); font-family:var(--mono); font-weight:700;
+ font-size:10px; letter-spacing:.14em; text-transform:uppercase; white-space:nowrap; }
+.md-body table.md-table tbody tr:last-child td { border-bottom:0; }
/* gutter change bars (Original / Updated / Split) */
.ln-row.bar-del { box-shadow:inset 2px 0 0 var(--del); }
.ln-row.bar-add { box-shadow:inset 2px 0 0 var(--add); }
-.ln-row.empty { background:repeating-linear-gradient(45deg, rgba(255,255,255,0.015) 0 7px, transparent 7px 14px); }
+.ln-row.empty { background:transparent; }
/* full-screen split */
-.split-overlay { position:fixed; inset:0; z-index:60; background:var(--bg-0); display:flex; flex-direction:column; animation:tin .12s ease-out; }
-.split-head { height:42px; flex:0 0 42px; display:flex; align-items:center; gap:11px; padding:0 16px; background:var(--bg-3); border-bottom:1px solid var(--border); }
-.split-head .sh-name { font-family:var(--mono); font-size:13px; color:var(--fg-0); }
-.split-head .git-stat { font-size:11px; }
-.split-exit { margin-left:auto; display:flex; align-items:center; gap:7px; background:transparent; border:1px solid var(--border-2); border-radius:7px; color:var(--fg-1); font:inherit; font-size:12px; padding:5px 11px; cursor:pointer; }
+.split-overlay { position:fixed; inset:0; z-index:60; background:var(--bg-0); display:flex; flex-direction:column; }
+/* The split covers the whole window, title bar included, so its own header has
+ to reserve the space macOS keeps for the traffic lights — otherwise the file
+ badge and the path sit underneath them. */
+.split-head { height:42px; flex:0 0 42px; display:flex; align-items:center; gap:14px; padding:0 16px 0 82px;
+ background:var(--bg-2); border-bottom:1px solid var(--border); -webkit-app-region:drag; }
+.app.fullscreen .split-head { padding-left:16px; }
+.split-head button { -webkit-app-region:no-drag; }
+.split-head .sh-name { font-family:var(--mono); font-weight:500; font-size:12px; color:var(--fg-0); }
+.split-head .git-stat { width:auto; flex:0 0 auto; font-family:var(--mono); font-weight:700; font-size:10px;
+ letter-spacing:.14em; text-transform:uppercase; color:var(--fg-3); }
+.split-exit { margin-left:auto; display:flex; align-items:center; gap:8px; background:transparent; border:1px solid var(--border-2); border-radius:var(--r-sm); color:var(--fg-2); font-family:var(--ui); font-size:12px; padding:6px 9px; cursor:pointer; }
.split-exit:hover { background:var(--hover); color:var(--fg-0); }
.split-body { flex:1; display:flex; min-height:0; }
.split-pane { flex:1; min-width:0; display:flex; flex-direction:column; }
-.split-pane.left { border-right:1px solid var(--border-2); }
-.split-label { height:27px; flex:0 0 27px; display:flex; align-items:center; gap:9px; padding:0 16px; font-size:10.5px; letter-spacing:.07em; text-transform:uppercase; color:var(--fg-2); background:var(--bg-2); border-bottom:1px solid var(--border); }
-.split-label span { text-transform:none; letter-spacing:0; color:var(--fg-3); font-family:var(--mono); font-size:10.5px; }
+.split-pane.left { border-right:1px solid var(--border); }
+.split-label { height:30px; flex:0 0 30px; display:flex; align-items:center; gap:10px; padding:0 16px;
+ font-family:var(--mono); font-weight:700; font-size:10px; letter-spacing:.14em; text-transform:uppercase;
+ color:var(--fg-3); background:var(--bg-0); border-bottom:1px solid var(--border); }
+.split-pane.right .split-label { color:var(--accent); }
+.split-label span { text-transform:none; letter-spacing:0; color:var(--fg-4); font-family:var(--mono); font-weight:400; font-size:11px; }
+/* Both panes number identically so the eye can travel across. Line box 22px. */
+.split-body .editor { line-height:22px; }
+.split-body .ln-row { min-height:22px; }
+.split-body .ln-gutter { flex:0 0 52px; width:52px; }
/* syntax token colors — applied to both the read-only line views (.ln-code)
* and the editable buffer's highlight layer (.ce-pre) */
@@ -382,7 +484,7 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
.ln-code .token.string,.ln-code .token.attr-value,.ln-code .token.char,.ln-code .token.regex,.ce-pre .token.string,.ce-pre .token.attr-value,.ce-pre .token.char,.ce-pre .token.regex{color:var(--t-str);}
.ln-code .token.number,.ln-code .token.unit,.ce-pre .token.number,.ce-pre .token.unit{color:var(--t-num);}
.ln-code .token.function,.ln-code .token.method,.ce-pre .token.function,.ce-pre .token.method{color:var(--t-fn);}
-.ln-code .token.comment,.ln-code .token.prolog,.ln-code .token.doctype,.ln-code .token.cdata,.ce-pre .token.comment,.ce-pre .token.prolog,.ce-pre .token.doctype,.ce-pre .token.cdata{color:var(--t-com);font-style:italic;}
+.ln-code .token.comment,.ln-code .token.prolog,.ln-code .token.doctype,.ln-code .token.cdata,.ce-pre .token.comment,.ce-pre .token.prolog,.ce-pre .token.doctype,.ce-pre .token.cdata{color:var(--t-com);}
.ln-code .token.tag,.ce-pre .token.tag{color:var(--t-tag);}
.ln-code .token.attr-name,.ce-pre .token.attr-name{color:var(--t-attr);}
.ln-code .token.punctuation,.ce-pre .token.punctuation{color:var(--t-punc);}
@@ -399,12 +501,14 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
/* ============ terminals (right column) ============ */
.term-pane { display:flex; flex-direction:column; min-height:0; background:var(--bg-1); }
-.term-head { height:28px; flex:0 0 28px; display:flex; align-items:center; gap:8px; padding:0 10px; background:var(--bg-3); border-bottom:1px solid var(--border); font-size:11px; color:var(--fg-2); user-select:none; }
-.term-head .dot { width:7px; height:7px; border-radius:50%; background:var(--fg-3); }
-.term-head .dot.live { background:var(--add); box-shadow:0 0 0 0 rgba(92,189,107,.5); animation:pulse 2.2s infinite; }
-@keyframes pulse { 0%{box-shadow:0 0 0 0 rgba(92,189,107,.45);} 70%{box-shadow:0 0 0 5px rgba(92,189,107,0);} 100%{box-shadow:0 0 0 0 rgba(92,189,107,0);} }
-.term-head .lbl { color:var(--fg-1); font-family:var(--mono); }
-.term-head .tag { margin-left:auto; font-size:10px; color:var(--fg-3); font-family:var(--mono); }
+/* 30px panel header, same label as every other column. A live pane marks itself
+ with an amber dot; nothing pulses. */
+.term-head { height:30px; flex:0 0 30px; display:flex; align-items:center; gap:8px; padding:0 12px; background:var(--bg-2); border-bottom:1px solid var(--border);
+ font-family:var(--mono); font-weight:700; font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--fg-3); user-select:none; }
+.term-head .dot { width:6px; height:6px; border-radius:9999px; background:var(--fg-4); }
+.term-head .dot.live { background:var(--accent); }
+.term-head .lbl { color:var(--fg-3); font-family:var(--mono); }
+.term-head .tag { margin-left:auto; font-size:10px; color:var(--fg-4); font-family:var(--mono); letter-spacing:.14em; }
.term-body { flex:1; overflow:auto; padding:8px 12px 12px; font-family:var(--mono); font-size:12.5px; line-height:18px; cursor:text; }
.tline { white-space:pre-wrap; word-break:break-word; }
.tline.dim{color:var(--fg-3);} .tline.acc{color:var(--accent);} .tline.ok{color:var(--add);} .tline.warn{color:var(--mod);} .tline.err{color:var(--del);}
@@ -421,64 +525,89 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
.term-input .ip { color:var(--accent); }
.term-input .ip.ag { color:#c98bdb; }
.term-input input { flex:1; background:transparent; border:0; outline:0; color:var(--fg-0); font-family:var(--mono); font-size:12.5px; caret-color:var(--accent); }
-.cursor-blink { display:inline-block; width:7px; height:14px; background:var(--accent); margin-left:1px; animation:blink 1.1s step-end infinite; vertical-align:-2px; }
-@keyframes blink { 50%{opacity:0;} }
+.cursor-blink { display:inline-block; width:7px; height:14px; background:var(--accent); margin-left:1px; animation:blink 1.1s steps(1,end) infinite; vertical-align:-2px; }
+/* The one animation in the whole editor: stepped on/off, never a fade. */
+@keyframes blink { 0%,49%{opacity:1;} 50%,100%{opacity:0;} }
/* ============ overlays ============ */
-.scrim { position:fixed; inset:0; background:rgba(8,9,11,0.5); z-index:50; display:flex; justify-content:center; align-items:flex-start; padding-top:90px; backdrop-filter:blur(1.5px); }
-.palette { width:620px; max-width:92vw; background:#212429; border:1px solid var(--border-2); border-radius:11px; box-shadow:0 24px 70px rgba(0,0,0,.55); overflow:hidden; }
-.palette .pi, .search-modal .pi { display:flex; align-items:center; gap:10px; padding:12px 15px; border-bottom:1px solid var(--border); }
-.palette .pi input, .search-modal .pi input { flex:1; min-width:0; background:transparent; border:0; outline:0; color:var(--fg-0); font-size:15px; font-family:var(--ui); }
+/* One overlay at a time, on a flat ink scrim. No blur, no entrance animation. */
+.scrim { position:fixed; inset:0; background:rgba(16,23,32,.72); z-index:50; display:flex; justify-content:center; align-items:flex-start; padding:34px; }
+.palette { width:620px; max-width:92vw; background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-lg); box-shadow:var(--shadow-overlay); overflow:hidden; }
+.palette .pi, .search-modal .pi { height:54px; flex:0 0 54px; display:flex; align-items:center; gap:12px; padding:0 18px; border-bottom:1px solid var(--border); }
+.palette .pi svg, .search-modal .pi svg { color:var(--accent); }
+.palette .pi input, .search-modal .pi input { flex:1; min-width:0; background:transparent; border:0; outline:0; color:var(--fg-0);
+ font-family:var(--mono); font-weight:500; font-size:16px; caret-color:var(--accent); }
.palette .pi input::placeholder, .search-modal .pi input::placeholder { color:var(--fg-3); }
.palette .pi svg, .search-modal .pi svg { flex:0 0 auto; }
-.palette .pi .mode-chip, .search-modal .pi .mode-chip { flex:0 0 auto; white-space:nowrap; font-size:10px; color:var(--fg-3); border:1px solid var(--border-2); border-radius:5px; padding:2px 7px; font-family:var(--mono); }
+.palette .pi .mode-chip, .search-modal .pi .mode-chip { flex:0 0 auto; white-space:nowrap; font-size:11px; color:var(--fg-3);
+ border:0; border-left:1px solid var(--border); border-radius:0; padding:0 0 0 12px; font-family:var(--mono); }
/* File-type filter chips. All chips read as "on" while no type is chosen, so the
* default state says "every type" without a separate All control. */
.search-modal .pi .ext-filters { flex:0 1 auto; min-width:0; display:flex; align-items:center; gap:4px; overflow:hidden; }
-.search-modal .ext-chip { flex:0 0 auto; font-family:var(--mono); font-size:10px; line-height:16px; padding:1px 7px; border:1px solid var(--border-2); border-radius:5px; background:transparent; color:var(--fg-3); cursor:pointer; opacity:.5; }
-.search-modal .ext-chip:hover { opacity:1; }
-.search-modal .ext-chip.on { opacity:1; color:var(--accent); border-color:var(--accent-line); background:var(--accent-soft); }
+.search-modal .ext-chip { flex:0 0 auto; font-family:var(--mono); font-weight:600; font-size:10px; line-height:1; padding:4px 6px;
+ border:1px solid var(--border-2); border-radius:var(--r-sm); background:transparent; color:var(--fg-2); cursor:pointer; }
+.search-modal .ext-chip:hover { color:var(--fg-0); }
+.search-modal .ext-chip.on { color:#171C22; border-color:var(--accent); background:var(--accent); }
.palette .results { max-height:380px; overflow:auto; padding:6px; }
-.pres { display:flex; align-items:center; gap:10px; padding:7px 10px; cursor:pointer; }
-.pres .pn { font-size:13px; color:var(--fg-0); }
+.pres { height:38px; display:flex; align-items:center; gap:10px; padding:0 14px; cursor:pointer; }
+.pres .pn { font-family:var(--ui); font-size:13px; font-weight:500; color:var(--fg-2); }
+.pres.sel .pn { color:var(--fg-0); }
.pres .pn b { color:var(--accent); font-weight:700; }
.pres .pp { font-size:11px; color:var(--fg-3); margin-left:auto; font-family:var(--mono); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:55%; direction:rtl; }
-.pempty { padding:26px; text-align:center; color:var(--fg-3); font-size:12.5px; }
+/* Empty and error states: one plain sentence. No illustration, no apology. */
+.pempty { padding:12px 14px; text-align:left; color:var(--fg-3); font-family:var(--ui); font-size:12px; line-height:1.6; }
/* combined search modal (content + files) */
-.search-modal { width:min(1680px, 92vw); max-width:92vw; background:#212429; border:1px solid var(--border-2); border-radius:11px; box-shadow:0 24px 70px rgba(0,0,0,.55); overflow:hidden; display:flex; flex-direction:column; }
-.search-cols { display:flex; min-height:0; }
+.search-modal { width:100%; height:100%; max-width:none; background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-lg); box-shadow:var(--shadow-overlay); overflow:hidden; display:flex; flex-direction:column; }
+.search-cols { display:flex; min-height:0; flex:1; }
/* The column that holds the selection takes 70%; the rest divide what is left,
* so two columns give 70/30 and three give 70/15/15. */
-.search-cols > div { flex:1 1 0; min-width:0; max-height:min(72vh, 720px); overflow:auto; padding-bottom:8px; transition:flex .14s ease; }
+/* Resting widths: this file 230 · project flex · files 250, split by hairlines.
+ The focused column then takes 70% and the other two divide what is left — the
+ side columns stay shrinkable (flex-shrink 1) so they give the room back. */
+.search-cols > div { min-width:0; overflow:auto; padding:12px 0; transition:flex .14s var(--ease); }
+/* Higher specificity than `.search-cols > div` above, or its min-width:0 wins
+ and a side column collapses when the other one takes its 70%. */
+.search-cols > .sc-infile { flex:0 1 230px; min-width:180px; border-right:1px solid var(--border); }
+.search-cols > .sc-left { flex:1 1 auto; }
+.search-cols > .sc-right { flex:0 1 250px; min-width:180px; border-left:1px solid var(--border); }
.search-cols > div.active { flex:0 0 70%; }
-.sc-infile { border-right:1px solid var(--border); background:rgba(0,0,0,0.18); }
-.sc-left { border-right:1px solid var(--border); }
-.sc-right { background:rgba(0,0,0,0.12); }
-.sc-head { position:sticky; top:0; z-index:1; background:#212429; padding:9px 14px 6px; font-size:10px; letter-spacing:.07em; text-transform:uppercase; color:var(--fg-3); display:flex; align-items:center; gap:7px; }
-.sc-right .sc-head { background:#1e2024; }
-.sc-infile .sc-head { background:#1c1e22; text-transform:none; letter-spacing:0; }
-.sc-infile .sc-head .scf-name { flex:1 1 auto; min-width:0; font-size:11.5px; color:var(--fg-1); font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
-.sc-infile .sc-head svg { flex:0 0 auto; }
-.sc-head .sc-ct { color:var(--fg-2); background:var(--bg-3); border:1px solid var(--border); border-radius:9px; padding:0 7px; line-height:15px; font-size:10px; }
+.search-cols > .sc-infile.active, .search-cols > .sc-right.active { flex:0 0 70%; }
+.sc-head { position:sticky; top:0; z-index:1; background:var(--bg-2); padding:0 16px 10px;
+ font-family:var(--mono); font-weight:700; font-size:10px; line-height:1; letter-spacing:.14em; text-transform:uppercase;
+ color:var(--fg-3); display:flex; align-items:center; gap:10px; }
+.sc-infile .sc-head, .sc-right .sc-head { padding:0 14px 10px; }
+.sc-infile .sc-head .scf-name { flex:1 1 auto; min-width:0; font-size:10px; color:var(--fg-3); font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+.sc-infile .sc-head svg { display:none; }
+/* The focused column's count becomes an amber chip with ink text. */
+.sc-head .sc-ct { color:var(--fg-3); background:transparent; border:0; border-radius:var(--r-sm); padding:0; line-height:1; font-size:10px; font-weight:600; letter-spacing:0; }
.srf-name { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
-.pempty.sm { padding:18px 14px; text-align:left; font-size:11.5px; }
-.fres { display:flex; align-items:center; gap:9px; padding:6px 12px; cursor:pointer; }
-.fres-txt { min-width:0; display:flex; flex-direction:column; line-height:1.25; }
-.fres-txt .fn { font-size:12.5px; color:var(--fg-0); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+.pempty.sm { padding:0 14px; text-align:left; font-size:12px; }
+.fres { min-height:26px; display:flex; align-items:center; gap:8px; padding:4px 14px; cursor:pointer; }
+.fres-txt { min-width:0; display:flex; flex-direction:column; line-height:1.35; }
+.fres-txt .fn { font-family:var(--ui); font-size:12px; color:var(--fg-2); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+.fres.sel .fres-txt .fn { color:var(--fg-0); font-weight:500; }
.fres-txt .fn b { color:var(--accent); font-weight:700; }
-.fres-txt .fd { font-size:10.5px; color:var(--fg-3); font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+.fres-txt .fd { font-size:11px; color:var(--fg-3); font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+
+/* Shared overlay footer: key hints left, the esc chip right. */
+.ov-foot { height:38px; flex:0 0 38px; display:flex; align-items:center; gap:14px; padding:0 18px;
+ border-top:1px solid var(--border); font-family:var(--mono); font-size:11px; color:var(--fg-3); }
+.ov-foot b { color:var(--accent); font-weight:400; }
+.ov-foot-spacer { flex:1; }
+.esc-chip { font-family:var(--mono); font-size:11px; color:var(--fg-3);
+ border:1px solid var(--border-2); border-radius:var(--r-sm); padding:4px 6px; }
/* recent-files navigator — single-column, keyboard-driven, search-modal styling */
-.history-modal { width:560px; max-width:92vw; background:#212429; border:1px solid var(--border-2); border-radius:11px; box-shadow:0 24px 70px rgba(0,0,0,.55); overflow:hidden; display:flex; flex-direction:column; }
-.history-modal .pi { display:flex; align-items:center; gap:10px; padding:12px 15px; border-bottom:1px solid var(--border); }
-.history-modal .pi svg { flex:0 0 auto; }
-.history-modal .hist-title { flex:1; min-width:0; color:var(--fg-1); font-size:14px; }
-.history-modal .mode-chip { flex:0 0 auto; white-space:nowrap; font-size:10px; color:var(--fg-3); border:1px solid var(--border-2); border-radius:5px; padding:2px 7px; font-family:var(--mono); display:flex; align-items:center; gap:4px; }
+.history-modal { width:560px; max-width:92vw; background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-lg); box-shadow:var(--shadow-overlay); overflow:hidden; display:flex; flex-direction:column; }
+.history-modal .pi { height:50px; flex:0 0 50px; display:flex; align-items:center; gap:12px; padding:0 18px; border-bottom:1px solid var(--border); }
+.history-modal .pi svg { flex:0 0 auto; color:var(--accent); }
+.history-modal .hist-title { flex:1; min-width:0; color:var(--fg-0); font-family:var(--mono); font-weight:700; font-size:14px; line-height:1; }
+.history-modal .mode-chip { flex:0 0 auto; white-space:nowrap; font-size:12px; color:var(--fg-3); border:1px solid var(--border-2); border-radius:var(--r-sm); padding:4px 6px; font-family:var(--mono); display:flex; align-items:center; gap:4px; }
/* stable gutter: without it the scrollbar eats into the rows, so the change dot
sits at a different distance from the edge than the header above it. */
-.hist-list { max-height:460px; overflow-y:auto; scrollbar-gutter:stable; padding:5px 0; }
-.hist-row { display:flex; align-items:center; gap:9px; padding:6px 13px; cursor:pointer; position:relative; }
+.hist-list { max-height:460px; overflow-y:auto; scrollbar-gutter:stable; padding:6px 0; }
+.hist-row { height:38px; display:flex; align-items:center; gap:10px; padding:0 14px; cursor:pointer; position:relative; }
/* ⌘↑/⌘↓ moves the selection while the pointer stays put, so hover has to give
way until the mouse moves again — otherwise two rows read as focused. */
.hist-list.kbd-nav .hist-row:hover:not(.sel) { background:transparent; }
@@ -486,33 +615,39 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
.search-cols.kbd-nav .sr-line:hover:not(.sel), .search-cols.kbd-nav .fres:hover:not(.sel) { background:transparent; }
.search-cols.kbd-nav .sr-line:hover:not(.sel)::before, .search-cols.kbd-nav .fres:hover:not(.sel)::before { content:none; }
.hist-txt { min-width:0; display:flex; flex-direction:column; line-height:1.25; }
-.hist-txt .fn { font-size:12.5px; color:var(--fg-0); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
-.hist-txt .fd { font-size:10.5px; color:var(--fg-3); font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+.hist-txt .fn { font-family:var(--ui); font-size:13px; font-weight:500; color:var(--fg-2); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+.hist-row.sel .hist-txt .fn { color:var(--fg-0); }
+.hist-txt .fd { font-size:11px; color:var(--fg-3); font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* content search */
-.search-results { max-height:min(68vh, 680px); overflow:auto; padding:4px 0 8px; }
-.sr-file { padding:7px 14px 3px; font-size:11.5px; color:var(--fg-2); display:flex; align-items:center; gap:8px; cursor:pointer; }
+.search-results { flex:1; overflow:auto; padding:0 0 8px; }
+/* Result group header: type badge, path, hit count right. */
+.sr-file { padding:14px 16px 6px; font-family:var(--mono); font-size:12px; line-height:1.6; color:var(--fg-2); display:flex; align-items:center; gap:8px; cursor:pointer; }
.sr-file:hover { color:var(--fg-0); }
-.sr-file .cnt { margin-left:auto; color:var(--fg-3); font-family:var(--mono); font-size:10.5px; }
-.sr-line { display:flex; gap:12px; padding:2px 14px 2px 38px; font-family:var(--mono); font-size:12px; cursor:pointer; color:var(--fg-1); }
-.sr-line .no { color:var(--fg-3); min-width:34px; text-align:right; }
-.sr-line .tx { white-space:pre; overflow:hidden; text-overflow:ellipsis; }
-.sr-line mark { background:rgba(216,168,92,.28); color:var(--fg-0); border-radius:2px; }
+.sr-file .cnt { margin-left:auto; color:var(--fg-3); font-family:var(--mono); font-size:12px; }
+/* Hit line: 64px number column, 24px line box. */
+.sr-line { display:grid; grid-template-columns:64px 1fr; align-items:center; padding:0; font-family:var(--mono); font-size:12px; line-height:24px; cursor:pointer; color:var(--fg-2); }
+.sr-line .no { color:var(--fg-4); text-align:right; padding-right:14px; }
+.sr-line.sel .no { color:var(--accent); }
+.sr-line.sel { color:var(--fg-1); }
+.sr-line .tx { white-space:pre; overflow:hidden; text-overflow:ellipsis; padding-right:14px; }
+.sr-line mark { background:transparent; color:var(--accent-lite); border-radius:var(--r-sm); }
+.sr-line.sel mark { background:var(--accent); color:#171C22; }
/* pass-on-to-agent inline popup */
-.pass-pop { position:fixed; z-index:85; width:344px; max-width:92vw; background:#23272d; border:1px solid var(--border-2); border-radius:10px; box-shadow:0 18px 48px rgba(0,0,0,.55); padding:11px; animation:popin .12s ease-out; }
-@keyframes popin { from { transform:translateY(6px); } }
-.pass-head { display:flex; align-items:center; gap:8px; font-size:12px; color:var(--fg-1); margin-bottom:9px; }
-.pass-head svg { color:#c98bdb; }
-.pass-head .pass-esc { margin-left:auto; font-family:var(--mono); font-size:10px; color:var(--fg-3); border:1px solid var(--border-2); border-radius:4px; padding:1px 6px; }
-.pass-input { width:100%; box-sizing:border-box; background:var(--bg-0); border:1px solid var(--border-2); border-radius:7px; color:var(--fg-0); font-family:var(--ui); font-size:13px; padding:8px 10px; outline:none; }
-.pass-input:focus { border-color:var(--accent-line); }
+.pass-pop { position:fixed; z-index:85; width:460px; max-width:92vw; background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-md); box-shadow:var(--shadow-menu); padding:14px; display:flex; flex-direction:column; gap:12px; }
+.pass-head { display:flex; align-items:center; gap:10px; font-family:var(--mono); font-weight:700; font-size:13px; color:var(--fg-0); }
+.pass-head svg { color:var(--accent); }
+.pass-head .pass-esc { margin-left:auto; font-family:var(--mono); font-size:12px; color:var(--fg-3); border:1px solid var(--border-2); border-radius:var(--r-sm); padding:4px 6px; }
+.pass-input { width:100%; box-sizing:border-box; height:38px; background:var(--bg-0); border:2px solid var(--accent); border-radius:var(--r-sm);
+ box-shadow:0 0 0 2px var(--accent-ring); color:var(--fg-1); font-family:var(--mono); font-size:13px; padding:0 10px; outline:none; caret-color:var(--accent); }
.pass-input::placeholder { color:var(--fg-3); }
-.pass-preview { margin-top:9px; display:flex; align-items:center; gap:8px; min-width:0; }
-.pass-preview .pp-lbl { font-size:10px; text-transform:uppercase; letter-spacing:.06em; color:var(--fg-3); flex:0 0 auto; }
-.pass-preview code { font-family:var(--mono); font-size:11.5px; color:var(--accent); background:var(--accent-soft); border-radius:5px; padding:3px 7px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+.pass-preview { margin:0; display:flex; align-items:center; gap:10px; min-width:0; }
+.pass-preview .pp-lbl { font-family:var(--mono); font-weight:700; font-size:10px; text-transform:uppercase; letter-spacing:.14em; color:var(--fg-3); flex:0 0 auto; }
+.pass-preview code { font-family:var(--mono); font-size:12px; color:#171C22; background:var(--accent); border-radius:var(--r-sm); padding:4px 8px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.pass-preview code.multiline { white-space:pre-wrap; text-overflow:clip; max-height:132px; overflow:auto; word-break:break-word; }
-.pass-foot { margin-top:9px; font-size:10.5px; color:var(--fg-3); }
+.pass-foot { margin:0; font-family:var(--mono); font-size:11px; color:var(--fg-3); }
+.pass-foot b { color:var(--accent); font-weight:400; }
/* terminal multi-line input */
.term-input { align-items:flex-start; }
@@ -527,12 +662,12 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
/* ⌘-click on a PHP class: declarations on top, references under them. Sized to
read a line of code, capped so it never covers the whole viewer. */
.sym-popup { width:min(700px, 82vw); max-height:min(72vh, 640px); display:flex; flex-direction:column;
- background:#23272d; border:1px solid var(--border-2); border-left:3px solid var(--accent); border-radius:4px; box-shadow:0 16px 44px rgba(0,0,0,.5); overflow:hidden; }
-.sym-head { display:flex; align-items:center; gap:9px; padding:9px 13px; border-bottom:1px solid var(--border); background:var(--bg-3); }
-.sym-name { font-family:var(--mono); font-size:13px; color:var(--fg-0); font-weight:600; }
+ background:var(--bg-2); border:1px solid var(--border); border-left:2px solid var(--accent); border-radius:var(--r-md); box-shadow:var(--shadow-overlay); overflow:hidden; }
+.sym-head { height:50px; flex:0 0 50px; display:flex; align-items:center; gap:10px; padding:0 18px; border-bottom:1px solid var(--border); background:var(--bg-2); }
+.sym-name { font-family:var(--mono); font-size:13px; color:var(--fg-0); font-weight:700; }
.sym-count { margin-left:auto; font-family:var(--mono); font-size:10.5px; color:var(--fg-3); }
.sym-body { overflow:auto; padding-bottom:6px; }
-.sym-sec { padding:8px 13px 4px; font-size:10px; letter-spacing:.07em; text-transform:uppercase; color:var(--fg-3); }
+.sym-sec { padding:14px 16px 6px; font-family:var(--mono); font-weight:700; font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--fg-3); }
.sym-row { cursor:pointer; }
.sym-row.def { display:flex; align-items:center; gap:8px; padding:4px 13px; font-size:12px; color:var(--fg-1); }
.sym-row.def .sym-path { font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
@@ -546,7 +681,7 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
.sym-rel-key { font-size:10px; letter-spacing:.06em; text-transform:uppercase; color:var(--fg-3); min-width:66px; }
.sym-chip { font-family:var(--mono); font-size:11px; line-height:17px; padding:0 7px; border:1px solid var(--border); border-radius:3px; background:transparent; color:var(--fg-3); }
.sym-chip.known { color:var(--fg-1); border-color:var(--border-2); cursor:pointer; }
-.sym-chip.known:hover { color:var(--accent); border-color:var(--accent-line); background:var(--accent-soft); }
+.sym-chip.known:hover { color:var(--accent); border-color:var(--accent-dim); background:var(--accent-soft); }
/* A class name this project declares, underlined only while ⌘ is held — the
affordance shows exactly when the click would do something.
@@ -560,39 +695,66 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
}
.code-edit.sym-live .token.sym:hover, .editor.sym-live .token.sym:hover { filter:brightness(1.25); }
-.ctx-menu { position:fixed; z-index:80; background:#23272d; border:1px solid var(--border-2); border-radius:9px; padding:5px; min-width:248px; box-shadow:0 16px 44px rgba(0,0,0,.5); }
-.ctx-item { display:flex; align-items:center; gap:10px; padding:7px 10px; border-radius:6px; cursor:pointer; font-size:12.5px; color:var(--fg-1); }
-.ctx-item:hover, .ctx-item.hi { background:var(--accent-soft); color:var(--fg-0); }
-.ctx-item .kc { margin-left:auto; font-family:var(--mono); font-size:10.5px; color:var(--fg-3); }
-.ctx-item.primary { color:var(--fg-0); }
-.ctx-item.primary .ic { color:var(--accent); }
+.ctx-menu { position:fixed; z-index:80; background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-md); padding:8px 0; width:320px; box-shadow:var(--shadow-menu); }
+.ctx-item { height:30px; display:flex; align-items:center; gap:10px; padding:0 14px; cursor:pointer;
+ font-family:var(--ui); font-size:13px; color:var(--fg-2); position:relative; border-left:2px solid transparent; }
+.ctx-item:hover, .ctx-item.hi { background:var(--sel); color:var(--fg-0); font-weight:500; border-left-color:var(--accent); }
+.ctx-item:hover .ic, .ctx-item.hi .ic { color:var(--accent); }
+.ctx-item .kc { margin-left:auto; font-family:var(--mono); font-size:11px; color:var(--fg-3); }
+.ctx-item.danger, .ctx-item.danger .ic { color:var(--del); }
+.ctx-item.danger:hover, .ctx-item.danger.hi { color:var(--del); }
+.ctx-item.danger:hover .ic, .ctx-item.danger.hi .ic { color:var(--del); }
+.ctx-item.primary .ic { color:var(--fg-3); }
.ctx-item .ic { width:15px; display:flex; justify-content:center; color:var(--fg-3); }
-.ctx-sep { height:1px; background:var(--border); margin:5px 6px; }
-.ctx-note { padding:4px 11px 7px; font-size:10.5px; color:var(--fg-3); font-family:var(--mono); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
+.ctx-sep { height:1px; background:var(--border); margin:6px 0; }
+.ctx-note { padding:0 14px 8px; margin-bottom:8px; border-bottom:1px solid var(--border); font-size:11px; color:var(--fg-3); font-family:var(--mono); line-height:1.5; overflow:hidden; text-overflow:ellipsis; }
/* toast */
-.toast-wrap { position:fixed; bottom:34px; left:50%; transform:translateX(-50%); z-index:90; display:flex; flex-direction:column; gap:8px; align-items:center; }
-.toast { background:#23272d; border:1px solid var(--border-2); border-left:3px solid var(--accent); border-radius:9px; padding:9px 14px; box-shadow:0 12px 34px rgba(0,0,0,.45); display:flex; align-items:center; gap:11px; animation:tin .18s ease-out; }
-@keyframes tin { from{opacity:0; transform:translateY(8px);} }
-.toast .tt { font-size:12.5px; color:var(--fg-0); }
-.toast .tref { font-family:var(--mono); font-size:11.5px; color:var(--accent); background:var(--accent-soft); border-radius:5px; padding:2px 8px; }
+.toast-wrap { position:fixed; bottom:44px; left:50%; transform:translateX(-50%); z-index:90; display:flex; flex-direction:column; gap:8px; align-items:center; }
+.toast { background:var(--bg-2); border:1px solid var(--border); border-left:2px solid var(--accent); border-radius:var(--r-md); padding:10px 14px; box-shadow:var(--shadow-menu); display:flex; align-items:center; gap:12px; }
+@keyframes tin { from{opacity:0;} }
+.toast .tt { font-family:var(--ui); font-size:13px; color:var(--fg-0); }
+.toast .tref { font-family:var(--mono); font-size:12px; color:#171C22; background:var(--accent); border-radius:var(--r-sm); padding:3px 7px; }
/* ============ status bar ============ */
+/* 28px, display only: nothing here is clickable and nothing navigates. */
+.statusbar {
+ height:28px; flex:0 0 28px; display:flex; align-items:center; gap:16px; padding:0 14px;
+ background:var(--bg-2); border-top:1px solid var(--border);
+ font-family:var(--mono); font-size:11px; line-height:1; color:var(--fg-3); user-select:none;
+}
+.statusbar .sb-branch { color:var(--accent); }
+.statusbar .sb-add { color:var(--add); }
+.statusbar .sb-del { color:var(--del); }
+.statusbar .sb-spacer { flex:1; }
+.statusbar .sb-path { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:52%; }
+.statusbar .sb-lang { color:var(--fg-2); }
+
+/* Tooltip: one surface, one border, no arrow and no shadow. The current state
+ is named inside the sentence in amber. */
+.tip-host { display:inline-flex; }
+.tip {
+ position:fixed; z-index:120; max-width:300px; pointer-events:none;
+ background:var(--raised); border:1px solid var(--fg-4); border-radius:var(--r-sm);
+ padding:8px 10px; font-family:var(--ui); font-size:12px; line-height:1.5; color:var(--fg-1);
+}
+.tip b { color:var(--accent); font-weight:400; }
+
/* editable buffer — transparent textarea over a highlighted
, synced gutter */
-.code-edit { flex:1; min-height:0; display:flex; overflow:hidden; }
-.ce-gutterwrap { flex:0 0 54px; overflow:hidden; position:relative; }
+.code-edit { flex:1; min-height:0; display:flex; overflow:hidden; background:var(--bg-0); }
+.ce-gutterwrap { flex:0 0 56px; overflow:hidden; position:relative; background:var(--bg-0); }
.ce-gutter {
- padding:6px 14px 0 0; will-change:transform;
+ padding:10px 14px 0 0; will-change:transform;
white-space:pre; text-align:right; line-height:20px;
- color:var(--fg-3); font-family:var(--code-font); font-size:12px; user-select:none;
+ color:var(--fg-4); font-family:var(--code-font); font-size:13px; user-select:none;
}
.ce-scroll { flex:1; min-width:0; overflow:auto; position:relative; }
/* min-height keeps the inset:0 textarea filling the pane on short/empty files,
so a click anywhere in the blank area below the last line still lands. */
.ce-inner { position:relative; width:max-content; min-width:100%; min-height:100%; }
.ce-pre, .ce-ta {
- margin:0; padding:6px 16px 40px 6px; border:0;
+ margin:0; padding:10px 16px 40px 0; border:0;
font-family:var(--code-font); font-size:var(--code-size); line-height:20px;
white-space:pre; tab-size:4; -moz-tab-size:4; letter-spacing:0;
}
@@ -601,7 +763,7 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
position:absolute; inset:0; resize:none; outline:none; overflow:hidden;
background:transparent; color:transparent; caret-color:var(--accent);
}
-.ce-ta::selection { background:rgba(241,159,63,0.30); }
+.ce-ta::selection { background:var(--accent-ring); }
/* jump target — the line a search result opened, orange for a second.
Behind both layers, so the code itself keeps its own colours. */
.ce-flash { position:absolute; left:0; right:0; min-width:100%; z-index:0; pointer-events:none; background:var(--accent-soft); box-shadow:inset 2px 0 0 var(--accent); animation:ce-flash-fade 1s ease forwards; }
@@ -619,14 +781,14 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
.ce-line { position:relative; min-height:20px; }
.ce-line::before {
counter-increment:ce-ln; content:counter(ce-ln);
- position:absolute; left:-54px; top:0; width:34px; text-align:right;
- font-size:12px; line-height:20px; color:var(--fg-3); user-select:none;
+ position:absolute; left:-56px; top:0; width:42px; text-align:right;
+ font-size:13px; line-height:20px; color:var(--fg-4); user-select:none;
}
/* xterm.js host (real terminals) */
/* The pane carries the colour, taken from the terminal palette in config.json,
so the padding around the canvas can never sit on a different ground. */
-.term-xterm { flex:1; min-height:0; overflow:hidden; padding:6px 4px 6px 8px; background:transparent; }
+.term-xterm { flex:1; min-height:0; overflow:hidden; padding:10px 6px 10px 12px; background:var(--bg-0); }
.term-xterm .xterm { height:100%; }
.term-xterm .xterm-viewport { background:transparent !important; }
.term-xterm .xterm-viewport::-webkit-scrollbar { width:9px; }
@@ -638,8 +800,8 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
decorative dots are hidden and the bar is made draggable. Interactive controls
opt back out of the drag region. */
.titlebar { -webkit-app-region: drag; padding-left: 82px; }
-/* Fullscreen: no traffic lights, so the project name moves back to the edge. */
-.titlebar.fullscreen { padding-left: 12px; }
+/* Fullscreen: no traffic lights, so the wordmark moves back to the edge. */
+.titlebar.fullscreen { padding-left: 14px; }
.titlebar .traffic { display: none; }
.titlebar button,
.titlebar input,
@@ -651,71 +813,92 @@ kbd { flex:0 0 auto; font-family:var(--mono); font-size:11.5px; color:var(--fg-3
}
/* ============ project launcher (no project open) ============ */
-.launcher { position:fixed; inset:0; background:var(--bg-0); display:flex; align-items:center; justify-content:center; }
-.launcher-drag { position:absolute; top:0; left:0; right:0; height:40px; -webkit-app-region:drag; }
-.launcher-card { width:560px; max-width:92vw; max-height:80vh; display:flex; flex-direction:column; background:var(--bg-2); border:1px solid var(--border-2); border-radius:14px; box-shadow:0 28px 80px rgba(0,0,0,.55); overflow:hidden; -webkit-app-region:no-drag; }
-.lp-head { display:flex; align-items:center; gap:12px; padding:18px 20px; border-bottom:1px solid var(--border); }
-.lp-title { display:flex; flex-direction:column; line-height:1.3; }
-.lp-title b { font-size:16px; color:var(--fg-0); font-weight:600; }
-.lp-title span { font-size:12px; color:var(--fg-3); }
-.lp-list { overflow:auto; padding:6px; flex:1; min-height:0; }
-.lp-sec { padding:10px 10px 4px; font-size:10px; letter-spacing:.07em; text-transform:uppercase; color:var(--fg-3); }
-.lp-row { display:flex; align-items:center; gap:11px; padding:9px 10px; border-radius:8px; cursor:pointer; }
+/* No title bar here — only the traffic lights, and the panel sits at the top. */
+.launcher { position:fixed; inset:0; background:var(--bg-0); display:flex; align-items:flex-start; justify-content:center; padding:40px 20px 20px; }
+.launcher-drag { position:absolute; top:0; left:0; right:0; height:34px; -webkit-app-region:drag; }
+.launcher-card { width:520px; max-width:92vw; max-height:calc(100vh - 80px); display:flex; flex-direction:column; background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-lg); box-shadow:var(--shadow-overlay); overflow:hidden; -webkit-app-region:no-drag; }
+.lp-head { display:flex; align-items:center; gap:14px; padding:20px; border-bottom:1px solid var(--border); }
+.lp-head > svg, .lp-head .lp-mark { color:var(--accent); flex:0 0 auto; }
+.lp-title { display:flex; flex-direction:column; gap:5px; }
+.lp-title b { font-family:var(--mono); font-size:14px; font-weight:700; letter-spacing:.02em; color:var(--fg-0); }
+.lp-title b i { font-style:normal; color:var(--accent); animation:blink 1.1s steps(1,end) infinite; }
+.lp-title span { font-family:var(--ui); font-size:12px; color:var(--fg-3); }
+.lp-list { overflow:auto; padding:0; flex:1; min-height:0; }
+.lp-sec { padding:14px 20px 6px; font-family:var(--mono); font-weight:700; font-size:10px; line-height:1; letter-spacing:.14em; text-transform:uppercase; color:var(--fg-3); }
+.lp-row { height:38px; display:flex; align-items:center; gap:12px; padding:0 20px; cursor:pointer; border-left:2px solid transparent; }
+.lp-row.lp-new { height:46px; border-bottom:1px solid var(--border); }
.lp-row:hover { background:var(--hover); }
-.lp-row.sel { background:var(--accent-soft); box-shadow:inset 2px 0 0 var(--accent); }
-.lp-ic { flex:0 0 auto; width:22px; height:22px; display:flex; align-items:center; justify-content:center; color:var(--fg-2); }
+.lp-row.sel { background:var(--sel); border-left-color:var(--accent); }
+.lp-ic { flex:0 0 auto; width:16px; height:16px; display:flex; align-items:center; justify-content:center; color:var(--fg-3); }
+.lp-row.sel .lp-ic { color:var(--accent); }
.lp-new .lp-ic { color:var(--accent); }
-.lp-txt { min-width:0; display:flex; flex-direction:column; line-height:1.3; flex:1; }
-.lp-name { font-size:13px; color:var(--fg-0); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
-.lp-path { font-size:11px; color:var(--fg-3); font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; direction:rtl; text-align:left; }
-.lp-foot { padding:10px 20px; border-top:1px solid var(--border); font-size:10.5px; color:var(--fg-3); }
+.lp-txt { min-width:0; display:flex; align-items:baseline; gap:10px; flex:1; }
+.lp-name { font-family:var(--ui); font-size:13px; font-weight:500; color:var(--fg-2); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+.lp-row.sel .lp-name, .lp-new .lp-name { color:var(--fg-0); }
+.lp-path { font-size:11px; color:var(--fg-3); font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
+.lp-row.sel .lp-path { color:var(--fg-2); }
+.lp-foot { height:36px; display:flex; align-items:center; padding:0 20px; border-top:1px solid var(--border); font-family:var(--mono); font-size:11px; color:var(--fg-3); }
+.lp-foot b { color:var(--accent); font-weight:400; }
/* ============ keyboard-shortcuts (help) modal ============ */
/* Project note (.notes.txt). Capped at 1000px so the text stays readable on a
wide screen; the height fills nearly the whole window, with a floor for small
ones, because a note is usually long. */
-.notes-modal { width:1000px; max-width:92vw; height:calc(100vh - 116px); min-height:260px;
- background:#212429; border:1px solid var(--border-2); border-radius:11px;
- box-shadow:0 24px 70px rgba(0,0,0,.55); overflow:hidden; display:flex; flex-direction:column; }
-.notes-modal .pi { display:flex; align-items:center; gap:10px; padding:12px 15px; border-bottom:1px solid var(--border); }
-.notes-modal .pi svg { flex:0 0 auto; }
-.notes-modal .hist-title { color:var(--fg-1); font-size:14px; }
-.notes-modal .notes-file { flex:1; min-width:0; font-family:var(--mono); font-size:10.5px; color:var(--fg-3); }
-.notes-modal .notes-hint { flex:0 0 auto; display:flex; align-items:center; gap:6px; font-size:11.5px; color:var(--fg-2); }
+.notes-modal { width:1000px; max-width:100%; height:100%;
+ background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-lg);
+ box-shadow:var(--shadow-overlay); overflow:hidden; display:flex; flex-direction:column; }
+.notes-modal .pi { height:50px; flex:0 0 50px; display:flex; align-items:center; gap:12px; padding:0 18px; border-bottom:1px solid var(--border); }
+.notes-modal .pi svg { flex:0 0 auto; color:var(--accent); }
+.notes-modal .hist-title { color:var(--fg-0); font-family:var(--mono); font-weight:700; font-size:14px; line-height:1; }
+.notes-modal .notes-file { flex:1; min-width:0; font-family:var(--mono); font-size:12px; color:var(--fg-3); }
+/* Primary button: amber fill, ink text, never white. */
+.notes-modal .notes-hint { flex:0 0 auto; display:flex; align-items:center; gap:8px;
+ background:var(--accent); color:#171C22; font-family:var(--ui); font-weight:500; font-size:12px;
+ border-radius:var(--r-sm); padding:6px 10px; }
+.notes-modal .notes-hint kbd { color:#171C22; border-color:rgba(23,28,34,.25); font-size:11px; padding:0; }
.notes-input { flex:1; min-height:0; width:100%; resize:none; background:transparent; border:0; outline:0;
- padding:14px 16px; color:var(--fg-1); font-family:var(--code-font); font-size:var(--code-size); line-height:20px; }
+ padding:18px 20px; color:var(--fg-1); font-family:var(--code-font); font-size:14px; line-height:1.7;
+ max-width:calc(68ch + 40px); caret-color:var(--accent); }
.notes-input::placeholder { color:var(--fg-3); }
+.notes-foot { height:34px; flex:0 0 34px; display:flex; align-items:center; padding:0 20px;
+ border-top:1px solid var(--border); font-family:var(--mono); font-size:11px; color:var(--fg-3); }
-.help-modal { width:520px; max-width:92vw; background:#212429; border:1px solid var(--border-2); border-radius:11px; box-shadow:0 24px 70px rgba(0,0,0,.55); overflow:hidden; display:flex; flex-direction:column; }
-.help-modal .pi { display:flex; align-items:center; gap:10px; padding:12px 15px; border-bottom:1px solid var(--border); }
-.help-modal .pi svg { flex:0 0 auto; }
-.help-modal .hist-title { flex:1; min-width:0; color:var(--fg-1); font-size:14px; }
-.help-list { max-height:62vh; overflow:auto; padding:8px 6px; }
-.help-row { display:flex; align-items:center; gap:14px; padding:6px 12px; border-radius:7px; }
-.help-row:hover { background:var(--hover); }
-.help-keys { flex:0 0 96px; display:flex; gap:4px; justify-content:flex-end; }
-.help-keys kbd { min-width:20px; text-align:center; }
-.help-label { font-size:12.5px; color:var(--fg-2); }
+.help-modal { width:600px; max-width:92vw; background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-lg); box-shadow:var(--shadow-overlay); overflow:hidden; display:flex; flex-direction:column; }
+.help-modal .pi { height:50px; flex:0 0 50px; display:flex; align-items:center; gap:12px; padding:0 18px; border-bottom:1px solid var(--border); }
+.help-modal .pi svg { flex:0 0 auto; color:var(--accent); }
+.help-modal .hist-title { flex:1; min-width:0; color:var(--fg-0); font-family:var(--mono); font-weight:700; font-size:14px; line-height:1; }
+.help-list { max-height:70vh; overflow:auto; padding:18px 20px 22px; }
+.help-sec { font-family:var(--mono); font-weight:700; font-size:10px; line-height:1; letter-spacing:.14em; text-transform:uppercase;
+ color:var(--fg-3); padding:16px 0 8px; }
+.help-sec:first-child { padding-top:0; }
+.help-row { display:grid; grid-template-columns:92px 1fr; align-items:center; gap:14px; padding:6px 0; }
+.help-keys { display:flex; gap:4px; justify-content:flex-start; }
+.help-keys kbd { min-width:22px; text-align:center; }
+.help-label { font-family:var(--ui); font-size:13px; color:var(--fg-1); }
/* title-bar icon-only button (help ?) */
-.tb-icon { padding:5px 7px; }
+/* Icon-only toolbar control: a 26px square with a hairline border. */
+.tb-icon { width:26px; height:26px; margin-left:6px; padding:0; justify-content:center;
+ border:1px solid var(--border-2); font-family:var(--mono); font-weight:600; font-size:12px; color:var(--fg-3); }
/* confirm dialog (delete, etc.) */
-.confirm-modal { width:420px; max-width:92vw; background:#23272d; border:1px solid var(--border-2); border-radius:12px; box-shadow:0 24px 70px rgba(0,0,0,.55); padding:18px 20px; }
-.cf-title { font-size:14px; font-weight:600; color:var(--fg-0); }
-.cf-body { margin-top:8px; font-size:12.5px; line-height:1.45; color:var(--fg-2); font-family:var(--mono); word-break:break-all; }
-.cf-actions { margin-top:18px; display:flex; justify-content:flex-end; gap:9px; }
-.cf-btn { display:flex; align-items:center; gap:7px; font-size:12.5px; color:var(--fg-1); background:var(--bg-2); border:1px solid var(--border-2); border-radius:7px; padding:7px 13px; cursor:pointer; }
+.confirm-modal { width:460px; max-width:92vw; background:var(--bg-2); border:1px solid var(--border); border-radius:var(--r-lg); box-shadow:var(--shadow-overlay); padding:20px; }
+.cf-title { font-family:var(--mono); font-size:14px; font-weight:700; line-height:1; color:var(--fg-0); }
+.cf-body { margin-top:12px; font-size:12px; line-height:1.6; color:var(--fg-3); font-family:var(--mono); word-break:break-all; }
+.cf-actions { margin-top:20px; display:flex; justify-content:flex-end; gap:8px; }
+.cf-btn { display:flex; align-items:center; gap:8px; font-family:var(--ui); font-size:12px; color:var(--fg-2); background:transparent; border:1px solid var(--border-2); border-radius:var(--r-sm); padding:6px 10px; cursor:pointer; }
.cf-btn:hover { background:var(--hover); color:var(--fg-0); }
-.cf-yes { background:var(--accent); color:#201608; border-color:transparent; font-weight:600; }
-.cf-yes:hover { background:#f6b35f; color:#201608; }
-.cf-yes kbd { color:#201608; border-color:rgba(0,0,0,.25); }
-.cf-yes.danger { background:var(--del); color:#fff; }
-.cf-yes.danger:hover { background:#e8797a; }
-.cf-yes.danger kbd { color:#fff; border-color:rgba(255,255,255,.4); }
+.cf-yes { background:var(--accent); color:#171C22; border-color:transparent; font-weight:500; }
+.cf-yes:hover { background:var(--accent); color:#171C22; }
+.cf-yes kbd { color:#171C22; border-color:rgba(23,28,34,.25); }
+.cf-yes.danger { background:var(--accent-deep); color:#F4F5F4; }
+.cf-yes.danger:hover { background:var(--accent-deep); }
+.cf-yes.danger kbd { color:#F4F5F4; border-color:rgba(244,245,244,.4); }
/* search: active result column + file-name selection */
-.sc-head .col-kbd { margin-left:auto; opacity:.55; }
+.sc-head .col-kbd { margin-left:auto; }
.sc-left.active .sc-head, .sc-right.active .sc-head, .sc-infile.active .sc-head { color:var(--accent); }
-.sc-left.active .sc-head .col-kbd, .sc-right.active .sc-head .col-kbd, .sc-infile.active .sc-head .col-kbd { color:var(--accent); border-color:var(--accent-line); opacity:1; }
+.sc-left.active .sc-head .sc-ct, .sc-right.active .sc-head .sc-ct, .sc-infile.active .sc-head .sc-ct {
+ color:#171C22; background:var(--accent); padding:3px 6px; }
+.sc-left.active .sc-head .col-kbd, .sc-right.active .sc-head .col-kbd, .sc-infile.active .sc-head .col-kbd { color:var(--accent); border-color:var(--accent-dim); }
.sc-infile.active .sc-head .scf-name { color:var(--accent); }
diff --git a/src/renderer/src/terminals.tsx b/src/renderer/src/terminals.tsx
index ced21d7..81b4106 100644
--- a/src/renderer/src/terminals.tsx
+++ b/src/renderer/src/terminals.tsx
@@ -17,7 +17,7 @@ import type { HelderConfig } from './types'
let _lid = 0
export const lid = (): number => ++_lid
-const MONO = '"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace'
+const MONO = '"IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace'
/* Everything visual comes from `terminal` in config.json — palette, font,
* cursor, scrollback — so the console is themed from the same file as the rest
@@ -33,7 +33,7 @@ function xtermOptions(cfg: HelderConfig['terminal']): {
const css = getComputedStyle(document.documentElement)
return {
fontFamily: cfg.fontFamily || css.getPropertyValue('--code-font').trim() || MONO,
- fontSize: cfg.fontSize || parseFloat(css.getPropertyValue('--term-size')) || 12.5,
+ fontSize: cfg.fontSize || parseFloat(css.getPropertyValue('--term-size')) || 12,
lineHeight: cfg.lineHeight,
letterSpacing: cfg.letterSpacing,
cursorStyle: cfg.cursorStyle,
diff --git a/src/renderer/src/types.ts b/src/renderer/src/types.ts
index 6011e41..c8e80d0 100644
--- a/src/renderer/src/types.ts
+++ b/src/renderer/src/types.ts
@@ -132,27 +132,30 @@ export const DEFAULT_CONFIG: HelderConfig = {
shell: null,
fontFamily: null,
fontSize: null,
- lineHeight: 1.35,
+ lineHeight: 1.7,
letterSpacing: 0,
cursorStyle: 'bar',
cursorBlink: true,
boldIsBright: false,
scrollback: 8000,
optionIsMeta: false,
- // The app's own palette: charcoal ground, the accent on the caret and the
- // selection, and the syntax colours reused for the ANSI table so a diff in
- // the terminal reads like a diff in the editor.
+ // The app's own palette: the editor ground, amber on the caret and the
+ // selection, and the six muted syntax colours on the ANSI table, so a diff
+ // in the terminal reads like a diff in the editor. Red is amber-deep and
+ // green is teal — the same pair the diff views use. A terminal still needs
+ // eight distinguishable slots, so blue and cyan take two cool tones that
+ // stay inside the muted register.
theme: {
- background: '#24272c',
- foreground: '#dde1e7',
- cursor: '#f19f3f',
- cursorAccent: '#24272c',
- selectionBackground: 'rgba(241,159,63,0.32)',
- selectionInactiveBackground: 'rgba(241,159,63,0.18)',
- black: '#2b2e34', red: '#e0696a', green: '#5cbd6b', yellow: '#d8a85c',
- blue: '#6aa6f0', magenta: '#c98bdb', cyan: '#6ec0c0', white: '#b0b6bf',
- brightBlack: '#7a828d', brightRed: '#ef8385', brightGreen: '#77d186', brightYellow: '#edc077',
- brightBlue: '#86bbf5', brightMagenta: '#dba6e9', brightCyan: '#8ad6d6', brightWhite: '#fbfcfd',
+ background: '#101720',
+ foreground: '#E4E7E6',
+ cursor: '#E8913A',
+ cursorAccent: '#101720',
+ selectionBackground: 'rgba(232,145,58,0.22)',
+ selectionInactiveBackground: 'rgba(232,145,58,0.12)',
+ black: '#232C39', red: '#C4741F', green: '#8FBFB4', yellow: '#F0B476',
+ blue: '#8FA9C4', magenta: '#C3A6CE', cyan: '#8FC4C4', white: '#BAC0C0',
+ brightBlack: '#6C7783', brightRed: '#E8913A', brightGreen: '#A6D2C7', brightYellow: '#F5C79A',
+ brightBlue: '#A9BFD6', brightMagenta: '#D6BFDF', brightCyan: '#A9D6D6', brightWhite: '#F4F5F4',
},
},
session: { restoreOnLaunch: true },
diff --git a/test/highlight.test.ts b/test/highlight.test.ts
index 2674130..619ba82 100644
--- a/test/highlight.test.ts
+++ b/test/highlight.test.ts
@@ -31,14 +31,15 @@ describe('HL.langFor / langLabel', () => {
describe('HL.iconFor', () => {
it('uses name-specific icons', () => {
- expect(HL.iconFor('composer.json').t).toBe('co')
- expect(HL.iconFor('package.json').t).toBe('pk')
+ expect(HL.iconFor('composer.json').c).toBe('#C3A6CE')
+ expect(HL.iconFor('package.json').c).toBe('#F0B476')
})
it('falls back to extension icons', () => {
- expect(HL.iconFor('x.php').c).toBe('#a78bdb')
+ expect(HL.iconFor('x.php').c).toBe('#C3A6CE')
})
- it('falls back to first two letters for unknown types', () => {
- expect(HL.iconFor('weird.zzz').t).toBe('we')
+ it('falls back to the extension for unknown types', () => {
+ expect(HL.iconFor('weird.zzz').t).toBe('zzz')
+ expect(HL.iconFor('weird.zzz').c).toBe('#BAC0C0')
})
})
diff --git a/test/notes.test.tsx b/test/notes.test.tsx
index f327914..7f33445 100644
--- a/test/notes.test.tsx
+++ b/test/notes.test.tsx
@@ -170,7 +170,7 @@ describe('project note', () => {
const c = await boot()
await openNote(c)
const hint = c.querySelector('.notes-modal .notes-hint')
- expect(hint?.textContent).toContain('To agent')
+ expect(hint?.textContent).toContain('To the agent')
expect(hint?.querySelector('kbd')?.textContent).toBe('⌘P')
})