wirenote 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 (60) hide show
  1. wirenote/__init__.py +3 -0
  2. wirenote/calendar/__init__.py +2 -0
  3. wirenote/calendar/ics.py +236 -0
  4. wirenote/capture/__init__.py +2 -0
  5. wirenote/capture/recorder.py +304 -0
  6. wirenote/capture/wav.py +58 -0
  7. wirenote/cli.py +262 -0
  8. wirenote/config/__init__.py +2 -0
  9. wirenote/config/apps.py +158 -0
  10. wirenote/config/migrate.py +130 -0
  11. wirenote/config/perms.py +61 -0
  12. wirenote/config/secrets.py +98 -0
  13. wirenote/config/settings.py +176 -0
  14. wirenote/config/vocabulary.py +32 -0
  15. wirenote/data/wirenote-ui.service +15 -0
  16. wirenote/data/wirenote.desktop +10 -0
  17. wirenote/data/wirenote.service +15 -0
  18. wirenote/detector/__init__.py +2 -0
  19. wirenote/detector/core.py +115 -0
  20. wirenote/detector/daemon.py +743 -0
  21. wirenote/detector/graph.py +102 -0
  22. wirenote/detector/identity.py +205 -0
  23. wirenote/detector/streams.py +69 -0
  24. wirenote/detector/tracker.py +304 -0
  25. wirenote/net/__init__.py +2 -0
  26. wirenote/net/peer.py +101 -0
  27. wirenote/notify/__init__.py +2 -0
  28. wirenote/notify/clipboard.py +43 -0
  29. wirenote/notify/dbus.py +89 -0
  30. wirenote/process/__init__.py +2 -0
  31. wirenote/process/jobs.py +122 -0
  32. wirenote/process/merge.py +87 -0
  33. wirenote/process/models.py +57 -0
  34. wirenote/process/note.py +124 -0
  35. wirenote/process/speakers.py +295 -0
  36. wirenote/process/summarize.py +287 -0
  37. wirenote/process/transcribe.py +97 -0
  38. wirenote/process/worker.py +229 -0
  39. wirenote/tools/__init__.py +2 -0
  40. wirenote/tools/dump_streams.py +595 -0
  41. wirenote/tools/install.py +140 -0
  42. wirenote/tools/setup.py +338 -0
  43. wirenote/ui/__init__.py +2 -0
  44. wirenote/ui/data.py +783 -0
  45. wirenote/ui/launch.py +88 -0
  46. wirenote/ui/server.py +423 -0
  47. wirenote/ui/static/app.css +907 -0
  48. wirenote/ui/static/app.js +1267 -0
  49. wirenote/ui/static/fonts/OFL.txt +93 -0
  50. wirenote/ui/static/fonts/inter-latin-ext.woff2 +0 -0
  51. wirenote/ui/static/fonts/inter-latin.woff2 +0 -0
  52. wirenote/ui/static/icon.svg +1 -0
  53. wirenote/ui/static/icons.svg +31 -0
  54. wirenote/ui/static/index.html +57 -0
  55. wirenote/ui/static/login.html +19 -0
  56. wirenote-0.1.0.dist-info/METADATA +106 -0
  57. wirenote-0.1.0.dist-info/RECORD +60 -0
  58. wirenote-0.1.0.dist-info/WHEEL +4 -0
  59. wirenote-0.1.0.dist-info/entry_points.txt +2 -0
  60. wirenote-0.1.0.dist-info/licenses/LICENSE +661 -0
