desic-okx-agent 0.3.2 → 0.3.3

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.
@@ -1,109 +1,355 @@
1
- /**
2
- * Hover readout for the comparison overlay.
3
- *
4
- * Shows every curve's value at one instant, which is the question an overlay
5
- * raises and a static image cannot answer: two lines crossing tells you they
6
- * crossed, not by how much.
7
- *
8
- * Same constraints as the single-run script — one IIFE, no network, no storage,
9
- * data read from a `data-series` attribute — so the report stays a self-contained
10
- * file that sends nothing.
11
- */
1
+ /** Interactive controller for the self-contained comparison observatory. */
12
2
  export const COMPARE_SCRIPT = String.raw `
13
3
  (function () {
14
4
  var chart = document.getElementById("compare-chart");
15
- if (!chart) return;
5
+ var themeToggle = document.querySelector("[data-theme-toggle]");
6
+ if (themeToggle) {
7
+ var systemDark = matchMedia("(prefers-color-scheme: dark)").matches;
8
+ themeToggle.setAttribute("aria-pressed", systemDark ? "true" : "false");
9
+ themeToggle.addEventListener("click", function () {
10
+ var explicit = document.body.getAttribute("data-theme");
11
+ var dark = explicit ? explicit === "dark" : matchMedia("(prefers-color-scheme: dark)").matches;
12
+ document.body.setAttribute("data-theme", dark ? "light" : "dark");
13
+ themeToggle.setAttribute("aria-pressed", dark ? "false" : "true");
14
+ });
15
+ }
16
16
 
17
+ var progress = document.querySelector(".compare-progress");
18
+ var progressFrame = 0;
19
+ addEventListener("scroll", function () {
20
+ if (progressFrame) return;
21
+ progressFrame = requestAnimationFrame(function () {
22
+ var maximum = Math.max(1, document.documentElement.scrollHeight - innerHeight);
23
+ if (progress) progress.style.transform = "scaleX(" + Math.min(1, scrollY / maximum) + ")";
24
+ progressFrame = 0;
25
+ });
26
+ }, { passive: true });
27
+
28
+ if (!chart) return;
17
29
  var payload;
18
30
  try {
19
31
  payload = JSON.parse(chart.getAttribute("data-series") || "");
20
32
  } catch (error) {
21
33
  return;
22
34
  }
23
- if (!payload || !payload.series || !payload.series.length) return;
35
+ if (!payload || !Array.isArray(payload.series) || payload.series.length === 0) return;
24
36
 
25
37
  var svg = chart.querySelector("svg");
26
- var tooltip = chart.querySelector(".tooltip");
27
- var crosshair = chart.querySelector(".crosshair");
28
- if (!svg || !tooltip) return;
38
+ var tooltip = chart.querySelector(".compare-tooltip");
39
+ var crosshair = chart.querySelector(".compare-crosshair");
40
+ if (!svg || !tooltip || !crosshair) return;
29
41
 
30
- var span = payload.endMs - payload.startMs || 1;
42
+ var reduced = matchMedia("(prefers-reduced-motion: reduce)").matches;
43
+ var fullStart = payload.startMs;
44
+ var fullEnd = payload.endMs;
45
+ var fullDuration = Math.max(1, fullEnd - fullStart);
46
+ var currentStart = fullStart;
47
+ var currentEnd = fullEnd;
48
+ var active = payload.series.map(function () { return true; });
49
+ var viewWidth = payload.width;
50
+ var viewHeight = payload.height;
51
+ var animation = new WeakMap();
52
+ var minimumGap = fullDuration;
53
+ payload.series.forEach(function (series) {
54
+ for (var index = 1; index < series.t.length; index += 1) {
55
+ var gap = series.t[index] - series.t[index - 1];
56
+ if (gap > 0) minimumGap = Math.min(minimumGap, gap);
57
+ }
58
+ });
59
+
60
+ function escapeText(value) {
61
+ return String(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\"/g, "&quot;").replace(/'/g, "&#39;");
62
+ }
31
63
 
32
64
  function formatTime(ms) {
33
65
  return new Date(ms).toISOString().slice(0, 16).replace("T", " ");
34
66
  }
35
67
 
36
- // Nearest sample at or before the cursor's time, by binary search: a linear scan
37
- // per mouse move is visibly slow once six series carry 900 points each.
68
+ function signed(value) {
69
+ return (value > 0 ? "+" : "") + value.toFixed(2) + "%";
70
+ }
71
+
72
+ function tone(element, value) {
73
+ element.classList.remove("positive", "negative", "neutral");
74
+ element.classList.add(value > 0 ? "positive" : value < 0 ? "negative" : "neutral");
75
+ }
76
+
77
+ function xForTime(timeMs) {
78
+ return ((timeMs - fullStart) / fullDuration) * viewWidth;
79
+ }
80
+
81
+ function yFor(value) {
82
+ return viewHeight - ((value - payload.minimum) / Math.max(0.0001, payload.maximum - payload.minimum)) * viewHeight;
83
+ }
84
+
38
85
  function sampleAt(series, timeMs) {
39
86
  var times = series.t;
40
- if (timeMs < times[0] || timeMs > times[times.length - 1]) return null;
87
+ if (!times.length || timeMs < times[0] || timeMs > times[times.length - 1]) return null;
41
88
  var low = 0;
42
89
  var high = times.length - 1;
43
90
  while (low < high) {
44
- var mid = (low + high + 1) >> 1;
45
- if (times[mid] <= timeMs) low = mid;
46
- else high = mid - 1;
91
+ var middle = (low + high + 1) >> 1;
92
+ if (times[middle] <= timeMs) low = middle;
93
+ else high = middle - 1;
94
+ }
95
+ return { index: low, time: times[low], value: series.v[low] };
96
+ }
97
+
98
+ function samplesInWindow(series, startTime, endTime) {
99
+ var values = [];
100
+ var start = sampleAt(series, Math.max(startTime, series.t[0]));
101
+ if (start) values.push(start.value);
102
+ for (var index = 0; index < series.t.length; index += 1) {
103
+ if (series.t[index] < startTime) continue;
104
+ if (series.t[index] > endTime) break;
105
+ values.push(series.v[index]);
106
+ }
107
+ var end = sampleAt(series, Math.min(endTime, series.t[series.t.length - 1]));
108
+ if (end) values.push(end.value);
109
+ return values;
110
+ }
111
+
112
+ function animateViewBox(target, immediate) {
113
+ var prior = animation.get(svg);
114
+ if (prior) cancelAnimationFrame(prior);
115
+ if (immediate || reduced) {
116
+ svg.setAttribute("viewBox", target.join(" "));
117
+ sizeMarkers();
118
+ return;
119
+ }
120
+ var from = (svg.getAttribute("viewBox") || target.join(" ")).split(/\s+/).map(Number);
121
+ var started = performance.now();
122
+ function frame(now) {
123
+ var progress = Math.min(1, (now - started) / 260);
124
+ var eased = 1 - Math.pow(1 - progress, 4);
125
+ var values = target.map(function (value, index) { return from[index] + (value - from[index]) * eased; });
126
+ svg.setAttribute("viewBox", values.join(" "));
127
+ sizeMarkers();
128
+ if (progress < 1) animation.set(svg, requestAnimationFrame(frame));
129
+ else animation.delete(svg);
130
+ }
131
+ animation.set(svg, requestAnimationFrame(frame));
132
+ }
133
+
134
+ function sizeMarkers() {
135
+ var bounds = svg.getBoundingClientRect();
136
+ if (bounds.width <= 0 || bounds.height <= 0) return;
137
+ var box = (svg.getAttribute("viewBox") || "0 0 1000 320").split(/\s+/).map(Number);
138
+ chart.querySelectorAll("[data-marker-radius]").forEach(function (marker) {
139
+ var radius = Number(marker.getAttribute("data-marker-radius")) || 4;
140
+ marker.setAttribute("rx", Math.max(0.001, (radius * box[2]) / bounds.width));
141
+ marker.setAttribute("ry", Math.max(0.001, (radius * box[3]) / bounds.height));
142
+ });
143
+ }
144
+
145
+ function updateWindowStrip() {
146
+ payload.series.forEach(function (series, index) {
147
+ var panel = document.querySelector('[data-window-series="' + index + '"]');
148
+ if (!panel) return;
149
+ panel.classList.toggle("is-hidden", !active[index]);
150
+ var start = sampleAt(series, Math.max(currentStart, series.t[0]));
151
+ var end = sampleAt(series, Math.min(currentEnd, series.t[series.t.length - 1]));
152
+ var output = panel.querySelector("[data-window-return]");
153
+ var value = panel.querySelector("[data-window-value]");
154
+ if (!start || !end || end.time < currentStart || start.time > currentEnd) {
155
+ output.textContent = "-";
156
+ value.textContent = "-";
157
+ tone(output, 0);
158
+ return;
159
+ }
160
+ var change = start.value !== 0 ? (end.value / start.value - 1) * 100 : 0;
161
+ output.textContent = signed(change);
162
+ value.textContent = end.value.toFixed(2);
163
+ tone(output, change);
164
+ });
165
+ var period = document.getElementById("compare-window-period");
166
+ if (period) period.textContent = formatTime(currentStart) + " → " + formatTime(currentEnd);
167
+ }
168
+
169
+ function setRange(startTime, endTime, source, immediate) {
170
+ var duration = Math.max(minimumGap * 8, Math.min(fullDuration, endTime - startTime));
171
+ startTime = Math.max(fullStart, Math.min(fullEnd - duration, startTime));
172
+ endTime = startTime + duration;
173
+ currentStart = startTime;
174
+ currentEnd = endTime;
175
+
176
+ var localMinimum = Infinity;
177
+ var localMaximum = -Infinity;
178
+ payload.series.forEach(function (series, index) {
179
+ if (!active[index]) return;
180
+ samplesInWindow(series, currentStart, currentEnd).forEach(function (value) {
181
+ localMinimum = Math.min(localMinimum, value);
182
+ localMaximum = Math.max(localMaximum, value);
183
+ });
184
+ });
185
+ if (!Number.isFinite(localMinimum) || !Number.isFinite(localMaximum)) {
186
+ localMinimum = payload.minimum;
187
+ localMaximum = payload.maximum;
47
188
  }
48
- return { time: times[low], value: series.v[low] };
189
+ var centre = (localMinimum + localMaximum) / 2;
190
+ var visibleRange = Math.max(4, (localMaximum - localMinimum) * 1.3);
191
+ var visibleMaximum = centre + visibleRange / 2;
192
+ var visibleMinimum = centre - visibleRange / 2;
193
+ var xStart = xForTime(currentStart);
194
+ var xEnd = xForTime(currentEnd);
195
+ var yTop = yFor(visibleMaximum);
196
+ var yBottom = yFor(visibleMinimum);
197
+ animateViewBox([xStart, yTop, Math.max(0.001, xEnd - xStart), Math.max(0.001, yBottom - yTop)], immediate);
198
+
199
+ var maximumLabel = chart.querySelector("[data-axis-maximum]");
200
+ var minimumLabel = chart.querySelector("[data-axis-minimum]");
201
+ if (maximumLabel) maximumLabel.textContent = visibleMaximum.toFixed(1);
202
+ if (minimumLabel) minimumLabel.textContent = visibleMinimum.toFixed(1);
203
+ document.querySelectorAll("[data-compare-range]").forEach(function (button) {
204
+ button.setAttribute("aria-pressed", button === source ? "true" : "false");
205
+ });
206
+ updateWindowStrip();
207
+ hide();
49
208
  }
50
209
 
51
210
  function show(clientX) {
52
211
  var box = svg.getBoundingClientRect();
53
212
  if (box.width <= 0) return;
54
- var ratio = Math.min(1, Math.max(0, (clientX - box.left) / box.width));
55
- var timeMs = payload.startMs + ratio * span;
56
-
57
- var rows = '<div class="row head"><span>' + payload.labels.time + "</span><b>" + formatTime(timeMs) + "</b></div>";
58
- for (var index = 0; index < payload.series.length; index += 1) {
59
- var series = payload.series[index];
213
+ var ratio = Math.max(0, Math.min(1, (clientX - box.left) / box.width));
214
+ var timeMs = currentStart + ratio * (currentEnd - currentStart);
215
+ var rows = '<div class="row head"><span>' + escapeText(payload.labels.time) + "</span><b>" + formatTime(timeMs) + "</b></div>";
216
+ payload.series.forEach(function (series, index) {
217
+ var marker = chart.querySelector('[data-series-marker="' + index + '"]');
218
+ if (!active[index]) {
219
+ if (marker) marker.setAttribute("hidden", "");
220
+ return;
221
+ }
60
222
  var sample = sampleAt(series, timeMs);
61
- // A run whose window does not cover this instant shows a dash rather than
62
- // its nearest endpoint, which would imply data it does not have.
63
- var reading = sample === null ? "-" : sample.value.toFixed(2);
64
- rows +=
65
- '<div class="row"><span><i class="swatch" style="background:' +
66
- series.colour +
67
- '"></i>' +
68
- series.label +
69
- "</span><b>" +
70
- reading +
71
- "</b></div>";
72
- }
223
+ rows += '<div class="row"><span><i class="swatch" style="background:' + series.colour + '"></i>' + escapeText(series.label) + "</span><b>" + (sample ? sample.value.toFixed(2) : "-") + "</b></div>";
224
+ if (marker) {
225
+ if (sample) {
226
+ marker.setAttribute("cx", xForTime(sample.time));
227
+ marker.setAttribute("cy", yFor(sample.value));
228
+ marker.removeAttribute("hidden");
229
+ } else marker.setAttribute("hidden", "");
230
+ }
231
+ });
73
232
  tooltip.innerHTML = rows;
74
233
  tooltip.hidden = false;
75
-
76
- // Flip the tooltip to the other side near the right edge so it stays on screen.
77
- var offset = ratio > 0.6 ? 12 : box.width * ratio + 18;
78
- if (ratio > 0.6) {
79
- tooltip.style.left = "auto";
80
- tooltip.style.right = offset + "px";
81
- } else {
82
- tooltip.style.right = "auto";
83
- tooltip.style.left = offset + "px";
84
- }
85
-
86
- if (crosshair) {
87
- var viewBox = svg.viewBox.baseVal;
88
- crosshair.setAttribute("x1", String(ratio * viewBox.width));
89
- crosshair.setAttribute("x2", String(ratio * viewBox.width));
90
- crosshair.hidden = false;
91
- }
234
+ tooltip.style.left = ratio > 0.62 ? "auto" : box.width * ratio + 18 + "px";
235
+ tooltip.style.right = ratio > 0.62 ? 14 + "px" : "auto";
236
+ var x = xForTime(timeMs);
237
+ crosshair.setAttribute("x1", x);
238
+ crosshair.setAttribute("x2", x);
239
+ crosshair.removeAttribute("hidden");
240
+ sizeMarkers();
92
241
  }
93
242
 
94
243
  function hide() {
95
244
  tooltip.hidden = true;
96
- if (crosshair) crosshair.hidden = true;
245
+ crosshair.setAttribute("hidden", "");
246
+ chart.querySelectorAll("[data-series-marker]").forEach(function (marker) { marker.setAttribute("hidden", ""); });
97
247
  }
98
248
 
99
- chart.addEventListener("mousemove", function (event) {
100
- show(event.clientX);
249
+ document.querySelectorAll("[data-series-toggle]").forEach(function (button) {
250
+ button.addEventListener("click", function () {
251
+ var index = Number(button.getAttribute("data-series-toggle"));
252
+ if (active[index] && active.filter(Boolean).length === 1) return;
253
+ active[index] = !active[index];
254
+ button.setAttribute("aria-pressed", active[index] ? "true" : "false");
255
+ button.classList.toggle("is-muted", !active[index]);
256
+ var path = chart.querySelector('[data-series-path="' + index + '"]');
257
+ if (path) path.classList.toggle("is-hidden", !active[index]);
258
+ setRange(currentStart, currentEnd, document.querySelector('[data-compare-range][aria-pressed="true"]'), true);
259
+ });
260
+ });
261
+
262
+ document.querySelectorAll("[data-compare-range]").forEach(function (button) {
263
+ button.addEventListener("click", function () {
264
+ var value = button.getAttribute("data-compare-range");
265
+ var start = value === "all" ? fullStart : Math.max(fullStart, fullEnd - Number(value) * 86400000);
266
+ setRange(start, fullEnd, button, false);
267
+ });
268
+ });
269
+
270
+ var pendingWheelDelta = 0;
271
+ var pendingWheelX = 0;
272
+ var wheelFrame = 0;
273
+ chart.addEventListener("wheel", function (event) {
274
+ if (!event.deltaY) return;
275
+ event.preventDefault();
276
+ var delta = event.deltaY;
277
+ if (event.deltaMode === 1) delta *= 16;
278
+ else if (event.deltaMode === 2) delta *= Math.max(1, svg.getBoundingClientRect().height);
279
+ pendingWheelDelta += delta;
280
+ pendingWheelX = event.clientX;
281
+ if (wheelFrame) return;
282
+ wheelFrame = requestAnimationFrame(function () {
283
+ var bounded = Math.max(-80, Math.min(80, pendingWheelDelta));
284
+ pendingWheelDelta = 0;
285
+ wheelFrame = 0;
286
+ var factor = Math.exp(bounded * 0.0015);
287
+ var duration = currentEnd - currentStart;
288
+ var targetDuration = Math.max(minimumGap * 8, Math.min(fullDuration, duration * factor));
289
+ var bounds = svg.getBoundingClientRect();
290
+ var ratio = Math.max(0, Math.min(1, (pendingWheelX - bounds.left) / Math.max(1, bounds.width)));
291
+ var anchor = currentStart + ratio * duration;
292
+ setRange(anchor - ratio * targetDuration, anchor + (1 - ratio) * targetDuration, null, false);
293
+ });
294
+ }, { passive: false });
295
+
296
+ var drag = null;
297
+ chart.addEventListener("pointerdown", function (event) {
298
+ if (event.pointerType !== "mouse" || event.button !== 0) return;
299
+ drag = { id: event.pointerId, x: event.clientX, start: currentStart, end: currentEnd };
300
+ chart.classList.add("is-dragging");
301
+ chart.setPointerCapture(event.pointerId);
302
+ hide();
303
+ event.preventDefault();
304
+ });
305
+ chart.addEventListener("pointermove", function (event) {
306
+ if (!drag || event.pointerId !== drag.id) return;
307
+ var bounds = svg.getBoundingClientRect();
308
+ var duration = drag.end - drag.start;
309
+ var shift = ((drag.x - event.clientX) / Math.max(1, bounds.width)) * duration;
310
+ setRange(drag.start + shift, drag.end + shift, null, true);
311
+ });
312
+ function endDrag(event) {
313
+ if (!drag || (typeof event.pointerId === "number" && event.pointerId !== drag.id)) return;
314
+ var id = drag.id;
315
+ drag = null;
316
+ chart.classList.remove("is-dragging");
317
+ if (chart.hasPointerCapture(id)) chart.releasePointerCapture(id);
318
+ }
319
+ chart.addEventListener("pointerup", endDrag);
320
+ chart.addEventListener("pointercancel", endDrag);
321
+ chart.addEventListener("dblclick", function () {
322
+ setRange(fullStart, fullEnd, document.querySelector('[data-compare-range="all"]'), false);
101
323
  });
102
- chart.addEventListener("mouseleave", hide);
324
+
325
+ chart.addEventListener("mousemove", function (event) { if (!drag) show(event.clientX); });
326
+ chart.addEventListener("mouseleave", function () { if (!drag) hide(); });
327
+ chart.addEventListener("touchstart", function (event) {
328
+ if (event.touches && event.touches.length) show(event.touches[0].clientX);
329
+ }, { passive: true });
103
330
  chart.addEventListener("touchmove", function (event) {
104
331
  if (event.touches && event.touches.length) show(event.touches[0].clientX);
105
- });
332
+ }, { passive: true });
106
333
  chart.addEventListener("touchend", hide);
334
+
335
+ var cursorTime = fullStart;
336
+ chart.setAttribute("tabindex", "0");
337
+ chart.addEventListener("keydown", function (event) {
338
+ var step = event.shiftKey ? Math.max(minimumGap, (currentEnd - currentStart) / 20) : minimumGap;
339
+ if (event.key === "ArrowRight") cursorTime = Math.min(currentEnd, Math.max(currentStart, cursorTime) + step);
340
+ else if (event.key === "ArrowLeft") cursorTime = Math.max(currentStart, Math.min(currentEnd, cursorTime) - step);
341
+ else if (event.key === "Home") cursorTime = currentStart;
342
+ else if (event.key === "End") cursorTime = currentEnd;
343
+ else if (event.key === "Escape") { hide(); return; }
344
+ else return;
345
+ event.preventDefault();
346
+ var bounds = svg.getBoundingClientRect();
347
+ show(bounds.left + ((cursorTime - currentStart) / Math.max(1, currentEnd - currentStart)) * bounds.width);
348
+ });
349
+ chart.addEventListener("blur", hide);
350
+
351
+ addEventListener("resize", sizeMarkers, { passive: true });
352
+ setRange(fullStart, fullEnd, document.querySelector('[data-compare-range="all"]'), true);
107
353
  })();
108
354
  `;
