1
2
3
4:root,
5:root[data-theme="dark"] {
6 color-scheme: dark;
7 --page: #0d0d0d;
8 --surface-1: #1a1a19;
9 --surface-2: #232321;
10 --text-primary: #ffffff;
11 --text-secondary: #c3c2b7;
12 --text-muted: #898781;
13 --grid: #2c2c2a;
14 --axis: #383835;
15 --border: rgba(255, 255, 255, 0.10);
16 --accent: #3987e5;
17 --delta-good: #0ca30c;
18 --status-good: #0ca30c;
19 --status-warning: #fab219;
20 --status-critical: #d03b3b;
21 --series-1: #3987e5;
22 --series-2: #d95926;
23 --series-3: #199e70;
24 --series-4: #c98500;
25 --series-5: #d55181;
26 --series-6: #008300;
27 --series-7: #9085e9;
28 --series-8: #e66767;
29}
30
31:root[data-theme="light"] {
32 color-scheme: light;
33 --page: #f9f9f7;
34 --surface-1: #fcfcfb;
35 --surface-2: #f0efec;
36 --text-primary: #0b0b0b;
37 --text-secondary: #52514e;
38 --text-muted: #898781;
39 --grid: #e1e0d9;
40 --axis: #c3c2b7;
41 --border: rgba(11, 11, 11, 0.10);
42 --accent: #2a78d6;
43 --delta-good: #006300;
44 --series-1: #2a78d6;
45 --series-2: #eb6834;
46 --series-3: #1baf7a;
47 --series-4: #eda100;
48 --series-5: #e87ba4;
49 --series-6: #008300;
50 --series-7: #4a3aa7;
51 --series-8: #e34948;
52}
53
54* { box-sizing: border-box; }
55
56html, body { margin: 0; }
57
58body {
59 background: var(--page);
60 color: var(--text-primary);
61 font: 14px/1.5 system-ui, -apple-system, "Segoe UI", sans-serif;
62 padding: 20px clamp(14px, 4vw, 32px) 40px;
63 max-width: 1160px;
64 margin: 0 auto;
65}
66
67h1, h2, h3 { margin: 0; font-weight: 650; }
68h1 { font-size: 20px; }
69h2 { font-size: 15px; }
70h3 { font-size: 13px; margin-top: 16px; }
71
72a { color: var(--accent); }
73
74.visually-hidden {
75 position: absolute;
76 width: 1px; height: 1px;
77 overflow: hidden;
78 clip: rect(0 0 0 0);
79 white-space: nowrap;
80}
81
82
83
84.topbar {
85 display: flex;
86 align-items: center;
87 justify-content: space-between;
88 gap: 12px;
89 flex-wrap: wrap;
90 padding-bottom: 18px;
91}
92
93.brand { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
94.tagline { color: var(--text-muted); font-size: 13px; }
95.topbar-actions { display: flex; gap: 8px; }
96
97
98
99.btn {
100 background: var(--surface-2);
101 color: var(--text-primary);
102 border: 1px solid var(--border);
103 border-radius: 8px;
104 padding: 7px 12px;
105 font: inherit;
106 cursor: pointer;
107}
108.btn:hover { border-color: var(--axis); }
109a.btn { text-decoration: none; display: inline-block; }
110.btn:focus-visible,
111input:focus-visible,
112select:focus-visible {
113 outline: 2px solid var(--accent);
114 outline-offset: 1px;
115}
116.btn-primary {
117 background: var(--accent);
118 border-color: transparent;
119 color: #ffffff;
120 font-weight: 600;
121}
122.btn-primary:hover { filter: brightness(1.1); }
123.btn-ghost { background: transparent; }
124.btn-sm { padding: 3px 9px; font-size: 12px; border-radius: 6px; }
125.btn-danger {
126 background: transparent;
127 border-color: transparent;
128 color: var(--status-critical);
129}
130.btn-danger:hover { border-color: var(--status-critical); }
131
132input, select {
133 background: var(--surface-2);
134 color: var(--text-primary);
135 border: 1px solid var(--border);
136 border-radius: 8px;
137 padding: 7px 10px;
138 font: inherit;
139}
140
141.field { display: flex; flex-direction: column; gap: 4px; }
142.field-grow { flex: 1; min-width: 160px; }
143.field-label { font-size: 12px; color: var(--text-secondary); }
144
145
146
147.card {
148 background: var(--surface-1);
149 border: 1px solid var(--border);
150 border-radius: 12px;
151 padding: 16px 18px;
152}
153
154.card-head {
155 display: flex;
156 align-items: baseline;
157 justify-content: space-between;
158 gap: 10px;
159 margin-bottom: 12px;
160}
161.card-sub { color: var(--text-muted); font-size: 12px; }
162
163
164
165.tiles {
166 display: grid;
167 grid-template-columns: 1.5fr 1fr 1fr;
168 gap: 14px;
169 margin-bottom: 14px;
170}
171
172.tile { display: flex; flex-direction: column; gap: 4px; }
173.tile-label { font-size: 13px; color: var(--text-secondary); }
174.tile-value { font-size: 26px; font-weight: 600; }
175.hero-value { font-size: 48px; font-weight: 650; line-height: 1.1; }
176.tile-delta { font-size: 13px; color: var(--text-secondary); min-height: 1.2em; }
177.tile-delta .delta-good { color: var(--delta-good); }
178.tile-delta .delta-bad { color: var(--status-critical); }
179.tile-value.net-negative { color: var(--status-critical); }
180
181
182
183.filters {
184 display: flex;
185 gap: 10px;
186 align-items: flex-end;
187 flex-wrap: wrap;
188 margin-bottom: 14px;
189}
190
191
192
193.charts-row {
194 display: grid;
195 grid-template-columns: 3fr 2fr;
196 gap: 14px;
197 margin-bottom: 14px;
198}
199
200.chart-wrap { position: relative; }
201#spend-chart { display: block; width: 100%; height: 280px; }
202
203.tooltip {
204 position: absolute;
205 pointer-events: none;
206 background: var(--surface-2);
207 border: 1px solid var(--border);
208 border-radius: 8px;
209 padding: 6px 10px;
210 font-size: 12px;
211 display: flex;
212 flex-direction: column;
213 gap: 2px;
214 box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
215 z-index: 5;
216 white-space: nowrap;
217}
218.tooltip[hidden] { display: none; }
219.tt-label { color: var(--text-muted); }
220.tt-value { color: var(--text-primary); font-weight: 600; font-variant-numeric: tabular-nums; }
221
222
223
224.budget-row {
225 padding: 9px 0;
226 border-bottom: 1px solid var(--grid);
227}
228.budget-row:last-child { border-bottom: none; }
229
230.budget-top {
231 display: flex;
232 align-items: center;
233 justify-content: space-between;
234 gap: 10px;
235 margin-bottom: 6px;
236}
237.budget-name { display: flex; align-items: center; gap: 8px; font-size: 13px; }
238.budget-nums {
239 font-size: 12px;
240 color: var(--text-secondary);
241 display: flex;
242 align-items: center;
243 gap: 4px;
244 font-variant-numeric: tabular-nums;
245}
246.budget-input {
247 width: 72px;
248 padding: 2px 6px;
249 font-size: 12px;
250 border-radius: 6px;
251 text-align: right;
252 font-variant-numeric: tabular-nums;
253}
254
255.cat-dot {
256 width: 9px;
257 height: 9px;
258 border-radius: 50%;
259 flex: 0 0 auto;
260 display: inline-block;
261}
262.cat-dot.cat-0 { background: var(--series-1); }
263.cat-dot.cat-1 { background: var(--series-2); }
264.cat-dot.cat-2 { background: var(--series-3); }
265.cat-dot.cat-3 { background: var(--series-4); }
266.cat-dot.cat-4 { background: var(--series-5); }
267.cat-dot.cat-5 { background: var(--series-6); }
268.cat-dot.cat-6 { background: var(--series-7); }
269.cat-dot.cat-7 { background: var(--series-8); }
270.cat-dot.cat-income { background: var(--text-muted); }
271
272
273
274.budget-track {
275 height: 10px;
276 border-radius: 5px;
277 overflow: hidden;
278 background: var(--surface-2);
279}
280.budget-fill { height: 100%; border-radius: 2px 5px 5px 2px; }
281.budget-track.level-ok { background: color-mix(in srgb, var(--accent) 16%, var(--surface-1)); }
282.budget-track.level-ok .budget-fill { background: var(--accent); }
283.budget-track.level-warning { background: color-mix(in srgb, var(--status-warning) 16%, var(--surface-1)); }
284.budget-track.level-warning .budget-fill { background: var(--status-warning); }
285.budget-track.level-over { background: color-mix(in srgb, var(--status-critical) 18%, var(--surface-1)); }
286.budget-track.level-over .budget-fill { background: var(--status-critical); }
287
288.budget-note {
289 margin-top: 5px;
290 font-size: 12px;
291 color: var(--text-muted);
292 display: flex;
293 align-items: center;
294 gap: 6px;
295}
296.status-ic { font-size: 11px; }
297.status-ic.level-warning { color: var(--status-warning); }
298.status-ic.level-over { color: var(--status-critical); }
299
300
301
302#txn-form {
303 display: flex;
304 gap: 10px;
305 align-items: flex-end;
306 flex-wrap: wrap;
307 margin-bottom: 4px;
308}
309.form-buttons { display: flex; gap: 8px; }
310
311.form-error {
312 color: var(--status-critical);
313 font-size: 13px;
314 min-height: 1.2em;
315 margin: 4px 0;
316}
317.import-status {
318 color: var(--text-secondary);
319 font-size: 13px;
320 margin: 0 0 6px;
321 min-height: 1.2em;
322}
323
324
325
326.table-scroll { overflow-x: auto; }
327
328table { width: 100%; border-collapse: collapse; }
329th {
330 text-align: left;
331 font-size: 12px;
332 font-weight: 600;
333 color: var(--text-secondary);
334 padding: 8px;
335 border-bottom: 1px solid var(--axis);
336}
337td {
338 padding: 9px 8px;
339 border-bottom: 1px solid var(--grid);
340 vertical-align: middle;
341}
342tbody tr:hover { background: color-mix(in srgb, var(--surface-2) 55%, transparent); }
343tbody tr.editing { outline: 2px solid var(--accent); outline-offset: -2px; }
344
345.td-date { white-space: nowrap; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
346.td-category { white-space: nowrap; }
347.td-category .cat-dot { margin-right: 7px; }
348.col-amount, .td-amount { text-align: right; }
349.td-amount { font-variant-numeric: tabular-nums; white-space: nowrap; }
350.td-amount.income { color: var(--delta-good); }
351.col-actions, .td-actions { text-align: right; white-space: nowrap; }
352tr.empty td { color: var(--text-muted); text-align: center; padding: 24px; }
353
354
355
356footer {
357 display: flex;
358 justify-content: space-between;
359 gap: 10px;
360 flex-wrap: wrap;
361 margin-top: 18px;
362 color: var(--text-muted);
363 font-size: 13px;
364}
365
366kbd {
367 background: var(--surface-2);
368 border: 1px solid var(--border);
369 border-bottom-width: 2px;
370 border-radius: 4px;
371 padding: 1px 6px;
372 font-size: 12px;
373 font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
374 color: var(--text-primary);
375}
376
377dialog {
378 background: var(--surface-1);
379 color: var(--text-primary);
380 border: 1px solid var(--border);
381 border-radius: 12px;
382 padding: 20px 24px;
383 max-width: 440px;
384 width: calc(100vw - 48px);
385}
386dialog::backdrop { background: rgba(0, 0, 0, 0.55); }
387dialog p, dialog td { color: var(--text-secondary); font-size: 13px; }
388dialog code, dialog em { color: var(--text-primary); }
389.shortcut-table td { border: none; padding: 4px 10px 4px 0; }
390dialog form { margin-top: 14px; }
391
392
393
394@media (max-width: 900px) {
395 .charts-row { grid-template-columns: 1fr; }
396 .tiles { grid-template-columns: 1fr; }
397 .hero-value { font-size: 38px; }
398}
399
Discussion
1 comment on this trajectory. Recorded by @patrick-toulme.