@oharness/server 0.7.0 → 0.7.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.
- package/dist/i18n.js +12 -0
- package/dist/i18n.js.map +1 -1
- package/dist/page.js +311 -15
- package/dist/page.js.map +1 -1
- package/dist/server.js +163 -4
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
package/dist/page.js
CHANGED
|
@@ -1984,9 +1984,28 @@ details.thinking[open]>summary::after{transform:translateY(-2px) rotate(45deg)}
|
|
|
1984
1984
|
/* composer */
|
|
1985
1985
|
form{padding:6px 24px 18px;background:var(--bg)}
|
|
1986
1986
|
.composer{
|
|
1987
|
+
position:relative;
|
|
1987
1988
|
max-width:720px;margin:0 auto;border-radius:16px;
|
|
1988
1989
|
background:var(--field);padding:16px 16px 10px;transition:background .15s,box-shadow .15s;
|
|
1989
1990
|
}
|
|
1991
|
+
/* The top edge, as a grab handle. It spans the box rather than sitting in a
|
|
1992
|
+
corner, because the edge is what a person aims at; the bar only appears
|
|
1993
|
+
under the cursor, so an idle composer keeps its clean top line. */
|
|
1994
|
+
#grip{
|
|
1995
|
+
position:absolute;top:0;left:0;right:0;height:12px;cursor:ns-resize;
|
|
1996
|
+
display:grid;place-items:center;touch-action:none;
|
|
1997
|
+
}
|
|
1998
|
+
/* Faint rather than hidden: a handle nobody can see is a handle nobody
|
|
1999
|
+
finds. A pill, not a rule across the top — this is a thing to grab, and the
|
|
2000
|
+
design carries no borders. */
|
|
2001
|
+
#grip::before{
|
|
2002
|
+
content:"";width:32px;height:3px;border-radius:999px;
|
|
2003
|
+
background:var(--dim);opacity:.2;transition:opacity .12s,width .12s;
|
|
2004
|
+
}
|
|
2005
|
+
#grip:hover::before,#grip.dragging::before{opacity:.5;width:40px}
|
|
2006
|
+
/* While dragging, the pointer owns the screen: without this a fast drag
|
|
2007
|
+
selects the transcript behind it. */
|
|
2008
|
+
body.resizing{user-select:none;cursor:ns-resize}
|
|
1990
2009
|
.composer:focus-within{background:var(--field-focus)}
|
|
1991
2010
|
textarea{
|
|
1992
2011
|
width:100%;resize:none;min-height:56px;max-height:32vh;padding:0;border:0;
|
|
@@ -2009,7 +2028,23 @@ textarea::placeholder{color:var(--dim)}
|
|
|
2009
2028
|
the field only has to agree on where each glyph lands, not on what is
|
|
2010
2029
|
drawn there. The selection is translucent so the words under it stay
|
|
2011
2030
|
readable; an opaque highlight would sit on top of the mirror. */
|
|
2012
|
-
.
|
|
2031
|
+
/* The native caret is hidden and one is drawn instead. A textarea offers
|
|
2032
|
+
caret-color and nothing else — no width — and at one device pixel the bar
|
|
2033
|
+
is hard to find on a pale field. See placeCaret(). */
|
|
2034
|
+
.input-wrap textarea{color:transparent;caret-color:transparent}
|
|
2035
|
+
#caret{
|
|
2036
|
+
position:absolute;width:2px;border-radius:1px;background:var(--brand);
|
|
2037
|
+
pointer-events:none;z-index:2;opacity:0;
|
|
2038
|
+
}
|
|
2039
|
+
#caret.on{animation:caret-blink 1.06s steps(1,end) infinite}
|
|
2040
|
+
@keyframes caret-blink{0%,55%{opacity:1}56%,100%{opacity:0}}
|
|
2041
|
+
/* Solid while the caret is moving: a bar that blinks out mid-keystroke reads
|
|
2042
|
+
as a dropped character. The class is taken off and put back to restart the
|
|
2043
|
+
animation, which is what makes the phase reset. */
|
|
2044
|
+
#caret.on.moving{animation:none;opacity:1}
|
|
2045
|
+
@media (prefers-reduced-motion:reduce){#caret.on{animation:none;opacity:1}}
|
|
2046
|
+
/* Measures where the caret goes: the mirror's metrics, none of its ink. */
|
|
2047
|
+
#caret-probe{visibility:hidden}
|
|
2013
2048
|
.input-wrap textarea::selection{background:var(--brand-tint)}
|
|
2014
2049
|
/* Every metric that decides where a glyph lands has to match the field: font,
|
|
2015
2050
|
line-height, wrapping, and the padding, which is zero on this textarea.
|
|
@@ -2017,7 +2052,7 @@ textarea::placeholder{color:var(--dim)}
|
|
|
2017
2052
|
glyphs land where the textarea puts them, and the chip's background — drawn
|
|
2018
2053
|
outside its own advance width — has somewhere to go instead of being cut off
|
|
2019
2054
|
at the start of a line. */
|
|
2020
|
-
#input-mirror{
|
|
2055
|
+
#input-mirror,#caret-probe{
|
|
2021
2056
|
position:absolute;top:0;bottom:0;left:-6px;right:-6px;padding:0 6px;border:0;
|
|
2022
2057
|
font:inherit;line-height:1.6;white-space:pre-wrap;overflow-wrap:break-word;
|
|
2023
2058
|
color:var(--fg);pointer-events:none;overflow:hidden;
|
|
@@ -2109,6 +2144,41 @@ textarea.boxed:focus{outline:none;background:var(--field-focus)}
|
|
|
2109
2144
|
.effort-name.on{color:var(--fg);font-weight:600}
|
|
2110
2145
|
#attachments{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
|
|
2111
2146
|
#attachments:empty{display:none}
|
|
2147
|
+
/* Outside the composer, tracking its width so the rows line up with the box
|
|
2148
|
+
they are waiting on. min-width:0 twice over — here and on the line inside
|
|
2149
|
+
each row — because a flex item defaults to refusing to shrink below its
|
|
2150
|
+
content, and one long queued line would push the page sideways at phone
|
|
2151
|
+
width instead of being cut. */
|
|
2152
|
+
#queued{
|
|
2153
|
+
display:flex;flex-direction:column;gap:4px;min-width:0;
|
|
2154
|
+
max-width:720px;margin:0 auto 6px;
|
|
2155
|
+
}
|
|
2156
|
+
#queued:empty{display:none}
|
|
2157
|
+
/* Full width, one per row, because these are sentences rather than file
|
|
2158
|
+
names: a chip that fits three words of a queued message says nothing about
|
|
2159
|
+
which message it is. --panel, not --field: out here the backdrop is the
|
|
2160
|
+
page, and the field's 2% wash is invisible against it. */
|
|
2161
|
+
.q{display:flex;align-items:center;gap:8px;background:var(--panel);border-radius:10px;padding:7px 10px 7px 12px;font-size:12px;min-width:0}
|
|
2162
|
+
/* min-width:0 or the ellipsis never engages: a flex item refuses to shrink
|
|
2163
|
+
below its content by default, so at phone width the row pushed the page
|
|
2164
|
+
sideways instead of cutting the line. */
|
|
2165
|
+
.q .n{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--dim)}
|
|
2166
|
+
/* Not ".mark": that is the connector glyph, and it is a fixed 18px box. */
|
|
2167
|
+
.q .tag{flex:0 0 auto;color:var(--dim);font-size:11px}
|
|
2168
|
+
/* Joining the turn already running, rather than waiting behind it. The brand
|
|
2169
|
+
colour is what this app uses for the harness being alive, which is exactly
|
|
2170
|
+
what the difference is. */
|
|
2171
|
+
.q.soon .tag{color:var(--brand-ink)}
|
|
2172
|
+
:root[data-theme="dark"] .q.soon .tag{color:var(--brand)}
|
|
2173
|
+
.q .go{
|
|
2174
|
+
flex:0 0 auto;height:22px;padding:0 9px;border:0;border-radius:7px;
|
|
2175
|
+
background:var(--hover);color:var(--fg);cursor:pointer;
|
|
2176
|
+
font:inherit;font-size:11px;white-space:nowrap;
|
|
2177
|
+
}
|
|
2178
|
+
.q .go:hover{background:var(--brand-tint);color:var(--brand-ink)}
|
|
2179
|
+
:root[data-theme="dark"] .q .go:hover{color:var(--brand)}
|
|
2180
|
+
.q .x{border:0;background:transparent;color:var(--dim);cursor:pointer;font:inherit;padding:0 2px}
|
|
2181
|
+
.q .x:hover{color:var(--err)}
|
|
2112
2182
|
.att{
|
|
2113
2183
|
display:flex;align-items:center;gap:7px;background:var(--bg);border-radius:8px;
|
|
2114
2184
|
padding:5px 8px;font-size:12px;max-width:260px;
|
|
@@ -2199,6 +2269,11 @@ button.primary{
|
|
|
2199
2269
|
}
|
|
2200
2270
|
button.primary svg{width:16px;height:16px}
|
|
2201
2271
|
button.primary:disabled{opacity:.3;cursor:default}
|
|
2272
|
+
/* Idle with messages still waiting: send releases them, and the button says
|
|
2273
|
+
so by quietly breathing rather than by growing an outline. */
|
|
2274
|
+
#send.has-queue{animation:queue-wait 2.4s ease-in-out infinite}
|
|
2275
|
+
@keyframes queue-wait{0%,100%{opacity:1}50%{opacity:.55}}
|
|
2276
|
+
@media (prefers-reduced-motion:reduce){#send.has-queue{animation:none;opacity:.8}}
|
|
2202
2277
|
button.ghost,a.ghost{
|
|
2203
2278
|
height:30px;padding:0 12px;border:0;border-radius:8px;
|
|
2204
2279
|
background:var(--sel);color:var(--fg);font:inherit;font-size:12.5px;cursor:pointer;
|
|
@@ -2399,6 +2474,10 @@ dialog::backdrop{background:rgba(0,0,0,.55)}
|
|
|
2399
2474
|
.composer .picker{position:static;min-width:0}
|
|
2400
2475
|
.composer .picker-btn{max-width:100%;height:32px}
|
|
2401
2476
|
#send,#stop{flex:0 0 auto}
|
|
2477
|
+
/* No hover on a touch screen, so the bar is always drawn, and the strip is
|
|
2478
|
+
taller because a thumb is not a cursor. */
|
|
2479
|
+
#grip{height:18px}
|
|
2480
|
+
#grip::before{opacity:.3;width:40px}
|
|
2402
2481
|
textarea{max-height:32dvh}
|
|
2403
2482
|
/* Menus span the box rather than hang off one picker: from a picker on the
|
|
2404
2483
|
right they otherwise open past the edge, where overflow:hidden loses them. */
|
|
@@ -4047,7 +4126,7 @@ function pane(id) {
|
|
|
4047
4126
|
const node = el("div", "pane");
|
|
4048
4127
|
node.hidden = true;
|
|
4049
4128
|
log.appendChild(node);
|
|
4050
|
-
entry = { node, title: t("session.untitled"), cwd: "", busy: false, turn: null, streaming: null, tools: new Map(), thinking: null };
|
|
4129
|
+
entry = { node, title: t("session.untitled"), cwd: "", busy: false, queued: [], turn: null, streaming: null, tools: new Map(), thinking: null };
|
|
4051
4130
|
panes.set(id, entry);
|
|
4052
4131
|
}
|
|
4053
4132
|
return entry;
|
|
@@ -4194,6 +4273,10 @@ function applyState(s) {
|
|
|
4194
4273
|
ctxText.textContent = pct + "%";
|
|
4195
4274
|
}
|
|
4196
4275
|
setBusy(Boolean(s.busy));
|
|
4276
|
+
// Addressed by session: a reload and a tab switch both land here, and the
|
|
4277
|
+
// pane this state describes is not always the one an event last touched.
|
|
4278
|
+
if (s.sessionId) pane(s.sessionId).queued = s.queued || [];
|
|
4279
|
+
renderQueued();
|
|
4197
4280
|
}
|
|
4198
4281
|
|
|
4199
4282
|
let workingNode = null;
|
|
@@ -4248,6 +4331,9 @@ function setBusy(busy) {
|
|
|
4248
4331
|
sendBtn.hidden = busy;
|
|
4249
4332
|
stopBtn.hidden = !busy;
|
|
4250
4333
|
if (!busy) stopWorking();
|
|
4334
|
+
// The row itself does not change, but whether the queue can be released by
|
|
4335
|
+
// hand does, and that is drawn on the send button.
|
|
4336
|
+
renderQueued();
|
|
4251
4337
|
}
|
|
4252
4338
|
|
|
4253
4339
|
/** "just now", "12m", "3h", "yesterday", "6 Aug" — scannable at a glance. */
|
|
@@ -5428,6 +5514,14 @@ events.onmessage = (message) => {
|
|
|
5428
5514
|
break;
|
|
5429
5515
|
}
|
|
5430
5516
|
|
|
5517
|
+
// One event carrying the whole list rather than add/remove pairs: the
|
|
5518
|
+
// page redraws from it, so a dropped event cannot leave a chip behind for
|
|
5519
|
+
// a message that was sent ten minutes ago.
|
|
5520
|
+
case "queue":
|
|
5521
|
+
P.queued = event.queued || [];
|
|
5522
|
+
renderQueued();
|
|
5523
|
+
break;
|
|
5524
|
+
|
|
5431
5525
|
case "assistant_message": P.streaming = null; break;
|
|
5432
5526
|
case "turn_start": dropPendingTools(); break;
|
|
5433
5527
|
case "tool_pending":
|
|
@@ -6334,6 +6428,7 @@ function questionSettled(entry) {
|
|
|
6334
6428
|
// stays small and a half-finished upload cannot start a turn.
|
|
6335
6429
|
|
|
6336
6430
|
const attachEl = document.getElementById("attachments");
|
|
6431
|
+
const queuedEl = document.getElementById("queued");
|
|
6337
6432
|
const fileInput = document.getElementById("file");
|
|
6338
6433
|
const composerBox = document.getElementById("composer-box");
|
|
6339
6434
|
let staged = [];
|
|
@@ -6354,6 +6449,52 @@ let refs = [];
|
|
|
6354
6449
|
const REF_ICON = { file: "file", folder: "folder", connector: "plug", plugin: "plugin", skill: "skill" };
|
|
6355
6450
|
const refKey = (ref) => ref.kind + ":" + ref.value;
|
|
6356
6451
|
|
|
6452
|
+
/**
|
|
6453
|
+
* The messages waiting behind the running turn.
|
|
6454
|
+
*
|
|
6455
|
+
* Drawn from the pane rather than from a local list: the queue lives on the
|
|
6456
|
+
* server, so a reload and a second tab show the same thing, and an entry that
|
|
6457
|
+
* has just been sent disappears because the server said so.
|
|
6458
|
+
*/
|
|
6459
|
+
function renderQueued() {
|
|
6460
|
+
queuedEl.replaceChildren();
|
|
6461
|
+
// The active pane, not the event-scoped P: this row sits in the composer,
|
|
6462
|
+
// and the composer belongs to the tab on screen even while a background
|
|
6463
|
+
// tab is the one streaming.
|
|
6464
|
+
const here = panes.get(activeId);
|
|
6465
|
+
const waiting = (here && here.queued) || [];
|
|
6466
|
+
for (const entry of waiting) {
|
|
6467
|
+
const row = el("div", "q" + (entry.soon ? " soon" : ""));
|
|
6468
|
+
// Two different promises: one joins the turn that is running, the other
|
|
6469
|
+
// waits for it to end. Saying "Queued" for both would misdescribe half.
|
|
6470
|
+
row.appendChild(el("span", "tag", t(entry.soon ? "queue.soon" : "queue.mark")));
|
|
6471
|
+
const names = (entry.attachments || []).join(", ");
|
|
6472
|
+
row.appendChild(el("span", "n", entry.text || names || t("queue.attachmentsOnly")));
|
|
6473
|
+
// Only on the ones that are waiting. A message already handed to the
|
|
6474
|
+
// running turn is as immediate as it gets, and a second button promising
|
|
6475
|
+
// to hurry it would be promising nothing.
|
|
6476
|
+
if (!entry.soon) {
|
|
6477
|
+
// Words, not an arrow. An arrow beside a × on a row that is already
|
|
6478
|
+
// about sending reads as "next" or "move"; the one thing it has to say
|
|
6479
|
+
// is that this message goes now.
|
|
6480
|
+
const now = el("button", "go", t("queue.sendNow"));
|
|
6481
|
+
now.type = "button";
|
|
6482
|
+
now.addEventListener("click", () => void api("/sendnow", { session: activeId, id: entry.id }));
|
|
6483
|
+
row.appendChild(now);
|
|
6484
|
+
}
|
|
6485
|
+
const drop = el("button", "x", "×");
|
|
6486
|
+
drop.type = "button";
|
|
6487
|
+
drop.title = t("queue.drop");
|
|
6488
|
+
drop.addEventListener("click", () => void api("/unqueue", { session: activeId, id: entry.id }));
|
|
6489
|
+
row.appendChild(drop);
|
|
6490
|
+
queuedEl.appendChild(row);
|
|
6491
|
+
}
|
|
6492
|
+
// Idle with something still waiting means the turn was stopped or failed —
|
|
6493
|
+
// the server will not restart a queue on its own after either. The send
|
|
6494
|
+
// button becomes the way to let it go.
|
|
6495
|
+
sendBtn.classList.toggle("has-queue", waiting.length > 0 && !(here && here.busy));
|
|
6496
|
+
}
|
|
6497
|
+
|
|
6357
6498
|
function renderAttachments() {
|
|
6358
6499
|
attachEl.replaceChildren();
|
|
6359
6500
|
|
|
@@ -7401,8 +7542,7 @@ input.addEventListener("keydown", (e) => {
|
|
|
7401
7542
|
input.setSelectionRange(from, from);
|
|
7402
7543
|
paintMirror();
|
|
7403
7544
|
// The box may now fit in fewer lines, and the grower only runs on input.
|
|
7404
|
-
|
|
7405
|
-
input.style.height = Math.min(Math.max(input.scrollHeight, 56), window.innerHeight * 0.32) + "px";
|
|
7545
|
+
autosize();
|
|
7406
7546
|
});
|
|
7407
7547
|
|
|
7408
7548
|
/**
|
|
@@ -7444,6 +7584,70 @@ function paintMirror() {
|
|
|
7444
7584
|
if (inputMirror.querySelector("mark")) inputMirror.style.setProperty("--at-w", atWidth() + "px");
|
|
7445
7585
|
}
|
|
7446
7586
|
|
|
7587
|
+
// --- the caret ------------------------------------------------------------
|
|
7588
|
+
|
|
7589
|
+
/**
|
|
7590
|
+
* Draw the caret, because the field cannot draw one thick enough.
|
|
7591
|
+
*
|
|
7592
|
+
* A textarea's caret is one device pixel and the only thing CSS offers is its
|
|
7593
|
+
* colour. On a pale field that bar is genuinely hard to find, so the native
|
|
7594
|
+
* one is hidden and this one is put where it would have been.
|
|
7595
|
+
*
|
|
7596
|
+
* Where that is comes from a probe: the same box as the mirror, with the same
|
|
7597
|
+
* font, width, padding and wrapping, holding the text up to the caret and
|
|
7598
|
+
* then a zero-width marker. Whatever rectangle the marker lands in is where
|
|
7599
|
+
* the field would have drawn the bar — including after a wrap, which is the
|
|
7600
|
+
* case arithmetic on character widths always gets wrong.
|
|
7601
|
+
*/
|
|
7602
|
+
const caretEl = document.getElementById("caret");
|
|
7603
|
+
const caretProbe = document.getElementById("caret-probe");
|
|
7604
|
+
let caretRest;
|
|
7605
|
+
|
|
7606
|
+
function placeCaret() {
|
|
7607
|
+
// Only when the field has the caret and nothing is selected. A selection
|
|
7608
|
+
// draws its own edges, and a bar inside one reads as a second insertion
|
|
7609
|
+
// point.
|
|
7610
|
+
const showing =
|
|
7611
|
+
document.activeElement === input && input.selectionStart === input.selectionEnd;
|
|
7612
|
+
caretEl.classList.toggle("on", showing);
|
|
7613
|
+
if (!showing) return;
|
|
7614
|
+
|
|
7615
|
+
const head = input.value.slice(0, input.selectionStart);
|
|
7616
|
+
caretProbe.textContent = head;
|
|
7617
|
+
// A trailing newline collapses unless something follows it, which would put
|
|
7618
|
+
// the caret at the end of the line above rather than on the empty one.
|
|
7619
|
+
const marker = document.createElement("span");
|
|
7620
|
+
marker.textContent = String.fromCharCode(0x200b);
|
|
7621
|
+
caretProbe.appendChild(marker);
|
|
7622
|
+
|
|
7623
|
+
// The marker's offsets are inside the probe; the caret is placed against
|
|
7624
|
+
// the wrapper they share. The probe is inset and padded so the mention chip
|
|
7625
|
+
// has somewhere to bleed — read those numbers off it rather than repeating
|
|
7626
|
+
// them here, or the caret drifts the day the padding changes. Scrolling is
|
|
7627
|
+
// the field's, not the probe's.
|
|
7628
|
+
// The line box, which is what the field's own caret fills. Nothing here is
|
|
7629
|
+
// trying to improve on the native geometry — the only reason this caret
|
|
7630
|
+
// exists is that CSS offers no way to make that one wider than a pixel.
|
|
7631
|
+
caretEl.style.left = caretProbe.offsetLeft + marker.offsetLeft + "px";
|
|
7632
|
+
caretEl.style.top = caretProbe.offsetTop + marker.offsetTop - input.scrollTop + "px";
|
|
7633
|
+
caretEl.style.height = marker.offsetHeight + "px";
|
|
7634
|
+
|
|
7635
|
+
// Solid while it is moving, blinking once it settles.
|
|
7636
|
+
caretEl.classList.add("moving");
|
|
7637
|
+
clearTimeout(caretRest);
|
|
7638
|
+
caretRest = setTimeout(() => caretEl.classList.remove("moving"), 420);
|
|
7639
|
+
}
|
|
7640
|
+
|
|
7641
|
+
// Every way the caret can move. The selectionchange event covers the keyboard
|
|
7642
|
+
// and the mouse both, and fires for a textarea in every browser this ships to.
|
|
7643
|
+
for (const event of ["input", "focus", "blur", "scroll"]) {
|
|
7644
|
+
input.addEventListener(event, placeCaret);
|
|
7645
|
+
}
|
|
7646
|
+
document.addEventListener("selectionchange", () => {
|
|
7647
|
+
if (document.activeElement === input) placeCaret();
|
|
7648
|
+
});
|
|
7649
|
+
window.addEventListener("resize", placeCaret);
|
|
7650
|
+
|
|
7447
7651
|
/** How wide the field draws an @ sign: the slot the icon has to fit in. */
|
|
7448
7652
|
function atWidth() {
|
|
7449
7653
|
const probe = document.createElement("canvas").getContext("2d");
|
|
@@ -7710,7 +7914,7 @@ document.getElementById("composer").addEventListener("submit", (e) => {
|
|
|
7710
7914
|
// are sent as prose, because /etc and and/or are things people write.
|
|
7711
7915
|
if (runCommand(text)) {
|
|
7712
7916
|
input.value = "";
|
|
7713
|
-
|
|
7917
|
+
autosize();
|
|
7714
7918
|
paintMirror();
|
|
7715
7919
|
closeAttachMenu();
|
|
7716
7920
|
return;
|
|
@@ -7721,12 +7925,19 @@ document.getElementById("composer").addEventListener("submit", (e) => {
|
|
|
7721
7925
|
const waiting = openQuestion(activeId);
|
|
7722
7926
|
if (waiting && text && !staged.length) {
|
|
7723
7927
|
input.value = "";
|
|
7724
|
-
|
|
7928
|
+
autosize();
|
|
7725
7929
|
paintMirror();
|
|
7726
7930
|
void sendQuestion(waiting, { outcome: "dismissed", note: text });
|
|
7727
7931
|
return;
|
|
7728
7932
|
}
|
|
7729
|
-
if (!text && !staged.length && !refs.length)
|
|
7933
|
+
if (!text && !staged.length && !refs.length) {
|
|
7934
|
+
// Send on an empty composer normally does nothing. With messages left
|
|
7935
|
+
// waiting — the turn under them was stopped, or it failed — it is the
|
|
7936
|
+
// release: the server does not restart a queue after either by itself.
|
|
7937
|
+
const here = panes.get(activeId);
|
|
7938
|
+
if (here && !here.busy && (here.queued || []).length) void api("/flush", { session: activeId });
|
|
7939
|
+
return;
|
|
7940
|
+
}
|
|
7730
7941
|
const ids = staged.map((file) => file.id);
|
|
7731
7942
|
const shots = staged
|
|
7732
7943
|
.filter((file) => file.preview)
|
|
@@ -7734,7 +7945,7 @@ document.getElementById("composer").addEventListener("submit", (e) => {
|
|
|
7734
7945
|
if (shots.length) sentPreviews.set(activeId, shots);
|
|
7735
7946
|
const referenced = refs.map((ref) => ({ kind: ref.kind, value: ref.value }));
|
|
7736
7947
|
input.value = "";
|
|
7737
|
-
|
|
7948
|
+
autosize();
|
|
7738
7949
|
paintMirror();
|
|
7739
7950
|
staged = [];
|
|
7740
7951
|
refs = [];
|
|
@@ -7756,14 +7967,91 @@ input.addEventListener("keydown", (e) => {
|
|
|
7756
7967
|
}
|
|
7757
7968
|
});
|
|
7758
7969
|
input.addEventListener("input", () => {
|
|
7759
|
-
|
|
7760
|
-
// matches the CSS min-height, or deleting a long paste would leave the box
|
|
7761
|
-
// taller than an empty one.
|
|
7762
|
-
input.style.height = "auto";
|
|
7763
|
-
const wanted = Math.max(input.scrollHeight, 56);
|
|
7764
|
-
input.style.height = Math.min(wanted, window.innerHeight * 0.32) + "px";
|
|
7970
|
+
autosize();
|
|
7765
7971
|
paintMirror();
|
|
7972
|
+
placeCaret();
|
|
7973
|
+
});
|
|
7974
|
+
|
|
7975
|
+
// --- the field's height ---------------------------------------------------
|
|
7976
|
+
|
|
7977
|
+
/**
|
|
7978
|
+
* How tall the field is: grown to fit what is typed, or what it was dragged to.
|
|
7979
|
+
*
|
|
7980
|
+
* FIELD_MIN matches the CSS floor, so deleting a long paste cannot leave the
|
|
7981
|
+
* box taller than an empty one. The ceilings are a share of the window rather
|
|
7982
|
+
* than fixed numbers: the field must not swallow the conversation on a short
|
|
7983
|
+
* screen. Growing on its own stops at a third of the window; a person dragging
|
|
7984
|
+
* is allowed most of it, because they can see what they are giving up.
|
|
7985
|
+
*/
|
|
7986
|
+
const FIELD_MIN = 56;
|
|
7987
|
+
const fieldGrowMax = () => window.innerHeight * 0.32;
|
|
7988
|
+
const fieldDragMax = () => Math.max(FIELD_MIN, window.innerHeight * 0.7);
|
|
7989
|
+
const FIELD_KEY = "oharness.composerHeight";
|
|
7990
|
+
|
|
7991
|
+
/** Set by dragging the grip; null means the field sizes itself. */
|
|
7992
|
+
let fieldHeight = null;
|
|
7993
|
+
try {
|
|
7994
|
+
const saved = Number(localStorage.getItem(FIELD_KEY));
|
|
7995
|
+
if (Number.isFinite(saved) && saved >= FIELD_MIN) fieldHeight = saved;
|
|
7996
|
+
} catch { /* private window, or storage turned off */ }
|
|
7997
|
+
|
|
7998
|
+
function autosize() {
|
|
7999
|
+
if (fieldHeight !== null) {
|
|
8000
|
+
// A dragged height wins over the CSS ceiling, which is there to bound the
|
|
8001
|
+
// field's own growing rather than to overrule the person.
|
|
8002
|
+
input.style.maxHeight = "none";
|
|
8003
|
+
input.style.height = Math.min(fieldHeight, fieldDragMax()) + "px";
|
|
8004
|
+
return;
|
|
8005
|
+
}
|
|
8006
|
+
input.style.maxHeight = "";
|
|
8007
|
+
// Reset first so the box can shrink as well as grow, then clamp.
|
|
8008
|
+
input.style.height = "auto";
|
|
8009
|
+
input.style.height = Math.min(Math.max(input.scrollHeight, FIELD_MIN), fieldGrowMax()) + "px";
|
|
8010
|
+
}
|
|
8011
|
+
|
|
8012
|
+
function setFieldHeight(px) {
|
|
8013
|
+
fieldHeight = px === null ? null : Math.round(Math.min(Math.max(px, FIELD_MIN), fieldDragMax()));
|
|
8014
|
+
try {
|
|
8015
|
+
if (fieldHeight === null) localStorage.removeItem(FIELD_KEY);
|
|
8016
|
+
else localStorage.setItem(FIELD_KEY, String(fieldHeight));
|
|
8017
|
+
} catch { /* nothing to do: the height still applies for this page */ }
|
|
8018
|
+
autosize();
|
|
8019
|
+
}
|
|
8020
|
+
|
|
8021
|
+
const grip = document.getElementById("grip");
|
|
8022
|
+
grip.addEventListener("pointerdown", (e) => {
|
|
8023
|
+
// Only the primary button, and never a second drag inside the first.
|
|
8024
|
+
if (e.button !== 0) return;
|
|
8025
|
+
e.preventDefault();
|
|
8026
|
+
const startY = e.clientY;
|
|
8027
|
+
const startHeight = input.getBoundingClientRect().height;
|
|
8028
|
+
// Capture is the nicety; the window listeners below are what make the drag
|
|
8029
|
+
// work. The strip is twelve pixels tall, and a pointer moving faster than
|
|
8030
|
+
// the box can follow leaves it within a frame.
|
|
8031
|
+
try { grip.setPointerCapture(e.pointerId); } catch { /* no live pointer to capture */ }
|
|
8032
|
+
grip.classList.add("dragging");
|
|
8033
|
+
document.body.classList.add("resizing");
|
|
8034
|
+
|
|
8035
|
+
// Up is taller: the box grows from its top edge, which is the edge in hand.
|
|
8036
|
+
const move = (ev) => setFieldHeight(startHeight + (startY - ev.clientY));
|
|
8037
|
+
const done = () => {
|
|
8038
|
+
window.removeEventListener("pointermove", move);
|
|
8039
|
+
window.removeEventListener("pointerup", done);
|
|
8040
|
+
window.removeEventListener("pointercancel", done);
|
|
8041
|
+
grip.classList.remove("dragging");
|
|
8042
|
+
document.body.classList.remove("resizing");
|
|
8043
|
+
};
|
|
8044
|
+
window.addEventListener("pointermove", move);
|
|
8045
|
+
window.addEventListener("pointerup", done);
|
|
8046
|
+
window.addEventListener("pointercancel", done);
|
|
7766
8047
|
});
|
|
8048
|
+
// Back to sizing itself. A drag is easy to do by accident on a trackpad, and
|
|
8049
|
+
// without this the only way back is to guess the original height.
|
|
8050
|
+
grip.addEventListener("dblclick", () => setFieldHeight(null));
|
|
8051
|
+
// A dragged height is kept, but never past the ceiling of a window that has
|
|
8052
|
+
// since been made shorter.
|
|
8053
|
+
window.addEventListener("resize", () => autosize());
|
|
8054
|
+
autosize();
|
|
7767
8055
|
|
|
7768
8056
|
// --- the mention chip under the text ------------------------------------
|
|
7769
8057
|
|
|
@@ -13713,7 +14001,13 @@ ${ANALYTICS_STUB}
|
|
|
13713
14001
|
<button id="jump" hidden type="button">↓ latest</button>
|
|
13714
14002
|
|
|
13715
14003
|
<form id="composer">
|
|
14004
|
+
<!-- Typed while a turn was running, waiting its turn. Outside the box
|
|
14005
|
+
rather than in it: what is in the box is the message being written,
|
|
14006
|
+
and a row sharing that surface reads as part of it. -->
|
|
14007
|
+
<div id="queued"></div>
|
|
13716
14008
|
<div class="composer" id="composer-box">
|
|
14009
|
+
<!-- The top edge is a grab handle: drag it to resize the field. -->
|
|
14010
|
+
<div id="grip" role="separator" aria-orientation="horizontal" data-t-title="composer.resize"></div>
|
|
13717
14011
|
<div id="attachments"></div>
|
|
13718
14012
|
<!-- A textarea draws its own glyphs and cannot style a range of them, so
|
|
13719
14013
|
the chip behind a mention is painted on a layer underneath that
|
|
@@ -13721,6 +14015,8 @@ ${ANALYTICS_STUB}
|
|
|
13721
14015
|
same string twice, and a screen reader should hear it once. -->
|
|
13722
14016
|
<div class="input-wrap">
|
|
13723
14017
|
<div id="input-mirror" aria-hidden="true"></div>
|
|
14018
|
+
<div id="caret-probe" aria-hidden="true"></div>
|
|
14019
|
+
<i id="caret" aria-hidden="true"></i>
|
|
13724
14020
|
<textarea id="input" rows="1" data-t-placeholder="composer.placeholder"></textarea>
|
|
13725
14021
|
</div>
|
|
13726
14022
|
<div class="composer-bar">
|
package/dist/page.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page.js","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;;;;;;;;;;GAcG;AAEH,0EAA0E;AAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAA;EACtB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAy4EV,CAAC;AAEF,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+3V5B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,OAAO,GAAG;;;;;yCAKyB,CAAC;AAE1C,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;4CAOwB,kBAAkB,CAAC,OAAO,CAAC;SAC9D,KAAK;EACZ,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAsSK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;qBACvB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;EAC1C,aAAa;EACb,UAAU;EACV,gBAAgB;;;QAGV,CAAC"}
|
|
1
|
+
{"version":3,"file":"page.js","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC;;;;;;;;;;;;;;GAcG;AAEH,0EAA0E;AAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAA;EACtB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAw9EV,CAAC;AAEF,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAglW5B,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,OAAO,GAAG;;;;;yCAKyB,CAAC;AAE1C,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;4CAOwB,kBAAkB,CAAC,OAAO,CAAC;SAC9D,KAAK;EACZ,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBA8SK,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;qBACvB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;EAC1C,aAAa;EACb,UAAU;EACV,gBAAgB;;;QAGV,CAAC"}
|