@lelouchhe/webagent 0.3.0 → 0.5.1

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 (61) hide show
  1. package/README.md +59 -23
  2. package/bin/webagent.mjs +119 -8
  3. package/config.toml +105 -3
  4. package/dist/fonts/temml/Temml.woff2 +0 -0
  5. package/dist/index.html +64 -41
  6. package/dist/js/app.3OEVQXHK.js +4 -0
  7. package/dist/js/chunk.AJZBJBMO.js +1 -0
  8. package/dist/js/chunk.D4ZYHJAM.js +1 -0
  9. package/dist/js/chunk.IJM5DBCO.js +173 -0
  10. package/dist/js/chunk.VZXGXFNN.js +5 -0
  11. package/dist/js/login.PYIK52HN.js +1 -0
  12. package/dist/js/viewer.FCSSTUVY.js +1 -0
  13. package/dist/login.html +49 -0
  14. package/dist/share-viewer.00gubshk.css +114 -0
  15. package/dist/share-viewer.html +54 -0
  16. package/dist/styles.00xfh3e6.css +1848 -0
  17. package/dist/sw.js +79 -27
  18. package/dist/theme-init.js +6 -0
  19. package/lib/agent-detect.js +110 -0
  20. package/lib/atomic-write.js +50 -0
  21. package/lib/attachment-dispatch.js +86 -0
  22. package/lib/attachment-interceptor.js +130 -0
  23. package/lib/attachment-labels.js +139 -0
  24. package/lib/attachments.js +154 -0
  25. package/lib/auth-middleware.js +105 -0
  26. package/lib/auth-store.js +269 -0
  27. package/lib/auth.js +89 -0
  28. package/lib/bootstrap.js +70 -0
  29. package/lib/bridge-event-config.js +29 -0
  30. package/lib/bridge.js +244 -93
  31. package/lib/client-registry.js +149 -0
  32. package/lib/config.js +130 -9
  33. package/lib/daemon.js +175 -41
  34. package/lib/event-handler.js +209 -91
  35. package/lib/image-dimensions.js +64 -0
  36. package/lib/log-fmt.js +67 -0
  37. package/lib/log.js +83 -0
  38. package/lib/message-cleanup.js +48 -0
  39. package/lib/mode-bucket.js +62 -0
  40. package/lib/model-picker.js +17 -0
  41. package/lib/preflight.js +214 -0
  42. package/lib/push-service.js +297 -52
  43. package/lib/routes.js +1315 -145
  44. package/lib/server.js +149 -37
  45. package/lib/session-manager.js +164 -18
  46. package/lib/session-state.js +160 -0
  47. package/lib/sessions-anchor.js +28 -0
  48. package/lib/share/cleanup.js +45 -0
  49. package/lib/share/routes.js +972 -0
  50. package/lib/share/sanitize.js +179 -0
  51. package/lib/sse-manager.js +94 -8
  52. package/lib/sse-ticket.js +45 -0
  53. package/lib/startup-checks.js +95 -0
  54. package/lib/store.js +636 -30
  55. package/lib/title-service.js +26 -9
  56. package/lib/tokens.js +50 -0
  57. package/lib/types.js +23 -0
  58. package/package.json +39 -4
  59. package/dist/js/app.2562YGRO.js +0 -10
  60. package/dist/styles.008ve1hx.css +0 -669
  61. package/lib/shared/constants.js +0 -17