109
355
  //# sourceMappingURL=compare-script.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"compare-script.js","sourceRoot":"","sources":["../../src/report/compare-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgGvC,CAAC"}
1
+ {"version":3,"file":"compare-script.js","sourceRoot":"","sources":["../../src/report/compare-script.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgWvC,CAAC"}
@@ -51,4 +51,4 @@ export declare function escapeAttribute(value: string): string;
51
51
  * second copy: the two documents should not drift apart visually, and a duplicated
52
52
  * sheet is exactly how that happens.
53
53
  */
54
- export declare const COMPARE_STYLES = "\n:root{--bg:#0f1116;--panel:#171a21;--line:#242833;--text:#e6e8ee;--dim:#8b90a0;--up:#3fb950;--down:#f2777a;--accent:#4f9cf9}\n@media(prefers-color-scheme:light){:root{--bg:#f7f8fa;--panel:#fff;--line:#e3e6ec;--text:#1a1d24;--dim:#6b7280;--up:#1a7f37;--down:#c9372c}}\n*{box-sizing:border-box}\nbody{margin:0;background:var(--bg);color:var(--text);font:14px/1.55 -apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,\"Helvetica Neue\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif}\nmain{max-width:1080px;margin:0 auto;padding:32px 24px 64px}\nheader{display:flex;justify-content:space-between;align-items:flex-end;gap:24px;flex-wrap:wrap;padding-bottom:20px;border-bottom:1px solid var(--line)}\nh1{margin:0;font-size:26px;font-weight:600;letter-spacing:-.01em}\n.sub{margin:4px 0 0;color:var(--dim);font-size:13px}\n.headline{text-align:right}\n.headline .value{display:block;font-size:34px;font-weight:650;letter-spacing:-.02em;font-variant-numeric:tabular-nums}\n.headline .label{color:var(--dim);font-size:12px;text-transform:uppercase;letter-spacing:.08em}\n.up{color:var(--up)}.down{color:var(--down)}.flat{color:var(--dim)}\n.facts{display:flex;gap:28px;flex-wrap:wrap;margin:20px 0 8px;color:var(--dim);font-size:13px}\n.facts span{display:block;text-transform:uppercase;letter-spacing:.06em;font-size:11px}\n.facts strong{color:var(--text);font-weight:550;font-variant-numeric:tabular-nums}\n.warnings{margin:20px 0 0;padding:12px 16px;border-left:3px solid var(--down);background:color-mix(in srgb,var(--down) 8%,transparent);border-radius:0 6px 6px 0}\n.warnings p{margin:4px 0;font-size:13px}\nsection{margin-top:32px}\nh2{margin:0 0 14px;font-size:12px;font-weight:600;text-transform:uppercase;letter-spacing:.1em;color:var(--dim)}\nh2 .count{color:var(--dim);font-weight:400}\ndl{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:1px;margin:0;background:var(--line);border:1px solid var(--line);border-radius:8px;overflow:hidden}\ndl>div{background:var(--panel);padding:12px 14px}\ndt{color:var(--dim);font-size:11px;text-transform:uppercase;letter-spacing:.06em}\ndd{margin:3px 0 0;font-size:16px;font-weight:550;font-variant-numeric:tabular-nums}\n.chart{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:10px 12px;display:flex;gap:10px;align-items:stretch}\n.chart.drawdown{margin-top:8px;border-radius:8px}\n.chart svg{flex:1;height:240px;width:100%;display:block}\n.chart.drawdown svg{height:80px}\n.axis{display:flex;flex-direction:column;justify-content:space-between;color:var(--dim);font-size:11px;font-variant-numeric:tabular-nums;min-width:62px;text-align:right}\n.range{margin:8px 0 0;color:var(--dim);font-size:12px}\n.chart{position:relative}\n.chart svg{cursor:crosshair}\n.chart:focus-visible{outline:2px solid var(--accent);outline-offset:2px}\n.baseline{stroke:var(--dim);stroke-width:1;stroke-dasharray:3 4;opacity:.5;vector-effect:non-scaling-stroke}\n.crosshair{stroke:var(--dim);stroke-width:1;vector-effect:non-scaling-stroke;pointer-events:none}\n.marker{fill:var(--accent);stroke:var(--panel);stroke-width:1.5;pointer-events:none}\n.tooltip{position:absolute;top:10px;pointer-events:none;background:var(--panel);border:1px solid var(--line);border-radius:6px;padding:8px 10px;font-size:12px;min-width:180px;box-shadow:0 4px 16px rgba(0,0,0,.28);z-index:2}\n.tooltip .row{display:flex;justify-content:space-between;gap:14px;padding:1px 0}\n.tooltip .row span{color:var(--dim)}\n.tooltip .row b{font-weight:550;font-variant-numeric:tabular-nums}\n.scroll{overflow-x:auto;border:1px solid var(--line);border-radius:8px}\ntable{width:100%;border-collapse:collapse;font-size:13px}\nth,td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--line);white-space:nowrap}\nth{background:var(--panel);color:var(--dim);font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.06em;position:sticky;top:0}\ntbody tr:last-child td{border-bottom:none}\ntd.n{text-align:right;font-variant-numeric:tabular-nums}\ntr.up td:nth-child(5),tr.up td:nth-child(6){color:var(--up)}\ntr.down td:nth-child(5),tr.down td:nth-child(6){color:var(--down)}\n.mono{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px}\ntd.dim{color:var(--dim)}\n.scroll.tall{max-height:520px;overflow-y:auto}\n.histogram{background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:12px 14px}\n.bin{display:flex;align-items:center;gap:10px;padding:3px 0}\n.bin .range{min-width:132px;color:var(--dim);text-align:right;flex-shrink:0}\n.bin .track{flex:1;height:12px;background:color-mix(in srgb,var(--line) 60%,transparent);border-radius:3px;overflow:hidden}\n.bin .fill{display:block;height:100%;border-radius:3px}\n.bin .fill.up{background:var(--up)}\n.bin .fill.down{background:var(--down)}\n.bin>.count{min-width:44px;text-align:right;color:var(--dim);font-size:12px;font-variant-numeric:tabular-nums;flex-shrink:0}\n.empty{color:var(--dim);font-size:13px}\nfooter{margin-top:40px;padding-top:16px;border-top:1px solid var(--line);color:var(--dim);font-size:12px}\nfooter p{margin:4px 0}\n\n.legend{display:flex;gap:20px;flex-wrap:wrap;margin:20px 0 0;font-size:13px}\n.legend div{display:flex;align-items:center;gap:7px}\n.legend i,th i{display:inline-block;width:10px;height:10px;border-radius:2px;flex-shrink:0}\nth i{margin-right:6px;vertical-align:middle}\ntable.matrix th[scope=row]{background:var(--panel);color:var(--dim);text-transform:none;letter-spacing:0;font-size:12px;font-weight:500;text-align:left;position:sticky;left:0}\ntable.matrix thead th{text-align:right}\ntable.matrix thead th span.dim{display:block;font-weight:400;text-transform:none;letter-spacing:0;font-size:10px}\ntd.best{color:var(--up);font-weight:600}\n.chart .tooltip .swatch{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:6px}\n.chart .tooltip .row.head{border-bottom:1px solid var(--line);margin-bottom:3px;padding-bottom:3px}\n";
54
+ export declare const COMPARE_STYLES: string;