@luxonis/visualizer-protobuf 2.11.2 → 2.13.0

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 (75) hide show
  1. package/dist/{index-9X5IFBUj.js → index-4msm-wtA.js} +1 -1
  2. package/dist/{index-CjJ4xAdB.js → index-BK0O58zw.js} +1 -1
  3. package/dist/{index-B3T-sU1j.js → index-BWakrawk.js} +2 -2
  4. package/dist/{index-BLoXvLKz.js → index-BbAm1fKU.js} +1 -1
  5. package/dist/{index-prbig-mv.js → index-BsQeBBzM.js} +1 -1
  6. package/dist/{index-DbFvmBsl.js → index-CE0akFDh.js} +14 -5
  7. package/dist/{index-B61jalVx.js → index-CbS2HMyR.js} +1 -1
  8. package/dist/{index-BTtZZhIx.js → index-CpLzYoX8.js} +1 -1
  9. package/dist/{index-CqFRR40y.js → index-CtKYoeeM.js} +1 -1
  10. package/dist/{index-CC5SpeJH.js → index-DFdQY59I.js} +1 -1
  11. package/dist/{index-DjE38-5p.js → index-DFlpZwK1.js} +505 -90
  12. package/dist/{index-2Zk3DeS3.js → index-DSIL_c41.js} +1 -1
  13. package/dist/{index-BisiS-gw.js → index-DTZuXJ1A.js} +1 -1
  14. package/dist/{index-Cm0UpxTw.js → index-DfgdvKhl.js} +1 -1
  15. package/dist/{index-BiV6mWEH.js → index-Do7UsSft.js} +1 -1
  16. package/dist/{index-vCAg8fos.js → index-DyoCH5GH.js} +1 -1
  17. package/dist/{index-Cc3zOB0y.js → index-PmNaQtc7.js} +1 -1
  18. package/dist/{index-B9aXaLUR.js → index-fN8Tpgww.js} +1 -1
  19. package/dist/{index-PSBhGaEs.js → index-nJgMRJTy.js} +1 -1
  20. package/dist/index.js +1 -1
  21. package/dist/lib/src/components/Panel.d.ts +2 -0
  22. package/dist/lib/src/components/Panel.d.ts.map +1 -1
  23. package/dist/lib/src/components/Panel.js +2 -2
  24. package/dist/lib/src/components/Panel.js.map +1 -1
  25. package/dist/lib/src/components/PanelToolbar.d.ts +3 -1
  26. package/dist/lib/src/components/PanelToolbar.d.ts.map +1 -1
  27. package/dist/lib/src/components/PanelToolbar.js +32 -20
  28. package/dist/lib/src/components/PanelToolbar.js.map +1 -1
  29. package/dist/lib/src/components/measure-event-loop-delay.d.ts +2 -0
  30. package/dist/lib/src/components/measure-event-loop-delay.d.ts.map +1 -0
  31. package/dist/lib/src/components/measure-event-loop-delay.js +18 -0
  32. package/dist/lib/src/components/measure-event-loop-delay.js.map +1 -0
  33. package/dist/lib/src/components/measure-render-delay.d.ts +5 -0
  34. package/dist/lib/src/components/measure-render-delay.d.ts.map +1 -0
  35. package/dist/lib/src/components/measure-render-delay.js +19 -0
  36. package/dist/lib/src/components/measure-render-delay.js.map +1 -0
  37. package/dist/lib/src/connection/foxglove-connection.d.ts +3 -2
  38. package/dist/lib/src/connection/foxglove-connection.d.ts.map +1 -1
  39. package/dist/lib/src/connection/foxglove-connection.js +17 -2
  40. package/dist/lib/src/connection/foxglove-connection.js.map +1 -1
  41. package/dist/lib/src/connection/webrtc/bridge.d.ts +1 -1
  42. package/dist/lib/src/connection/webrtc/bridge.d.ts.map +1 -1
  43. package/dist/lib/src/connection/webrtc/bridge.js +1 -1
  44. package/dist/lib/src/connection/webrtc/bridge.js.map +1 -1
  45. package/dist/lib/src/connection/webrtc/comms-proxy.d.ts.map +1 -1
  46. package/dist/lib/src/connection/webrtc/comms-proxy.js +4 -1
  47. package/dist/lib/src/connection/webrtc/comms-proxy.js.map +1 -1
  48. package/dist/lib/src/messaging/deserialization/pointcloud/utils.d.ts +19 -0
  49. package/dist/lib/src/messaging/deserialization/pointcloud/utils.d.ts.map +1 -0
  50. package/dist/lib/src/messaging/deserialization/pointcloud/utils.js +97 -0
  51. package/dist/lib/src/messaging/deserialization/pointcloud/utils.js.map +1 -0
  52. package/dist/lib/src/messaging/deserialization/video/depth.d.ts +6 -1
  53. package/dist/lib/src/messaging/deserialization/video/depth.d.ts.map +1 -1
  54. package/dist/lib/src/messaging/deserialization/video/depth.js +185 -7
  55. package/dist/lib/src/messaging/deserialization/video/depth.js.map +1 -1
  56. package/dist/lib/src/messaging/deserialization.js +2 -2
  57. package/dist/lib/src/messaging/deserialization.js.map +1 -1
  58. package/dist/lib/src/panels/ImagePanel.d.ts +1 -0
  59. package/dist/lib/src/panels/ImagePanel.d.ts.map +1 -1
  60. package/dist/lib/src/panels/ImagePanel.js +27 -3
  61. package/dist/lib/src/panels/ImagePanel.js.map +1 -1
  62. package/dist/lib/src/panels/PointCloudPanel.js +2 -2
  63. package/dist/lib/src/panels/PointCloudPanel.js.map +1 -1
  64. package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.d.ts.map +1 -1
  65. package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.js +1 -0
  66. package/dist/packages/studio-base/src/panels/ThreeDeeRender/Renderer.js.map +1 -1
  67. package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.d.ts +1 -0
  68. package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.d.ts.map +1 -1
  69. package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.js +4 -0
  70. package/dist/packages/studio-base/src/panels/ThreeDeeRender/ThreeDeeRender.js.map +1 -1
  71. package/dist/packages/studio-base/src/panels/ThreeDeeRender/index.d.ts +1 -0
  72. package/dist/packages/studio-base/src/panels/ThreeDeeRender/index.d.ts.map +1 -1
  73. package/dist/packages/studio-base/src/panels/ThreeDeeRender/index.js +4 -2
  74. package/dist/packages/studio-base/src/panels/ThreeDeeRender/index.js.map +1 -1
  75. package/package.json +2 -1
@@ -1048,6 +1048,69 @@ function estimateObjectSize(obj) {
1048
1048
  return SMALL_INTEGER_SIZE;
1049
1049
  }
1050
1050
 
1051
+ // This Source Code Form is subject to the terms of the Mozilla Public
1052
+ // License, v2.0. If a copy of the MPL was not distributed with this
1053
+ // file, You can obtain one at http://mozilla.org/MPL/2.0/
1054
+ /// <reference types="@webgpu/types" />
1055
+
1056
+ function uint8ArrayToUint16Array(uint8Array) {
1057
+ if (uint8Array.length % 2 !== 0) {
1058
+ throw new Error("Uint8Array length must be a multiple of 2 for conversion to Uint16Array");
1059
+ }
1060
+ const uint16Array = new Uint16Array(uint8Array.length / 2);
1061
+ for (let i = 0; i < uint16Array.length; i++) {
1062
+ const lowByte = uint8Array[i * 2];
1063
+ const highByte = uint8Array[i * 2 + 1];
1064
+
1065
+ // eslint-disable-next-line @foxglove/strict-equality
1066
+ if (highByte === undefined || lowByte === undefined) {
1067
+ throw new Error("Invalid data in uint8Array");
1068
+ }
1069
+ uint16Array[i] = highByte << 8 | lowByte;
1070
+ }
1071
+ return uint16Array;
1072
+ }
1073
+
1074
+ /* H264 (i420) to RGBA */
1075
+ function i420ToRgbaToPointcloud(i420Data, i420Width, i420Height, depthWidth, depthHeight, data) {
1076
+ const frameSize = i420Width * i420Height;
1077
+ const uOffset = frameSize;
1078
+ const vOffset = frameSize + frameSize / 4;
1079
+ const pointCount = data.byteLength / 16;
1080
+ const buffer = new ArrayBuffer(data.byteLength);
1081
+ const view = new DataView(buffer);
1082
+ const dataView = new DataView(data.buffer);
1083
+ for (let i = 0; i < pointCount; i++) {
1084
+ const depthX = i % depthWidth;
1085
+ const depthY = Math.floor(i / depthWidth);
1086
+ const i420X = Math.round(depthX * (i420Width / depthWidth));
1087
+ const i420Y = Math.round(depthY * (i420Height / depthHeight));
1088
+ if (i420X >= i420Width || i420Y >= i420Height) {
1089
+ continue;
1090
+ }
1091
+ const index = i420Y * i420Width + i420X;
1092
+ const uvIndex = Math.floor(i420Y / 2) * (i420Width / 2) + Math.floor(i420X / 2);
1093
+ const Y = i420Data[index] ?? 0;
1094
+ const U = (i420Data[uOffset + uvIndex] ?? 128) - 128;
1095
+ const V = (i420Data[vOffset + uvIndex] ?? 128) - 128;
1096
+ let R = Y + 1.402 * V;
1097
+ let G = Y - 0.344136 * U - 0.714136 * V;
1098
+ let B = Y + 1.772 * U;
1099
+ R = Math.min(255, Math.max(0, R));
1100
+ G = Math.min(255, Math.max(0, G));
1101
+ B = Math.min(255, Math.max(0, B));
1102
+ const offset = i * 16;
1103
+ view.setFloat32(offset, dataView.getFloat32(offset, true), true); // x
1104
+ view.setFloat32(offset + 4, dataView.getFloat32(offset + 4, true), true); // y
1105
+ view.setFloat32(offset + 8, dataView.getFloat32(offset + 8, true), true); // z
1106
+ view.setUint8(offset + 12, R); // Red
1107
+ view.setUint8(offset + 13, G); // Green
1108
+ view.setUint8(offset + 14, B); // Blue
1109
+ view.setUint8(offset + 15, 255); // Alpha (fully opaque)
1110
+ }
1111
+ return new Uint8Array(buffer);
1112
+ }
1113
+
1051
1114
  var typescript$1 = {};
1052
1115
 
1053
1116
  /******************************************************************************
@@ -11357,34 +11420,270 @@ function deserializeColorFrame({
11357
11420
  // This Source Code Form is subject to the terms of the Mozilla Public
11358
11421
  // License, v2.0. If a copy of the MPL was not distributed with this
11359
11422
  // file, You can obtain one at http://mozilla.org/MPL/2.0/
11360
-
11361
- function deserializeDepthFrame({
11423
+ /* eslint-disable no-underscore-dangle */
11424
+
11425
+ const shader = `
11426
+ @group(0) @binding(0) var<storage, read> depthBuffer: array<u32>; // Uint16 stored as u32
11427
+ @group(0) @binding(1) var<storage, read> intrinsicsBuffer: array<f32>;
11428
+ @group(0) @binding(2) var<storage, read_write> xyzColorBuffer: array<u32>; // Stores XYZ + RGBA
11429
+
11430
+ @compute @workgroup_size(256, 1, 1)
11431
+ fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
11432
+ let i = global_id.x;
11433
+ let fx = intrinsicsBuffer[0];
11434
+ let fy = intrinsicsBuffer[1];
11435
+ let cx = intrinsicsBuffer[2];
11436
+ let cy = intrinsicsBuffer[3];
11437
+ let scale = intrinsicsBuffer[4];
11438
+ let width = intrinsicsBuffer[5];
11439
+ let height = intrinsicsBuffer[6];
11440
+
11441
+ if (i >= u32(width * height)) { return; }
11442
+
11443
+ let u = i % u32(width);
11444
+ let v = i / u32(width);
11445
+
11446
+ // Convert uint16 depth value to float (stored as u32, so we bitwise mask)
11447
+ let rawDepth = depthBuffer[i] & 0xFFFFu;
11448
+ let z = f32(rawDepth) * scale;
11449
+
11450
+ let x = (cx - f32(u)) * z / fx;
11451
+ let y = (cy - f32(v)) * z / fy;
11452
+
11453
+ let base = i * 4u; // 4 values per point (X, Y, Z, Color)
11454
+
11455
+ // Convert floats to u32 representation for storage
11456
+ xyzColorBuffer[base] = bitcast<u32>(x);
11457
+ xyzColorBuffer[base + 1u] = bitcast<u32>(y);
11458
+ xyzColorBuffer[base + 2u] = bitcast<u32>(z);
11459
+
11460
+ // Example: RGB set based on depth, Alpha is fixed at 255
11461
+ let r = u32(clamp(z * 255.0, 0.0, 255.0));
11462
+ let g = u32(clamp(y * 255.0, 0.0, 255.0));
11463
+ let b = u32(clamp(x * 255.0, 0.0, 255.0));
11464
+ xyzColorBuffer[base + 3u] = (r & 0xFFu) | ((g & 0xFFu) << 8) | ((b & 0xFFu) << 16) | (255u << 24);
11465
+ }
11466
+ `;
11467
+ async function depthToPointcloudGPU(depthArray, width, height, fx, fy, cx, cy) {
11468
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
11469
+ if (!navigator.gpu) {
11470
+ console.warn("WebGPU not supported.");
11471
+ return depthToPointCloudBuffer(depthArray, width, height, fx, fy, cx, cy);
11472
+ }
11473
+ const adapter = await navigator.gpu.requestAdapter();
11474
+ if (!adapter) {
11475
+ console.warn("Couldn't request WebGPU adapter.");
11476
+ return depthToPointCloudBuffer(depthArray, width, height, fx, fy, cx, cy);
11477
+ }
11478
+ const device = await adapter.requestDevice();
11479
+ const queue = device.queue;
11480
+ const scale = 1.0;
11481
+ const numPixels = width * height;
11482
+ const outputSize = numPixels * 16;
11483
+ const depthData32 = new Uint32Array(depthArray);
11484
+ const intrinsics = new Float32Array([fx, fy, cx, cy, scale, width, height]);
11485
+ const depthBuffer = device.createBuffer({
11486
+ size: depthData32.byteLength,
11487
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
11488
+ });
11489
+ const intrinsicsBuffer = device.createBuffer({
11490
+ size: intrinsics.byteLength,
11491
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST
11492
+ });
11493
+ const xyzColorBuffer = device.createBuffer({
11494
+ size: outputSize,
11495
+ usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC
11496
+ });
11497
+ queue.writeBuffer(depthBuffer, 0, depthData32);
11498
+ queue.writeBuffer(intrinsicsBuffer, 0, intrinsics);
11499
+ const bindGroupLayout = device.createBindGroupLayout({
11500
+ entries: [{
11501
+ binding: 0,
11502
+ visibility: GPUShaderStage.COMPUTE,
11503
+ buffer: {
11504
+ type: "read-only-storage"
11505
+ }
11506
+ }, {
11507
+ binding: 1,
11508
+ visibility: GPUShaderStage.COMPUTE,
11509
+ buffer: {
11510
+ type: "read-only-storage"
11511
+ }
11512
+ }, {
11513
+ binding: 2,
11514
+ visibility: GPUShaderStage.COMPUTE,
11515
+ buffer: {
11516
+ type: "storage"
11517
+ }
11518
+ }]
11519
+ });
11520
+ const bindGroup = device.createBindGroup({
11521
+ layout: bindGroupLayout,
11522
+ entries: [{
11523
+ binding: 0,
11524
+ resource: {
11525
+ buffer: depthBuffer
11526
+ }
11527
+ }, {
11528
+ binding: 1,
11529
+ resource: {
11530
+ buffer: intrinsicsBuffer
11531
+ }
11532
+ }, {
11533
+ binding: 2,
11534
+ resource: {
11535
+ buffer: xyzColorBuffer
11536
+ }
11537
+ }]
11538
+ });
11539
+ const shaderModule = device.createShaderModule({
11540
+ code: shader
11541
+ });
11542
+ const pipeline = device.createComputePipeline({
11543
+ layout: device.createPipelineLayout({
11544
+ bindGroupLayouts: [bindGroupLayout]
11545
+ }),
11546
+ compute: {
11547
+ module: shaderModule,
11548
+ entryPoint: "main"
11549
+ }
11550
+ });
11551
+ const commandEncoder = device.createCommandEncoder();
11552
+ const passEncoder = commandEncoder.beginComputePass();
11553
+ passEncoder.setPipeline(pipeline);
11554
+ passEncoder.setBindGroup(0, bindGroup);
11555
+ passEncoder.dispatchWorkgroups(Math.ceil(numPixels / 256));
11556
+ passEncoder.end();
11557
+ device.queue.submit([commandEncoder.finish()]);
11558
+ const outputBuffer = device.createBuffer({
11559
+ size: xyzColorBuffer.size,
11560
+ usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ
11561
+ });
11562
+ const copyEncoder = device.createCommandEncoder();
11563
+ copyEncoder.copyBufferToBuffer(xyzColorBuffer, 0, outputBuffer, 0, xyzColorBuffer.size);
11564
+ device.queue.submit([copyEncoder.finish()]);
11565
+
11566
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
11567
+ await outputBuffer.mapAsync(GPUMapMode.READ);
11568
+ const mappedRange = outputBuffer.getMappedRange();
11569
+ const result = new Uint8Array(mappedRange.byteLength);
11570
+ result.set(new Uint8Array(mappedRange));
11571
+ outputBuffer.unmap();
11572
+ return result;
11573
+ }
11574
+ function depthToPointCloudBuffer(uint16Array, width, height, fx, fy, cx, cy) {
11575
+ const depthData = Array.from({
11576
+ length: height
11577
+ }, () => new Array(width));
11578
+ for (let v = 0; v < height; v++) {
11579
+ depthData[v] = depthData[v] ?? [];
11580
+ for (let u = 0; u < width; u++) {
11581
+ const d = uint16Array[v * width + u] ?? -1;
11582
+ depthData[v][u] = d > 0 ? d : -1;
11583
+ }
11584
+ }
11585
+ const points = [];
11586
+ // Accumulate the x, y, z values for each pixel.
11587
+ for (let v = 0; v < height; v++) {
11588
+ const row = depthData[v];
11589
+ if (!row) {
11590
+ continue;
11591
+ }
11592
+ for (let u = 0; u < width; u++) {
11593
+ const z = row[u] ?? 0;
11594
+ const x = (cx - u) * z / fx;
11595
+ const y = (cy - v) * z / fy;
11596
+ points.push(x, y, z);
11597
+ }
11598
+ }
11599
+ const pointCount = points.length / 3;
11600
+ const buffer = new ArrayBuffer(pointCount * 16);
11601
+ const view = new DataView(buffer);
11602
+ for (let i = 0; i < pointCount; i++) {
11603
+ const offset = i * 16;
11604
+ view.setFloat32(offset, points[i * 3] ?? 0, true); //X
11605
+ view.setFloat32(offset + 4, points[i * 3 + 1] ?? 0, true); //Y
11606
+ view.setFloat32(offset + 8, points[i * 3 + 2] ?? 0, true); //Z
11607
+ view.setUint8(offset + 12, 0); // R
11608
+ view.setUint8(offset + 13, 0); // G
11609
+ view.setUint8(offset + 14, 0); // B
11610
+ view.setUint8(offset + 15, 255); // A
11611
+ }
11612
+ return new Uint8Array(buffer);
11613
+ }
11614
+ async function deserializeDepthFrame({
11362
11615
  topic,
11363
11616
  message,
11364
11617
  callback
11365
11618
  }) {
11366
11619
  const {
11367
11620
  receiveTime,
11368
- encoding,
11369
- step,
11370
11621
  width,
11371
11622
  height
11372
11623
  } = parseMessage(message);
11624
+ const neuralCameraIntrinsics = JSON.parse(localStorage.getItem("neuralCameraIntrinsics") ?? "{}");
11625
+ const uint16Array = uint8ArrayToUint16Array(message.data);
11626
+ const fx = neuralCameraIntrinsics.right.focalLenght.x;
11627
+ const fy = neuralCameraIntrinsics.right.focalLenght.y;
11628
+ const cx = neuralCameraIntrinsics.right.principalPoint.x;
11629
+ const cy = neuralCameraIntrinsics.right.principalPoint.y;
11630
+ const pointCloudBufferGPU = depthToPointcloudGPU(uint16Array, width, height, fx, fy, cx, cy);
11373
11631
  const foxgloveMessage = {
11374
11632
  timestamp: receiveTime,
11375
- frame_id: `depth-${topic}-frame`,
11633
+ frame_id: `pointcloud-${topic}-frame`,
11634
+ point_stride: 16,
11635
+ pose: {
11636
+ position: {
11637
+ x: 0,
11638
+ y: 0,
11639
+ z: 0
11640
+ },
11641
+ orientation: {
11642
+ x: 0,
11643
+ y: 0,
11644
+ z: 1,
11645
+ w: 0
11646
+ }
11647
+ },
11376
11648
  width,
11377
11649
  height,
11378
- encoding,
11379
- step: width * step,
11380
- data: message.data
11650
+ fields: [{
11651
+ name: "x",
11652
+ offset: 0,
11653
+ type: typescript$1.NumericType.FLOAT32
11654
+ }, {
11655
+ name: "y",
11656
+ offset: 4,
11657
+ type: typescript$1.NumericType.FLOAT32
11658
+ }, {
11659
+ name: "z",
11660
+ offset: 8,
11661
+ type: typescript$1.NumericType.FLOAT32
11662
+ }, {
11663
+ name: "red",
11664
+ offset: 12,
11665
+ type: typescript$1.NumericType.UINT8
11666
+ }, {
11667
+ name: "green",
11668
+ offset: 13,
11669
+ type: typescript$1.NumericType.UINT8
11670
+ }, {
11671
+ name: "blue",
11672
+ offset: 14,
11673
+ type: typescript$1.NumericType.UINT8
11674
+ }, {
11675
+ name: "alpha",
11676
+ offset: 15,
11677
+ type: typescript$1.NumericType.UINT8
11678
+ }],
11679
+ data: await pointCloudBufferGPU
11381
11680
  };
11382
11681
  callback({
11383
11682
  topic,
11384
11683
  receiveTime,
11385
11684
  message: foxgloveMessage,
11386
11685
  sizeInBytes: estimateObjectSize(foxgloveMessage),
11387
- schemaName: "foxglove.RawImage"
11686
+ schemaName: "foxglove.PointCloud"
11388
11687
  });
11389
11688
  }