@@ -0,0 +1,1848 @@
1
+ :root {
2
+ --bg: #0d1117;
3
+ --surface: #161b22;
4
+ --border: #30363d;
5
+ --text: #c9d1d9;
6
+ --text-dim: #6e7681;
7
+ --accent: #58a6ff;
8
+ --green: #3fb950;
9
+ --yellow: #d29922;
10
+ --red: #f85149;
11
+ --blue: #58a6ff;
12
+ --radius: 4px;
13
+ --user-bg: #1e3a5f;
14
+ --code-bg: #0d2818;
15
+ --permission-bg: #1c1305;
16
+ --permission-title: #d29922;
17
+ --accent-soft: rgba(88, 166, 255, 0.18);
18
+ --user-image-max-width: 200px;
19
+ --user-image-max-height: 150px;
20
+ }
21
+ [data-theme="light"] {
22
+ --bg: #ffffff;
23
+ --surface: #f6f8fa;
24
+ --border: #d0d7de;
25
+ --text: #1f2328;
26
+ --text-dim: #656d76;
27
+ --accent: #0969da;
28
+ --green: #1a7f37;
29
+ --yellow: #9a6700;
30
+ --red: #cf222e;
31
+ --blue: #0969da;
32
+ --user-bg: #ddf4ff;
33
+ --code-bg: #f0faf0;
34
+ --permission-bg: #fff4cc;
35
+ --permission-title: #7a4f00;
36
+ --accent-soft: rgba(9, 105, 218, 0.14);
37
+ }
38
+ @media (prefers-color-scheme: light) {
39
+ [data-theme="auto"] {
40
+ --bg: #ffffff;
41
+ --surface: #f6f8fa;
42
+ --border: #d0d7de;
43
+ --text: #1f2328;
44
+ --text-dim: #656d76;
45
+ --accent: #0969da;
46
+ --green: #1a7f37;
47
+ --yellow: #9a6700;
48
+ --red: #cf222e;
49
+ --blue: #0969da;
50
+ --user-bg: #ddf4ff;
51
+ --code-bg: #f0faf0;
52
+ --permission-bg: #fff4cc;
53
+ --permission-title: #7a4f00;
54
+ --accent-soft: rgba(9, 105, 218, 0.14);
55
+ }
56
+ }
57
+ * {
58
+ box-sizing: border-box;
59
+ margin: 0;
60
+ padding: 0;
61
+ }
62
+ body {
63
+ font-family: "SF Mono", "Fira Code", "Cascadia Code", "Consolas", monospace;
64
+ background: var(--bg);
65
+ color: var(--text);
66
+ height: 100dvh;
67
+ display: flex;
68
+ flex-direction: column;
69
+ font-size: 16px;
70
+ }
71
+
72
+ /* Header */
73
+ #header {
74
+ padding: 6px 16px;
75
+ background: var(--surface);
76
+ border-bottom: 1px solid var(--border);
77
+ display: grid;
78
+ grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1fr);
79
+ align-items: center;
80
+ gap: 12px;
81
+ font-size: 15px;
82
+ }
83
+ #header .logo {
84
+ font-weight: bold;
85
+ color: var(--green);
86
+ }
87
+ .header-side {
88
+ min-width: 0;
89
+ display: flex;
90
+ align-items: center;
91
+ }
92
+ .header-left {
93
+ justify-content: flex-start;
94
+ }
95
+ .header-right {
96
+ justify-content: flex-end;
97
+ gap: 12px;
98
+ }
99
+ #header .status {
100
+ color: var(--text-dim);
101
+ }
102
+ #status {
103
+ width: 12px;
104
+ height: 12px;
105
+ display: inline-block;
106
+ flex: 0 0 auto;
107
+ border-radius: 999px;
108
+ border: 2px solid transparent;
109
+ background: transparent;
110
+ }
111
+ #status.is-disconnected {
112
+ background: var(--red);
113
+ border-color: var(--red);
114
+ }
115
+ #status.is-connected {
116
+ background: var(--green);
117
+ border-color: var(--green);
118
+ }
119
+ #status.is-connecting {
120
+ border-color: var(--yellow);
121
+ animation: status-pulse 1.2s ease-in-out infinite;
122
+ }
123
+ @keyframes status-pulse {
124
+ 0%,
125
+ 100% {
126
+ background: transparent;
127
+ opacity: 0.9;
128
+ }
129
+ 50% {
130
+ background: var(--yellow);
131
+ opacity: 1;
132
+ }
133
+ }
134
+ #session-info {
135
+ overflow: hidden;
136
+ text-overflow: ellipsis;
137
+ white-space: nowrap;
138
+ min-width: 0;
139
+ width: 100%;
140
+ text-align: center;
141
+ }
142
+ #theme-btn {
143
+ background: transparent;
144
+ border: none;
145
+ color: var(--text-dim);
146
+ cursor: pointer;
147
+ font-size: 15px;
148
+ font-family: inherit;
149
+ padding: 2px 6px;
150
+ }
151
+ #theme-btn:hover {
152
+ color: var(--text);
153
+ }
154
+ @media (max-width: 640px) {
155
+ #header {
156
+ display: flex;
157
+ gap: 8px;
158
+ }
159
+ .header-left,
160
+ .header-right {
161
+ flex: 0 0 auto;
162
+ }
163
+ .header-right {
164
+ margin-left: auto;
165
+ }
166
+ #session-info {
167
+ flex: 1 1 auto;
168
+ text-align: left;
169
+ }
170
+ }
171
+
172
+ /* Messages */
173
+ #messages {
174
+ flex: 1;
175
+ overflow-y: auto;
176
+ padding: 16px;
177
+ display: flex;
178
+ flex-direction: column;
179
+ gap: 4px;
180
+ }
181
+ #messages > * {
182
+ min-width: 0;
183
+ max-width: 100%;
184
+ overflow-wrap: break-word;
185
+ }
186
+ .msg {
187
+ padding: 8px 14px;
188
+ line-height: 1.6;
189
+ font-size: 16px;
190
+ overflow-wrap: break-word;
191
+ }
192
+ .msg.user {
193
+ background: var(--user-bg);
194
+ border-left: 3px solid var(--accent);
195
+ border-radius: 0 var(--radius) var(--radius) 0;
196
+ margin: 8px 0 4px 0;
197
+ font-weight: 500;
198
+ }
199
+ .msg.user::before {
200
+ content: "▶ ";
201
+ color: var(--accent);
202
+ font-weight: bold;
203
+ }
204
+ .msg.assistant {
205
+ padding: 4px 14px;
206
+ }
207
+ .msg.assistant pre {
208
+ background: none;
209
+ padding: 8px 14px;
210
+ overflow-x: auto;
211
+ margin: 0;
212
+ font-size: 15px;
213
+ border-radius: 0;
214
+ }
215
+ .msg.assistant code {
216
+ font-family: "SF Mono", "Fira Code", monospace;
217
+ font-size: 15px;
218
+ }
219
+
220
+ /* Code block wrapper — aligned with prompt/permission/thinking style */
221
+ .code-block-wrapper {
222
+ margin: 8px -14px;
223
+ background: var(--code-bg);
224
+ border-left: 3px solid var(--green);
225
+ border-radius: 0 var(--radius) var(--radius) 0;
226
+ position: relative;
227
+ overflow: hidden;
228
+ }
229
+ .code-block-wrapper pre {
230
+ margin: 0;
231
+ padding: 8px 14px;
232
+ }
233
+ .code-block-wrapper pre code,
234
+ .code-block-wrapper pre code.hljs {
235
+ background: none;
236
+ padding: 0;
237
+ }
238
+ .code-toolbar {
239
+ display: flex;
240
+ align-items: center;
241
+ justify-content: flex-end;
242
+ padding: 2px 6px;
243
+ position: absolute;
244
+ top: 0;
245
+ right: 0;
246
+ z-index: 1;
247
+ font-size: 12px;
248
+ color: var(--text-dim);
249
+ gap: 8px;
250
+ opacity: 0;
251
+ transition: opacity 0.15s;
252
+ }
253
+ .code-block-wrapper:hover .code-toolbar {
254
+ opacity: 1;
255
+ }
256
+ .copy-btn {
257
+ background: transparent;
258
+ color: var(--text-dim);
259
+ border: 1px solid var(--border);
260
+ border-radius: var(--radius);
261
+ min-width: 28px;
262
+ height: 22px;
263
+ padding: 0 4px;
264
+ font-size: 12px;
265
+ font-family: inherit;
266
+ cursor: pointer;
267
+ display: inline-flex;
268
+ align-items: center;
269
+ justify-content: center;
270
+ line-height: 1;
271
+ transition:
272
+ color 0.15s,
273
+ border-color 0.15s;
274
+ }
275
+ .copy-btn:hover {
276
+ color: var(--text);
277
+ border-color: var(--text-dim);
278
+ }
279
+ .copy-btn.copied {
280
+ color: var(--green);
281
+ border-color: var(--green);
282
+ }
283
+ .msg.assistant p {
284
+ margin: 4px 0;
285
+ }
286
+ .msg.assistant ul,
287
+ .msg.assistant ol {
288
+ padding-left: 20px;
289
+ margin: 4px 0;
290
+ }
291
+ .msg.assistant table {
292
+ border-collapse: collapse;
293
+ margin: 8px 0;
294
+ font-family: inherit;
295
+ font-size: inherit;
296
+ line-height: 1.5;
297
+ display: block;
298
+ overflow-x: auto;
299
+ max-width: 100%;
300
+ }
301
+ .msg.assistant th,
302
+ .msg.assistant td {
303
+ border: 1px solid var(--border);
304
+ padding: 5px 12px;
305
+ text-align: left;
306
+ vertical-align: top;
307
+ }
308
+ .msg.assistant th {
309
+ color: var(--green);
310
+ border-color: var(--green);
311
+ font-weight: normal;
312
+ }
313
+
314
+ /* Thinking */
315
+ .thinking {
316
+ color: var(--text-dim);
317
+ font-style: italic;
318
+ font-size: 15px;
319
+ padding: 6px 14px;
320
+ border-left: 2px solid var(--border);
321
+ }
322
+ .thinking summary {
323
+ cursor: pointer;
324
+ }
325
+ .thinking-content {
326
+ cursor: default;
327
+ }
328
+ .thinking summary.active {
329
+ animation: pulse 1.5s ease-in-out infinite;
330
+ }
331
+
332
+ /* Inbox message card — same collapsible feel as .thinking but with accent. */
333
+ .message {
334
+ color: var(--text);
335
+ font-size: 15px;
336
+ padding: 6px 14px;
337
+ border-left: 2px solid var(--accent-muted, var(--accent));
338
+ margin: 6px 0;
339
+ }
340
+ .message summary {
341
+ cursor: pointer;
342
+ color: var(--text-dim);
343
+ font-size: 13px;
344
+ font-style: italic;
345
+ }
346
+ .message-content {
347
+ cursor: default;
348
+ margin-top: 4px;
349
+ }
350
+
351
+ /* Waiting indicator (after user sends, before first response) */
352
+ @keyframes blink {
353
+ 0%,
354
+ 100% {
355
+ opacity: 1;
356
+ }
357
+ 50% {
358
+ opacity: 0.3;
359
+ }
360
+ }
361
+ @keyframes pulse {
362
+ 0%,
363
+ 100% {
364
+ opacity: 1;
365
+ }
366
+ 50% {
367
+ opacity: 0.4;
368
+ }
369
+ }
370
+ #waiting {
371
+ padding: 6px 14px;
372
+ color: var(--text-dim);
373
+ font-size: 15px;
374
+ }
375
+ #waiting .cursor {
376
+ animation: blink 1s step-end infinite;
377
+ }
378
+
379
+ /* System messages */
380
+ .system-msg {
381
+ font-size: 15px;
382
+ padding: 2px 14px;
383
+ color: var(--text-dim);
384
+ white-space: pre-wrap;
385
+ }
386
+ .system-msg a {
387
+ color: var(--accent);
388
+ text-decoration: underline;
389
+ word-break: break-all;
390
+ }
391
+ .system-msg a:hover {
392
+ color: var(--text);
393
+ }
394
+
395
+ /* Tool calls */
396
+ .tool-call {
397
+ font-size: 15px;
398
+ padding: 2px 14px;
399
+ color: var(--text-dim);
400
+ animation: pulse 1.5s ease-in-out infinite;
401
+ }
402
+ .tool-call .icon {
403
+ margin-right: 4px;
404
+ }
405
+ .tool-call.completed {
406
+ color: var(--green);
407
+ animation: none;
408
+ }
409
+ .tool-call.failed {
410
+ color: var(--red);
411
+ animation: none;
412
+ }
413
+ .tool-call {
414
+ cursor: pointer;
415
+ }
416
+ .tool-call .tc-detail {
417
+ display: block;
418
+ color: var(--text-dim);
419
+ white-space: nowrap;
420
+ overflow: hidden;
421
+ text-overflow: ellipsis;
422
+ max-width: 100%;
423
+ }
424
+ .tool-call .tc-detail.expanded {
425
+ white-space: pre-wrap;
426
+ overflow: visible;
427
+ text-overflow: unset;
428
+ }
429
+ .tool-call details {
430
+ margin-top: 2px;
431
+ }
432
+ .tool-call details summary {
433
+ cursor: pointer;
434
+ color: var(--text-dim);
435
+ }
436
+ .tool-call .tc-content {
437
+ margin: 4px 0 4px 16px;
438
+ padding: 6px 10px;
439
+ background: var(--code-bg);
440
+ border-radius: var(--radius);
441
+ font-size: 14px;
442
+ white-space: pre-wrap;
443
+ max-height: 200px;
444
+ overflow-y: auto;
445
+ color: var(--text);
446
+ cursor: default;
447
+ }
448
+ .tool-call .tc-summary {
449
+ margin: 4px 0 4px 16px;
450
+ font-size: 14px;
451
+ color: var(--text);
452
+ }
453
+
454
+ /* Diff view for edit tool calls */
455
+ .diff-view {
456
+ margin: 4px 0 4px 16px;
457
+ padding: 6px 10px;
458
+ background: var(--code-bg);
459
+ border-radius: var(--radius);
460
+ font-size: 13px;
461
+ font-family: monospace;
462
+ white-space: pre-wrap;
463
+ word-break: break-all;
464
+ max-height: 300px;
465
+ overflow-y: auto;
466
+ line-height: 1.4;
467
+ cursor: default;
468
+ }
469
+ .diff-view .diff-file {
470
+ color: var(--blue);
471
+ font-weight: bold;
472
+ }
473
+ .diff-view .diff-hunk {
474
+ color: var(--text-dim);
475
+ }
476
+ .diff-view .diff-del {
477
+ color: var(--red);
478
+ }
479
+ .diff-view .diff-add {
480
+ color: var(--green);
481
+ }
482
+
483
+ /* Plan */
484
+ .plan {
485
+ font-size: 15px;
486
+ padding: 6px 14px;
487
+ border-left: 3px solid var(--blue);
488
+ border-radius: 0 var(--radius) var(--radius) 0;
489
+ }
490
+ .plan-summary {
491
+ color: var(--blue);
492
+ font-weight: bold;
493
+ margin-bottom: 2px;
494
+ cursor: pointer;
495
+ }
496
+ .plan-counts {
497
+ color: var(--text-dim);
498
+ font-weight: normal;
499
+ margin-left: 14px;
500
+ }
501
+ .plan-entries {
502
+ margin-top: 2px;
503
+ }
504
+ .plan-entry {
505
+ padding: 1px 0;
506
+ }
507
+
508
+ /* Permission dialog */
509
+ .permission {
510
+ background: var(--permission-bg);
511
+ border-left: 3px solid var(--yellow);
512
+ border-radius: 0 var(--radius) var(--radius) 0;
513
+ padding: 8px 14px;
514
+ font-size: 15px;
515
+ }
516
+ .permission .title {
517
+ color: var(--permission-title);
518
+ font-weight: bold;
519
+ margin-bottom: 6px;
520
+ }
521
+ .permission button {
522
+ margin: 2px 4px 2px 0;
523
+ padding: 4px 10px;
524
+ border: 1px solid var(--border);
525
+ border-radius: var(--radius);
526
+ background: transparent;
527
+ color: var(--text);
528
+ cursor: pointer;
529
+ font-size: 14px;
530
+ font-family: inherit;
531
+ }
532
+ .permission button:hover {
533
+ background: var(--surface);
534
+ }
535
+ .permission button.allow {
536
+ border-color: var(--green);
537
+ }
538
+ .permission button.deny {
539
+ border-color: var(--red);
540
+ }
541
+
542
+ /* Bash command output */
543
+ .bash-block {
544
+ margin: 2px 0;
545
+ padding: 2px 14px;
546
+ font-size: 15px;
547
+ min-width: 0;
548
+ overflow-wrap: break-word;
549
+ }
550
+ .bash-block .bash-cmd {
551
+ color: var(--green);
552
+ font-family: monospace;
553
+ font-size: 14px;
554
+ cursor: pointer;
555
+ overflow-wrap: break-word;
556
+ }
557
+ .bash-block .bash-cmd::before {
558
+ content: "$ ";
559
+ color: var(--text-dim);
560
+ }
561
+ .bash-block .bash-cmd.running {
562
+ animation: pulse 1.5s ease-in-out infinite;
563
+ }
564
+ .bash-block .bash-output {
565
+ margin: 4px 0 4px 0;
566
+ padding: 6px 10px;
567
+ background: var(--code-bg);
568
+ border-radius: var(--radius);
569
+ font-size: 13px;
570
+ font-family: monospace;
571
+ white-space: pre-wrap;
572
+ word-break: break-all;
573
+ max-height: 400px;
574
+ overflow-y: auto;
575
+ color: var(--text);
576
+ line-height: 1.4;
577
+ display: none;
578
+ }
579
+ .bash-block .bash-output.has-content {
580
+ display: block;
581
+ }
582
+ .bash-block .bash-output .stderr {
583
+ color: var(--red);
584
+ }
585
+ .bash-block .bash-exit {
586
+ font-size: 13px;
587
+ color: var(--text-dim);
588
+ margin-left: 8px;
589
+ }
590
+ .bash-block .bash-exit.ok {
591
+ color: var(--green);
592
+ }
593
+ .bash-block .bash-exit.fail {
594
+ color: var(--red);
595
+ }
596
+
597
+ /* Input */
598
+ #input-area {
599
+ position: relative;
600
+ padding: 8px 16px 4px;
601
+ background: var(--bg);
602
+ border-top: 1px solid var(--border);
603
+ display: flex;
604
+ align-items: center;
605
+ gap: 4px;
606
+ transition: border-color 0.15s;
607
+ }
608
+ #input-area.bash-mode {
609
+ border-top: 2px solid #e8872b;
610
+ }
611
+ #input-area.bash-mode #input-prompt {
612
+ --prompt-color: #e8872b;
613
+ color: var(--prompt-color);
614
+ }
615
+ #input-area.bash-mode #input {
616
+ color: #e8872b;
617
+ }
618
+ #input-area.plan-mode {
619
+ border-top: 2px solid var(--green);
620
+ }
621
+ #input-area.plan-mode #input-prompt {
622
+ --prompt-color: var(--green);
623
+ color: var(--prompt-color);
624
+ }
625
+ #input-area.plan-mode #mode-pill {
626
+ color: var(--green);
627
+ }
628
+ #input-area.autopilot-mode {
629
+ border-top: 2px solid var(--red);
630
+ }
631
+ #input-area.autopilot-mode #input-prompt {
632
+ --prompt-color: var(--red);
633
+ color: var(--prompt-color);
634
+ }
635
+ #input-area.autopilot-mode #mode-pill {
636
+ color: var(--red);
637
+ }
638
+ #input-area.preview-mode {
639
+ border-top: 2px solid var(--blue);
640
+ }
641
+ #input-area.preview-mode #input-prompt {
642
+ --prompt-color: var(--blue);
643
+ color: var(--prompt-color);
644
+ }
645
+ #input-area.preview-mode #mode-pill {
646
+ color: var(--blue);
647
+ }
648
+ /* Mode pill: JS writes the actual mode name (#plan, autopilot, default,
649
+ acceptEdits, etc.) into textContent. The :empty selector hides the
650
+ element when there's no mode to show (e.g. before configOptions land).
651
+ Color comes from the bucket-specific rules above; default is dim. */
652
+ #mode-pill {
653
+ position: absolute;
654
+ top: -7px;
655
+ left: 16px;
656
+ font-size: 10px;
657
+ line-height: 1;
658
+ padding: 0 4px;
659
+ background: var(--bg);
660
+ color: var(--text-dim);
661
+ text-transform: uppercase;
662
+ letter-spacing: 0.5px;
663
+ }
664
+ #mode-pill:empty {
665
+ display: none;
666
+ }
667
+ #status-bar {
668
+ display: flex;
669
+ padding: 0 16px 10px;
670
+ background: var(--bg);
671
+ color: var(--text-dim);
672
+ font-size: 11px;
673
+ line-height: 1.4;
674
+ white-space: nowrap;
675
+ user-select: none;
676
+ }
677
+ #status-bar::before {
678
+ content: "\200b";
679
+ }
680
+ #status-bar .status-cwd {
681
+ overflow: hidden;
682
+ text-overflow: ellipsis;
683
+ direction: rtl;
684
+ text-align: left;
685
+ }
686
+ #input-prompt {
687
+ --prompt-color: var(--text);
688
+ color: var(--prompt-color);
689
+ font-weight: bold;
690
+ user-select: none;
691
+ line-height: 1.5;
692
+ cursor: pointer;
693
+ }
694
+ #input-prompt::before {
695
+ content: "❯ ";
696
+ }
697
+ #input-prompt.busy::before {
698
+ content: "⠋ ";
699
+ animation: spinner 0.8s steps(1) infinite;
700
+ }
701
+ #input {
702
+ flex: 1;
703
+ background: transparent;
704
+ color: var(--text);
705
+ border: none;
706
+ padding: 4px 8px;
707
+ font-size: 16px;
708
+ font-family: inherit;
709
+ resize: none;
710
+ min-height: 28px;
711
+ max-height: 200px;
712
+ line-height: 1.5;
713
+ }
714
+ #input:focus {
715
+ outline: none;
716
+ }
717
+ .input-btn {
718
+ background: transparent;
719
+ color: var(--text-dim);
720
+ border: 1px solid var(--border);
721
+ border-radius: var(--radius);
722
+ width: 34px;
723
+ height: 28px;
724
+ padding: 0 6px;
725
+ font-size: 14px;
726
+ font-family: inherit;
727
+ cursor: pointer;
728
+ display: inline-flex;
729
+ align-items: center;
730
+ justify-content: center;
731
+ line-height: 1;
732
+ flex: 0 0 auto;
733
+ }
734
+ .input-btn:hover {
735
+ color: var(--text);
736
+ border-color: var(--text-dim);
737
+ }
738
+ #send-btn.cancel {
739
+ color: var(--red);
740
+ border-color: var(--red);
741
+ font-weight: bold;
742
+ }
743
+ #send-btn.cancel:hover,
744
+ #send-btn.cancel:focus,
745
+ #send-btn.cancel:active {
746
+ color: var(--red);
747
+ border-color: var(--red);
748
+ }
749
+ .input-btn.publish {
750
+ color: var(--blue);
751
+ border-color: var(--blue);
752
+ font-weight: bold;
753
+ }
754
+ .input-btn.publish:hover,
755
+ .input-btn.publish:focus,
756
+ .input-btn.publish:active {
757
+ color: var(--blue);
758
+ border-color: var(--blue);
759
+ }
760
+ #input-area.preview-mode #input {
761
+ opacity: 0.5;
762
+ cursor: not-allowed;
763
+ }
764
+ @keyframes spinner {
765
+ 0% {
766
+ content: "⠋";
767
+ }
768
+ 10% {
769
+ content: "⠙";
770
+ }
771
+ 20% {
772
+ content: "⠹";
773
+ }
774
+ 30% {
775
+ content: "⠸";
776
+ }
777
+ 40% {
778
+ content: "⠼";
779
+ }
780
+ 50% {
781
+ content: "⠴";
782
+ }
783
+ 60% {
784
+ content: "⠦";
785
+ }
786
+ 70% {
787
+ content: "⠧";
788
+ }
789
+ 80% {
790
+ content: "⠇";
791
+ }
792
+ 90% {
793
+ content: "⠏";
794
+ }
795
+ }
796
+
797
+ /* Slash command autocomplete */
798
+ #slash-menu {
799
+ display: none;
800
+ position: absolute;
801
+ bottom: 100%;
802
+ left: 0;
803
+ right: 0;
804
+ background: var(--surface);
805
+ border: 1px solid var(--border);
806
+ border-bottom: none;
807
+ max-height: 220px;
808
+ overflow-y: auto;
809
+ z-index: 10;
810
+ }
811
+ #slash-menu.active {
812
+ display: block;
813
+ }
814
+
815
+ .slash-item {
816
+ padding: 6px 6px;
817
+ cursor: pointer;
818
+ font-size: 15px;
819
+ display: flex;
820
+ flex-direction: column;
821
+ gap: 2px;
822
+ width: max-content;
823
+ min-width: 100%;
824
+ box-sizing: border-box;
825
+ }
826
+ .slash-item:hover,
827
+ .slash-item.selected {
828
+ background: var(--accent-soft);
829
+ }
830
+
831
+ .slash-row-l1 {
832
+ display: grid;
833
+ grid-template-columns: 1ch auto 1fr;
834
+ align-items: baseline;
835
+ gap: 4px;
836
+ min-width: 100%;
837
+ }
838
+ .slash-row-l2 {
839
+ grid-column: 2 / -1;
840
+ display: flex;
841
+ align-items: baseline;
842
+ gap: 8px;
843
+ color: var(--text-dim);
844
+ font-size: 12px;
845
+ line-height: 1.4;
846
+ padding-left: calc(4ch + 4px);
847
+ min-width: 100%;
848
+ }
849
+
850
+ .slash-prefix {
851
+ display: inline-block;
852
+ width: 1ch;
853
+ text-align: center;
854
+ user-select: none;
855
+ flex: 0 0 auto;
856
+ }
857
+ .slash-primary {
858
+ font-weight: bold;
859
+ white-space: nowrap;
860
+ }
861
+ .slash-menu-root .slash-primary {
862
+ min-width: 7ch;
863
+ }
864
+ .slash-current {
865
+ color: var(--green);
866
+ }
867
+ .slash-secondary {
868
+ color: var(--text-dim);
869
+ white-space: nowrap;
870
+ margin-left: 1ch;
871
+ }
872
+ .slash-path {
873
+ white-space: nowrap;
874
+ overflow: hidden;
875
+ text-overflow: ellipsis;
876
+ direction: rtl;
877
+ text-align: left;
878
+ flex: 1 1 auto;
879
+ min-width: 0;
880
+ }
881
+ .slash-path-secondary {
882
+ white-space: nowrap;
883
+ flex: 0 0 auto;
884
+ }
885
+
886
+ .slash-separator {
887
+ height: 1px;
888
+ background: var(--border);
889
+ opacity: 0.5;
890
+ margin: 4px 0;
891
+ }
892
+ .slash-placeholder {
893
+ color: var(--text-dim);
894
+ font-style: italic;
895
+ }
896
+ .slash-placeholder:hover,
897
+ .slash-placeholder.selected {
898
+ background: transparent;
899
+ cursor: default;
900
+ }
901
+
902
+ /* Image attach */
903
+ #attach-preview {
904
+ display: none;
905
+ padding: 4px 16px;
906
+ background: var(--bg);
907
+ border-top: 1px solid var(--border);
908
+ }
909
+ #attach-preview.active {
910
+ display: flex;
911
+ gap: 8px;
912
+ flex-wrap: wrap;
913
+ align-items: center;
914
+ }
915
+ .attach-thumb {
916
+ position: relative;
917
+ display: inline-block;
918
+ }
919
+ .attach-thumb img {
920
+ max-height: 60px;
921
+ max-width: 120px;
922
+ border-radius: 4px;
923
+ border: 1px solid var(--border);
924
+ }
925
+ .attach-thumb.attach-file {
926
+ border: 1px solid var(--border);
927
+ border-radius: 4px;
928
+ padding: 6px 8px;
929
+ font-size: 12px;
930
+ color: var(--fg);
931
+ background: var(--bg-alt, transparent);
932
+ max-width: 200px;
933
+ }
934
+ .attach-thumb.attach-file .attach-file-name {
935
+ display: inline-block;
936
+ max-width: 170px;
937
+ overflow: hidden;
938
+ text-overflow: ellipsis;
939
+ white-space: nowrap;
940
+ vertical-align: middle;
941
+ }
942
+ .attach-thumb .remove {
943
+ position: absolute;
944
+ top: -4px;
945
+ right: -4px;
946
+ background: var(--red);
947
+ color: #fff;
948
+ border: none;
949
+ border-radius: 50%;
950
+ width: 16px;
951
+ height: 16px;
952
+ font-size: 10px;
953
+ line-height: 16px;
954
+ text-align: center;
955
+ cursor: pointer;
956
+ padding: 0;
957
+ }
958
+ .msg.user img.user-image {
959
+ max-width: var(--user-image-max-width);
960
+ max-height: var(--user-image-max-height);
961
+ border-radius: 4px;
962
+ border: 1px solid var(--border);
963
+ display: block;
964
+ margin-top: 4px;
965
+ cursor: zoom-in;
966
+ }
967
+ .msg.user a.user-file {
968
+ display: inline-block;
969
+ margin-top: 4px;
970
+ padding: 2px 6px;
971
+ border: 1px solid var(--border);
972
+ border-radius: 4px;
973
+ color: var(--accent);
974
+ text-decoration: none;
975
+ font-family: monospace;
976
+ font-size: 0.9em;
977
+ }
978
+ .msg.user a.user-file:hover {
979
+ text-decoration: underline;
980
+ }
981
+
982
+ /* Image lightbox overlay */
983
+ #lightbox-overlay {
984
+ position: fixed;
985
+ inset: 0;
986
+ z-index: 9999;
987
+ background: rgba(0, 0, 0, 0.85);
988
+ display: flex;
989
+ align-items: center;
990
+ justify-content: center;
991
+ cursor: zoom-out;
992
+ visibility: hidden;
993
+ pointer-events: none;
994
+ }
995
+ #lightbox-overlay.active {
996
+ visibility: visible;
997
+ pointer-events: auto;
998
+ }
999
+ #lightbox-overlay img {
1000
+ max-width: 90vw;
1001
+ max-height: 90vh;
1002
+ border-radius: 6px;
1003
+ cursor: default;
1004
+ }
1005
+
1006
+ /* History pagination sentinel */
1007
+ .history-sentinel {
1008
+ text-align: center;
1009
+ padding: 8px;
1010
+ opacity: 0.5;
1011
+ font-size: 0.85em;
1012
+ }
1013
+
1014
+ /* Utility: dim out cancelled / settled / past states. Used in dynamic innerHTML
1015
+ where inline `style="opacity:0.5"` would violate strict CSP `style-src 'self'`. */
1016
+ .dim {
1017
+ opacity: 0.5;
1018
+ }
1019
+
1020
+ /* --- Login page (extracted from login.html for CSP `style-src 'self'`) --- */
1021
+ body.login-page {
1022
+ display: flex;
1023
+ align-items: center;
1024
+ justify-content: center;
1025
+ min-height: 100vh;
1026
+ margin: 0;
1027
+ }
1028
+ .login-card {
1029
+ width: 100%;
1030
+ max-width: 480px;
1031
+ padding: 2rem 1.5rem;
1032
+ box-sizing: border-box;
1033
+ }
1034
+ .login-card h1 {
1035
+ font-size: 1.2rem;
1036
+ margin: 0 0 0.5rem;
1037
+ }
1038
+ .login-card p {
1039
+ font-size: 0.9rem;
1040
+ opacity: 0.75;
1041
+ margin: 0 0 1.25rem;
1042
+ line-height: 1.45;
1043
+ }
1044
+ .login-card input {
1045
+ width: 100%;
1046
+ box-sizing: border-box;
1047
+ font-family: inherit;
1048
+ font-size: 0.95rem;
1049
+ padding: 0.6rem;
1050
+ border: 1px solid currentColor;
1051
+ border-radius: 4px;
1052
+ background: transparent;
1053
+ color: inherit;
1054
+ }
1055
+ .login-card .error {
1056
+ display: none;
1057
+ margin-top: 0.75rem;
1058
+ padding: 0.5rem 0.75rem;
1059
+ border: 1px solid #c0392b;
1060
+ color: #c0392b;
1061
+ border-radius: 4px;
1062
+ font-size: 0.85rem;
1063
+ }
1064
+ .login-card button {
1065
+ margin-top: 1rem;
1066
+ width: 100%;
1067
+ padding: 0.6rem;
1068
+ font: inherit;
1069
+ cursor: pointer;
1070
+ border: 1px solid currentColor;
1071
+ background: transparent;
1072
+ color: inherit;
1073
+ border-radius: 4px;
1074
+ }
1075
+ .login-card button:disabled {
1076
+ opacity: 0.5;
1077
+ cursor: not-allowed;
1078
+ }
1079
+ .login-card .hint {
1080
+ font-size: 0.78rem;
1081
+ opacity: 0.6;
1082
+ margin-top: 1rem;
1083
+ }
1084
+ .login-card code {
1085
+ background: rgba(127, 127, 127, 0.15);
1086
+ padding: 0.1rem 0.35rem;
1087
+ border-radius: 3px;
1088
+ }
1089
+
1090
+ /* --- Math (Temml MathML output) --- */
1091
+ /* Block math is wrapped in <div class="math-block"> by the renderer.
1092
+ Safari's overflow on <math> is broken — long equations escape the
1093
+ element and push the parent's width, causing page-level horizontal
1094
+ scroll. The wrapper div absorbs the overflow into a local scrollbar. */
1095
+ .math-block {
1096
+ overflow-x: auto;
1097
+ overflow-y: hidden;
1098
+ max-width: 100%;
1099
+ }
1100
+ /* Long inline math: wrap in an inline-block box so it can carry its own
1101
+ max-width + overflow-x without pushing page width. Applying these
1102
+ directly to <math> doesn't work on WebKit. vertical-align: middle keeps
1103
+ the formula visually centered with surrounding CJK/Latin text. */
1104
+ .math-inline {
1105
+ display: inline-block;
1106
+ max-width: 100%;
1107
+ overflow-x: auto;
1108
+ overflow-y: hidden;
1109
+ vertical-align: middle;
1110
+ }
1111
+ math:not(.tml-display) {
1112
+ max-width: 100%;
1113
+ }
1114
+ /* When Temml fails to parse math, the renderer falls back to a span
1115
+ containing the literal $...$ source (instead of Temml's red inline
1116
+ error message, which breaks paragraph flow and pollutes copy/paste).
1117
+ Styling is intentionally minimal — just dim text. We tried dotted /
1118
+ wavy / dashed underlines and thicker custom strokes, but iOS Safari
1119
+ silently drops non-solid text-decoration-style on inline spans
1120
+ (WebKit bug #233181), and any solid/colored underline that *does*
1121
+ render reads as "wrong" rather than "soft warning". The dim color
1122
+ alone signals "something off here" without distracting from the
1123
+ surrounding correct prose. The actual parse error is preserved in
1124
+ the span's title attribute for desktop hover. */
1125
+ .math-error {
1126
+ color: var(--text-dim);
1127
+ }
1128
+
1129
+ /* --- highlight.js themes (vendored from highlight.js@common, BSD-3-Clause) --- */
1130
+ /* light: default */
1131
+ pre code.hljs {
1132
+ display: block;
1133
+ overflow-x: auto;
1134
+ padding: 1em
1135
+ }
1136
+ code.hljs {
1137
+ padding: 3px 5px
1138
+ }
1139
+ /*!
1140
+ Theme: GitHub
1141
+ Description: Light theme as seen on github.com
1142
+ Author: github.com
1143
+ Maintainer: @Hirse
1144
+ Updated: 2021-05-15
1145
+
1146
+ Outdated base version: https://github.com/primer/github-syntax-light
1147
+ Current colors taken from GitHub's CSS
1148
+ */
1149
+ .hljs {
1150
+ color: #24292e;
1151
+ background: #ffffff
1152
+ }
1153
+ .hljs-doctag,
1154
+ .hljs-keyword,
1155
+ .hljs-meta .hljs-keyword,
1156
+ .hljs-template-tag,
1157
+ .hljs-template-variable,
1158
+ .hljs-type,
1159
+ .hljs-variable.language_ {
1160
+ /* prettylights-syntax-keyword */
1161
+ color: #d73a49
1162
+ }
1163
+ .hljs-title,
1164
+ .hljs-title.class_,
1165
+ .hljs-title.class_.inherited__,
1166
+ .hljs-title.function_ {
1167
+ /* prettylights-syntax-entity */
1168
+ color: #6f42c1
1169
+ }
1170
+ .hljs-attr,
1171
+ .hljs-attribute,
1172
+ .hljs-literal,
1173
+ .hljs-meta,
1174
+ .hljs-number,
1175
+ .hljs-operator,
1176
+ .hljs-variable,
1177
+ .hljs-selector-attr,
1178
+ .hljs-selector-class,
1179
+ .hljs-selector-id {
1180
+ /* prettylights-syntax-constant */
1181
+ color: #005cc5
1182
+ }
1183
+ .hljs-regexp,
1184
+ .hljs-string,
1185
+ .hljs-meta .hljs-string {
1186
+ /* prettylights-syntax-string */
1187
+ color: #032f62
1188
+ }
1189
+ .hljs-built_in,
1190
+ .hljs-symbol {
1191
+ /* prettylights-syntax-variable */
1192
+ color: #e36209
1193
+ }
1194
+ .hljs-comment,
1195
+ .hljs-code,
1196
+ .hljs-formula {
1197
+ /* prettylights-syntax-comment */
1198
+ color: #6a737d
1199
+ }
1200
+ .hljs-name,
1201
+ .hljs-quote,
1202
+ .hljs-selector-tag,
1203
+ .hljs-selector-pseudo {
1204
+ /* prettylights-syntax-entity-tag */
1205
+ color: #22863a
1206
+ }
1207
+ .hljs-subst {
1208
+ /* prettylights-syntax-storage-modifier-import */
1209
+ color: #24292e
1210
+ }
1211
+ .hljs-section {
1212
+ /* prettylights-syntax-markup-heading */
1213
+ color: #005cc5;
1214
+ font-weight: bold
1215
+ }
1216
+ .hljs-bullet {
1217
+ /* prettylights-syntax-markup-list */
1218
+ color: #735c0f
1219
+ }
1220
+ .hljs-emphasis {
1221
+ /* prettylights-syntax-markup-italic */
1222
+ color: #24292e;
1223
+ font-style: italic
1224
+ }
1225
+ .hljs-strong {
1226
+ /* prettylights-syntax-markup-bold */
1227
+ color: #24292e;
1228
+ font-weight: bold
1229
+ }
1230
+ .hljs-addition {
1231
+ /* prettylights-syntax-markup-inserted */
1232
+ color: #22863a;
1233
+ background-color: #f0fff4
1234
+ }
1235
+ .hljs-deletion {
1236
+ /* prettylights-syntax-markup-deleted */
1237
+ color: #b31d28;
1238
+ background-color: #ffeef0
1239
+ }
1240
+ .hljs-char.escape_,
1241
+ .hljs-link,
1242
+ .hljs-params,
1243
+ .hljs-property,
1244
+ .hljs-punctuation,
1245
+ .hljs-tag {
1246
+ /* purposely ignored */
1247
+
1248
+ }
1249
+ /* dark: explicit */
1250
+ [data-theme="dark"] {
1251
+ pre code.hljs {
1252
+ display: block;
1253
+ overflow-x: auto;
1254
+ padding: 1em
1255
+ }
1256
+ code.hljs {
1257
+ padding: 3px 5px
1258
+ }
1259
+ /*!
1260
+ Theme: GitHub Dark
1261
+ Description: Dark theme as seen on github.com
1262
+ Author: github.com
1263
+ Maintainer: @Hirse
1264
+ Updated: 2021-05-15
1265
+
1266
+ Outdated base version: https://github.com/primer/github-syntax-dark
1267
+ Current colors taken from GitHub's CSS
1268
+ */
1269
+ .hljs {
1270
+ color: #c9d1d9;
1271
+ background: #0d1117
1272
+ }
1273
+ .hljs-doctag,
1274
+ .hljs-keyword,
1275
+ .hljs-meta .hljs-keyword,
1276
+ .hljs-template-tag,
1277
+ .hljs-template-variable,
1278
+ .hljs-type,
1279
+ .hljs-variable.language_ {
1280
+ /* prettylights-syntax-keyword */
1281
+ color: #ff7b72
1282
+ }
1283
+ .hljs-title,
1284
+ .hljs-title.class_,
1285
+ .hljs-title.class_.inherited__,
1286
+ .hljs-title.function_ {
1287
+ /* prettylights-syntax-entity */
1288
+ color: #d2a8ff
1289
+ }
1290
+ .hljs-attr,
1291
+ .hljs-attribute,
1292
+ .hljs-literal,
1293
+ .hljs-meta,
1294
+ .hljs-number,
1295
+ .hljs-operator,
1296
+ .hljs-variable,
1297
+ .hljs-selector-attr,
1298
+ .hljs-selector-class,
1299
+ .hljs-selector-id {
1300
+ /* prettylights-syntax-constant */
1301
+ color: #79c0ff
1302
+ }
1303
+ .hljs-regexp,
1304
+ .hljs-string,
1305
+ .hljs-meta .hljs-string {
1306
+ /* prettylights-syntax-string */
1307
+ color: #a5d6ff
1308
+ }
1309
+ .hljs-built_in,
1310
+ .hljs-symbol {
1311
+ /* prettylights-syntax-variable */
1312
+ color: #ffa657
1313
+ }
1314
+ .hljs-comment,
1315
+ .hljs-code,
1316
+ .hljs-formula {
1317
+ /* prettylights-syntax-comment */
1318
+ color: #8b949e
1319
+ }
1320
+ .hljs-name,
1321
+ .hljs-quote,
1322
+ .hljs-selector-tag,
1323
+ .hljs-selector-pseudo {
1324
+ /* prettylights-syntax-entity-tag */
1325
+ color: #7ee787
1326
+ }
1327
+ .hljs-subst {
1328
+ /* prettylights-syntax-storage-modifier-import */
1329
+ color: #c9d1d9
1330
+ }
1331
+ .hljs-section {
1332
+ /* prettylights-syntax-markup-heading */
1333
+ color: #1f6feb;
1334
+ font-weight: bold
1335
+ }
1336
+ .hljs-bullet {
1337
+ /* prettylights-syntax-markup-list */
1338
+ color: #f2cc60
1339
+ }
1340
+ .hljs-emphasis {
1341
+ /* prettylights-syntax-markup-italic */
1342
+ color: #c9d1d9;
1343
+ font-style: italic
1344
+ }
1345
+ .hljs-strong {
1346
+ /* prettylights-syntax-markup-bold */
1347
+ color: #c9d1d9;
1348
+ font-weight: bold
1349
+ }
1350
+ .hljs-addition {
1351
+ /* prettylights-syntax-markup-inserted */
1352
+ color: #aff5b4;
1353
+ background-color: #033a16
1354
+ }
1355
+ .hljs-deletion {
1356
+ /* prettylights-syntax-markup-deleted */
1357
+ color: #ffdcd7;
1358
+ background-color: #67060c
1359
+ }
1360
+ .hljs-char.escape_,
1361
+ .hljs-link,
1362
+ .hljs-params,
1363
+ .hljs-property,
1364
+ .hljs-punctuation,
1365
+ .hljs-tag {
1366
+ /* purposely ignored */
1367
+
1368
+ }
1369
+ }
1370
+
1371
+ /* dark: auto + system prefers dark */
1372
+ @media (prefers-color-scheme: dark) {
1373
+ [data-theme="auto"] {
1374
+ pre code.hljs {
1375
+ display: block;
1376
+ overflow-x: auto;
1377
+ padding: 1em
1378
+ }
1379
+ code.hljs {
1380
+ padding: 3px 5px
1381
+ }
1382
+ /*!
1383
+ Theme: GitHub Dark
1384
+ Description: Dark theme as seen on github.com
1385
+ Author: github.com
1386
+ Maintainer: @Hirse
1387
+ Updated: 2021-05-15
1388
+
1389
+ Outdated base version: https://github.com/primer/github-syntax-dark
1390
+ Current colors taken from GitHub's CSS
1391
+ */
1392
+ .hljs {
1393
+ color: #c9d1d9;
1394
+ background: #0d1117
1395
+ }
1396
+ .hljs-doctag,
1397
+ .hljs-keyword,
1398
+ .hljs-meta .hljs-keyword,
1399
+ .hljs-template-tag,
1400
+ .hljs-template-variable,
1401
+ .hljs-type,
1402
+ .hljs-variable.language_ {
1403
+ /* prettylights-syntax-keyword */
1404
+ color: #ff7b72
1405
+ }
1406
+ .hljs-title,
1407
+ .hljs-title.class_,
1408
+ .hljs-title.class_.inherited__,
1409
+ .hljs-title.function_ {
1410
+ /* prettylights-syntax-entity */
1411
+ color: #d2a8ff
1412
+ }
1413
+ .hljs-attr,
1414
+ .hljs-attribute,
1415
+ .hljs-literal,
1416
+ .hljs-meta,
1417
+ .hljs-number,
1418
+ .hljs-operator,
1419
+ .hljs-variable,
1420
+ .hljs-selector-attr,
1421
+ .hljs-selector-class,
1422
+ .hljs-selector-id {
1423
+ /* prettylights-syntax-constant */
1424
+ color: #79c0ff
1425
+ }
1426
+ .hljs-regexp,
1427
+ .hljs-string,
1428
+ .hljs-meta .hljs-string {
1429
+ /* prettylights-syntax-string */
1430
+ color: #a5d6ff
1431
+ }
1432
+ .hljs-built_in,
1433
+ .hljs-symbol {
1434
+ /* prettylights-syntax-variable */
1435
+ color: #ffa657
1436
+ }
1437
+ .hljs-comment,
1438
+ .hljs-code,
1439
+ .hljs-formula {
1440
+ /* prettylights-syntax-comment */
1441
+ color: #8b949e
1442
+ }
1443
+ .hljs-name,
1444
+ .hljs-quote,
1445
+ .hljs-selector-tag,
1446
+ .hljs-selector-pseudo {
1447
+ /* prettylights-syntax-entity-tag */
1448
+ color: #7ee787
1449
+ }
1450
+ .hljs-subst {
1451
+ /* prettylights-syntax-storage-modifier-import */
1452
+ color: #c9d1d9
1453
+ }
1454
+ .hljs-section {
1455
+ /* prettylights-syntax-markup-heading */
1456
+ color: #1f6feb;
1457
+ font-weight: bold
1458
+ }
1459
+ .hljs-bullet {
1460
+ /* prettylights-syntax-markup-list */
1461
+ color: #f2cc60
1462
+ }
1463
+ .hljs-emphasis {
1464
+ /* prettylights-syntax-markup-italic */
1465
+ color: #c9d1d9;
1466
+ font-style: italic
1467
+ }
1468
+ .hljs-strong {
1469
+ /* prettylights-syntax-markup-bold */
1470
+ color: #c9d1d9;
1471
+ font-weight: bold
1472
+ }
1473
+ .hljs-addition {
1474
+ /* prettylights-syntax-markup-inserted */
1475
+ color: #aff5b4;
1476
+ background-color: #033a16
1477
+ }
1478
+ .hljs-deletion {
1479
+ /* prettylights-syntax-markup-deleted */
1480
+ color: #ffdcd7;
1481
+ background-color: #67060c
1482
+ }
1483
+ .hljs-char.escape_,
1484
+ .hljs-link,
1485
+ .hljs-params,
1486
+ .hljs-property,
1487
+ .hljs-punctuation,
1488
+ .hljs-tag {
1489
+ /* purposely ignored */
1490
+
1491
+ }
1492
+ }
1493
+ }
1494
+
1495
+ /* --- Temml (LaTeX → MathML rendering, MIT) --- */
1496
+ /*
1497
+ Temml.woff2 is a clone of KaTeX_Script-Regular, except that the code points
1498
+ have been changed from ASCII to Unicode Mathematical Alphanumeric Symbols Script capitals,
1499
+ Unicode range 1D49C to 1D4B5.
1500
+ */
1501
+
1502
+ @font-face {
1503
+ font-family: 'Temml';
1504
+ src: url('/fonts/temml/Temml.woff2') format('woff2');
1505
+ font-weight: normal;
1506
+ font-style: normal;
1507
+ }
1508
+
1509
+ math {
1510
+ font-family: "Cambria Math", 'STIXTwoMath-Regular', 'NotoSansMath-Regular', math;
1511
+ font-style: normal;
1512
+ font-weight: normal;
1513
+ line-height: normal;
1514
+ font-size-adjust: none;
1515
+ text-indent: 0;
1516
+ text-transform: none;
1517
+ letter-spacing: normal;
1518
+ word-wrap: normal;
1519
+ direction: ltr;
1520
+ /* Prevent Firefox from omitting the dot on i or j. */
1521
+ font-feature-settings: "dtls" off;
1522
+ }
1523
+
1524
+ math * {
1525
+ border-color: currentColor;
1526
+ }
1527
+
1528
+ /* display: block is necessary in Firefox and Safari.
1529
+ * Not in Chromium, which recognizes display: "block math" written inline. */
1530
+ math.tml-display {
1531
+ display: block;
1532
+ width: 100%;
1533
+ }
1534
+
1535
+ *.mathcal {
1536
+ /* NotoSans */
1537
+ font-feature-settings: 'ss01';
1538
+ }
1539
+
1540
+ math .mathscr {
1541
+ font-family: "Temml";
1542
+ }
1543
+
1544
+ mo.tml-prime {
1545
+ font-family: Temml;
1546
+ }
1547
+
1548
+ /* Cramped superscripts in WebKit */
1549
+ mfrac > :nth-child(2),
1550
+ msqrt,
1551
+ mover > :first-child {
1552
+ math-shift: compact
1553
+ }
1554
+
1555
+ .menclose {
1556
+ display: inline-block;
1557
+ position: relative;
1558
+ padding: 0.5ex 0ex;
1559
+ }
1560
+ .tml-cancelto {
1561
+ display: inline-block;
1562
+ position: absolute;
1563
+ top: 0;
1564
+ left: 0;
1565
+ padding: 0.5ex 0ex;
1566
+ background-color: currentColor;
1567
+ /* Use the SVG as an alpha mask (painted by background-color) */
1568
+ -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><defs><marker id='a' markerHeight='5' markerUnits='strokeWidth' markerWidth='7' orient='auto' refX='7' refY='2.5'><path fill='black' d='m0 0 7 2.5L0 5z'/></marker></defs><line x2='100%25' y1='100%25' stroke='black' stroke-width='.06em' marker-end='url(%23a)' vector-effect='non-scaling-stroke'/></svg>");
1569
+ mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><defs><marker id='a' markerHeight='5' markerUnits='strokeWidth' markerWidth='7' orient='auto' refX='7' refY='2.5'><path fill='black' d='m0 0 7 2.5L0 5z'/></marker></defs><line x2='100%25' y1='100%25' stroke='black' stroke-width='.06em' marker-end='url(%23a)' vector-effect='non-scaling-stroke'/></svg>");
1570
+ -webkit-mask-repeat: no-repeat;
1571
+ mask-repeat: no-repeat;
1572
+ -webkit-mask-size: 100% 100%;
1573
+ mask-size: 100% 100%;
1574
+ -webkit-mask-position: 0 0;
1575
+ mask-position: 0 0;
1576
+ }
1577
+
1578
+ @supports (-moz-appearance: none) {
1579
+ /* \vec w/o italic correction for Firefox */
1580
+ .tml-vec {
1581
+ transform: scale(0.75)
1582
+ }
1583
+ /* Fix \cancelto in Firefox */
1584
+ .ff-narrow {
1585
+ width: 0em;
1586
+ }
1587
+ .ff-nudge-left {
1588
+ margin-left: -0.2em;
1589
+ }
1590
+ }
1591
+
1592
+ @supports (not (-moz-appearance: none)) {
1593
+ /* Chromium and WebKit */
1594
+ /* prime vertical alignment */
1595
+ mo.tml-prime {
1596
+ font-family: Temml;
1597
+ }
1598
+ /* Italic correction on superscripts */
1599
+ .tml-sml-pad {
1600
+ padding-left: 0.05em;
1601
+ }
1602
+ .tml-med-pad {
1603
+ padding-left: 0.10em;
1604
+ }
1605
+ .tml-lrg-pad {
1606
+ padding-left: 0.15em;
1607
+ }
1608
+ }
1609
+
1610
+ @supports (-webkit-backdrop-filter: blur(1px)) {
1611
+ /* WebKit vertical & italic correction on accents */
1612
+ .wbk-acc {
1613
+ /* lower by x-height distance */
1614
+ transform: translate(0em, 0.431em);
1615
+ }
1616
+ .wbk-sml {
1617
+ transform: translate(0.07em, 0);
1618
+ }
1619
+ .wbk-sml-acc {
1620
+ transform: translate(0.07em, 0.431em);
1621
+ }
1622
+ .wbk-sml-vec {
1623
+ transform: scale(0.75) translate(0.07em, 0);
1624
+ }
1625
+ .wbk-med {
1626
+ transform: translate(0.14em, 0);
1627
+ }
1628
+ .wbk-med-acc {
1629
+ transform: translate(0.14em, 0.431em);
1630
+ }
1631
+ .wbk-med-vec {
1632
+ transform: scale(0.75) translate(0.14em, 0);
1633
+ }
1634
+ .wbk-lrg {
1635
+ transform: translate(0.21em, 0);
1636
+ }
1637
+ .wbk-lrg-acc {
1638
+ transform: translate(0.21em, 0.431em);
1639
+ }
1640
+ .wbk-lrg-vec {
1641
+ transform: scale(0.75) translate(0.21em, 0);
1642
+ }
1643
+ }
1644
+
1645
+ /* \cancel & \phase use background images. Get them to print. */
1646
+ menclose {
1647
+ -webkit-print-color-adjust: exact; /* Chrome & Edge */
1648
+ print-color-adjust: exact;
1649
+ }
1650
+
1651
+ /* Array cell justification in Firefox & WebKit */
1652
+ .tml-right {
1653
+ text-align: right;
1654
+ }
1655
+ .tml-left {
1656
+ text-align: left;
1657
+ }
1658
+
1659
+ /* For CD labels that grow to the left in Firefox and WebKit */
1660
+ .tml-shift-left { margin-left:-200% }
1661
+
1662
+ /* Styles for Chromium only */
1663
+ @supports (not (-webkit-backdrop-filter: blur(1px))) and (not (-moz-appearance: none)) {
1664
+ /* Italic correction on accents */
1665
+ .chr-sml {
1666
+ transform: translate(0.07em, 0)
1667
+ }
1668
+ .chr-sml-vec {
1669
+ transform: scale(0.75) translate(0.07em, 0)
1670
+ }
1671
+ .chr-med {
1672
+ transform: translate(0.14em, 0)
1673
+ }
1674
+ .chr-med-vec {
1675
+ transform: scale(0.75) translate(0.14em, 0)
1676
+ }
1677
+ .chr-lrg {
1678
+ transform: translate(0.21em, 0)
1679
+ }
1680
+ .chr-lrg-vec {
1681
+ transform: scale(0.75) translate(0.21em, 0)
1682
+ }
1683
+
1684
+ /* For CD labels that grow to the left */
1685
+ .tml-shift-left { margin-left:-100% }
1686
+
1687
+ /* MathML Core & Chromium do not support the MathML 3.0 element <menclose> attributes. */
1688
+ /* So use styles. */
1689
+ menclose {
1690
+ position: relative;
1691
+ padding: 0.5ex 0ex;
1692
+ }
1693
+
1694
+ .tml-overline {
1695
+ padding: 0.1em 0 0 0;
1696
+ border-top: 0.065em solid;
1697
+ }
1698
+
1699
+ .tml-underline {
1700
+ padding: 0 0 0.1em 0;
1701
+ border-bottom: 0.065em solid;
1702
+ }
1703
+
1704
+ .tml-cancel {
1705
+ display: inline-block;
1706
+ position: absolute;
1707
+ left: 0.5px;
1708
+ bottom: 0;
1709
+ width: 100%;
1710
+ height: 100%;
1711
+ background-color: currentColor;
1712
+ }
1713
+ .upstrike {
1714
+ clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
1715
+ }
1716
+ .downstrike {
1717
+ clip-path: polygon(0em 0.05em, 0.05em 0em, 100% calc(100% - 0.05em), calc(100% - 0.05em) 100%);
1718
+ }
1719
+ .sout {
1720
+ clip-path: polygon(0em calc(55% + 0.0333em), 0em calc(55% - 0.0333em), 100% calc(55% - 0.0333em), 100% calc(55% + 0.0333em));
1721
+ }
1722
+ .tml-xcancel {
1723
+ clip-path: polygon(0.05em 0em, 0em 0.05em, calc(50% - 0.05em) 50%, 0em calc(100% - 0.05em), 0.05em 100%, 50% calc(50% + 0.05em), calc(100% - 0.05em) 100%, 100% calc(100% - 0.05em), calc(50% + 0.05em) 50%, 100% 0.05em, calc(100% - 0.05em) 0%, 50% calc(50% - 0.05em));
1724
+ }
1725
+
1726
+ .longdiv-top {
1727
+ border-top: 0.067em solid;
1728
+ padding: 0.1em 0.2em 0.2em 0.433em;
1729
+ }
1730
+ .longdiv-arc {
1731
+ position: absolute;
1732
+ top: 0;
1733
+ bottom: 0.1em;
1734
+ left: -0.4em;
1735
+ width: 0.7em;
1736
+ border: 0.067em solid;
1737
+ transform: translateY(-0.067em);
1738
+ border-radius: 70%;
1739
+ clip-path: inset(0 0 0 0.4em);
1740
+ box-sizing: border-box;}
1741
+ .menclose {display: inline-block;
1742
+ text-align: left;
1743
+ position: relative;
1744
+ }
1745
+
1746
+ .phasor-bottom {
1747
+ border-bottom: 0.067em solid;
1748
+ padding: 0.2em 0.2em 0.1em 0.6em;
1749
+ }
1750
+ .phasor-angle {
1751
+ display: inline-block;
1752
+ position: absolute;
1753
+ left: 0.5px;
1754
+ bottom: -0.04em;
1755
+ height: 100%;
1756
+ aspect-ratio: 0.5;
1757
+ background-color: currentColor;
1758
+ clip-path: polygon(0.05em 100%, 0em calc(100% - 0.05em), calc(100% - 0.05em) 0em, 100% 0.05em);
1759
+ }
1760
+
1761
+ .tml-fbox {
1762
+ padding: 3pt;
1763
+ border: 1px solid;
1764
+ }
1765
+
1766
+ .circle-pad {
1767
+ padding: 0.267em;
1768
+ }
1769
+ .textcircle {
1770
+ position: absolute;
1771
+ top: 0;
1772
+ bottom: 0;
1773
+ right: 0;
1774
+ left: 0;
1775
+ border: 0.067em solid;
1776
+ border-radius: 50%;
1777
+ }
1778
+
1779
+ .actuarial {
1780
+ padding: 0.03889em 0.03889em 0 0.03889em;
1781
+ border-width: 0.08em 0.08em 0em 0em;
1782
+ border-style: solid;
1783
+ margin-right: 0.03889em;
1784
+ }
1785
+
1786
+ /* Stretch \widetilde */
1787
+ .tml-crooked-2 {
1788
+ transform: scale(2.0, 1.1)
1789
+ }
1790
+ .tml-crooked-3 {
1791
+ transform: scale(3.0, 1.3)
1792
+ }
1793
+ .tml-crooked-4 {
1794
+ transform: scale(4.0, 1.4)
1795
+ }
1796
+ /* set array cell justification */
1797
+ .tml-right {
1798
+ text-align: -webkit-right;
1799
+ }
1800
+ .tml-left {
1801
+ text-align: -webkit-left;
1802
+ }
1803
+ }
1804
+
1805
+ .special-fraction {
1806
+ font-family: 'STIX TWO', 'Times New Roman', Times, Tinos, serif;
1807
+ }
1808
+
1809
+ /* flex-wrap for line-breaking in Chromium */
1810
+ math {
1811
+ display: inline-flex;
1812
+ flex-wrap: wrap;
1813
+ align-items: baseline;
1814
+ }
1815
+ math > mrow {
1816
+ padding: 0.5ex 0ex;
1817
+ }
1818
+
1819
+ /* Default mtd top padding is 0.5ex per MathML-Core and user-agent CSS */
1820
+ /* We adjust for jot and small */
1821
+ mtable.tml-jot mtd {
1822
+ padding-top: 0.7ex;
1823
+ padding-bottom: 0.7ex;
1824
+ }
1825
+ mtable.tml-small mtd {
1826
+ padding-top: 0.35ex;
1827
+ padding-bottom: 0.35ex;
1828
+ }
1829
+
1830
+ /* Firefox */
1831
+ @-moz-document url-prefix() {
1832
+ /* Avoid flex-wrap */
1833
+ math { display: inline; }
1834
+ math > mrow { padding: 0 }
1835
+ /* Adjust Firefox spacing between array rows */
1836
+ mtd, mtable.tml-small mtd { padding-top: 0; padding-bottom: 0; }
1837
+ mtable.tml-jot mtd { padding-top: 0.2ex; padding-bottom: 0.ex; }
1838
+ }
1839
+
1840
+ /* AMS environment auto-numbering via CSS counter. */
1841
+ .tml-eqn::before {
1842
+ counter-increment: tmlEqnNo;
1843
+ content: "(" counter(tmlEqnNo) ")";
1844
+ }
1845
+
1846
+ body {
1847
+ counter-reset: tmlEqnNo;
1848
+ }