hyperframes 0.6.74 → 0.6.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -50,7 +50,7 @@ var VERSION;
50
50
  var init_version = __esm({
51
51
  "src/version.ts"() {
52
52
  "use strict";
53
- VERSION = true ? "0.6.74" : "0.0.0-dev";
53
+ VERSION = true ? "0.6.75" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -62042,21 +62042,33 @@ var init_manager2 = __esm({
62042
62042
  }
62043
62043
  });
62044
62044
 
62045
- // ../engine/src/config.ts
62045
+ // ../engine/src/services/systemMemory.ts
62046
62046
  import { totalmem as totalmem2 } from "os";
62047
62047
  function getSystemTotalMb() {
62048
62048
  return Math.floor(totalmem2() / (1024 * 1024));
62049
62049
  }
62050
+ function isLowMemorySystem(totalMb = getSystemTotalMb()) {
62051
+ return totalMb <= LOW_MEMORY_TOTAL_MB_THRESHOLD;
62052
+ }
62053
+ var LOW_MEMORY_TOTAL_MB_THRESHOLD;
62054
+ var init_systemMemory = __esm({
62055
+ "../engine/src/services/systemMemory.ts"() {
62056
+ "use strict";
62057
+ LOW_MEMORY_TOTAL_MB_THRESHOLD = 8192;
62058
+ }
62059
+ });
62060
+
62061
+ // ../engine/src/config.ts
62050
62062
  function memoryAdaptiveCacheLimit() {
62051
62063
  const total = getSystemTotalMb();
62052
62064
  if (total < 4096) return 32;
62053
- if (total <= 8192) return 64;
62065
+ if (total <= LOW_MEMORY_TOTAL_MB_THRESHOLD) return 64;
62054
62066
  return DEFAULT_CONFIG2.frameDataUriCacheLimit;
62055
62067
  }
62056
62068
  function memoryAdaptiveCacheBytesMb() {
62057
62069
  const total = getSystemTotalMb();
62058
62070
  if (total < 4096) return 128;
62059
- if (total <= 8192) return 256;
62071
+ if (total <= LOW_MEMORY_TOTAL_MB_THRESHOLD) return 256;
62060
62072
  return DEFAULT_CONFIG2.frameDataUriCacheBytesLimitMb;
62061
62073
  }
62062
62074
  function resolveConfig(overrides) {
@@ -62077,6 +62089,12 @@ function resolveConfig(overrides) {
62077
62089
  if (raw === "hardware" || raw === "software" || raw === "auto") return raw;
62078
62090
  return DEFAULT_CONFIG2.browserGpuMode;
62079
62091
  };
62092
+ const resolveLowMemoryMode = () => {
62093
+ const raw = env("PRODUCER_LOW_MEMORY_MODE")?.toLowerCase();
62094
+ if (raw === "true" || raw === "on" || raw === "1") return true;
62095
+ if (raw === "false" || raw === "off" || raw === "0") return false;
62096
+ return isLowMemorySystem();
62097
+ };
62080
62098
  const fromEnv = {
62081
62099
  concurrency: env("PRODUCER_MAX_WORKERS") ? Number(env("PRODUCER_MAX_WORKERS")) : void 0,
62082
62100
  coresPerWorker: envNum("PRODUCER_CORES_PER_WORKER", DEFAULT_CONFIG2.coresPerWorker),
@@ -62096,6 +62114,7 @@ function resolveConfig(overrides) {
62096
62114
  ),
62097
62115
  expectedChromiumMajor: env("PRODUCER_EXPECTED_CHROMIUM_MAJOR") ? Number(env("PRODUCER_EXPECTED_CHROMIUM_MAJOR")) : void 0,
62098
62116
  forceScreenshot: envBool("PRODUCER_FORCE_SCREENSHOT", DEFAULT_CONFIG2.forceScreenshot),
62117
+ lowMemoryMode: resolveLowMemoryMode(),
62099
62118
  enablePageSideCompositing: envBool(
62100
62119
  "HF_PAGE_SIDE_COMPOSITING",
62101
62120
  DEFAULT_CONFIG2.enablePageSideCompositing
@@ -62167,6 +62186,7 @@ var DEFAULT_CONFIG2;
62167
62186
  var init_config2 = __esm({
62168
62187
  "../engine/src/config.ts"() {
62169
62188
  "use strict";
62189
+ init_systemMemory();
62170
62190
  DEFAULT_CONFIG2 = {
62171
62191
  fps: 30,
62172
62192
  quality: "standard",
@@ -62182,6 +62202,9 @@ var init_config2 = __esm({
62182
62202
  browserTimeout: 12e4,
62183
62203
  protocolTimeout: 3e5,
62184
62204
  forceScreenshot: false,
62205
+ // Auto-detected per host in `resolveConfig`; defaults off for the raw
62206
+ // DEFAULT_CONFIG (used directly by tests and worker-sizing fallbacks).
62207
+ lowMemoryMode: false,
62185
62208
  enablePageSideCompositing: true,
62186
62209
  enableChunkedEncode: false,
62187
62210
  chunkSizeFrames: 360,
@@ -62208,7 +62231,7 @@ var init_config2 = __esm({
62208
62231
  import { execSync as execSync4 } from "child_process";
62209
62232
  import { existsSync as existsSync19, readdirSync as readdirSync9 } from "fs";
62210
62233
  import { join as join23 } from "path";
62211
- import { homedir as homedir6, totalmem as totalmem3 } from "os";
62234
+ import { homedir as homedir6 } from "os";
62212
62235
  async function getPuppeteer() {
62213
62236
  if (_puppeteer) return _puppeteer;
62214
62237
  try {
@@ -62402,6 +62425,10 @@ async function launchBrowser(chromeArgs, config) {
62402
62425
  timeout: browserTimeout,
62403
62426
  protocolTimeout
62404
62427
  });
62428
+ const browserVersion = await browser.version().catch(() => "unknown");
62429
+ console.log(
62430
+ `[BrowserManager] Browser launched (${browserVersion}, ${captureMode}, headlessShell=${!!headlessShell}, platform=${process.platform})`
62431
+ );
62405
62432
  if (captureMode === "beginframe") {
62406
62433
  const supported = await probeBeginFrameSupport(browser).catch(() => true);
62407
62434
  if (!supported) {
@@ -62480,9 +62507,6 @@ async function drainBrowserPool() {
62480
62507
  });
62481
62508
  }
62482
62509
  }
62483
- function getTotalMemMb() {
62484
- return Math.floor(totalmem3() / (1024 * 1024));
62485
- }
62486
62510
  function probeNvidiaVramMb() {
62487
62511
  if (_cachedVramMb !== null) return _cachedVramMb;
62488
62512
  try {
@@ -62503,14 +62527,14 @@ function probeNvidiaVramMb() {
62503
62527
  function getGpuMemBudgetMb() {
62504
62528
  const vram = probeNvidiaVramMb();
62505
62529
  if (vram) return Math.min(vram, 16384);
62506
- const total = getTotalMemMb();
62530
+ const total = getSystemTotalMb();
62507
62531
  if (total < 4096) return 512;
62508
- if (total <= 8192) return 1024;
62532
+ if (total <= LOW_MEMORY_TOTAL_MB_THRESHOLD) return 1024;
62509
62533
  return Math.min(Math.floor(total / 2), 16384);
62510
62534
  }
62511
62535
  function getLowMemoryFlags() {
62512
- const total = getTotalMemMb();
62513
- if (total > 8192) return [];
62536
+ const total = getSystemTotalMb();
62537
+ if (total > LOW_MEMORY_TOTAL_MB_THRESHOLD) return [];
62514
62538
  const heapMb = total < 4096 ? 256 : 512;
62515
62539
  return [`--js-flags=--max-old-space-size=${heapMb}`];
62516
62540
  }
@@ -62606,6 +62630,7 @@ var init_browserManager = __esm({
62606
62630
  "../engine/src/services/browserManager.ts"() {
62607
62631
  "use strict";
62608
62632
  init_config2();
62633
+ init_systemMemory();
62609
62634
  pooledBrowser = null;
62610
62635
  pooledBrowserRefCount = 0;
62611
62636
  pooledCaptureMode = "screenshot";
@@ -63305,17 +63330,26 @@ async function initializeSession(session) {
63305
63330
  });
63306
63331
  const url = `${serverUrl}/index.html`;
63307
63332
  const pageNavigationTimeout = session.config?.pageNavigationTimeout ?? DEFAULT_CONFIG2.pageNavigationTimeout;
63333
+ const initStart = Date.now();
63334
+ const logInitPhase = (phase) => {
63335
+ console.log(`[initSession:${session.captureMode}] ${phase} (${Date.now() - initStart}ms)`);
63336
+ };
63308
63337
  if (session.captureMode === "screenshot") {
63309
63338
  await page.goto(url, { waitUntil: "domcontentloaded", timeout: pageNavigationTimeout });
63339
+ logInitPhase("page.goto complete");
63310
63340
  const pageReadyTimeout2 = session.config?.playerReadyTimeout ?? DEFAULT_CONFIG2.playerReadyTimeout;
63311
63341
  await pollHfReady(page, pageReadyTimeout2);
63342
+ logInitPhase("pollHfReady complete");
63312
63343
  await pollSubCompositionTimelines(page, pageReadyTimeout2);
63344
+ logInitPhase("pollSubCompositionTimelines complete");
63313
63345
  await applyVideoMetadataHints(page, session.options.videoMetadataHints);
63346
+ logInitPhase("applyVideoMetadataHints complete");
63314
63347
  const videosReady = await pollVideosReady(
63315
63348
  page,
63316
63349
  session.options.skipReadinessVideoIds ?? [],
63317
63350
  pageReadyTimeout2
63318
63351
  );
63352
+ logInitPhase("pollVideosReady complete");
63319
63353
  if (!videosReady) {
63320
63354
  const failedVideos = await page.evaluate((skipIdList) => {
63321
63355
  const skip = new Set(skipIdList);
@@ -63340,8 +63374,11 @@ async function initializeSession(session) {
63340
63374
  );
63341
63375
  }
63342
63376
  await decodeAllImages(page);
63377
+ logInitPhase("images ready + decoded");
63343
63378
  await page.evaluate(`document.fonts?.ready`);
63379
+ logInitPhase("fonts ready");
63344
63380
  await waitForOptionalTailwindReady(page, pageReadyTimeout2);
63381
+ logInitPhase("tailwind ready");
63345
63382
  if (session.options.format === "png") {
63346
63383
  await initTransparentBackground(session.page);
63347
63384
  }
@@ -63384,16 +63421,21 @@ async function initializeSession(session) {
63384
63421
  })();
63385
63422
  warmupLoopPromise.catch(() => {
63386
63423
  });
63424
+ logInitPhase("warmup loop started");
63387
63425
  await page.goto(url, { waitUntil: "domcontentloaded", timeout: pageNavigationTimeout });
63426
+ logInitPhase("page.goto complete");
63388
63427
  const pageReadyTimeout = session.config?.playerReadyTimeout ?? DEFAULT_CONFIG2.playerReadyTimeout;
63389
63428
  try {
63390
63429
  await pollHfReady(page, pageReadyTimeout);
63430
+ logInitPhase("pollHfReady complete");
63391
63431
  } catch (err) {
63392
63432
  warmupState.running = false;
63393
63433
  throw err;
63394
63434
  }
63395
63435
  await pollSubCompositionTimelines(page, pageReadyTimeout);
63436
+ logInitPhase("pollSubCompositionTimelines complete");
63396
63437
  await applyVideoMetadataHints(page, session.options.videoMetadataHints);
63438
+ logInitPhase("applyVideoMetadataHints complete");
63397
63439
  const bfVideosReady = await pollVideosReady(
63398
63440
  page,
63399
63441
  session.options.skipReadinessVideoIds ?? [],
@@ -63408,6 +63450,7 @@ async function initializeSession(session) {
63408
63450
  `[FrameCapture] Some video elements did not decode within ${pageReadyTimeout}ms: ${failedVideos}. Continuing render \u2014 affected videos will appear as blank/black frames.`
63409
63451
  );
63410
63452
  }
63453
+ logInitPhase("pollVideosReady complete");
63411
63454
  const bfImagesReady = await pollImagesReady(page, pageReadyTimeout);
63412
63455
  if (!bfImagesReady) {
63413
63456
  const failedImages = await page.evaluate(() => {
@@ -63423,8 +63466,11 @@ async function initializeSession(session) {
63423
63466
  );
63424
63467
  }
63425
63468
  await decodeAllImages(page);
63469
+ logInitPhase("images ready + decoded");
63426
63470
  await page.evaluate(`document.fonts?.ready`);
63471
+ logInitPhase("fonts ready");
63427
63472
  await waitForOptionalTailwindReady(page, pageReadyTimeout);
63473
+ logInitPhase("tailwind ready");
63428
63474
  warmupState.running = false;
63429
63475
  if (lockWarmupTicks) {
63430
63476
  await warmupLoopPromise.catch(() => {
@@ -68579,7 +68625,7 @@ var init_readWebGlVendorInfoFromCanvas = __esm({
68579
68625
  });
68580
68626
 
68581
68627
  // ../engine/src/services/parallelCoordinator.ts
68582
- import { cpus as cpus2, freemem as freemem3, totalmem as totalmem4 } from "os";
68628
+ import { cpus as cpus2, freemem as freemem3, totalmem as totalmem3 } from "os";
68583
68629
  import { existsSync as existsSync28, mkdirSync as mkdirSync17, readdirSync as readdirSync13 } from "fs";
68584
68630
  import { copyFile, rename } from "fs/promises";
68585
68631
  import { join as join31 } from "path";
@@ -68604,7 +68650,7 @@ function calculateOptimalWorkers(totalFrames, requested, config) {
68604
68650
  if (totalFrames < MIN_FRAMES_PER_WORKER * 2) return 1;
68605
68651
  const cpuCount = cpus2().length;
68606
68652
  const cpuBasedWorkers = Math.max(1, cpuCount - 2);
68607
- const totalMemoryMB = Math.round(totalmem4() / (1024 * 1024));
68653
+ const totalMemoryMB = Math.round(totalmem3() / (1024 * 1024));
68608
68654
  const memoryBasedWorkers = Math.max(1, Math.floor(totalMemoryMB * 0.5 / MEMORY_PER_WORKER_MB));
68609
68655
  const frameBasedWorkers = Math.floor(totalFrames / MIN_FRAMES_PER_WORKER);
68610
68656
  const optimal = Math.min(cpuBasedWorkers, memoryBasedWorkers, frameBasedWorkers);
@@ -68782,7 +68828,7 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
68782
68828
  function getSystemResources() {
68783
68829
  return {
68784
68830
  cpuCores: cpus2().length,
68785
- totalMemoryMB: Math.round(totalmem4() / (1024 * 1024)),
68831
+ totalMemoryMB: Math.round(totalmem3() / (1024 * 1024)),
68786
68832
  freeMemoryMB: Math.round(freemem3() / (1024 * 1024)),
68787
68833
  recommendedWorkers: calculateOptimalWorkers(1e3)
68788
68834
  };
@@ -70357,6 +70403,7 @@ __export(src_exports2, {
70357
70403
  ENABLE_BROWSER_POOL: () => ENABLE_BROWSER_POOL,
70358
70404
  ENCODER_PRESETS: () => ENCODER_PRESETS,
70359
70405
  FrameLookupTable: () => FrameLookupTable,
70406
+ LOW_MEMORY_TOTAL_MB_THRESHOLD: () => LOW_MEMORY_TOTAL_MB_THRESHOLD,
70360
70407
  MEDIA_VISUAL_STYLE_PROPERTIES: () => MEDIA_VISUAL_STYLE_PROPERTIES,
70361
70408
  SwiftShaderAssertionError: () => SwiftShaderAssertionError,
70362
70409
  TRANSITIONS: () => TRANSITIONS,
@@ -70412,6 +70459,7 @@ __export(src_exports2, {
70412
70459
  getFrameAtTime: () => getFrameAtTime,
70413
70460
  getHdrEncoderColorParams: () => getHdrEncoderColorParams,
70414
70461
  getSystemResources: () => getSystemResources,
70462
+ getSystemTotalMb: () => getSystemTotalMb,
70415
70463
  groupIntoLayers: () => groupIntoLayers,
70416
70464
  hdrToLinear: () => hdrToLinear,
70417
70465
  hideVideoElements: () => hideVideoElements,
@@ -70421,6 +70469,7 @@ __export(src_exports2, {
70421
70469
  injectVideoFramesBatch: () => injectVideoFramesBatch,
70422
70470
  isHdrColorSpace: () => isHdrColorSpace,
70423
70471
  isHttpUrl: () => isHttpUrl,
70472
+ isLowMemorySystem: () => isLowMemorySystem,
70424
70473
  killTrackedProcesses: () => killTrackedProcesses,
70425
70474
  launchHdrBrowser: () => launchHdrBrowser,
70426
70475
  linearToHdr: () => linearToHdr,
@@ -70459,6 +70508,7 @@ var init_src2 = __esm({
70459
70508
  "../engine/src/index.ts"() {
70460
70509
  "use strict";
70461
70510
  init_config2();
70511
+ init_systemMemory();
70462
70512
  init_browserManager();
70463
70513
  init_frameCapture();
70464
70514
  init_screenshotService();
@@ -72130,6 +72180,12 @@ function resolveRenderWorkerCount(totalFrames, requestedWorkers, cfg, compiled,
72130
72180
  );
72131
72181
  return 1;
72132
72182
  }
72183
+ if (cfg.lowMemoryMode && requestedWorkers === void 0) {
72184
+ log2.info(
72185
+ "[Render] Low-memory profile \u2014 pinning to 1 capture worker (auto-worker calibration skipped)."
72186
+ );
72187
+ return 1;
72188
+ }
72133
72189
  const captureCost = combineCaptureCostEstimates(
72134
72190
  estimateCaptureCostMultiplier(compiled),
72135
72191
  measuredCaptureCost
@@ -72158,7 +72214,7 @@ function resolveRenderWorkerCount(totalFrames, requestedWorkers, cfg, compiled,
72158
72214
  function createCaptureCalibrationConfig(cfg) {
72159
72215
  return {
72160
72216
  ...cfg,
72161
- protocolTimeout: Math.max(cfg.protocolTimeout, CAPTURE_CALIBRATION_PROTOCOL_TIMEOUT_MS)
72217
+ protocolTimeout: Math.min(cfg.protocolTimeout, CAPTURE_CALIBRATION_PROTOCOL_TIMEOUT_MS)
72162
72218
  };
72163
72219
  }
72164
72220
  function estimateMeasuredCaptureCostMultiplier(samples) {
@@ -72290,6 +72346,12 @@ async function runCaptureCalibration(input2) {
72290
72346
  return result;
72291
72347
  };
72292
72348
  const calibrationCfg = createCaptureCalibrationConfig({ ...cfg, forceScreenshot });
72349
+ log2.info("[Render] Calibration config", {
72350
+ protocolTimeout: calibrationCfg.protocolTimeout,
72351
+ parentProtocolTimeout: cfg.protocolTimeout,
72352
+ forceScreenshot,
72353
+ totalFrames
72354
+ });
72293
72355
  let calibration;
72294
72356
  try {
72295
72357
  calibration = await runOneCalibration(join38(workDir, "capture-calibration"), calibrationCfg);
@@ -76531,6 +76593,20 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
76531
76593
  };
76532
76594
  job.startedAt = /* @__PURE__ */ new Date();
76533
76595
  assertNotAborted();
76596
+ log2.info("[Render] Pipeline started", {
76597
+ platform: process.platform,
76598
+ arch: process.arch,
76599
+ nodeVersion: process.version,
76600
+ fps: job.config.fps,
76601
+ format: outputFormat,
76602
+ quality: job.config.quality,
76603
+ browserGpuMode: cfg.browserGpuMode,
76604
+ forceScreenshot: cfg.forceScreenshot,
76605
+ protocolTimeout: cfg.protocolTimeout,
76606
+ browserTimeout: cfg.browserTimeout,
76607
+ pageNavigationTimeout: cfg.pageNavigationTimeout,
76608
+ playerReadyTimeout: cfg.playerReadyTimeout
76609
+ });
76534
76610
  if (!existsSync40(workDir)) mkdirSync24(workDir, { recursive: true });
76535
76611
  if (job.config.debug) {
76536
76612
  const logPath = join50(workDir, "render.log");
@@ -76585,6 +76661,13 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
76585
76661
  const { width, height } = composition;
76586
76662
  perfStages.compileOnlyMs = compileResult.compileOnlyMs;
76587
76663
  let captureForceScreenshot = compileResult.forceScreenshot;
76664
+ if (cfg.lowMemoryMode) {
76665
+ captureForceScreenshot = true;
76666
+ log2.info(
76667
+ "[Render] Low-memory render profile active \u2014 screenshot capture, auto-worker calibration skipped" + (job.config.workers === void 0 ? ", pinned to 1 worker" : "") + ". Override with --no-low-memory-mode or PRODUCER_LOW_MEMORY_MODE=false.",
76668
+ { totalMemMb: getSystemTotalMb(), thresholdMb: LOW_MEMORY_TOTAL_MB_THRESHOLD }
76669
+ );
76670
+ }
76588
76671
  const probeResult = await runProbeStage({
76589
76672
  projectDir,
76590
76673
  workDir,
@@ -76689,7 +76772,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
76689
76772
  const htmlInCanvasDetected = compiled.renderModeHints.reasons.some(
76690
76773
  (r2) => r2.code === "htmlInCanvas"
76691
76774
  );
76692
- if (job.config.workers === void 0 && totalFrames >= 60 && !htmlInCanvasDetected) {
76775
+ if (job.config.workers === void 0 && totalFrames >= 60 && !htmlInCanvasDetected && !cfg.lowMemoryMode) {
76693
76776
  const outcome = await runCaptureCalibration({
76694
76777
  cfg,
76695
76778
  fileServer,
@@ -77006,6 +77089,16 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
77006
77089
  perfStages,
77007
77090
  hdrDiagnostics
77008
77091
  });
77092
+ log2.info("[Render] Failure summary", {
77093
+ failedStage: job.currentStage,
77094
+ error: errorMessage,
77095
+ elapsedMs: Date.now() - pipelineStart,
77096
+ stageTimings: perfStages,
77097
+ isTimeout: isTimeoutError,
77098
+ workers: job.config.workers ?? "auto",
77099
+ protocolTimeout: cfg.protocolTimeout,
77100
+ browserConsoleErrors: lastBrowserConsole.filter((l) => l.includes("ERROR") || l.includes("PAGEERROR")).slice(-5)
77101
+ });
77009
77102
  await cleanupRenderResources({
77010
77103
  fileServer,
77011
77104
  probeSession,
@@ -83467,6 +83560,10 @@ var init_render2 = __esm({
83467
83560
  "player-ready-timeout": {
83468
83561
  type: "string",
83469
83562
  description: "Timeout in ms for the composition player to become ready. Increase for complex compositions on slow hardware. Default: 45000 (45 s). Env: PRODUCER_PLAYER_READY_TIMEOUT_MS."
83563
+ },
83564
+ "low-memory-mode": {
83565
+ type: "boolean",
83566
+ description: "Force the low-memory safe render profile on (--low-memory-mode) or off (--no-low-memory-mode). Safe mode pins to 1 worker, uses screenshot capture, and skips auto-worker calibration to avoid memory thrash on constrained machines. Default: auto-detected from total RAM (<= 8 GB). Env: PRODUCER_LOW_MEMORY_MODE."
83470
83567
  }
83471
83568
  },
83472
83569
  // `run` is the citty handler for `hyperframes render` — sequential flag
@@ -83550,6 +83647,9 @@ var init_render2 = __esm({
83550
83647
  if (args["page-side-compositing"] === false) {
83551
83648
  process.env.HF_PAGE_SIDE_COMPOSITING = "false";
83552
83649
  }
83650
+ if (args["low-memory-mode"] != null) {
83651
+ process.env.PRODUCER_LOW_MEMORY_MODE = args["low-memory-mode"] ? "true" : "false";
83652
+ }
83553
83653
  if (args["max-concurrent-renders"] != null) {
83554
83654
  const parsed = parseInt(args["max-concurrent-renders"], 10);
83555
83655
  if (isNaN(parsed) || parsed < 1 || parsed > 10) {
@@ -127970,35 +128070,71 @@ async function downloadAndRewriteFonts(css, outputDir) {
127970
128070
  }
127971
128071
  return rewritten;
127972
128072
  }
128073
+ function isPrivateIpv4(host) {
128074
+ const octets = host.split(".").map(Number);
128075
+ if (octets.length !== 4) return false;
128076
+ const [a, b2] = octets;
128077
+ return PRIVATE_V4_BLOCKS.some(([first, lo, hi]) => a === first && b2 >= lo && b2 <= hi);
128078
+ }
128079
+ function isPrivateIpv6(bracketed) {
128080
+ const addr = bracketed.replace(/^\[|\]$/g, "").toLowerCase();
128081
+ if (addr === "::1" || addr === "::") return true;
128082
+ const mapped = /^::ffff:(.+)$/.exec(addr);
128083
+ if (mapped) {
128084
+ const tail = mapped[1];
128085
+ if (tail.includes(".")) return isPrivateIpv4(tail);
128086
+ const hex = tail.split(":");
128087
+ if (hex.length === 2) {
128088
+ const n = (parseInt(hex[0], 16) << 16 | parseInt(hex[1], 16)) >>> 0;
128089
+ return isPrivateIpv4(
128090
+ [n >>> 24 & 255, n >>> 16 & 255, n >>> 8 & 255, n & 255].join(".")
128091
+ );
128092
+ }
128093
+ }
128094
+ if (/^f[cd]/.test(addr)) return true;
128095
+ if (/^fe[89ab]/.test(addr)) return true;
128096
+ return false;
128097
+ }
127973
128098
  function isPrivateUrl(url) {
127974
128099
  try {
127975
- const { hostname } = new URL(url);
127976
- if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]") return true;
127977
- if (hostname === "169.254.169.254") return true;
128100
+ const u = new URL(url);
128101
+ if (u.protocol !== "http:" && u.protocol !== "https:") return true;
128102
+ const hostname = u.hostname;
128103
+ if (hostname === "localhost") return true;
127978
128104
  if (hostname.endsWith(".internal") || hostname.endsWith(".local")) return true;
127979
- const parts = hostname.split(".").map(Number);
127980
- if (parts.length === 4 && parts.every((p2) => !isNaN(p2))) {
127981
- if (parts[0] === 10) return true;
127982
- if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) return true;
127983
- if (parts[0] === 192 && parts[1] === 168) return true;
127984
- if (parts[0] === 169 && parts[1] === 254) return true;
127985
- }
127986
- const scheme = new URL(url).protocol;
127987
- if (scheme !== "http:" && scheme !== "https:") return true;
128105
+ if (hostname.startsWith("[")) return isPrivateIpv6(hostname);
128106
+ if (/^\d+(\.\d+){3}$/.test(hostname)) return isPrivateIpv4(hostname);
127988
128107
  return false;
127989
128108
  } catch {
127990
128109
  return true;
127991
128110
  }
127992
128111
  }
128112
+ async function safeFetch(url, init) {
128113
+ let current = url;
128114
+ for (let hop = 0; hop <= MAX_FETCH_REDIRECTS; hop++) {
128115
+ if (isPrivateUrl(current)) return null;
128116
+ const res = await fetch(current, { ...init, redirect: "manual" });
128117
+ if (res.status >= 300 && res.status < 400) {
128118
+ const loc = res.headers.get("location");
128119
+ if (!loc) return res;
128120
+ try {
128121
+ current = new URL(loc, current).toString();
128122
+ } catch {
128123
+ return null;
128124
+ }
128125
+ continue;
128126
+ }
128127
+ return res;
128128
+ }
128129
+ return null;
128130
+ }
127993
128131
  async function fetchBuffer(url) {
127994
128132
  try {
127995
- if (isPrivateUrl(url)) return null;
127996
- const res = await fetch(url, {
128133
+ const res = await safeFetch(url, {
127997
128134
  signal: AbortSignal.timeout(1e4),
127998
- headers: { "User-Agent": "HyperFrames/1.0" },
127999
- redirect: "follow"
128135
+ headers: { "User-Agent": "HyperFrames/1.0" }
128000
128136
  });
128001
- if (!res.ok) return null;
128137
+ if (!res || !res.ok) return null;
128002
128138
  const ct2 = res.headers.get("content-type") || "";
128003
128139
  if (ct2.includes("text/xml") || ct2.includes("text/html") || ct2.includes("application/xml")) {
128004
128140
  return null;
@@ -128046,9 +128182,25 @@ function deriveAssetName(parsedUrl, catalog, isPoster, idx, usedNames) {
128046
128182
  }
128047
128183
  return final;
128048
128184
  }
128185
+ var PRIVATE_V4_BLOCKS, MAX_FETCH_REDIRECTS;
128049
128186
  var init_assetDownloader = __esm({
128050
128187
  "src/capture/assetDownloader.ts"() {
128051
128188
  "use strict";
128189
+ PRIVATE_V4_BLOCKS = [
128190
+ [0, 0, 255],
128191
+ // 0.0.0.0/8 (incl. 0.0.0.0, which routes to localhost)
128192
+ [10, 0, 255],
128193
+ // 10.0.0.0/8
128194
+ [127, 0, 255],
128195
+ // 127.0.0.0/8 loopback
128196
+ [172, 16, 31],
128197
+ // 172.16.0.0/12
128198
+ [192, 168, 168],
128199
+ // 192.168.0.0/16
128200
+ [169, 254, 254]
128201
+ // 169.254.0.0/16 link-local (cloud metadata)
128202
+ ];
128203
+ MAX_FETCH_REDIRECTS = 5;
128052
128204
  }
128053
128205
  });
128054
128206
 
@@ -129245,12 +129397,11 @@ async function saveLottieAnimations(discoveredLotties, lottieDir) {
129245
129397
  if (lottieItem.data) {
129246
129398
  jsonData = JSON.stringify(lottieItem.data);
129247
129399
  } else if (lottieItem.url) {
129248
- if (isPrivateUrl(lottieItem.url)) continue;
129249
- const res = await fetch(lottieItem.url, {
129400
+ const res = await safeFetch(lottieItem.url, {
129250
129401
  signal: AbortSignal.timeout(1e4),
129251
129402
  headers: { "User-Agent": "HyperFrames/1.0" }
129252
129403
  });
129253
- if (!res.ok) continue;
129404
+ if (!res || !res.ok) continue;
129254
129405
  const buf = Buffer.from(await res.arrayBuffer());
129255
129406
  if (lottieItem.url.endsWith(".lottie")) {
129256
129407
  try {
@@ -0,0 +1 @@
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.inset-2{top:.5rem;right:.5rem;bottom:.5rem;left:.5rem}.inset-x-0{left:0;right:0}.inset-y-0{top:0;bottom:0}.-bottom-1\.5{bottom:-.375rem}.-right-1\.5{right:-.375rem}.bottom-0{bottom:0}.bottom-1{bottom:.25rem}.bottom-2{bottom:.5rem}.bottom-3{bottom:.75rem}.bottom-6{bottom:1.5rem}.bottom-full{bottom:100%}.left-0{left:0}.left-1\/2{left:50%}.left-2{left:.5rem}.left-3{left:.75rem}.left-\[100px\]{left:100px}.left-\[176px\]{left:176px}.left-\[24px\]{left:24px}.left-\[31px\]{left:31px}.left-\[34px\]{left:34px}.left-\[52px\]{left:52px}.left-\[82px\]{left:82px}.left-full{left:100%}.right-0{right:0}.right-1{right:.25rem}.right-2{right:.5rem}.right-3{right:.75rem}.top-0{top:0}.top-0\.5{top:.125rem}.top-1{top:.25rem}.top-1\/2{top:50%}.top-2{top:.5rem}.top-3{top:.75rem}.top-\[18px\]{top:18px}.top-\[21px\]{top:21px}.top-\[27px\]{top:27px}.top-\[3px\]{top:3px}.top-\[51px\]{top:51px}.top-\[calc\(100\%\+6px\)\]{top:calc(100% + 6px)}.top-full{top:100%}.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-\[100\]{z-index:100}.z-\[1\]{z-index:1}.z-\[200\]{z-index:200}.z-\[3\]{z-index:3}.z-\[4\]{z-index:4}.z-\[90\]{z-index:90}.z-\[91\]{z-index:91}.z-\[9999\]{z-index:9999}.mx-1{margin-left:.25rem;margin-right:.25rem}.my-0\.5{margin-top:.125rem;margin-bottom:.125rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.-mt-\[72px\]{margin-top:-72px}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.ml-0\.5{margin-left:.125rem}.ml-1{margin-left:.25rem}.ml-1\.5{margin-left:.375rem}.ml-2{margin-left:.5rem}.ml-3{margin-left:.75rem}.ml-\[16px\]{margin-left:16px}.ml-auto{margin-left:auto}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-\[22px\]{margin-top:22px}.\!block{display:block!important}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.contents{display:contents}.hidden{display:none}.aspect-video{aspect-ratio:16 / 9}.h-0\.5{height:.125rem}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-2{height:.5rem}.h-24{height:6rem}.h-28{height:7rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-32{height:8rem}.h-36{height:9rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[18px\]{height:18px}.h-\[3px\]{height:3px}.h-\[45px\]{height:45px}.h-\[52px\]{height:52px}.h-\[5px\]{height:5px}.h-\[70px\]{height:70px}.h-full{height:100%}.h-px{height:1px}.max-h-24{max-height:6rem}.max-h-40{max-height:10rem}.max-h-64{max-height:16rem}.max-h-\[300px\]{max-height:300px}.max-h-\[70\%\]{max-height:70%}.max-h-\[80vh\]{max-height:80vh}.max-h-full{max-height:100%}.min-h-0{min-height:0px}.min-h-7{min-height:1.75rem}.min-h-8{min-height:2rem}.min-h-9{min-height:2.25rem}.min-h-\[240px\]{min-height:240px}.w-0{width:0px}.w-1\.5{width:.375rem}.w-10{width:2.5rem}.w-14{width:3.5rem}.w-16{width:4rem}.w-2{width:.5rem}.w-20{width:5rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-52{width:13rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-\[110px\]{width:110px}.w-\[118px\]{width:118px}.w-\[160px\]{width:160px}.w-\[292px\]{width:292px}.w-\[320px\]{width:320px}.w-\[480px\]{width:480px}.w-\[560px\]{width:560px}.w-\[56px\]{width:56px}.w-\[72px\]{width:72px}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:0px}.min-w-7{min-width:1.75rem}.min-w-8{min-width:2rem}.min-w-9{min-width:2.25rem}.min-w-\[140px\]{min-width:140px}.min-w-\[160px\]{min-width:160px}.min-w-\[180px\]{min-width:180px}.min-w-\[20px\]{min-width:20px}.min-w-\[220px\]{min-width:220px}.min-w-\[36px\]{min-width:36px}.min-w-\[52px\]{min-width:52px}.min-w-\[56px\]{min-width:56px}.min-w-\[58px\]{min-width:58px}.min-w-\[96px\]{min-width:96px}.max-w-\[260px\]{max-width:260px}.max-w-\[280px\]{max-width:280px}.max-w-\[calc\(100vw-2rem\)\]{max-width:calc(100vw - 2rem)}.max-w-full{max-width:100%}.max-w-xl{max-width:36rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0\.5{--tw-translate-x: .125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-3\.5{--tw-translate-x: .875rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-2{--tw-translate-y: .5rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-rotate-90{--tw-rotate: -90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.\!transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))!important}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-col-resize{cursor:col-resize}.cursor-crosshair{cursor:crosshair}.cursor-default{cursor:default}.cursor-ew-resize{cursor:ew-resize}.cursor-grab{cursor:grab}.cursor-grabbing{cursor:grabbing}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.cursor-row-resize{cursor:row-resize}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.resize-y{resize:vertical}.\!resize{resize:both!important}.resize{resize:both}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-cols-\[minmax\(0\,1fr\)_68px_28px\]{grid-template-columns:minmax(0,1fr) 68px 28px}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_auto_auto\]{grid-template-columns:minmax(0,1fr) auto auto}.grid-cols-\[repeat\(auto-fit\,minmax\(118px\,1fr\)\)\]{grid-template-columns:repeat(auto-fit,minmax(118px,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.gap-y-1{row-gap:.25rem}.gap-y-1\.5{row-gap:.375rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-\[10px\]{border-radius:10px}.rounded-\[11px\]{border-radius:11px}.rounded-\[14px\]{border-radius:14px}.rounded-\[18px\]{border-radius:18px}.rounded-\[9px\]{border-radius:9px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.rounded-l{border-top-left-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-r{border-top-right-radius:.25rem;border-bottom-right-radius:.25rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-green-500\/30{border-color:#22c55e4d}.border-neutral-600{--tw-border-opacity: 1;border-color:rgb(82 82 82 / var(--tw-border-opacity, 1))}.border-neutral-700{--tw-border-opacity: 1;border-color:rgb(64 64 64 / var(--tw-border-opacity, 1))}.border-neutral-700\/40{border-color:#40404066}.border-neutral-700\/50{border-color:#40404080}.border-neutral-700\/60{border-color:#40404099}.border-neutral-800{--tw-border-opacity: 1;border-color:rgb(38 38 38 / var(--tw-border-opacity, 1))}.border-neutral-800\/30{border-color:#2626264d}.border-neutral-800\/40{border-color:#26262666}.border-neutral-800\/50{border-color:#26262680}.border-neutral-800\/60{border-color:#26262699}.border-neutral-800\/80{border-color:#262626cc}.border-neutral-900{--tw-border-opacity: 1;border-color:rgb(23 23 23 / var(--tw-border-opacity, 1))}.border-purple-500\/20{border-color:#a855f733}.border-red-500{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.border-red-700\/50{border-color:#b91c1c80}.border-studio-accent{--tw-border-opacity: 1;border-color:rgb(60 230 172 / var(--tw-border-opacity, 1))}.border-studio-accent\/25{border-color:#3ce6ac40}.border-studio-accent\/30{border-color:#3ce6ac4d}.border-studio-accent\/40{border-color:#3ce6ac66}.border-studio-accent\/50{border-color:#3ce6ac80}.border-studio-accent\/60{border-color:#3ce6ac99}.border-studio-accent\/70{border-color:#3ce6acb3}.border-studio-accent\/80{border-color:#3ce6accc}.border-transparent{border-color:transparent}.border-white{--tw-border-opacity: 1;border-color:rgb(255 255 255 / var(--tw-border-opacity, 1))}.border-white\/10{border-color:#ffffff1a}.border-white\/90{border-color:#ffffffe6}.border-yellow-400\/30{border-color:#facc154d}.border-yellow-400\/40{border-color:#facc1566}.border-t-neutral-500{--tw-border-opacity: 1;border-top-color:rgb(115 115 115 / var(--tw-border-opacity, 1))}.bg-\[\#0a0a0b\]{--tw-bg-opacity: 1;background-color:rgb(10 10 11 / var(--tw-bg-opacity, 1))}.bg-\[\#0d1117\]{--tw-bg-opacity: 1;background-color:rgb(13 17 23 / var(--tw-bg-opacity, 1))}.bg-\[\#0f141c\]{--tw-bg-opacity: 1;background-color:rgb(15 20 28 / var(--tw-bg-opacity, 1))}.bg-\[\#3CE6AC\]\/10{background-color:#3ce6ac1a}.bg-\[\#3CE6AC\]\/5{background-color:#3ce6ac0d}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.bg-amber-500\/10{background-color:#f59e0b1a}.bg-amber-500\/15{background-color:#f59e0b26}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\/40{background-color:#0006}.bg-black\/50{background-color:#00000080}.bg-black\/60{background-color:#0009}.bg-blue-400{--tw-bg-opacity: 1;background-color:rgb(96 165 250 / var(--tw-bg-opacity, 1))}.bg-blue-500\/15{background-color:#3b82f626}.bg-blue-900\/40{background-color:#1e3a8a66}.bg-cyan-400{--tw-bg-opacity: 1;background-color:rgb(34 211 238 / var(--tw-bg-opacity, 1))}.bg-cyan-500\/15{background-color:#06b6d426}.bg-emerald-400{--tw-bg-opacity: 1;background-color:rgb(52 211 153 / var(--tw-bg-opacity, 1))}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-emerald-500\/10{background-color:#10b9811a}.bg-emerald-500\/30{background-color:#10b9814d}.bg-green-400{--tw-bg-opacity: 1;background-color:rgb(74 222 128 / var(--tw-bg-opacity, 1))}.bg-green-500\/15{background-color:#22c55e26}.bg-green-500\/20{background-color:#22c55e33}.bg-green-600{--tw-bg-opacity: 1;background-color:rgb(22 163 74 / var(--tw-bg-opacity, 1))}.bg-neutral-500{--tw-bg-opacity: 1;background-color:rgb(115 115 115 / var(--tw-bg-opacity, 1))}.bg-neutral-600{--tw-bg-opacity: 1;background-color:rgb(82 82 82 / var(--tw-bg-opacity, 1))}.bg-neutral-700{--tw-bg-opacity: 1;background-color:rgb(64 64 64 / var(--tw-bg-opacity, 1))}.bg-neutral-700\/40{background-color:#40404066}.bg-neutral-800{--tw-bg-opacity: 1;background-color:rgb(38 38 38 / var(--tw-bg-opacity, 1))}.bg-neutral-800\/50{background-color:#26262680}.bg-neutral-800\/60{background-color:#26262699}.bg-neutral-800\/70{background-color:#262626b3}.bg-neutral-900{--tw-bg-opacity: 1;background-color:rgb(23 23 23 / var(--tw-bg-opacity, 1))}.bg-neutral-900\/50{background-color:#17171780}.bg-neutral-900\/60{background-color:#17171799}.bg-neutral-900\/80{background-color:#171717cc}.bg-neutral-900\/95{background-color:#171717f2}.bg-neutral-950{--tw-bg-opacity: 1;background-color:rgb(10 10 10 / var(--tw-bg-opacity, 1))}.bg-neutral-950\/80{background-color:#0a0a0acc}.bg-pink-400{--tw-bg-opacity: 1;background-color:rgb(244 114 182 / var(--tw-bg-opacity, 1))}.bg-pink-500\/15{background-color:#ec489926}.bg-purple-400{--tw-bg-opacity: 1;background-color:rgb(192 132 252 / var(--tw-bg-opacity, 1))}.bg-purple-500\/10{background-color:#a855f71a}.bg-purple-500\/15{background-color:#a855f726}.bg-purple-900\/70{background-color:#581c87b3}.bg-red-400{--tw-bg-opacity: 1;background-color:rgb(248 113 113 / var(--tw-bg-opacity, 1))}.bg-red-500\/10{background-color:#ef44441a}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-red-900\/60{background-color:#7f1d1d99}.bg-red-900\/90{background-color:#7f1d1de6}.bg-red-950\/30{background-color:#450a0a4d}.bg-rose-400{--tw-bg-opacity: 1;background-color:rgb(251 113 133 / var(--tw-bg-opacity, 1))}.bg-rose-500\/15{background-color:#f43f5e26}.bg-studio-accent{--tw-bg-opacity: 1;background-color:rgb(60 230 172 / var(--tw-bg-opacity, 1))}.bg-studio-accent\/10{background-color:#3ce6ac1a}.bg-studio-accent\/15{background-color:#3ce6ac26}.bg-studio-accent\/20{background-color:#3ce6ac33}.bg-studio-accent\/5{background-color:#3ce6ac0d}.bg-studio-accent\/60{background-color:#3ce6ac99}.bg-studio-accent\/90{background-color:#3ce6ace6}.bg-studio-accent\/\[0\.03\]{background-color:#3ce6ac08}.bg-studio-accent\/\[0\.04\]{background-color:#3ce6ac0a}.bg-studio-accent\/\[0\.05\]{background-color:#3ce6ac0d}.bg-studio-accent\/\[0\.06\]{background-color:#3ce6ac0f}.bg-transparent{background-color:transparent}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/10{background-color:#ffffff1a}.bg-white\/15{background-color:#ffffff26}.bg-white\/5{background-color:#ffffff0d}.bg-white\/70{background-color:#ffffffb3}.bg-white\/\[0\.035\]{background-color:#ffffff09}.bg-white\/\[0\.04\]{background-color:#ffffff0a}.bg-white\/\[0\.07\]{background-color:#ffffff12}.bg-yellow-400\/10{background-color:#facc151a}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.from-black{--tw-gradient-from: #000 var(--tw-gradient-from-position);--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-white{--tw-gradient-from: #fff var(--tw-gradient-from-position);--tw-gradient-to: rgb(255 255 255 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-transparent{--tw-gradient-to: transparent var(--tw-gradient-to-position)}.fill-neutral-400{fill:#a3a3a3}.fill-neutral-500{fill:#737373}.fill-neutral-600{fill:#525252}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-3{padding:.75rem}.p-4{padding:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.py-px{padding-top:1px;padding-bottom:1px}.pb-0\.5{padding-bottom:.125rem}.pb-1{padding-bottom:.25rem}.pb-2{padding-bottom:.5rem}.pb-2\.5{padding-bottom:.625rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-1{padding-left:.25rem}.pl-6{padding-left:1.5rem}.pl-7{padding-left:1.75rem}.pr-1{padding-right:.25rem}.pr-2{padding-right:.5rem}.pr-9{padding-right:2.25rem}.pt-0\.5{padding-top:.125rem}.pt-1{padding-top:.25rem}.pt-1\.5{padding-top:.375rem}.pt-2{padding-top:.5rem}.pt-2\.5{padding-top:.625rem}.pt-3{padding-top:.75rem}.pt-\[72px\]{padding-top:72px}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[7px\]{font-size:7px}.text-\[8px\]{font-size:8px}.text-\[9px\]{font-size:9px}.text-base{font-size:1rem;line-height:1.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.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)}.leading-4{line-height:1rem}.leading-5{line-height:1.25rem}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-\[0\.12em\]{letter-spacing:.12em}.tracking-\[0\.14em\]{letter-spacing:.14em}.tracking-\[0\.16em\]{letter-spacing:.16em}.tracking-\[0\.18em\]{letter-spacing:.18em}.tracking-\[0\.22em\]{letter-spacing:.22em}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.text-\[\#09090B\]{--tw-text-opacity: 1;color:rgb(9 9 11 / var(--tw-text-opacity, 1))}.text-\[\#3ce6ac\]{--tw-text-opacity: 1;color:rgb(60 230 172 / var(--tw-text-opacity, 1))}.text-\[\#7f8796\]{--tw-text-opacity: 1;color:rgb(127 135 150 / var(--tw-text-opacity, 1))}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity, 1))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-cyan-400{--tw-text-opacity: 1;color:rgb(34 211 238 / var(--tw-text-opacity, 1))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-emerald-400\/70{color:#34d399b3}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-neutral-100{--tw-text-opacity: 1;color:rgb(245 245 245 / var(--tw-text-opacity, 1))}.text-neutral-200{--tw-text-opacity: 1;color:rgb(229 229 229 / var(--tw-text-opacity, 1))}.text-neutral-300{--tw-text-opacity: 1;color:rgb(212 212 212 / var(--tw-text-opacity, 1))}.text-neutral-400{--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.text-neutral-50{--tw-text-opacity: 1;color:rgb(250 250 250 / var(--tw-text-opacity, 1))}.text-neutral-500{--tw-text-opacity: 1;color:rgb(115 115 115 / var(--tw-text-opacity, 1))}.text-neutral-600{--tw-text-opacity: 1;color:rgb(82 82 82 / var(--tw-text-opacity, 1))}.text-neutral-700{--tw-text-opacity: 1;color:rgb(64 64 64 / var(--tw-text-opacity, 1))}.text-neutral-950{--tw-text-opacity: 1;color:rgb(10 10 10 / var(--tw-text-opacity, 1))}.text-orange-400\/70{color:#fb923cb3}.text-pink-400{--tw-text-opacity: 1;color:rgb(244 114 182 / var(--tw-text-opacity, 1))}.text-purple-200{--tw-text-opacity: 1;color:rgb(233 213 255 / var(--tw-text-opacity, 1))}.text-purple-300{--tw-text-opacity: 1;color:rgb(216 180 254 / var(--tw-text-opacity, 1))}.text-purple-400{--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-red-200{--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.text-red-300{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-rose-400{--tw-text-opacity: 1;color:rgb(251 113 133 / var(--tw-text-opacity, 1))}.text-studio-accent{--tw-text-opacity: 1;color:rgb(60 230 172 / var(--tw-text-opacity, 1))}.text-studio-accent\/50{color:#3ce6ac80}.text-studio-accent\/80{color:#3ce6accc}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-white\/60{color:#fff9}.text-white\/80{color:#fffc}.text-white\/90{color:#ffffffe6}.text-yellow-300{--tw-text-opacity: 1;color:rgb(253 224 71 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.placeholder-neutral-600::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(82 82 82 / var(--tw-placeholder-opacity, 1))}.placeholder-neutral-600::placeholder{--tw-placeholder-opacity: 1;color:rgb(82 82 82 / var(--tw-placeholder-opacity, 1))}.accent-\[\#3ce6ac\]{accent-color:#3ce6ac}.accent-studio-accent{accent-color:#3CE6AC}.accent-yellow-400{accent-color:#facc15}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-25{opacity:.25}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.opacity-75{opacity:.75}.mix-blend-difference{mix-blend-mode:difference}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(0\,0\,0\,0\.35\)\]{--tw-shadow: 0 0 0 1px rgba(0,0,0,.35);--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(0\,0\,0\,0\.45\)\]{--tw-shadow: 0 0 0 1px rgba(0,0,0,.45);--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(0\,0\,0\,0\.85\)\,0_6px_14px_rgba\(0\,0\,0\,0\.5\)\]{--tw-shadow: 0 0 0 1px rgba(0,0,0,.85),0 6px 14px rgba(0,0,0,.5);--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color), 0 6px 14px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(0\,0\,0\,0\.85\)\,0_8px_18px_rgba\(0\,0\,0\,0\.45\)\]{--tw-shadow: 0 0 0 1px rgba(0,0,0,.85),0 8px 18px rgba(0,0,0,.45);--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color), 0 8px 18px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(60\,230\,172\,0\.25\)\]{--tw-shadow: 0 0 0 1px rgba(60,230,172,.25);--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_1px_rgba\(60\,230\,172\,0\.3\)\]{--tw-shadow: 0 0 0 1px rgba(60,230,172,.3);--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_0_0_2px_rgba\(60\,230\,172\,0\.18\)\]{--tw-shadow: 0 0 0 2px rgba(60,230,172,.18);--tw-shadow-colored: 0 0 0 2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_18px_40px_rgba\(0\,0\,0\,0\.3\)\,0_4px_14px_rgba\(0\,0\,0\,0\.18\)\]{--tw-shadow: 0 18px 40px rgba(0,0,0,.3),0 4px 14px rgba(0,0,0,.18);--tw-shadow-colored: 0 18px 40px var(--tw-shadow-color), 0 4px 14px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_1px_2px_rgba\(0\,0\,0\,0\.2\)\]{--tw-shadow: 0 1px 2px rgba(0,0,0,.2);--tw-shadow-colored: 0 1px 2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_1px_3px_rgba\(0\,0\,0\,0\.28\)\]{--tw-shadow: 0 1px 3px rgba(0,0,0,.28);--tw-shadow-colored: 0 1px 3px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[inset_0_0_0_1px_rgba\(255\,255\,255\,0\.06\)\]{--tw-shadow: inset 0 0 0 1px rgba(255,255,255,.06);--tw-shadow-colored: inset 0 0 0 1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[inset_0_1px_0_rgba\(255\,255\,255\,0\.03\)\]{--tw-shadow: inset 0 1px 0 rgba(255,255,255,.03);--tw-shadow-colored: inset 0 1px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[inset_0_1px_0_rgba\(255\,255\,255\,0\.04\)\]{--tw-shadow: inset 0 1px 0 rgba(255,255,255,.04);--tw-shadow-colored: inset 0 1px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[inset_0_1px_0_rgba\(255\,255\,255\,0\.08\)\]{--tw-shadow: inset 0 1px 0 rgba(255,255,255,.08);--tw-shadow-colored: inset 0 1px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[inset_0_1px_2px_rgba\(0\,0\,0\,0\.55\)\]{--tw-shadow: inset 0 1px 2px rgba(0,0,0,.55);--tw-shadow-colored: inset 0 1px 2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-black\/40{--tw-shadow-color: rgb(0 0 0 / .4);--tw-shadow: var(--tw-shadow-colored)}.shadow-black\/50{--tw-shadow-color: rgb(0 0 0 / .5);--tw-shadow: var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.outline-1{outline-width:1px}.-outline-offset-1{outline-offset:-1px}.outline-\[\#3CE6AC\]\/30{outline-color:#3ce6ac4d}.outline-\[\#3CE6AC\]\/40{outline-color:#3ce6ac66}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-inset{--tw-ring-inset: inset}.ring-studio-accent{--tw-ring-opacity: 1;--tw-ring-color: rgb(60 230 172 / var(--tw-ring-opacity, 1))}.ring-white\/50{--tw-ring-color: rgb(255 255 255 / .5)}.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{--tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / .1)) drop-shadow(0 1px 1px rgb(0 0 0 / .06));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)}.grayscale{--tw-grayscale: grayscale(100%);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)}.invert{--tw-invert: invert(100%);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)}.filter{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-sm{--tw-backdrop-blur: blur(4px);-webkit-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);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)}.backdrop-blur-xl{--tw-backdrop-blur: blur(24px);-webkit-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);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)}.backdrop-filter{-webkit-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);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,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-150{transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}:root{color-scheme:dark}body{margin:0;padding:0;background:#0a0a0a;color:#e5e5e5;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;overflow:hidden}#root{width:100vw;height:100vh;height:100dvh}.cm-editor{height:100%;font-size:13px}.cm-editor .cm-scroller{font-family:JetBrains Mono,Fira Code,SF Mono,monospace}.cm-editor.cm-focused{outline:none}.hf-loader{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;width:min(34rem,100%);padding:1.5rem;box-sizing:border-box;text-align:center;cursor:default;-moz-user-select:none;user-select:none;-webkit-user-select:none;-webkit-user-drag:none}.hf-frame{display:grid;place-items:center;width:100%;height:100%;min-height:12rem;border:1px solid rgba(255,255,255,.08);background:#00000085}.hf-loader-mark-frame{display:grid;place-items:center;overflow:visible;transform-origin:50% 50%;-moz-user-select:none;user-select:none;-webkit-user-select:none;-webkit-user-drag:none}.hf-loader-mark{display:block;overflow:visible;filter:drop-shadow(0 0 7px rgba(79,219,94,.2));-moz-user-select:none;user-select:none;-webkit-user-select:none;-webkit-user-drag:none}.hf-loader-title{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:1rem;font-weight:600;letter-spacing:0;color:var(--hf-heading, #f4f4f5);max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hf-loader-detail{max-width:32rem;min-height:2.5rem;overflow:hidden;color:var(--hf-text-secondary, rgba(244, 244, 245, .68));font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;font-size:.82rem;line-height:1.6}.hf-loader-mono{width:min(36rem,100%);min-height:1.5rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--hf-text-tertiary, rgba(244, 244, 245, .46));font-family:IBM Plex Mono,SF Mono,Fira Code,monospace;font-size:.75rem;letter-spacing:0;font-variant-numeric:tabular-nums}.hf-loader-progress{width:min(18rem,72vw);height:.375rem;overflow:hidden;border-radius:999px;background:#ffffff1a}@keyframes hf-thumb-fade{0%{opacity:0}to{opacity:1}}.hf-loader-progress__fill{width:100%;height:100%;transform:scaleX(0);transform-origin:left center;border-radius:inherit;background:linear-gradient(90deg,#06e3fa,#4fdb5e);transition:transform .16s ease}.placeholder\:text-neutral-600::-moz-placeholder{--tw-text-opacity: 1;color:rgb(82 82 82 / var(--tw-text-opacity, 1))}.placeholder\:text-neutral-600::placeholder{--tw-text-opacity: 1;color:rgb(82 82 82 / var(--tw-text-opacity, 1))}.last\:border-0:last-child{border-width:0px}.focus-within\:border-neutral-600:focus-within{--tw-border-opacity: 1;border-color:rgb(82 82 82 / var(--tw-border-opacity, 1))}.hover\:border-neutral-500:hover{--tw-border-opacity: 1;border-color:rgb(115 115 115 / var(--tw-border-opacity, 1))}.hover\:border-neutral-600:hover{--tw-border-opacity: 1;border-color:rgb(82 82 82 / var(--tw-border-opacity, 1))}.hover\:border-neutral-700:hover{--tw-border-opacity: 1;border-color:rgb(64 64 64 / var(--tw-border-opacity, 1))}.hover\:border-neutral-800:hover{--tw-border-opacity: 1;border-color:rgb(38 38 38 / var(--tw-border-opacity, 1))}.hover\:border-studio-accent\/40:hover{border-color:#3ce6ac66}.hover\:border-studio-accent\/50:hover{border-color:#3ce6ac80}.hover\:bg-black\/60:hover{background-color:#0009}.hover\:bg-black\/70:hover{background-color:#000000b3}.hover\:bg-emerald-500\/10:hover{background-color:#10b9811a}.hover\:bg-neutral-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 229 229 / var(--tw-bg-opacity, 1))}.hover\:bg-neutral-600:hover{--tw-bg-opacity: 1;background-color:rgb(82 82 82 / var(--tw-bg-opacity, 1))}.hover\:bg-neutral-700\/50:hover{background-color:#40404080}.hover\:bg-neutral-800:hover{--tw-bg-opacity: 1;background-color:rgb(38 38 38 / var(--tw-bg-opacity, 1))}.hover\:bg-neutral-800\/30:hover{background-color:#2626264d}.hover\:bg-neutral-800\/50:hover{background-color:#26262680}.hover\:bg-neutral-800\/70:hover{background-color:#262626b3}.hover\:bg-neutral-900:hover{--tw-bg-opacity: 1;background-color:rgb(23 23 23 / var(--tw-bg-opacity, 1))}.hover\:bg-red-500:hover{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.hover\:bg-red-600:hover{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.hover\:bg-red-800\/60:hover{background-color:#991b1b99}.hover\:bg-red-900\/30:hover{background-color:#7f1d1d4d}.hover\:bg-studio-accent:hover{--tw-bg-opacity: 1;background-color:rgb(60 230 172 / var(--tw-bg-opacity, 1))}.hover\:bg-studio-accent\/25:hover{background-color:#3ce6ac40}.hover\:bg-studio-accent\/80:hover{background-color:#3ce6accc}.hover\:bg-white\/25:hover{background-color:#ffffff40}.hover\:bg-white\/\[0\.04\]:hover{background-color:#ffffff0a}.hover\:bg-white\/\[0\.06\]:hover{background-color:#ffffff0f}.hover\:text-amber-300:hover{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.hover\:text-green-400:hover{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.hover\:text-neutral-100:hover{--tw-text-opacity: 1;color:rgb(245 245 245 / var(--tw-text-opacity, 1))}.hover\:text-neutral-200:hover{--tw-text-opacity: 1;color:rgb(229 229 229 / var(--tw-text-opacity, 1))}.hover\:text-neutral-300:hover{--tw-text-opacity: 1;color:rgb(212 212 212 / var(--tw-text-opacity, 1))}.hover\:text-neutral-400:hover{--tw-text-opacity: 1;color:rgb(163 163 163 / var(--tw-text-opacity, 1))}.hover\:text-orange-300:hover{--tw-text-opacity: 1;color:rgb(253 186 116 / var(--tw-text-opacity, 1))}.hover\:text-red-300:hover{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.hover\:text-red-400:hover{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.hover\:text-studio-accent:hover{--tw-text-opacity: 1;color:rgb(60 230 172 / var(--tw-text-opacity, 1))}.hover\:text-white:hover{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.hover\:text-white\/80:hover{color:#fffc}.hover\:opacity-100:hover{opacity:1}.hover\:opacity-80:hover{opacity:.8}.hover\:ring-1:hover{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.hover\:ring-white\/30:hover{--tw-ring-color: rgb(255 255 255 / .3)}.hover\:brightness-110:hover{--tw-brightness: brightness(1.1);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\:border-\[\#3CE6AC\]:focus{--tw-border-opacity: 1;border-color:rgb(60 230 172 / var(--tw-border-opacity, 1))}.focus\:border-\[\#f5a400\]:focus{--tw-border-opacity: 1;border-color:rgb(245 164 0 / var(--tw-border-opacity, 1))}.focus\:border-neutral-600:focus{--tw-border-opacity: 1;border-color:rgb(82 82 82 / var(--tw-border-opacity, 1))}.focus\:border-neutral-700:focus{--tw-border-opacity: 1;border-color:rgb(64 64 64 / var(--tw-border-opacity, 1))}.focus\:border-studio-accent:focus{--tw-border-opacity: 1;border-color:rgb(60 230 172 / var(--tw-border-opacity, 1))}.focus\:border-studio-accent\/40:focus{border-color:#3ce6ac66}.focus\:border-studio-accent\/60:focus{border-color:#3ce6ac99}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-\[\#3ce6ac\]:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(60 230 172 / var(--tw-ring-opacity, 1))}.focus\:ring-\[\#f5a400\]\/40:focus{--tw-ring-color: rgb(245 164 0 / .4)}.focus\:ring-studio-accent\/30:focus{--tw-ring-color: rgb(60 230 172 / .3)}.focus\:ring-studio-accent\/40:focus{--tw-ring-color: rgb(60 230 172 / .4)}.focus-visible\:rounded:focus-visible{border-radius:.25rem}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-1:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-studio-accent\/50:focus-visible{--tw-ring-color: rgb(60 230 172 / .5)}.focus-visible\:ring-white\/30:focus-visible{--tw-ring-color: rgb(255 255 255 / .3)}.active\:scale-\[0\.97\]:active{--tw-scale-x: .97;--tw-scale-y: .97;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:scale-\[0\.98\]:active{--tw-scale-x: .98;--tw-scale-y: .98;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.active\:cursor-grabbing:active{cursor:grabbing}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-default:disabled{cursor:default}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:border-neutral-800:disabled{--tw-border-opacity: 1;border-color:rgb(38 38 38 / var(--tw-border-opacity, 1))}.disabled\:text-neutral-600:disabled{--tw-text-opacity: 1;color:rgb(82 82 82 / var(--tw-text-opacity, 1))}.disabled\:text-neutral-700:disabled{--tw-text-opacity: 1;color:rgb(64 64 64 / var(--tw-text-opacity, 1))}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.group:hover .group-hover\:block{display:block}.group:hover .group-hover\:scale-125{--tw-scale-x: 1.25;--tw-scale-y: 1.25;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group\/card:hover .group-hover\/card\:opacity-100{opacity:1}@media(min-width:640px){.sm\:inline{display:inline}}.\[\&\:\:-webkit-slider-thumb\]\:h-3::-webkit-slider-thumb{height:.75rem}.\[\&\:\:-webkit-slider-thumb\]\:w-3::-webkit-slider-thumb{width:.75rem}.\[\&\:\:-webkit-slider-thumb\]\:appearance-none::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none}.\[\&\:\:-webkit-slider-thumb\]\:rounded-full::-webkit-slider-thumb{border-radius:9999px}.\[\&\:\:-webkit-slider-thumb\]\:bg-yellow-400::-webkit-slider-thumb{--tw-bg-opacity: 1;background-color:rgb(250 204 21 / var(--tw-bg-opacity, 1))}