11390
11689
 
@@ -11549,7 +11848,9 @@ async function deserializeDepthAiMessage(args) {
11549
11848
  callback,
11550
11849
  topic
11551
11850
  } = args;
11552
- console.log(`Encoded "${type}" message at ${new Date().toLocaleString()}`, message);
11851
+
11852
+ //console.log(`Encoded "${type}" message at ${new Date().toLocaleString()}`, message);
11853
+
11553
11854
  switch (type) {
11554
11855
  case "encodedFrame":
11555
11856
  {
@@ -11597,7 +11898,7 @@ async function deserializeDepthAiMessage(args) {
11597
11898
  }
11598
11899
  case Type$1.RAW16:
11599
11900
  {
11600
- deserializeDepthFrame({
11901
+ await deserializeDepthFrame({
11601
11902
  topic,
11602
11903
  message,
11603
11904
  callback
@@ -11773,8 +12074,8 @@ class FoxgloveConnection {
11773
12074
  }
11774
12075
  getTopicMetrics(topic) {
11775
12076
  return {
11776
- inputFPS: this.inputMetrics.calculate(topic),
11777
- postDecodeFPS: this.decodeMetrics.calculate(topic)
12077
+ incomingMessagesFps: this.inputMetrics.calculate(topic),
12078
+ decodedMessagesFps: this.decodeMetrics.calculate(topic)
11778
12079
  };
11779
12080
  }
11780
12081
  getCurrentTime() {
@@ -11786,6 +12087,18 @@ class FoxgloveConnection {
11786
12087
  }
11787
12088
  handleParsedMessage(event) {
11788
12089
  this.decodeMetrics.registerEvent(event.topic);
12090
+ if (event.topic === "H.264 Stream") {
12091
+ this.lastEncodedFrame = event;
12092
+ }
12093
+ if (event.topic === "Point Cloud") {
12094
+ if (!this.lastEncodedFrame) {
12095
+ console.warn("didnt find H.264 Stream");
12096
+ } else {
12097
+ // @ts-expect-error - ITS unknow
12098
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
12099
+ event.message.data = i420ToRgbaToPointcloud(this.lastEncodedFrame.message.data, this.lastEncodedFrame.message.width, this.lastEncodedFrame.message.height, event.message.width, event.message.height, event.message.data);
12100
+ }
12101
+ }
11789
12102
  const messageSize = estimateObjectSize(event.message);
11790
12103
  event.sizeInBytes = messageSize;
11791
12104
  this.messageEvents.push(event);
@@ -12327,44 +12640,6 @@ class WebRtcClient {
12327
12640
  on = this.events.on.bind(this.events);
12328
12641
  }
12329
12642
 
12330
- // This Source Code Form is subject to the terms of the Mozilla Public
12331
- // License, v2.0. If a copy of the MPL was not distributed with this
12332
- // file, You can obtain one at http://mozilla.org/MPL/2.0/
12333
-
12334
- class ArtificialWorker extends EventTarget {
12335
- #selfTarget = new EventTarget();
12336
-
12337
- // Post message from main to worker
12338
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
12339
- postMessage(data, _transferable) {
12340
- const event = new MessageEvent('message', {
12341
- data
12342
- });
12343
- this.#selfTarget.dispatchEvent(event);
12344
- }
12345
-
12346
- // Listen for worker-to-main messages
12347
- // @ts-expect-error Make it typed
12348
- addEventListener(type, callback) {
12349
- super.addEventListener(type, callback);
12350
- }
12351
-
12352
- // Post message from worker to main
12353
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
12354
- postMessageToMain(data, _transferable) {
12355
- const event = new MessageEvent('message', {
12356
- data
12357
- });
12358
- super.dispatchEvent(event);
12359
- }
12360
-
12361
- // Listen for main-to-worker messages
12362
- // @ts-expect-error Make it typed
12363
- addEventListenerFromMain(type, callback) {
12364
- this.#selfTarget.addEventListener(type, callback);
12365
- }
12366
- }
12367
-
12368
12643
  var safeStableStringify = {exports: {}};
12369
12644
 
12370
12645
  (function (module, exports) {
@@ -29850,6 +30125,10 @@ const uuidv7 = () => uuidv7obj().toString();
29850
30125
  /** Generates a UUIDv7 object. */
29851
30126
  const uuidv7obj = () => (defaultGenerator$1 || (defaultGenerator$1 = new V7Generator())).generate();
29852
30127
 
30128
+ // This Source Code Form is subject to the terms of the Mozilla Public
30129
+ // License, v2.0. If a copy of the MPL was not distributed with this
30130
+ // file, You can obtain one at http://mozilla.org/MPL/2.0/
30131
+
29853
30132
  const GET_APP_CONNECTION = () => ({
29854
30133
  GetAppConnection: {}
29855
30134
  });
@@ -29903,7 +30182,7 @@ class WebRtcCommsProxy {
29903
30182
  }
29904
30183
  }
29905
30184
  #isAppConnectionResponse(message) {
29906
- return message.data.Ok?.GetAppConnection !== undefined;
30185
+ return message.data.Ok.GetAppConnection !== undefined;
29907
30186
  }
29908
30187
  #startRefreshInterval() {
29909
30188
  this.#refreshIntervalId = setInterval(() => {
@@ -29916,6 +30195,44 @@ class WebRtcCommsProxy {
29916
30195
  // License, v2.0. If a copy of the MPL was not distributed with this
29917
30196
  // file, You can obtain one at http://mozilla.org/MPL/2.0/
29918
30197
 
30198
+ class ArtificialWorker extends EventTarget {
30199
+ #selfTarget = new EventTarget();
30200
+
30201
+ // Post message from main to worker
30202
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
30203
+ postMessage(data, _transferable) {
30204
+ const event = new MessageEvent('message', {
30205
+ data
30206
+ });
30207
+ this.#selfTarget.dispatchEvent(event);
30208
+ }
30209
+
30210
+ // Listen for worker-to-main messages
30211
+ // @ts-expect-error Make it typed
30212
+ addEventListener(type, callback) {
30213
+ super.addEventListener(type, callback);
30214
+ }
30215
+
30216
+ // Post message from worker to main
30217
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
30218
+ postMessageToMain(data, _transferable) {
30219
+ const event = new MessageEvent('message', {
30220
+ data
30221
+ });
30222
+ super.dispatchEvent(event);
30223
+ }
30224
+
30225
+ // Listen for main-to-worker messages
30226
+ // @ts-expect-error Make it typed
30227
+ addEventListenerFromMain(type, callback) {
30228
+ this.#selfTarget.addEventListener(type, callback);
30229
+ }
30230
+ }
30231
+
30232
+ // This Source Code Form is subject to the terms of the Mozilla Public
30233
+ // License, v2.0. If a copy of the MPL was not distributed with this
30234
+ // file, You can obtain one at http://mozilla.org/MPL/2.0/
30235
+
29919
30236
  const MESSAGE_CHANNEL_NAME = "message";
29920
30237
  const SYSTEM_CHANNEL_NAME = "system";
29921
30238
  const COMMS_CHANNEL_NAME = "comms";
@@ -90251,7 +90568,7 @@ function legacy(parser) {
90251
90568
  return new LanguageSupport(StreamLanguage.define(parser));
90252
90569
  }
90253
90570
  function sql$1(dialectName) {
90254
- return import('./index-PSBhGaEs.js').then(m => m.sql({ dialect: m[dialectName] }));
90571
+ return import('./index-nJgMRJTy.js').then(m => m.sql({ dialect: m[dialectName] }));
90255
90572
  }
90256
90573
  /**
90257
90574
  An array of language descriptions for known language packages.
@@ -90262,7 +90579,7 @@ const languages = [
90262
90579
  name: "C",
90263
90580
  extensions: ["c", "h", "ino"],
90264
90581
  load() {
90265
- return import('./index-vCAg8fos.js').then(m => m.cpp());
90582
+ return import('./index-DyoCH5GH.js').then(m => m.cpp());
90266
90583
  }
90267
90584
  }),
90268
90585
  /*@__PURE__*/LanguageDescription.of({
@@ -90270,7 +90587,7 @@ const languages = [
90270
90587
  alias: ["cpp"],
90271
90588
  extensions: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"],
90272
90589
  load() {
90273
- return import('./index-vCAg8fos.js').then(m => m.cpp());
90590
+ return import('./index-DyoCH5GH.js').then(m => m.cpp());
90274
90591
  }
90275
90592
  }),
90276
90593
  /*@__PURE__*/LanguageDescription.of({
@@ -90290,7 +90607,7 @@ const languages = [
90290
90607
  name: "Go",
90291
90608
  extensions: ["go"],
90292
90609
  load() {
90293
- return import('./index-B9aXaLUR.js').then(m => m.go());
90610
+ return import('./index-fN8Tpgww.js').then(m => m.go());
90294
90611
  }
90295
90612
  }),
90296
90613
  /*@__PURE__*/LanguageDescription.of({
@@ -90305,7 +90622,7 @@ const languages = [
90305
90622
  name: "Java",
90306
90623
  extensions: ["java"],
90307
90624
  load() {
90308
- return import('./index-Cc3zOB0y.js').then(m => m.java());
90625
+ return import('./index-PmNaQtc7.js').then(m => m.java());
90309
90626
  }
90310
90627
  }),
90311
90628
  /*@__PURE__*/LanguageDescription.of({
@@ -90321,7 +90638,7 @@ const languages = [
90321
90638
  alias: ["json5"],
90322
90639
  extensions: ["json", "map"],
90323
90640
  load() {
90324
- return import('./index-CqFRR40y.js').then(m => m.json());
90641
+ return import('./index-CtKYoeeM.js').then(m => m.json());
90325
90642
  }
90326
90643
  }),
90327
90644
  /*@__PURE__*/LanguageDescription.of({
@@ -90335,14 +90652,14 @@ const languages = [
90335
90652
  name: "LESS",
90336
90653
  extensions: ["less"],
90337
90654
  load() {
90338
- return import('./index-BiV6mWEH.js').then(m => m.less());
90655
+ return import('./index-Do7UsSft.js').then(m => m.less());
90339
90656
  }
90340
90657
  }),
90341
90658
  /*@__PURE__*/LanguageDescription.of({
90342
90659
  name: "Liquid",
90343
90660
  extensions: ["liquid"],
90344
90661
  load() {
90345
- return import('./index-BLoXvLKz.js').then(m => m.liquid());
90662
+ return import('./index-BbAm1fKU.js').then(m => m.liquid());
90346
90663
  }
90347
90664
  }),
90348
90665
  /*@__PURE__*/LanguageDescription.of({
@@ -90368,7 +90685,7 @@ const languages = [
90368
90685
  name: "PHP",
90369
90686
  extensions: ["php", "php3", "php4", "php5", "php7", "phtml"],
90370
90687
  load() {
90371
- return import('./index-BTtZZhIx.js').then(m => m.php());
90688
+ return import('./index-CpLzYoX8.js').then(m => m.php());
90372
90689
  }
90373
90690
  }),
90374
90691
  /*@__PURE__*/LanguageDescription.of({
@@ -90385,28 +90702,28 @@ const languages = [
90385
90702
  extensions: ["BUILD", "bzl", "py", "pyw"],
90386
90703
  filename: /^(BUCK|BUILD)$/,
90387
90704
  load() {
90388
- return import('./index-CjJ4xAdB.js').then(m => m.python());
90705
+ return import('./index-BK0O58zw.js').then(m => m.python());
90389
90706
  }
90390
90707
  }),
90391
90708
  /*@__PURE__*/LanguageDescription.of({
90392
90709
  name: "Rust",
90393
90710
  extensions: ["rs"],
90394
90711
  load() {
90395
- return import('./index-B61jalVx.js').then(m => m.rust());
90712
+ return import('./index-CbS2HMyR.js').then(m => m.rust());
90396
90713
  }
90397
90714
  }),
90398
90715
  /*@__PURE__*/LanguageDescription.of({
90399
90716
  name: "Sass",
90400
90717
  extensions: ["sass"],
90401
90718
  load() {
90402
- return import('./index-BisiS-gw.js').then(m => m.sass({ indented: true }));
90719
+ return import('./index-DTZuXJ1A.js').then(m => m.sass({ indented: true }));
90403
90720
  }
90404
90721
  }),
90405
90722
  /*@__PURE__*/LanguageDescription.of({
90406
90723
  name: "SCSS",
90407
90724
  extensions: ["scss"],
90408
90725
  load() {
90409
- return import('./index-BisiS-gw.js').then(m => m.sass());
90726
+ return import('./index-DTZuXJ1A.js').then(m => m.sass());
90410
90727
  }
90411
90728
  }),
90412
90729
  /*@__PURE__*/LanguageDescription.of({
@@ -90437,7 +90754,7 @@ const languages = [
90437
90754
  name: "WebAssembly",
90438
90755
  extensions: ["wat", "wast"],
90439
90756
  load() {
90440
- return import('./index-9X5IFBUj.js').then(m => m.wast());
90757
+ return import('./index-4msm-wtA.js').then(m => m.wast());
90441
90758
  }
90442
90759
  }),
90443
90760
  /*@__PURE__*/LanguageDescription.of({
@@ -90445,7 +90762,7 @@ const languages = [
90445
90762
  alias: ["rss", "wsdl", "xsd"],
90446
90763
  extensions: ["xml", "xsl", "xsd", "svg"],
90447
90764
  load() {
90448
- return import('./index-2Zk3DeS3.js').then(m => m.xml());
90765
+ return import('./index-DSIL_c41.js').then(m => m.xml());
90449
90766
  }
90450
90767
  }),
90451
90768
  /*@__PURE__*/LanguageDescription.of({
@@ -90453,7 +90770,7 @@ const languages = [
90453
90770
  alias: ["yml"],
90454
90771
  extensions: ["yaml", "yml"],
90455
90772
  load() {
90456
- return import('./index-CC5SpeJH.js').then(m => m.yaml());
90773
+ return import('./index-DFdQY59I.js').then(m => m.yaml());
90457
90774
  }
90458
90775
  }),
90459
90776
  // Legacy modes ported from CodeMirror 5
@@ -91249,13 +91566,13 @@ const languages = [
91249
91566
  name: "Vue",
91250
91567
  extensions: ["vue"],
91251
91568
  load() {
91252
- return import('./index-Cm0UpxTw.js').then(m => m.vue());
91569
+ return import('./index-DfgdvKhl.js').then(m => m.vue());
91253
91570
  }
91254
91571
  }),
91255
91572
  /*@__PURE__*/LanguageDescription.of({
91256
91573
  name: "Angular Template",
91257
91574
  load() {
91258
- return import('./index-prbig-mv.js').then(m => m.angular());
91575
+ return import('./index-BsQeBBzM.js').then(m => m.angular());
91259
91576
  }
91260
91577
  })
91261
91578
  ];
@@ -162059,6 +162376,24 @@ function ImCheckboxChecked (props) {
162059
162376
  var css$1 = "@layer reset, base, tokens, recipes, utilities;\n\n@layer reset{\n * {\n margin: 0;\n padding: 0;\n font: inherit;\n }\n\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n border-width: 0;\n border-style: solid;\n border-color: var(--global-color-border, currentColor);\n }\n\n html {\n line-height: 1.5;\n --font-fallback: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,\n 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',\n 'Noto Color Emoji';\n -webkit-text-size-adjust: 100%;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n -moz-tab-size: 4;\n tab-size: 4;\n font-family: var(--global-font-body, var(--font-fallback));\n }\n\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n\n body {\n height: 100%;\n line-height: inherit;\n }\n\n img {\n border-style: none;\n }\n\n img,\n svg,\n video,\n canvas,\n audio,\n iframe,\n embed,\n object {\n display: block;\n vertical-align: middle;\n }\n\n img,\n video {\n max-width: 100%;\n height: auto;\n }\n\n p,\n h1,\n h2,\n h3,\n h4,\n h5,\n h6 {\n overflow-wrap: break-word;\n }\n\n ol,\n ul {\n list-style: none;\n }\n\n code,\n kbd,\n pre,\n samp {\n font-size: 1em;\n }\n\n button,\n [type='button'],\n [type='reset'],\n [type='submit'] {\n -webkit-appearance: button;\n background-color: transparent;\n background-image: none;\n }\n\n button,\n input,\n optgroup,\n select,\n textarea {\n color: inherit;\n }\n\n button,\n select {\n text-transform: none;\n }\n\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n\n input::placeholder,\n textarea::placeholder {\n opacity: 1;\n color: var(--global-color-placeholder, #9ca3af);\n }\n\n textarea {\n resize: vertical;\n }\n\n summary {\n display: list-item;\n }\n\n small {\n font-size: 80%;\n }\n\n sub,\n sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n\n sub {\n bottom: -0.25em;\n }\n\n sup {\n top: -0.5em;\n }\n\n dialog {\n padding: 0;\n }\n\n a {\n color: inherit;\n text-decoration: inherit;\n }\n\n abbr:where([title]) {\n text-decoration: underline dotted;\n }\n\n b,\n strong {\n font-weight: bolder;\n }\n\n code,\n kbd,\n samp,\n pre {\n font-size: 1em;\n --font-mono-fallback: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New';\n font-family: var(--global-font-mono, var(--font-mono-fallback));\n }\n\n input[type=\"text\"],\n input[type=\"email\"],\n input[type=\"search\"],\n input[type=\"password\"] {\n -webkit-appearance: none;\n -moz-appearance: none;\n }\n\n input[type='search'] {\n -webkit-appearance: textfield;\n outline-offset: -2px;\n }\n\n ::-webkit-search-decoration,\n ::-webkit-search-cancel-button {\n -webkit-appearance: none;\n }\n\n ::-webkit-file-upload-button {\n -webkit-appearance: button;\n font: inherit;\n }\n\n input[type=\"number\"]::-webkit-inner-spin-button,\n input[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n }\n\n input[type='number']{\n -moz-appearance: textfield;\n }\n\n :-moz-ui-invalid {\n box-shadow: none;\n }\n\n :-moz-focusring {\n outline: auto;\n }\n}\n\n@layer base{\n :root{\n --made-with-panda: '🐼';\n }\n\n *, *::before, *::after, ::backdrop{\n --blur: ;\n --brightness: ;\n --contrast: ;\n --grayscale: ;\n --hue-rotate: ;\n --invert: ;\n --saturate: ;\n --sepia: ;\n --drop-shadow: ;\n --backdrop-blur: ;\n --backdrop-brightness: ;\n --backdrop-contrast: ;\n --backdrop-grayscale: ;\n --backdrop-hue-rotate: ;\n --backdrop-invert: ;\n --backdrop-opacity: ;\n --backdrop-saturate: ;\n --backdrop-sepia: ;\n --scroll-snap-strictness: proximity;\n --border-spacing-x: 0;\n --border-spacing-y: 0;\n --translate-x: 0;\n --translate-y: 0;\n --rotate: 0;\n --skew-x: 0;\n --skew-y: 0;\n --scale-x: 1;\n --scale-y: 1;\n }\n\n html{\n -moz-osx-font-smoothing: grayscale;\n text-rendering: optimizeLegibility;\n -webkit-font-smoothing: antialiased;\n -webkit-text-size-adjust: 100%;\n }\n\n body{\n background: var(--colors-background);\n color: var(--colors-foreground);\n font-family: var(--fonts-sans);\n }\n\n button{\n color: inherit;\n outline: 2px solid transparent;\n }\n\n *{\n box-sizing: border-box;\n font-family: var(--fonts-body);\n }\n\n html, body{\n margin: var(--spacing-0);\n padding: var(--spacing-0);\n }\n\n #root{\n display: flex;\n flex-direction: column;\n height: 100vh;\n }\n}\n\n@layer tokens{\n :where(:root, :host) {\n --letter-spacings-tighter: -0.05em;\n --letter-spacings-tight: -0.025em;\n --letter-spacings-normal: 0em;\n --letter-spacings-wide: 0.025em;\n --letter-spacings-wider: 0.05em;\n --letter-spacings-widest: 0.1em;\n --blurs-sm: 4px;\n --blurs-base: 8px;\n --blurs-md: 12px;\n --blurs-lg: 16px;\n --blurs-xl: 24px;\n --blurs-2xl: 40px;\n --blurs-3xl: 64px;\n --animations-spin: spin 1s linear infinite;\n --animations-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;\n --animations-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;\n --animations-bounce: bounce 1s infinite;\n --font-sizes-2xs: 0.5rem;\n --font-sizes-2xl: 1.5rem;\n --font-sizes-3xl: 1.875rem;\n --font-sizes-4xl: 2.25rem;\n --font-sizes-5xl: 3rem;\n --font-sizes-6xl: 3.75rem;\n --font-sizes-7xl: 4.5rem;\n --font-sizes-8xl: 6rem;\n --font-sizes-9xl: 8rem;\n --font-sizes-xxs: 10px;\n --font-sizes-xs: 12px;\n --font-sizes-sm: 14px;\n --font-sizes-primary: 16px;\n --font-sizes-md: 20px;\n --font-sizes-lg: 24px;\n --font-sizes-xl: 32px;\n --font-weights-thin: 100;\n --font-weights-extralight: 200;\n --font-weights-light: 300;\n --font-weights-normal: 400;\n --font-weights-medium: 500;\n --font-weights-semibold: 600;\n --font-weights-bold: 700;\n --font-weights-extrabold: 800;\n --font-weights-black: 900;\n --font-weights-primary: 400;\n --font-weights-md: 500;\n --font-weights-lg: 600;\n --font-weights-xl: 800;\n --sizes-0: 0rem;\n --sizes-1: 0.25rem;\n --sizes-2: 0.5rem;\n --sizes-3: 0.75rem;\n --sizes-4: 1rem;\n --sizes-5: 1.25rem;\n --sizes-6: 1.5rem;\n --sizes-7: 1.75rem;\n --sizes-8: 2rem;\n --sizes-9: 2.25rem;\n --sizes-10: 2.5rem;\n --sizes-11: 2.75rem;\n --sizes-12: 3rem;\n --sizes-14: 3.5rem;\n --sizes-16: 4rem;\n --sizes-20: 5rem;\n --sizes-24: 6rem;\n --sizes-28: 7rem;\n --sizes-32: 8rem;\n --sizes-36: 9rem;\n --sizes-40: 10rem;\n --sizes-44: 11rem;\n --sizes-48: 12rem;\n --sizes-52: 13rem;\n --sizes-56: 14rem;\n --sizes-60: 15rem;\n --sizes-64: 16rem;\n --sizes-72: 18rem;\n --sizes-80: 20rem;\n --sizes-96: 24rem;\n --sizes-0\\.5: 0.125rem;\n --sizes-1\\.5: 0.375rem;\n --sizes-2\\.5: 0.625rem;\n --sizes-3\\.5: 0.875rem;\n --sizes-xs: 20rem;\n --sizes-sm: 24rem;\n --sizes-md: 28rem;\n --sizes-lg: 32rem;\n --sizes-xl: 36rem;\n --sizes-2xl: 42rem;\n --sizes-3xl: 48rem;\n --sizes-4xl: 56rem;\n --sizes-5xl: 64rem;\n --sizes-6xl: 72rem;\n --sizes-7xl: 80rem;\n --sizes-8xl: 90rem;\n --sizes-prose: 65ch;\n --sizes-full: 100%;\n --sizes-min: min-content;\n --sizes-max: max-content;\n --sizes-fit: fit-content;\n --sizes-basic-almost-full: 90%;\n --sizes-card-xs: 175px;\n --sizes-card-sm: 414px;\n --sizes-responsive-card-xs: min(95vw,var(--sizes-card-xs));\n --sizes-responsive-card-sm: min(95vw,var(--sizes-card-sm));\n --sizes-circle: 40px;\n --sizes-container-smaller-xxxs: 80px;\n --sizes-container-smaller-xxs: 120px;\n --sizes-container-smaller-xs: 290px;\n --sizes-container-smaller-sm: 410px;\n --sizes-container-bigger-xs: 380px;\n --sizes-container-xxs: 150px;\n --sizes-container-xs: 350px;\n --sizes-container-sm: 640px;\n --sizes-container-md: 768px;\n --sizes-container-lg: 1024px;\n --sizes-container-xl: 1280px;\n --sizes-container-xxl: 1440px;\n --sizes-container-content-xl: 729px;\n --sizes-container-content-2xl: 829px;\n --sizes-container-grid-base-size: 220px;\n --sizes-container-grid-label-height: 56px;\n --sizes-container-grid-grid-gap: 28px;\n --sizes-container-side-bar-collapsed: 65px;\n --sizes-container-side-bar-expanded: 210px;\n --sizes-table-cell-min-width: 200px;\n --sizes-table-instances-name-cell: 300px;\n --sizes-table-instances-name: 200px;\n --sizes-table-instances-cell: 180px;\n --sizes-sourcecode-width: 40px;\n --sizes-slider-label: 40px;\n --sizes-slider-thumb-sm: 16px;\n --sizes-slider-thumb-lg: 20px;\n --sizes-skeleton-height: 40px;\n --sizes-skeleton-width: full;\n --sizes-skeleton-button-width: 150px;\n --sizes-skeleton-button-height: var(--sizes-skeleton-height);\n --sizes-skeleton-input-width: 230px;\n --sizes-skeleton-input-height: var(--sizes-skeleton-height);\n --sizes-skeleton-textarea-width: var(--sizes-skeleton-width);\n --sizes-skeleton-textarea-height: 80px;\n --sizes-skeleton-avatar-width: var(--sizes-skeleton-height);\n --sizes-skeleton-avatar-height: var(--sizes-skeleton-height);\n --sizes-skeleton-grid-width-xs: 32px;\n --sizes-skeleton-grid-width-sm: 64px;\n --sizes-skeleton-grid-width-md: 128px;\n --sizes-skeleton-grid-width-lg: 256px;\n --sizes-skeleton-grid-width-xl: 512px;\n --sizes-skeleton-grid-height-xs: 32px;\n --sizes-skeleton-grid-height-sm: 64px;\n --sizes-skeleton-grid-height-md: 128px;\n --sizes-skeleton-grid-height-lg: 256px;\n --sizes-skeleton-grid-height-xl: 512px;\n --sizes-skeleton-table-height-sm: 32px;\n --sizes-skeleton-table-height-md: 64px;\n --sizes-skeleton-table-height-lg: 128px;\n --sizes-skeleton-table-height-xl: 256px;\n --sizes-icon-xxs: 8px;\n --sizes-icon-xs: 16px;\n --sizes-icon-sm: 20px;\n --sizes-icon-md: 24px;\n --sizes-icon-lg: 32px;\n --sizes-icon-xl: 40px;\n --sizes-icon-xxl: 48px;\n --sizes-icon-smaller-xs: 14px;\n --sizes-breakpoint-2lg: 1100px;\n --sizes-breakpoint-sm: 640px;\n --sizes-breakpoint-md: 768px;\n --sizes-breakpoint-lg: 1024px;\n --sizes-breakpoint-xl: 1280px;\n --sizes-breakpoint-2xl: 1536px;\n --spacing-0: 0rem;\n --spacing-1: 0.25rem;\n --spacing-2: 0.5rem;\n --spacing-3: 0.75rem;\n --spacing-4: 1rem;\n --spacing-5: 1.25rem;\n --spacing-6: 1.5rem;\n --spacing-7: 1.75rem;\n --spacing-8: 2rem;\n --spacing-9: 2.25rem;\n --spacing-10: 2.5rem;\n --spacing-11: 2.75rem;\n --spacing-12: 3rem;\n --spacing-14: 3.5rem;\n --spacing-16: 4rem;\n --spacing-20: 5rem;\n --spacing-24: 6rem;\n --spacing-28: 7rem;\n --spacing-32: 8rem;\n --spacing-36: 9rem;\n --spacing-40: 10rem;\n --spacing-44: 11rem;\n --spacing-48: 12rem;\n --spacing-52: 13rem;\n --spacing-56: 14rem;\n --spacing-60: 15rem;\n --spacing-64: 16rem;\n --spacing-72: 18rem;\n --spacing-80: 20rem;\n --spacing-96: 24rem;\n --spacing-0\\.5: 0.125rem;\n --spacing-1\\.5: 0.375rem;\n --spacing-2\\.5: 0.625rem;\n --spacing-3\\.5: 0.875rem;\n --spacing-separator: 10px;\n --spacing-smaller-xs: 4px;\n --spacing-smaller-sm: 12px;\n --spacing-smaller-md: 14px;\n --spacing-xxs: 6px;\n --spacing-xs: 8px;\n --spacing-sm: 16px;\n --spacing-3xs: 24px;\n --spacing-md: 32px;\n --spacing-lg: 64px;\n --shadows-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);\n --shadows-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);\n --shadows-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);\n --shadows-xs: 0px 1px 2px rgba(16, 24, 40, 0.05);\n --shadows-sm: 0px 1px 3px rgba(16, 24, 40, 0.1), 0px 1px 2px rgba(16, 24, 40, 0.06);\n --shadows-md: 0px 4px 8px -2px rgba(16, 24, 40, 0.1), 0px 2px 4px -2px rgba(16, 24, 40, 0.06);\n --shadows-lg: 0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03);\n --borders-none: none;\n --borders-outline-base: 1px solid var(--colors-light-gray);\n --borders-border-base: 1px solid var(--colors-decoration-gray);\n --borders-border-error: 1px solid var(--colors-decoration-error);\n --borders-border-success: 1px solid var(--colors-decoration-success);\n --borders-border-active: 1px solid var(--colors-decoration-active);\n --opacity-90: 0.9;\n --easings-default: cubic-bezier(0.4, 0, 0.2, 1);\n --easings-linear: linear;\n --easings-in: cubic-bezier(0.4, 0, 1, 1);\n --easings-out: cubic-bezier(0, 0, 0.2, 1);\n --easings-in-out: cubic-bezier(0.4, 0, 0.2, 1);\n --easings-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);\n --durations-fastest: 50ms;\n --durations-faster: 100ms;\n --durations-normal: 200ms;\n --durations-slow: 300ms;\n --durations-slower: 400ms;\n --durations-slowest: 500ms;\n --durations-fast: 150ms;\n --colors-current: currentColor;\n --colors-black: #000;\n --colors-white: #fff;\n --colors-transparent: rgb(0 0 0 / 0);\n --colors-rose-50: #fff1f2;\n --colors-rose-100: #ffe4e6;\n --colors-rose-200: #fecdd3;\n --colors-rose-300: #fda4af;\n --colors-rose-400: #fb7185;\n --colors-rose-500: #f43f5e;\n --colors-rose-600: #e11d48;\n --colors-rose-700: #be123c;\n --colors-rose-800: #9f1239;\n --colors-rose-900: #881337;\n --colors-rose-950: #4c0519;\n --colors-pink-50: #fdf2f8;\n --colors-pink-100: #fce7f3;\n --colors-pink-200: #fbcfe8;\n --colors-pink-300: #f9a8d4;\n --colors-pink-400: #f472b6;\n --colors-pink-500: #ec4899;\n --colors-pink-600: #db2777;\n --colors-pink-700: #be185d;\n --colors-pink-800: #9d174d;\n --colors-pink-900: #831843;\n --colors-pink-950: #500724;\n --colors-fuchsia-50: #fdf4ff;\n --colors-fuchsia-100: #fae8ff;\n --colors-fuchsia-200: #f5d0fe;\n --colors-fuchsia-300: #f0abfc;\n --colors-fuchsia-400: #e879f9;\n --colors-fuchsia-500: #d946ef;\n --colors-fuchsia-600: #c026d3;\n --colors-fuchsia-700: #a21caf;\n --colors-fuchsia-800: #86198f;\n --colors-fuchsia-900: #701a75;\n --colors-fuchsia-950: #4a044e;\n --colors-purple-50: #faf5ff;\n --colors-purple-100: #f3e8ff;\n --colors-purple-200: #e9d5ff;\n --colors-purple-300: #d8b4fe;\n --colors-purple-400: #c084fc;\n --colors-purple-500: #a855f7;\n --colors-purple-600: #9333ea;\n --colors-purple-700: #7e22ce;\n --colors-purple-800: #6b21a8;\n --colors-purple-900: #581c87;\n --colors-purple-950: #3b0764;\n --colors-violet-50: #f5f3ff;\n --colors-violet-100: #ede9fe;\n --colors-violet-200: #ddd6fe;\n --colors-violet-300: #c4b5fd;\n --colors-violet-400: #a78bfa;\n --colors-violet-500: #8b5cf6;\n --colors-violet-600: #7c3aed;\n --colors-violet-700: #6d28d9;\n --colors-violet-800: #5b21b6;\n --colors-violet-900: #4c1d95;\n --colors-violet-950: #2e1065;\n --colors-indigo-50: #eef2ff;\n --colors-indigo-100: #e0e7ff;\n --colors-indigo-200: #c7d2fe;\n --colors-indigo-300: #a5b4fc;\n --colors-indigo-400: #818cf8;\n --colors-indigo-500: #6366f1;\n --colors-indigo-600: #4f46e5;\n --colors-indigo-700: #4338ca;\n --colors-indigo-800: #3730a3;\n --colors-indigo-900: #312e81;\n --colors-indigo-950: #1e1b4b;\n --colors-blue-50: #eff6ff;\n --colors-blue-100: #dbeafe;\n --colors-blue-200: #bfdbfe;\n --colors-blue-300: #93c5fd;\n --colors-blue-400: #60a5fa;\n --colors-blue-500: #3b82f6;\n --colors-blue-600: #2563eb;\n --colors-blue-700: #1d4ed8;\n --colors-blue-800: #1e40af;\n --colors-blue-900: #1e3a8a;\n --colors-blue-950: #172554;\n --colors-sky-50: #f0f9ff;\n --colors-sky-100: #e0f2fe;\n --colors-sky-200: #bae6fd;\n --colors-sky-300: #7dd3fc;\n --colors-sky-400: #38bdf8;\n --colors-sky-500: #0ea5e9;\n --colors-sky-600: #0284c7;\n --colors-sky-700: #0369a1;\n --colors-sky-800: #075985;\n --colors-sky-900: #0c4a6e;\n --colors-sky-950: #082f49;\n --colors-cyan-50: #ecfeff;\n --colors-cyan-100: #cffafe;\n --colors-cyan-200: #a5f3fc;\n --colors-cyan-300: #67e8f9;\n --colors-cyan-400: #22d3ee;\n --colors-cyan-500: #06b6d4;\n --colors-cyan-600: #0891b2;\n --colors-cyan-700: #0e7490;\n --colors-cyan-800: #155e75;\n --colors-cyan-900: #164e63;\n --colors-cyan-950: #083344;\n --colors-teal-50: #f0fdfa;\n --colors-teal-100: #ccfbf1;\n --colors-teal-200: #99f6e4;\n --colors-teal-300: #5eead4;\n --colors-teal-400: #2dd4bf;\n --colors-teal-500: #14b8a6;\n --colors-teal-600: #0d9488;\n --colors-teal-700: #0f766e;\n --colors-teal-800: #115e59;\n --colors-teal-900: #134e4a;\n --colors-teal-950: #042f2e;\n --colors-emerald-50: #ecfdf5;\n --colors-emerald-100: #d1fae5;\n --colors-emerald-200: #a7f3d0;\n --colors-emerald-300: #6ee7b7;\n --colors-emerald-400: #34d399;\n --colors-emerald-500: #10b981;\n --colors-emerald-600: #059669;\n --colors-emerald-700: #047857;\n --colors-emerald-800: #065f46;\n --colors-emerald-900: #064e3b;\n --colors-emerald-950: #022c22;\n --colors-green-50: #f0fdf4;\n --colors-green-100: #dcfce7;\n --colors-green-200: #bbf7d0;\n --colors-green-300: #86efac;\n --colors-green-400: #4ade80;\n --colors-green-500: #22c55e;\n --colors-green-600: #16a34a;\n --colors-green-700: #15803d;\n --colors-green-800: #166534;\n --colors-green-900: #14532d;\n --colors-green-950: #052e16;\n --colors-lime-50: #f7fee7;\n --colors-lime-100: #ecfccb;\n --colors-lime-200: #d9f99d;\n --colors-lime-300: #bef264;\n --colors-lime-400: #a3e635;\n --colors-lime-500: #84cc16;\n --colors-lime-600: #65a30d;\n --colors-lime-700: #4d7c0f;\n --colors-lime-800: #3f6212;\n --colors-lime-900: #365314;\n --colors-lime-950: #1a2e05;\n --colors-yellow-50: #fefce8;\n --colors-yellow-100: #fef9c3;\n --colors-yellow-200: #fef08a;\n --colors-yellow-300: #fde047;\n --colors-yellow-400: #facc15;\n --colors-yellow-500: #eab308;\n --colors-yellow-600: #ca8a04;\n --colors-yellow-700: #a16207;\n --colors-yellow-800: #854d0e;\n --colors-yellow-900: #713f12;\n --colors-yellow-950: #422006;\n --colors-amber-50: #fffbeb;\n --colors-amber-100: #fef3c7;\n --colors-amber-200: #fde68a;\n --colors-amber-300: #fcd34d;\n --colors-amber-400: #fbbf24;\n --colors-amber-500: #f59e0b;\n --colors-amber-600: #d97706;\n --colors-amber-700: #b45309;\n --colors-amber-800: #92400e;\n --colors-amber-900: #78350f;\n --colors-amber-950: #451a03;\n --colors-orange-50: #fff7ed;\n --colors-orange-100: #ffedd5;\n --colors-orange-200: #fed7aa;\n --colors-orange-300: #fdba74;\n --colors-orange-400: #fb923c;\n --colors-orange-500: #f97316;\n --colors-orange-600: #ea580c;\n --colors-orange-700: #c2410c;\n --colors-orange-800: #9a3412;\n --colors-orange-900: #7c2d12;\n --colors-orange-950: #431407;\n --colors-red-50: #fef2f2;\n --colors-red-100: #fee2e2;\n --colors-red-200: #fecaca;\n --colors-red-300: #fca5a5;\n --colors-red-400: #f87171;\n --colors-red-500: #ef4444;\n --colors-red-600: #dc2626;\n --colors-red-700: #b91c1c;\n --colors-red-800: #991b1b;\n --colors-red-900: #7f1d1d;\n --colors-red-950: #450a0a;\n --colors-neutral-50: #fafafa;\n --colors-neutral-100: #f5f5f5;\n --colors-neutral-200: #e5e5e5;\n --colors-neutral-300: #d4d4d4;\n --colors-neutral-400: #a3a3a3;\n --colors-neutral-500: #737373;\n --colors-neutral-600: #525252;\n --colors-neutral-700: #404040;\n --colors-neutral-800: #262626;\n --colors-neutral-900: #171717;\n --colors-neutral-950: #0a0a0a;\n --colors-stone-50: #fafaf9;\n --colors-stone-100: #f5f5f4;\n --colors-stone-200: #e7e5e4;\n --colors-stone-300: #d6d3d1;\n --colors-stone-400: #a8a29e;\n --colors-stone-500: #78716c;\n --colors-stone-600: #57534e;\n --colors-stone-700: #44403c;\n --colors-stone-800: #292524;\n --colors-stone-900: #1c1917;\n --colors-stone-950: #0c0a09;\n --colors-zinc-50: #fafafa;\n --colors-zinc-100: #f4f4f5;\n --colors-zinc-200: #e4e4e7;\n --colors-zinc-300: #d4d4d8;\n --colors-zinc-400: #a1a1aa;\n --colors-zinc-500: #71717a;\n --colors-zinc-600: #52525b;\n --colors-zinc-700: #3f3f46;\n --colors-zinc-800: #27272a;\n --colors-zinc-900: #18181b;\n --colors-zinc-950: #09090b;\n --colors-gray-50: #f9fafb;\n --colors-gray-100: #f3f4f6;\n --colors-gray-200: #e5e7eb;\n --colors-gray-300: #d1d5db;\n --colors-gray-400: #9ca3af;\n --colors-gray-500: #6b7280;\n --colors-gray-600: #4b5563;\n --colors-gray-700: #374151;\n --colors-gray-800: #1f2937;\n --colors-gray-900: #111827;\n --colors-gray-950: #030712;\n --colors-slate-50: #f8fafc;\n --colors-slate-100: #f1f5f9;\n --colors-slate-200: #e2e8f0;\n --colors-slate-300: #cbd5e1;\n --colors-slate-400: #94a3b8;\n --colors-slate-500: #64748b;\n --colors-slate-600: #475569;\n --colors-slate-700: #334155;\n --colors-slate-800: #1e293b;\n --colors-slate-900: #0f172a;\n --colors-slate-950: #020617;\n --colors-hover-light-success: #ECFDF3d9;\n --colors-hover-light-warning: #FFFAEBd9;\n --colors-hover-light-error: #FEF3F2d9;\n --colors-hover-light-active: #DCEFFCd9;\n --colors-hover-light-gray: #F2F4F7d9;\n --colors-hover-dark-success: #12B76Ad9;\n --colors-hover-dark-warning: #DC6803d9;\n --colors-hover-dark-error: #F04438d9;\n --colors-hover-dark-active: #4c4ff1d9;\n --colors-hover-dark-gray: #667085d9;\n --colors-light-success: #ECFDF3;\n --colors-light-warning: #FFFAEB;\n --colors-light-error: #FEF3F2;\n --colors-light-active: #DCEFFC;\n --colors-light-gray: #F2F4F7;\n --colors-dark-success: #12B76A;\n --colors-dark-warning: #DC6803;\n --colors-dark-error: #F04438;\n --colors-dark-active: #4c4ff1;\n --colors-dark-gray: #667085;\n --colors-text-normal: #1D2939;\n --colors-text-label: #475467;\n --colors-text-light: #667085;\n --colors-text-success: #027A48;\n --colors-text-warning: #B54708;\n --colors-text-error: #B42318;\n --colors-text-active: #5724e8;\n --colors-text-gray: #344054;\n --colors-decoration-success: #6CE9A6;\n --colors-decoration-warning: #FEC84B;\n --colors-decoration-error: #FDA29B;\n --colors-decoration-active: #8da4f4;\n --colors-decoration-gray: #D0D5DD;\n --colors-grayscale-0: var(--colors-white);\n --colors-grayscale-50: var(--colors-zinc-50);\n --colors-grayscale-100: var(--colors-zinc-100);\n --colors-grayscale-200: var(--colors-zinc-200);\n --colors-grayscale-300: var(--colors-zinc-300);\n --colors-grayscale-400: var(--colors-zinc-400);\n --colors-grayscale-500: var(--colors-zinc-500);\n --colors-grayscale-600: var(--colors-zinc-600);\n --colors-grayscale-700: var(--colors-zinc-700);\n --colors-grayscale-800: var(--colors-zinc-800);\n --colors-grayscale-900: var(--colors-zinc-900);\n --colors-grayscale-950: var(--colors-zinc-950);\n --fonts-serif: ui-serif, Georgia, Cambria, \"Times New Roman\", Times, serif;\n --fonts-body: Inter;\n --fonts-mono: JetBrainsMono;\n --fonts-sans: var(--font-inter, Inter), ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, \"Noto Sans\", sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --line-heights-3: .75rem;\n --line-heights-4: 1rem;\n --line-heights-5: 1.25rem;\n --line-heights-6: 1.5rem;\n --line-heights-7: 1.75rem;\n --line-heights-8: 2rem;\n --line-heights-9: 2.25rem;\n --line-heights-10: 2.5rem;\n --line-heights-sm: 20px;\n --line-heights-primary: 24px;\n --line-heights-md: 32px;\n --line-heights-lg: 38px;\n --line-heights-none: 1;\n --line-heights-tight: 1.25;\n --line-heights-snug: 1.375;\n --line-heights-normal: 1.5;\n --line-heights-relaxed: 1.625;\n --line-heights-loose: 2;\n --radii-xs: 0.125rem;\n --radii-sm: calc(var(--radii-radius) - 4px);\n --radii-md: calc(var(--radii-radius) - 2px);\n --radii-lg: var(--radii-radius);\n --radii-xl: calc(var(--radii-radius) + 4px);\n --radii-2xl: 1rem;\n --radii-3xl: 1.5rem;\n --radii-full: 9999px;\n --radii-common: 6px;\n --radii-radius: 0.5rem;\n --breakpoints-2lg: 1100px;\n --breakpoints-sm: 640px;\n --breakpoints-md: 768px;\n --breakpoints-lg: 1024px;\n --breakpoints-xl: 1280px;\n --breakpoints-2xl: 1536px;\n --sizes-icon-primary: var(--sizes-icon-xs);\n --colors-background: var(--colors-grayscale-0);\n --colors-foreground: var(--colors-grayscale-950);\n --colors-muted: var(--colors-grayscale-100);\n --colors-muted-foreground: var(--colors-grayscale-500);\n --colors-card: var(--colors-grayscale-0);\n --colors-card-foreground: var(--colors-grayscale-950);\n --colors-popover: var(--colors-grayscale-0);\n --colors-popover-foreground: var(--colors-grayscale-950);\n --colors-border: var(--colors-grayscale-200);\n --colors-input: var(--colors-grayscale-200);\n --colors-primary: var(--colors-grayscale-900);\n --colors-primary-foreground: var(--colors-grayscale-50);\n --colors-secondary: var(--colors-grayscale-100);\n --colors-secondary-foreground: var(--colors-grayscale-900);\n --colors-accent: var(--colors-grayscale-100);\n --colors-accent-foreground: var(--colors-grayscale-900);\n --colors-destructive: var(--colors-red-500);\n --colors-destructive-foreground: var(--colors-grayscale-50);\n --colors-ring: var(--colors-grayscale-400);\n --borders-base: 1px solid var(--colors-border);\n --borders-input: 1px solid var(--colors-input);\n --borders-primary: 1px solid var(--colors-primary);\n --borders-destructive: 1px solid var(--colors-destructive);\n --animations-accordion-down: accordion-down 0.2s ease-out;\n --animations-accordion-up: accordion-up 0.2s ease-out\n}\n\n .dark {\n --colors-background: var(--colors-grayscale-950);\n --colors-foreground: var(--colors-grayscale-50);\n --colors-muted: var(--colors-grayscale-800);\n --colors-muted-foreground: var(--colors-grayscale-400);\n --colors-card: var(--colors-grayscale-950);\n --colors-card-foreground: var(--colors-grayscale-50);\n --colors-popover: var(--colors-grayscale-950);\n --colors-popover-foreground: var(--colors-grayscale-50);\n --colors-border: var(--colors-grayscale-800);\n --colors-input: var(--colors-grayscale-800);\n --colors-primary: var(--colors-grayscale-50);\n --colors-primary-foreground: var(--colors-grayscale-900);\n --colors-secondary: var(--colors-grayscale-800);\n --colors-secondary-foreground: var(--colors-grayscale-50);\n --colors-accent: var(--colors-grayscale-800);\n --colors-accent-foreground: var(--colors-grayscale-50);\n --colors-destructive: var(--colors-red-700);\n --colors-destructive-foreground: var(--colors-red-50);\n --colors-ring: var(--colors-grayscale-300)\n}\n\n @keyframes spin{\n to{\n transform: rotate(360deg);\n }\n }\n\n @keyframes ping{\n 75%, 100%{\n transform: scale(2);\n opacity: 0;\n }\n }\n\n @keyframes pulse{\n 50%{\n opacity: .5;\n }\n }\n\n @keyframes bounce{\n 0%, 100%{\n transform: translateY(-25%);\n animation-timing-function: cubic-bezier(0.8,0,1,1);\n }\n\n 50%{\n transform: none;\n animation-timing-function: cubic-bezier(0,0,0.2,1);\n }\n }\n\n @keyframes enter{\n from{\n opacity: var(--shadow-panda-enter-opacity, 1);\n transform: translate3d(var(--shadow-panda-enter-translate-x, 0), var(--shadow-panda-enter-translate-y, 0), 0) scale3d(var(--shadow-panda-enter-scale, 1), var(--shadow-panda-enter-scale, 1), var(--shadow-panda-enter-scale, 1)) rotate(var(--shadow-panda-enter-rotate, 0));\n }\n }\n\n @keyframes exit{\n to{\n opacity: var(--shadow-panda-exit-opacity, 1);\n transform: translate3d(var(--shadow-panda-exit-translate-x, 0), var(--shadow-panda-exit-translate-y, 0), 0) scale3d(var(--shadow-panda-exit-scale, 1), var(--shadow-panda-exit-scale, 1), var(--shadow-panda-exit-scale, 1)) rotate(var(--shadow-panda-exit-rotate, 0));\n }\n }\n\n @keyframes accordion-down{\n from{\n height: 0;\n }\n\n to{\n height: var(--radix-accordion-content-height);\n }\n }\n\n @keyframes accordion-up{\n from{\n height: var(--radix-accordion-content-height);\n }\n\n to{\n height: 0;\n }\n }\n}\n\n@layer recipes{\n\n .button--variant_default {\n background: var(--colors-primary);\n color: var(--colors-primary-foreground);\n}\n\n .button--size_default {\n height: var(--sizes-10);\n padding-inline: var(--spacing-4);\n padding-block: var(--spacing-2)\n}\n\n .button--variant_destructive {\n background: var(--colors-destructive);\n color: var(--colors-destructive-foreground);\n}\n\n .button--variant_outline {\n border: var(--borders-input);\n background: var(--colors-background);\n}\n\n .button--variant_secondary {\n background: var(--colors-secondary);\n color: var(--colors-secondary-foreground);\n}\n\n .button--variant_link {\n color: var(--colors-primary);\n text-underline-offset: 4px;\n}\n\n .button--size_sm {\n height: var(--sizes-9);\n border-radius: var(--radii-md);\n padding-inline: var(--spacing-3)\n}\n\n .button--size_lg {\n height: var(--sizes-11);\n border-radius: var(--radii-md);\n padding-inline: var(--spacing-8)\n}\n\n .button--size_icon {\n height: var(--sizes-10);\n width: var(--sizes-10)\n}\n\n .icon--size_md {\n height: var(--sizes-4);\n width: var(--sizes-4)\n}\n\n .icon--size_xs {\n height: var(--sizes-2);\n width: var(--sizes-2)\n}\n\n .icon--size_sm {\n height: var(--sizes-3);\n width: var(--sizes-3)\n}\n\n .badge--variant_default {\n border-color: var(--colors-transparent);\n background: var(--colors-primary);\n color: var(--colors-primary-foreground);\n}\n\n .separator--orientation_vertical {\n height: var(--sizes-full);\n width: 1px\n}\n\n .separator--orientation_horizontal {\n height: 1px;\n width: var(--sizes-full)\n}\n\n .button--variant_default:is(:hover, [data-hover]) {\n --sp-bga: color-mix(in srgb, transparent NaN, var(--colors-primary));\n background-color: var(--sp-bga, var(--colors-primary));\n}\n\n .button--variant_destructive:is(:hover, [data-hover]) {\n --sp-bga: color-mix(in srgb, transparent NaN, var(--colors-destructive));\n background-color: var(--sp-bga, var(--colors-destructive));\n}\n\n .button--variant_outline:is(:hover, [data-hover]) {\n background: var(--colors-accent);\n color: var(--colors-accent-foreground);\n}\n\n .button--variant_secondary:is(:hover, [data-hover]) {\n --sp-bga: color-mix(in srgb, transparent NaN, var(--colors-secondary));\n background-color: var(--sp-bga, var(--colors-secondary));\n}\n\n .button--variant_ghost:is(:hover, [data-hover]) {\n background: var(--colors-accent);\n color: var(--colors-accent-foreground)\n}\n\n .button--variant_link:is(:hover, [data-hover]) {\n text-decoration: underline;\n}\n\n .badge--variant_default:is(:hover, [data-hover]) {\n --sp-bga: color-mix(in srgb, transparent 20%, var(--colors-primary));\n background-color: var(--sp-bga, var(--colors-primary));\n}\n\n @layer _base{\n\n .button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n border-radius: var(--radii-md);\n font-size: 0.875rem;\n line-height: 1.25rem;\n font-weight: var(--font-weights-medium);\n transition-property: var(--transition-prop, color, background-color, border-color, outline-color, text-decoration-color, fill, stroke);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n cursor: pointer;\n --shadow-panda-ring-offset-color: var(--colors-background);\n gap: var(--spacing-2);\n}\n\n .button:is(:disabled, [disabled], [data-disabled]) {\n pointer-events: none;\n opacity: 50%;\n}\n\n .badge {\n display: inline-flex;\n align-items: center;\n border-radius: var(--radii-full);\n border: var(--borders-base);\n padding-inline: var(--spacing-2\\.5);\n padding-block: var(--spacing-0\\.5);\n font-size: 0.75rem;\n line-height: 1rem;\n font-weight: var(--font-weights-semibold);\n transition-property: var(--transition-prop, color, background-color, border-color, outline-color, text-decoration-color, fill, stroke);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n --shadow-panda-ring-offset-color: var(--colors-background);\n}\n\n .label {\n font-size: 0.875rem;\n line-height: var(--line-heights-none);\n font-weight: var(--font-weights-medium);\n}\n\n .peer:is(:disabled, [disabled], [data-disabled]) ~ .label {\n cursor: not-allowed;\n opacity: 0.7;\n}\n\n .separator {\n flex-shrink: 0;\n background: var(--colors-border)\n}\n\n .tableRow {\n border-bottom: var(--borders-base);\n transition-property: var(--transition-prop, color, background-color, border-color, outline-color, text-decoration-color, fill, stroke);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n}\n\n .tableRow[data-state=selected] {\n --sp-bga: color-mix(in srgb, transparent 0%, var(--colors-muted));\n background-color: var(--sp-bga, var(--colors-muted));\n}\n\n .tableCell {\n padding: var(--spacing-4);\n vertical-align: middle;\n}\n\n .tableCell:has([role=checkbox]) {\n padding-right: var(--spacing-0);\n}\n\n .card {\n border-radius: var(--radii-lg);\n border: var(--borders-base);\n background: var(--colors-card);\n color: var(--colors-card-foreground);\n box-shadow: var(--shadows-sm)\n}\n\n .table {\n width: var(--sizes-full);\n caption-side: bottom;\n font-size: 0.875rem;\n line-height: 1.25rem\n}\n\n .tableBody tr:last-child {\n border-bottom: transparent\n}\n\n .formItem {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-2)\n}\n\n .formDescription {\n color: var(--colors-muted-foreground)\n}\n\n .formDescription,.formMessage {\n font-size: 0.875rem;\n line-height: 1.25rem\n}\n\n .formMessage {\n font-weight: var(--font-weights-medium);\n color: var(--colors-destructive)\n}\n\n .input {\n display: flex;\n height: var(--sizes-10);\n width: var(--sizes-full);\n border-radius: var(--radii-md);\n border: var(--borders-input);\n background: var(--colors-background);\n padding-inline: var(--spacing-3);\n padding-block: var(--spacing-2);\n font-size: 0.875rem;\n line-height: 1.25rem;\n --shadow-panda-ring-offset-color: var(--colors-background);\n}\n\n .input::file-selector-button {\n border: var(--borders-none);\n background: var(--colors-transparent);\n font-size: 0.875rem;\n line-height: 1.25rem;\n font-weight: var(--font-weights-medium);\n}\n\n .input::placeholder, .input[data-placeholder] {\n color: var(--colors-muted-foreground);\n}\n\n .input:is(:disabled, [disabled], [data-disabled]) {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n .tableContainer {\n width: var(--sizes-full);\n overflow: auto\n}\n\n .toastViewport {\n position: fixed;\n top: var(--spacing-0);\n z-index: 100;\n display: flex;\n max-height: 100vh;\n width: var(--sizes-full);\n flex-direction: column-reverse;\n padding: var(--spacing-4);\n}\n\n .skeleton {\n animation: var(--animations-pulse);\n border-radius: var(--radii-md);\n background: var(--colors-muted)\n}\n\n .button:is(:focus-visible, [data-focus-visible]) {\n outline: 2px solid transparent;\n outline-offset: 2px;\n --shadow-panda-ring-offset-shadow: var(--shadow-panda-ring-inset,) 0 0 0 var(--shadow-panda-ring-offset-width, 0px) var(--shadow-panda-ring-offset-color);\n --shadow-panda-ring-shadow: var(--shadow-panda-ring-inset,) 0 0 0 calc(2px + var(--shadow-panda-ring-offset-width, 0px)) var(--shadow-panda-ring-color);\n box-shadow: var(--shadow-panda-ring-offset-shadow),var(--shadow-panda-ring-shadow),var(--shadow-panda-base-shadow,0 0 #0000);\n --shadow-panda-ring-color: var(--colors-ring);\n --shadow-panda-ring-offset-width: 2px;\n}\n\n .badge:is(:focus, [data-focus]) {\n outline: 2px solid transparent;\n outline-offset: 2px;\n --shadow-panda-ring-offset-shadow: var(--shadow-panda-ring-inset,) 0 0 0 var(--shadow-panda-ring-offset-width, 0px) var(--shadow-panda-ring-offset-color);\n --shadow-panda-ring-shadow: var(--shadow-panda-ring-inset,) 0 0 0 calc(2px + var(--shadow-panda-ring-offset-width, 0px)) var(--shadow-panda-ring-color);\n box-shadow: var(--shadow-panda-ring-offset-shadow),var(--shadow-panda-ring-shadow),var(--shadow-panda-base-shadow,0 0 #0000);\n --shadow-panda-ring-color: var(--colors-ring);\n --shadow-panda-ring-offset-width: 2px;\n}\n\n .input:is(:focus-visible, [data-focus-visible]) {\n outline: 2px solid transparent;\n outline-offset: 2px;\n --shadow-panda-ring-offset-shadow: var(--shadow-panda-ring-inset,) 0 0 0 var(--shadow-panda-ring-offset-width, 0px) var(--shadow-panda-ring-offset-color);\n --shadow-panda-ring-shadow: var(--shadow-panda-ring-inset,) 0 0 0 calc(2px + var(--shadow-panda-ring-offset-width, 0px)) var(--shadow-panda-ring-color);\n box-shadow: var(--shadow-panda-ring-offset-shadow),var(--shadow-panda-ring-shadow),var(--shadow-panda-base-shadow,0 0 #0000);\n --shadow-panda-ring-color: var(--colors-ring);\n --shadow-panda-ring-offset-width: 2px;\n}\n\n .tableRow:is(:hover, [data-hover]) {\n --sp-bga: color-mix(in srgb, transparent 50%, var(--colors-muted));\n background-color: var(--sp-bga, var(--colors-muted));\n}\n\n @media screen and (min-width: 40em) {\n .toastViewport {\n bottom: var(--spacing-0);\n right: var(--spacing-0);\n top: auto;\n flex-direction: column;\n }\n}\n\n @media screen and (min-width: 48em) {\n .toastViewport {\n max-width: 420px;\n }\n}\n }\n}\n\n@layer recipes.slots{\n\n .toast__root--variant_default {\n border: var(--borders-base);\n background: var(--colors-background)\n}\n\n .toast__root--variant_destructive {\n border: var(--borders-destructive);\n background: var(--colors-destructive);\n color: var(--colors-destructive-foreground)\n}\n\n .toast__action--variant_destructive {\n --sp-bca: color-mix(in srgb, transparent 60%, var(--colors-muted));\n border-color: var(--sp-bca, var(--colors-muted));\n}\n\n .toast__close--variant_destructive {\n color: var(--colors-red-300);\n}\n\n .toast__action--variant_destructive:is(:focus, [data-focus]) {\n --shadow-panda-ring-color: var(--colors-destructive)\n ;\n}\n\n .toast__close--variant_destructive:is(:focus, [data-focus]) {\n --shadow-panda-ring-color: var(--colors-red-400)\n ;\n --shadow-panda-ring-offset-color: var(--colors-red-600)\n ;\n}\n\n .toast__action--variant_destructive:is(:hover, [data-hover]) {\n --sp-bca: color-mix(in srgb, transparent 70%, var(--colors-destructive));\n border-color: var(--sp-bca, var(--colors-destructive));\n background: var(--colors-destructive);\n color: var(--colors-destructive-foreground);\n}\n\n .toast__close--variant_destructive:is(:hover, [data-hover]) {\n color: var(--colors-red-50);\n}\n\n @layer _base{\n\n .toast__root {\n pointer-events: auto;\n position: relative;\n display: flex;\n width: var(--sizes-full);\n align-items: center;\n justify-content: space-between;\n gap: var(--spacing-4);\n overflow: hidden;\n border-radius: var(--radii-md);\n border: var(--borders-base);\n padding: var(--spacing-6);\n padding-right: var(--spacing-8);\n box-shadow: var(--shadows-lg);\n transition-property: var(--transition-prop, all);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n}\n\n .toast__root[data-swipe=cancel] {\n transform: translateX(0);\n}\n\n .toast__root[data-swipe=end] {\n transform: translateX(var(--radix-toast-swipe-end-x));\n animation-name: exit;\n animation-duration: var(--durations-fast);\n --shadow-panda-exit-opacity: 1;\n --shadow-panda-exit-scale: 1;\n --shadow-panda-exit-rotate: 0;\n --shadow-panda-exit-translate-x: 0;\n --shadow-panda-exit-translate-y: 0;\n}\n\n .toast__root[data-swipe=move] {\n transform: translateX(var(--radix-toast-swipe-move-x));\n transition: none;\n}\n\n .toast__root[data-state=open] {\n animation-name: enter;\n animation-duration: var(--durations-fast);\n --shadow-panda-enter-opacity: 1;\n --shadow-panda-enter-scale: 1;\n --shadow-panda-enter-rotate: 0;\n --shadow-panda-enter-translate-x: 0;\n --shadow-panda-enter-translate-y: calc(100% * -1);\n}\n\n .toast__root[data-state=closed] {\n animation-name: exit;\n animation-duration: var(--durations-fast);\n --shadow-panda-exit-opacity: 0.8;\n --shadow-panda-exit-scale: 1;\n --shadow-panda-exit-rotate: 0;\n --shadow-panda-exit-translate-x: 100%;\n --shadow-panda-exit-translate-y: 0;\n}\n\n .toast__action {\n display: inline-flex;\n height: var(--sizes-8);\n flex-shrink: 0;\n align-items: center;\n justify-content: center;\n border-radius: var(--radii-md);\n border: var(--borders-base);\n background: var(--colors-transparent);\n padding-inline: var(--spacing-3);\n font-size: 0.875rem;\n line-height: 1.25rem;\n font-weight: var(--font-weights-medium);\n --shadow-panda-ring-offset-color: var(--colors-background);\n transition-property: var(--transition-prop, color, background-color, border-color, outline-color, text-decoration-color, fill, stroke);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n cursor: pointer;\n}\n\n .toast__action:is(:disabled, [disabled], [data-disabled]) {\n pointer-events: none;\n opacity: 0.5;\n}\n\n .toast__close {\n position: absolute;\n right: var(--spacing-2);\n top: var(--spacing-2);\n border-radius: var(--radii-md);\n padding: var(--spacing-1);\n --sp-ca: color-mix(in srgb, transparent 50%, var(--colors-foreground));\n color: var(--sp-ca, var(--colors-foreground));\n opacity: 0;\n transition-property: var(--transition-prop, opacity);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n cursor: pointer;\n}\n\n .toast__title {\n font-weight: var(--font-weights-semibold)\n}\n\n .toast__title,.toast__description {\n font-size: 0.875rem;\n line-height: 1.25rem\n}\n\n .toast__description {\n opacity: 0.9\n}\n\n .tooltip__content {\n z-index: 50;\n overflow: hidden;\n border-radius: var(--radii-md);\n border: var(--borders-base);\n background: var(--colors-popover);\n padding-inline: var(--spacing-3);\n padding-block: var(--spacing-1\\.5);\n font-size: 0.875rem;\n line-height: 1.25rem;\n color: var(--colors-popover-foreground);\n box-shadow: var(--shadows-md);\n animation-name: enter;\n animation-duration: var(--durations-fast);\n --shadow-panda-enter-opacity: 0;\n --shadow-panda-enter-scale: 0.95;\n --shadow-panda-enter-rotate: 0;\n --shadow-panda-enter-translate-x: 0;\n --shadow-panda-enter-translate-y: 0;\n}\n\n .tooltip__content[data-state=closed] {\n animation-name: exit;\n animation-duration: var(--durations-fast);\n --shadow-panda-exit-opacity: 0;\n --shadow-panda-exit-scale: 0.95;\n --shadow-panda-exit-rotate: 0;\n --shadow-panda-exit-translate-x: 0;\n --shadow-panda-exit-translate-y: 0;\n}\n\n .tooltip__content[data-side=top] {\n --shadow-panda-enter-translate-y: var(--spacing-2);\n}\n\n .tooltip__content[data-side=bottom] {\n --shadow-panda-enter-translate-y: calc(var(--spacing-2) * -1);\n}\n\n .tooltip__content[data-side=left] {\n --shadow-panda-enter-translate-x: var(--spacing-2);\n}\n\n .tooltip__content[data-side=right] {\n --shadow-panda-enter-translate-x: calc(var(--spacing-2) * -1);\n}\n\n .dropdownMenu__subTrigger {\n display: flex;\n cursor: default;\n -webkit-user-select: none;\n user-select: none;\n align-items: center;\n border-radius: var(--radii-sm);\n padding-inline: var(--spacing-2);\n padding-block: var(--spacing-1\\.5);\n font-size: 0.875rem;\n line-height: 1.25rem;\n outline: var(--borders-none);\n gap: var(--spacing-2);\n}\n\n .dropdownMenu__subTrigger[data-state=open] {\n background: var(--colors-accent);\n}\n\n .dropdownMenu__subContent {\n z-index: 50;\n min-width: 8rem;\n overflow: hidden;\n border-radius: var(--radii-md);\n border: var(--borders-base);\n background: var(--colors-popover);\n padding: var(--spacing-1);\n color: var(--colors-popover-foreground);\n box-shadow: var(--shadows-lg);\n}\n\n .dropdownMenu__subContent[data-state=open] {\n animation-name: enter;\n animation-duration: var(--durations-fast);\n --shadow-panda-enter-opacity: 0;\n --shadow-panda-enter-scale: 0.95;\n --shadow-panda-enter-rotate: 0;\n --shadow-panda-enter-translate-x: 0;\n --shadow-panda-enter-translate-y: 0;\n}\n\n .dropdownMenu__subContent[data-state=closed] {\n animation-name: exit;\n animation-duration: var(--durations-fast);\n --shadow-panda-exit-opacity: 0;\n --shadow-panda-exit-scale: 0.95;\n --shadow-panda-exit-rotate: 0;\n --shadow-panda-exit-translate-x: 0;\n --shadow-panda-exit-translate-y: 0;\n}\n\n .dropdownMenu__content {\n z-index: 50;\n min-width: 8rem;\n overflow: hidden;\n border-radius: var(--radii-md);\n border: var(--borders-base);\n background: var(--colors-popover);\n padding: var(--spacing-1);\n color: var(--colors-popover-foreground);\n box-shadow: var(--shadows-md);\n}\n\n .dropdownMenu__content[data-state=open] {\n animation-name: enter;\n animation-duration: var(--durations-fast);\n --shadow-panda-enter-opacity: 0;\n --shadow-panda-enter-scale: 0.95;\n --shadow-panda-enter-rotate: 0;\n --shadow-panda-enter-translate-x: 0;\n --shadow-panda-enter-translate-y: 0;\n}\n\n .dropdownMenu__content[data-state=closed] {\n animation-name: exit;\n animation-duration: var(--durations-fast);\n --shadow-panda-exit-opacity: 0;\n --shadow-panda-exit-scale: 0.95;\n --shadow-panda-exit-rotate: 0;\n --shadow-panda-exit-translate-x: 0;\n --shadow-panda-exit-translate-y: 0;\n}\n\n .dropdownMenu__item {\n position: relative;\n display: flex;\n cursor: default;\n -webkit-user-select: none;\n user-select: none;\n align-items: center;\n border-radius: var(--radii-sm);\n padding-inline: var(--spacing-2);\n padding-block: var(--spacing-1\\.5);\n font-size: 0.875rem;\n line-height: 1.25rem;\n outline: var(--borders-none);\n transition-property: var(--transition-prop, color, background-color, border-color, outline-color, text-decoration-color, fill, stroke);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n gap: var(--spacing-2);\n}\n\n .dropdownMenu__item[data-disabled] {\n pointer-events: none;\n opacity: 0.5;\n}\n\n .dropdownMenu__itemIndicator {\n position: absolute;\n left: var(--spacing-2);\n display: flex;\n height: var(--sizes-3\\.5);\n width: var(--sizes-3\\.5);\n align-items: center;\n justify-content: center\n}\n\n .dropdownMenu__checkboxItem {\n position: relative;\n display: flex;\n cursor: default;\n -webkit-user-select: none;\n user-select: none;\n align-items: center;\n border-radius: var(--radii-sm);\n padding-block: var(--spacing-1\\.5);\n padding-left: var(--spacing-8);\n padding-right: var(--spacing-2);\n font-size: 0.875rem;\n line-height: 1.25rem;\n outline: var(--borders-none);\n transition-property: var(--transition-prop, color, background-color, border-color, outline-color, text-decoration-color, fill, stroke);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n}\n\n .dropdownMenu__checkboxItem[data-disabled] {\n pointer-events: none;\n opacity: 0.5;\n}\n\n .dropdownMenu__radioItem {\n position: relative;\n display: flex;\n cursor: default;\n -webkit-user-select: none;\n user-select: none;\n align-items: center;\n border-radius: var(--radii-sm);\n padding-block: var(--spacing-1\\.5);\n padding-left: var(--spacing-8);\n padding-right: var(--spacing-2);\n font-size: 0.875rem;\n line-height: 1.25rem;\n outline: var(--borders-none);\n transition-property: var(--transition-prop, color, background-color, border-color, outline-color, text-decoration-color, fill, stroke);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n}\n\n .dropdownMenu__radioItem[data-disabled] {\n pointer-events: none;\n opacity: 0.5;\n}\n\n .dropdownMenu__label {\n padding-inline: var(--spacing-2);\n padding-block: var(--spacing-1\\.5);\n font-size: 0.875rem;\n line-height: 1.25rem;\n font-weight: var(--font-weights-semibold)\n}\n\n .dropdownMenu__separator {\n margin-inline: calc(var(--spacing-1) * -1);\n margin-block: var(--spacing-1);\n height: 1px;\n background: var(--colors-muted)\n}\n\n .dropdownMenu__shortcut {\n margin-left: auto;\n font-size: 0.75rem;\n line-height: 1rem;\n letter-spacing: var(--letter-spacings-widest);\n opacity: 0.6\n}\n\n .checkbox__root {\n height: var(--sizes-4);\n width: var(--sizes-4);\n flex-shrink: 0;\n border-radius: var(--radii-sm);\n border: var(--borders-primary);\n cursor: pointer;\n --shadow-panda-ring-offset-color: var(--colors-background);\n}\n\n .checkbox__root:is(:disabled, [disabled], [data-disabled]) {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n .checkbox__root[data-state=\"checked\"] {\n background: var(--colors-primary);\n color: var(--colors-primary-foreground);\n}\n\n .checkbox__indicator {\n display: flex;\n align-items: center;\n justify-content: center;\n color: currentColor\n}\n\n .accordion__item {\n border-bottom: var(--borders-base)\n}\n\n .accordion__header {\n display: flex\n}\n\n .accordion__trigger {\n display: flex;\n flex: 1 1 0%;\n align-items: center;\n justify-content: space-between;\n padding-block: var(--spacing-4);\n font-weight: var(--font-weights-medium);\n transition-property: var(--transition-prop, all);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n cursor: pointer;\n}\n\n .accordion__trigger > svg {\n height: var(--sizes-4);\n width: var(--sizes-4);\n flex-shrink: 0;\n transition-property: var(--transition-prop, transform);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--durations-normal);\n --transition-duration: var(--durations-normal);\n}\n\n .accordion__trigger[data-state=open] > svg {\n transform: rotate(180deg);\n}\n\n .accordion__content {\n overflow: hidden;\n font-size: 0.875rem;\n line-height: 1.25rem;\n transition-property: var(--transition-prop, all);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n}\n\n .accordion__content[data-state=closed] {\n animation: var(--animations-accordion-up);\n}\n\n .accordion__content[data-state=open] {\n animation: var(--animations-accordion-down);\n}\n\n .accordion__content > div {\n padding-bottom: var(--spacing-4);\n padding-top: var(--spacing-0);\n}\n\n .progress__root {\n position: relative;\n height: var(--sizes-4);\n width: var(--sizes-full);\n overflow: hidden;\n border-radius: var(--radii-full);\n background: var(--colors-secondary)\n}\n\n .progress__indicator {\n height: var(--sizes-full);\n width: var(--sizes-full);\n flex: 1 1 0%;\n background: var(--colors-primary);\n transition-property: var(--transition-prop, all);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms)\n}\n\n .dialog__overlay {\n position: fixed;\n inset: var(--spacing-0);\n z-index: 50;\n --sp-bga: color-mix(in srgb, transparent 20%, var(--colors-background));\n background-color: var(--sp-bga, var(--colors-background));\n backdrop-filter: blur(4px);\n}\n\n .dialog__overlay[data-state=open] {\n animation-name: enter;\n animation-duration: var(--durations-fast);\n --shadow-panda-enter-opacity: 0;\n --shadow-panda-enter-scale: 1;\n --shadow-panda-enter-rotate: 0;\n --shadow-panda-enter-translate-x: 0;\n --shadow-panda-enter-translate-y: 0;\n}\n\n .dialog__overlay[data-state=closed] {\n animation-name: exit;\n animation-duration: var(--durations-fast);\n --shadow-panda-exit-opacity: 0;\n --shadow-panda-exit-scale: 1;\n --shadow-panda-exit-rotate: 0;\n --shadow-panda-exit-translate-x: 0;\n --shadow-panda-exit-translate-y: 0;\n}\n\n .dialog__close {\n position: absolute;\n right: var(--spacing-4);\n top: var(--spacing-4);\n border-radius: var(--radii-sm);\n opacity: 0.7;\n --shadow-panda-ring-offset-color: var(--colors-background);\n transition-property: var(--transition-prop, opacity);\n transition-timing-function: var(--transition-easing, cubic-bezier(0.4, 0, 0.2, 1));\n transition-duration: var(--transition-duration, 150ms);\n cursor: pointer;\n}\n\n .dialog__close:is(:disabled, [disabled], [data-disabled]) {\n pointer-events: none;\n}\n\n .dialog__close {\n background: var(--colors-accent);\n color: var(--colors-muted-foreground);\n}\n\n .dialog__content {\n position: fixed;\n left: 50%;\n top: 50%;\n z-index: 50;\n display: grid;\n width: var(--sizes-full);\n max-width: var(--sizes-lg);\n transform: translate(var(--shadow-panda-translate-x, 0), var(--shadow-panda-translate-y, 0)) rotate(var(--shadow-panda-rotate, 0)) skewX(var(--shadow-panda-skew-x, 0)) skewY(var(--shadow-panda-skew-y, 0)) scaleX(var(--shadow-panda-scale-x, 1)) scaleY(var(--shadow-panda-scale-y, 1));\n --shadow-panda-translate-x: -50%;\n --shadow-panda-translate-y: -50%;\n --transition-duration: var(--durations-normal);\n transition-duration: var(--durations-normal);\n gap: var(--spacing-4);\n border: var(--borders-base);\n background: var(--colors-background);\n padding: var(--spacing-6);\n box-shadow: var(--shadows-lg);\n}\n\n .dialog__content[data-state=open] {\n animation-name: enter;\n animation-duration: var(--durations-fast);\n --shadow-panda-enter-opacity: 0;\n --shadow-panda-enter-scale: 0.95;\n --shadow-panda-enter-rotate: 0;\n --shadow-panda-enter-translate-x: calc(50% * -1);\n --shadow-panda-enter-translate-y: calc(48% * -1);\n}\n\n .dialog__content[data-state=closed] {\n animation-name: exit;\n animation-duration: var(--durations-fast);\n --shadow-panda-exit-opacity: 0;\n --shadow-panda-exit-scale: 0.95;\n --shadow-panda-exit-rotate: 0;\n --shadow-panda-exit-translate-x: calc(50% * -1);\n --shadow-panda-exit-translate-y: calc(48% * -1);\n}\n\n .dialog__header {\n display: flex;\n flex-direction: column;\n}\n\n .dialog__header > * + * {\n margin-top: var(--spacing-1\\.5);\n}\n\n .dialog__header {\n text-align: center;\n}\n\n .dialog__footer {\n display: flex;\n flex-direction: column-reverse;\n}\n\n .dialog__title {\n font-size: 1.125rem;\n line-height: var(--line-heights-none);\n font-weight: var(--font-weights-semibold);\n letter-spacing: var(--letter-spacings-tight)\n}\n\n .dialog__description {\n font-size: 0.875rem;\n line-height: 1.25rem;\n color: var(--colors-muted-foreground)\n}\n\n .command__root {\n display: flex;\n height: var(--sizes-full);\n width: var(--sizes-full);\n flex-direction: column;\n overflow: hidden;\n border-radius: var(--radii-md);\n background: var(--colors-popover);\n color: var(--colors-popover-foreground)\n}\n\n .command__inputWrapper {\n display: flex;\n align-items: center;\n border-bottom: var(--borders-base);\n padding-inline: var(--spacing-3)\n}\n\n .command__inputSearch {\n margin-right: var(--spacing-2);\n height: var(--sizes-4);\n width: var(--sizes-4);\n flex-shrink: 0;\n opacity: 0.5\n}\n\n .command__input {\n display: flex;\n height: var(--sizes-11);\n width: var(--sizes-full);\n border-radius: var(--radii-md);\n background: var(--colors-transparent);\n padding-block: var(--spacing-3);\n font-size: 0.875rem;\n line-height: 1.25rem;\n outline: var(--borders-none);\n box-shadow: none;\n}\n\n .command__input::placeholder, .command__input[data-placeholder] {\n color: var(--colors-muted-foreground);\n}\n\n .command__input:is(:disabled, [disabled], [data-disabled]) {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n .command__list {\n max-height: 300px;\n overflow-y: auto;\n overflow-x: hidden\n}\n\n .command__empty {\n padding-block: var(--spacing-6);\n text-align: center;\n font-size: 0.875rem;\n line-height: 1.25rem\n}\n\n .command__group {\n overflow: hidden;\n padding: var(--spacing-1);\n color: var(--colors-foreground);\n}\n\n .command__group [cmdk-group-heading] {\n padding-inline: var(--spacing-2);\n padding-block: var(--spacing-1\\.5);\n font-size: 0.75rem;\n line-height: 1rem;\n font-weight: var(--font-weights-medium);\n color: var(--colors-muted-foreground);\n}\n\n .command__separator {\n margin-inline: calc(var(--spacing-1) * -1);\n height: 1px;\n background: var(--colors-border)\n}\n\n .command__item {\n position: relative;\n display: flex;\n cursor: default;\n -webkit-user-select: none;\n user-select: none;\n align-items: center;\n border-radius: var(--radii-sm);\n padding-inline: var(--spacing-2);\n padding-block: var(--spacing-1\\.5);\n font-size: 0.875rem;\n line-height: 1.25rem;\n outline: var(--borders-none);\n gap: var(--spacing-2);\n}\n\n .command__item[aria-selected=true] {\n background: var(--colors-accent);\n color: var(--colors-accent-foreground);\n}\n\n .command__item[data-disabled] {\n opacity: 0.5;\n}\n\n .command__shortcut {\n margin-left: auto;\n font-size: 0.75rem;\n line-height: 1rem;\n letter-spacing: var(--letter-spacings-widest);\n color: var(--colors-muted-foreground)\n}\n\n .toast__action:is(:focus, [data-focus]) {\n outline: 2px solid transparent;\n outline-offset: 2px;\n --shadow-panda-ring-offset-shadow: var(--shadow-panda-ring-inset,) 0 0 0 var(--shadow-panda-ring-offset-width, 0px) var(--shadow-panda-ring-offset-color);\n --shadow-panda-ring-shadow: var(--shadow-panda-ring-inset,) 0 0 0 calc(2px + var(--shadow-panda-ring-offset-width, 0px)) var(--shadow-panda-ring-color);\n box-shadow: var(--shadow-panda-ring-offset-shadow),var(--shadow-panda-ring-shadow),var(--shadow-panda-base-shadow,0 0 #0000);\n --shadow-panda-ring-color: var(--colors-ring);\n --shadow-panda-ring-offset-width: 2px;\n}\n\n .toast__close:is(:focus, [data-focus]) {\n opacity: 1;\n outline: 2px solid transparent;\n outline-offset: 2px;\n --shadow-panda-ring-offset-shadow: var(--shadow-panda-ring-inset,) 0 0 0 var(--shadow-panda-ring-offset-width, 0px) var(--shadow-panda-ring-offset-color);\n --shadow-panda-ring-shadow: var(--shadow-panda-ring-inset,) 0 0 0 calc(2px + var(--shadow-panda-ring-offset-width, 0px)) var(--shadow-panda-ring-color);\n box-shadow: var(--shadow-panda-ring-offset-shadow),var(--shadow-panda-ring-shadow),var(--shadow-panda-base-shadow,0 0 #0000);\n --shadow-panda-ring-color: var(--colors-ring);\n --shadow-panda-ring-offset-width: 2px;\n}\n\n .dropdownMenu__subTrigger:is(:focus, [data-focus]) {\n background: var(--colors-accent);\n}\n\n .dropdownMenu__item:is(:focus, [data-focus]) {\n background: var(--colors-accent);\n color: var(--colors-accent-foreground);\n}\n\n .dropdownMenu__checkboxItem:is(:focus, [data-focus]) {\n background: var(--colors-accent);\n color: var(--colors-accent-foreground);\n}\n\n .dropdownMenu__radioItem:is(:focus, [data-focus]) {\n background: var(--colors-accent);\n color: var(--colors-accent-foreground);\n}\n\n .checkbox__root:is(:focus-visible, [data-focus-visible]) {\n outline: 2px solid transparent;\n outline-offset: 2px;\n --shadow-panda-ring-offset-shadow: var(--shadow-panda-ring-inset,) 0 0 0 var(--shadow-panda-ring-offset-width, 0px) var(--shadow-panda-ring-offset-color);\n --shadow-panda-ring-shadow: var(--shadow-panda-ring-inset,) 0 0 0 calc(2px + var(--shadow-panda-ring-offset-width, 0px)) var(--shadow-panda-ring-color);\n box-shadow: var(--shadow-panda-ring-offset-shadow),var(--shadow-panda-ring-shadow),var(--shadow-panda-base-shadow,0 0 #0000);\n --shadow-panda-ring-color: var(--colors-ring);\n --shadow-panda-ring-offset-width: 2px;\n}\n\n .dialog__close:is(:focus, [data-focus]) {\n outline: 2px solid transparent;\n outline-offset: 2px;\n --shadow-panda-ring-offset-shadow: var(--shadow-panda-ring-inset,) 0 0 0 var(--shadow-panda-ring-offset-width, 0px) var(--shadow-panda-ring-offset-color);\n --shadow-panda-ring-shadow: var(--shadow-panda-ring-inset,) 0 0 0 calc(2px + var(--shadow-panda-ring-offset-width, 0px)) var(--shadow-panda-ring-color);\n box-shadow: var(--shadow-panda-ring-offset-shadow),var(--shadow-panda-ring-shadow),var(--shadow-panda-base-shadow,0 0 #0000);\n --shadow-panda-ring-color: var(--colors-ring);\n --shadow-panda-ring-offset-width: 2px;\n}\n\n .toast__action:is(:hover, [data-hover]) {\n background: var(--colors-secondary);\n}\n\n .toast__close:is(:hover, [data-hover]) {\n color: var(--colors-foreground);\n}\n\n .group:is(:hover, [data-hover]) .toast__close {\n opacity: 1;\n}\n\n .accordion__trigger:is(:hover, [data-hover]) {\n text-decoration: underline;\n}\n\n .dialog__close:is(:hover, [data-hover]) {\n opacity: 1;\n}\n\n @media screen and (min-width: 40em) {\n .toast__root[data-state=open] {\n --shadow-panda-enter-translate-y: 100%;\n }\n .dialog__content {\n border-radius: var(--radii-lg);\n }\n .dialog__header {\n text-align: left;\n }\n .dialog__footer {\n flex-direction: row;\n justify-content: flex-end;\n }\n\n .dialog__footer > * + * {\n margin-left: var(--spacing-2);\n }\n}\n }\n}\n\n@layer utilities{\n .border-w_1px {\n border-width: 1px\n}\n\n .text_black {\n color: var(--colors-black)\n}\n\n .text_text\\.active {\n color: var(--colors-text-active)\n}\n\n .text_text\\.gray {\n color: var(--colors-text-gray)\n}\n\n .text_text\\.success {\n color: var(--colors-text-success)\n}\n\n .text_text\\.warning {\n color: var(--colors-text-warning)\n}\n\n .text_text\\.error {\n color: var(--colors-text-error)\n}\n\n .text_white {\n color: var(--colors-white)\n}\n\n .border_transparent {\n border-color: var(--colors-transparent)\n}\n\n .bg_transparent {\n background-color: var(--colors-transparent)\n}\n\n .border_none {\n border: var(--borders-none)\n}\n\n .py_0 {\n padding-block: var(--spacing-0)\n}\n\n .px_0 {\n padding-inline: var(--spacing-0)\n}\n\n .border_dark\\.active {\n border-color: var(--colors-dark-active)\n}\n\n .bg_dark\\.active {\n background-color: var(--colors-dark-active)\n}\n\n .border_dark\\.gray {\n border-color: var(--colors-dark-gray)\n}\n\n .bg_dark\\.gray {\n background-color: var(--colors-dark-gray)\n}\n\n .border_dark\\.success {\n border-color: var(--colors-dark-success)\n}\n\n .bg_dark\\.success {\n background-color: var(--colors-dark-success)\n}\n\n .border_dark\\.warning {\n border-color: var(--colors-dark-warning)\n}\n\n .bg_dark\\.warning {\n background-color: var(--colors-dark-warning)\n}\n\n .border_dark\\.error {\n border-color: var(--colors-dark-error)\n}\n\n .bg_dark\\.error {\n background-color: var(--colors-dark-error)\n}\n\n .border_white {\n border-color: var(--colors-white)\n}\n\n .bg_white {\n background-color: var(--colors-white)\n}\n\n .border_light\\.active {\n border-color: var(--colors-light-active)\n}\n\n .bg_light\\.active {\n background-color: var(--colors-light-active)\n}\n\n .border_light\\.gray {\n border-color: var(--colors-light-gray)\n}\n\n .bg_light\\.gray {\n background-color: var(--colors-light-gray)\n}\n\n .border_light\\.success {\n border-color: var(--colors-light-success)\n}\n\n .bg_light\\.success {\n background-color: var(--colors-light-success)\n}\n\n .border_light\\.warning {\n border-color: var(--colors-light-warning)\n}\n\n .bg_light\\.warning {\n background-color: var(--colors-light-warning)\n}\n\n .border_light\\.error {\n border-color: var(--colors-light-error)\n}\n\n .bg_light\\.error {\n background-color: var(--colors-light-error)\n}\n\n .border_decoration\\.active {\n border-color: var(--colors-decoration-active)\n}\n\n .border_decoration\\.gray {\n border-color: var(--colors-decoration-gray)\n}\n\n .border_decoration\\.success {\n border-color: var(--colors-decoration-success)\n}\n\n .border_decoration\\.warning {\n border-color: var(--colors-decoration-warning)\n}\n\n .border_decoration\\.error {\n border-color: var(--colors-decoration-error)\n}\n\n .text_text\\.white {\n color: text.white\n}\n\n .transition-prop_background-color\\,_border-color\\,_color\\,_opacity {\n --transition-prop: background-color, border-color, color, opacity;\n transition-property: background-color, border-color, color, opacity\n}\n\n .duration_token\\(durations\\.fast\\) {\n --transition-duration: var(--durations-fast);\n transition-duration: var(--durations-fast)\n}\n\n .ease_token\\(easings\\.easeInOut\\) {\n --transition-easing: var(--easings-ease-in-out);\n transition-timing-function: var(--easings-ease-in-out)\n}\n\n .p_sm {\n padding: var(--spacing-sm)\n}\n\n .text_unset {\n color: unset\n}\n\n .d_flex {\n display: flex\n}\n\n .items_center {\n align-items: center\n}\n\n .justify_space-between {\n justify-content: space-between\n}\n\n .border-w_thin {\n border-width: thin\n}\n\n .bg_blue {\n background-color: blue\n}\n\n .border_blueviolet {\n border-color: blueviolet\n}\n\n .bg_\\#C70000 {\n background-color: #C70000\n}\n\n .border_\\#C70000 {\n border-color: #C70000\n}\n\n .bg_\\#0000A8 {\n background-color: #0000A8\n}\n\n .border_\\#0000A8 {\n border-color: #0000A8\n}\n\n .bg_\\#00c700 {\n background-color: #00c700\n}\n\n .border_\\#00c700 {\n border-color: #00c700\n}\n\n .pointer-events_visible {\n pointer-events: visible\n}\n\n .pointer-events_none {\n pointer-events: none\n}\n\n .cursor_help {\n cursor: help\n}\n\n .cursor_auto {\n cursor: auto\n}\n\n .flex_row {\n flex-direction: row\n}\n\n .flex_row-reverse {\n flex-direction: row-reverse\n}\n\n .justify_space-evenly {\n justify-content: space-evenly\n}\n\n .gap_xs {\n gap: var(--spacing-xs)\n}\n\n .white-space_nowrap {\n white-space: nowrap\n}\n\n .max-w_full {\n max-width: var(--sizes-full)\n}\n\n .text_ellipsis {\n text-overflow: ellipsis\n}\n\n .text_clip {\n text-overflow: clip\n}\n\n .overflow_hidden {\n overflow: hidden\n}\n\n .gap_smaller\\.xs {\n gap: var(--spacing-smaller-xs)\n}\n\n .py_1 {\n padding-block: var(--spacing-1)\n}\n\n .pl_1 {\n padding-left: var(--spacing-1)\n}\n\n .w_icon\\.xs {\n width: var(--sizes-icon-xs)\n}\n\n .h_icon\\.xs {\n height: var(--sizes-icon-xs)\n}\n\n .list_disc {\n list-style-type: disc\n}\n\n .list_inside {\n list-style-position: inside\n}\n\n .text_dark\\.gray {\n color: var(--colors-dark-gray)\n}\n\n .flex-wrap_nowrap {\n flex-wrap: nowrap\n}\n\n .max-w_container\\.smaller\\.xxs {\n max-width: var(--sizes-container-smaller-xxs)\n}\n\n .text_light {\n color: light\n}\n\n .rounded_common {\n border-radius: var(--radii-common)\n}\n\n .shrink_0 {\n flex-shrink: 0\n}\n\n .h_lineHeights\\.sm {\n height: lineHeights.sm\n}\n\n .h_lineHeights\\.xs {\n height: lineHeights.xs\n}\n\n .cursor_default {\n cursor: default\n}\n\n .cursor_pointer {\n cursor: pointer\n}\n\n .d_none {\n display: none\n}\n\n .pr_0 {\n padding-right: var(--spacing-0)\n}\n\n .rounded-l_0 {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0\n}\n\n .my_-xs {\n margin-block: calc(var(--spacing-xs) * -1)\n}\n\n .p_smaller\\.sm {\n padding: var(--spacing-smaller-sm)\n}\n\n .text_inherit {\n color: inherit\n}\n\n .w_auto {\n width: auto\n}\n\n .h_full {\n height: var(--sizes-full)\n}\n\n .max-h_container\\.smaller\\.xs {\n max-height: var(--sizes-container-smaller-xs)\n}\n\n .overflow-y_auto {\n overflow-y: auto\n}\n\n .w_full {\n width: var(--sizes-full)\n}\n\n .overflow_auto {\n overflow: auto\n}\n\n .gap_sm {\n gap: var(--spacing-sm)\n}\n\n .flex_column {\n flex-direction: column\n}\n\n .grow_1 {\n flex-grow: 1\n}\n\n .border-b_decoration\\.gray {\n border-bottom-color: var(--colors-decoration-gray)\n}\n\n .items_left {\n align-items: left\n}\n\n .justify_center {\n justify-content: center\n}\n\n .justify_end {\n justify-content: end\n}\n\n .flex-wrap_wrap {\n flex-wrap: wrap\n}\n\n .text_normal {\n color: normal\n}\n\n .text_left {\n text-align: left\n}\n\n .text_label {\n color: label\n}\n\n .p_0 {\n padding: var(--spacing-0)\n}\n\n .w_circle {\n width: var(--sizes-circle)\n}\n\n .h_circle {\n height: var(--sizes-circle)\n}\n\n .rounded_full {\n border-radius: var(--radii-full)\n}\n\n .grow_0 {\n flex-grow: 0\n}\n\n .text_dark\\.success {\n color: var(--colors-dark-success)\n}\n\n .text_dark\\.error {\n color: var(--colors-dark-error)\n}\n\n .text_dark\\.active {\n color: var(--colors-dark-active)\n}\n\n .text_dark\\.warning {\n color: var(--colors-dark-warning)\n}\n\n .text_dark {\n color: dark\n}\n\n .rounded_md {\n border-radius: var(--radii-md)\n}\n\n .border_border\\.base {\n border: var(--borders-border-base)\n}\n\n .h_8 {\n height: var(--sizes-8)\n}\n\n .opacity_1 {\n opacity: 1\n}\n\n .mx_xs {\n margin-inline: var(--spacing-xs)\n}\n\n .border_base {\n border: var(--borders-base)\n}\n\n .border_border\\.success {\n border: var(--borders-border-success)\n}\n\n .border_border\\.active {\n border: var(--borders-border-active)\n}\n\n .pos_relative {\n position: relative\n}\n\n .z_1 {\n z-index: 1\n}\n\n .max-w_container\\.xs {\n max-width: var(--sizes-container-xs)\n}\n\n .bg_light\\.gray {\n background: var(--colors-light-gray)\n}\n\n .py_xs {\n padding-block: var(--spacing-xs)\n}\n\n .px_sm {\n padding-inline: var(--spacing-sm)\n}\n\n .items_start {\n align-items: start\n}\n\n .gap_xxs {\n gap: var(--spacing-xxs)\n}\n\n .max-w_card\\.sm {\n max-width: var(--sizes-card-sm)\n}\n\n .flex_0_0_auto {\n flex: 0 0 auto\n}\n\n .rounded_9999px {\n border-radius: 9999px\n}\n\n .text_success {\n color: success\n}\n\n .text_gray {\n color: gray\n}\n\n .leading_sm {\n line-height: var(--line-heights-sm)\n}\n\n .columns_1 {\n columns: 1\n}\n\n .text_error {\n color: error\n}\n\n .cursor_not-allowed {\n cursor: not-allowed\n}\n\n .w_fit-content {\n width: fit-content\n}\n\n .w_container\\.smaller\\.sm {\n width: var(--sizes-container-smaller-sm)\n}\n\n .max-h_container\\.xs {\n max-height: var(--sizes-container-xs)\n}\n\n .mt_sm,.space_y_sm > * + * {\n margin-top: var(--spacing-sm)\n}\n\n .justify_flex-end {\n justify-content: flex-end\n}\n\n .my_md {\n margin-block: var(--spacing-md)\n}\n\n .w_icon\\.primary {\n width: var(--sizes-icon-primary)\n}\n\n .h_icon\\.primary {\n height: var(--sizes-icon-primary)\n}\n\n .w_icon\\.xxs {\n width: var(--sizes-icon-xxs)\n}\n\n .h_icon\\.xxs {\n height: var(--sizes-icon-xxs)\n}\n\n .w_icon\\.sm {\n width: var(--sizes-icon-sm)\n}\n\n .h_icon\\.sm {\n height: var(--sizes-icon-sm)\n}\n\n .w_icon\\.md {\n width: var(--sizes-icon-md)\n}\n\n .h_icon\\.md {\n height: var(--sizes-icon-md)\n}\n\n .w_icon\\.lg {\n width: var(--sizes-icon-lg)\n}\n\n .h_icon\\.lg {\n height: var(--sizes-icon-lg)\n}\n\n .w_icon\\.xxl {\n width: var(--sizes-icon-xxl)\n}\n\n .h_icon\\.xxl {\n height: var(--sizes-icon-xxl)\n}\n\n .w_icon\\.smaller\\.xs {\n width: var(--sizes-icon-smaller-xs)\n}\n\n .h_icon\\.smaller\\.xs {\n height: var(--sizes-icon-smaller-xs)\n}\n\n .text_dark\\.black {\n color: dark.black\n}\n\n .text_dark\\.white {\n color: dark.white\n}\n\n .cursor_inherit {\n cursor: inherit\n}\n\n .ps_3 {\n padding-inline-start: var(--spacing-3)\n}\n\n .pe_3 {\n padding-inline-end: var(--spacing-3)\n}\n\n .ps_md {\n padding-inline-start: var(--spacing-md)\n}\n\n .pe_md {\n padding-inline-end: var(--spacing-md)\n}\n\n .pos_absolute {\n position: absolute\n}\n\n .top_0 {\n top: var(--spacing-0)\n}\n\n .bottom_0 {\n bottom: var(--spacing-0)\n}\n\n .left_0 {\n left: var(--spacing-0)\n}\n\n .right_0 {\n right: var(--spacing-0)\n}\n\n .min-w_container\\.xxs {\n min-width: var(--sizes-container-xxs)\n}\n\n .\\[\\&_code\\,_\\&_code_\\*\\]\\:font_mono code, .\\[\\&_code\\,_\\&_code_\\*\\]\\:font_mono code * {\n font-family: var(--fonts-mono)\n}\n\n .h_auto {\n height: auto\n}\n\n .mb_sm {\n margin-bottom: var(--spacing-sm)\n}\n\n .font-style_italic {\n font-style: italic\n}\n\n .max-h_basic\\.almost-full {\n max-height: var(--sizes-basic-almost-full)\n}\n\n .min-h_container\\.smaller\\.xxs {\n min-height: var(--sizes-container-smaller-xxs)\n}\n\n .min-w_min-content {\n min-width: min-content\n}\n\n .max-w_basic\\.almost-full {\n max-width: var(--sizes-basic-almost-full)\n}\n\n .sr_true {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border-width: 0\n}\n\n .ring_none {\n outline: var(--borders-none)\n}\n\n .justify_start {\n justify-content: start\n}\n\n .justify_normal {\n justify-content: normal\n}\n\n .ml_-xs {\n margin-left: calc(var(--spacing-xs) * -1)\n}\n\n .mr_-xs {\n margin-right: calc(var(--spacing-xs) * -1)\n}\n\n .leading_unset {\n line-height: unset\n}\n\n .d_flex\\! {\n display: flex !important\n}\n\n .w_0 {\n width: var(--sizes-0)\n}\n\n .break_break-all {\n word-break: break-all\n}\n\n .font_mono {\n font-family: var(--fonts-mono)\n}\n\n .text_primary {\n color: var(--colors-primary)\n}\n\n .gap_0 {\n gap: var(--spacing-0)\n}\n\n .border-rw_0 {\n border-right-width: 0\n}\n\n .\\[\\&\\:first-child\\]\\:rounded-l_common:first-child {\n border-top-left-radius: var(--radii-common);\n border-bottom-left-radius: var(--radii-common)\n}\n\n .\\[\\&\\:last-child\\]\\:rounded-r_common:last-child {\n border-top-right-radius: var(--radii-common);\n border-bottom-right-radius: var(--radii-common)\n}\n\n .\\[\\&\\:last-child\\]\\:border-rw_1px:last-child {\n border-right-width: 1px\n}\n\n .\\[\\&\\:checked\\]\\:border_decoration\\.active:checked {\n border-color: var(--colors-decoration-active)\n}\n\n .\\[\\&\\:checked\\]\\:bg_light\\.active:checked {\n background-color: var(--colors-light-active)\n}\n\n .border-rw_1px {\n border-right-width: 1px\n}\n\n .\\[\\&_\\+_label\\]\\:border-lw_0 + label {\n border-left-width: 0\n}\n\n .leading_lineHeights\\.sm {\n line-height: lineHeights.sm\n}\n\n .direction_row {\n direction: row\n}\n\n .right_5 {\n right: var(--spacing-5)\n}\n\n .right_1 {\n right: var(--spacing-1)\n}\n\n .top_1 {\n top: var(--spacing-1)\n}\n\n .shrink_1 {\n flex-shrink: 1\n}\n\n .mt_xs {\n margin-top: var(--spacing-xs)\n}\n\n .rounded-r_0 {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0\n}\n\n .font_medium {\n font-weight: var(--font-weights-medium)\n}\n\n .break_break-word {\n word-break: break-word\n}\n\n .white-space_break-spaces {\n white-space: break-spaces\n}\n\n .fs_primary {\n font-size: var(--font-sizes-primary)\n}\n\n .fs_xl {\n font-size: var(--font-sizes-xl)\n}\n\n .fs_lg {\n font-size: var(--font-sizes-lg)\n}\n\n .fs_md {\n font-size: var(--font-sizes-md)\n}\n\n .fs_sm {\n font-size: var(--font-sizes-sm)\n}\n\n .fs_xs {\n font-size: var(--font-sizes-xs)\n}\n\n .fs_xxs {\n font-size: var(--font-sizes-xxs)\n}\n\n .text_text\\.normal {\n color: var(--colors-text-normal)\n}\n\n .text_text\\.label {\n color: var(--colors-text-label)\n}\n\n .text_text\\.light {\n color: var(--colors-text-light)\n}\n\n .font_primary {\n font-weight: var(--font-weights-primary)\n}\n\n .font_md {\n font-weight: var(--font-weights-md)\n}\n\n .font_lg {\n font-weight: var(--font-weights-lg)\n}\n\n .font_xl {\n font-weight: var(--font-weights-xl)\n}\n\n .font_body {\n font-family: var(--fonts-body)\n}\n\n .white-space_pre-wrap {\n white-space: pre-wrap\n}\n\n .text_center {\n text-align: center\n}\n\n .text_right {\n text-align: right\n}\n\n .border_input {\n border: var(--borders-input)\n}\n\n .p_xs {\n padding: var(--spacing-xs)\n}\n\n .cursor_text {\n cursor: text\n}\n\n .d_inline-block {\n display: inline-block\n}\n\n .leading_1 {\n line-height: 1\n}\n\n .w_300px {\n width: 300px\n}\n\n .rounded_var\\(--border-radius\\) {\n border-radius: var(--border-radius)\n}\n\n .w_100\\% {\n width: 100%\n}\n\n .ring_unset {\n outline: unset\n}\n\n .m_0_-1px_-1px_0 {\n margin: 0 -1px -1px 0\n}\n\n .bg_\\#000 {\n background-color: #000\n}\n\n .z_10 {\n z-index: 10\n}\n\n .h_100\\% {\n height: 100%\n}\n\n .pl_8 {\n padding-left: var(--spacing-8)\n}\n\n .text_destructive {\n color: var(--colors-destructive)\n}\n\n .pos_popper {\n position: popper\n}\n\n .top_100\\% {\n top: 100%\n}\n\n .left_calc\\(-1_\\*_token\\(sizes\\.slider\\.label\\)_\\/_3\\) {\n left: calc(-1 * var(--sizes-slider-label) / 3)\n}\n\n .w_slider\\.label {\n width: var(--sizes-slider-label)\n}\n\n .w_slider\\.thumb\\.sm\\! {\n width: var(--sizes-slider-thumb-sm) !important\n}\n\n .h_slider\\.thumb\\.sm\\! {\n height: var(--sizes-slider-thumb-sm) !important\n}\n\n .w_slider\\.thumb\\.lg\\! {\n width: var(--sizes-slider-thumb-lg) !important\n}\n\n .h_slider\\.thumb\\.lg\\! {\n height: var(--sizes-slider-thumb-lg) !important\n}\n\n .min-w_skeleton\\.button\\.width {\n min-width: var(--sizes-skeleton-button-width)\n}\n\n .min-h_skeleton\\.button\\.height {\n min-height: var(--sizes-skeleton-button-height)\n}\n\n .min-w_full {\n min-width: var(--sizes-full)\n}\n\n .min-h_skeleton\\.grid\\.height\\.sm {\n min-height: var(--sizes-skeleton-grid-height-sm)\n}\n\n .min-h_skeleton\\.grid\\.height\\.xs {\n min-height: var(--sizes-skeleton-grid-height-xs)\n}\n\n .min-h_skeleton\\.grid\\.height\\.md {\n min-height: var(--sizes-skeleton-grid-height-md)\n}\n\n .min-h_skeleton\\.grid\\.height\\.lg {\n min-height: var(--sizes-skeleton-grid-height-lg)\n}\n\n .min-h_skeleton\\.grid\\.height\\.xl {\n min-height: var(--sizes-skeleton-grid-height-xl)\n}\n\n .d_grid {\n display: grid\n}\n\n .grid-cols_5 {\n grid-template-columns: repeat(5, minmax(0, 1fr))\n}\n\n .gap_10px {\n gap: 10px\n}\n\n .min-w_skeleton\\.input\\.width {\n min-width: var(--sizes-skeleton-input-width)\n}\n\n .min-h_skeleton\\.input\\.height {\n min-height: var(--sizes-skeleton-input-height)\n}\n\n .min-h_skeleton\\.height {\n min-height: var(--sizes-skeleton-height)\n}\n\n .min-w_skeleton\\.textarea\\.width {\n min-width: var(--sizes-skeleton-textarea-width)\n}\n\n .min-h_skeleton\\.textarea\\.height {\n min-height: var(--sizes-skeleton-textarea-height)\n}\n\n .pos_right {\n position: right\n}\n\n .max-w_container\\.sm {\n max-width: var(--sizes-container-sm)\n}\n\n .gap_-25px {\n gap: -25px\n}\n\n .border-b_1px_solid_gray {\n border-bottom: 1px solid gray\n}\n\n .pb_3px {\n padding-bottom: 3px\n}\n\n .border-style_dotted {\n border-style: dotted\n}\n\n .my_-20px {\n margin-block: -20px\n}\n\n .font_lighter {\n font-weight: lighter\n}\n\n .font_semibold {\n font-weight: var(--font-weights-semibold)\n}\n\n .hover\\:text-decor_underline:is(:hover, [data-hover]) {\n text-decoration: underline\n}\n\n .hover\\:border_token\\(colors\\.hover\\.dark\\.active\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-dark-active)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.dark\\.active\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-dark-active)\n}\n\n .hover\\:border_token\\(colors\\.hover\\.dark\\.gray\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-dark-gray)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.dark\\.gray\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-dark-gray)\n}\n\n .hover\\:border_token\\(colors\\.hover\\.dark\\.success\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-dark-success)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.dark\\.success\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-dark-success)\n}\n\n .hover\\:border_token\\(colors\\.hover\\.dark\\.warning\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-dark-warning)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.dark\\.warning\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-dark-warning)\n}\n\n .hover\\:border_token\\(colors\\.hover\\.dark\\.error\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-dark-error)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.dark\\.error\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-dark-error)\n}\n\n .hover\\:border_token\\(colors\\.light\\.gray\\):is(:hover, [data-hover]) {\n border-color: var(--colors-light-gray)\n}\n\n .hover\\:bg_token\\(colors\\.light\\.gray\\):is(:hover, [data-hover]) {\n background-color: var(--colors-light-gray)\n}\n\n .hover\\:border_token\\(colors\\.light\\.active\\):is(:hover, [data-hover]) {\n border-color: var(--colors-light-active)\n}\n\n .hover\\:bg_token\\(colors\\.light\\.active\\):is(:hover, [data-hover]) {\n background-color: var(--colors-light-active)\n}\n\n .hover\\:border_token\\(colors\\.light\\.success\\):is(:hover, [data-hover]) {\n border-color: var(--colors-light-success)\n}\n\n .hover\\:bg_token\\(colors\\.light\\.success\\):is(:hover, [data-hover]) {\n background-color: var(--colors-light-success)\n}\n\n .hover\\:border_token\\(colors\\.light\\.warning\\):is(:hover, [data-hover]) {\n border-color: var(--colors-light-warning)\n}\n\n .hover\\:bg_token\\(colors\\.light\\.warning\\):is(:hover, [data-hover]) {\n background-color: var(--colors-light-warning)\n}\n\n .hover\\:border_token\\(colors\\.light\\.error\\):is(:hover, [data-hover]) {\n border-color: var(--colors-light-error)\n}\n\n .hover\\:bg_token\\(colors\\.light\\.error\\):is(:hover, [data-hover]) {\n background-color: var(--colors-light-error)\n}\n\n .hover\\:border_token\\(colors\\.hover\\.light\\.active\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-light-active)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.light\\.active\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-light-active)\n}\n\n .hover\\:border_token\\(colors\\.hover\\.light\\.gray\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-light-gray)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.light\\.gray\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-light-gray)\n}\n\n .hover\\:border_token\\(colors\\.hover\\.light\\.success\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-light-success)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.light\\.success\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-light-success)\n}\n\n .hover\\:border_token\\(colors\\.hover\\.light\\.warning\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-light-warning)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.light\\.warning\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-light-warning)\n}\n\n .hover\\:border_token\\(colors\\.hover\\.light\\.error\\):is(:hover, [data-hover]) {\n border-color: var(--colors-hover-light-error)\n}\n\n .hover\\:bg_token\\(colors\\.hover\\.light\\.error\\):is(:hover, [data-hover]) {\n background-color: var(--colors-hover-light-error)\n}\n\n .hover\\:bg_light\\.success:is(:hover, [data-hover]) {\n background-color: var(--colors-light-success)\n}\n\n .hover\\:bg_light\\.active:is(:hover, [data-hover]) {\n background-color: var(--colors-light-active)\n}\n\n .hover\\:bg_light\\.error:is(:hover, [data-hover]) {\n background-color: var(--colors-light-error)\n}\n\n .hover\\:bg_transparent:is(:hover, [data-hover]) {\n background-color: var(--colors-transparent)\n}\n\n .hover\\:\\[\\&_\\+_label\\]\\:border-lw_0:is(:hover, [data-hover]) + label {\n border-left-width: 0\n}\n\n .hover\\:bg_hover\\.light\\.active:is(:hover, [data-hover]) {\n background-color: var(--colors-hover-light-active)\n}\n\n .hover\\:border_decoration\\.active:is(:hover, [data-hover]) {\n border-color: var(--colors-decoration-active)\n}\n\n .hover\\:cursor_pointer:is(:hover, [data-hover]) {\n cursor: pointer\n}\n\n .\\[\\&_\\+_label\\:hover\\]\\:border-lw_0 + label:hover {\n border-left-width: 0\n}\n\n @media screen and (min-width: 40em) {\n .sm\\:d_block {\n display: block\n }\n}\n}";
162060
162377
  n$1(css$1,{});
162061
162378
 
162379
+ const refreshInterval$1 = 500;
162380
+ function createEventLoopDelaySampler() {
162381
+ const [lastKnownTime, setLastKnownTime] = React__default.useState(performance.now());
162382
+ const [delay, setDelay] = React__default.useState(0);
162383
+ React__default.useEffect(() => {
162384
+ const interval = setInterval(() => {
162385
+ const now = performance.now();
162386
+ const delay = now - lastKnownTime - refreshInterval$1;
162387
+ setLastKnownTime(now);
162388
+ setDelay(delay);
162389
+ }, refreshInterval$1);
162390
+ return () => {
162391
+ clearInterval(interval);
162392
+ };
162393
+ }, [lastKnownTime]);
162394
+ return delay;
162395
+ }
162396
+
162062
162397
  const PanelAnnotationButton = ({
162063
162398
  topic,
162064
162399
  onClick
@@ -162085,13 +162420,16 @@ const PanelToolbar = ({
162085
162420
  setDetections,
162086
162421
  disableAnnotations = false,
162087
162422
  targetFps,
162088
- triggerToast
162423
+ triggerToast,
162424
+ renderedFps,
162425
+ renderDelay
162089
162426
  }) => {
162427
+ const [metrics, setMetrics] = React__default.useState();
162090
162428
  const {
162091
162429
  detections
162092
162430
  } = useDetections();
162093
162431
  const connections = useConnections();
162094
- const [metrics, setMetrics] = React__default.useState();
162432
+ const eventLoopDelay = createEventLoopDelaySampler();
162095
162433
  React__default.useEffect(() => {
162096
162434
  const interval = setInterval(() => {
162097
162435
  setMetrics(connections[0]?.getTopicMetrics(topic));
@@ -162115,12 +162453,12 @@ const PanelToolbar = ({
162115
162453
 
162116
162454
  // TODO: show only when debug mode is ON
162117
162455
  const name = React__default.useMemo(() => {
162118
- return `${topic} ${metrics?.inputFPS && metrics.inputFPS > 0 ? `- ${metrics.postDecodeFPS}/${metrics.inputFPS} FPS` : ""}`;
162119
- }, [topic, metrics]);
162456
+ return topic;
162457
+ }, [topic]);
162120
162458
  React__default.useEffect(() => {
162121
- if (targetFps && metrics?.inputFPS && targetFps > metrics.inputFPS) {
162459
+ if (targetFps && metrics?.incomingMessagesFps && targetFps > metrics.incomingMessagesFps) {
162122
162460
  const timeout = setTimeout(() => {
162123
- if (targetFps * 0.8 > metrics.inputFPS) {
162461
+ if (targetFps * 0.8 > metrics.incomingMessagesFps) {
162124
162462
  triggerToast?.();
162125
162463
  }
162126
162464
  }, 10_000);
@@ -162129,7 +162467,7 @@ const PanelToolbar = ({
162129
162467
  };
162130
162468
  }
162131
162469
  return;
162132
- }, [targetFps, metrics?.inputFPS]);
162470
+ }, [targetFps, metrics?.incomingMessagesFps]);
162133
162471
  const makeDetection = React__default.useCallback((detection, {
162134
162472
  extra
162135
162473
  }) => (extra ? detection.extra && !detection.enabled : !detection.extra || detection.enabled) && /*#__PURE__*/React__default.createElement(PanelAnnotationButton, {
@@ -162147,11 +162485,30 @@ const PanelToolbar = ({
162147
162485
  style: {
162148
162486
  paddingLeft: 16
162149
162487
  }
162150
- }, /*#__PURE__*/React__default.createElement(Tooltip, {
162151
- content: "Post-decode FPS / Receive FPS (maximum available)"
162488
+ }, /*#__PURE__*/React__default.createElement(Flex, {
162489
+ direction: "column",
162490
+ gap: "xxs",
162491
+ align: "start",
162492
+ justify: "start",
162493
+ paddingY: "xs"
162152
162494
  }, /*#__PURE__*/React__default.createElement(SubHeader, {
162153
162495
  text: name
162154
- })), !disableAnnotations && kind === 'image' && /*#__PURE__*/React__default.createElement(DropdownMenu, {
162496
+ }), /*#__PURE__*/React__default.createElement(Flex, {
162497
+ direction: "row",
162498
+ gap: "sm",
162499
+ align: "start",
162500
+ justify: "start"
162501
+ }, /*#__PURE__*/React__default.createElement(Label$3, {
162502
+ text: `Network: ${metrics?.incomingMessagesFps ? `${metrics.incomingMessagesFps} FPS` : "-"}`
162503
+ }), /*#__PURE__*/React__default.createElement(Label$3, {
162504
+ text: `Decoding: ${metrics?.decodedMessagesFps ? `${metrics.decodedMessagesFps} FPS` : "-"}`
162505
+ }), /*#__PURE__*/React__default.createElement(Label$3, {
162506
+ text: `Rendering: ${renderedFps ? `${Math.round(renderedFps / 2)} FPS` : "-"}`
162507
+ }), /*#__PURE__*/React__default.createElement(Label$3, {
162508
+ text: `Camera: ${targetFps ? `${targetFps} FPS` : "-"}`
162509
+ }), /*#__PURE__*/React__default.createElement(Label$3, {
162510
+ text: `Frontend Delay: ${eventLoopDelay ? `${Math.ceil(eventLoopDelay)} ms` : "-"}`
162511
+ }))), !disableAnnotations && kind === "image" && /*#__PURE__*/React__default.createElement(DropdownMenu, {
162155
162512
  onOpenChange: setAnnotationsOpened
162156
162513
  }, /*#__PURE__*/React__default.createElement(DropdownMenuTrigger, {
162157
162514
  asChild: true,
@@ -162166,7 +162523,8 @@ const PanelToolbar = ({
162166
162523
  disabled: detections.length === 0,
162167
162524
  style: {
162168
162525
  borderRadius: 0,
162169
- borderTopRightRadius: 8
162526
+ borderTopRightRadius: 8,
162527
+ height: "100%"
162170
162528
  }
162171
162529
  })), /*#__PURE__*/React__default.createElement(DropdownMenuContent, null, detections.map(detection => makeDetection(detection, {
162172
162530
  extra: false
@@ -162184,7 +162542,7 @@ const PanelToolbar = ({
162184
162542
  }
162185
162543
  }, extraVisible ? "Less" : "More"), extraVisible && detections.map(detection => makeDetection(detection, {
162186
162544
  extra: true
162187
- })))), kind === 'pointCloud' && /*#__PURE__*/React__default.createElement(Tooltip, {
162545
+ })))), kind === "pointCloud" && /*#__PURE__*/React__default.createElement(Tooltip, {
162188
162546
  content: /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(Label$3, {
162189
162547
  text: "To move camera:"
162190
162548
  }), /*#__PURE__*/React__default.createElement("ul", null, /*#__PURE__*/React__default.createElement("li", null, "w - Move camera forward"), /*#__PURE__*/React__default.createElement("li", null, "a - Move camera backward"), /*#__PURE__*/React__default.createElement("li", null, "s - Move camera to the left"), /*#__PURE__*/React__default.createElement("li", null, "d - Move camera to the right"), /*#__PURE__*/React__default.createElement("li", null, "Scroll \u2013 Zoom in and out"), /*#__PURE__*/React__default.createElement("li", null, "Drag \u2013 Move camera parallel to the ground"), /*#__PURE__*/React__default.createElement("li", null, `Right-click + Drag horizontally – Rotate the camera around the world's z-axis`), /*#__PURE__*/React__default.createElement("li", null, `Right-click + Drag vertically – Pan the camera around the world's x- and y- axes`)))
@@ -162224,6 +162582,8 @@ const Panel = ({
162224
162582
  annotationTopics = [],
162225
162583
  extraAnnotationTopics = [],
162226
162584
  targetFps,
162585
+ renderedFps,
162586
+ renderDelay,
162227
162587
  triggerToast
162228
162588
  }) => {
162229
162589
  const [detections, setDetections] = React__default.useState([]);
@@ -162252,6 +162612,8 @@ const Panel = ({
162252
162612
  setDetections: setDetections,
162253
162613
  disableAnnotations: disableAnnotations,
162254
162614
  targetFps: targetFps,
162615
+ renderedFps: renderedFps,
162616
+ renderDelay: renderDelay,
162255
162617
  triggerToast: triggerToast
162256
162618
  }), /*#__PURE__*/React__default.createElement(Suspense, {
162257
162619
  fallback: /*#__PURE__*/React__default.createElement(EmptyState, null, /*#__PURE__*/React__default.createElement("div", null, "Loading..."))
@@ -162260,9 +162622,32 @@ const Panel = ({
162260
162622
  }, children))))));
162261
162623
  };
162262
162624
 
162263
- const ImagePanelComponent = /*#__PURE__*/React__default.lazy(async () => await import('./index-B3T-sU1j.js'));
162625
+ const refreshInterval = 500;
162626
+ function createRenderDelaySampler() {
162627
+ const [frameDelays, setFrameDelays] = React__default.useState([]);
162628
+ const [averageFrameDelay, setAverageFrameDelay] = React__default.useState(0);
162629
+ React__default.useEffect(() => {
162630
+ const interval = setInterval(() => {
162631
+ setAverageFrameDelay(frameDelays.reduce((a, b) => a + b, 0) / frameDelays.length);
162632
+ setFrameDelays([]);
162633
+ }, refreshInterval);
162634
+ return () => {
162635
+ clearInterval(interval);
162636
+ };
162637
+ }, [frameDelays]);
162638
+ const addFrameTime = frameTime => {
162639
+ setFrameDelays(currentFrameDelays => [...currentFrameDelays, performance.now() - frameTime]);
162640
+ };
162641
+ return {
162642
+ averageFrameDelay,
162643
+ addFrameTime
162644
+ };
162645
+ }
162646
+
162647
+ const ImagePanelComponent = /*#__PURE__*/React__default.lazy(async () => await import('./index-BWakrawk.js'));
162264
162648
  const ImagePanelBody = ({
162265
- topic
162649
+ topic,
162650
+ frameRenderedEvent
162266
162651
  }) => {
162267
162652
  const {
162268
162653
  detections
@@ -162280,14 +162665,44 @@ const ImagePanelBody = ({
162280
162665
  }
162281
162666
  }), [detections, topic]);
162282
162667
  return /*#__PURE__*/React__default.createElement(ImagePanelComponent, {
162283
- overrideConfig: defaultConfig
162668
+ overrideConfig: defaultConfig,
162669
+ frameRenderedEvent: frameRenderedEvent
162284
162670
  });
162285
162671
  };
162286
162672
  const ImagePanel = /*#__PURE__*/React__default.memo(function ImagePanel(props) {
162673
+ const renderedFpsMetricsManagerRef = React__default.useRef(null);
162674
+ const [renderedFps, setRenderedFps] = React__default.useState(undefined);
162675
+ const {
162676
+ averageFrameDelay,
162677
+ addFrameTime
162678
+ } = createRenderDelaySampler();
162679
+ React__default.useEffect(() => {
162680
+ renderedFpsMetricsManagerRef.current = new MetricsManager();
162681
+ }, []);
162682
+ React__default.useEffect(() => {
162683
+ const interval = setInterval(() => {
162684
+ if (!renderedFpsMetricsManagerRef.current) {
162685
+ console.warn('renderedFpsMetricsManagerRef is null');
162686
+ return;
162687
+ }
162688
+ setRenderedFps(renderedFpsMetricsManagerRef.current.calculate('render'));
162689
+ }, 500);
162690
+ return () => {
162691
+ clearInterval(interval);
162692
+ };
162693
+ }, [renderedFpsMetricsManagerRef]);
162694
+ const handleFrameRendered = React__default.useCallback(frameTime => {
162695
+ renderedFpsMetricsManagerRef.current?.registerEvent('render');
162696
+ addFrameTime(frameTime);
162697
+ }, [addFrameTime]);
162287
162698
  return /*#__PURE__*/React__default.createElement(Panel, _extends$3({
162288
162699
  kind: "image"
162289
- }, props), /*#__PURE__*/React__default.createElement(ImagePanelBody, {
162290
- topic: props.topic
162700
+ }, props, {
162701
+ renderedFps: renderedFps,
162702
+ renderDelay: averageFrameDelay
162703
+ }), /*#__PURE__*/React__default.createElement(ImagePanelBody, {
162704
+ topic: props.topic,
162705
+ frameRenderedEvent: handleFrameRendered
162291
162706
  }));
162292
162707
  });
162293
162708
 
@@ -162295,7 +162710,7 @@ const ImagePanel = /*#__PURE__*/React__default.memo(function ImagePanel(props) {
162295
162710
  // License, v2.0. If a copy of the MPL was not distributed with this
162296
162711
  // file, You can obtain one at http://mozilla.org/MPL/2.0/
162297
162712
 
162298
- const ThreeDeeRenderComponent = /*#__PURE__*/React__default.lazy(async () => await import('./index-DbFvmBsl.js'));
162713
+ const ThreeDeeRenderComponent = /*#__PURE__*/React__default.lazy(async () => await import('./index-CE0akFDh.js'));
162299
162714
  const PointCloudPanelBody = ({
162300
162715
  topic
162301
162716
  }) => {
@@ -162313,8 +162728,8 @@ const PointCloudPanelBody = ({
162313
162728
  distance: -2000,
162314
162729
  perspective: true,
162315
162730
  phi: 0,
162316
- target: [0, 0, 0],
162317
- targetOffset: [0, 0, 0],
162731
+ target: [-2000, 0, 0],
162732
+ targetOffset: [-500, -500, 0],
162318
162733
  targetOrientation: [0, 0, 0, 1],
162319
162734
  thetaOffset: 0,
162320
162735
  fovy: 45,