simultex 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 (79) hide show
  1. simultex/__init__.py +3 -0
  2. simultex/assets/simultex.ansi +6 -0
  3. simultex/browser.py +329 -0
  4. simultex/browser_assets/KaTeX_AMS-Regular-CYEKBG2K.woff +0 -0
  5. simultex/browser_assets/KaTeX_AMS-Regular-JKX5W2C4.ttf +0 -0
  6. simultex/browser_assets/KaTeX_AMS-Regular-U6PRYMIZ.woff2 +0 -0
  7. simultex/browser_assets/KaTeX_Caligraphic-Bold-5QL5CMTE.woff2 +0 -0
  8. simultex/browser_assets/KaTeX_Caligraphic-Bold-WZ3QSGD3.woff +0 -0
  9. simultex/browser_assets/KaTeX_Caligraphic-Bold-ZTS3R3HK.ttf +0 -0
  10. simultex/browser_assets/KaTeX_Caligraphic-Regular-3LKEU76G.woff +0 -0
  11. simultex/browser_assets/KaTeX_Caligraphic-Regular-A7XRTZ5Q.ttf +0 -0
  12. simultex/browser_assets/KaTeX_Caligraphic-Regular-KX5MEWCF.woff2 +0 -0
  13. simultex/browser_assets/KaTeX_Fraktur-Bold-2QVFK6NQ.woff2 +0 -0
  14. simultex/browser_assets/KaTeX_Fraktur-Bold-T4SWXBMT.woff +0 -0
  15. simultex/browser_assets/KaTeX_Fraktur-Bold-WGHVTYOR.ttf +0 -0
  16. simultex/browser_assets/KaTeX_Fraktur-Regular-2PEIFJSJ.woff2 +0 -0
  17. simultex/browser_assets/KaTeX_Fraktur-Regular-5U4OPH2X.ttf +0 -0
  18. simultex/browser_assets/KaTeX_Fraktur-Regular-PQMHCIK6.woff +0 -0
  19. simultex/browser_assets/KaTeX_Main-Bold-2GA4IZIN.woff +0 -0
  20. simultex/browser_assets/KaTeX_Main-Bold-W5FBVCZM.ttf +0 -0
  21. simultex/browser_assets/KaTeX_Main-Bold-YP5VVQRP.woff2 +0 -0
  22. simultex/browser_assets/KaTeX_Main-BoldItalic-4P4C7HJH.woff +0 -0
  23. simultex/browser_assets/KaTeX_Main-BoldItalic-N4V3DX7S.woff2 +0 -0
  24. simultex/browser_assets/KaTeX_Main-BoldItalic-ODMLBJJQ.ttf +0 -0
  25. simultex/browser_assets/KaTeX_Main-Italic-I43T2HSR.ttf +0 -0
  26. simultex/browser_assets/KaTeX_Main-Italic-RELBIK7M.woff2 +0 -0
  27. simultex/browser_assets/KaTeX_Main-Italic-SASNQFN2.woff +0 -0
  28. simultex/browser_assets/KaTeX_Main-Regular-ARRPAO67.woff2 +0 -0
  29. simultex/browser_assets/KaTeX_Main-Regular-P5I74A2A.woff +0 -0
  30. simultex/browser_assets/KaTeX_Main-Regular-W74P5G27.ttf +0 -0
  31. simultex/browser_assets/KaTeX_Math-BoldItalic-6EBV3DK5.woff +0 -0
  32. simultex/browser_assets/KaTeX_Math-BoldItalic-K4WTGH3J.woff2 +0 -0
  33. simultex/browser_assets/KaTeX_Math-BoldItalic-VB447A4D.ttf +0 -0
  34. simultex/browser_assets/KaTeX_Math-Italic-6KGCHLFN.woff2 +0 -0
  35. simultex/browser_assets/KaTeX_Math-Italic-KKK3USB2.woff +0 -0
  36. simultex/browser_assets/KaTeX_Math-Italic-SON4MRCA.ttf +0 -0
  37. simultex/browser_assets/KaTeX_SansSerif-Bold-RRNVJFFW.woff2 +0 -0
  38. simultex/browser_assets/KaTeX_SansSerif-Bold-STQ6RXC7.ttf +0 -0
  39. simultex/browser_assets/KaTeX_SansSerif-Bold-X5M5EMOD.woff +0 -0
  40. simultex/browser_assets/KaTeX_SansSerif-Italic-HMPFTM52.woff2 +0 -0
  41. simultex/browser_assets/KaTeX_SansSerif-Italic-PSN4QKYX.woff +0 -0
  42. simultex/browser_assets/KaTeX_SansSerif-Italic-WTBAZBGY.ttf +0 -0
  43. simultex/browser_assets/KaTeX_SansSerif-Regular-2TL3USAE.ttf +0 -0
  44. simultex/browser_assets/KaTeX_SansSerif-Regular-OQCII6EP.woff +0 -0
  45. simultex/browser_assets/KaTeX_SansSerif-Regular-XIQ62X4E.woff2 +0 -0
  46. simultex/browser_assets/KaTeX_Script-Regular-72OLXYNA.ttf +0 -0
  47. simultex/browser_assets/KaTeX_Script-Regular-A5IFOEBS.woff +0 -0
  48. simultex/browser_assets/KaTeX_Script-Regular-APUWIHLP.woff2 +0 -0
  49. simultex/browser_assets/KaTeX_Size1-Regular-4HRHTS65.woff +0 -0
  50. simultex/browser_assets/KaTeX_Size1-Regular-5LRUTBFT.woff2 +0 -0
  51. simultex/browser_assets/KaTeX_Size1-Regular-7K6AASVL.ttf +0 -0
  52. simultex/browser_assets/KaTeX_Size2-Regular-222HN3GT.ttf +0 -0
  53. simultex/browser_assets/KaTeX_Size2-Regular-K5ZHAIS6.woff +0 -0
  54. simultex/browser_assets/KaTeX_Size2-Regular-LELKET5D.woff2 +0 -0
  55. simultex/browser_assets/KaTeX_Size3-Regular-TLFPAHDE.woff +0 -0
  56. simultex/browser_assets/KaTeX_Size3-Regular-UFCO6WCA.ttf +0 -0
  57. simultex/browser_assets/KaTeX_Size3-Regular-WQRQ47UD.woff2 +0 -0
  58. simultex/browser_assets/KaTeX_Size4-Regular-7PGNVPQK.ttf +0 -0
  59. simultex/browser_assets/KaTeX_Size4-Regular-CDMV7U5C.woff2 +0 -0
  60. simultex/browser_assets/KaTeX_Size4-Regular-PKMWZHNC.woff +0 -0
  61. simultex/browser_assets/KaTeX_Typewriter-Regular-3F5K6SQ6.ttf +0 -0
  62. simultex/browser_assets/KaTeX_Typewriter-Regular-MJMFSK64.woff +0 -0
  63. simultex/browser_assets/KaTeX_Typewriter-Regular-VBYJ4NRC.woff2 +0 -0
  64. simultex/browser_assets/app.css +1 -0
  65. simultex/browser_assets/app.js +3683 -0
  66. simultex/browser_assets/index.html +22 -0
  67. simultex/cli.py +369 -0
  68. simultex/codex_history.py +330 -0
  69. simultex/model_proxy.py +961 -0
  70. simultex/protocol.py +218 -0
  71. simultex/pty_proxy.py +166 -0
  72. simultex/render.py +234 -0
  73. simultex/screen.py +333 -0
  74. simultex/stream.py +276 -0
  75. simultex-0.1.0.dist-info/METADATA +221 -0
  76. simultex-0.1.0.dist-info/RECORD +79 -0
  77. simultex-0.1.0.dist-info/WHEEL +4 -0
  78. simultex-0.1.0.dist-info/entry_points.txt +2 -0
  79. simultex-0.1.0.dist-info/licenses/LICENSE +21 -0
