@playwright-opentelemetry/trace-viewer 0.13.6 → 0.15.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.
package/README.md CHANGED
@@ -9,7 +9,7 @@ A trace viewer designed around tests, part of [Playwright OpenTelemetry](https:/
9
9
 
10
10
  ## Overview
11
11
 
12
- The viewer reads OpenTelemetry trace data directly rather than a proprietary test-result format. The layout uses a time-aligned flame graph with a screenshot filmstrip above it, separated into three views that match how you investigate a failure:
12
+ The viewer reads OpenTelemetry trace data directly rather than a proprietary test-result format. The layout plays the test back above a time-aligned flame graph: a large screenshot of the page (or, chosen in the settings menu, a filmstrip with a row of frames per page), a control bar to step through the test or play it, and a step ruler that scrubs through the whole test and shows a screenshot filmstrip as you hover it. The flame graph below is separated into three views that match how you investigate a failure:
13
13
 
14
14
  - **Test steps** for the Playwright test, hooks, fixtures, and actions
15
15
  - **Browser spans** for navigation, routes, JavaScript, fonts, images, fetches, and other requests
@@ -25,7 +25,7 @@ To boot the trace viewer on `localhost:9294`:
25
25
  npx @playwright-opentelemetry/trace-viewer
26
26
  ```
27
27
 
28
- The viewer can load a local trace zip or a trace-specific API base URL such as `/playwright-otel-trace-viewer/v1/{traceId}`. Remote API loading fetches `{baseUrl}/traces` once for the merged OTLP export, derives test metadata from the root `playwright.test` span, then downloads `{baseUrl}/screenshots.zip` into the service worker when screenshots are needed.
28
+ The viewer can load a local trace zip or a trace-specific API base URL such as `/playwright-otel-trace-viewer/v1/{traceId}`. Remote API loading fetches `{baseUrl}/traces` once for the merged OTLP export, derives test metadata from the root `playwright.test` span, then downloads `{baseUrl}/screenshots.zip` when screenshots are needed.
29
29
 
30
30
  If the viewer URL includes `traceToken`, the token is propagated to remote Trace API requests as a query parameter:
31
31
 
@@ -39,10 +39,110 @@ The token can also be embedded in the `traceSource` URL, or in a Trace API URL e
39
39
 
40
40
  The remote API contract is:
41
41
 
42
- - `GET {baseUrl}/traces` returns `{ "resourceSpans": [...] }` or `404` when the trace does not exist
42
+ - `GET {baseUrl}/traces` returns `{ "resourceSpans": [...] }`, `404` when the trace does not exist, or `401` when the viewer isn't allowed to read it
43
43
  - `GET {baseUrl}/screenshots.zip` returns a ZIP with root `manifest.json` and `screenshots/*`, or `404` when there are no screenshots
44
44
 
45
- The service worker exposes internal per-screenshot URLs to the viewer after loading the ZIP.
45
+ A `401` can say why with a `code` in its JSON body, and the viewer then shows a page explaining the problem instead of the load form. The codes are `token_expired`, `token_invalid` and `token_missing`. With `token_expired`, add `expiredAt` as an ISO 8601 time to show when:
46
+
47
+ ```json
48
+ { "code": "token_expired", "expiredAt": "2026-11-06T11:53:00.000Z" }
49
+ ```
50
+
51
+ Any other response shows the generic error above the load form.
52
+
53
+ The service worker loads the ZIP and exposes internal per-screenshot URLs to the viewer. Where no service worker can run, the page downloads and unpacks the ZIP itself.
54
+
55
+ ## Choose which panels to show
56
+
57
+ To show only some regions of the viewer, for example when embedding it in an iframe, add a `view` query parameter with a preset:
58
+
59
+ ```text
60
+ https://trace.endform.dev/?traceSource=...&view=player
61
+ ```
62
+
63
+ | View | Panels |
64
+ | -------- | --------------------------- |
65
+ | `full` | Every panel |
66
+ | `player` | `viewer`, `ruler` |
67
+ | `spans` | Every panel except `viewer` |
68
+
69
+ For full control, list the panels yourself with a comma-separated `panels` query parameter. It overrides `view`:
70
+
71
+ ```text
72
+ https://trace.endform.dev/?traceSource=...&panels=viewer,ruler,steps
73
+ ```
74
+
75
+ | Panel | Region |
76
+ | ---------- | ------------------------------------------------------------------------------------------ |
77
+ | `header` | Top bar with the test name, status, error spans, search, viewer settings, and time readout |
78
+ | `ruler` | Step ruler: the whole test with its steps and hooks, with a screenshot filmstrip on hover |
79
+ | `viewer` | Step viewer: the big screen or filmstrip, with a bar of step, playback and page controls |
80
+ | `steps` | Test steps timeline |
81
+ | `browser` | Browser spans timeline |
82
+ | `external` | External spans timeline |
83
+ | `details` | Span details sidebar |
84
+
85
+ ## Add an action to an embedded player
86
+
87
+ When embedding the viewer in an iframe, add an `action` query parameter to put a button at the end of the player's control bar. For now the only action is `expand`:
88
+
89
+ ```text
90
+ https://trace.endform.dev/?traceSource=...&view=player&action=expand
91
+ ```
92
+
93
+ The viewer doesn't run the action itself. Clicking the button posts `{ type: "trace-viewer:action", action: "expand" }` to the embedding page, which decides what to do, for example open a modal holding the same trace in the `full` view. The button doesn't show when the viewer isn't in an iframe.
94
+
95
+ The message can be sent to any origin, so check who sent it:
96
+
97
+ ```ts
98
+ window.addEventListener("message", (event) => {
99
+ if (event.source !== iframe.contentWindow) return;
100
+ if (event.origin !== "https://trace.endform.dev") return;
101
+ if (event.data?.type !== "trace-viewer:action") return;
102
+ if (event.data.action === "expand") openExpandedTrace();
103
+ });
104
+ ```
105
+
106
+ Without `view` or `panels`, the viewer settings saved in the browser decide what is shown. With them, the URL decides instead: saved settings are ignored for that page, and changes made in the settings menu there are not saved. Unknown panel names are ignored. A `panels` list with no known names falls back to `view`, and an unknown `view` falls back to the saved settings. A listed panel is still hidden when the trace has no data for it. Sections with no data are disabled in the settings menu.
107
+
108
+ ## Compare with another trace
109
+
110
+ Add a second trace to show its screenshots beside this one's on the big screen, for example the last passing run of a test that just failed:
111
+
112
+ | Parameter | Meaning |
113
+ | --------------- | ----------------------------------------------------------------------------------------- |
114
+ | `compareSource` | The trace to compare with: a Trace API base URL or a `.zip` URL, read like `traceSource`. |
115
+ | `compareToken` | Token for a Trace API `compareSource`, sent as `traceToken` on its requests. |
116
+ | `compareLabel` | Caption over the comparison, at most 80 characters. Defaults to "Baseline". |
117
+
118
+ ```text
119
+ https://trace.endform.dev/?traceSource=https%3A%2F%2Fapi.example.com%2Fv1%2F{failingTraceId}&traceToken={tokenA}
120
+ &compareSource=https%3A%2F%2Fapi.example.com%2Fv1%2F{passingTraceId}&compareToken={tokenB}
121
+ &compareLabel=Last%20passing%20run%20on%20main&view=player
122
+ ```
123
+
124
+ Each trace gets only its own token: `traceToken` never goes to `compareSource`, nor `compareToken` to `traceSource`, so the two can live on different origins. A token embedded in `compareSource` is moved to `compareToken`. The comparison is shown on the left, this run on the right, and a button in the control bar hides it. If it can't be loaded, the trace is shown as usual with a notice in its place. Loading another trace from the viewer's form drops the comparison.
125
+
126
+ The two runs never take the same time, so the viewer works out which moment of the comparison goes with each moment of this run from the steps they share. Steps that match start and end together; between them the comparison is slowed down or sped up evenly to fit. Two steps match when they do the same thing to the same locator, even with another value, so a fill with a generated email still matches. Source lines aren't compared, since editing the test moves them. Actions and expects match even when the `test.step` blocks around them were renamed or removed. When either run failed, the comparison plays on from the start of the step that failed to its settled result of that step, and holds there. The caption says "No matching step" when the step on show has no counterpart, and "Approximate timing" when no step matched and only the whole test body is stretched to fit.
127
+
128
+ ## Embed in a sandboxed iframe
129
+
130
+ Remote API traces work inside `<iframe sandbox="allow-scripts allow-forms">`, which gives the viewer an opaque origin (`null`) and no service worker. The viewer detects this and needs no configuration, but two things have to be readable from origin `null`:
131
+
132
+ - The viewer's assets. Served with `Access-Control-Allow-Origin: *` on `/assets/*` by default on Cloudflare (through `public/_headers`) and by `npx @playwright-opentelemetry/trace-viewer`. On any other host, including a custom base path behind a proxy, add that header yourself. Without it the sandboxed page stays blank.
133
+ - The Trace API. Set [`corsOrigin: "*"`](../trace-api/README.md#configuration) and pass a `traceToken`, because a sandboxed frame can't send cookies this way. The viewer only forwards the token: [validate it in your Trace API](../trace-api/README.md#low-level-building-blocks-with-authentication), which doesn't check it for you.
134
+
135
+ Local and remote trace ZIPs still need a service worker, so they can't be loaded there.
136
+
137
+ Messages from an [action](#add-an-action-to-an-embedded-player) arrive with the origin `"null"`, so the `event.origin` check in that section rejects them. Any sandboxed page has that origin too, so don't allow `"null"` instead. Check which frame sent the message:
138
+
139
+ ```ts
140
+ window.addEventListener("message", (event) => {
141
+ if (event.source !== iframe.contentWindow) return;
142
+ if (event.data?.type !== "trace-viewer:action") return;
143
+ if (event.data.action === "expand") openExpandedTrace();
144
+ });
145
+ ```
46
146
 
47
147
  ## Deploy Your Own
48
148
 
@@ -64,7 +164,7 @@ pnpm deploy
64
164
  If you want to build with absolute paths for a specific deployment location:
65
165
 
66
166
  ```bash
67
- TRACE_VIEWER_BASE=/trace-viewer/ pnpm build
167
+ VITE_TRACE_VIEWER_BASE=/trace-viewer/ pnpm build
68
168
  ```
69
169
 
70
170
  ## Local Development
package/bin/serve.js CHANGED
@@ -2,11 +2,12 @@
2
2
 
3
3
  import { access, readFile } from "node:fs/promises";
4
4
  import { createServer } from "node:http";
5
- import { extname, join } from "node:path";
5
+ import { extname, join, sep } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
7
 
8
8
  const __dirname = fileURLToPath(new URL(".", import.meta.url));
9
9
  const DIST_DIR = join(__dirname, "..", "dist");
10
+ const ASSETS_DIR = join(DIST_DIR, "assets") + sep;
10
11
 
11
12
  const DEFAULT_PORT = 9294;
12
13
 
@@ -81,6 +82,12 @@ async function serveFile(filePath, res) {
81
82
  headers["Service-Worker-Allowed"] = "/";
82
83
  }
83
84
 
85
+ // A sandboxed iframe has an opaque origin, so even the viewer's own
86
+ // assets are cross-origin to it. Matches public/_headers.
87
+ if (filePath.startsWith(ASSETS_DIR)) {
88
+ headers["Access-Control-Allow-Origin"] = "*";
89
+ }
90
+
84
91
  res.writeHead(200, headers);
85
92
  res.end(content);
86
93
  } catch (err) {
package/dist/_headers ADDED
@@ -0,0 +1,2 @@
1
+ /assets/*
2
+ Access-Control-Allow-Origin: *
@@ -0,0 +1 @@
1
+ @font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2)format("woff2-variations");unicode-range:U+460-52F,U+1C80-1C8A,U+20B4,U+2DE0-2DFF,U+A640-A69F,U+FE2E-FE2F}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2)format("woff2-variations");unicode-range:U+301,U+400-45F,U+490-491,U+4B0-4B1,U+2116}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2)format("woff2-variations");unicode-range:U+1F??}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-greek-wght-normal-CkhJZR-_.woff2)format("woff2-variations");unicode-range:U+370-377,U+37A-37F,U+384-38A,U+38C,U+38E-3A1,U+3A3-3FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2)format("woff2-variations");unicode-range:U+102-103,U+110-111,U+128-129,U+168-169,U+1A0-1A1,U+1AF-1B0,U+300-301,U+303-304,U+308-309,U+323,U+329,U+1EA0-1EF9,U+20AB}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2)format("woff2-variations");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:Inter Variable;font-style:normal;font-display:swap;font-weight:100 900;src:url(/assets/inter-latin-wght-normal-Dx4kXJAl.woff2)format("woff2-variations");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-tracking:initial;--tw-leading:initial;--tw-font-weight:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-outline-style:solid}}}@layer theme{:root,:host{--font-sans:"Inter Variable", ui-sans-serif, system-ui, sans-serif;--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-900:oklch(41.4% .112 45.904);--color-emerald-50:oklch(97.9% .021 166.113);--color-emerald-500:oklch(69.6% .17 162.48);--color-emerald-700:oklch(50.8% .118 165.612);--color-blue-50:oklch(97% .014 254.604);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-700:oklch(48.8% .243 264.376);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-gray-950:oklch(13% .028 261.692);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--leading-snug:1.375;--radius-xs:.125rem;--radius-sm:.35rem;--radius-md:.475rem;--radius-lg:.6rem;--radius-xl:.85rem;--drop-shadow-md:0 3px 3px #0000001f;--ease-out:cubic-bezier(0, 0, .2, 1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--aspect-video:16 / 9;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-fill-playhead:var(--color-emerald-500);--color-fill-playhead-strong:oklab(41.76% -.162114 .0511766)}@supports (color:color-mix(in lab, red, red)){:root,:host{--color-fill-playhead-strong:color-mix(in oklab, var(--color-fill-playhead) 60%, black)}}:root,:host{--color-brand-yellow:oklch(87% .17 90)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{font-feature-settings:"liga" 1, "calt" 1}button:not(:disabled),[role=button]:not(:disabled){cursor:pointer}button:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);--tw-ring-color:#0307121a}@supports (color:color-mix(in lab, red, red)){button:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-gray-950) 10%, transparent)}}button:focus-visible{outline-style:var(--tw-outline-style);outline-width:1px;outline-color:#03071280}@supports (color:color-mix(in lab, red, red)){button:focus-visible{outline-color:color-mix(in oklab, var(--color-gray-950) 50%, transparent)}}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.inset-0{inset:0}.inset-x-0{inset-inline:0}.-inset-y-1{inset-block:calc(var(--spacing) * -1)}.inset-y-0{inset-block:0}.inset-y-0\.5{inset-block:calc(var(--spacing) * .5)}.inset-y-1{inset-block:var(--spacing)}.-top-2{top:calc(var(--spacing) * -2)}.top-0{top:0}.top-0\.5{top:calc(var(--spacing) * .5)}.top-1{top:var(--spacing)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing) * 2)}.top-5{top:calc(var(--spacing) * 5)}.top-6{top:calc(var(--spacing) * 6)}.top-7{top:calc(var(--spacing) * 7)}.top-8{top:calc(var(--spacing) * 8)}.top-\[5px\]{top:5px}.top-\[7px\]{top:7px}.top-full{top:100%}.right-0{right:0}.right-0\.5{right:calc(var(--spacing) * .5)}.right-1{right:var(--spacing)}.right-2{right:calc(var(--spacing) * 2)}.-bottom-2{bottom:calc(var(--spacing) * -2)}.bottom-0{bottom:0}.bottom-1{bottom:var(--spacing)}.bottom-5{bottom:calc(var(--spacing) * 5)}.bottom-full{bottom:100%}.left-0{left:0}.left-0\.5{left:calc(var(--spacing) * .5)}.left-1{left:var(--spacing)}.left-3{left:calc(var(--spacing) * 3)}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.z-\[60\]{z-index:60}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.mx-1{margin-inline:var(--spacing)}.mx-3{margin-inline:calc(var(--spacing) * 3)}.mx-auto{margin-inline:auto}.my-1{margin-block:var(--spacing)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-6{margin-top:calc(var(--spacing) * 6)}.-mr-1{margin-right:calc(var(--spacing) * -1)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-1{margin-bottom:var(--spacing)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.-ml-\[7px\]{margin-left:-7px}.-ml-px{margin-left:-1px}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.aspect-video{aspect-ratio:var(--aspect-video)}.h-1{height:var(--spacing)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-7{height:calc(var(--spacing) * 7)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-10{height:calc(var(--spacing) * 10)}.h-12{height:calc(var(--spacing) * 12)}.h-24{height:calc(var(--spacing) * 24)}.h-\[18px\]{height:18px}.h-\[52px\]{height:52px}.h-auto{height:auto}.h-full{height:100%}.h-screen{height:100vh}.max-h-16{max-height:calc(var(--spacing) * 16)}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-96{max-height:calc(var(--spacing) * 96)}.min-h-0{min-height:0}.min-h-full{min-height:100%}.min-h-screen{min-height:100vh}.w-1{width:var(--spacing)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-4\/5{width:80%}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-9{width:calc(var(--spacing) * 9)}.w-10{width:calc(var(--spacing) * 10)}.w-12{width:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.w-20{width:calc(var(--spacing) * 20)}.w-24{width:calc(var(--spacing) * 24)}.w-40{width:calc(var(--spacing) * 40)}.w-56{width:calc(var(--spacing) * 56)}.w-64{width:calc(var(--spacing) * 64)}.w-80{width:calc(var(--spacing) * 80)}.w-\[3px\]{width:3px}.w-\[min\(24rem\,calc\(100vw-1rem\)\)\]{width:min(24rem,100vw - 1rem)}.w-full{width:100%}.w-px{width:1px}.w-screen{width:100vw}.max-w-2xl{max-width:var(--container-2xl)}.max-w-\[40\%\]{max-width:40%}.max-w-\[70\%\]{max-width:70%}.max-w-\[150px\]{max-width:150px}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:0}.min-w-4{min-width:calc(var(--spacing) * 4)}.min-w-8{min-width:calc(var(--spacing) * 8)}.min-w-9{min-width:calc(var(--spacing) * 9)}.min-w-10{min-width:calc(var(--spacing) * 10)}.min-w-\[140px\]{min-width:140px}.flex-1{flex:1}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.translate-x-px{--tw-translate-x:1px;translate:var(--tw-translate-x) var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y:calc(calc(1 / 2 * 100%) * -1);translate:var(--tw-translate-x) var(--tw-translate-y)}.rotate-90{rotate:90deg}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.skeleton{animation:var(--animate-pulse);background-color:var(--color-gray-100);animation-delay:var(--skeleton-delay,0s);border-radius:.25rem}.animate-spin{animation:var(--animate-spin)}.cursor-col-resize{cursor:col-resize}.cursor-ew-resize{cursor:ew-resize}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-row-resize{cursor:row-resize}.resize{resize:both}.grid-cols-\[auto\,1fr\]{grid-template-columns:auto,1fr}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-y-1{row-gap:var(--spacing)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-\[3px\]{border-radius:3px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-xs{border-radius:var(--radius-xs)}.rounded-tr{border-top-right-radius:.25rem}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-x{border-inline-style:var(--tw-border-style);border-inline-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-amber-200{border-color:var(--color-amber-200)}.border-amber-700\/70{border-color:#b75000b3}@supports (color:color-mix(in lab, red, red)){.border-amber-700\/70{border-color:color-mix(in oklab, var(--color-amber-700) 70%, transparent)}}.border-black\/20{border-color:#0003}@supports (color:color-mix(in lab, red, red)){.border-black\/20{border-color:color-mix(in oklab, var(--color-black) 20%, transparent)}}.border-blue-200{border-color:var(--color-blue-200)}.border-blue-500{border-color:var(--color-blue-500)}.border-gray-50{border-color:var(--color-gray-50)}.border-gray-100{border-color:var(--color-gray-100)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-400\/60{border-color:#99a1af99}@supports (color:color-mix(in lab, red, red)){.border-gray-400\/60{border-color:color-mix(in oklab, var(--color-gray-400) 60%, transparent)}}.border-gray-500{border-color:var(--color-gray-500)}.border-red-100{border-color:var(--color-red-100)}.border-red-200{border-color:var(--color-red-200)}.border-red-300{border-color:var(--color-red-300)}.border-red-700\/70{border-color:#bf000fb3}@supports (color:color-mix(in lab, red, red)){.border-red-700\/70{border-color:color-mix(in oklab, var(--color-red-700) 70%, transparent)}}.border-red-900{border-color:var(--color-red-900)}.border-t-fill-playhead{border-top-color:var(--color-fill-playhead)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-amber-200\/95{background-color:#fee685f2}@supports (color:color-mix(in lab, red, red)){.bg-amber-200\/95{background-color:color-mix(in oklab, var(--color-amber-200) 95%, transparent)}}.bg-amber-500{background-color:var(--color-amber-500)}.bg-black\/25{background-color:#00000040}@supports (color:color-mix(in lab, red, red)){.bg-black\/25{background-color:color-mix(in oklab, var(--color-black) 25%, transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-brand-yellow\/40{background-color:#ffce2b66}@supports (color:color-mix(in lab, red, red)){.bg-brand-yellow\/40{background-color:color-mix(in oklab, var(--color-brand-yellow) 40%, transparent)}}.bg-emerald-50{background-color:var(--color-emerald-50)}.bg-fill-playhead{background-color:var(--color-fill-playhead)}.bg-fill-playhead-strong{background-color:var(--color-fill-playhead-strong)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-50\/90{background-color:#f9fafbe6}@supports (color:color-mix(in lab, red, red)){.bg-gray-50\/90{background-color:color-mix(in oklab, var(--color-gray-50) 90%, transparent)}}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-200{background-color:var(--color-gray-200)}.bg-gray-300{background-color:var(--color-gray-300)}.bg-gray-400{background-color:var(--color-gray-400)}.bg-gray-400\/15{background-color:#99a1af26}@supports (color:color-mix(in lab, red, red)){.bg-gray-400\/15{background-color:color-mix(in oklab, var(--color-gray-400) 15%, transparent)}}.bg-gray-500{background-color:var(--color-gray-500)}.bg-gray-700{background-color:var(--color-gray-700)}.bg-gray-800{background-color:var(--color-gray-800)}.bg-gray-900{background-color:var(--color-gray-900)}.bg-gray-900\/5{background-color:#1018280d}@supports (color:color-mix(in lab, red, red)){.bg-gray-900\/5{background-color:color-mix(in oklab, var(--color-gray-900) 5%, transparent)}}.bg-gray-900\/10{background-color:#1018281a}@supports (color:color-mix(in lab, red, red)){.bg-gray-900\/10{background-color:color-mix(in oklab, var(--color-gray-900) 10%, transparent)}}.bg-gray-900\/25{background-color:#10182840}@supports (color:color-mix(in lab, red, red)){.bg-gray-900\/25{background-color:color-mix(in oklab, var(--color-gray-900) 25%, transparent)}}.bg-gray-900\/75{background-color:#101828bf}@supports (color:color-mix(in lab, red, red)){.bg-gray-900\/75{background-color:color-mix(in oklab, var(--color-gray-900) 75%, transparent)}}.bg-gray-900\/80{background-color:#101828cc}@supports (color:color-mix(in lab, red, red)){.bg-gray-900\/80{background-color:color-mix(in oklab, var(--color-gray-900) 80%, transparent)}}.bg-gray-950{background-color:var(--color-gray-950)}.bg-red-50{background-color:var(--color-red-50)}.bg-red-200\/95{background-color:#ffcacaf2}@supports (color:color-mix(in lab, red, red)){.bg-red-200\/95{background-color:color-mix(in oklab, var(--color-red-200) 95%, transparent)}}.bg-red-900\/50{background-color:#82181a80}@supports (color:color-mix(in lab, red, red)){.bg-red-900\/50{background-color:color-mix(in oklab, var(--color-red-900) 50%, transparent)}}.bg-white{background-color:var(--color-white)}.bg-white\/75{background-color:#ffffffbf}@supports (color:color-mix(in lab, red, red)){.bg-white\/75{background-color:color-mix(in oklab, var(--color-white) 75%, transparent)}}.bg-white\/80{background-color:#fffc}@supports (color:color-mix(in lab, red, red)){.bg-white\/80{background-color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.bg-gradient-to-b{--tw-gradient-position:to bottom in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-t{--tw-gradient-position:to top in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-gray-900\/\[0\.07\]{--tw-gradient-from:#10182812}@supports (color:color-mix(in lab, red, red)){.from-gray-900\/\[0\.07\]{--tw-gradient-from:color-mix(in oklab, var(--color-gray-900) 7.0%, transparent)}}.from-gray-900\/\[0\.07\]{--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.to-transparent{--tw-gradient-to:transparent;--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position))}.bg-clip-content{background-clip:content-box}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.object-top{object-position:top}.p-1{padding:var(--spacing)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.px-1{padding-inline:var(--spacing)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-\[1\.5px\]{padding-inline:1.5px}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-\[1\.5px\]{padding-block:1.5px}.py-px{padding-block:1px}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-8{padding-top:calc(var(--spacing) * 8)}.pt-px{padding-top:1px}.pr-8{padding-right:calc(var(--spacing) * 8)}.pr-16{padding-right:calc(var(--spacing) * 16)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pl-1{padding-left:var(--spacing)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-9{padding-left:calc(var(--spacing) * 9)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.align-middle{vertical-align:middle}.eyebrow{font-family:var(--font-mono);--tw-tracking:.18em;letter-spacing:.18em;text-transform:uppercase;font-size:10px}.font-mono{font-family:var(--font-mono)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-\[13px\]{--tw-leading:13px;line-height:13px}.leading-none{--tw-leading:1;line-height:1}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.break-words{overflow-wrap:break-word}.wrap-anywhere{overflow-wrap:anywhere}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-amber-700{color:var(--color-amber-700)}.text-amber-900{color:var(--color-amber-900)}.text-blue-700{color:var(--color-blue-700)}.text-emerald-700{color:var(--color-emerald-700)}.text-gray-50{color:var(--color-gray-50)}.text-gray-100{color:var(--color-gray-100)}.text-gray-200{color:var(--color-gray-200)}.text-gray-300{color:var(--color-gray-300)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-gray-950{color:var(--color-gray-950)}.text-red-400{color:var(--color-red-400)}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-white{color:var(--color-white)}.capitalize{text-transform:capitalize}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-blue-200{--tw-ring-color:var(--color-blue-200)}.ring-brand-yellow{--tw-ring-color:var(--color-brand-yellow)}.ring-fill-playhead{--tw-ring-color:var(--color-fill-playhead)}.ring-gray-200{--tw-ring-color:var(--color-gray-200)}.ring-gray-300{--tw-ring-color:var(--color-gray-300)}.ring-gray-900{--tw-ring-color:var(--color-gray-900)}.ring-white{--tw-ring-color:var(--color-white)}.ring-white\/80{--tw-ring-color:#fffc}@supports (color:color-mix(in lab, red, red)){.ring-white\/80{--tw-ring-color:color-mix(in oklab, var(--color-white) 80%, transparent)}}.ring-offset-1{--tw-ring-offset-width:1px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.ring-offset-2{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)}.ring-offset-white{--tw-ring-offset-color:var(--color-white)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.drop-shadow-md{--tw-drop-shadow-size:drop-shadow(0 3px 3px var(--tw-drop-shadow-color,#0000001f));--tw-drop-shadow:drop-shadow(var(--drop-shadow-md));filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur-\[2px\]{--tw-backdrop-blur:blur(2px);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[filter\]{transition-property:filter;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[opacity\,visibility\]{transition-property:opacity,visibility;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-\(--label-fade-in\){--tw-duration:var(--label-fade-in);transition-duration:var(--label-fade-in)}.duration-150{--tw-duration:.15s;transition-duration:.15s}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{user-select:none}.group-data-\[labels-hidden\]\/plot\:opacity-0:is(:where(.group\/plot)[data-labels-hidden] *){opacity:0}.group-data-\[labels-hidden\]\/plot\:transition-none:is(:where(.group\/plot)[data-labels-hidden] *){transition-property:none}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:bg-fill-playhead\/90:hover{background-color:#00bb7fe6}@supports (color:color-mix(in lab, red, red)){.hover\:bg-fill-playhead\/90:hover{background-color:color-mix(in oklab, var(--color-fill-playhead) 90%, transparent)}}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-gray-400:hover{background-color:var(--color-gray-400)}.hover\:bg-gray-600:hover{background-color:var(--color-gray-600)}.hover\:bg-gray-700:hover{background-color:var(--color-gray-700)}.hover\:bg-gray-900\/90:hover{background-color:#101828e6}@supports (color:color-mix(in lab, red, red)){.hover\:bg-gray-900\/90:hover{background-color:color-mix(in oklab, var(--color-gray-900) 90%, transparent)}}.hover\:bg-red-100:hover{background-color:var(--color-red-100)}.hover\:text-gray-400:hover{color:var(--color-gray-400)}.hover\:text-gray-800:hover{color:var(--color-gray-800)}.hover\:text-gray-900:hover{color:var(--color-gray-900)}.hover\:opacity-80:hover{opacity:.8}.hover\:opacity-100:hover{opacity:1}.hover\:ring-gray-300:hover{--tw-ring-color:var(--color-gray-300)}.hover\:brightness-95:hover{--tw-brightness:brightness(95%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.hover\:brightness-110:hover{--tw-brightness:brightness(110%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}}.focus\:bg-white:focus{background-color:var(--color-white)}.focus\:ring-4:focus{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(4px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus\:ring-gray-950\/10:focus{--tw-ring-color:#0307121a}@supports (color:color-mix(in lab, red, red)){.focus\:ring-gray-950\/10:focus{--tw-ring-color:color-mix(in oklab, var(--color-gray-950) 10%, transparent)}}.focus\:outline-1:focus{outline-style:var(--tw-outline-style);outline-width:1px}.focus\:-outline-offset-1:focus{outline-offset:calc(1px * -1)}.focus\:outline-gray-950\/50:focus{outline-color:#03071280}@supports (color:color-mix(in lab, red, red)){.focus\:outline-gray-950\/50:focus{outline-color:color-mix(in oklab, var(--color-gray-950) 50%, transparent)}}@media (hover:hover){.enabled\:hover\:bg-gray-100:enabled:hover{background-color:var(--color-gray-100)}.enabled\:hover\:text-gray-900:enabled:hover{color:var(--color-gray-900)}}.disabled\:cursor-default:disabled{cursor:default}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.data-\[disabled\]\:cursor-not-allowed[data-disabled]{cursor:not-allowed}.data-\[disabled\]\:text-gray-400[data-disabled]{color:var(--color-gray-400)}.data-\[dragging\]\:border-blue-400[data-dragging]{border-color:var(--color-blue-400)}.data-\[dragging\]\:bg-blue-50[data-dragging]{background-color:var(--color-blue-50)}.data-\[highlighted\]\:bg-gray-100[data-highlighted]{background-color:var(--color-gray-100)}.data-\[highlighted\]\:bg-red-50[data-highlighted]{background-color:var(--color-red-50)}.data-\[invalid\]\:border-red-500[data-invalid]{border-color:var(--color-red-500)}.data-\[invalid\]\:bg-red-50[data-invalid]{background-color:var(--color-red-50)}}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}