ai-code-engineer 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. ai_code_engineer/__init__.py +2 -0
  2. ai_code_engineer/catalog.py +143 -0
  3. ai_code_engineer/chat.py +181 -0
  4. ai_code_engineer/cli.py +384 -0
  5. ai_code_engineer/config.py +405 -0
  6. ai_code_engineer/engine.py +1282 -0
  7. ai_code_engineer/errors.py +27 -0
  8. ai_code_engineer/git_integration.py +443 -0
  9. ai_code_engineer/gui.py +2646 -0
  10. ai_code_engineer/host.py +81 -0
  11. ai_code_engineer/ignore.py +269 -0
  12. ai_code_engineer/intent.py +222 -0
  13. ai_code_engineer/labels.py +871 -0
  14. ai_code_engineer/memory.py +91 -0
  15. ai_code_engineer/modes.py +156 -0
  16. ai_code_engineer/overrides.py +540 -0
  17. ai_code_engineer/planbook.py +192 -0
  18. ai_code_engineer/providers.py +404 -0
  19. ai_code_engineer/redaction.py +54 -0
  20. ai_code_engineer/repair.py +564 -0
  21. ai_code_engineer/report.py +352 -0
  22. ai_code_engineer/runner.py +854 -0
  23. ai_code_engineer/setup.py +386 -0
  24. ai_code_engineer/symbols.py +1286 -0
  25. ai_code_engineer/verification.py +218 -0
  26. ai_code_engineer/webapp/__init__.py +1 -0
  27. ai_code_engineer/webapp/__main__.py +45 -0
  28. ai_code_engineer/webapp/contract.py +36 -0
  29. ai_code_engineer/webapp/controller.py +3556 -0
  30. ai_code_engineer/webapp/fake.py +1141 -0
  31. ai_code_engineer/webapp/launch.py +108 -0
  32. ai_code_engineer/webapp/server.py +349 -0
  33. ai_code_engineer/webapp/static/app.css +780 -0
  34. ai_code_engineer/webapp/static/app.js +2118 -0
  35. ai_code_engineer/webapp/static/boot.js +19 -0
  36. ai_code_engineer/webapp/static/index.html +89 -0
  37. ai_code_engineer/webapp/static/tokens.css +173 -0
  38. ai_code_engineer/workspace.py +385 -0
  39. ai_code_engineer-0.1.0.dist-info/METADATA +7 -0
  40. ai_code_engineer-0.1.0.dist-info/RECORD +44 -0
  41. ai_code_engineer-0.1.0.dist-info/WHEEL +5 -0
  42. ai_code_engineer-0.1.0.dist-info/entry_points.txt +2 -0
  43. ai_code_engineer-0.1.0.dist-info/licenses/LICENSE +21 -0
  44. ai_code_engineer-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,19 @@