simultex/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """Render LaTeX from interactive programs directly in a terminal."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,6 @@
1
+  ███████╗ ██╗ ███╗   ███╗ ██╗   ██╗ ██╗      ████████╗ ███████╗ ██╗  ██╗
2
+  ██╔════╝ ██║ ████╗ ████║ ██║   ██║ ██║      ╚══██╔══╝ ██╔════╝ ╚██╗██╔╝
3
+  ███████╗ ██║ ██╔████╔██║ ██║   ██║ ██║         ██║    █████╗    ╚███╔╝ 
4
+  ╚════██║ ██║ ██║╚██╔╝██║ ██║   ██║ ██║         ██║    ██╔══╝    ██╔██╗ 
5
+  ███████║ ██║ ██║ ╚═╝ ██║ ╚██████╔╝ ███████╗    ██║    ███████╗ ██╔╝ ██╗
6
+  ╚══════╝ ╚═╝ ╚═╝     ╚═╝  ╚═════╝  ╚══════╝    ╚═╝    ╚══════╝ ╚═╝  ╚═╝
simultex/browser.py ADDED
@@ -0,0 +1,329 @@
1
+ """Loopback-only browser companion for mirroring a terminal session."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import base64
6
+ import html
7
+ import json
8
+ import secrets
9
+ import sys
10
+ import threading
11
+ from collections import deque
12
+ from dataclasses import dataclass, replace
13
+ from http import HTTPStatus
14
+ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
15
+ from pathlib import Path
16
+ from queue import Empty, Full, Queue
17
+ from urllib.parse import parse_qs, urlsplit
18
+
19
+
20
+ _ASSET_ROOT = Path(__file__).with_name("browser_assets")
21
+ _MAX_HISTORY_BYTES = 8 * 1024 * 1024
22
+ _CLIENT_QUEUE_SIZE = 512
23
+ _MAX_SESSION_IMAGE_BYTES = 64 * 1024 * 1024
24
+ _SESSION_IMAGE_TYPES = {
25
+ ".avif": "image/avif",
26
+ ".bmp": "image/bmp",
27
+ ".gif": "image/gif",
28
+ ".jpeg": "image/jpeg",
29
+ ".jpg": "image/jpeg",
30
+ ".png": "image/png",
31
+ ".webp": "image/webp",
32
+ }
33
+
34
+
35
+ class _QuietThreadingHTTPServer(ThreadingHTTPServer):
36
+ def handle_error(self, request: object, client_address: object) -> None:
37
+ error = sys.exc_info()[1]
38
+ if isinstance(error, (BrokenPipeError, ConnectionResetError)):
39
+ return
40
+ super().handle_error(request, client_address)
41
+
42
+
43
+ @dataclass(frozen=True)
44
+ class _Event:
45
+ name: str
46
+ data: str
47
+ size: int
48
+ sequence: int = 0
49
+
50
+ def encode(self) -> bytes:
51
+ return (
52
+ f"id: {self.sequence}\nevent: {self.name}\ndata: {self.data}\n\n"
53
+ ).encode("utf-8")
54
+
55
+
56
+ class _EventBus:
57
+ def __init__(self, history_limit: int = _MAX_HISTORY_BYTES):
58
+ self._history_limit = history_limit
59
+ self._history: deque[_Event] = deque()
60
+ self._history_size = 0
61
+ self._clients: set[Queue[_Event | None]] = set()
62
+ self._lock = threading.Lock()
63
+ self._next_sequence = 1
64
+
65
+ def publish(self, event: _Event) -> None:
66
+ with self._lock:
67
+ event = replace(event, sequence=self._next_sequence)
68
+ self._next_sequence += 1
69
+ self._history.append(event)
70
+ self._history_size += event.size
71
+ while self._history and self._history_size > self._history_limit:
72
+ removed = self._history.popleft()
73
+ self._history_size -= removed.size
74
+ stale: list[Queue[_Event | None]] = []
75
+ for client in self._clients:
76
+ try:
77
+ client.put_nowait(event)
78
+ except Full:
79
+ stale.append(client)
80
+ for client in stale:
81
+ self._clients.discard(client)
82
+ try:
83
+ client.get_nowait()
84
+ client.put_nowait(None)
85
+ except (Empty, Full):
86
+ pass
87
+
88
+ def subscribe(
89
+ self, after_sequence: int = 0
90
+ ) -> tuple[list[_Event], Queue[_Event | None]]:
91
+ client: Queue[_Event | None] = Queue(maxsize=_CLIENT_QUEUE_SIZE)
92
+ with self._lock:
93
+ history = [event for event in self._history if event.sequence > after_sequence]
94
+ self._clients.add(client)
95
+ return history, client
96
+
97
+ def unsubscribe(self, client: Queue[_Event | None]) -> None:
98
+ with self._lock:
99
+ self._clients.discard(client)
100
+
101
+ def close(self) -> None:
102
+ with self._lock:
103
+ clients = list(self._clients)
104
+ self._clients.clear()
105
+ for client in clients:
106
+ try:
107
+ client.put_nowait(None)
108
+ except Full:
109
+ pass
110
+
111
+
112
+ class BrowserCompanion:
113
+ """Serve a read-only rich transcript derived from raw PTY output."""
114
+
115
+ def __init__(
116
+ self,
117
+ port: int = 0,
118
+ *,
119
+ parse_dollars: bool = True,
120
+ content_root: Path | None = None,
121
+ ):
122
+ self.token = secrets.token_urlsafe(24)
123
+ self.parse_dollars = parse_dollars
124
+ self.content_root = (content_root or Path.cwd()).resolve()
125
+ self._events = _EventBus()
126
+ handler = self._handler_type()
127
+ self._server = _QuietThreadingHTTPServer(("127.0.0.1", port), handler)
128
+ self._server.daemon_threads = True
129
+ self._thread = threading.Thread(
130
+ target=self._server.serve_forever,
131
+ name="simultex-browser",
132
+ daemon=True,
133
+ )
134
+
135
+ @property
136
+ def port(self) -> int:
137
+ return int(self._server.server_address[1])
138
+
139
+ @property
140
+ def url(self) -> str:
141
+ return f"http://127.0.0.1:{self.port}/?token={self.token}"
142
+
143
+ def start(self) -> None:
144
+ self._thread.start()
145
+
146
+ def feed(self, data: bytes) -> None:
147
+ encoded = base64.b64encode(data).decode("ascii")
148
+ self._events.publish(_Event("output", encoded, len(data)))
149
+
150
+ def resize(self, columns: int, rows: int) -> None:
151
+ payload = json.dumps({"columns": columns, "rows": rows}, separators=(",", ":"))
152
+ self._events.publish(_Event("resize", payload, len(payload)))
153
+
154
+ def api_event(self, payload: dict[str, object]) -> None:
155
+ """Publish a normalized model event without changing PTY rendering."""
156
+ encoded = json.dumps(payload, ensure_ascii=False, separators=(",", ":"))
157
+ self._events.publish(_Event("api", encoded, len(encoded.encode("utf-8"))))
158
+
159
+ def close(self) -> None:
160
+ self._events.close()
161
+ self._server.shutdown()
162
+ self._server.server_close()
163
+ self._thread.join(timeout=2)
164
+
165
+ def __enter__(self) -> BrowserCompanion:
166
+ self.start()
167
+ return self
168
+
169
+ def __exit__(self, _type: object, _value: object, _traceback: object) -> None:
170
+ self.close()
171
+
172
+ def _handler_type(self) -> type[BaseHTTPRequestHandler]:
173
+ companion = self
174
+
175
+ class Handler(BaseHTTPRequestHandler):
176
+ server_version = "simultex-browser"
177
+
178
+ def do_GET(self) -> None: # noqa: N802 - BaseHTTPRequestHandler API
179
+ parsed = urlsplit(self.path)
180
+ if parsed.path == "/":
181
+ self._serve_index()
182
+ return
183
+ if parsed.path == "/events":
184
+ self._serve_events(parsed.query)
185
+ return
186
+ if parsed.path == "/session-image":
187
+ self._serve_session_image(parsed.query)
188
+ return
189
+ self._serve_asset(parsed.path)
190
+
191
+ def log_message(self, _format: str, *_args: object) -> None:
192
+ return
193
+
194
+ def _headers(self, content_type: str, length: int | None = None) -> None:
195
+ self.send_header("Content-Type", content_type)
196
+ self.send_header("Cache-Control", "no-store")
197
+ self.send_header("X-Content-Type-Options", "nosniff")
198
+ self.send_header("Referrer-Policy", "no-referrer")
199
+ self.send_header("Cross-Origin-Resource-Policy", "same-origin")
200
+ self.send_header(
201
+ "Content-Security-Policy",
202
+ "default-src 'self'; connect-src 'self'; script-src 'self'; "
203
+ "style-src 'self' 'unsafe-inline'; font-src 'self' data:; "
204
+ "img-src 'self' data: blob: http: https:",
205
+ )
206
+ if length is not None:
207
+ self.send_header("Content-Length", str(length))
208
+
209
+ def _serve_index(self) -> None:
210
+ try:
211
+ template = (_ASSET_ROOT / "index.html").read_text(encoding="utf-8")
212
+ except OSError:
213
+ self.send_error(
214
+ HTTPStatus.SERVICE_UNAVAILABLE,
215
+ "browser assets are missing; run npm install && npm run build in browser-ui",
216
+ )
217
+ return
218
+ config = html.escape(
219
+ json.dumps({"parseDollars": companion.parse_dollars}),
220
+ quote=True,
221
+ )
222
+ body = template.replace("__SIMULTEX_CONFIG__", config).encode("utf-8")
223
+ self.send_response(HTTPStatus.OK)
224
+ self._headers("text/html; charset=utf-8", len(body))
225
+ self.end_headers()
226
+ self.wfile.write(body)
227
+
228
+ def _serve_session_image(self, query: str) -> None:
229
+ values = parse_qs(query)
230
+ supplied = values.get("token", [""])[0]
231
+ if not secrets.compare_digest(supplied, companion.token):
232
+ self.send_error(HTTPStatus.FORBIDDEN)
233
+ return
234
+ requested = values.get("path", [""])[0]
235
+ if not requested:
236
+ self.send_error(HTTPStatus.NOT_FOUND)
237
+ return
238
+ candidate = Path(requested)
239
+ if not candidate.is_absolute():
240
+ candidate = companion.content_root / candidate
241
+ try:
242
+ path = candidate.resolve(strict=True)
243
+ path.relative_to(companion.content_root)
244
+ size = path.stat().st_size
245
+ except (OSError, ValueError):
246
+ self.send_error(HTTPStatus.NOT_FOUND)
247
+ return
248
+ content_type = _SESSION_IMAGE_TYPES.get(path.suffix.lower())
249
+ if not path.is_file() or content_type is None or size > _MAX_SESSION_IMAGE_BYTES:
250
+ self.send_error(HTTPStatus.NOT_FOUND)
251
+ return
252
+ try:
253
+ body = path.read_bytes()
254
+ except OSError:
255
+ self.send_error(HTTPStatus.NOT_FOUND)
256
+ return
257
+ self.send_response(HTTPStatus.OK)
258
+ self._headers(content_type, len(body))
259
+ self.end_headers()
260
+ self.wfile.write(body)
261
+
262
+ def _serve_asset(self, request_path: str) -> None:
263
+ name = request_path.removeprefix("/")
264
+ if not name or Path(name).name != name:
265
+ self.send_error(HTTPStatus.NOT_FOUND)
266
+ return
267
+ path = _ASSET_ROOT / name
268
+ types = {
269
+ ".js": "text/javascript; charset=utf-8",
270
+ ".css": "text/css; charset=utf-8",
271
+ ".woff2": "font/woff2",
272
+ ".woff": "font/woff",
273
+ ".ttf": "font/ttf",
274
+ }
275
+ content_type = types.get(path.suffix)
276
+ if content_type is None:
277
+ self.send_error(HTTPStatus.NOT_FOUND)
278
+ return
279
+ try:
280
+ body = path.read_bytes()
281
+ except OSError:
282
+ self.send_error(HTTPStatus.NOT_FOUND)
283
+ return
284
+ self.send_response(HTTPStatus.OK)
285
+ self._headers(content_type, len(body))
286
+ self.end_headers()
287
+ self.wfile.write(body)
288
+
289
+ def _serve_events(self, query: str) -> None:
290
+ supplied = parse_qs(query).get("token", [""])[0]
291
+ if not secrets.compare_digest(supplied, companion.token):
292
+ self.send_error(HTTPStatus.FORBIDDEN)
293
+ return
294
+ origin = self.headers.get("Origin")
295
+ expected = f"http://127.0.0.1:{companion.port}"
296
+ if origin not in {None, expected}:
297
+ self.send_error(HTTPStatus.FORBIDDEN)
298
+ return
299
+
300
+ try:
301
+ after_sequence = max(int(self.headers.get("Last-Event-ID", "0")), 0)
302
+ except ValueError:
303
+ after_sequence = 0
304
+ history, events = companion._events.subscribe(after_sequence)
305
+ try:
306
+ self.send_response(HTTPStatus.OK)
307
+ self._headers("text/event-stream; charset=utf-8")
308
+ self.send_header("Connection", "keep-alive")
309
+ self.end_headers()
310
+ for event in history:
311
+ self.wfile.write(event.encode())
312
+ self.wfile.flush()
313
+ while True:
314
+ try:
315
+ event = events.get(timeout=15)
316
+ except Empty:
317
+ self.wfile.write(b": keepalive\n\n")
318
+ self.wfile.flush()
319
+ continue
320
+ if event is None:
321
+ return
322
+ self.wfile.write(event.encode())
323
+ self.wfile.flush()
324
+ except (BrokenPipeError, ConnectionResetError):
325
+ return
326
+ finally:
327
+ companion._events.unsubscribe(events)
328
+
329
+ return Handler
@@ -0,0 +1 @@
1
+ @font-face{font-family:KaTeX_AMS;src:url("./KaTeX_AMS-Regular-U6PRYMIZ.woff2") format("woff2"),url("./KaTeX_AMS-Regular-CYEKBG2K.woff") format("woff"),url("./KaTeX_AMS-Regular-JKX5W2C4.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Caligraphic;src:url("./KaTeX_Caligraphic-Bold-5QL5CMTE.woff2") format("woff2"),url("./KaTeX_Caligraphic-Bold-WZ3QSGD3.woff") format("woff"),url("./KaTeX_Caligraphic-Bold-ZTS3R3HK.ttf") format("truetype");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Caligraphic;src:url("./KaTeX_Caligraphic-Regular-KX5MEWCF.woff2") format("woff2"),url("./KaTeX_Caligraphic-Regular-3LKEU76G.woff") format("woff"),url("./KaTeX_Caligraphic-Regular-A7XRTZ5Q.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Fraktur;src:url("./KaTeX_Fraktur-Bold-2QVFK6NQ.woff2") format("woff2"),url("./KaTeX_Fraktur-Bold-T4SWXBMT.woff") format("woff"),url("./KaTeX_Fraktur-Bold-WGHVTYOR.ttf") format("truetype");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Fraktur;src:url("./KaTeX_Fraktur-Regular-2PEIFJSJ.woff2") format("woff2"),url("./KaTeX_Fraktur-Regular-PQMHCIK6.woff") format("woff"),url("./KaTeX_Fraktur-Regular-5U4OPH2X.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Main;src:url("./KaTeX_Main-Bold-YP5VVQRP.woff2") format("woff2"),url("./KaTeX_Main-Bold-2GA4IZIN.woff") format("woff"),url("./KaTeX_Main-Bold-W5FBVCZM.ttf") format("truetype");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Main;src:url("./KaTeX_Main-BoldItalic-N4V3DX7S.woff2") format("woff2"),url("./KaTeX_Main-BoldItalic-4P4C7HJH.woff") format("woff"),url("./KaTeX_Main-BoldItalic-ODMLBJJQ.ttf") format("truetype");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:KaTeX_Main;src:url("./KaTeX_Main-Italic-RELBIK7M.woff2") format("woff2"),url("./KaTeX_Main-Italic-SASNQFN2.woff") format("woff"),url("./KaTeX_Main-Italic-I43T2HSR.ttf") format("truetype");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:KaTeX_Main;src:url("./KaTeX_Main-Regular-ARRPAO67.woff2") format("woff2"),url("./KaTeX_Main-Regular-P5I74A2A.woff") format("woff"),url("./KaTeX_Main-Regular-W74P5G27.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Math;src:url("./KaTeX_Math-BoldItalic-K4WTGH3J.woff2") format("woff2"),url("./KaTeX_Math-BoldItalic-6EBV3DK5.woff") format("woff"),url("./KaTeX_Math-BoldItalic-VB447A4D.ttf") format("truetype");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:KaTeX_Math;src:url("./KaTeX_Math-Italic-6KGCHLFN.woff2") format("woff2"),url("./KaTeX_Math-Italic-KKK3USB2.woff") format("woff"),url("./KaTeX_Math-Italic-SON4MRCA.ttf") format("truetype");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:KaTeX_SansSerif;src:url("./KaTeX_SansSerif-Bold-RRNVJFFW.woff2") format("woff2"),url("./KaTeX_SansSerif-Bold-X5M5EMOD.woff") format("woff"),url("./KaTeX_SansSerif-Bold-STQ6RXC7.ttf") format("truetype");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:KaTeX_SansSerif;src:url("./KaTeX_SansSerif-Italic-HMPFTM52.woff2") format("woff2"),url("./KaTeX_SansSerif-Italic-PSN4QKYX.woff") format("woff"),url("./KaTeX_SansSerif-Italic-WTBAZBGY.ttf") format("truetype");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:KaTeX_SansSerif;src:url("./KaTeX_SansSerif-Regular-XIQ62X4E.woff2") format("woff2"),url("./KaTeX_SansSerif-Regular-OQCII6EP.woff") format("woff"),url("./KaTeX_SansSerif-Regular-2TL3USAE.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Script;src:url("./KaTeX_Script-Regular-APUWIHLP.woff2") format("woff2"),url("./KaTeX_Script-Regular-A5IFOEBS.woff") format("woff"),url("./KaTeX_Script-Regular-72OLXYNA.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Size1;src:url("./KaTeX_Size1-Regular-5LRUTBFT.woff2") format("woff2"),url("./KaTeX_Size1-Regular-4HRHTS65.woff") format("woff"),url("./KaTeX_Size1-Regular-7K6AASVL.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Size2;src:url("./KaTeX_Size2-Regular-LELKET5D.woff2") format("woff2"),url("./KaTeX_Size2-Regular-K5ZHAIS6.woff") format("woff"),url("./KaTeX_Size2-Regular-222HN3GT.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Size3;src:url("./KaTeX_Size3-Regular-WQRQ47UD.woff2") format("woff2"),url("./KaTeX_Size3-Regular-TLFPAHDE.woff") format("woff"),url("./KaTeX_Size3-Regular-UFCO6WCA.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Size4;src:url("./KaTeX_Size4-Regular-CDMV7U5C.woff2") format("woff2"),url("./KaTeX_Size4-Regular-PKMWZHNC.woff") format("woff"),url("./KaTeX_Size4-Regular-7PGNVPQK.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:KaTeX_Typewriter;src:url("./KaTeX_Typewriter-Regular-VBYJ4NRC.woff2") format("woff2"),url("./KaTeX_Typewriter-Regular-MJMFSK64.woff") format("woff"),url("./KaTeX_Typewriter-Regular-3F5K6SQ6.ttf") format("truetype");font-weight:400;font-style:normal;font-display:block}.katex{font: 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;position:relative;text-indent:0;text-rendering:auto}.katex *{-ms-high-contrast-adjust:none!important}.katex *{border-color:currentColor}.katex .katex-version:after{content:"0.16.47"}.katex .katex-mathml{position:absolute;-webkit-clip-path:inset(50%);clip-path:inset(50%);padding:0;border:0;height:1px;width:1px;overflow:hidden}.katex .katex-html>.newline{display:block}.katex .base{position:relative;display:inline-block;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-weight:700;font-style:italic}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathboldfrak,.katex .textboldfrak{font-family:KaTeX_Fraktur;font-weight:700}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathsfit,.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{display:inline-table;table-layout:fixed;border-collapse:collapse}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;vertical-align:bottom;position:relative}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;vertical-align:bottom;font-size:1px;width:2px;min-width:2px}.katex .vbox{display:inline-flex;flex-direction:column;align-items:baseline}.katex .hbox{display:inline-flex;flex-direction:row;width:100%}.katex .thinbox{display:inline-flex;flex-direction:row;width:0;max-width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{display:inline-block;width:100%;border-bottom-style:solid}.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .underline .underline-line,.katex .hline,.katex .hdashline,.katex .rule{min-height:1px}.katex .mspace{display:inline-block}.katex .smash{display:inline;line-height:0}.katex .llap,.katex .rlap,.katex .clap{width:0;position:relative}.katex .llap>.inner,.katex .rlap>.inner,.katex .clap>.inner{position:absolute}.katex .llap>.fix,.katex .rlap>.fix,.katex .clap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .rlap>.inner,.katex .clap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{display:inline-block;border:solid 0;position:relative}.katex .overline .overline-line,.katex .underline .underline-line,.katex .hline{display:inline-block;width:100%;border-bottom-style:solid}.katex .hdashline{display:inline-block;width:100%;border-bottom-style:dashed}.katex .sqrt>.root{margin-left:.2777777778em;margin-right:-.5555555556em}.katex .sizing.reset-size1.size1,.katex .fontsize-ensurer.reset-size1.size1{font-size:1em}.katex .sizing.reset-size1.size2,.katex .fontsize-ensurer.reset-size1.size2{font-size:1.2em}.katex .sizing.reset-size1.size3,.katex .fontsize-ensurer.reset-size1.size3{font-size:1.4em}.katex .sizing.reset-size1.size4,.katex .fontsize-ensurer.reset-size1.size4{font-size:1.6em}.katex .sizing.reset-size1.size5,.katex .fontsize-ensurer.reset-size1.size5{font-size:1.8em}.katex .sizing.reset-size1.size6,.katex .fontsize-ensurer.reset-size1.size6{font-size:2em}.katex .sizing.reset-size1.size7,.katex .fontsize-ensurer.reset-size1.size7{font-size:2.4em}.katex .sizing.reset-size1.size8,.katex .fontsize-ensurer.reset-size1.size8{font-size:2.88em}.katex .sizing.reset-size1.size9,.katex .fontsize-ensurer.reset-size1.size9{font-size:3.456em}.katex .sizing.reset-size1.size10,.katex .fontsize-ensurer.reset-size1.size10{font-size:4.148em}.katex .sizing.reset-size1.size11,.katex .fontsize-ensurer.reset-size1.size11{font-size:4.976em}.katex .sizing.reset-size2.size1,.katex .fontsize-ensurer.reset-size2.size1{font-size:.8333333333em}.katex .sizing.reset-size2.size2,.katex .fontsize-ensurer.reset-size2.size2{font-size:1em}.katex .sizing.reset-size2.size3,.katex .fontsize-ensurer.reset-size2.size3{font-size:1.1666666667em}.katex .sizing.reset-size2.size4,.katex .fontsize-ensurer.reset-size2.size4{font-size:1.3333333333em}.katex .sizing.reset-size2.size5,.katex .fontsize-ensurer.reset-size2.size5{font-size:1.5em}.katex .sizing.reset-size2.size6,.katex .fontsize-ensurer.reset-size2.size6{font-size:1.6666666667em}.katex .sizing.reset-size2.size7,.katex .fontsize-ensurer.reset-size2.size7{font-size:2em}.katex .sizing.reset-size2.size8,.katex .fontsize-ensurer.reset-size2.size8{font-size:2.4em}.katex .sizing.reset-size2.size9,.katex .fontsize-ensurer.reset-size2.size9{font-size:2.88em}.katex .sizing.reset-size2.size10,.katex .fontsize-ensurer.reset-size2.size10{font-size:3.4566666667em}.katex .sizing.reset-size2.size11,.katex .fontsize-ensurer.reset-size2.size11{font-size:4.1466666667em}.katex .sizing.reset-size3.size1,.katex .fontsize-ensurer.reset-size3.size1{font-size:.7142857143em}.katex .sizing.reset-size3.size2,.katex .fontsize-ensurer.reset-size3.size2{font-size:.8571428571em}.katex .sizing.reset-size3.size3,.katex .fontsize-ensurer.reset-size3.size3{font-size:1em}.katex .sizing.reset-size3.size4,.katex .fontsize-ensurer.reset-size3.size4{font-size:1.1428571429em}.katex .sizing.reset-size3.size5,.katex .fontsize-ensurer.reset-size3.size5{font-size:1.2857142857em}.katex .sizing.reset-size3.size6,.katex .fontsize-ensurer.reset-size3.size6{font-size:1.4285714286em}.katex .sizing.reset-size3.size7,.katex .fontsize-ensurer.reset-size3.size7{font-size:1.7142857143em}.katex .sizing.reset-size3.size8,.katex .fontsize-ensurer.reset-size3.size8{font-size:2.0571428571em}.katex .sizing.reset-size3.size9,.katex .fontsize-ensurer.reset-size3.size9{font-size:2.4685714286em}.katex .sizing.reset-size3.size10,.katex .fontsize-ensurer.reset-size3.size10{font-size:2.9628571429em}.katex .sizing.reset-size3.size11,.katex .fontsize-ensurer.reset-size3.size11{font-size:3.5542857143em}.katex .sizing.reset-size4.size1,.katex .fontsize-ensurer.reset-size4.size1{font-size:.625em}.katex .sizing.reset-size4.size2,.katex .fontsize-ensurer.reset-size4.size2{font-size:.75em}.katex .sizing.reset-size4.size3,.katex .fontsize-ensurer.reset-size4.size3{font-size:.875em}.katex .sizing.reset-size4.size4,.katex .fontsize-ensurer.reset-size4.size4{font-size:1em}.katex .sizing.reset-size4.size5,.katex .fontsize-ensurer.reset-size4.size5{font-size:1.125em}.katex .sizing.reset-size4.size6,.katex .fontsize-ensurer.reset-size4.size6{font-size:1.25em}.katex .sizing.reset-size4.size7,.katex .fontsize-ensurer.reset-size4.size7{font-size:1.5em}.katex .sizing.reset-size4.size8,.katex .fontsize-ensurer.reset-size4.size8{font-size:1.8em}.katex .sizing.reset-size4.size9,.katex .fontsize-ensurer.reset-size4.size9{font-size:2.16em}.katex .sizing.reset-size4.size10,.katex .fontsize-ensurer.reset-size4.size10{font-size:2.5925em}.katex .sizing.reset-size4.size11,.katex .fontsize-ensurer.reset-size4.size11{font-size:3.11em}.katex .sizing.reset-size5.size1,.katex .fontsize-ensurer.reset-size5.size1{font-size:.5555555556em}.katex .sizing.reset-size5.size2,.katex .fontsize-ensurer.reset-size5.size2{font-size:.6666666667em}.katex .sizing.reset-size5.size3,.katex .fontsize-ensurer.reset-size5.size3{font-size:.7777777778em}.katex .sizing.reset-size5.size4,.katex .fontsize-ensurer.reset-size5.size4{font-size:.8888888889em}.katex .sizing.reset-size5.size5,.katex .fontsize-ensurer.reset-size5.size5{font-size:1em}.katex .sizing.reset-size5.size6,.katex .fontsize-ensurer.reset-size5.size6{font-size:1.1111111111em}.katex .sizing.reset-size5.size7,.katex .fontsize-ensurer.reset-size5.size7{font-size:1.3333333333em}.katex .sizing.reset-size5.size8,.katex .fontsize-ensurer.reset-size5.size8{font-size:1.6em}.katex .sizing.reset-size5.size9,.katex .fontsize-ensurer.reset-size5.size9{font-size:1.92em}.katex .sizing.reset-size5.size10,.katex .fontsize-ensurer.reset-size5.size10{font-size:2.3044444444em}.katex .sizing.reset-size5.size11,.katex .fontsize-ensurer.reset-size5.size11{font-size:2.7644444444em}.katex .sizing.reset-size6.size1,.katex .fontsize-ensurer.reset-size6.size1{font-size:.5em}.katex .sizing.reset-size6.size2,.katex .fontsize-ensurer.reset-size6.size2{font-size:.6em}.katex .sizing.reset-size6.size3,.katex .fontsize-ensurer.reset-size6.size3{font-size:.7em}.katex .sizing.reset-size6.size4,.katex .fontsize-ensurer.reset-size6.size4{font-size:.8em}.katex .sizing.reset-size6.size5,.katex .fontsize-ensurer.reset-size6.size5{font-size:.9em}.katex .sizing.reset-size6.size6,.katex .fontsize-ensurer.reset-size6.size6{font-size:1em}.katex .sizing.reset-size6.size7,.katex .fontsize-ensurer.reset-size6.size7{font-size:1.2em}.katex .sizing.reset-size6.size8,.katex .fontsize-ensurer.reset-size6.size8{font-size:1.44em}.katex .sizing.reset-size6.size9,.katex .fontsize-ensurer.reset-size6.size9{font-size:1.728em}.katex .sizing.reset-size6.size10,.katex .fontsize-ensurer.reset-size6.size10{font-size:2.074em}.katex .sizing.reset-size6.size11,.katex .fontsize-ensurer.reset-size6.size11{font-size:2.488em}.katex .sizing.reset-size7.size1,.katex .fontsize-ensurer.reset-size7.size1{font-size:.4166666667em}.katex .sizing.reset-size7.size2,.katex .fontsize-ensurer.reset-size7.size2{font-size:.5em}.katex .sizing.reset-size7.size3,.katex .fontsize-ensurer.reset-size7.size3{font-size:.5833333333em}.katex .sizing.reset-size7.size4,.katex .fontsize-ensurer.reset-size7.size4{font-size:.6666666667em}.katex .sizing.reset-size7.size5,.katex .fontsize-ensurer.reset-size7.size5{font-size:.75em}.katex .sizing.reset-size7.size6,.katex .fontsize-ensurer.reset-size7.size6{font-size:.8333333333em}.katex .sizing.reset-size7.size7,.katex .fontsize-ensurer.reset-size7.size7{font-size:1em}.katex .sizing.reset-size7.size8,.katex .fontsize-ensurer.reset-size7.size8{font-size:1.2em}.katex .sizing.reset-size7.size9,.katex .fontsize-ensurer.reset-size7.size9{font-size:1.44em}.katex .sizing.reset-size7.size10,.katex .fontsize-ensurer.reset-size7.size10{font-size:1.7283333333em}.katex .sizing.reset-size7.size11,.katex .fontsize-ensurer.reset-size7.size11{font-size:2.0733333333em}.katex .sizing.reset-size8.size1,.katex .fontsize-ensurer.reset-size8.size1{font-size:.3472222222em}.katex .sizing.reset-size8.size2,.katex .fontsize-ensurer.reset-size8.size2{font-size:.4166666667em}.katex .sizing.reset-size8.size3,.katex .fontsize-ensurer.reset-size8.size3{font-size:.4861111111em}.katex .sizing.reset-size8.size4,.katex .fontsize-ensurer.reset-size8.size4{font-size:.5555555556em}.katex .sizing.reset-size8.size5,.katex .fontsize-ensurer.reset-size8.size5{font-size:.625em}.katex .sizing.reset-size8.size6,.katex .fontsize-ensurer.reset-size8.size6{font-size:.6944444444em}.katex .sizing.reset-size8.size7,.katex .fontsize-ensurer.reset-size8.size7{font-size:.8333333333em}.katex .sizing.reset-size8.size8,.katex .fontsize-ensurer.reset-size8.size8{font-size:1em}.katex .sizing.reset-size8.size9,.katex .fontsize-ensurer.reset-size8.size9{font-size:1.2em}.katex .sizing.reset-size8.size10,.katex .fontsize-ensurer.reset-size8.size10{font-size:1.4402777778em}.katex .sizing.reset-size8.size11,.katex .fontsize-ensurer.reset-size8.size11{font-size:1.7277777778em}.katex .sizing.reset-size9.size1,.katex .fontsize-ensurer.reset-size9.size1{font-size:.2893518519em}.katex .sizing.reset-size9.size2,.katex .fontsize-ensurer.reset-size9.size2{font-size:.3472222222em}.katex .sizing.reset-size9.size3,.katex .fontsize-ensurer.reset-size9.size3{font-size:.4050925926em}.katex .sizing.reset-size9.size4,.katex .fontsize-ensurer.reset-size9.size4{font-size:.462962963em}.katex .sizing.reset-size9.size5,.katex .fontsize-ensurer.reset-size9.size5{font-size:.5208333333em}.katex .sizing.reset-size9.size6,.katex .fontsize-ensurer.reset-size9.size6{font-size:.5787037037em}.katex .sizing.reset-size9.size7,.katex .fontsize-ensurer.reset-size9.size7{font-size:.6944444444em}.katex .sizing.reset-size9.size8,.katex .fontsize-ensurer.reset-size9.size8{font-size:.8333333333em}.katex .sizing.reset-size9.size9,.katex .fontsize-ensurer.reset-size9.size9{font-size:1em}.katex .sizing.reset-size9.size10,.katex .fontsize-ensurer.reset-size9.size10{font-size:1.2002314815em}.katex .sizing.reset-size9.size11,.katex .fontsize-ensurer.reset-size9.size11{font-size:1.4398148148em}.katex .sizing.reset-size10.size1,.katex .fontsize-ensurer.reset-size10.size1{font-size:.2410800386em}.katex .sizing.reset-size10.size2,.katex .fontsize-ensurer.reset-size10.size2{font-size:.2892960463em}.katex .sizing.reset-size10.size3,.katex .fontsize-ensurer.reset-size10.size3{font-size:.337512054em}.katex .sizing.reset-size10.size4,.katex .fontsize-ensurer.reset-size10.size4{font-size:.3857280617em}.katex .sizing.reset-size10.size5,.katex .fontsize-ensurer.reset-size10.size5{font-size:.4339440694em}.katex .sizing.reset-size10.size6,.katex .fontsize-ensurer.reset-size10.size6{font-size:.4821600771em}.katex .sizing.reset-size10.size7,.katex .fontsize-ensurer.reset-size10.size7{font-size:.5785920926em}.katex .sizing.reset-size10.size8,.katex .fontsize-ensurer.reset-size10.size8{font-size:.6943105111em}.katex .sizing.reset-size10.size9,.katex .fontsize-ensurer.reset-size10.size9{font-size:.8331726133em}.katex .sizing.reset-size10.size10,.katex .fontsize-ensurer.reset-size10.size10{font-size:1em}.katex .sizing.reset-size10.size11,.katex .fontsize-ensurer.reset-size10.size11{font-size:1.1996142719em}.katex .sizing.reset-size11.size1,.katex .fontsize-ensurer.reset-size11.size1{font-size:.2009646302em}.katex .sizing.reset-size11.size2,.katex .fontsize-ensurer.reset-size11.size2{font-size:.2411575563em}.katex .sizing.reset-size11.size3,.katex .fontsize-ensurer.reset-size11.size3{font-size:.2813504823em}.katex .sizing.reset-size11.size4,.katex .fontsize-ensurer.reset-size11.size4{font-size:.3215434084em}.katex .sizing.reset-size11.size5,.katex .fontsize-ensurer.reset-size11.size5{font-size:.3617363344em}.katex .sizing.reset-size11.size6,.katex .fontsize-ensurer.reset-size11.size6{font-size:.4019292605em}.katex .sizing.reset-size11.size7,.katex .fontsize-ensurer.reset-size11.size7{font-size:.4823151125em}.katex .sizing.reset-size11.size8,.katex .fontsize-ensurer.reset-size11.size8{font-size:.578778135em}.katex .sizing.reset-size11.size9,.katex .fontsize-ensurer.reset-size11.size9{font-size:.6945337621em}.katex .sizing.reset-size11.size10,.katex .fontsize-ensurer.reset-size11.size10{font-size:.8336012862em}.katex .sizing.reset-size11.size11,.katex .fontsize-ensurer.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .op-limits>.vlist-t{text-align:center}.katex .accent>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{display:block;position:absolute;width:100%;height:inherit;fill:currentColor;stroke:currentColor}.katex svg path{stroke:none}.katex svg{fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1}.katex img{border-style:none;min-width:0;min-height:0;max-width:none;max-height:none}.katex .stretchy{width:100%;display:block;position:relative;overflow:hidden}.katex .stretchy:before,.katex .stretchy:after{content:""}.katex .hide-tail{width:100%;position:relative;overflow:hidden}.katex .halfarrow-left{position:absolute;left:0;width:50.2%;overflow:hidden}.katex .halfarrow-right{position:absolute;right:0;width:50.2%;overflow:hidden}.katex .brace-left{position:absolute;left:0;width:25.1%;overflow:hidden}.katex .brace-center{position:absolute;left:25%;width:50%;overflow:hidden}.katex .brace-right{position:absolute;right:0;width:25.1%;overflow:hidden}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .x-arrow,.katex .mover,.katex .munder{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{box-sizing:border-box;border:.04em solid}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{box-sizing:border-box;border-top:.049em solid;border-right:.049em solid;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{counter-increment:katexEqnNo;content:"(" counter(katexEqnNo) ")"}.katex .mml-eqn-num:before{counter-increment:mmlEqnNo;content:"(" counter(mmlEqnNo) ")"}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;position:absolute;left:calc(50% + .3em);text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{text-align:left;padding-left:2em}body{counter-reset:katexEqnNo mmlEqnNo}:root{color-scheme:dark;--terminal-background: #242830;--terminal-foreground: #e7e9ee;--terminal-font: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;--terminal-font-size: 15px;--terminal-line-height: 1.22}*{box-sizing:border-box}html,body{width:100%;height:100%;margin:0;overflow:hidden;background:var(--terminal-background);color:var(--terminal-foreground);font-family:var(--terminal-font)}body{display:grid;grid-template-rows:34px minmax(0,1fr)}header{z-index:2;display:flex;align-items:center;gap:12px;padding:0 12px;border-bottom:1px solid #3a414d;background:#1c2027;color:#aeb5c1;font-size:12px}.brand{color:#f0f2f6;font-weight:700}.mode{margin-left:auto}#download-html{padding:3px 9px;border:1px solid #525b69;border-radius:4px;background:#292f38;color:#d8dce4;font:inherit;cursor:pointer}#download-html:hover:not(:disabled){border-color:#73c9d2;color:#f0f2f6}#download-html:disabled{cursor:wait;opacity:.55}.live{color:#70d68b}.error{color:#ff7b72}#transcript-host{min-width:0;min-height:0;overflow:auto;overflow-anchor:none;background:var(--terminal-background)}#transcript{width:max(100%,calc(var(--terminal-columns, 80) * 1ch + 32px));min-height:100%;padding:10px 16px 18vh;font-family:var(--terminal-font);font-size:var(--terminal-font-size);line-height:var(--terminal-line-height);font-variant-ligatures:none}.transcript-block{width:100%}.terminal-group{margin:0 0 .8rem}.terminal-group.panel{margin:.45rem 0 1rem}.terminal-row{min-height:calc(1em * var(--terminal-line-height));margin:0;white-space:pre}.message{position:relative;min-width:0;margin:0 0 1rem;padding:.45rem 1.2rem .65rem 2rem;overflow-wrap:anywhere}.message.assistant:before{position:absolute;top:.55rem;left:.15rem;color:#aeb5c1;content:"\2022"}.message.user{margin:.45rem 0 1rem;padding:.8rem 1.2rem;background:#444955}.message>:first-child{margin-top:0}.message>:last-child{margin-bottom:0}.message p,.message ul,.message ol,.message blockquote,.message pre,.message table,.message .math-display{margin:.7rem 0}.message h1,.message h2,.message h3,.message h4,.message h5,.message h6{margin:1.15rem 0 .55rem;color:#f1f3f7;line-height:1.25}.message h1{padding-bottom:.3rem;border-bottom:1px solid #4a515e;font-size:1.55rem}.message h2{font-size:1.3rem}.message h3{font-size:1.1rem;font-style:italic}.message ul,.message ol{padding-left:1.7rem}.message li+li{margin-top:.25rem}.message blockquote{padding:.2rem 0 .2rem .9rem;border-left:3px solid #697386;color:#c1c6d0}.message code{padding:.08rem .3rem;border:1px solid #454c59;border-radius:4px;background:#1d2128;color:#f0d9a6;font-family:var(--terminal-font);font-size:.93em}.message pre{max-width:100%;padding:.85rem 1rem;overflow:auto;border:1px solid #3c4350;border-radius:7px;background:#1b1f26;white-space:pre}.message pre code{padding:0;border:0;background:transparent;color:#e7e9ee;font-size:.92rem}.message .hljs-comment,.message .hljs-quote{color:#82909f;font-style:italic}.message .hljs-keyword,.message .hljs-selector-tag,.message .hljs-literal,.message .hljs-section,.message .hljs-link{color:#d2a8ff}.message .hljs-string,.message .hljs-attr,.message .hljs-template-tag,.message .hljs-template-variable,.message .hljs-regexp,.message .hljs-addition{color:#a5d6a7}.message .hljs-number,.message .hljs-symbol,.message .hljs-bullet,.message .hljs-variable,.message .hljs-variable.constant_,.message .hljs-meta{color:#79c0ff}.message .hljs-title,.message .hljs-title.class_,.message .hljs-title.function_,.message .hljs-selector-id,.message .hljs-selector-class{color:#dcdcaa}.message .hljs-built_in,.message .hljs-type,.message .hljs-params,.message .hljs-attribute{color:#ffa657}.message .hljs-name,.message .hljs-tag,.message .hljs-deletion{color:#ff7b72}.message .hljs-property,.message .hljs-punctuation{color:#c9d1d9}.message .hljs-emphasis{font-style:italic}.message .hljs-strong{font-weight:700}.message img{display:block;max-width:100%;height:auto;margin:.65rem 0;border:1px solid #3c4350;border-radius:7px}.copy-inline{cursor:copy}.copy-inline:hover,.copy-inline:focus-visible{border-color:#73c9d2;background:#29343c;color:#fff0c6;outline:none}.copy-inline:active,.copy-inline.copy-pressed{border-color:#70d68b;background:#20352c;color:#baf2c8}.copy-inline.copy-failed{border-color:#ff7b72}.copy-block{position:relative;border-radius:7px;cursor:copy}.copy-block:after{position:absolute;top:.42rem;right:.55rem;z-index:1;padding:.16rem .4rem;border:1px solid #56606f;border-radius:4px;background:#252b34;color:#c8ced8;content:"Copy";font-size:.7rem;line-height:1.2;opacity:0;pointer-events:none;transition:opacity .12s ease}.copy-block:hover:after,.copy-block:focus-visible:after,.copy-block:active:after,.copy-block.copy-pressed:after,.copy-block.copy-failed:after{opacity:1}.copy-block:hover>pre,.copy-block:focus-visible>pre{border-color:#5c7d87;background:#20262e}.copy-block:focus-visible{outline:1px solid #73c9d2;outline-offset:2px}.copy-block:active:after,.copy-block.copy-pressed:after{border-color:#70d68b;color:#9be9ad}.copy-block.copy-failed:after{border-color:#ff7b72;color:#ff9b94;content:"Copy failed"}.latex-fence.copy-block{padding:.42rem .55rem;border:1px solid transparent}.latex-fence.copy-block:hover,.latex-fence.copy-block:focus-visible{border-color:#4e6570;background:#282e36}.mermaid-diagram{min-height:4rem;margin:.65rem 0;padding:.8rem;overflow:auto;border:1px solid #3c4350;background:#20242b}.mermaid-diagram:hover,.mermaid-diagram:focus-visible{border-color:#5c7d87;background:#232a32}.mermaid-diagram>svg{display:block;max-width:100%;height:auto;margin:auto}.mermaid-diagram .mermaid-source{margin:0;border:0;background:transparent;white-space:pre-wrap}.mermaid-diagram[data-mermaid-state=failed]{border-color:#ff7b72}.message table{display:block;max-width:100%;overflow-x:auto;border-spacing:0;border-collapse:collapse}.message th,.message td{padding:.45rem .7rem;border:1px solid #48505d;text-align:left;white-space:nowrap}.message th{background:#343a45;color:#f1f3f7}.message tr:nth-child(2n) td{background:#292e37}.message a{color:#73c9d2;text-decoration-thickness:1px;text-underline-offset:.18em}.message hr{margin:1.1rem 0;border:0;border-top:1px solid #48505d}.math-display,.math-inline-display{max-width:100%;overflow-x:auto}.math-display .katex-display,.math-inline-display .katex-display{margin:0;text-align:left!important}.math-inline-display{display:inline-block;vertical-align:middle}.math-source{padding:.65rem .8rem;border-left:3px solid #697386;background:#1f242c;color:#d9dde5;white-space:pre-wrap}.math-source-inline{color:inherit;white-space:pre-wrap}