@@ -0,0 +1,907 @@
1
+ /* wirenote UI. Quiet, document-like, one accent (docs/dev/ui-design.md). */
2
+
3
+ @font-face {
4
+ font-family: "Inter";
5
+ font-style: normal;
6
+ font-weight: 100 900;
7
+ font-display: swap;
8
+ src: url("/static/fonts/inter-latin.woff2") format("woff2");
9
+ unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
10
+ U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
11
+ U+FEFF, U+FFFD;
12
+ }
13
+ @font-face {
14
+ font-family: "Inter";
15
+ font-style: normal;
16
+ font-weight: 100 900;
17
+ font-display: swap;
18
+ src: url("/static/fonts/inter-latin-ext.woff2") format("woff2");
19
+ unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304,
20
+ U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
21
+ U+2113, U+2C60-2C7F, U+A720-A7FF;
22
+ }
23
+
24
+ :root {
25
+ --bg: #ffffff;
26
+ --sidebar: #f7f7f5;
27
+ --panel: #fbfbfa;
28
+ --text: #1f1f1d;
29
+ --text-2: #4a4945;
30
+ --muted: #787772;
31
+ --faint: #a8a7a2;
32
+ --line: #ebeae6;
33
+ --line-2: #e2e1dc;
34
+ --hover: #f0efeb;
35
+ --active: #e9e8e3;
36
+ --accent: #1f8a5b;
37
+ --accent-ink: #176b46;
38
+ --accent-soft: #e8f3ed;
39
+ --rec: #e5484d;
40
+ --rec-soft: #fdeceb;
41
+ --warn-soft: #fbf3e2;
42
+ --warn-ink: #8a5a00;
43
+ --mark: #fff1a8;
44
+ --shadow: 0 1px 2px rgb(0 0 0 / 0.04), 0 6px 24px rgb(0 0 0 / 0.07);
45
+ --radius: 10px;
46
+ --font: "Inter", "Noto Sans", ui-sans-serif, system-ui, sans-serif;
47
+ --mono: ui-monospace, "JetBrains Mono", "Noto Sans Mono", monospace;
48
+ color-scheme: light;
49
+ }
50
+
51
+ @media (prefers-color-scheme: dark) {
52
+ :root {
53
+ --bg: #191918;
54
+ --sidebar: #1f1f1e;
55
+ --panel: #1d1d1c;
56
+ --text: #ebeae6;
57
+ --text-2: #c9c8c3;
58
+ --muted: #9a9994;
59
+ --faint: #6d6c68;
60
+ --line: #2c2c2a;
61
+ --line-2: #353533;
62
+ --hover: #262625;
63
+ --active: #2e2e2c;
64
+ --accent: #3db57f;
65
+ --accent-ink: #6fd0a3;
66
+ --accent-soft: #1d3329;
67
+ --rec: #ff6369;
68
+ --rec-soft: #3a2224;
69
+ --warn-soft: #36301f;
70
+ --warn-ink: #e8c46a;
71
+ --mark: #5c4f12;
72
+ --shadow: 0 1px 2px rgb(0 0 0 / 0.3), 0 8px 28px rgb(0 0 0 / 0.45);
73
+ color-scheme: dark;
74
+ }
75
+ }
76
+
77
+ * { box-sizing: border-box; }
78
+ html, body { height: 100%; }
79
+ body {
80
+ margin: 0;
81
+ background: var(--bg);
82
+ color: var(--text);
83
+ font: 15px/1.6 var(--font);
84
+ font-feature-settings: "cv11", "ss01";
85
+ -webkit-font-smoothing: antialiased;
86
+ }
87
+ button, input { font: inherit; color: inherit; }
88
+ button { cursor: pointer; }
89
+ a { color: inherit; text-decoration: none; }
90
+ [hidden] { display: none !important; }
91
+ .icon {
92
+ width: 18px;
93
+ height: 18px;
94
+ flex: none;
95
+ /* <use> into an external sprite does not inherit the sprite's own attributes */
96
+ fill: none;
97
+ stroke: currentColor;
98
+ stroke-width: 1.75;
99
+ stroke-linecap: round;
100
+ stroke-linejoin: round;
101
+ }
102
+ kbd {
103
+ font: 500 11px/1 var(--font);
104
+ color: var(--faint);
105
+ border: 1px solid var(--line-2);
106
+ border-radius: 5px;
107
+ padding: 3px 5px;
108
+ }
109
+ ::selection { background: var(--accent-soft); }
110
+
111
+ /* Layout ------------------------------------------------------------------ */
112
+
113
+ .app { display: grid; grid-template-columns: 284px 1fr; height: 100vh; }
114
+ .content { position: relative; display: flex; flex-direction: column; min-width: 0; height: 100vh; }
115
+ .main { flex: 1; overflow-y: auto; outline: none; scroll-behavior: smooth; }
116
+
117
+ /* Sidebar ----------------------------------------------------------------- */
118
+
119
+ .sidebar {
120
+ display: flex;
121
+ flex-direction: column;
122
+ background: var(--sidebar);
123
+ border-right: 1px solid var(--line);
124
+ min-height: 0;
125
+ }
126
+ .brand {
127
+ display: flex;
128
+ align-items: center;
129
+ gap: 10px;
130
+ padding: 18px 20px 14px;
131
+ font-weight: 650;
132
+ font-size: 15px;
133
+ letter-spacing: -0.01em;
134
+ }
135
+ .brand-mark {
136
+ width: 22px;
137
+ height: 22px;
138
+ border-radius: 6px;
139
+ background: url("/static/icon.svg") center / cover;
140
+ }
141
+ .search {
142
+ display: flex;
143
+ align-items: center;
144
+ gap: 8px;
145
+ margin: 0 12px 10px;
146
+ padding: 7px 10px;
147
+ border-radius: 8px;
148
+ background: var(--bg);
149
+ border: 1px solid var(--line);
150
+ color: var(--muted);
151
+ transition: border-color 0.15s, box-shadow 0.15s;
152
+ }
153
+ .search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
154
+ .search input {
155
+ flex: 1;
156
+ min-width: 0;
157
+ border: 0;
158
+ outline: 0;
159
+ background: transparent;
160
+ color: var(--text);
161
+ font-size: 14px;
162
+ }
163
+ .search input::placeholder { color: var(--faint); }
164
+ .search input::-webkit-search-cancel-button { display: none; }
165
+ .list { flex: 1; overflow-y: auto; padding: 4px 8px 16px; }
166
+ .group-label {
167
+ padding: 14px 12px 4px;
168
+ font-size: 11.5px;
169
+ font-weight: 600;
170
+ letter-spacing: 0.04em;
171
+ text-transform: uppercase;
172
+ color: var(--faint);
173
+ }
174
+ .item {
175
+ display: block;
176
+ padding: 8px 12px;
177
+ border-radius: 8px;
178
+ color: var(--text-2);
179
+ transition: background 0.12s;
180
+ }
181
+ .item:hover { background: var(--hover); }
182
+ .item.active { background: var(--active); color: var(--text); }
183
+ .item-title {
184
+ display: flex;
185
+ align-items: center;
186
+ gap: 6px;
187
+ font-size: 14px;
188
+ font-weight: 520;
189
+ color: var(--text);
190
+ white-space: nowrap;
191
+ overflow: hidden;
192
+ text-overflow: ellipsis;
193
+ }
194
+ .item-title span { overflow: hidden; text-overflow: ellipsis; }
195
+ .item-meta { display: flex; gap: 6px; align-items: center; font-size: 12.5px; color: var(--muted); }
196
+ .item-match { margin-top: 2px; font-size: 12.5px; color: var(--muted); line-height: 1.45; }
197
+ .item-match mark, .t-text mark, .hl { background: var(--mark); color: inherit; border-radius: 2px; }
198
+ .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--accent); }
199
+ .dot.rec { background: var(--rec); animation: pulse 1.4s ease-in-out infinite; }
200
+ .dot.work, .sidebar-status .dot.work { background: var(--warn-ink); animation: pulse 1.4s ease-in-out infinite; }
201
+ .dot.fail { background: var(--rec); }
202
+ @keyframes pulse { 50% { opacity: 0.35; } }
203
+ .list-empty { padding: 24px 14px; color: var(--muted); font-size: 13.5px; }
204
+ .sidebar-status {
205
+ display: flex;
206
+ align-items: center;
207
+ gap: 8px;
208
+ padding: 12px 20px;
209
+ border-top: 1px solid var(--line);
210
+ font-size: 12.5px;
211
+ color: var(--muted);
212
+ }
213
+
214
+ /* Banner ------------------------------------------------------------------ */
215
+
216
+ .banner {
217
+ display: flex;
218
+ align-items: center;
219
+ gap: 12px;
220
+ padding: 10px 24px;
221
+ background: var(--rec-soft);
222
+ color: var(--text);
223
+ font-size: 14px;
224
+ border-bottom: 1px solid var(--line);
225
+ }
226
+ .banner .grow { flex: 1; }
227
+ .banner .elapsed { font-variant-numeric: tabular-nums; color: var(--muted); }
228
+
229
+ /* Buttons ----------------------------------------------------------------- */
230
+
231
+ .btn, .btn-ghost, .btn-danger {
232
+ display: inline-flex;
233
+ align-items: center;
234
+ gap: 7px;
235
+ padding: 6px 12px;
236
+ border-radius: 8px;
237
+ font-size: 13.5px;
238
+ font-weight: 520;
239
+ border: 1px solid var(--line-2);
240
+ background: var(--bg);
241
+ transition: background 0.12s, border-color 0.12s;
242
+ white-space: nowrap;
243
+ }
244
+ .btn:hover, .btn-ghost:hover { background: var(--hover); }
245
+ .btn-ghost { border-color: transparent; background: transparent; color: var(--muted); }
246
+ .btn-ghost:hover { color: var(--text); }
247
+ .btn-primary { background: var(--accent); border-color: var(--accent); color: #fff; }
248
+ .btn-primary:hover { background: var(--accent-ink); }
249
+ .btn-danger { color: var(--rec); }
250
+ .btn-danger:hover { background: var(--rec-soft); }
251
+ .btn-stop { background: var(--rec); border-color: var(--rec); color: #fff; }
252
+ .btn-stop:hover { filter: brightness(0.92); background: var(--rec); }
253
+ .btn-icon {
254
+ display: inline-grid;
255
+ place-items: center;
256
+ width: 32px;
257
+ height: 32px;
258
+ border-radius: 8px;
259
+ border: 0;
260
+ background: transparent;
261
+ color: var(--muted);
262
+ }
263
+ .btn-icon:hover { background: var(--hover); color: var(--text); }
264
+ .btn-chip {
265
+ border: 1px solid var(--line-2);
266
+ background: var(--bg);
267
+ border-radius: 999px;
268
+ padding: 2px 10px;
269
+ font-size: 12.5px;
270
+ font-weight: 600;
271
+ color: var(--muted);
272
+ font-variant-numeric: tabular-nums;
273
+ }
274
+ button:disabled { opacity: 0.5; cursor: default; }
275
+
276
+ /* Page -------------------------------------------------------------------- */
277
+
278
+ .page { max-width: 780px; margin: 0 auto; padding: 44px 48px 140px; }
279
+ .eyebrow { font-size: 13px; color: var(--muted); margin-bottom: 6px; }
280
+ .title {
281
+ margin: 0;
282
+ font-size: 32px;
283
+ line-height: 1.2;
284
+ font-weight: 680;
285
+ letter-spacing: -0.022em;
286
+ outline: none;
287
+ border-radius: 6px;
288
+ cursor: text;
289
+ }
290
+ .title:focus { box-shadow: 0 0 0 3px var(--accent-soft); }
291
+ .meta { display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 14px; color: var(--muted); font-size: 13.5px; }
292
+ .meta span { display: inline-flex; align-items: center; gap: 6px; }
293
+ .meta .icon { width: 16px; height: 16px; color: var(--faint); }
294
+ .head-row { display: flex; align-items: flex-start; gap: 16px; }
295
+ .head-row .grow { flex: 1; min-width: 0; }
296
+ .head-actions { display: flex; gap: 4px; padding-top: 4px; }
297
+ .people { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
298
+ .person {
299
+ display: inline-flex;
300
+ align-items: center;
301
+ gap: 6px;
302
+ padding: 2px 10px 2px 3px;
303
+ border-radius: 999px;
304
+ background: var(--hover);
305
+ font-size: 12.5px;
306
+ color: var(--text-2);
307
+ }
308
+ .avatar {
309
+ display: inline-grid;
310
+ place-items: center;
311
+ width: 20px;
312
+ height: 20px;
313
+ border-radius: 50%;
314
+ font-size: 10.5px;
315
+ font-weight: 650;
316
+ color: #fff;
317
+ background: var(--faint);
318
+ flex: none;
319
+ }
320
+
321
+ .notice {
322
+ display: flex;
323
+ align-items: center;
324
+ gap: 12px;
325
+ margin-top: 24px;
326
+ padding: 12px 16px;
327
+ border-radius: var(--radius);
328
+ background: var(--warn-soft);
329
+ color: var(--warn-ink);
330
+ font-size: 14px;
331
+ }
332
+ .notice .grow { flex: 1; }
333
+ .notice.info { background: var(--accent-soft); color: var(--accent-ink); }
334
+ .notice.bad { background: var(--rec-soft); color: var(--rec); }
335
+ .spinner {
336
+ width: 16px;
337
+ height: 16px;
338
+ border-radius: 50%;
339
+ border: 2px solid currentColor;
340
+ border-right-color: transparent;
341
+ animation: spin 0.8s linear infinite;
342
+ flex: none;
343
+ }
344
+ @keyframes spin { to { transform: rotate(360deg); } }
345
+
346
+ .tabs { display: flex; gap: 4px; margin: 32px 0 8px; border-bottom: 1px solid var(--line); }
347
+ .tab {
348
+ position: relative;
349
+ padding: 8px 12px 10px;
350
+ border: 0;
351
+ background: none;
352
+ color: var(--muted);
353
+ font-size: 14px;
354
+ font-weight: 560;
355
+ }
356
+ .tab:hover { color: var(--text); }
357
+ .tab.active { color: var(--text); }
358
+ .tab.active::after {
359
+ content: "";
360
+ position: absolute;
361
+ left: 8px;
362
+ right: 8px;
363
+ bottom: -1px;
364
+ height: 2px;
365
+ border-radius: 2px;
366
+ background: var(--text);
367
+ }
368
+ .tab .count { margin-left: 6px; color: var(--faint); font-weight: 500; }
369
+
370
+ /* Notes ------------------------------------------------------------------- */
371
+
372
+ .section { margin-top: 28px; }
373
+ .section h2 {
374
+ display: flex;
375
+ align-items: center;
376
+ gap: 8px;
377
+ margin: 0 0 8px;
378
+ font-size: 12px;
379
+ font-weight: 650;
380
+ letter-spacing: 0.06em;
381
+ text-transform: uppercase;
382
+ color: var(--muted);
383
+ }
384
+ .section h2 .n { color: var(--faint); font-weight: 500; letter-spacing: 0; }
385
+ .bullets { margin: 0; padding: 0; list-style: none; }
386
+ .bullets li {
387
+ position: relative;
388
+ display: flex;
389
+ gap: 10px;
390
+ padding: 5px 34px 5px 0;
391
+ border-radius: 6px;
392
+ color: var(--text);
393
+ }
394
+ .bullets li::before {
395
+ content: "";
396
+ width: 5px;
397
+ height: 5px;
398
+ margin-top: 10px;
399
+ border-radius: 50%;
400
+ background: var(--faint);
401
+ flex: none;
402
+ }
403
+ .bullets.decisions li::before { background: var(--accent); }
404
+ .bullets.questions li::before { background: transparent; border: 1.5px solid var(--faint); width: 6px; height: 6px; }
405
+ .jump {
406
+ position: absolute;
407
+ right: 0;
408
+ top: 3px;
409
+ display: grid;
410
+ place-items: center;
411
+ width: 28px;
412
+ height: 28px;
413
+ border: 0;
414
+ border-radius: 6px;
415
+ background: none;
416
+ color: var(--faint);
417
+ opacity: 0;
418
+ transition: opacity 0.12s, background 0.12s;
419
+ }
420
+ li:hover > .jump, .jump:focus-visible { opacity: 1; }
421
+ .jump:hover { background: var(--hover); color: var(--text); }
422
+ .jump .icon { width: 15px; height: 15px; }
423
+
424
+ .actions { margin: 0; padding: 0; list-style: none; }
425
+ .actions li {
426
+ position: relative;
427
+ display: flex;
428
+ align-items: flex-start;
429
+ gap: 12px;
430
+ padding: 8px 34px 8px 0;
431
+ border-bottom: 1px solid var(--line);
432
+ }
433
+ .actions li:last-child { border-bottom: 0; }
434
+ .check {
435
+ display: grid;
436
+ place-items: center;
437
+ width: 19px;
438
+ height: 19px;
439
+ margin-top: 2px;
440
+ border: 1.5px solid var(--line-2);
441
+ border-radius: 6px;
442
+ background: var(--bg);
443
+ color: transparent;
444
+ flex: none;
445
+ transition: all 0.12s;
446
+ }
447
+ .check:hover { border-color: var(--accent); }
448
+ .check .icon { width: 13px; height: 13px; stroke-width: 2.6; }
449
+ .done .check { background: var(--accent); border-color: var(--accent); color: #fff; }
450
+ .done .a-task { color: var(--faint); text-decoration: line-through; text-decoration-color: var(--line-2); }
451
+ .a-body { flex: 1; min-width: 0; }
452
+ .a-task { color: var(--text); }
453
+ .a-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
454
+ .tag {
455
+ display: inline-flex;
456
+ align-items: center;
457
+ gap: 5px;
458
+ padding: 1px 8px 1px 2px;
459
+ border-radius: 999px;
460
+ background: var(--hover);
461
+ font-size: 12px;
462
+ color: var(--text-2);
463
+ }
464
+ .tag .avatar { width: 17px; height: 17px; font-size: 9.5px; }
465
+ .tag.due { padding-left: 8px; background: var(--warn-soft); color: var(--warn-ink); }
466
+ .empty-line { color: var(--faint); font-size: 14px; padding: 4px 0; }
467
+
468
+ /* Ask --------------------------------------------------------------------- */
469
+
470
+ .ask { margin-top: 40px; }
471
+ .qa { margin-bottom: 14px; padding: 14px 16px; border-radius: var(--radius); background: var(--panel); border: 1px solid var(--line); }
472
+ .qa-q { font-weight: 600; font-size: 14px; }
473
+ .qa-a { margin-top: 6px; color: var(--text-2); white-space: pre-wrap; }
474
+ .qa-cites { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
475
+ .qa-meta { margin-top: 8px; font-size: 12px; color: var(--faint); }
476
+ .cite {
477
+ border: 1px solid var(--line-2);
478
+ background: var(--bg);
479
+ border-radius: 999px;
480
+ padding: 1px 9px;
481
+ font: 500 12px/1.6 var(--mono);
482
+ color: var(--accent-ink);
483
+ }
484
+ .cite:hover { background: var(--accent-soft); border-color: var(--accent); }
485
+ .ask-box {
486
+ display: flex;
487
+ align-items: center;
488
+ gap: 8px;
489
+ padding: 6px 6px 6px 14px;
490
+ border: 1px solid var(--line-2);
491
+ border-radius: 12px;
492
+ background: var(--bg);
493
+ box-shadow: var(--shadow);
494
+ transition: border-color 0.15s;
495
+ }
496
+ .ask-box:focus-within { border-color: var(--accent); }
497
+ .ask-box .icon { color: var(--accent); }
498
+ .ask-box input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; padding: 6px 0; }
499
+ .ask-box input::placeholder { color: var(--faint); }
500
+ .send {
501
+ display: grid;
502
+ place-items: center;
503
+ width: 32px;
504
+ height: 32px;
505
+ border: 0;
506
+ border-radius: 8px;
507
+ background: var(--text);
508
+ color: var(--bg);
509
+ }
510
+ .send:disabled { background: var(--line-2); }
511
+ .ask-wait { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; color: var(--muted); font-size: 14px; }
512
+
513
+ /* Transcript -------------------------------------------------------------- */
514
+
515
+ .t-tools { display: flex; align-items: center; gap: 10px; margin: 16px 0 8px; }
516
+ .t-find {
517
+ display: flex;
518
+ align-items: center;
519
+ gap: 8px;
520
+ flex: 1;
521
+ max-width: 320px;
522
+ padding: 5px 10px;
523
+ border: 1px solid var(--line);
524
+ border-radius: 8px;
525
+ color: var(--faint);
526
+ }
527
+ .t-find:focus-within { border-color: var(--accent); }
528
+ .t-find input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; font-size: 14px; }
529
+ .t-count { font-size: 12.5px; color: var(--muted); }
530
+ .t-info { margin-left: auto; font-size: 12.5px; color: var(--faint); }
531
+ .t-line {
532
+ display: grid;
533
+ grid-template-columns: 64px 1fr;
534
+ gap: 4px 12px;
535
+ padding: 10px 12px;
536
+ margin: 0 -12px;
537
+ border-radius: 8px;
538
+ transition: background 0.3s;
539
+ }
540
+ .t-line.playing { background: var(--accent-soft); }
541
+ .t-line.flash { animation: flash 1.6s ease-out; }
542
+ @keyframes flash { 0%, 30% { background: var(--mark); } 100% { background: transparent; } }
543
+ .t-time {
544
+ border: 0;
545
+ background: none;
546
+ padding: 2px 0 0;
547
+ text-align: left;
548
+ font: 500 12px/1.6 var(--mono);
549
+ color: var(--faint);
550
+ align-self: start;
551
+ }
552
+ .t-time:hover { color: var(--accent-ink); text-decoration: underline; }
553
+ .t-speaker { font-size: 13px; font-weight: 650; margin-bottom: 1px; }
554
+ .t-speaker.me { color: var(--accent-ink); }
555
+ .t-speaker.others { color: var(--text-2); }
556
+ .t-text { color: var(--text); }
557
+
558
+ /* Home -------------------------------------------------------------------- */
559
+
560
+ .hello { margin: 0; font-size: 30px; font-weight: 680; letter-spacing: -0.022em; }
561
+ .today { color: var(--muted); margin-top: 4px; }
562
+ .home-section { margin-top: 36px; }
563
+ .cards { display: grid; gap: 10px; }
564
+ .card {
565
+ display: block;
566
+ padding: 14px 16px;
567
+ border-radius: var(--radius);
568
+ border: 1px solid var(--line);
569
+ background: var(--bg);
570
+ transition: border-color 0.12s, box-shadow 0.12s, transform 0.12s;
571
+ }
572
+ a.card:hover { border-color: var(--line-2); box-shadow: var(--shadow); }
573
+ .card-title { display: flex; align-items: center; gap: 8px; font-weight: 600; }
574
+ .card-title .grow { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
575
+ .card-meta { font-size: 13px; color: var(--muted); margin-top: 2px; }
576
+ .card-preview { font-size: 14px; color: var(--text-2); margin-top: 8px; line-height: 1.5;
577
+ display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
578
+ .event { display: flex; align-items: center; gap: 14px; }
579
+ .event-time { width: 92px; flex: none; font-variant-numeric: tabular-nums; font-size: 13.5px; color: var(--muted); }
580
+ .event-time b { display: block; color: var(--text); font-weight: 600; font-size: 14px; }
581
+ .event-bar { width: 3px; align-self: stretch; border-radius: 3px; background: var(--line-2); }
582
+ .event-bar.call { background: var(--accent); }
583
+ .event.now .event-time b { color: var(--accent-ink); }
584
+ .pill { font-size: 11.5px; font-weight: 600; padding: 1px 8px; border-radius: 999px; background: var(--accent-soft); color: var(--accent-ink); }
585
+ .pill.warn { background: var(--warn-soft); color: var(--warn-ink); }
586
+ .pill.bad { background: var(--rec-soft); color: var(--rec); }
587
+ .pill.cloud { background: var(--warn-soft); color: var(--warn-ink); margin-left: 8px; vertical-align: middle; }
588
+ .pill.local { margin-left: 8px; vertical-align: middle; }
589
+ .qa-meta .pill { margin: 0 6px 0 0; }
590
+ .hint { color: var(--muted); font-size: 14px; }
591
+ .hint code { font: 13px var(--mono); background: var(--hover); padding: 1px 6px; border-radius: 5px; color: var(--text-2); }
592
+ .steps { display: grid; gap: 14px; margin-top: 18px; counter-reset: step; }
593
+ .step { display: flex; gap: 14px; color: var(--text-2); }
594
+ .step::before {
595
+ counter-increment: step;
596
+ content: counter(step);
597
+ display: grid;
598
+ place-items: center;
599
+ width: 26px;
600
+ height: 26px;
601
+ border-radius: 50%;
602
+ background: var(--accent-soft);
603
+ color: var(--accent-ink);
604
+ font-size: 13px;
605
+ font-weight: 650;
606
+ flex: none;
607
+ }
608
+
609
+ /* Player ------------------------------------------------------------------ */
610
+
611
+ .player {
612
+ display: flex;
613
+ align-items: center;
614
+ gap: 8px;
615
+ margin: 0 auto 16px;
616
+ width: min(720px, calc(100% - 48px));
617
+ padding: 8px 14px 8px 10px;
618
+ border: 1px solid var(--line);
619
+ border-radius: 14px;
620
+ background: color-mix(in srgb, var(--bg) 88%, transparent);
621
+ backdrop-filter: blur(12px);
622
+ box-shadow: var(--shadow);
623
+ position: absolute;
624
+ left: 0;
625
+ right: 0;
626
+ bottom: 0;
627
+ }
628
+ .btn-play {
629
+ display: grid;
630
+ place-items: center;
631
+ width: 36px;
632
+ height: 36px;
633
+ border-radius: 50%;
634
+ border: 0;
635
+ background: var(--text);
636
+ color: var(--bg);
637
+ }
638
+ .btn-play .icon { width: 16px; height: 16px; }
639
+ .btn-play.loading .icon { opacity: 0; }
640
+ .btn-play.loading { position: relative; }
641
+ .btn-play.loading::after {
642
+ content: "";
643
+ position: absolute;
644
+ width: 16px;
645
+ height: 16px;
646
+ border-radius: 50%;
647
+ border: 2px solid var(--bg);
648
+ border-right-color: transparent;
649
+ animation: spin 0.8s linear infinite;
650
+ }
651
+ .p-time { font: 500 12.5px var(--mono); color: var(--muted); min-width: 44px; text-align: center; }
652
+ .p-scrub { flex: 1; accent-color: var(--accent); height: 4px; }
653
+
654
+ /* Menus, modal, toast ----------------------------------------------------- */
655
+
656
+ .menu-wrap { position: relative; }
657
+ .menu {
658
+ position: absolute;
659
+ right: 0;
660
+ top: 38px;
661
+ z-index: 20;
662
+ min-width: 230px;
663
+ padding: 6px;
664
+ border-radius: 12px;
665
+ border: 1px solid var(--line);
666
+ background: var(--bg);
667
+ box-shadow: var(--shadow);
668
+ }
669
+ .menu button {
670
+ display: flex;
671
+ align-items: center;
672
+ gap: 10px;
673
+ width: 100%;
674
+ padding: 7px 10px;
675
+ border: 0;
676
+ border-radius: 7px;
677
+ background: none;
678
+ font-size: 13.5px;
679
+ text-align: left;
680
+ }
681
+ .menu button:hover { background: var(--hover); }
682
+ .menu button .icon { width: 16px; height: 16px; color: var(--muted); }
683
+ .menu button.danger { color: var(--rec); }
684
+ .menu button.danger .icon { color: var(--rec); }
685
+ .menu hr { border: 0; border-top: 1px solid var(--line); margin: 5px 4px; }
686
+
687
+ .modal { position: fixed; inset: 0; z-index: 50; display: grid; place-items: center; background: rgb(0 0 0 / 0.28); }
688
+ .dialog { width: min(420px, calc(100% - 32px)); padding: 22px; border-radius: 14px; background: var(--bg); box-shadow: var(--shadow); }
689
+ .dialog h3 { margin: 0 0 6px; font-size: 17px; }
690
+ .dialog p { margin: 0 0 18px; color: var(--muted); font-size: 14px; }
691
+ .dialog .row { display: flex; justify-content: flex-end; gap: 8px; }
692
+
693
+ .toast {
694
+ position: fixed;
695
+ left: 50%;
696
+ bottom: 92px;
697
+ z-index: 60;
698
+ transform: translate(-50%, 12px);
699
+ padding: 9px 16px;
700
+ border-radius: 10px;
701
+ background: var(--text);
702
+ color: var(--bg);
703
+ font-size: 13.5px;
704
+ opacity: 0;
705
+ pointer-events: none;
706
+ transition: opacity 0.18s, transform 0.18s;
707
+ }
708
+ .toast.show { opacity: 1; transform: translate(-50%, 0); }
709
+
710
+ @media (max-width: 860px) {
711
+ .app { grid-template-columns: 1fr; }
712
+ .sidebar { display: none; }
713
+ .page { padding: 28px 20px 140px; }
714
+ }
715
+
716
+ /* Sidebar: record button and sections ------------------------------------ */
717
+
718
+ .record-btn {
719
+ display: flex;
720
+ align-items: center;
721
+ justify-content: center;
722
+ gap: 9px;
723
+ margin: 0 12px 10px;
724
+ padding: 9px 12px;
725
+ border-radius: 9px;
726
+ border: 1px solid var(--line-2);
727
+ background: var(--bg);
728
+ font-size: 14px;
729
+ font-weight: 600;
730
+ transition: background 0.12s, border-color 0.12s, color 0.12s;
731
+ }
732
+ .record-btn:hover { border-color: var(--rec); color: var(--rec); }
733
+ .rec-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--rec); flex: none; }
734
+ .record-btn.recording { background: var(--rec); border-color: var(--rec); color: #fff; }
735
+ .record-btn.recording .rec-dot { background: #fff; border-radius: 2px; }
736
+ .nav { display: grid; gap: 1px; padding: 0 8px 10px; border-bottom: 1px solid var(--line); margin-bottom: 10px; }
737
+ .nav-item {
738
+ display: flex;
739
+ align-items: center;
740
+ gap: 10px;
741
+ padding: 6px 12px;
742
+ border-radius: 8px;
743
+ font-size: 14px;
744
+ font-weight: 520;
745
+ color: var(--text-2);
746
+ }
747
+ .nav-item .icon { width: 17px; height: 17px; color: var(--muted); }
748
+ .nav-item:hover { background: var(--hover); }
749
+ .nav-item.active { background: var(--active); color: var(--text); }
750
+ .nav-count {
751
+ margin-left: auto;
752
+ min-width: 20px;
753
+ padding: 0 6px;
754
+ border-radius: 999px;
755
+ background: var(--accent-soft);
756
+ color: var(--accent-ink);
757
+ font-size: 12px;
758
+ font-weight: 650;
759
+ text-align: center;
760
+ }
761
+ .nav-count:empty { display: none; }
762
+
763
+ /* Speakers ---------------------------------------------------------------- */
764
+
765
+ .speakers { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
766
+ .speaker-chip {
767
+ display: inline-flex;
768
+ align-items: center;
769
+ gap: 7px;
770
+ padding: 3px 10px 3px 3px;
771
+ border-radius: 999px;
772
+ border: 1px solid var(--line);
773
+ background: var(--bg);
774
+ font-size: 13px;
775
+ color: var(--text-2);
776
+ transition: border-color 0.12s, background 0.12s;
777
+ }
778
+ button.speaker-chip:hover { border-color: var(--line-2); background: var(--hover); }
779
+ .speaker-chip .share { color: var(--faint); font-variant-numeric: tabular-nums; font-size: 12px; }
780
+ .speaker-chip.unnamed { border-style: dashed; }
781
+ .speaker-chip .icon { width: 13px; height: 13px; color: var(--faint); }
782
+ .speakers-hint { font-size: 12.5px; color: var(--faint); align-self: center; }
783
+ button.t-speaker { border: 0; background: none; padding: 0; text-align: left; cursor: pointer; }
784
+ button.t-speaker:hover { text-decoration: underline; text-underline-offset: 3px; }
785
+
786
+ /* Your notes -------------------------------------------------------------- */
787
+
788
+ .mynotes {
789
+ margin-top: 26px;
790
+ border: 1px solid var(--line);
791
+ border-radius: 12px;
792
+ background: var(--panel);
793
+ transition: border-color 0.15s, box-shadow 0.15s;
794
+ }
795
+ .mynotes:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
796
+ .mynotes-head {
797
+ display: flex;
798
+ align-items: center;
799
+ gap: 8px;
800
+ padding: 10px 14px 0;
801
+ font-size: 12px;
802
+ font-weight: 650;
803
+ letter-spacing: 0.06em;
804
+ text-transform: uppercase;
805
+ color: var(--muted);
806
+ }
807
+ .mynotes-head .icon { width: 15px; height: 15px; }
808
+ .mynotes-head .saved { margin-left: auto; font-size: 12px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--faint); }
809
+ .mynotes textarea {
810
+ display: block;
811
+ width: 100%;
812
+ min-height: 96px;
813
+ padding: 8px 14px 14px;
814
+ border: 0;
815
+ outline: 0;
816
+ resize: none;
817
+ background: transparent;
818
+ color: var(--text);
819
+ font: inherit;
820
+ line-height: 1.6;
821
+ }
822
+ .mynotes textarea::placeholder { color: var(--faint); }
823
+ .mynotes.big textarea { min-height: 320px; font-size: 16px; }
824
+ .live-head { display: flex; align-items: center; gap: 12px; margin-top: 18px; color: var(--rec); font-weight: 600; }
825
+ .live-head .clock { font-variant-numeric: tabular-nums; color: var(--text); font-size: 15px; }
826
+ .live-tip { margin-top: 10px; color: var(--muted); font-size: 13.5px; }
827
+
828
+ /* Dialog form ------------------------------------------------------------- */
829
+
830
+ .dialog.wide { width: min(520px, calc(100% - 32px)); }
831
+ .field { display: grid; gap: 6px; margin-bottom: 14px; }
832
+ .field label { font-size: 13px; font-weight: 600; color: var(--text-2); }
833
+ .field input[type="text"], .field input[type="password"], .field select, .field textarea {
834
+ width: 100%;
835
+ padding: 8px 11px;
836
+ border: 1px solid var(--line-2);
837
+ border-radius: 8px;
838
+ background: var(--bg);
839
+ color: var(--text);
840
+ font: inherit;
841
+ outline: none;
842
+ }
843
+ .field input:focus, .field select:focus, .field textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
844
+ .field textarea { min-height: 260px; resize: vertical; line-height: 1.55; }
845
+ .check-row { display: flex; align-items: center; gap: 8px; font-size: 13.5px; color: var(--text-2); margin-bottom: 14px; }
846
+ .check-row input { accent-color: var(--accent); width: 16px; height: 16px; }
847
+ .suggest { display: flex; flex-wrap: wrap; gap: 6px; }
848
+ .suggest button { border: 1px solid var(--line-2); background: var(--bg); border-radius: 999px; padding: 2px 10px; font-size: 12.5px; color: var(--text-2); }
849
+ .suggest button:hover { border-color: var(--accent); color: var(--accent-ink); }
850
+ .evidence { font-size: 12.5px; color: var(--muted); margin: -6px 0 14px; }
851
+ .merge-list { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 18px; }
852
+ .dialog .sub { margin: 4px 0 8px; font-size: 13px; font-weight: 600; color: var(--text-2); }
853
+
854
+ /* Tasks, ask, settings pages ---------------------------------------------- */
855
+
856
+ .page-title { margin: 0; font-size: 28px; font-weight: 680; letter-spacing: -0.02em; }
857
+ .page-sub { color: var(--muted); margin-top: 4px; }
858
+ .task-row { position: relative; display: flex; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--line); }
859
+ .task-row .a-meta a { color: var(--muted); font-size: 12.5px; }
860
+ .task-row .a-meta a:hover { color: var(--text); text-decoration: underline; }
861
+ .task-row.done .a-task { color: var(--faint); text-decoration: line-through; }
862
+ .task-row.done .check { background: var(--accent); border-color: var(--accent); color: #fff; }
863
+ .toggle-done { margin-top: 14px; }
864
+ .big-ask { margin-top: 22px; }
865
+ .big-ask .ask-box { padding: 8px 8px 8px 16px; }
866
+ .big-ask input { font-size: 16px; }
867
+ .cite.call { font-family: var(--font); }
868
+ .examples { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
869
+ .examples button { border: 1px solid var(--line); background: var(--bg); border-radius: 999px; padding: 4px 12px; font-size: 13px; color: var(--text-2); }
870
+ .examples button:hover { border-color: var(--accent); color: var(--accent-ink); }
871
+ .settings-card { margin-top: 18px; padding: 18px 20px; border: 1px solid var(--line); border-radius: 12px; }
872
+ .settings-card h2 { margin: 0 0 4px; font-size: 15px; font-weight: 650; }
873
+ .settings-card p { margin: 0 0 12px; color: var(--muted); font-size: 13.5px; }
874
+ .settings-card textarea { width: 100%; min-height: 130px; padding: 10px 12px; border: 1px solid var(--line-2); border-radius: 8px; background: var(--bg); color: var(--text); font: 14px/1.55 var(--font); resize: vertical; outline: none; }
875
+ .settings-card textarea:focus { border-color: var(--accent); }
876
+ .kv { display: grid; grid-template-columns: 170px 1fr; gap: 6px 12px; font-size: 14px; }
877
+ .kv dt { color: var(--muted); }
878
+ .kv dd { margin: 0; }
879
+ .voice-row { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--line); font-size: 14px; }
880
+ .voice-row:last-child { border-bottom: 0; }
881
+ .voice-row .grow { flex: 1; }
882
+ .voice-row .muted { color: var(--faint); font-size: 12.5px; }
883
+ .row-end { display: flex; justify-content: flex-end; gap: 8px; margin-top: 10px; }
884
+ .settings-card .field textarea.short { min-height: 64px; }
885
+ .settings-card .row-end + .kv { margin-top: 16px; }
886
+ .field .inline { display: flex; gap: 8px; }
887
+ .field .inline input { flex: 1; min-width: 0; }
888
+ .inline-add { margin: 12px 0 0; }
889
+
890
+ /* Login page */
891
+ .login { max-width: 34rem; margin: 18vh auto 0; padding: 0 16px; text-align: center; }
892
+ .login h1 { font-size: 1.4rem; margin: 1rem 0 .5rem; }
893
+ .login code { padding: 0 .3em; border-radius: 4px; background: var(--bg-soft, rgba(127,127,127,.15)); }
894
+
895
+ /* Setup check and footer */
896
+ .doctor-checks { list-style: none; margin: 0; padding: 0; }
897
+ .doctor-check { display: flex; gap: 10px; align-items: baseline; padding: 6px 0; border-bottom: 1px solid var(--line, rgba(127,127,127,.18)); }
898
+ .doctor-check:last-child { border-bottom: 0; }
899
+ .doctor-check .grow { flex: 1; min-width: 0; }
900
+ .check-mark { width: 1.2em; text-align: center; font-weight: 700; }
901
+ .doctor-check.ok .check-mark { color: var(--accent-ink); }
902
+ .doctor-check.warn .check-mark { color: var(--warn-ink); }
903
+ .doctor-check.bad .check-mark { color: var(--rec); }
904
+ .check-fix { display: block; margin-top: 4px; font: 12px/1.4 ui-monospace, monospace; padding: 2px 6px; border-radius: 4px; border: 1px solid var(--line, rgba(127,127,127,.25)); background: transparent; color: inherit; cursor: pointer; text-align: left; }
905
+ .setup-check { border: 1px solid var(--rec-soft); border-radius: 10px; padding: 12px 16px; }
906
+ .about { font-size: 11.5px; opacity: .65; padding: 8px 12px 12px; }
907
+ .about a { color: inherit; }