1
+ /* Set the style before the first paint: doing it after bootstrap arrives would animate
2
+ every token at once, which reads as a colour flash on launch.
3
+
4
+ A separate file rather than an inline <script> so the server's Content-Security-Policy can be
5
+ `script-src 'self'` with no 'unsafe-inline'. A classic script in <head> still runs before the body
6
+ is parsed, so the timing this depends on is unchanged. */
7
+ (function () {
8
+ const q = new URLSearchParams(location.search);
9
+ const saved = JSON.parse(localStorage.getItem('ui.prefs') || '{}');
10
+ const root = document.documentElement;
11
+ root.dataset.style = q.get('style') || saved.style || 'claude';
12
+ const mode = q.get('theme') || saved.theme || 'light';
13
+ root.dataset.theme = mode === 'auto'
14
+ ? (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') : mode;
15
+ // The collapsed state is the window's own choice too: applying it after bootstrap arrives
16
+ // would show the sidebar for a frame and then snap it away.
17
+ if (saved.collapsed) root.classList.add('side-collapsed');
18
+ root.classList.add('booting');
19
+ })();
@@ -0,0 +1,89 @@
1
+ <!doctype html>
2
+ <html lang="en" data-style="claude" data-theme="light">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="color-scheme" content="light dark">
7
+ <title>AI Code Engineer</title>
8
+ <link rel="stylesheet" href="tokens.css">
9
+ <link rel="stylesheet" href="app.css">
10
+ <script src="boot.js"></script>
11
+ </head>
12
+ <body>
13
+ <div class="app" id="app">
14
+
15
+ <aside class="side">
16
+ <div class="brand">
17
+ <div class="mark">A</div><b>AI Code Engineer</b>
18
+ <div class="spacer"></div>
19
+ <button class="icon-btn" id="collapse" title="Collapse sidebar (Ctrl+B)" aria-label="Collapse sidebar">
20
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 5h16v14H4z"/><path d="M10 5v14"/></svg>
21
+ </button>
22
+ </div>
23
+
24
+ <button class="newbtn" id="new-chat" title="New chat (Ctrl+Shift+K). Ctrl+K opens the command palette.">
25
+ <span class="l">
26
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M12 5v14M5 12h14"/></svg>
27
+ New chat
28
+ </span><span class="kbd">Ctrl ⇧ K</span>
29
+ </button>
30
+
31
+ <label class="search" for="search">
32
+ <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><circle cx="11" cy="11" r="7"/><path d="M20 20l-3.6-3.6"/></svg>
33
+ <input id="search" placeholder="Search tasks and chats" autocomplete="off" spellcheck="false">
34
+ </label>
35
+
36
+ <nav class="nav" id="nav"></nav>
37
+
38
+ <div class="foot">
39
+ <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 3l7 4v5c0 4.4-3 7.6-7 9-4-1.4-7-4.6-7-9V7l7-4z"/></svg>
40
+ You always review first
41
+ <div class="themepick" id="themepick"></div>
42
+ </div>
43
+ </aside>
44
+
45
+ <main class="main">
46
+ <header class="top">
47
+ <button class="icon-btn" id="sidebar-expand" title="Expand sidebar (Ctrl+B)" aria-label="Expand sidebar">
48
+ <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 5h16v14H4z"/><path d="M10 5v14"/><path d="M6.6 12h2.2M6.6 9.4h2.2M6.6 14.6h2.2"/></svg>
49
+ </button>
50
+ <div style="min-width:0">
51
+ <h1 id="title">New chat</h1>
52
+ <div class="sub" id="subtitle">Standalone chat — no folder attached, nothing to change</div>
53
+ </div>
54
+ <div class="seg" id="seg" role="tablist" aria-label="Switch view">
55
+ <button data-view="details" role="tab" aria-selected="false" aria-controls="view-details">Activity</button>
56
+ <button data-view="task" role="tab" aria-selected="true" aria-controls="view-task" class="on">Chat</button>
57
+ </div>
58
+ <button class="ghost" id="attach-top" title="Attach a project plan">+ Plan</button>
59
+ </header>
60
+ <div class="busybar hidden" id="busybar"></div>
61
+
62
+ <!-- chat -->
63
+ <section class="view on" id="view-task" role="tabpanel" aria-label="Chat">
64
+ <div class="scroll" id="scroller"><div class="thread" id="thread"></div></div>
65
+ <div class="dock">
66
+ <div class="setup" id="setup" role="region" aria-label="First-run checks"></div>
67
+ <div class="queue" id="queue" aria-live="polite"></div>
68
+ <div class="composer" id="composer">
69
+ <textarea id="prompt" dir="auto" rows="2" placeholder="Ask anything — or choose a project and describe the change"></textarea>
70
+ <div class="cbar" id="cbar"></div>
71
+ </div>
72
+ </div>
73
+ </section>
74
+
75
+ <!-- activity -->
76
+ <section class="view" id="view-details" role="tabpanel" aria-label="Activity">
77
+ <div class="logwrap"><div class="log" id="log"></div></div>
78
+ </section>
79
+ </main>
80
+
81
+ <aside class="rail" id="rail"></aside>
82
+ </div>
83
+
84
+ <div class="toasts" id="toasts" role="status" aria-live="polite"></div>
85
+ <div id="modal-root"></div>
86
+
87
+ <script src="app.js"></script>
88
+ </body>
89
+ </html>
@@ -0,0 +1,173 @@
1
+ /* Design tokens only. Every colour, radius and shadow in the app comes from here,
2
+ so a style family and a theme are one attribute swap on <html>.
3
+
4
+ Two naming rules exist because one colour rarely has one correct ink:
5
+ --accent / --accent-hover filled surfaces; label takes --accent-ink
6
+ --accent-text the same hue used AS text on a page or card
7
+ --ok / --on-ok a filled badge and the mark painted on it
8
+ --ok-bg / --ok-ink a tinted pill and its label
9
+ Every one of these pairs is measured by tools/check_contrast.py. */
10
+
11
+ /* ---- shared metrics: the layout does not change between families ---- */
12
+ :root {
13
+ --ui: "Segoe UI Variable Text", "Segoe UI", Inter, system-ui, sans-serif;
14
+ --mono: "JetBrains Mono", "Cascadia Mono", Consolas, monospace;
15
+ --side-w: 270px;
16
+ --rail-w: 322px;
17
+ --thread-w: 760px;
18
+ --ease: cubic-bezier(.22, .61, .36, 1);
19
+ --t-fast: 110ms var(--ease);
20
+ --t-med: 190ms var(--ease);
21
+ }
22
+
23
+ /* ===================== claude · warm paper ===================== */
24
+ :root,
25
+ :root[data-style="claude"][data-theme="light"] {
26
+ --bg: #faf9f6; --side: #f2efe9; --topbar: #faf9f6; --panel: #ffffff; --field: #ffffff;
27
+ --ink: #26251f; --ink-2: #4d4a42; --faint: #6b665c;
28
+ --line: #e6e2d9; --line-2: #d8d3c8; --line-soft: #f0ede6;
29
+ --accent: #d97757; --accent-hover: #c86546; --accent-ink: #26251f; --accent-text: #bd4f2b; --accent-ring: #f6ded4;
30
+ --hover: #eae6de; --sel: #f1e9e2; --seg: #eae6de; --seg-on: #ffffff;
31
+ --seg-shadow: 0 1px 2px rgba(38, 37, 31, .09);
32
+ --chip: #f2efe9; --me: #f1ece3; --me-line: #e6dfd2; --me-ink: #26251f;
33
+ --pic: #e9e5dd; --pic-ink: #6a655c;
34
+ --code: #fbfaf7; --code-bar: #f4f2ec;
35
+ --syn-k: #a0414f; --syn-s: #3f6b4a; --syn-c: #a49e93; --syn-n: #7a5cb8;
36
+ --ok: #4f7a52; --on-ok: #ffffff; --ok-bg: #eef4ec; --ok-ink: #3d6440; --ok-line: #d9e6d6;
37
+ --warn: #b07a3c; --warn-bg: #faf2e5; --warn-ink: #8a5f2c; --warn-line: #eddfc8;
38
+ --bad: #a8453c; --bad-bg: #fbeeec; --bad-ink: #8d3b34; --bad-line: #edd9d6;
39
+ --info: #4a6b8a; --info-bg: #eef3f7; --info-ink: #3c5a75; --info-line: #d8e3ec;
40
+ --add: #eef6ec; --add-ink: #2f5d38; --del: #fbeeec; --del-ink: #8d3b34; --hunk: #f4f2ec;
41
+ --scroll: #d8d3c8; --kbd: rgba(38, 37, 31, .07); --kbd-ink: #716b61;
42
+ --pop: #26251f; --pop-ink: #faf9f6; --scrim: rgba(38, 37, 31, .34);
43
+ --r-s: 8px; --r-m: 11px; --r-l: 15px; --r-xl: 20px;
44
+ --card-shadow: 0 1px 2px rgba(38, 37, 31, .04);
45
+ --btn-shadow: 0 1px 2px rgba(38, 37, 31, .14);
46
+ --pop-shadow: 0 8px 28px rgba(38, 37, 31, .16);
47
+ --fs: 14px; --ls: 0px;
48
+ }
49
+
50
+ :root[data-style="claude"][data-theme="dark"] {
51
+ --bg: #262624; --side: #1f1f1d; --topbar: #262624; --panel: #2e2e2b; --field: #2a2a27;
52
+ --ink: #ece9e3; --ink-2: #c6c2ba; --faint: #9a968f;
53
+ --line: #3c3b37; --line-2: #4a4844; --line-soft: #333230;
54
+ --accent: #d97757; --accent-hover: #e38a6c; --accent-ink: #262624; --accent-text: #db7d5e; --accent-ring: rgba(217, 119, 87, .24);
55
+ --hover: #34332f; --sel: #3a322d; --seg: #1f1f1d; --seg-on: #3d3c38;
56
+ --seg-shadow: 0 1px 2px rgba(0, 0, 0, .3);
57
+ --chip: #34332f; --me: #3a322d; --me-line: #4a4038; --me-ink: #f3efe9;
58
+ --pic: #3d3c38; --pic-ink: #aca79f;
59
+ --code: #222220; --code-bar: #2a2a27;
60
+ --syn-k: #e79a86; --syn-s: #9ecf9f; --syn-c: #7a756d; --syn-n: #c2aef5;
61
+ --ok: #7fb37f; --on-ok: #262624; --ok-bg: #2b3529; --ok-ink: #a5cfa2; --ok-line: #3a4a38;
62
+ --warn: #d6a86a; --warn-bg: #3a3125; --warn-ink: #e3bd8b; --warn-line: #4d4030;
63
+ --bad: #e08a80; --bad-bg: #3a2523; --bad-ink: #eabdb7; --bad-line: #4d3230;
64
+ --info: #8fb4d0; --info-bg: #26313a; --info-ink: #b3cfe3; --info-line: #35434e;
65
+ --add: #253224; --add-ink: #a9d3a4; --del: #3a2523; --del-ink: #e5a89e; --hunk: #2a2a27;
66
+ --scroll: #4a4844; --kbd: rgba(255, 255, 255, .09); --kbd-ink: #b2ada5;
67
+ --pop: #ece9e3; --pop-ink: #262624; --scrim: rgba(0, 0, 0, .55);
68
+ --r-s: 8px; --r-m: 11px; --r-l: 15px; --r-xl: 20px;
69
+ --card-shadow: 0 1px 2px rgba(0, 0, 0, .24);
70
+ --btn-shadow: 0 1px 2px rgba(0, 0, 0, .3);
71
+ --pop-shadow: 0 12px 34px rgba(0, 0, 0, .5);
72
+ --fs: 14px; --ls: 0px;
73
+ }
74
+
75
+ /* ===================== codex · charcoal, dense ===================== */
76
+ :root[data-style="codex"][data-theme="dark"] {
77
+ --bg: #0e1013; --side: #0a0b0e; --topbar: #0e1013; --panel: #15181d; --field: #12141a;
78
+ --ink: #e9ecef; --ink-2: #b9bfc7; --faint: #7c838e;
79
+ --line: #23272e; --line-2: #2e333b; --line-soft: #1b1e23;
80
+ --accent: #f7f7f5; --accent-hover: #ffffff; --accent-ink: #111316; --accent-text: #f7f7f5; --accent-ring: rgba(247, 247, 245, .14);
81
+ --hover: #1a1e24; --sel: #1e242c; --seg: #0a0b0e; --seg-on: #22262d;
82
+ --seg-shadow: 0 1px 0 rgba(255, 255, 255, .05);
83
+ --chip: #1a1e24; --me: #1e242c; --me-line: #2b323b; --me-ink: #e9ecef;
84
+ --pic: #22262d; --pic-ink: #9aa1ab;
85
+ --code: #0c0e11; --code-bar: #12141a;
86
+ --syn-k: #c7aeff; --syn-s: #9ad4a0; --syn-c: #5c636d; --syn-n: #f5c777;
87
+ --ok: #5cc98a; --on-ok: #0e1013; --ok-bg: #132a1e; --ok-ink: #7fd9a3; --ok-line: #1e3b2a;
88
+ --warn: #e0b25f; --warn-bg: #2a2317; --warn-ink: #e8c98a; --warn-line: #3b3120;
89
+ --bad: #f2777a; --bad-bg: #2c1618; --bad-ink: #f5a3a5; --bad-line: #442325;
90
+ --info: #8ab4d6; --info-bg: #13222c; --info-ink: #a6cbe3; --info-line: #1f3440;
91
+ --add: #122a1c; --add-ink: #8fd8a6; --del: #2c1618; --del-ink: #f0a1a3; --hunk: #12141a;
92
+ --scroll: #2e333b; --kbd: rgba(255, 255, 255, .08); --kbd-ink: #9aa1ab;
93
+ --pop: #e9ecef; --pop-ink: #0e1013; --scrim: rgba(0, 0, 0, .62);
94
+ --r-s: 6px; --r-m: 8px; --r-l: 10px; --r-xl: 12px;
95
+ --card-shadow: none; --btn-shadow: 0 0 0 1px rgba(255, 255, 255, .08);
96
+ --pop-shadow: 0 10px 30px rgba(0, 0, 0, .6);
97
+ --fs: 13.5px; --ls: -.05px;
98
+ }
99
+
100
+ :root[data-style="codex"][data-theme="light"] {
101
+ --bg: #f7f7f5; --side: #efece7; --topbar: #f7f7f5; --panel: #ffffff; --field: #ffffff;
102
+ --ink: #0d0d0c; --ink-2: #3f3f3c; --faint: #6a6a64;
103
+ --line: #e3e0da; --line-2: #cfccc4; --line-soft: #efece7;
104
+ --accent: #0d0d0c; --accent-hover: #26261f; --accent-ink: #ffffff; --accent-text: #0d0d0c; --accent-ring: rgba(13, 13, 12, .12);
105
+ --hover: #eae7e1; --sel: #e5e2da; --seg: #eae7e1; --seg-on: #ffffff;
106
+ --seg-shadow: 0 1px 2px rgba(13, 13, 12, .08);
107
+ --chip: #efece7; --me: #e9e6df; --me-line: #dcd8cf; --me-ink: #0d0d0c;
108
+ --pic: #e3e0da; --pic-ink: #63625d;
109
+ --code: #fbfaf8; --code-bar: #f2efe9;
110
+ --syn-k: #7a3ba8; --syn-s: #146a3f; --syn-c: #9a9994; --syn-n: #a35200;
111
+ --ok: #12683d; --on-ok: #ffffff; --ok-bg: #e9f5ee; --ok-ink: #0f5c36; --ok-line: #cbe6d6;
112
+ --warn: #8a5f2c; --warn-bg: #f8f0e2; --warn-ink: #6f4c22; --warn-line: #e8dcc4;
113
+ --bad: #a52a3d; --bad-bg: #fbeceb; --bad-ink: #8a2434; --bad-line: #f0d5d3;
114
+ --info: #2f5d78; --info-bg: #eaf1f5; --info-ink: #274c62; --info-line: #d3e2ea;
115
+ --add: #eefaf1; --add-ink: #0f5c36; --del: #fdefef; --del-ink: #8a2434; --hunk: #f2efe9;
116
+ --scroll: #cfccc4; --kbd: rgba(13, 13, 12, .06); --kbd-ink: #6d6c67;
117
+ --pop: #0d0d0c; --pop-ink: #f7f7f5; --scrim: rgba(13, 13, 12, .32);
118
+ --r-s: 6px; --r-m: 8px; --r-l: 10px; --r-xl: 12px;
119
+ --card-shadow: none; --btn-shadow: 0 0 0 1px rgba(13, 13, 12, .1);
120
+ --pop-shadow: 0 10px 30px rgba(13, 13, 12, .2);
121
+ --fs: 13.5px; --ls: -.05px;
122
+ }
123
+
124
+ /* ===================== linear · indigo, crisp ===================== */
125
+ :root[data-style="linear"][data-theme="light"] {
126
+ --bg: #ffffff; --side: #f8f9fb; --topbar: #ffffff; --panel: #ffffff; --field: #f6f7f9;
127
+ --ink: #14181f; --ink-2: #3d434c; --faint: #656d78;
128
+ --line: #e7e9ee; --line-2: #d6dae1; --line-soft: #f0f1f4;
129
+ --accent: #4a63d8; --accent-hover: #3c53c4; --accent-ink: #ffffff; --accent-text: #4a63d8; --accent-ring: rgba(91, 124, 250, .2);
130
+ --hover: #f1f3f7; --sel: #eaf0ff; --seg: #eef0f4; --seg-on: #ffffff;
131
+ --seg-shadow: 0 1px 2px rgba(20, 24, 31, .08);
132
+ --chip: #f1f3f7; --me: #eef2ff; --me-line: #dbe3ff; --me-ink: #14181f;
133
+ --pic: #e7e9ee; --pic-ink: #626873;
134
+ --code: #fafbfc; --code-bar: #f4f5f8;
135
+ --syn-k: #8250df; --syn-s: #0a7a4a; --syn-c: #9aa1ab; --syn-n: #b3571a;
136
+ --ok: #1a7f4b; --on-ok: #ffffff; --ok-bg: #e9f7ef; --ok-ink: #12683d; --ok-line: #cfeadb;
137
+ --warn: #9a6510; --warn-bg: #fdf4e3; --warn-ink: #7d5310; --warn-line: #f0dfbd;
138
+ --bad: #c2334a; --bad-bg: #fdefef; --bad-ink: #a52a3d; --bad-line: #f5d7dc;
139
+ --info: #2f6bad; --info-bg: #eaf1fb; --info-ink: #275785; --info-line: #d3e3f5;
140
+ --add: #eefaf1; --add-ink: #12683d; --del: #fdefef; --del-ink: #a52a3d; --hunk: #f4f5f8;
141
+ --scroll: #d6dae1; --kbd: rgba(20, 24, 31, .06); --kbd-ink: #676d79;
142
+ --pop: #14181f; --pop-ink: #ffffff; --scrim: rgba(20, 24, 31, .3);
143
+ --r-s: 7px; --r-m: 9px; --r-l: 12px; --r-xl: 16px;
144
+ --card-shadow: 0 1px 2px rgba(20, 24, 31, .05);
145
+ --btn-shadow: 0 1px 2px rgba(91, 124, 250, .3);
146
+ --pop-shadow: 0 10px 30px rgba(20, 24, 31, .18);
147
+ --fs: 13.5px; --ls: -.05px;
148
+ }
149
+
150
+ :root[data-style="linear"][data-theme="dark"] {
151
+ --bg: #101216; --side: #0b0d10; --topbar: #101216; --panel: #171a1f; --field: #12151a;
152
+ --ink: #e6e9ef; --ink-2: #b4bac5; --faint: #7c8490;
153
+ --line: #23272e; --line-2: #313640; --line-soft: #1b1e23;
154
+ --accent: #7c93ff; --accent-hover: #93a8ff; --accent-ink: #0b0d10; --accent-text: #7c93ff; --accent-ring: rgba(124, 147, 255, .22);
155
+ --hover: #1c2027; --sel: #222a3d; --seg: #0b0d10; --seg-on: #242932;
156
+ --seg-shadow: 0 1px 2px rgba(0, 0, 0, .4);
157
+ --chip: #1c2027; --me: #1e2432; --me-line: #2c3446; --me-ink: #e6e9ef;
158
+ --pic: #242932; --pic-ink: #98a0ad;
159
+ --code: #0c0e11; --code-bar: #12151a;
160
+ --syn-k: #b79bff; --syn-s: #7fd6a4; --syn-c: #5f6773; --syn-n: #f0b96a;
161
+ --ok: #4ec98a; --on-ok: #101216; --ok-bg: #14291f; --ok-ink: #7fd9a3; --ok-line: #1f3d2c;
162
+ --warn: #dfae5f; --warn-bg: #2a2317; --warn-ink: #e8c98a; --warn-line: #3b3120;
163
+ --bad: #f2777a; --bad-bg: #2d181b; --bad-ink: #f5a3a5; --bad-line: #452528;
164
+ --info: #7fb6e8; --info-bg: #142230; --info-ink: #a6cbe3; --info-line: #213648;
165
+ --add: #14291f; --add-ink: #7fd9a3; --del: #2d181b; --del-ink: #f0a1a3; --hunk: #12151a;
166
+ --scroll: #313640; --kbd: rgba(255, 255, 255, .08); --kbd-ink: #98a0ad;
167
+ --pop: #e6e9ef; --pop-ink: #101216; --scrim: rgba(0, 0, 0, .6);
168
+ --r-s: 7px; --r-m: 9px; --r-l: 12px; --r-xl: 16px;
169
+ --card-shadow: 0 1px 2px rgba(0, 0, 0, .3);
170
+ --btn-shadow: 0 1px 2px rgba(0, 0, 0, .4);
171
+ --pop-shadow: 0 12px 34px rgba(0, 0, 0, .55);
172
+ --fs: 13.5px; --ls: -.05px;
173
+ }