issue-sticker 0.11.0 → 0.12.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.
@@ -15,35 +15,92 @@ var __privateWrapper = (obj, member, setter, getter) => ({
15
15
  }
16
16
  });
17
17
  var _focused, _cleanup, _setup, _b, _provider, _providerCalled, _c, _online, _cleanup2, _setup2, _d, _gcTimeout, _e, _queryType, _initialState, _revertState, _cache, _client, _retryer, _defaultOptions, _abortSignalConsumed, _Query_instances, isInitialPausedFetch_fn, dispatch_fn, _f, _client2, _currentQuery, _currentQueryInitialState, _currentResult, _currentResultState, _currentResultOptions, _currentThenable, _selectError, _selectFn, _selectResult, _lastQueryWithDefinedData, _staleTimeoutId, _refetchIntervalId, _currentRefetchInterval, _trackedProps, _QueryObserver_instances, executeFetch_fn, updateStaleTimeout_fn, computeRefetchInterval_fn, updateRefetchInterval_fn, updateTimers_fn, clearStaleTimeout_fn, clearRefetchInterval_fn, updateQuery_fn, notify_fn, _g, _client3, _observers, _mutationCache, _retryer2, _Mutation_instances, dispatch_fn2, _h, _mutations, _scopes, _mutationId, _i, _client4, _currentResult2, _currentMutation, _mutateOptions, _MutationObserver_instances, updateResult_fn, notify_fn2, _j, _queries, _k, _queryCache, _mutationCache2, _defaultOptions2, _queryDefaults, _mutationDefaults, _mountCount, _unsubscribeFocus, _unsubscribeOnline, _l, _m;
18
- import { O as OVERLAY_LAYER_INDEX, c as createLucideIcon$1, d as usePortalContainer, a as cn$1, e as OVERLAY_LAYER, s as stopEscapePropagation, P as Presence, f as Primitive, g as composeEventHandlers, h as useDismissableLayerSurface, i as useComposedRefs$1, j as Portal$1, k as createContextScope, l as createSlot, D as DismissableLayer, m as useControllableState, n as useId$1, o as useLayoutEffect2, p as useCallbackRef, u as ungzip_1, q as PortalContainerProvider, r as registerThree } from "./three-DQdLNs7v.js";
19
- import { A as trimLogBackupPayload, B as createSafeLogBackup, D as getLogBackupSessionId, N as NetworkCollector, C as ConsoleCollector, W as WebSocketCollector, E as createIndexedDbLogBackup, b as buildJiraCreateFields, P as Popover, F as PopoverTrigger, G as Input, H as PopoverContent, L as Label, J as Select, K as SelectTrigger, M as SelectValue, O as SelectContent, Q as SelectItem, R as JIRA_ISSUE_TYPE_VALUE_KEY, T as getJiraMetadata, U as buildJiraIssueFields, V as getJiraIssueTypeLabel, X as Button, Y as Root2$2, Z as Trigger$2, _ as ChevronDown, $ as Portal, a0 as Content2$1, a1 as Check, a2 as X$1, a3 as DatePicker, e as buildNotionCreateFields, a4 as getNotionPageMetadata, a5 as buildNotionFieldViews, c as captureWithModernScreenshot, p as pristineFetch, d as directUploadToSignedUrl, a6 as DirectUploadError, a7 as toast, a8 as getSnapshot, a9 as subscribe$1, a as uploadSignedMediaWithApi, t as sanitizeString, aa as getRegisteredUploadId, f as buildGuestOwnerQuery, j as devLogger, x as getCurrentPageUrl, ab as ChevronRight, ac as ReactRemoveScroll, ad as hideOthers, ae as useFocusGuards, af as FocusScope, ag as getExposedJiraFields, ah as isJiraFieldExposed, ai as normalizeExposedJiraFields, z as preloadModernScreenshot, g as getElementPosition, u as uploadScreenshotDataUrls, k as filterExcludeServiceRelatedLogs, l as filterExcludeServiceRelatedConsoleLogs, s as selectNetworkLogsForSubmit, m as compactNetworkLogsForTransport, n as CONSOLE_LOG_SUBMIT_LIMIT, o as buildExternalUserPayload, v as serializeSocketTranscript, w as uploadSocketTranscript, q as shrinkNetworkLogsToFit, r as measureJsonBytes, i as buildIssueIntegrationsPayload, y as SessionReplayCaptureController, aj as resolveJiraIssueTypeId, ak as pickJiraIssueTypeFields, al as switchJiraIssueType, am as getPrimaryJiraMapping, an as createCollection, ao as useDirection, ap as getPrimaryNotionMapping, aq as buttonVariants, ar as TEST_ATTR_KEYS, as as jaccard, at as textSimilarity, au as collectHeadings, av as buildElementLocator, aw as normalizeForCompare, ax as CONTAINER_SELECTOR, ay as safeRole, az as safeAccessibleName, aA as sameDigitGroups, aB as labelSimilarityKeepingDigits, aC as landmarkRole, aD as findElementBySelector, aE as findElementByXPath, S as ScreenRecordingController, h as composeIssueFilterGroups, aF as OnboardingProvider, aG as useOnboardingTarget, aH as useOnboardingFlow, aI as PopoverAnchor } from "./externalUserPayload-BbOEmKZD.js";
18
+ import { O as OVERLAY_LAYER_INDEX, c as createLucideIcon$1, d as usePortalContainer, a as cn$1, e as OVERLAY_LAYER, s as stopEscapePropagation, f as useControllableState, g as useId$1, P as Presence, h as Primitive, i as composeEventHandlers, j as useDismissableLayerSurface, k as useComposedRefs$1, l as Portal$1, m as createContextScope, n as createSlot, D as DismissableLayer, o as useLayoutEffect2, p as useCallbackRef, u as ungzip_1, q as PortalContainerProvider, r as registerThree } from "./three-B228j4M6.js";
19
+ import { L as toast, M as trimLogBackupPayload, O as createSafeLogBackup, P as getLogBackupSessionId, N as NetworkCollector, C as ConsoleCollector, W as WebSocketCollector, Q as createIndexedDbLogBackup, e as buildJiraCreateFields, R as Popover, T as PopoverTrigger, U as Input, X as PopoverContent, Y as Label, Z as Select, _ as SelectTrigger, $ as SelectValue, a0 as SelectContent, a1 as SelectItem, a2 as JIRA_ISSUE_TYPE_VALUE_KEY, a3 as getJiraMetadata, a4 as buildJiraIssueFields, a5 as getJiraIssueTypeLabel, a6 as Button, a7 as Root2$2, a8 as Trigger$2, a9 as ChevronDown, aa as Portal, ab as Content2$1, ac as Check, ad as X$1, ae as DatePicker, f as buildNotionCreateFields, af as getNotionPageMetadata, ag as buildNotionFieldViews, b as captureWithModernScreenshot, p as pristineFetch, d as directUploadToSignedUrl, ah as DirectUploadError, a as uploadSignedMediaWithApi, v as sanitizeString, ai as getRegisteredUploadId, h as buildGuestOwnerQuery, z as createIssueUploadQueues, G as loadTusClient, H as createIndexedDbPendingUploadStore, K as createMediaUploadApi, J as ATTACHMENT_UPLOAD_DB_NAME, V as VIDEO_UPLOAD_DB_NAME, aj as getSnapshot, ak as subscribe$1, k as devLogger, y as getCurrentPageUrl, al as ChevronRight, am as ReactRemoveScroll, an as hideOthers, ao as useFocusGuards, ap as FocusScope, aq as createShadowDismissRoot, ar as getExposedJiraFields, as as isJiraFieldExposed, at as normalizeExposedJiraFields, c as captureViewportWithElementCrop, B as preloadModernScreenshot, g as getElementPosition, u as uploadScreenshotDataUrls, l as filterExcludeServiceRelatedLogs, m as filterExcludeServiceRelatedConsoleLogs, s as selectNetworkLogsForSubmit, n as compactNetworkLogsForTransport, o as CONSOLE_LOG_SUBMIT_LIMIT, q as buildExternalUserPayload, w as collectAttachmentUploads, x as hasReplayUpload, r as shrinkNetworkLogsToFit, t as measureJsonBytes, j as buildIssueIntegrationsPayload, D as enqueueIssueUploads, E as normalizeUploadMimeType, A as SessionReplayCaptureController, au as resolveJiraIssueTypeId, av as pickJiraIssueTypeFields, aw as switchJiraIssueType, ax as getPrimaryJiraMapping, ay as createCollection, az as useDirection, aA as useShadowOutsideDismiss, aB as getPrimaryNotionMapping, aC as buttonVariants, aD as TEST_ATTR_KEYS, aE as jaccard, aF as textSimilarity, aG as collectHeadings, aH as buildElementLocator, aI as normalizeForCompare, aJ as CONTAINER_SELECTOR, aK as safeRole, aL as safeAccessibleName, aM as sameDigitGroups, aN as labelSimilarityKeepingDigits, aO as landmarkRole, aP as findElementBySelector, aQ as findElementByXPath, S as ScreenRecordingController, i as composeIssueFilterGroups, aR as OnboardingProvider, aS as useOnboardingTarget, aT as useOnboardingFlow, aU as PopoverAnchor } from "./externalUserPayload-DWcXyz2U.js";
20
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
20
21
  import * as React from "react";
21
22
  import { useRef, useState, useEffect, useId, useLayoutEffect, useCallback, forwardRef, createElement, createContext, useContext, Component, Suspense, useInsertionEffect, useMemo, Children, isValidElement, Fragment as Fragment$1, useSyncExternalStore, useDeferredValue } from "react";
22
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
23
23
  import { createRoot } from "react-dom/client";
24
24
  import { createPortal } from "react-dom";
25
- import { T as TooltipProvider, a as Tooltip, b as TooltipTrigger, c as TooltipContent } from "./tooltip-DSCAsWIp.js";
26
- function readReleaseMarker() {
27
- try {
28
- const g = globalThis.__ISSUE_STICKER_RELEASE__;
29
- if (g && typeof g.id === "string" && g.id.length > 0) {
30
- return {
31
- release: g.id,
32
- release_source: typeof g.source === "string" && g.source.length > 0 ? g.source : "global"
33
- };
34
- }
35
- if (typeof document !== "undefined") {
36
- const meta = document.querySelector('meta[name="issue-sticker:release"]');
37
- const content2 = meta == null ? void 0 : meta.getAttribute("content");
38
- if (content2 && content2.length > 0) {
39
- return { release: content2, release_source: "meta" };
25
+ import { T as TooltipProvider, a as Tooltip, b as TooltipTrigger, c as TooltipContent } from "./tooltip-CT7e9xbU.js";
26
+ import { g as getDefaultExportFromCjs } from "./_commonjsHelpers-DWwsNxpa.js";
27
+ const ISSUE_STICKER_REPORT_FORM_CLASS = "issue-sticker-report-form";
28
+ function summarizeVideoUploads(states) {
29
+ if (states.length === 0) return void 0;
30
+ const remaining = states.filter((state) => state.status !== "failed");
31
+ const current = states.find((state) => state.status === "uploading");
32
+ const percent2 = current && current.bytesTotal > 0 ? Math.floor(current.bytesSent / current.bytesTotal * 100) : 0;
33
+ return { percent: percent2, count: remaining.length, failed: remaining.length === 0 };
34
+ }
35
+ const VIDEO_UPLOAD_COPY = {
36
+ created: "이슈가 생성되었습니다. 영상 업로드가 끝나면 이슈에 첨부됩니다.",
37
+ resumed: (count) => `업로드하지 못한 영상 ${count}개를 이어서 업로드합니다.`
38
+ };
39
+ function visibleKinds(kinds) {
40
+ const video = kinds.includes("video");
41
+ const replay = kinds.includes("replay");
42
+ if (video && replay) return "both";
43
+ if (video) return "video";
44
+ return replay ? "replay" : null;
45
+ }
46
+ const ISSUE_UPLOAD_COPY = {
47
+ failedMessage: "네트워크 연결을 확인한 뒤 다시 시도해주세요.",
48
+ retry: "다시 시도",
49
+ failedTitle: {
50
+ video: "영상 업로드 실패",
51
+ replay: "세션 리플레이 업로드 실패",
52
+ both: "영상·세션 리플레이 업로드 실패"
53
+ },
54
+ aborted: {
55
+ video: "영상을 업로드하지 못했습니다.",
56
+ replay: "세션 리플레이를 업로드하지 못했습니다.",
57
+ both: "영상과 세션 리플레이를 업로드하지 못했습니다."
58
+ },
59
+ /** 완료는 영상이 있을 때만 알린다. 리플레이만 붙은 경우의 문구는 없다. */
60
+ attached: {
61
+ video: "영상이 이슈에 첨부되었습니다.",
62
+ both: "영상과 세션 리플레이가 이슈에 첨부되었습니다."
63
+ }
64
+ };
65
+ function createIssueUploadToaster() {
66
+ const failureToastIds = /* @__PURE__ */ new Map();
67
+ return {
68
+ show(notice, retry) {
69
+ const previous2 = failureToastIds.get(notice.issueId);
70
+ if (previous2 !== void 0) {
71
+ toast.dismiss(previous2);
72
+ failureToastIds.delete(notice.issueId);
73
+ }
74
+ const failed = visibleKinds(notice.failed);
75
+ if (failed) {
76
+ const id2 = toast.error(ISSUE_UPLOAD_COPY.failedMessage, {
77
+ title: ISSUE_UPLOAD_COPY.failedTitle[failed],
78
+ duration: 0,
79
+ action: {
80
+ label: ISSUE_UPLOAD_COPY.retry,
81
+ onClick: () => {
82
+ failureToastIds.delete(notice.issueId);
83
+ retry(notice.issueId);
84
+ }
85
+ }
86
+ });
87
+ failureToastIds.set(notice.issueId, id2);
88
+ return;
89
+ }
90
+ const aborted = visibleKinds(notice.aborted);
91
+ if (aborted) {
92
+ toast.error(ISSUE_UPLOAD_COPY.aborted[aborted], {
93
+ title: ISSUE_UPLOAD_COPY.failedTitle[aborted]
94
+ });
95
+ return;
96
+ }
97
+ const completed = visibleKinds(notice.completed);
98
+ if (completed === "video" || completed === "both") {
99
+ toast.success(ISSUE_UPLOAD_COPY.attached[completed]);
40
100
  }
41
101
  }
42
- } catch {
43
- }
44
- return null;
102
+ };
45
103
  }
46
- const ISSUE_STICKER_REPORT_FORM_CLASS = "issue-sticker-report-form";
47
104
  const DEFAULT_DEBOUNCE_MS = 1e3;
48
105
  function bindLogBackup(options) {
49
106
  const { store, sessionId, snapshot, restoreInto } = options;
@@ -523,17 +580,105 @@ const HOST_POINTER_GUARD_EVENTS = [
523
580
  "touchstart",
524
581
  "touchend"
525
582
  ];
583
+ const HOST_CAPTURE_GUARD_EVENTS = [
584
+ "pointerdown",
585
+ "mousedown",
586
+ "click",
587
+ "dblclick",
588
+ "auxclick",
589
+ "contextmenu"
590
+ ];
591
+ const CLICK_EVENTS = /* @__PURE__ */ new Set(["click", "dblclick", "auxclick", "contextmenu"]);
592
+ const ACTIVATION_INPUT_TYPES = /* @__PURE__ */ new Set([
593
+ "checkbox",
594
+ "radio",
595
+ "submit",
596
+ "reset",
597
+ "image",
598
+ "file",
599
+ "color",
600
+ "date",
601
+ "datetime-local",
602
+ "month",
603
+ "time",
604
+ "week"
605
+ ]);
606
+ function hasActivationBehavior(node2) {
607
+ if (!(node2 instanceof Element)) return false;
608
+ if (node2.matches("a[href], area[href], label, summary, [popovertarget], [commandfor]")) {
609
+ return true;
610
+ }
611
+ if (node2 instanceof HTMLButtonElement) return node2.type !== "button" && node2.form !== null;
612
+ if (node2 instanceof HTMLInputElement) return ACTIVATION_INPUT_TYPES.has(node2.type);
613
+ return false;
614
+ }
615
+ function cloneInsideShadow(event) {
616
+ const init = {
617
+ bubbles: event.bubbles,
618
+ cancelable: event.cancelable,
619
+ composed: false,
620
+ view: event.view,
621
+ detail: event.detail,
622
+ screenX: event.screenX,
623
+ screenY: event.screenY,
624
+ clientX: event.clientX,
625
+ clientY: event.clientY,
626
+ movementX: event.movementX,
627
+ movementY: event.movementY,
628
+ button: event.button,
629
+ buttons: event.buttons,
630
+ relatedTarget: event.relatedTarget,
631
+ ctrlKey: event.ctrlKey,
632
+ shiftKey: event.shiftKey,
633
+ altKey: event.altKey,
634
+ metaKey: event.metaKey
635
+ };
636
+ if (typeof PointerEvent !== "undefined" && event instanceof PointerEvent) {
637
+ return new PointerEvent(event.type, {
638
+ ...init,
639
+ pointerId: event.pointerId,
640
+ pointerType: event.pointerType,
641
+ isPrimary: event.isPrimary,
642
+ width: event.width,
643
+ height: event.height,
644
+ pressure: event.pressure,
645
+ tangentialPressure: event.tangentialPressure,
646
+ tiltX: event.tiltX,
647
+ tiltY: event.tiltY,
648
+ twist: event.twist
649
+ });
650
+ }
651
+ return new MouseEvent(event.type, init);
652
+ }
526
653
  function attachHostPointerGuard(shadowRoot) {
654
+ const view = shadowRoot.ownerDocument.defaultView;
527
655
  const stopLeakingToPage = (event) => {
528
656
  event.stopPropagation();
529
657
  };
658
+ const forwardInsideWidget = (event) => {
659
+ const path2 = event.composedPath();
660
+ const origin = path2[0];
661
+ if (!(origin instanceof Node) || origin.getRootNode() !== shadowRoot) return;
662
+ if (CLICK_EVENTS.has(event.type)) {
663
+ const insideWidget = path2.slice(0, path2.indexOf(shadowRoot));
664
+ if (insideWidget.some(hasActivationBehavior)) return;
665
+ }
666
+ event.stopImmediatePropagation();
667
+ if (!origin.dispatchEvent(cloneInsideShadow(event))) event.preventDefault();
668
+ };
530
669
  HOST_POINTER_GUARD_EVENTS.forEach((type) => {
531
670
  shadowRoot.addEventListener(type, stopLeakingToPage);
532
671
  });
672
+ HOST_CAPTURE_GUARD_EVENTS.forEach((type) => {
673
+ view == null ? void 0 : view.addEventListener(type, forwardInsideWidget, true);
674
+ });
533
675
  return () => {
534
676
  HOST_POINTER_GUARD_EVENTS.forEach((type) => {
535
677
  shadowRoot.removeEventListener(type, stopLeakingToPage);
536
678
  });
679
+ HOST_CAPTURE_GUARD_EVENTS.forEach((type) => {
680
+ view == null ? void 0 : view.removeEventListener(type, forwardInsideWidget, true);
681
+ });
537
682
  };
538
683
  }
539
684
  const HOST_INTERACTION_GUARD_EVENTS = [
@@ -551,16 +696,32 @@ const HOST_INTERACTION_GUARD_EVENTS = [
551
696
  "dragend"
552
697
  ];
553
698
  function attachHostInteractionGuard(shadowRoot) {
699
+ const host = shadowRoot.host;
700
+ const view = shadowRoot.ownerDocument.defaultView;
554
701
  const stopLeakingToPage = (event) => {
555
702
  event.stopPropagation();
556
703
  };
704
+ const hideFocusLeavingForWidget = (event) => {
705
+ if (event.relatedTarget !== host) return;
706
+ if (event.composedPath().includes(host)) return;
707
+ event.stopPropagation();
708
+ };
709
+ const hideWidgetFocus = (event) => {
710
+ if (event.composedPath().includes(host)) event.stopImmediatePropagation();
711
+ };
557
712
  HOST_INTERACTION_GUARD_EVENTS.forEach((type) => {
558
713
  shadowRoot.addEventListener(type, stopLeakingToPage, { passive: true });
559
714
  });
715
+ view == null ? void 0 : view.addEventListener("focusout", hideFocusLeavingForWidget, true);
716
+ view == null ? void 0 : view.addEventListener("blur", hideFocusLeavingForWidget, true);
717
+ view == null ? void 0 : view.addEventListener("focus", hideWidgetFocus, true);
560
718
  return () => {
561
719
  HOST_INTERACTION_GUARD_EVENTS.forEach((type) => {
562
720
  shadowRoot.removeEventListener(type, stopLeakingToPage);
563
721
  });
722
+ view == null ? void 0 : view.removeEventListener("focusout", hideFocusLeavingForWidget, true);
723
+ view == null ? void 0 : view.removeEventListener("blur", hideFocusLeavingForWidget, true);
724
+ view == null ? void 0 : view.removeEventListener("focus", hideWidgetFocus, true);
564
725
  };
565
726
  }
566
727
  const RUNTIME_OWNER_MARKER_KEY = "__issueStickerRuntimeOwner";
@@ -1482,7 +1643,7 @@ function MultiSelect({
1482
1643
  const contentRef = React.useRef(null);
1483
1644
  const portalContainer = usePortalContainer();
1484
1645
  React.useEffect(() => {
1485
- var _a, _b2;
1646
+ var _a, _b2, _c2, _d2;
1486
1647
  if (!open) {
1487
1648
  return;
1488
1649
  }
@@ -1493,8 +1654,12 @@ function MultiSelect({
1493
1654
  }
1494
1655
  setOpen(false);
1495
1656
  };
1496
- ownerDocument.addEventListener("click", closeOnOutsideClick, true);
1497
- return () => ownerDocument.removeEventListener("click", closeOnOutsideClick, true);
1657
+ const scopes = /* @__PURE__ */ new Set([
1658
+ ownerDocument,
1659
+ ((_c2 = contentRef.current) == null ? void 0 : _c2.getRootNode()) ?? ((_d2 = triggerRef.current) == null ? void 0 : _d2.getRootNode()) ?? ownerDocument
1660
+ ]);
1661
+ scopes.forEach((scope) => scope.addEventListener("click", closeOnOutsideClick, true));
1662
+ return () => scopes.forEach((scope) => scope.removeEventListener("click", closeOnOutsideClick, true));
1498
1663
  }, [open]);
1499
1664
  const emitChange = (next) => {
1500
1665
  onValueChange == null ? void 0 : onValueChange(next);
@@ -5127,6 +5292,612 @@ class WebPlatform {
5127
5292
  this.eventBus = eventBus;
5128
5293
  }
5129
5294
  }
5295
+ function isHttpStatusError(error) {
5296
+ return typeof error === "object" && error !== null && typeof error.status === "number";
5297
+ }
5298
+ const MAX_RETRIES = 3;
5299
+ const MAX_BACKOFF_MS = 3e4;
5300
+ const MAX_RETRY_AFTER_MS = 6e4;
5301
+ function parseRetryAfterMs(value, now2 = Date.now()) {
5302
+ const trimmed = value == null ? void 0 : value.trim();
5303
+ if (!trimmed) return void 0;
5304
+ if (/^\d+$/.test(trimmed)) return Number(trimmed) * 1e3;
5305
+ const date = Date.parse(trimmed);
5306
+ return Number.isNaN(date) ? void 0 : Math.max(0, date - now2);
5307
+ }
5308
+ function retryAfterMsOf(response) {
5309
+ var _a;
5310
+ return parseRetryAfterMs((_a = response.headers) == null ? void 0 : _a.get("Retry-After"));
5311
+ }
5312
+ function jitteredBackoffMs(failureCount, capMs = MAX_BACKOFF_MS) {
5313
+ return Math.random() * Math.min(capMs, 1e3 * 2 ** failureCount);
5314
+ }
5315
+ function statusOf(error) {
5316
+ return isHttpStatusError(error) ? error.status : 0;
5317
+ }
5318
+ function retryAfterOf(error) {
5319
+ return isHttpStatusError(error) ? error.retryAfterMs : void 0;
5320
+ }
5321
+ function queryRetry(failureCount, error) {
5322
+ const status = statusOf(error);
5323
+ if (status === 429) {
5324
+ const retryAfterMs = retryAfterOf(error);
5325
+ return failureCount < 1 && retryAfterMs !== void 0 && retryAfterMs <= MAX_RETRY_AFTER_MS;
5326
+ }
5327
+ if (status >= 400 && status < 500 && status !== 408) return false;
5328
+ return failureCount < MAX_RETRIES;
5329
+ }
5330
+ function queryRetryDelay(failureCount, error) {
5331
+ const retryAfterMs = retryAfterOf(error);
5332
+ return retryAfterMs !== void 0 ? Math.min(retryAfterMs, MAX_RETRY_AFTER_MS) : jitteredBackoffMs(failureCount);
5333
+ }
5334
+ function readApiBaseUrlFromEnv() {
5335
+ if (typeof process !== "undefined" && process.env && Object.prototype.hasOwnProperty.call(process.env, "VITE_API_BASE_URL")) {
5336
+ const processValue = process.env.VITE_API_BASE_URL;
5337
+ if (typeof processValue === "string") {
5338
+ const trimmed = processValue.trim();
5339
+ return trimmed.length > 0 && trimmed !== "undefined" ? trimmed : void 0;
5340
+ }
5341
+ }
5342
+ const viteValue = "https://api.issuesticker.com";
5343
+ {
5344
+ const trimmed = viteValue.trim();
5345
+ return trimmed.length > 0 && trimmed !== "undefined" ? trimmed : void 0;
5346
+ }
5347
+ }
5348
+ let tokenMemoryCache = null;
5349
+ let apiKeyCache = null;
5350
+ let sdkMode = null;
5351
+ let memberTokenProvider = null;
5352
+ function normalizeToken(token) {
5353
+ const trimmed = token.trim();
5354
+ if (trimmed.toLowerCase().startsWith("bearer ")) {
5355
+ return trimmed.slice(7).trim();
5356
+ }
5357
+ return trimmed;
5358
+ }
5359
+ function createMemberAuthRequiredError(message = "멤버 로그인이 필요합니다.") {
5360
+ return new ApiError(message, 401, {
5361
+ success: false,
5362
+ error: {
5363
+ code: "MEMBER_AUTH_REQUIRED",
5364
+ message
5365
+ }
5366
+ });
5367
+ }
5368
+ async function resolveAuthorizationHeader(options) {
5369
+ if (sdkMode === "public" || sdkMode === null) {
5370
+ if (apiKeyCache) {
5371
+ return `ApiKey ${apiKeyCache}`;
5372
+ }
5373
+ return void 0;
5374
+ }
5375
+ if (sdkMode === "member" && memberTokenProvider) {
5376
+ const token2 = await memberTokenProvider({
5377
+ forceRefresh: options == null ? void 0 : options.forceRefreshMemberToken,
5378
+ reason: (options == null ? void 0 : options.memberRefreshReason) || "missing"
5379
+ });
5380
+ if (!token2) {
5381
+ throw createMemberAuthRequiredError();
5382
+ }
5383
+ return `Bearer ${token2}`;
5384
+ }
5385
+ const token = tokenMemoryCache ? normalizeToken(tokenMemoryCache) : null;
5386
+ if (token) {
5387
+ return `Bearer ${token}`;
5388
+ }
5389
+ return void 0;
5390
+ }
5391
+ const isDemoMode = false;
5392
+ function getApiBaseUrl() {
5393
+ const baseUrl = readApiBaseUrlFromEnv();
5394
+ if (!baseUrl) {
5395
+ throw new ApiError(
5396
+ "API 서버 주소(VITE_API_BASE_URL)가 설정되지 않았습니다. SDK 빌드/환경을 확인해주세요.",
5397
+ 0
5398
+ );
5399
+ }
5400
+ if (!/^https?:\/\//.test(baseUrl)) {
5401
+ throw new ApiError(`API 서버 주소(VITE_API_BASE_URL)가 올바르지 않습니다: ${baseUrl}`, 0);
5402
+ }
5403
+ return baseUrl.replace(/\/+$/, "");
5404
+ }
5405
+ function setApiKey(key) {
5406
+ apiKeyCache = key;
5407
+ }
5408
+ function setSdkMode(mode) {
5409
+ sdkMode = mode;
5410
+ }
5411
+ function getSdkMode() {
5412
+ return sdkMode;
5413
+ }
5414
+ function setMemberTokenProvider(provider) {
5415
+ memberTokenProvider = provider;
5416
+ }
5417
+ function assertRelativeApiEndpoint(endpoint) {
5418
+ if (!endpoint.startsWith("/") || endpoint.startsWith("//")) {
5419
+ throw new ApiError(`API endpoint는 백엔드 상대 경로여야 합니다: ${endpoint}`, 0);
5420
+ }
5421
+ }
5422
+ function buildApiUrl(endpoint) {
5423
+ assertRelativeApiEndpoint(endpoint);
5424
+ return `${getApiBaseUrl()}${endpoint}`;
5425
+ }
5426
+ async function saveToken(token) {
5427
+ const normalizedToken = normalizeToken(token);
5428
+ tokenMemoryCache = normalizedToken;
5429
+ }
5430
+ async function clearToken() {
5431
+ tokenMemoryCache = null;
5432
+ }
5433
+ class ApiError extends Error {
5434
+ constructor(message, status, data, retryAfterMs) {
5435
+ super(message);
5436
+ this.status = status;
5437
+ this.data = data;
5438
+ this.retryAfterMs = retryAfterMs;
5439
+ this.name = "ApiError";
5440
+ }
5441
+ }
5442
+ function extractErrorMessage(error) {
5443
+ if (!error) return void 0;
5444
+ if (typeof error === "string") return error;
5445
+ return error.message || error.code || JSON.stringify(error);
5446
+ }
5447
+ async function requestResponse(endpoint, options = {}) {
5448
+ const { body, skipAuth = false, headers: customHeaders, ...rest } = options;
5449
+ const headers = {
5450
+ "Content-Type": "application/json",
5451
+ "x-client-info": "issue-sticker-sdk",
5452
+ ...customHeaders || {}
5453
+ };
5454
+ if (!skipAuth) {
5455
+ const authHeader = await resolveAuthorizationHeader();
5456
+ if (authHeader) {
5457
+ headers["Authorization"] = authHeader;
5458
+ }
5459
+ }
5460
+ const url = buildApiUrl(endpoint);
5461
+ const execute = (nextHeaders) => pristineFetch(url, {
5462
+ ...rest,
5463
+ headers: nextHeaders,
5464
+ body: body ? JSON.stringify(body) : void 0
5465
+ });
5466
+ let response = await execute(headers);
5467
+ let retriedMemberAuth = false;
5468
+ if (!skipAuth && response.status === 401 && sdkMode === "member" && memberTokenProvider) {
5469
+ const retryHeaders = { ...headers };
5470
+ try {
5471
+ const authHeader = await resolveAuthorizationHeader({
5472
+ forceRefreshMemberToken: true,
5473
+ memberRefreshReason: "unauthorized"
5474
+ });
5475
+ if (authHeader) {
5476
+ retryHeaders.Authorization = authHeader;
5477
+ retriedMemberAuth = true;
5478
+ response = await execute(retryHeaders);
5479
+ }
5480
+ } catch {
5481
+ throw new ApiError("인증이 만료되었습니다. 다시 로그인해주세요.", 401, {
5482
+ success: false,
5483
+ error: {
5484
+ code: "SESSION_EXPIRED",
5485
+ message: "인증이 만료되었습니다. 다시 로그인해주세요."
5486
+ }
5487
+ });
5488
+ }
5489
+ }
5490
+ if (retriedMemberAuth && response.status === 401) {
5491
+ throw new ApiError("인증이 만료되었습니다. 다시 로그인해주세요.", 401, {
5492
+ success: false,
5493
+ error: {
5494
+ code: "SESSION_EXPIRED",
5495
+ message: "인증이 만료되었습니다. 다시 로그인해주세요."
5496
+ }
5497
+ });
5498
+ }
5499
+ if (response.status === 204) {
5500
+ return { success: true };
5501
+ }
5502
+ const json = await response.json();
5503
+ if (!response.ok || !json.success) {
5504
+ throw new ApiError(
5505
+ extractErrorMessage(json.error) || json.message || `요청 실패: ${response.status}`,
5506
+ response.status,
5507
+ json,
5508
+ retryAfterMsOf(response)
5509
+ );
5510
+ }
5511
+ return json;
5512
+ }
5513
+ async function request(endpoint, options = {}) {
5514
+ const json = await requestResponse(endpoint, options);
5515
+ return json.data;
5516
+ }
5517
+ async function uploadRequest(endpoint, formData, skipAuth = false) {
5518
+ const headers = {
5519
+ "x-client-info": "issue-sticker-sdk"
5520
+ };
5521
+ if (!skipAuth) {
5522
+ const authHeader = await resolveAuthorizationHeader();
5523
+ if (authHeader) {
5524
+ headers["Authorization"] = authHeader;
5525
+ }
5526
+ }
5527
+ const url = buildApiUrl(endpoint);
5528
+ const execute = (nextHeaders) => pristineFetch(url, {
5529
+ method: "POST",
5530
+ headers: nextHeaders,
5531
+ body: formData
5532
+ });
5533
+ let response = await execute(headers);
5534
+ let retriedMemberAuth = false;
5535
+ if (!skipAuth && response.status === 401 && sdkMode === "member" && memberTokenProvider) {
5536
+ const retryHeaders = { ...headers };
5537
+ try {
5538
+ const authHeader = await resolveAuthorizationHeader({
5539
+ forceRefreshMemberToken: true,
5540
+ memberRefreshReason: "unauthorized"
5541
+ });
5542
+ if (authHeader) {
5543
+ retryHeaders.Authorization = authHeader;
5544
+ retriedMemberAuth = true;
5545
+ response = await execute(retryHeaders);
5546
+ }
5547
+ } catch {
5548
+ throw new ApiError("인증이 만료되었습니다. 다시 로그인해주세요.", 401, {
5549
+ success: false,
5550
+ error: {
5551
+ code: "SESSION_EXPIRED",
5552
+ message: "인증이 만료되었습니다. 다시 로그인해주세요."
5553
+ }
5554
+ });
5555
+ }
5556
+ }
5557
+ if (retriedMemberAuth && response.status === 401) {
5558
+ throw new ApiError("인증이 만료되었습니다. 다시 로그인해주세요.", 401, {
5559
+ success: false,
5560
+ error: {
5561
+ code: "SESSION_EXPIRED",
5562
+ message: "인증이 만료되었습니다. 다시 로그인해주세요."
5563
+ }
5564
+ });
5565
+ }
5566
+ const json = await response.json();
5567
+ if (!response.ok || !json.success) {
5568
+ throw new ApiError(
5569
+ extractErrorMessage(json.error) || json.message || `업로드 실패: ${response.status}`,
5570
+ response.status,
5571
+ json,
5572
+ retryAfterMsOf(response)
5573
+ );
5574
+ }
5575
+ return json.data;
5576
+ }
5577
+ async function directUpload(signedUrl, file, contentType) {
5578
+ try {
5579
+ await directUploadToSignedUrl(signedUrl, file, contentType);
5580
+ } catch (error) {
5581
+ if (error instanceof ApiError) {
5582
+ throw error;
5583
+ }
5584
+ if (error instanceof DirectUploadError) {
5585
+ throw new ApiError(error.message, error.status, error.data);
5586
+ }
5587
+ throw new ApiError(error instanceof Error ? error.message : "스토리지 업로드 실패", 0, error);
5588
+ }
5589
+ }
5590
+ const apiClient = {
5591
+ get(endpoint, options) {
5592
+ return request(endpoint, { ...options, method: "GET" });
5593
+ },
5594
+ getResponse(endpoint, options) {
5595
+ return requestResponse(endpoint, { ...options, method: "GET" });
5596
+ },
5597
+ post(endpoint, body, options) {
5598
+ return request(endpoint, { ...options, method: "POST", body });
5599
+ },
5600
+ put(endpoint, body, options) {
5601
+ return request(endpoint, { ...options, method: "PUT", body });
5602
+ },
5603
+ delete(endpoint, options) {
5604
+ return request(endpoint, { ...options, method: "DELETE" });
5605
+ },
5606
+ upload(endpoint, formData, skipAuth) {
5607
+ return uploadRequest(endpoint, formData, skipAuth);
5608
+ }
5609
+ };
5610
+ const queryClient = new QueryClient({
5611
+ defaultOptions: {
5612
+ queries: {
5613
+ staleTime: 5 * 60 * 1e3,
5614
+ // 5분
5615
+ gcTime: 10 * 60 * 1e3,
5616
+ // 10분 (v5에서는 cacheTime 대신 gcTime 사용)
5617
+ refetchOnWindowFocus: true,
5618
+ refetchOnReconnect: true,
5619
+ retry: queryRetry,
5620
+ retryDelay: queryRetryDelay
5621
+ },
5622
+ mutations: {
5623
+ retry: 0
5624
+ }
5625
+ }
5626
+ });
5627
+ async function uploadSignedMedia(file, mediaType, issueId) {
5628
+ return uploadSignedMediaWithApi(
5629
+ {
5630
+ post: (endpoint, body) => apiClient.post(endpoint, body),
5631
+ directUpload
5632
+ },
5633
+ file,
5634
+ mediaType,
5635
+ { issueId }
5636
+ );
5637
+ }
5638
+ function issuesEndpoint() {
5639
+ return "/api/sdk/issues";
5640
+ }
5641
+ function guestOwnerQuery() {
5642
+ var _a;
5643
+ const mode = getSdkMode();
5644
+ if (mode !== "public") return "";
5645
+ return buildGuestOwnerQuery(mode, (_a = SDKManager.getInstance().config.user) == null ? void 0 : _a.id);
5646
+ }
5647
+ let issuesCache = null;
5648
+ const CACHE_DURATION_MS = 30 * 1e3;
5649
+ const STICKER_PAGE_SIZE = 500;
5650
+ const STICKER_FETCH_LIMIT = 2e3;
5651
+ function getFilterKey(filters) {
5652
+ var _a;
5653
+ const normalizeArray = (value) => {
5654
+ if (value === "all" || !value) return "all";
5655
+ if (Array.isArray(value)) {
5656
+ return value.length === 0 ? "all" : [...value].sort().join(",");
5657
+ }
5658
+ return String(value);
5659
+ };
5660
+ const normalizeRecord = (record) => {
5661
+ if (!record) return "";
5662
+ const entries = Object.entries(record).map(([k, v]) => [k, [...v].sort()]).sort(([a], [b]) => a.localeCompare(b));
5663
+ return JSON.stringify(entries);
5664
+ };
5665
+ return JSON.stringify({
5666
+ sdkMode: getSdkMode() || "public",
5667
+ url: normalizeArray(filters.url),
5668
+ projectId: filters.projectId || "all",
5669
+ externalUserId: filters.externalUserId || "",
5670
+ search: ((_a = filters.search) == null ? void 0 : _a.trim()) || "",
5671
+ dateFrom: filters.dateFrom || "",
5672
+ dateTo: filters.dateTo || "",
5673
+ page: filters.page ?? 0,
5674
+ pageSize: filters.pageSize ?? 0,
5675
+ custom: normalizeRecord(filters.customFieldValues),
5676
+ jira: normalizeRecord(filters.jiraFieldValues),
5677
+ notion: normalizeRecord(filters.notionFieldValues),
5678
+ sortOrder: filters.sortOrder || ""
5679
+ });
5680
+ }
5681
+ function invalidateIssuesCache() {
5682
+ issuesCache = null;
5683
+ }
5684
+ function recordToFilterArray(record, keyFieldName) {
5685
+ if (!record) return null;
5686
+ const entries = Object.entries(record).filter(([, values]) => values.length > 0);
5687
+ if (entries.length === 0) return null;
5688
+ return entries.map(
5689
+ ([key, values]) => ({ [keyFieldName]: key, values })
5690
+ );
5691
+ }
5692
+ function buildFilterQueryParams(filters) {
5693
+ var _a;
5694
+ const params = new URLSearchParams();
5695
+ if (filters.projectId) {
5696
+ params.set("project_id", filters.projectId);
5697
+ }
5698
+ if (filters.url && filters.url !== "all") {
5699
+ if (Array.isArray(filters.url) && filters.url.length > 0) {
5700
+ params.set("url", filters.url.join(","));
5701
+ } else if (typeof filters.url === "string") {
5702
+ params.set("url", filters.url);
5703
+ }
5704
+ }
5705
+ const search2 = (_a = filters.search) == null ? void 0 : _a.trim();
5706
+ if (search2) {
5707
+ params.set("search", search2);
5708
+ }
5709
+ if (filters.dateFrom) {
5710
+ params.set("date_from", filters.dateFrom);
5711
+ }
5712
+ if (filters.dateTo) {
5713
+ params.set("date_to", filters.dateTo);
5714
+ }
5715
+ const customArr = recordToFilterArray(filters.customFieldValues, "fieldDefinitionId");
5716
+ if (customArr) {
5717
+ params.set("custom_field_filters", JSON.stringify(customArr));
5718
+ }
5719
+ const jiraArr = recordToFilterArray(filters.jiraFieldValues, "fieldName");
5720
+ if (jiraArr) {
5721
+ params.set("jira_field_filters", JSON.stringify(jiraArr));
5722
+ }
5723
+ const notionArr = recordToFilterArray(filters.notionFieldValues, "fieldName");
5724
+ if (notionArr) {
5725
+ params.set("notion_field_filters", JSON.stringify(notionArr));
5726
+ }
5727
+ if (filters.externalUserId) {
5728
+ params.set("external_user_id", filters.externalUserId);
5729
+ }
5730
+ if (typeof filters.page === "number" && filters.page > 0) {
5731
+ params.set("page", String(filters.page));
5732
+ }
5733
+ if (typeof filters.pageSize === "number" && filters.pageSize > 0) {
5734
+ params.set("page_size", String(filters.pageSize));
5735
+ }
5736
+ if (filters.sortOrder) {
5737
+ params.set("sort_order", filters.sortOrder);
5738
+ }
5739
+ const queryString = params.toString();
5740
+ return queryString ? `?${queryString}` : "";
5741
+ }
5742
+ const issueService = {
5743
+ async createIssue(issueData) {
5744
+ const sanitizedData = sanitizeString(issueData);
5745
+ const screenshotUploadIds = (sanitizedData.screenshot || []).map((url) => getRegisteredUploadId(url, "screenshot")).filter((id2) => typeof id2 === "string" && id2.length > 0);
5746
+ const videoUploadId = sanitizedData.video ? getRegisteredUploadId(sanitizedData.video, "video") : void 0;
5747
+ if (screenshotUploadIds.length > 0) {
5748
+ sanitizedData.screenshot_upload_ids = screenshotUploadIds;
5749
+ }
5750
+ if (videoUploadId) {
5751
+ sanitizedData.video_upload_id = videoUploadId;
5752
+ }
5753
+ const issue = await apiClient.post(issuesEndpoint(), sanitizedData);
5754
+ invalidateIssuesCache();
5755
+ return issue;
5756
+ },
5757
+ async getIssues(filters = {}, options = {}) {
5758
+ if (!filters.projectId) {
5759
+ throw new Error("프로젝트 ID가 필요합니다. 로그인 상태를 확인해주세요.");
5760
+ }
5761
+ const filterKey = getFilterKey(filters);
5762
+ const now2 = Date.now();
5763
+ if (!options.forceRefresh && issuesCache && issuesCache.filterKey === filterKey && now2 - issuesCache.timestamp < CACHE_DURATION_MS) {
5764
+ return issuesCache.data;
5765
+ }
5766
+ const queryParams = buildFilterQueryParams(filters);
5767
+ const { items: issues = [] } = await apiClient.get(
5768
+ `${issuesEndpoint()}${queryParams}`
5769
+ );
5770
+ issuesCache = {
5771
+ data: issues,
5772
+ timestamp: now2,
5773
+ filterKey
5774
+ };
5775
+ return issues;
5776
+ },
5777
+ async getIssueStickers(filters = {}, options = {}) {
5778
+ var _a, _b2;
5779
+ if (!filters.projectId) {
5780
+ throw new Error("프로젝트 ID가 필요합니다. 로그인 상태를 확인해주세요.");
5781
+ }
5782
+ const filterKey = `${getFilterKey(filters)}:stickers`;
5783
+ const now2 = Date.now();
5784
+ if (!options.forceRefresh && issuesCache && issuesCache.filterKey === filterKey && now2 - issuesCache.timestamp < CACHE_DURATION_MS) {
5785
+ return issuesCache.data;
5786
+ }
5787
+ const issues = [];
5788
+ let page = 1;
5789
+ let hasMore = true;
5790
+ while (hasMore && issues.length <= STICKER_FETCH_LIMIT) {
5791
+ const response = await apiClient.getResponse(
5792
+ `${issuesEndpoint()}/stickers${buildFilterQueryParams({
5793
+ ...filters,
5794
+ page,
5795
+ pageSize: STICKER_PAGE_SIZE
5796
+ })}`
5797
+ );
5798
+ const pageItems = ((_a = response.data) == null ? void 0 : _a.items) ?? [];
5799
+ issues.push(...pageItems);
5800
+ hasMore = Boolean((_b2 = response.data) == null ? void 0 : _b2.hasMore) && pageItems.length > 0;
5801
+ page += 1;
5802
+ }
5803
+ issuesCache = {
5804
+ data: issues,
5805
+ timestamp: now2,
5806
+ filterKey
5807
+ };
5808
+ return issues;
5809
+ },
5810
+ invalidateCache() {
5811
+ invalidateIssuesCache();
5812
+ },
5813
+ // 계약 기준: 백엔드 GET /api/sdk/issues/:id 는 back#101부터 읽기-시점-스크럽된
5814
+ // llm_prompt 를 상세 응답에 포함한다(목록 응답에는 없음) — 스코프를 이 반환 타입에만 한정한다.
5815
+ async getIssue(id2) {
5816
+ return apiClient.get(
5817
+ `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`
5818
+ );
5819
+ },
5820
+ async updateIssue(id2, updates) {
5821
+ const sanitizedUpdates = sanitizeString(updates);
5822
+ const issue = await apiClient.put(
5823
+ `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`,
5824
+ sanitizedUpdates
5825
+ );
5826
+ invalidateIssuesCache();
5827
+ return issue;
5828
+ },
5829
+ /**
5830
+ * 재생성. 스펙상 세 채널 모두에서 되고 역할과 무관하다 — 검사는 역할이 아니라
5831
+ * 그 이슈에 접근할 수 있는지다(백엔드가 판정한다).
5832
+ *
5833
+ * 응답으로 갱신된 이슈가 오지만 상태는 다시 pending 이다. 호출부는 응답을
5834
+ * 그대로 쓰지 말고 폴링으로 이어받아야 한다.
5835
+ */
5836
+ async regenerateIssue(id2) {
5837
+ const issue = await apiClient.post(
5838
+ `${issuesEndpoint()}/${encodeURIComponent(id2)}/regenerate${guestOwnerQuery()}`,
5839
+ {}
5840
+ );
5841
+ invalidateIssuesCache();
5842
+ return issue;
5843
+ },
5844
+ async deleteIssue(id2, options) {
5845
+ const endpoint = `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`;
5846
+ if (options == null ? void 0 : options.deleteExternal) {
5847
+ await apiClient.delete(endpoint, {
5848
+ body: { deleteExternal: true }
5849
+ });
5850
+ } else {
5851
+ await apiClient.delete(endpoint);
5852
+ }
5853
+ invalidateIssuesCache();
5854
+ }
5855
+ };
5856
+ function invalidateIssueQueries(issueId) {
5857
+ issueService.invalidateCache();
5858
+ queryClient.invalidateQueries({ queryKey: ["contentIssues"] });
5859
+ queryClient.invalidateQueries({ queryKey: ["issue", issueId] });
5860
+ }
5861
+ function notifyIssueUpdated(issueId) {
5862
+ SDKManager.getInstance().eventBus.emit("issue:updated", issueId);
5863
+ }
5864
+ function applyIssueMutationEffects(issueId) {
5865
+ invalidateIssueQueries(issueId);
5866
+ notifyIssueUpdated(issueId);
5867
+ }
5868
+ let queues = null;
5869
+ const toaster = createIssueUploadToaster();
5870
+ function getQueues() {
5871
+ if (queues) return queues;
5872
+ queues = createIssueUploadQueues({
5873
+ api: createMediaUploadApi({ post: (endpoint, body) => apiClient.post(endpoint, body) }),
5874
+ clientInfo: "issue-sticker-sdk",
5875
+ videoStore: createIndexedDbPendingUploadStore(VIDEO_UPLOAD_DB_NAME),
5876
+ attachmentStore: createIndexedDbPendingUploadStore(ATTACHMENT_UPLOAD_DB_NAME),
5877
+ loadTus: loadTusClient,
5878
+ onEvent: (event) => {
5879
+ if (event.type !== "failed") invalidateIssueQueries(event.issueId);
5880
+ },
5881
+ onNotice: (notice) => toaster.show(notice, retryWidgetIssueUploads)
5882
+ });
5883
+ return queues;
5884
+ }
5885
+ function getWidgetVideoUploadQueue() {
5886
+ return getQueues().video;
5887
+ }
5888
+ function getWidgetAttachmentUploadQueue() {
5889
+ return getQueues().attachments;
5890
+ }
5891
+ function resumeWidgetIssueUploads(projectKey) {
5892
+ return getQueues().resume([projectKey]);
5893
+ }
5894
+ function retryWidgetIssueUploads(issueId) {
5895
+ queues == null ? void 0 : queues.retry(issueId);
5896
+ }
5897
+ function stopWidgetUploadQueues() {
5898
+ queues == null ? void 0 : queues.stop();
5899
+ queues = null;
5900
+ }
5130
5901
  class EventBus {
5131
5902
  constructor() {
5132
5903
  this.listeners = /* @__PURE__ */ new Map();
@@ -5216,6 +5987,7 @@ const _SDKManager = class _SDKManager {
5216
5987
  }
5217
5988
  destroy() {
5218
5989
  var _a;
5990
+ stopWidgetUploadQueues();
5219
5991
  (_a = this._eventBus) == null ? void 0 : _a.removeAllListeners();
5220
5992
  this._config = null;
5221
5993
  this._platform = null;
@@ -5271,279 +6043,6 @@ function flushPendingSdkEventListeners(eventBus) {
5271
6043
  });
5272
6044
  pendingListeners.clear();
5273
6045
  }
5274
- function readApiBaseUrlFromEnv() {
5275
- if (typeof process !== "undefined" && process.env && Object.prototype.hasOwnProperty.call(process.env, "VITE_API_BASE_URL")) {
5276
- const processValue = process.env.VITE_API_BASE_URL;
5277
- if (typeof processValue === "string") {
5278
- const trimmed = processValue.trim();
5279
- return trimmed.length > 0 && trimmed !== "undefined" ? trimmed : void 0;
5280
- }
5281
- }
5282
- const viteValue = "https://api.issuesticker.com";
5283
- {
5284
- const trimmed = viteValue.trim();
5285
- return trimmed.length > 0 && trimmed !== "undefined" ? trimmed : void 0;
5286
- }
5287
- }
5288
- let tokenMemoryCache = null;
5289
- let apiKeyCache = null;
5290
- let sdkMode = null;
5291
- let memberTokenProvider = null;
5292
- function normalizeToken(token) {
5293
- const trimmed = token.trim();
5294
- if (trimmed.toLowerCase().startsWith("bearer ")) {
5295
- return trimmed.slice(7).trim();
5296
- }
5297
- return trimmed;
5298
- }
5299
- function createMemberAuthRequiredError(message = "멤버 로그인이 필요합니다.") {
5300
- return new ApiError(message, 401, {
5301
- success: false,
5302
- error: {
5303
- code: "MEMBER_AUTH_REQUIRED",
5304
- message
5305
- }
5306
- });
5307
- }
5308
- async function resolveAuthorizationHeader(options) {
5309
- if (sdkMode === "public" || sdkMode === null) {
5310
- if (apiKeyCache) {
5311
- return `ApiKey ${apiKeyCache}`;
5312
- }
5313
- return void 0;
5314
- }
5315
- if (sdkMode === "member" && memberTokenProvider) {
5316
- const token2 = await memberTokenProvider({
5317
- forceRefresh: options == null ? void 0 : options.forceRefreshMemberToken,
5318
- reason: (options == null ? void 0 : options.memberRefreshReason) || "missing"
5319
- });
5320
- if (!token2) {
5321
- throw createMemberAuthRequiredError();
5322
- }
5323
- return `Bearer ${token2}`;
5324
- }
5325
- const token = tokenMemoryCache ? normalizeToken(tokenMemoryCache) : null;
5326
- if (token) {
5327
- return `Bearer ${token}`;
5328
- }
5329
- return void 0;
5330
- }
5331
- const isDemoMode = false;
5332
- function getApiBaseUrl() {
5333
- const baseUrl = readApiBaseUrlFromEnv();
5334
- if (!baseUrl) {
5335
- throw new ApiError(
5336
- "API 서버 주소(VITE_API_BASE_URL)가 설정되지 않았습니다. SDK 빌드/환경을 확인해주세요.",
5337
- 0
5338
- );
5339
- }
5340
- if (!/^https?:\/\//.test(baseUrl)) {
5341
- throw new ApiError(`API 서버 주소(VITE_API_BASE_URL)가 올바르지 않습니다: ${baseUrl}`, 0);
5342
- }
5343
- return baseUrl.replace(/\/+$/, "");
5344
- }
5345
- function setApiKey(key) {
5346
- apiKeyCache = key;
5347
- }
5348
- function setSdkMode(mode) {
5349
- sdkMode = mode;
5350
- }
5351
- function getSdkMode() {
5352
- return sdkMode;
5353
- }
5354
- function setMemberTokenProvider(provider) {
5355
- memberTokenProvider = provider;
5356
- }
5357
- function assertRelativeApiEndpoint(endpoint) {
5358
- if (!endpoint.startsWith("/") || endpoint.startsWith("//")) {
5359
- throw new ApiError(`API endpoint는 백엔드 상대 경로여야 합니다: ${endpoint}`, 0);
5360
- }
5361
- }
5362
- function buildApiUrl(endpoint) {
5363
- assertRelativeApiEndpoint(endpoint);
5364
- return `${getApiBaseUrl()}${endpoint}`;
5365
- }
5366
- async function saveToken(token) {
5367
- const normalizedToken = normalizeToken(token);
5368
- tokenMemoryCache = normalizedToken;
5369
- }
5370
- async function clearToken() {
5371
- tokenMemoryCache = null;
5372
- }
5373
- class ApiError extends Error {
5374
- constructor(message, status, data) {
5375
- super(message);
5376
- this.status = status;
5377
- this.data = data;
5378
- this.name = "ApiError";
5379
- }
5380
- }
5381
- function extractErrorMessage(error) {
5382
- if (!error) return void 0;
5383
- if (typeof error === "string") return error;
5384
- return error.message || error.code || JSON.stringify(error);
5385
- }
5386
- async function requestResponse(endpoint, options = {}) {
5387
- const { body, skipAuth = false, headers: customHeaders, ...rest } = options;
5388
- const headers = {
5389
- "Content-Type": "application/json",
5390
- "x-client-info": "issue-sticker-sdk",
5391
- ...customHeaders || {}
5392
- };
5393
- if (!skipAuth) {
5394
- const authHeader = await resolveAuthorizationHeader();
5395
- if (authHeader) {
5396
- headers["Authorization"] = authHeader;
5397
- }
5398
- }
5399
- const url = buildApiUrl(endpoint);
5400
- const execute = (nextHeaders) => pristineFetch(url, {
5401
- ...rest,
5402
- headers: nextHeaders,
5403
- body: body ? JSON.stringify(body) : void 0
5404
- });
5405
- let response = await execute(headers);
5406
- let retriedMemberAuth = false;
5407
- if (!skipAuth && response.status === 401 && sdkMode === "member" && memberTokenProvider) {
5408
- const retryHeaders = { ...headers };
5409
- try {
5410
- const authHeader = await resolveAuthorizationHeader({
5411
- forceRefreshMemberToken: true,
5412
- memberRefreshReason: "unauthorized"
5413
- });
5414
- if (authHeader) {
5415
- retryHeaders.Authorization = authHeader;
5416
- retriedMemberAuth = true;
5417
- response = await execute(retryHeaders);
5418
- }
5419
- } catch {
5420
- throw new ApiError("인증이 만료되었습니다. 다시 로그인해주세요.", 401, {
5421
- success: false,
5422
- error: {
5423
- code: "SESSION_EXPIRED",
5424
- message: "인증이 만료되었습니다. 다시 로그인해주세요."
5425
- }
5426
- });
5427
- }
5428
- }
5429
- if (retriedMemberAuth && response.status === 401) {
5430
- throw new ApiError("인증이 만료되었습니다. 다시 로그인해주세요.", 401, {
5431
- success: false,
5432
- error: {
5433
- code: "SESSION_EXPIRED",
5434
- message: "인증이 만료되었습니다. 다시 로그인해주세요."
5435
- }
5436
- });
5437
- }
5438
- if (response.status === 204) {
5439
- return { success: true };
5440
- }
5441
- const json = await response.json();
5442
- if (!response.ok || !json.success) {
5443
- throw new ApiError(
5444
- extractErrorMessage(json.error) || json.message || `요청 실패: ${response.status}`,
5445
- response.status,
5446
- json
5447
- );
5448
- }
5449
- return json;
5450
- }
5451
- async function request(endpoint, options = {}) {
5452
- const json = await requestResponse(endpoint, options);
5453
- return json.data;
5454
- }
5455
- async function uploadRequest(endpoint, formData, skipAuth = false) {
5456
- const headers = {
5457
- "x-client-info": "issue-sticker-sdk"
5458
- };
5459
- if (!skipAuth) {
5460
- const authHeader = await resolveAuthorizationHeader();
5461
- if (authHeader) {
5462
- headers["Authorization"] = authHeader;
5463
- }
5464
- }
5465
- const url = buildApiUrl(endpoint);
5466
- const execute = (nextHeaders) => pristineFetch(url, {
5467
- method: "POST",
5468
- headers: nextHeaders,
5469
- body: formData
5470
- });
5471
- let response = await execute(headers);
5472
- let retriedMemberAuth = false;
5473
- if (!skipAuth && response.status === 401 && sdkMode === "member" && memberTokenProvider) {
5474
- const retryHeaders = { ...headers };
5475
- try {
5476
- const authHeader = await resolveAuthorizationHeader({
5477
- forceRefreshMemberToken: true,
5478
- memberRefreshReason: "unauthorized"
5479
- });
5480
- if (authHeader) {
5481
- retryHeaders.Authorization = authHeader;
5482
- retriedMemberAuth = true;
5483
- response = await execute(retryHeaders);
5484
- }
5485
- } catch {
5486
- throw new ApiError("인증이 만료되었습니다. 다시 로그인해주세요.", 401, {
5487
- success: false,
5488
- error: {
5489
- code: "SESSION_EXPIRED",
5490
- message: "인증이 만료되었습니다. 다시 로그인해주세요."
5491
- }
5492
- });
5493
- }
5494
- }
5495
- if (retriedMemberAuth && response.status === 401) {
5496
- throw new ApiError("인증이 만료되었습니다. 다시 로그인해주세요.", 401, {
5497
- success: false,
5498
- error: {
5499
- code: "SESSION_EXPIRED",
5500
- message: "인증이 만료되었습니다. 다시 로그인해주세요."
5501
- }
5502
- });
5503
- }
5504
- const json = await response.json();
5505
- if (!response.ok || !json.success) {
5506
- throw new ApiError(
5507
- extractErrorMessage(json.error) || json.message || `업로드 실패: ${response.status}`,
5508
- response.status,
5509
- json
5510
- );
5511
- }
5512
- return json.data;
5513
- }
5514
- async function directUpload(signedUrl, file, contentType) {
5515
- try {
5516
- await directUploadToSignedUrl(signedUrl, file, contentType);
5517
- } catch (error) {
5518
- if (error instanceof ApiError) {
5519
- throw error;
5520
- }
5521
- if (error instanceof DirectUploadError) {
5522
- throw new ApiError(error.message, error.status, error.data);
5523
- }
5524
- throw new ApiError(error instanceof Error ? error.message : "스토리지 업로드 실패", 0, error);
5525
- }
5526
- }
5527
- const apiClient = {
5528
- get(endpoint, options) {
5529
- return request(endpoint, { ...options, method: "GET" });
5530
- },
5531
- getResponse(endpoint, options) {
5532
- return requestResponse(endpoint, { ...options, method: "GET" });
5533
- },
5534
- post(endpoint, body, options) {
5535
- return request(endpoint, { ...options, method: "POST", body });
5536
- },
5537
- put(endpoint, body, options) {
5538
- return request(endpoint, { ...options, method: "PUT", body });
5539
- },
5540
- delete(endpoint, options) {
5541
- return request(endpoint, { ...options, method: "DELETE" });
5542
- },
5543
- upload(endpoint, formData, skipAuth) {
5544
- return uploadRequest(endpoint, formData, skipAuth);
5545
- }
5546
- };
5547
6046
  let session = null;
5548
6047
  function resolveApiBaseUrl() {
5549
6048
  try {
@@ -5710,25 +6209,6 @@ const createShadowRoot = (hostElement, cssTexts = []) => {
5710
6209
  const getPortalContainer = () => {
5711
6210
  return _portalTarget || document.body;
5712
6211
  };
5713
- const queryClient = new QueryClient({
5714
- defaultOptions: {
5715
- queries: {
5716
- staleTime: 5 * 60 * 1e3,
5717
- // 5분
5718
- gcTime: 10 * 60 * 1e3,
5719
- // 10분 (v5에서는 cacheTime 대신 gcTime 사용)
5720
- refetchOnWindowFocus: true,
5721
- refetchOnReconnect: true,
5722
- retry: 3,
5723
- retryDelay: (attemptIndex) => Math.min(1e3 * 2 ** attemptIndex, 3e4)
5724
- },
5725
- mutations: {
5726
- retry: 1,
5727
- // Mutation은 1번만 재시도
5728
- retryDelay: 1e3
5729
- }
5730
- }
5731
- });
5732
6212
  /**
5733
6213
  * @license lucide-react v0.562.0 - ISC
5734
6214
  *
@@ -14657,7 +15137,10 @@ const ToastItem = forwardRef(function ToastItem2({ t, behindCount, onDismiss },
14657
15137
  ),
14658
15138
  children: /* @__PURE__ */ jsxs("div", { className: cn$1("flex items-center gap-2.5 px-3 py-2.5", style.tint), children: [
14659
15139
  t.type !== "default" ? /* @__PURE__ */ jsx(Icon2, { className: cn$1("h-4 w-4 shrink-0", style.iconColor) }) : null,
14660
- /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 text-sm font-medium text-text-primary", children: t.message }),
15140
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 text-sm text-text-primary", children: [
15141
+ t.title ? /* @__PURE__ */ jsx("span", { className: "block font-semibold", children: t.title }) : null,
15142
+ /* @__PURE__ */ jsx("span", { className: t.title ? "block" : "font-medium", children: t.message })
15143
+ ] }),
14661
15144
  t.action ? /* @__PURE__ */ jsx(
14662
15145
  "button",
14663
15146
  {
@@ -14765,235 +15248,6 @@ function toIssueFilterParams(filters) {
14765
15248
  ...countRecord(filters.notionFieldValues) ? { notionFieldValues: filters.notionFieldValues } : {}
14766
15249
  };
14767
15250
  }
14768
- async function uploadSignedMedia(file, mediaType, issueId) {
14769
- return uploadSignedMediaWithApi(
14770
- {
14771
- post: (endpoint, body) => apiClient.post(endpoint, body),
14772
- directUpload
14773
- },
14774
- file,
14775
- mediaType,
14776
- { issueId }
14777
- );
14778
- }
14779
- function issuesEndpoint() {
14780
- return "/api/sdk/issues";
14781
- }
14782
- function guestOwnerQuery() {
14783
- var _a;
14784
- const mode = getSdkMode();
14785
- if (mode !== "public") return "";
14786
- return buildGuestOwnerQuery(mode, (_a = SDKManager.getInstance().config.user) == null ? void 0 : _a.id);
14787
- }
14788
- let issuesCache = null;
14789
- const CACHE_DURATION_MS = 30 * 1e3;
14790
- const STICKER_PAGE_SIZE = 500;
14791
- const STICKER_FETCH_LIMIT = 2e3;
14792
- function getFilterKey(filters) {
14793
- var _a;
14794
- const normalizeArray = (value) => {
14795
- if (value === "all" || !value) return "all";
14796
- if (Array.isArray(value)) {
14797
- return value.length === 0 ? "all" : [...value].sort().join(",");
14798
- }
14799
- return String(value);
14800
- };
14801
- const normalizeRecord = (record) => {
14802
- if (!record) return "";
14803
- const entries = Object.entries(record).map(([k, v]) => [k, [...v].sort()]).sort(([a], [b]) => a.localeCompare(b));
14804
- return JSON.stringify(entries);
14805
- };
14806
- return JSON.stringify({
14807
- sdkMode: getSdkMode() || "public",
14808
- url: normalizeArray(filters.url),
14809
- projectId: filters.projectId || "all",
14810
- externalUserId: filters.externalUserId || "",
14811
- search: ((_a = filters.search) == null ? void 0 : _a.trim()) || "",
14812
- dateFrom: filters.dateFrom || "",
14813
- dateTo: filters.dateTo || "",
14814
- page: filters.page ?? 0,
14815
- pageSize: filters.pageSize ?? 0,
14816
- custom: normalizeRecord(filters.customFieldValues),
14817
- jira: normalizeRecord(filters.jiraFieldValues),
14818
- notion: normalizeRecord(filters.notionFieldValues),
14819
- sortOrder: filters.sortOrder || ""
14820
- });
14821
- }
14822
- function invalidateIssuesCache() {
14823
- issuesCache = null;
14824
- }
14825
- function recordToFilterArray(record, keyFieldName) {
14826
- if (!record) return null;
14827
- const entries = Object.entries(record).filter(([, values]) => values.length > 0);
14828
- if (entries.length === 0) return null;
14829
- return entries.map(
14830
- ([key, values]) => ({ [keyFieldName]: key, values })
14831
- );
14832
- }
14833
- function buildFilterQueryParams(filters) {
14834
- var _a;
14835
- const params = new URLSearchParams();
14836
- if (filters.projectId) {
14837
- params.set("project_id", filters.projectId);
14838
- }
14839
- if (filters.url && filters.url !== "all") {
14840
- if (Array.isArray(filters.url) && filters.url.length > 0) {
14841
- params.set("url", filters.url.join(","));
14842
- } else if (typeof filters.url === "string") {
14843
- params.set("url", filters.url);
14844
- }
14845
- }
14846
- const search2 = (_a = filters.search) == null ? void 0 : _a.trim();
14847
- if (search2) {
14848
- params.set("search", search2);
14849
- }
14850
- if (filters.dateFrom) {
14851
- params.set("date_from", filters.dateFrom);
14852
- }
14853
- if (filters.dateTo) {
14854
- params.set("date_to", filters.dateTo);
14855
- }
14856
- const customArr = recordToFilterArray(filters.customFieldValues, "fieldDefinitionId");
14857
- if (customArr) {
14858
- params.set("custom_field_filters", JSON.stringify(customArr));
14859
- }
14860
- const jiraArr = recordToFilterArray(filters.jiraFieldValues, "fieldName");
14861
- if (jiraArr) {
14862
- params.set("jira_field_filters", JSON.stringify(jiraArr));
14863
- }
14864
- const notionArr = recordToFilterArray(filters.notionFieldValues, "fieldName");
14865
- if (notionArr) {
14866
- params.set("notion_field_filters", JSON.stringify(notionArr));
14867
- }
14868
- if (filters.externalUserId) {
14869
- params.set("external_user_id", filters.externalUserId);
14870
- }
14871
- if (typeof filters.page === "number" && filters.page > 0) {
14872
- params.set("page", String(filters.page));
14873
- }
14874
- if (typeof filters.pageSize === "number" && filters.pageSize > 0) {
14875
- params.set("page_size", String(filters.pageSize));
14876
- }
14877
- if (filters.sortOrder) {
14878
- params.set("sort_order", filters.sortOrder);
14879
- }
14880
- const queryString = params.toString();
14881
- return queryString ? `?${queryString}` : "";
14882
- }
14883
- const issueService = {
14884
- async createIssue(issueData) {
14885
- const sanitizedData = sanitizeString(issueData);
14886
- const screenshotUploadIds = (sanitizedData.screenshot || []).map((url) => getRegisteredUploadId(url, "screenshot")).filter((id2) => typeof id2 === "string" && id2.length > 0);
14887
- const videoUploadId = sanitizedData.video ? getRegisteredUploadId(sanitizedData.video, "video") : void 0;
14888
- if (screenshotUploadIds.length > 0) {
14889
- sanitizedData.screenshot_upload_ids = screenshotUploadIds;
14890
- }
14891
- if (videoUploadId) {
14892
- sanitizedData.video_upload_id = videoUploadId;
14893
- }
14894
- const issue = await apiClient.post(issuesEndpoint(), sanitizedData);
14895
- invalidateIssuesCache();
14896
- return issue;
14897
- },
14898
- async getIssues(filters = {}, options = {}) {
14899
- if (!filters.projectId) {
14900
- throw new Error("프로젝트 ID가 필요합니다. 로그인 상태를 확인해주세요.");
14901
- }
14902
- const filterKey = getFilterKey(filters);
14903
- const now2 = Date.now();
14904
- if (!options.forceRefresh && issuesCache && issuesCache.filterKey === filterKey && now2 - issuesCache.timestamp < CACHE_DURATION_MS) {
14905
- return issuesCache.data;
14906
- }
14907
- const queryParams = buildFilterQueryParams(filters);
14908
- const { items: issues = [] } = await apiClient.get(
14909
- `${issuesEndpoint()}${queryParams}`
14910
- );
14911
- issuesCache = {
14912
- data: issues,
14913
- timestamp: now2,
14914
- filterKey
14915
- };
14916
- return issues;
14917
- },
14918
- async getIssueStickers(filters = {}, options = {}) {
14919
- var _a, _b2;
14920
- if (!filters.projectId) {
14921
- throw new Error("프로젝트 ID가 필요합니다. 로그인 상태를 확인해주세요.");
14922
- }
14923
- const filterKey = `${getFilterKey(filters)}:stickers`;
14924
- const now2 = Date.now();
14925
- if (!options.forceRefresh && issuesCache && issuesCache.filterKey === filterKey && now2 - issuesCache.timestamp < CACHE_DURATION_MS) {
14926
- return issuesCache.data;
14927
- }
14928
- const issues = [];
14929
- let page = 1;
14930
- let hasMore = true;
14931
- while (hasMore && issues.length <= STICKER_FETCH_LIMIT) {
14932
- const response = await apiClient.getResponse(
14933
- `${issuesEndpoint()}/stickers${buildFilterQueryParams({
14934
- ...filters,
14935
- page,
14936
- pageSize: STICKER_PAGE_SIZE
14937
- })}`
14938
- );
14939
- const pageItems = ((_a = response.data) == null ? void 0 : _a.items) ?? [];
14940
- issues.push(...pageItems);
14941
- hasMore = Boolean((_b2 = response.data) == null ? void 0 : _b2.hasMore) && pageItems.length > 0;
14942
- page += 1;
14943
- }
14944
- issuesCache = {
14945
- data: issues,
14946
- timestamp: now2,
14947
- filterKey
14948
- };
14949
- return issues;
14950
- },
14951
- invalidateCache() {
14952
- invalidateIssuesCache();
14953
- },
14954
- // 계약 기준: 백엔드 GET /api/sdk/issues/:id 는 back#101부터 읽기-시점-스크럽된
14955
- // llm_prompt 를 상세 응답에 포함한다(목록 응답에는 없음) — 스코프를 이 반환 타입에만 한정한다.
14956
- async getIssue(id2) {
14957
- return apiClient.get(
14958
- `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`
14959
- );
14960
- },
14961
- async updateIssue(id2, updates) {
14962
- const sanitizedUpdates = sanitizeString(updates);
14963
- const issue = await apiClient.put(
14964
- `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`,
14965
- sanitizedUpdates
14966
- );
14967
- invalidateIssuesCache();
14968
- return issue;
14969
- },
14970
- /**
14971
- * 재생성. 스펙상 세 채널 모두에서 되고 역할과 무관하다 — 검사는 역할이 아니라
14972
- * 그 이슈에 접근할 수 있는지다(백엔드가 판정한다).
14973
- *
14974
- * 응답으로 갱신된 이슈가 오지만 상태는 다시 pending 이다. 호출부는 응답을
14975
- * 그대로 쓰지 말고 폴링으로 이어받아야 한다.
14976
- */
14977
- async regenerateIssue(id2) {
14978
- const issue = await apiClient.post(
14979
- `${issuesEndpoint()}/${encodeURIComponent(id2)}/regenerate${guestOwnerQuery()}`,
14980
- {}
14981
- );
14982
- invalidateIssuesCache();
14983
- return issue;
14984
- },
14985
- async deleteIssue(id2, options) {
14986
- const endpoint = `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`;
14987
- if (options == null ? void 0 : options.deleteExternal) {
14988
- await apiClient.delete(endpoint, {
14989
- body: { deleteExternal: true }
14990
- });
14991
- } else {
14992
- await apiClient.delete(endpoint);
14993
- }
14994
- invalidateIssuesCache();
14995
- }
14996
- };
14997
15251
  async function loadIssuesFromServer(url, projectId, externalUserId, filters, options = {}) {
14998
15252
  if (!projectId) return [];
14999
15253
  try {
@@ -15171,18 +15425,18 @@ function UnrenderedStickerDialog({
15171
15425
  {
15172
15426
  role: "dialog",
15173
15427
  "aria-modal": "false",
15174
- "aria-label": "미표시 스티커 목록",
15428
+ "aria-label": "표시하지 못한 스티커 목록",
15175
15429
  className: "pointer-events-auto flex h-[min(480px,calc(100vh-64px))] w-[min(560px,calc(100vw-32px))] flex-col overflow-hidden rounded-xl border border-slate-200 bg-white text-slate-900 shadow-2xl",
15176
15430
  children: [
15177
15431
  /* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between border-b border-slate-100 px-5 py-3.5", children: [
15178
- /* @__PURE__ */ jsx("h2", { className: "min-w-0 truncate text-sm font-semibold", children: "미표시 스티커" }),
15432
+ /* @__PURE__ */ jsx("h2", { className: "min-w-0 truncate text-sm font-semibold", children: "표시하지 못한 스티커" }),
15179
15433
  /* @__PURE__ */ jsx(
15180
15434
  "button",
15181
15435
  {
15182
15436
  type: "button",
15183
15437
  className: "inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-slate-500 hover:bg-slate-100 hover:text-slate-900",
15184
15438
  onClick: () => onOpenChange(false),
15185
- "aria-label": "미표시 스티커 목록 닫기",
15439
+ "aria-label": "표시하지 못한 스티커 목록 닫기",
15186
15440
  children: /* @__PURE__ */ jsx(X$1, { className: "h-4 w-4" })
15187
15441
  }
15188
15442
  )
@@ -15360,7 +15614,8 @@ function OverlayShell({
15360
15614
  }
15361
15615
  const ISSUE_DRAFT_DISABLED_MESSAGE = "지금은 AI 작성을 사용할 수 없습니다. 제목과 설명을 직접 작성해주세요.";
15362
15616
  const LABEL = "기대한 동작";
15363
- const PLACEHOLDER = "예: 할인 쿠폰을 적용하면 결제 금액에서 즉시 차감되어야 합니다";
15617
+ const ISSUE_INTENT_PLACEHOLDER = "기대한 동작을 적으면 AI가 제목과 설명을 작성합니다.\n예: 쿠폰을 적용하면 결제 금액이 바로 줄어야 합니다";
15618
+ const PLACEHOLDER = ISSUE_INTENT_PLACEHOLDER;
15364
15619
  const SWITCH_TO_MANUAL = "직접 작성";
15365
15620
  const SWITCH_TO_MANUAL_TOOLTIP = "제목, 설명 등 이슈 필드를 직접 작성합니다";
15366
15621
  const SUBMIT = "보내기";
@@ -15397,20 +15652,28 @@ function IssueIntentBubble({
15397
15652
  if (isFocused(node2) || Date.now() >= deadline) return;
15398
15653
  frame2 = requestAnimationFrame(attempt);
15399
15654
  };
15400
- window.addEventListener("pointerdown", abandon, { capture: true });
15655
+ const pointerScopes = /* @__PURE__ */ new Set([window, node2.getRootNode()]);
15656
+ pointerScopes.forEach(
15657
+ (scope) => scope.addEventListener("pointerdown", abandon, { capture: true })
15658
+ );
15401
15659
  window.addEventListener("keydown", abandon, { capture: true });
15402
15660
  attempt();
15403
15661
  return () => {
15404
- window.removeEventListener("pointerdown", abandon, { capture: true });
15662
+ pointerScopes.forEach(
15663
+ (scope) => scope.removeEventListener("pointerdown", abandon, { capture: true })
15664
+ );
15405
15665
  window.removeEventListener("keydown", abandon, { capture: true });
15406
15666
  if (frame2) cancelAnimationFrame(frame2);
15407
15667
  };
15408
15668
  }, []);
15669
+ const minHeightRef = useRef(null);
15409
15670
  useLayoutEffect(() => {
15410
15671
  const node2 = inputRef.current;
15411
15672
  if (!node2) return;
15412
15673
  node2.style.height = "auto";
15413
- node2.style.height = `${Math.min(node2.scrollHeight, MAX_INPUT_HEIGHT)}px`;
15674
+ minHeightRef.current ?? (minHeightRef.current = node2.scrollHeight);
15675
+ const next = Math.max(node2.scrollHeight, minHeightRef.current);
15676
+ node2.style.height = `${Math.min(next, MAX_INPUT_HEIGHT)}px`;
15414
15677
  }, [value]);
15415
15678
  return (
15416
15679
  /*
@@ -15426,7 +15689,7 @@ function IssueIntentBubble({
15426
15689
  /* @__PURE__ */ jsxs(
15427
15690
  "div",
15428
15691
  {
15429
- className: `${ISSUE_STICKER_REPORT_FORM_CLASS} w-[min(20rem,calc(100vw_-_1.5rem))] space-y-1.5 rounded-md border border-line-subtle bg-surface-1 p-1.5 transition-colors duration-fast ease-out focus-within:border-line-focus`,
15692
+ className: `${ISSUE_STICKER_REPORT_FORM_CLASS} w-[min(24rem,calc(100vw_-_1.5rem))] space-y-1.5 rounded-md border border-line-subtle bg-surface-1 p-1.5 transition-colors duration-fast ease-out focus-within:border-line-focus`,
15430
15693
  children: [
15431
15694
  /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-1.5", children: [
15432
15695
  /* @__PURE__ */ jsx(
@@ -15736,7 +15999,9 @@ DialogClose$1.displayName = CLOSE_NAME;
15736
15999
  function getState$2(open) {
15737
16000
  return open ? "open" : "closed";
15738
16001
  }
15739
- const Dialog = Dialog$1;
16002
+ const [Dialog, useDialogContentDismissRef] = createShadowDismissRoot(Dialog$1, {
16003
+ focusOutside: false
16004
+ });
15740
16005
  const DialogClose = DialogClose$1;
15741
16006
  const DialogPortal = ({ children }) => {
15742
16007
  const portalContainer = usePortalContainer();
@@ -15769,13 +16034,13 @@ const DialogContent = React.forwardRef(
15769
16034
  ...props
15770
16035
  }, ref) => {
15771
16036
  const [content2, setContent] = React.useState(null);
16037
+ const dismissRef = useDialogContentDismissRef(ref);
15772
16038
  const composedRef = React.useCallback(
15773
16039
  (node2) => {
15774
16040
  setContent(node2);
15775
- if (typeof ref === "function") ref(node2);
15776
- else if (ref) ref.current = node2;
16041
+ dismissRef(node2);
15777
16042
  },
15778
- [ref]
16043
+ [dismissRef]
15779
16044
  );
15780
16045
  useOverlayFocus({ enabled: true, container: content2, initialFocusRef });
15781
16046
  return /* @__PURE__ */ jsxs(DialogPortal, { children: [
@@ -16048,7 +16313,11 @@ function appendSnippet(base, body) {
16048
16313
  ${trimmedBody}`;
16049
16314
  }
16050
16315
  const TRIGGER_LABEL = "고정 문구 선택";
16316
+ const TRIGGER_HINT = "이슈 설명 끝에 추가할 고정 문구를 선택합니다";
16051
16317
  const CLEAR_OPTION_LABEL = "선택 안 함";
16318
+ const EMPTY_TITLE = "등록된 고정 문구가 없습니다";
16319
+ const EMPTY_DESCRIPTION = "테스트 계정처럼 이슈마다 반복해서 적는 내용을 등록해두면 이슈 설명 끝에 추가됩니다.";
16320
+ const DEFAULT_EMPTY_HINT = "어드민 프로젝트 상세의 고정 문구 탭에서 등록합니다.";
16052
16321
  const GROUP_LABEL = {
16053
16322
  project: "공용 문구",
16054
16323
  personal: "내 문구"
@@ -16057,7 +16326,8 @@ function SnippetPicker({
16057
16326
  snippets,
16058
16327
  selectedId,
16059
16328
  onSelect,
16060
- disabled = false
16329
+ disabled = false,
16330
+ emptyHint = DEFAULT_EMPTY_HINT
16061
16331
  }) {
16062
16332
  const [open, setOpen] = useState(false);
16063
16333
  const listRef = useRef(null);
@@ -16116,7 +16386,8 @@ function SnippetPicker({
16116
16386
  "button",
16117
16387
  {
16118
16388
  type: "button",
16119
- disabled: disabled || isEmpty,
16389
+ title: TRIGGER_HINT,
16390
+ disabled,
16120
16391
  className: cn$1(
16121
16392
  "inline-flex max-w-[10rem] items-center gap-1 rounded-sm border border-transparent px-2 py-1 text-xs text-text-secondary outline-none",
16122
16393
  "hover:bg-surface-2 focus-visible:border-line-focus disabled:cursor-not-allowed disabled:opacity-40"
@@ -16134,8 +16405,18 @@ function SnippetPicker({
16134
16405
  align: "start",
16135
16406
  sideOffset: 4,
16136
16407
  onEscapeKeyDown: stopEscapePropagation(),
16137
- className: cn$1(`panel-shell-subtle w-72 p-1.5 shadow-lg ${OVERLAY_LAYER.floating}`),
16138
- children: /* @__PURE__ */ jsxs(
16408
+ className: cn$1(
16409
+ `panel-shell-subtle p-1.5 shadow-lg ${OVERLAY_LAYER.floating}`,
16410
+ isEmpty ? "w-[min(30rem,calc(100vw_-_1.5rem))]" : "w-72"
16411
+ ),
16412
+ children: isEmpty ? (
16413
+ // 비어 있다고 버튼을 막으면 무엇을 하는 버튼인지조차 알 수 없다. 열어서 이유를 알려준다.
16414
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1 break-keep px-2.5 py-2 [overflow-wrap:anywhere]", children: [
16415
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-text-primary", children: EMPTY_TITLE }),
16416
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: EMPTY_DESCRIPTION }),
16417
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: emptyHint })
16418
+ ] })
16419
+ ) : /* @__PURE__ */ jsxs(
16139
16420
  "div",
16140
16421
  {
16141
16422
  ref: listRef,
@@ -16531,6 +16812,16 @@ async function captureScreenshot(options) {
16531
16812
  }
16532
16813
  return void 0;
16533
16814
  }
16815
+ async function captureViewportAndElement(element2, excludeSelectors) {
16816
+ try {
16817
+ if (SDKManager.getInstance().isInitialized()) {
16818
+ return await captureViewportWithElementCrop({ element: element2, excludeSelectors });
16819
+ }
16820
+ } catch (err) {
16821
+ devLogger.error("screenshotCapture", "스크린샷 캡처 실패:", err);
16822
+ }
16823
+ return {};
16824
+ }
16534
16825
  function toScreenshotList(dataUrls, dataUrl) {
16535
16826
  if (dataUrls && dataUrls.length > 0) {
16536
16827
  return dataUrls;
@@ -16652,15 +16943,17 @@ function useClickPosition(isCreatingIssueRef, recordedVideoFile) {
16652
16943
  useEffect(() => {
16653
16944
  const captureScreenshotsInBackground = async (position2) => {
16654
16945
  await waitForFormOpen();
16655
- const [fullScreenshotDataUrl, elementScreenshotDataUrl] = await pauseNetworkLogCollectionWhile(
16656
- () => Promise.all([
16657
- captureScreenshot({ excludeSelectors: SCREENSHOT_EXCLUDE_SELECTORS }),
16658
- captureScreenshot({
16659
- element: position2.element,
16660
- excludeSelectors: SCREENSHOT_EXCLUDE_SELECTORS
16661
- })
16662
- ])
16663
- );
16946
+ const { fullScreenshotDataUrl, elementScreenshotDataUrl } = await pauseNetworkLogCollectionWhile(async () => {
16947
+ const { fullDataUrl, elementDataUrl } = await captureViewportAndElement(
16948
+ position2.element,
16949
+ SCREENSHOT_EXCLUDE_SELECTORS
16950
+ );
16951
+ const element2 = elementDataUrl ?? await captureScreenshot({
16952
+ element: position2.element,
16953
+ excludeSelectors: SCREENSHOT_EXCLUDE_SELECTORS
16954
+ });
16955
+ return { fullScreenshotDataUrl: fullDataUrl, elementScreenshotDataUrl: element2 };
16956
+ });
16664
16957
  const captured = {
16665
16958
  screenshotDataUrl: elementScreenshotDataUrl,
16666
16959
  screenshotDataUrls: [fullScreenshotDataUrl, elementScreenshotDataUrl].filter(
@@ -16787,43 +17080,6 @@ function useScreenshotUpload() {
16787
17080
  uploadMany
16788
17081
  };
16789
17082
  }
16790
- async function uploadVideo(videoFile, issueId) {
16791
- devLogger.log("videoUpload", "영상 파일 업로드 시작", {
16792
- 크기: `${(videoFile.size / 1024 / 1024).toFixed(2)}MB`,
16793
- 타입: videoFile.type
16794
- });
16795
- const result = await uploadSignedMedia(videoFile, "video", issueId);
16796
- devLogger.log("videoUpload", "영상 파일 업로드 성공:", result.url);
16797
- return result.url;
16798
- }
16799
- function useVideoUpload() {
16800
- const upload = async (videoFile) => uploadVideo(videoFile);
16801
- return {
16802
- upload
16803
- };
16804
- }
16805
- async function uploadSessionReplay(snapshot) {
16806
- try {
16807
- const file = new File([snapshot.payload], "session-replay.gz", {
16808
- type: "application/gzip"
16809
- });
16810
- const { id: id2 } = await uploadSignedMedia(file, "replay");
16811
- const marker = readReleaseMarker();
16812
- return {
16813
- uploadId: id2,
16814
- meta: {
16815
- window_seconds: snapshot.windowSeconds,
16816
- event_count: snapshot.eventCount,
16817
- size_bytes: snapshot.sizeBytes,
16818
- rrweb_version: snapshot.rrwebVersion,
16819
- privacy_config_version: snapshot.privacyConfigVersion,
16820
- ...marker ? { release: marker.release, release_source: marker.release_source } : {}
16821
- }
16822
- };
16823
- } catch {
16824
- return null;
16825
- }
16826
- }
16827
17083
  function assertSubmittable(data) {
16828
17084
  var _a, _b2, _c2;
16829
17085
  const hasIntent = Boolean((_a = data.intent) == null ? void 0 : _a.trim());
@@ -16849,18 +17105,13 @@ function useIssueSubmission({
16849
17105
  const { fetchConsoleLogs } = useConsoleLogs();
16850
17106
  const { getAuthInfo } = useAuthInfo();
16851
17107
  const { uploadMany: uploadScreenshots2 } = useScreenshotUpload();
16852
- const { upload: uploadVideo2 } = useVideoUpload();
16853
17108
  const createIssueMutation = useDebouncedMutation({
16854
17109
  mutationFn: async (data) => {
16855
17110
  var _a, _b2, _c2, _d2, _e2, _f2;
16856
17111
  assertSubmittable(data);
16857
17112
  let screenshotUrls;
16858
- let videoUrl;
16859
- if (data.videoFile) {
16860
- videoUrl = await uploadVideo2(data.videoFile);
16861
- } else if (data.position.videoFile) {
16862
- videoUrl = await uploadVideo2(data.position.videoFile);
16863
- } else {
17113
+ const videoFile2 = data.videoFile ?? data.position.videoFile;
17114
+ if (!videoFile2) {
16864
17115
  const screenshotDataUrls = await resolveClickPositionScreenshots(data.position);
16865
17116
  if (screenshotDataUrls.length > 0) {
16866
17117
  const uploadedUrls = await uploadScreenshots2(screenshotDataUrls, {
@@ -16901,7 +17152,7 @@ function useIssueSubmission({
16901
17152
  component: positionData.component
16902
17153
  },
16903
17154
  screenshot: screenshotUrls && screenshotUrls.length > 0 ? screenshotUrls : void 0,
16904
- video: videoUrl,
17155
+ ...videoFile2 ? { video_pending: true } : {},
16905
17156
  network_logs: networkLogs,
16906
17157
  console_logs: consoleLogs.length > 0 ? consoleLogs : void 0,
16907
17158
  user_agent: userAgent,
@@ -16916,39 +17167,17 @@ function useIssueSubmission({
16916
17167
  if (((_e2 = issueData.custom_field_values) == null ? void 0 : _e2.length) === 0) {
16917
17168
  delete issueData.custom_field_values;
16918
17169
  }
16919
- if (sessionReplay == null ? void 0 : sessionReplay.canAttach) {
16920
- try {
16921
- const snapshot = await sessionReplay.takeSnapshot();
16922
- if (snapshot) {
16923
- const uploaded = await uploadSessionReplay(snapshot);
16924
- if (uploaded) {
16925
- issueData.session_replay_upload_id = uploaded.uploadId;
16926
- issueData.session_replay_meta = uploaded.meta;
16927
- }
16928
- }
16929
- } catch (replayError) {
16930
- devLogger.error(
16931
- "useIssueSubmission",
16932
- "세션 리플레이 첨부 실패 (이슈 생성 계속):",
16933
- replayError
16934
- );
16935
- }
16936
- }
16937
- try {
16938
- const socketSnapshot = await serializeSocketTranscript(
16939
- getCollectorSession().socket.getConnections()
16940
- );
16941
- if (socketSnapshot) {
16942
- const uploaded = await uploadSocketTranscript(
16943
- { post: (endpoint, body) => apiClient.post(endpoint, body), directUpload },
16944
- socketSnapshot
16945
- );
16946
- if (uploaded) {
16947
- issueData.socket_log_upload_id = uploaded.uploadId;
16948
- }
16949
- }
16950
- } catch (socketError) {
16951
- devLogger.error("useIssueSubmission", "소켓 전사 첨부 실패 (이슈 생성 계속):", socketError);
17170
+ const attachments = await collectAttachmentUploads({
17171
+ takeReplay: (sessionReplay == null ? void 0 : sessionReplay.canAttach) ? () => sessionReplay.takeSnapshot() : void 0,
17172
+ getConnections: () => getCollectorSession().socket.getConnections(),
17173
+ onError: (kind, error) => devLogger.error(
17174
+ "useIssueSubmission",
17175
+ kind === "replay" ? "세션 리플레이 스냅샷 실패 (이슈 생성 계속):" : "소켓 전사 직렬화 실패 (이슈 생성 계속):",
17176
+ error
17177
+ )
17178
+ });
17179
+ if (hasReplayUpload(attachments)) {
17180
+ issueData.session_replay_pending = true;
16952
17181
  }
16953
17182
  const { networkLogs: fittedNetworkLogs, stillOverBudget } = shrinkNetworkLogsToFit(
16954
17183
  issueData.network_logs ?? [],
@@ -16967,6 +17196,16 @@ function useIssueSubmission({
16967
17196
  notionProperties: data.notionFields
16968
17197
  });
16969
17198
  const createdIssue = await issueService.createIssue({ ...issueData, integrations });
17199
+ if (videoFile2 || attachments.length > 0) {
17200
+ await enqueueIssueUploads({
17201
+ videoQueue: getWidgetVideoUploadQueue(),
17202
+ attachmentQueue: getWidgetAttachmentUploadQueue(),
17203
+ issueId: createdIssue.id,
17204
+ projectKey: authInfo.projectId,
17205
+ video: videoFile2 ? { blob: videoFile2, mimeType: normalizeUploadMimeType(videoFile2.type, "video") } : null,
17206
+ attachments
17207
+ });
17208
+ }
16970
17209
  for (const service of createdIssue.failed_services ?? []) {
16971
17210
  toast.error(getIntegrationFailureMessage(service));
16972
17211
  }
@@ -17608,6 +17847,7 @@ function IssueFormError({ error }) {
17608
17847
  return /* @__PURE__ */ jsx("div", { className: "rounded-[18px] border border-danger/20 bg-danger-subtle px-4 py-3 text-sm text-danger", children: error });
17609
17848
  }
17610
17849
  const SWITCH_TO_AI = "AI 작성으로 돌아가기";
17850
+ const SWITCH_TO_AI_HINT = "기대한 동작만 적으면 AI가 제목과 설명을 작성합니다.";
17611
17851
  function IssueFormHeader({ title, onClose, onSwitchToAi }) {
17612
17852
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
17613
17853
  /* @__PURE__ */ jsx("h2", { className: "m-0 text-lg font-semibold text-text-primary", children: title }),
@@ -17624,7 +17864,10 @@ function IssueFormHeader({ title, onClose, onSwitchToAi }) {
17624
17864
  children: /* @__PURE__ */ jsx(Sparkles, { className: "h-4 w-4" })
17625
17865
  }
17626
17866
  ) }),
17627
- /* @__PURE__ */ jsx(TooltipContent, { side: "top", sideOffset: 10, children: SWITCH_TO_AI })
17867
+ /* @__PURE__ */ jsxs(TooltipContent, { side: "top", sideOffset: 10, className: "max-w-[16rem]", children: [
17868
+ /* @__PURE__ */ jsx("p", { className: "font-medium", children: SWITCH_TO_AI }),
17869
+ /* @__PURE__ */ jsx("p", { className: "mt-0.5 opacity-80", children: SWITCH_TO_AI_HINT })
17870
+ ] })
17628
17871
  ] }) }) : null,
17629
17872
  /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: onClose, "aria-label": "닫기", children: /* @__PURE__ */ jsx(X$1, { className: "h-4 w-4" }) })
17630
17873
  ] })
@@ -18175,18 +18418,6 @@ function IssueForm({
18175
18418
  getPortalContainer()
18176
18419
  );
18177
18420
  }
18178
- function invalidateIssueQueries(issueId) {
18179
- issueService.invalidateCache();
18180
- queryClient.invalidateQueries({ queryKey: ["contentIssues"] });
18181
- queryClient.invalidateQueries({ queryKey: ["issue", issueId] });
18182
- }
18183
- function notifyIssueUpdated(issueId) {
18184
- SDKManager.getInstance().eventBus.emit("issue:updated", issueId);
18185
- }
18186
- function applyIssueMutationEffects(issueId) {
18187
- invalidateIssueQueries(issueId);
18188
- notifyIssueUpdated(issueId);
18189
- }
18190
18421
  function useJiraIssueSync(issue) {
18191
18422
  const [isSyncingAll, setIsSyncingAll] = useState(false);
18192
18423
  const mapping = getPrimaryJiraMapping(issue);
@@ -18770,12 +19001,13 @@ function ResizableSplitPane({
18770
19001
  var _a;
18771
19002
  event.preventDefault();
18772
19003
  (_a = dragCleanupRef.current) == null ? void 0 : _a.call(dragCleanupRef);
19004
+ const releaseScopes = /* @__PURE__ */ new Set([document, event.currentTarget.getRootNode()]);
18773
19005
  const handleDocumentMouseMove = (moveEvent) => {
18774
19006
  updateRatio(moveEvent.clientX);
18775
19007
  };
18776
19008
  const stopDragging = () => {
18777
19009
  document.removeEventListener("mousemove", handleDocumentMouseMove);
18778
- document.removeEventListener("mouseup", stopDragging);
19010
+ releaseScopes.forEach((scope) => scope.removeEventListener("mouseup", stopDragging));
18779
19011
  window.removeEventListener("blur", stopDragging);
18780
19012
  if (dragCleanupRef.current === stopDragging) {
18781
19013
  dragCleanupRef.current = null;
@@ -18783,7 +19015,7 @@ function ResizableSplitPane({
18783
19015
  };
18784
19016
  dragCleanupRef.current = stopDragging;
18785
19017
  document.addEventListener("mousemove", handleDocumentMouseMove);
18786
- document.addEventListener("mouseup", stopDragging);
19018
+ releaseScopes.forEach((scope) => scope.addEventListener("mouseup", stopDragging));
18787
19019
  window.addEventListener("blur", stopDragging);
18788
19020
  },
18789
19021
  [updateRatio]
@@ -21232,9 +21464,6 @@ const svg = merge([aria, svg$1, xlink, xmlns, xml], "svg");
21232
21464
  function stringify(values) {
21233
21465
  return values.join(" ").trim();
21234
21466
  }
21235
- function getDefaultExportFromCjs(x) {
21236
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
21237
- }
21238
21467
  var cjs$2 = {};
21239
21468
  var cjs$1;
21240
21469
  var hasRequiredCjs$2;
@@ -34839,9 +35068,20 @@ const markdownComponents = {
34839
35068
  h2: ({ children }) => /* @__PURE__ */ jsx("h2", { className: "my-3 whitespace-pre-wrap text-lg font-semibold text-text-primary", children }),
34840
35069
  h3: ({ children }) => /* @__PURE__ */ jsx("h3", { className: "my-2.5 whitespace-pre-wrap text-base font-semibold text-text-primary", children }),
34841
35070
  p: ({ children }) => /* @__PURE__ */ jsx("p", { className: "my-2 whitespace-pre-wrap text-text-primary", children }),
34842
- ul: ({ children }) => /* @__PURE__ */ jsx("ul", { className: "my-2 list-disc pl-5 text-text-primary", children }),
35071
+ // 노션 할 일 블록은 GFM 작업 목록(`- [ ]`)으로 들어온다. 글머리표 대신 체크박스가 그 자리를 맡는다.
35072
+ ul: ({ children, className }) => (className == null ? void 0 : className.includes("contains-task-list")) ? /* @__PURE__ */ jsx("ul", { className: "my-2 list-none pl-0 text-text-primary [li_&]:pl-5", children }) : /* @__PURE__ */ jsx("ul", { className: "my-2 list-disc pl-5 text-text-primary", children }),
34843
35073
  ol: ({ children }) => /* @__PURE__ */ jsx("ol", { className: "my-2 list-decimal pl-5 text-text-primary", children }),
34844
35074
  li: ({ children }) => /* @__PURE__ */ jsx("li", { className: "my-1", children }),
35075
+ input: ({ type, checked }) => type === "checkbox" ? /* @__PURE__ */ jsx(
35076
+ "input",
35077
+ {
35078
+ type: "checkbox",
35079
+ checked,
35080
+ disabled: true,
35081
+ readOnly: true,
35082
+ className: "mr-2 align-middle accent-brand"
35083
+ }
35084
+ ) : null,
34845
35085
  code: ({ children, className }) => {
34846
35086
  const isInline = !className;
34847
35087
  if (isInline) {
@@ -34858,7 +35098,8 @@ const markdownComponents = {
34858
35098
  // 깊이만큼 밀린다.
34859
35099
  details: ({ children }) => /* @__PURE__ */ jsx("details", { className: "my-2 [&>*:not(summary)]:pl-4", children }),
34860
35100
  summary: ({ children }) => /* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-text-primary marker:text-text-tertiary", children }),
34861
- a: ({ href, children }) => /* @__PURE__ */ jsx(
35101
+ // 노션의 빈 파일·PDF 블록은 `[pdf]()` 로 들어온다. 빈 href 는 현재 페이지로 이동하므로 글자로만 둔다.
35102
+ a: ({ href, children }) => href ? /* @__PURE__ */ jsx(
34862
35103
  "a",
34863
35104
  {
34864
35105
  href,
@@ -34867,7 +35108,7 @@ const markdownComponents = {
34867
35108
  className: "text-brand underline underline-offset-2 hover:text-brand-hover",
34868
35109
  children
34869
35110
  }
34870
- ),
35111
+ ) : /* @__PURE__ */ jsx("span", { className: "text-text-secondary", children }),
34871
35112
  blockquote: ({ children }) => /* @__PURE__ */ jsx("blockquote", { className: "my-2 border-l-4 border-line-strong pl-3 italic text-text-secondary", children }),
34872
35113
  hr: () => /* @__PURE__ */ jsx("hr", { className: "my-4 border-0 border-t border-line" }),
34873
35114
  strong: ({ children }) => /* @__PURE__ */ jsx("strong", { className: "font-semibold", children }),
@@ -35354,6 +35595,10 @@ function ImageViewer({
35354
35595
  title = "이미지 전체화면 보기"
35355
35596
  }) {
35356
35597
  const portalContainer = usePortalContainer();
35598
+ const dismissRef = useShadowOutsideDismiss(
35599
+ useCallback(() => onOpenChange(false), [onOpenChange]),
35600
+ { focusOutside: false }
35601
+ );
35357
35602
  return /* @__PURE__ */ jsx(Dialog$1, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogPortal$1, { container: portalContainer, children: [
35358
35603
  /* @__PURE__ */ jsx(
35359
35604
  DialogOverlay$1,
@@ -35368,6 +35613,7 @@ function ImageViewer({
35368
35613
  /* @__PURE__ */ jsxs(
35369
35614
  DialogContent$1,
35370
35615
  {
35616
+ ref: dismissRef,
35371
35617
  onEscapeKeyDown: stopEscapePropagation(),
35372
35618
  style: {
35373
35619
  left: `calc(50% - (var(${BODY_SCROLLBAR_WIDTH_CSS_VAR}, 0px) / 2))`
@@ -35405,6 +35651,11 @@ function ImageViewer({
35405
35651
  )
35406
35652
  ] }) });
35407
35653
  }
35654
+ function orderScreenshotsForDisplay(urls) {
35655
+ if (urls.length !== 2) return [...urls];
35656
+ const [full, element2] = urls;
35657
+ return [element2, full];
35658
+ }
35408
35659
  function parseScreenshotUrls(screenshot) {
35409
35660
  if (Array.isArray(screenshot)) {
35410
35661
  return screenshot.filter((url) => typeof url === "string" && url.length > 0);
@@ -35427,7 +35678,7 @@ function parseScreenshotUrls(screenshot) {
35427
35678
  return [screenshot];
35428
35679
  }
35429
35680
  function IssueScreenshot({ screenshot }) {
35430
- const screenshotUrls = parseScreenshotUrls(screenshot);
35681
+ const screenshotUrls = orderScreenshotsForDisplay(parseScreenshotUrls(screenshot));
35431
35682
  const [selectedImageUrl, setSelectedImageUrl] = useState(
35432
35683
  screenshotUrls[0] ?? null
35433
35684
  );
@@ -37839,6 +38090,7 @@ function IssueStickersContainer$1({
37839
38090
  [clearClosingCluster, collapseExpandedCluster, expandedClusterId]
37840
38091
  );
37841
38092
  useEffect(() => {
38093
+ var _a;
37842
38094
  if (!expandedClusterId) return void 0;
37843
38095
  const handlePointerDown = (event) => {
37844
38096
  const root2 = rootRef.current;
@@ -37847,8 +38099,9 @@ function IssueStickersContainer$1({
37847
38099
  collapseExpandedCluster();
37848
38100
  }
37849
38101
  };
37850
- document.addEventListener("pointerdown", handlePointerDown, true);
37851
- return () => document.removeEventListener("pointerdown", handlePointerDown, true);
38102
+ const scopes = /* @__PURE__ */ new Set([document, ((_a = rootRef.current) == null ? void 0 : _a.getRootNode()) ?? document]);
38103
+ scopes.forEach((scope) => scope.addEventListener("pointerdown", handlePointerDown, true));
38104
+ return () => scopes.forEach((scope) => scope.removeEventListener("pointerdown", handlePointerDown, true));
37852
38105
  }, [collapseExpandedCluster, expandedClusterId]);
37853
38106
  if (!visible) {
37854
38107
  return null;
@@ -38112,6 +38365,9 @@ function useKeyboardShortcuts(isCreatingIssueRef, onToggleIssueMode, onToggleRec
38112
38365
  return;
38113
38366
  }
38114
38367
  if (isRecordingShortcut(eventLike)) {
38368
+ if (isIssueFormOpen) {
38369
+ return;
38370
+ }
38115
38371
  e.preventDefault();
38116
38372
  e.stopPropagation();
38117
38373
  if (isProcessingRecordingRef.current) {
@@ -38439,15 +38695,16 @@ function useContentAppState() {
38439
38695
  }, [isCreatingIssue]);
38440
38696
  const handleIssueCreated = useCallback(
38441
38697
  async (hasIntegrationFailure = false) => {
38698
+ const hadVideo = Boolean(clickPosition == null ? void 0 : clickPosition.videoFile);
38442
38699
  clearClickPosition();
38443
38700
  screenRecording.clearRecordedFile();
38444
38701
  await loadIssues();
38445
38702
  await toggleIssueMode(false);
38446
38703
  if (!hasIntegrationFailure) {
38447
- showToast("이슈가 생성되었습니다.");
38704
+ showToast(hadVideo ? VIDEO_UPLOAD_COPY.created : "이슈가 생성되었습니다.");
38448
38705
  }
38449
38706
  },
38450
- [clearClickPosition, loadIssues, screenRecording, toggleIssueMode, showToast]
38707
+ [clickPosition, clearClickPosition, loadIssues, screenRecording, toggleIssueMode, showToast]
38451
38708
  );
38452
38709
  return {
38453
38710
  // 상태
@@ -38476,6 +38733,31 @@ function useContentAppState() {
38476
38733
  setFieldFilters
38477
38734
  };
38478
38735
  }
38736
+ function useWidgetVideoUploads(projectId) {
38737
+ const [states, setStates] = useState([]);
38738
+ useEffect(() => getWidgetVideoUploadQueue().subscribe(setStates), []);
38739
+ useEffect(() => {
38740
+ if (!projectId) return;
38741
+ void resumeWidgetIssueUploads(projectId).then((count) => {
38742
+ if (count > 0) toast.info(VIDEO_UPLOAD_COPY.resumed(count));
38743
+ void getWidgetVideoUploadQueue().pruneExpired();
38744
+ void getWidgetAttachmentUploadQueue().pruneExpired();
38745
+ });
38746
+ }, [projectId]);
38747
+ useEffect(() => {
38748
+ const handleBeforeUnload = (event) => {
38749
+ if (getWidgetVideoUploadQueue().hasActiveUploads() || getWidgetAttachmentUploadQueue().hasActiveUploads()) {
38750
+ event.preventDefault();
38751
+ }
38752
+ };
38753
+ window.addEventListener("beforeunload", handleBeforeUnload);
38754
+ return () => window.removeEventListener("beforeunload", handleBeforeUnload);
38755
+ }, []);
38756
+ const retryFailedUploads = () => {
38757
+ states.filter((state) => state.status === "failed").forEach((state) => retryWidgetIssueUploads(state.issueId));
38758
+ };
38759
+ return { uploadProgress: summarizeVideoUploads(states), retryFailedUploads };
38760
+ }
38479
38761
  const STORAGE_KEY = "issue-sticker-sticker-render-mode";
38480
38762
  const QUERY_ROOT = ["stickerRenderMode"];
38481
38763
  function readLocalRenderMode() {
@@ -38841,7 +39123,7 @@ function MoreMenu({
38841
39123
  },
38842
39124
  {
38843
39125
  id: "unrendered",
38844
- label: unrenderedStickerCount > 0 ? `미표시 스티커 ${unrenderedStickerCount}개` : "미표시 스티커 없음",
39126
+ label: unrenderedStickerCount > 0 ? `표시하지 못한 스티커 ${unrenderedStickerCount}개` : "표시하지 못한 스티커 없음",
38845
39127
  icon: /* @__PURE__ */ jsx(CircleAlert, { size: ICON_SIZE }),
38846
39128
  onClick: onOpenUnrenderedStickers,
38847
39129
  // 0개일 때도 노출한다. 숨기면 목록을 열어 확인할 진입점 자체가 없어진다.
@@ -39086,6 +39368,35 @@ const TOOLBAR_STYLES = `
39086
39368
  border: 2px solid hsl(var(--surface-1));
39087
39369
  pointer-events: none;
39088
39370
  }
39371
+ .toolbar-upload {
39372
+ width: 34px;
39373
+ height: 34px;
39374
+ display: flex;
39375
+ align-items: center;
39376
+ justify-content: center;
39377
+ flex: none;
39378
+ border-radius: 50%;
39379
+ border: none;
39380
+ background: transparent;
39381
+ padding: 0;
39382
+ outline: none;
39383
+ }
39384
+ button.toolbar-upload { cursor: pointer; }
39385
+ .toolbar-upload:focus-visible { box-shadow: var(--shadow-focus); }
39386
+ .toolbar-upload svg { transform: rotate(-90deg); }
39387
+ .toolbar-upload-track {
39388
+ fill: none;
39389
+ stroke: hsl(var(--border-subtle));
39390
+ stroke-width: 2.5;
39391
+ }
39392
+ .toolbar-upload-bar {
39393
+ fill: none;
39394
+ stroke: var(--brand);
39395
+ stroke-width: 2.5;
39396
+ stroke-linecap: round;
39397
+ transition: stroke-dashoffset 0.3s ease;
39398
+ }
39399
+ .toolbar-upload[data-failed="true"] .toolbar-upload-bar { stroke: hsl(var(--danger)); }
39089
39400
 
39090
39401
  .toolbar-menu {
39091
39402
  position: absolute;
@@ -39363,6 +39674,13 @@ function formatElapsed(startedAt, now2) {
39363
39674
  const ss = String(seconds % 60).padStart(2, "0");
39364
39675
  return `${mm}:${ss}`;
39365
39676
  }
39677
+ const UPLOAD_RING_RADIUS = 7;
39678
+ const UPLOAD_RING_LENGTH = 2 * Math.PI * UPLOAD_RING_RADIUS;
39679
+ function formatUploadLabel({ percent: percent2, count, failed }) {
39680
+ if (failed) return "영상 업로드 실패";
39681
+ const waiting = count > 1 ? ` · 대기 ${count - 1}개` : "";
39682
+ return `영상 업로드 중 ${percent2}%${waiting}`;
39683
+ }
39366
39684
  function Toolbar({
39367
39685
  onCreateIssue,
39368
39686
  onToggleStickers,
@@ -39384,7 +39702,9 @@ function Toolbar({
39384
39702
  targets,
39385
39703
  account,
39386
39704
  blocked,
39387
- filter: filter2
39705
+ filter: filter2,
39706
+ uploadProgress,
39707
+ onUploadRetry
39388
39708
  }) {
39389
39709
  const rootRef = useRef(null);
39390
39710
  const [internalOpen, setInternalOpen] = useState(false);
@@ -39488,6 +39808,20 @@ function Toolbar({
39488
39808
  }, []);
39489
39809
  const anchor = toCssAnchor(placement);
39490
39810
  const menuPlacement = getMenuPlacement(placement);
39811
+ const uploadRing = uploadProgress ? /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 18 18", "aria-hidden": "true", children: [
39812
+ /* @__PURE__ */ jsx("circle", { className: "toolbar-upload-track", cx: "9", cy: "9", r: UPLOAD_RING_RADIUS }),
39813
+ /* @__PURE__ */ jsx(
39814
+ "circle",
39815
+ {
39816
+ className: "toolbar-upload-bar",
39817
+ cx: "9",
39818
+ cy: "9",
39819
+ r: UPLOAD_RING_RADIUS,
39820
+ strokeDasharray: UPLOAD_RING_LENGTH,
39821
+ strokeDashoffset: uploadProgress.failed ? 0 : UPLOAD_RING_LENGTH * (1 - uploadProgress.percent / 100)
39822
+ }
39823
+ )
39824
+ ] }) : null;
39491
39825
  const idleBody = /* @__PURE__ */ jsxs(TooltipProvider, { delayDuration: 240, skipDelayDuration: 120, disableHoverableContent: true, children: [
39492
39826
  /* @__PURE__ */ jsxs(Tooltip, { children: [
39493
39827
  /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
@@ -39526,6 +39860,30 @@ function Toolbar({
39526
39860
  /* @__PURE__ */ jsx("span", { className: "block font-normal opacity-70", children: "공유할 화면을 선택하는 창이 열립니다" })
39527
39861
  ] })
39528
39862
  ] }),
39863
+ uploadProgress ? /* @__PURE__ */ jsxs(Tooltip, { children: [
39864
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: uploadProgress.failed && onUploadRetry ? /* @__PURE__ */ jsx(
39865
+ "button",
39866
+ {
39867
+ type: "button",
39868
+ className: "toolbar-upload",
39869
+ "aria-label": ISSUE_UPLOAD_COPY.retry,
39870
+ "data-failed": true,
39871
+ onClick: onUploadRetry,
39872
+ children: uploadRing
39873
+ }
39874
+ ) : /* @__PURE__ */ jsx(
39875
+ "span",
39876
+ {
39877
+ className: "toolbar-upload",
39878
+ role: "status",
39879
+ "aria-label": formatUploadLabel(uploadProgress),
39880
+ "data-failed": uploadProgress.failed,
39881
+ tabIndex: 0,
39882
+ children: uploadRing
39883
+ }
39884
+ ) }),
39885
+ /* @__PURE__ */ jsx(TooltipContent, { side: "top", sideOffset: 10, children: formatUploadLabel(uploadProgress) })
39886
+ ] }) : null,
39529
39887
  /* @__PURE__ */ jsx("div", { className: "toolbar-divider" }),
39530
39888
  /* @__PURE__ */ jsxs(
39531
39889
  "button",
@@ -39577,7 +39935,7 @@ function Toolbar({
39577
39935
  children: /* @__PURE__ */ jsx(X$1, { size: 15 })
39578
39936
  }
39579
39937
  )
39580
- ] }) : state === "writing" ? /* @__PURE__ */ jsx("span", { className: "toolbar-hint", children: "이슈를 작성 중입니다" }) : state === "recording" ? /* @__PURE__ */ jsxs(Fragment, { children: [
39938
+ ] }) : state === "recording" ? /* @__PURE__ */ jsxs(Fragment, { children: [
39581
39939
  /* @__PURE__ */ jsx("span", { className: "toolbar-pulse", "aria-hidden": "true" }),
39582
39940
  /* @__PURE__ */ jsx("span", { className: "toolbar-elapsed", "aria-hidden": "true", children: formatElapsed(recordingStartedAt, now2) }),
39583
39941
  /* @__PURE__ */ jsx("div", { className: "toolbar-divider" }),
@@ -39592,6 +39950,7 @@ function Toolbar({
39592
39950
  }
39593
39951
  )
39594
39952
  ] }) : idleBody;
39953
+ if (state === "writing") return null;
39595
39954
  return /* @__PURE__ */ jsxs(Fragment, { children: [
39596
39955
  /* @__PURE__ */ jsx("style", { children: TOOLBAR_STYLES }),
39597
39956
  /* @__PURE__ */ jsxs(Popover, { open: filterOpen, onOpenChange: setFilterOpen, children: [
@@ -39747,6 +40106,7 @@ function ContentAppWrapper({
39747
40106
  const { renderMode, saveRenderMode } = useStickerRenderMode();
39748
40107
  const { isMember } = useAuthContext();
39749
40108
  const { selectedProjectId } = useProject();
40109
+ const { uploadProgress, retryFailedUploads } = useWidgetVideoUploads(selectedProjectId);
39750
40110
  const filterProjectId = isMember ? selectedProjectId : null;
39751
40111
  const { data: filterGroups = [] } = useQuery({
39752
40112
  queryKey: ["issueFilterGroups", filterProjectId],
@@ -39789,6 +40149,8 @@ function ContentAppWrapper({
39789
40149
  recordingStartedAt: screenRecording.startedAt,
39790
40150
  showStickers,
39791
40151
  toolbar,
40152
+ uploadProgress,
40153
+ onUploadRetry: retryFailedUploads,
39792
40154
  stickerRenderMode: renderMode,
39793
40155
  onToggleStickerRenderMode: () => void saveRenderMode(nextRenderMode),
39794
40156
  unrenderedStickerCount: unrenderedCount,
@@ -39884,12 +40246,13 @@ function AuthGate() {
39884
40246
  ) })
39885
40247
  ] });
39886
40248
  }
39887
- const globalsCSS = `:root,:host{color-scheme:light;--brand-h: 150;--brand-s: 100%;--brand-l: 34%;--brand-hsl: var(--brand-h) var(--brand-s) var(--brand-l);--brand: hsl(var(--brand-hsl));--brand-hover: hsl(var(--brand-h) calc(var(--brand-s) + 3%) calc(var(--brand-l) - 4%));--brand-active: hsl(var(--brand-h) calc(var(--brand-s) + 2%) calc(var(--brand-l) - 8%));--brand-subtle: hsl(var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .14);--brand-border: hsl(var(--brand-h) calc(var(--brand-s) + 8%) calc(var(--brand-l) + 8%) / .34);--brand-fg: hsl(0 0% 100%);--brand-ring: hsl(var(--brand-h) calc(var(--brand-s) + 12%) calc(var(--brand-l) + 10%) / .22);--font-sans: "Pretendard", -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif;--font-display: var(--font-sans);--font-mono: var(--font-sans);--surface-0: 0 0% 99%;--surface-1: 0 0% 100%;--surface-2: 144 8% 96%;--surface-3: 144 6% 93%;--surface-inset: 144 6% 95%;--overlay-backdrop: hsl(0 0% 0% / .24);--overlay-backdrop-strong: hsl(0 0% 0% / .48);--text-primary: 150 10% 12%;--text-secondary: 148 6% 36%;--text-tertiary: 145 5% 42%;--text-disabled: 145 4% 70%;--text-inverse: 0 0% 100%;--border-subtle: 144 8% 91%;--border-default: 144 6% 85%;--border-strong: 144 5% 72%;--border-focus: var(--brand-h) var(--brand-s) var(--brand-l);--success: var(--brand-h) var(--brand-s) var(--brand-l);--success-subtle: var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .14;--success-surface: var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .24;--warning: 34 82% 52%;--warning-subtle: 34 82% 52% / .14;--danger: 3 68% 56%;--danger-subtle: 3 68% 56% / .12;--danger-deep: 3 62% 40%;--info: 202 52% 44%;--info-subtle: 202 52% 44% / .12;--accent-terra: 13 52% 47%;--accent-terra-subtle: 13 52% 47% / .1;--accent-terra-deep: 13 48% 44%;--accent-blue: 213 86% 56%;--accent-blue-subtle: 213 92% 56% / .12;--accent-blue-deep: 216 78% 40%;--accent-blue-border: 213 86% 62% / .36;--accent-cream: 38 52% 88%;--accent-cream-warm: 40 56% 95%;--accent-cream-deep: 38 48% 82%;--accent-highlight: 55 96% 70%;--accent-ink: 32 13% 11%;--radius-xs: 4px;--radius-sm: 8px;--radius-md: 12px;--radius-lg: 16px;--radius-xl: 20px;--radius-2xl: 24px;--radius-pill: 9999px;--shadow-xs: 0 1px 2px 0 hsl(0 0% 0% / .04);--shadow-sm: 0 1px 3px 0 hsl(0 0% 0% / .06), 0 1px 2px -1px hsl(0 0% 0% / .06);--shadow-md: 0 4px 6px -1px hsl(0 0% 0% / .06), 0 2px 4px -2px hsl(0 0% 0% / .04);--shadow-lg: 0 10px 15px -3px hsl(0 0% 0% / .06), 0 4px 6px -4px hsl(0 0% 0% / .04);--shadow-xl: 0 20px 25px -5px hsl(0 0% 0% / .06), 0 8px 10px -6px hsl(0 0% 0% / .04);--shadow-focus: 0 0 0 3px var(--brand-ring);--shadow-inset: inset 0 1px 2px 0 hsl(0 0% 0% / .04);--shadow-brand: 0 2px 8px hsl(var(--brand-h) calc(var(--brand-s) - 60%) calc(var(--brand-l) - 14%) / .24), 0 6px 20px hsl(var(--brand-h) calc(var(--brand-s) - 70%) calc(var(--brand-l) - 19%) / .16);--duration-instant: 90ms;--duration-fast: .16s;--duration-base: .26s;--duration-out: .18s;--duration-slow: .36s;--ease-out: cubic-bezier(.23, 1, .32, 1);--ease-in-out: cubic-bezier(.45, 0, .15, 1);--ease-spring: cubic-bezier(.18, .94, .32, 1.08);--grid-line: 0 0% 92%}.dark,:host(.dark){color-scheme:dark;--brand-l: 34%;--brand-fg: hsl(0 0% 100%);--surface-0: 150 8% 7%;--surface-1: 150 6% 10%;--surface-2: 150 5% 14%;--surface-3: 150 4% 18%;--surface-inset: 150 6% 6%;--overlay-backdrop: hsl(0 0% 0% / .56);--overlay-backdrop-strong: hsl(0 0% 0% / .8);--text-primary: 40 16% 93%;--text-secondary: 36 8% 68%;--text-tertiary: 34 6% 50%;--text-disabled: 30 5% 34%;--text-inverse: 150 8% 10%;--border-subtle: 150 6% 16%;--border-default: 150 5% 22%;--border-strong: 150 4% 34%;--success: var(--brand-h) var(--brand-s) var(--brand-l);--success-subtle: var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .14;--success-surface: var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .24;--warning: 34 82% 62%;--danger: 2 70% 64%;--danger-deep: 2 80% 76%;--info: 202 54% 62%;--accent-terra: 13 56% 62%;--accent-terra-subtle: 13 56% 62% / .14;--accent-terra-deep: 13 52% 56%;--accent-blue: 210 92% 68%;--accent-blue-subtle: 210 92% 68% / .18;--accent-blue-deep: 209 100% 78%;--accent-blue-border: 210 92% 72% / .44;--accent-cream: 38 30% 26%;--accent-cream-warm: 38 22% 18%;--accent-cream-deep: 38 26% 32%;--accent-highlight: 55 96% 70%;--accent-ink: 32 13% 8%;--shadow-xs: 0 1px 2px 0 hsl(0 0% 0% / .2);--shadow-sm: 0 1px 3px 0 hsl(0 0% 0% / .3), 0 1px 2px -1px hsl(0 0% 0% / .24);--shadow-md: 0 4px 6px -1px hsl(0 0% 0% / .34), 0 2px 4px -2px hsl(0 0% 0% / .2);--shadow-lg: 0 10px 15px -3px hsl(0 0% 0% / .38), 0 4px 6px -4px hsl(0 0% 0% / .24);--shadow-xl: 0 20px 25px -5px hsl(0 0% 0% / .44), 0 8px 10px -6px hsl(0 0% 0% / .28);--shadow-inset: inset 0 1px 2px 0 hsl(0 0% 0% / .16);--shadow-brand: 0 2px 8px hsl(var(--brand-h) calc(var(--brand-s) - 60%) calc(var(--brand-l) - 24%) / .44), 0 6px 20px hsl(0 0% 0% / .32);--grid-line: 150 6% 14%}*{border-color:hsl(var(--border-default))}html{font-family:var(--font-sans),ui-sans-serif,system-ui,-apple-system,sans-serif;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;font-feature-settings:"cv11","ss01","ss03";background-color:hsl(var(--surface-0))}body{margin:0;min-height:100vh;color:hsl(var(--text-primary));background-color:hsl(var(--surface-0))}::-moz-selection{background-color:hsl(var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 16%) / .22);color:hsl(var(--text-primary))}::selection{background-color:hsl(var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 16%) / .22);color:hsl(var(--text-primary))}code,kbd,samp,pre{font-family:var(--font-mono),ui-monospace,SFMono-Regular,Menlo,monospace;font-feature-settings:"ss01","ss02","cv11"}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:hsl(var(--border-strong) / .52);border-radius:var(--radius-pill);border:2px solid transparent;background-clip:padding-box}::-webkit-scrollbar-thumb:hover{background:hsl(var(--border-strong) / .9);background-clip:padding-box;border:2px solid transparent}.app-canvas,.grid-canvas{background-color:hsl(var(--surface-0))}.onboarding-canvas{word-break:keep-all;overflow-wrap:break-word;--surface-0: var(--brand-h) var(--brand-s) var(--brand-l);--surface-1: 0 0% 100%;--surface-2: var(--brand-h) 62% 28%;--surface-3: var(--brand-h) 60% 25%;--surface-inset: var(--brand-h) 62% 28%;--text-primary: 0 0% 100%;--text-secondary: var(--brand-h) 46% 90%;--text-tertiary: var(--brand-h) 34% 84%;--text-disabled: var(--brand-h) 20% 72%;--border-subtle: var(--brand-h) 44% 52%;--border-default: var(--brand-h) 40% 58%;--border-strong: var(--brand-h) 36% 70%;--border-focus: 0 0% 100%;--brand-hsl: 0 0% 100%;--brand: hsl(var(--brand-hsl));--brand-hover: hsl(var(--brand-h) 24% 94%);--brand-active: hsl(var(--brand-h) 20% 88%);--brand-fg: hsl(var(--brand-h) var(--brand-s) 24%);--brand-ring: hsl(0 0% 100% / .4);--danger: 6 96% 86%;--danger-subtle: 6 96% 86% / .18;--danger-deep: 6 96% 92%;--warning: 42 96% 82%;--warning-subtle: 42 96% 82% / .18}.onboarding-canvas .bg-surface-1,.onboarding-canvas input,.onboarding-canvas textarea,.onboarding-canvas [role=combobox]{--text-primary: 150 10% 12%;--text-secondary: 148 6% 36%;--text-tertiary: 145 5% 42%;--surface-2: 144 8% 96%;--surface-inset: 144 6% 95%;--border-subtle: 144 8% 91%;--border-default: 144 6% 85%;--brand-hsl: var(--brand-h) var(--brand-s) var(--brand-l);--brand: hsl(var(--brand-hsl));--brand-hover: hsl(var(--brand-h) calc(var(--brand-s) + 3%) calc(var(--brand-l) - 4%));--brand-active: hsl(var(--brand-h) calc(var(--brand-s) + 2%) calc(var(--brand-l) - 8%));--brand-fg: hsl(0 0% 100%);--brand-ring: hsl(var(--brand-h) calc(var(--brand-s) + 12%) calc(var(--brand-l) + 10%) / .22);--warning: 34 82% 52%;--warning-subtle: 34 82% 52% / .14;--danger: 3 68% 56%;--danger-subtle: 3 68% 56% / .12;--danger-deep: 3 62% 40%}@keyframes onboarding-step-in{0%{opacity:0;transform:translate(96px)}to{opacity:1;transform:translate(0)}}.onboarding-step-in{animation:onboarding-step-in var(--duration-slow) var(--ease-out) forwards}@keyframes onboarding-enter-up{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.onboarding-enter{position:fixed;top:0;right:0;bottom:0;left:0;overflow-x:hidden;overflow-y:auto;animation:onboarding-enter-up var(--duration-base) var(--ease-out) forwards}body:has(.onboarding-canvas){background-color:hsl(var(--brand-h) var(--brand-s) var(--brand-l))}.panel-shell,.surface-shell{border:1px solid hsl(var(--border-subtle));border-radius:var(--radius-xl);background:hsl(var(--surface-1));box-shadow:var(--shadow-sm)}.panel-shell-muted,.surface-shell-muted{background:hsl(var(--surface-2));box-shadow:var(--shadow-xs)}.panel-shell-subtle{border:1px solid hsl(var(--border-subtle));border-radius:var(--radius-lg);background:hsl(var(--surface-1));box-shadow:var(--shadow-xs)}.panel-shell-elevated{border:1px solid hsl(var(--border-default));border-radius:var(--radius-xl);background:hsl(var(--surface-1));box-shadow:var(--shadow-md)}.utility-chip,.floating-chip{display:inline-flex;align-items:center;gap:8px;border:1px solid hsl(var(--border-default));border-radius:var(--radius-pill);background:hsl(var(--surface-1));box-shadow:var(--shadow-xs)}.hairline{border-bottom:1px solid hsl(var(--border-subtle))}.mono-label{font-family:var(--font-mono),ui-monospace,monospace;font-size:11px;text-transform:uppercase;color:hsl(var(--text-tertiary))}*,: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:var(--font-sans),ui-sans-serif,system-ui,sans-serif;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:var(--font-mono),ui-monospace,SFMono-Regular,Menlo,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}:root,:host{--font-sans: "Pretendard", -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif;--font-mono: var(--font-sans);--issue-marker-expand-duration: .52s;--surface-0: 0 0% 99%;--surface-1: 0 0% 100%;--surface-2: 144 8% 96%;--surface-3: 144 6% 93%;--surface-inset: 144 6% 95%;--overlay-backdrop: hsl(0 0% 0% / .24);--overlay-backdrop-strong: hsl(0 0% 0% / .48);--text-primary: 150 10% 12%;--text-secondary: 148 6% 36%;--text-tertiary: 145 5% 52%;--text-disabled: 145 4% 70%;--border-subtle: 144 8% 91%;--border-default: 144 6% 85%;--border-strong: 144 5% 72%;--grid-line: 0 0% 92%;--shadow-xs: 0 1px 2px 0 hsl(0 0% 0% / .04);--shadow-sm: 0 1px 3px 0 hsl(0 0% 0% / .06), 0 1px 2px -1px hsl(0 0% 0% / .06);--shadow-md: 0 4px 6px -1px hsl(0 0% 0% / .06), 0 2px 4px -2px hsl(0 0% 0% / .04);--shadow-lg: 0 10px 15px -3px hsl(0 0% 0% / .06), 0 4px 6px -4px hsl(0 0% 0% / .04);--shadow-xl: 0 20px 25px -5px hsl(0 0% 0% / .06), 0 8px 10px -6px hsl(0 0% 0% / .04);--shadow-focus: 0 0 0 4px var(--brand-ring);--shadow-inset: inset 0 1px 2px 0 hsl(0 0% 0% / .04)}*{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}#issue-sticker-shadow-root{all:initial;display:block;background-color:transparent;--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1));font-family:var(--font-sans);line-height:1.5}.\\!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}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.inset-x-0{left:0;right:0}.inset-x-1{left:4px;right:4px}.inset-y-0{top:0;bottom:0}.-bottom-px{bottom:-1px}.bottom-0{bottom:0}.bottom-4{bottom:16px}.bottom-6{bottom:24px}.left-0{left:0}.left-1\\/2{left:50%}.left-2{left:8px}.left-4{left:16px}.left-\\[50\\%\\]{left:50%}.right-0{right:0}.right-2{right:8px}.right-3{right:12px}.right-4{right:16px}.right-5{right:20px}.right-6{right:24px}.top-0{top:0}.top-1{top:4px}.top-1\\/2{top:50%}.top-2{top:8px}.top-3{top:12px}.top-4{top:16px}.top-5{top:20px}.top-\\[50\\%\\]{top:50%}.top-\\[calc\\(\\(3\\.5rem-1\\.75rem\\)\\/2\\)\\]{top:14px}.top-full{top:100%}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-\\[1000000\\]{z-index:1000000}.z-\\[1000003\\]{z-index:1000003}.z-\\[1000004\\]{z-index:1000004}.z-\\[1000005\\]{z-index:1000005}.z-\\[1000006\\]{z-index:1000006}.z-\\[1000007\\]{z-index:1000007}.z-\\[1000008\\]{z-index:1000008}.z-\\[1000010\\]{z-index:1000010}.z-\\[1000011\\]{z-index:1000011}.z-\\[10001\\]{z-index:10001}.z-\\[999999\\]{z-index:999999}.z-\\[9999\\]{z-index:9999}.m-0{margin:0}.-mx-2{margin-left:-8px;margin-right:-8px}.mx-3{margin-left:12px;margin-right:12px}.my-1{margin-top:4px;margin-bottom:4px}.my-2{margin-top:8px;margin-bottom:8px}.my-2\\.5{margin-top:10px;margin-bottom:10px}.my-3{margin-top:12px;margin-bottom:12px}.my-4{margin-top:16px;margin-bottom:16px}.mb-0\\.5{margin-bottom:2px}.mb-1{margin-bottom:4px}.mb-2{margin-bottom:8px}.mb-3{margin-bottom:12px}.mb-5{margin-bottom:20px}.ml-0\\.5{margin-left:2px}.ml-4{margin-left:16px}.mr-1\\.5{margin-right:6px}.mt-0{margin-top:0}.mt-0\\.5{margin-top:2px}.mt-1{margin-top:4px}.mt-2{margin-top:8px}.mt-3{margin-top:12px}.mt-4{margin-top:16px}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.aspect-square{aspect-ratio:1 / 1}.\\!h-auto{height:auto!important}.h-1\\.5{height:6px}.h-10{height:40px}.h-11{height:44px}.h-2{height:8px}.h-24{height:96px}.h-3{height:12px}.h-3\\.5{height:14px}.h-4{height:16px}.h-5{height:20px}.h-6{height:24px}.h-7{height:28px}.h-8{height:32px}.h-9{height:36px}.h-\\[1\\.4rem\\]{height:22.4px}.h-\\[100vh\\]{height:100vh}.h-\\[18px\\]{height:18px}.h-\\[220px\\]{height:220px}.h-\\[22px\\]{height:22px}.h-\\[30px\\]{height:30px}.h-\\[min\\(36vh\\,320px\\)\\]{height:min(36vh,320px)}.h-\\[min\\(480px\\,calc\\(100vh-64px\\)\\)\\]{height:min(480px,calc(100vh - 64px))}.h-\\[min\\(54vh\\,520px\\)\\]{height:min(54vh,520px)}.h-\\[min\\(560px\\,calc\\(100vh-32px\\)\\)\\]{height:min(560px,calc(100vh - 32px))}.h-\\[var\\(--issue-sticker-size\\)\\]{height:var(--issue-sticker-size)}.h-\\[var\\(--radix-select-trigger-height\\)\\]{height:var(--radix-select-trigger-height)}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.max-h-24{max-height:96px}.max-h-40{max-height:160px}.max-h-56{max-height:224px}.max-h-80{max-height:320px}.max-h-96{max-height:384px}.max-h-\\[150px\\]{max-height:150px}.max-h-\\[220px\\]{max-height:220px}.max-h-\\[320px\\]{max-height:320px}.max-h-\\[420px\\]{max-height:420px}.max-h-\\[90vh\\]{max-height:90vh}.max-h-\\[calc\\(100vh-3rem\\)\\]{max-height:calc(100vh - 48px)}.max-h-\\[min\\(80vh\\,640px\\)\\]{max-height:min(80vh,640px)}.min-h-0{min-height:0px}.min-h-11{min-height:44px}.min-h-\\[108px\\]{min-height:108px}.min-h-\\[120px\\]{min-height:120px}.min-h-\\[140px\\]{min-height:140px}.min-h-\\[220px\\]{min-height:220px}.w-0\\.5{width:2px}.w-1{width:4px}.w-1\\.5{width:6px}.w-1\\/2{width:50%}.w-10{width:40px}.w-12{width:48px}.w-14{width:56px}.w-16{width:64px}.w-2{width:8px}.w-3{width:12px}.w-3\\.5{width:14px}.w-4{width:16px}.w-5{width:20px}.w-6{width:24px}.w-7{width:28px}.w-72{width:288px}.w-8{width:32px}.w-80{width:320px}.w-9{width:36px}.w-\\[1\\.4rem\\]{width:22.4px}.w-\\[18px\\]{width:18px}.w-\\[22\\.5rem\\]{width:360px}.w-\\[22rem\\]{width:352px}.w-\\[30px\\]{width:30px}.w-\\[38px\\]{width:38px}.w-\\[calc\\(100vw-32px\\)\\]{width:calc(100vw - 32px)}.w-\\[min\\(20rem\\,calc\\(100vw_-_1\\.5rem\\)\\)\\]{width:min(320px,calc(100vw - 24px))}.w-\\[min\\(560px\\,calc\\(100vw-32px\\)\\)\\]{width:min(560px,calc(100vw - 32px))}.w-\\[var\\(--radix-popover-trigger-width\\)\\]{width:var(--radix-popover-trigger-width)}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.min-w-0{min-width:0px}.min-w-9{min-width:36px}.min-w-\\[12rem\\]{min-width:192px}.min-w-\\[200px\\]{min-width:200px}.min-w-\\[var\\(--radix-popover-trigger-width\\)\\]{min-width:var(--radix-popover-trigger-width)}.min-w-\\[var\\(--radix-select-trigger-width\\)\\]{min-width:var(--radix-select-trigger-width)}.max-w-\\[10rem\\]{max-width:160px}.max-w-\\[120px\\]{max-width:120px}.max-w-\\[160px\\]{max-width:160px}.max-w-\\[260px\\]{max-width:260px}.max-w-\\[280px\\]{max-width:280px}.max-w-\\[28rem\\]{max-width:448px}.max-w-\\[300px\\]{max-width:300px}.max-w-\\[360px\\]{max-width:360px}.max-w-\\[36rem\\]{max-width:576px}.max-w-\\[400px\\]{max-width:400px}.max-w-\\[420px\\]{max-width:420px}.max-w-\\[428px\\]{max-width:428px}.max-w-\\[480px\\]{max-width:480px}.max-w-\\[62ch\\]{max-width:62ch}.max-w-\\[640px\\]{max-width:640px}.max-w-\\[70ch\\]{max-width:70ch}.max-w-\\[90vw\\]{max-width:90vw}.max-w-\\[960px\\]{max-width:960px}.max-w-\\[calc\\(100vw-24px\\)\\]{max-width:calc(100vw - 24px)}.max-w-\\[var\\(--issue-sticker-size\\)\\]{max-width:var(--issue-sticker-size)}.max-w-full{max-width:100%}.max-w-md{max-width:448px}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.grow{flex-grow:1}.caption-bottom{caption-side:bottom}.border-collapse{border-collapse:collapse}.-translate-x-1{--tw-translate-x: -4px;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-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{--tw-translate-x: 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-x-1{--tw-translate-x: 4px;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-\\[-50\\%\\]{--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-x-\\[18px\\]{--tw-translate-x: 18px;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-\\[2px\\]{--tw-translate-x: 2px;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-\\[-50\\%\\]{--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))}.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 pulse-ring{0%,to{box-shadow:0 0 0 0 var(--brand-ring)}50%{box-shadow:0 0 0 8px transparent}}.animate-pulse-ring{animation:pulse-ring 1.8s var(--ease-in-out) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-col-resize{cursor:col-resize}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.resize-y{resize:vertical}.resize{resize:both}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.content-center{align-content:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0px}.gap-0\\.5{gap:2px}.gap-1{gap:4px}.gap-1\\.5{gap:6px}.gap-2{gap:8px}.gap-2\\.5{gap:10px}.gap-3{gap:12px}.gap-3\\.5{gap:14px}.gap-4{gap:16px}.gap-5{gap:20px}.gap-6{gap:24px}.gap-x-5{-moz-column-gap:20px;column-gap:20px}.gap-y-2{row-gap:8px}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(4px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(4px * var(--tw-space-y-reverse))}.space-y-1\\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(6px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(6px * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(8px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(8px * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(12px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(12px * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(16px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(16px * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(20px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(20px * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(24px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(24px * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-line-subtle>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-divide-opacity, 1))}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.break-keep{word-break:keep-all}.\\!rounded-none{border-radius:0!important}.rounded{border-radius:4px}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-\\[18px\\]{border-radius:18px}.rounded-\\[20px\\]{border-radius:20px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-xs{border-radius:var(--radius-xs)}.rounded-b-md{border-bottom-right-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.border{border-width:1px}.border-0{border-width:0px}.border-2{border-width:2px}.border-y{border-top-width:1px;border-bottom-width:1px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-t-0{border-top-width:0px}.border-dashed{border-style:dashed}.border-\\[hsl\\(144_8\\%_91\\%\\)\\]{--tw-border-opacity: 1;border-color:hsl(144 8% 91% / var(--tw-border-opacity, 1))}.border-brand{--tw-border-opacity: 1;border-color:hsl(var(--brand-hsl) / var(--tw-border-opacity, 1))}.border-brand-border{border-color:var(--brand-border)}.border-brand\\/30{border-color:hsl(var(--brand-hsl) / .3)}.border-brand\\/40{border-color:hsl(var(--brand-hsl) / .4)}.border-danger\\/20{border-color:hsl(var(--danger) / .2)}.border-danger\\/30{border-color:hsl(var(--danger) / .3)}.border-info\\/20{border-color:hsl(var(--info) / .2)}.border-info\\/30{border-color:hsl(var(--info) / .3)}.border-line{--tw-border-opacity: 1;border-color:hsl(var(--border-default) / var(--tw-border-opacity, 1))}.border-line-focus{--tw-border-opacity: 1;border-color:hsl(var(--border-focus) / var(--tw-border-opacity, 1))}.border-line-strong{--tw-border-opacity: 1;border-color:hsl(var(--border-strong) / var(--tw-border-opacity, 1))}.border-line-subtle{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}.border-line-subtle\\/50{border-color:hsl(var(--border-subtle) / .5)}.border-line-subtle\\/90{border-color:hsl(var(--border-subtle) / .9)}.border-slate-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-success{--tw-border-opacity: 1;border-color:hsl(var(--success) / var(--tw-border-opacity, 1))}.border-success\\/20{border-color:hsl(var(--success) / .2)}.border-success\\/30{border-color:hsl(var(--success) / .3)}.border-text-primary{--tw-border-opacity: 1;border-color:hsl(var(--text-primary) / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-warning\\/20{border-color:hsl(var(--warning) / .2)}.border-warning\\/30{border-color:hsl(var(--warning) / .3)}.border-white\\/70{border-color:#ffffffb3}.border-white\\/80{border-color:#fffc}.border-white\\/90{border-color:#ffffffe6}.border-l-brand{--tw-border-opacity: 1;border-left-color:hsl(var(--brand-hsl) / var(--tw-border-opacity, 1))}.\\!bg-success-surface{background-color:hsl(var(--success-surface))!important}.bg-\\[var\\(--overlay-backdrop-strong\\)\\]{background-color:var(--overlay-backdrop-strong)}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\\/10{background-color:#0000001a}.bg-black\\/40{background-color:#0006}.bg-black\\/80{background-color:#000c}.bg-brand{--tw-bg-opacity: 1;background-color:hsl(var(--brand-hsl) / var(--tw-bg-opacity, 1))}.bg-brand-subtle{background-color:var(--brand-subtle)}.bg-brand\\/10{background-color:hsl(var(--brand-hsl) / .1)}.bg-brand\\/5{background-color:hsl(var(--brand-hsl) / .05)}.bg-danger{--tw-bg-opacity: 1;background-color:hsl(var(--danger) / var(--tw-bg-opacity, 1))}.bg-danger-subtle{background-color:hsl(var(--danger-subtle))}.bg-danger\\/10{background-color:hsl(var(--danger) / .1)}.bg-info-subtle{background-color:hsl(var(--info-subtle))}.bg-line{--tw-bg-opacity: 1;background-color:hsl(var(--border-default) / var(--tw-bg-opacity, 1))}.bg-line-subtle{--tw-bg-opacity: 1;background-color:hsl(var(--border-subtle) / var(--tw-bg-opacity, 1))}.bg-success{--tw-bg-opacity: 1;background-color:hsl(var(--success) / var(--tw-bg-opacity, 1))}.bg-success-subtle{background-color:hsl(var(--success-subtle))}.bg-success-surface{background-color:hsl(var(--success-surface))}.bg-surface-0{--tw-bg-opacity: 1;background-color:hsl(var(--surface-0) / var(--tw-bg-opacity, 1))}.bg-surface-1{--tw-bg-opacity: 1;background-color:hsl(var(--surface-1) / var(--tw-bg-opacity, 1))}.bg-surface-2{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.bg-surface-3{--tw-bg-opacity: 1;background-color:hsl(var(--surface-3) / var(--tw-bg-opacity, 1))}.bg-surface-inset{--tw-bg-opacity: 1;background-color:hsl(var(--surface-inset) / var(--tw-bg-opacity, 1))}.bg-text-primary{--tw-bg-opacity: 1;background-color:hsl(var(--text-primary) / var(--tw-bg-opacity, 1))}.bg-text-tertiary{--tw-bg-opacity: 1;background-color:hsl(var(--text-tertiary) / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-warning{--tw-bg-opacity: 1;background-color:hsl(var(--warning) / var(--tw-bg-opacity, 1))}.bg-warning-subtle{background-color:hsl(var(--warning-subtle))}.bg-warning\\/10{background-color:hsl(var(--warning) / .1)}.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\\/25{background-color:#ffffff40}.fill-text-primary{fill:hsl(var(--text-primary) / 1)}.stroke-\\[3\\]{stroke-width:3}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.\\!p-0{padding:0!important}.p-0{padding:0}.p-0\\.5{padding:2px}.p-1{padding:4px}.p-1\\.5{padding:6px}.p-2{padding:8px}.p-3{padding:12px}.p-3\\.5{padding:14px}.p-4{padding:16px}.p-5{padding:20px}.p-6{padding:24px}.p-7{padding:28px}.p-8{padding:32px}.p-\\[18px\\]{padding:18px}.px-0{padding-left:0;padding-right:0}.px-1\\.5{padding-left:6px;padding-right:6px}.px-2{padding-left:8px;padding-right:8px}.px-2\\.5{padding-left:10px;padding-right:10px}.px-3{padding-left:12px;padding-right:12px}.px-4{padding-left:16px;padding-right:16px}.px-5{padding-left:20px;padding-right:20px}.px-6{padding-left:24px;padding-right:24px}.px-9{padding-left:36px;padding-right:36px}.py-0\\.5{padding-top:2px;padding-bottom:2px}.py-1{padding-top:4px;padding-bottom:4px}.py-1\\.5{padding-top:6px;padding-bottom:6px}.py-10{padding-top:40px;padding-bottom:40px}.py-16{padding-top:64px;padding-bottom:64px}.py-2{padding-top:8px;padding-bottom:8px}.py-2\\.5{padding-top:10px;padding-bottom:10px}.py-3{padding-top:12px;padding-bottom:12px}.py-3\\.5{padding-top:14px;padding-bottom:14px}.py-4{padding-top:16px;padding-bottom:16px}.py-5{padding-top:20px;padding-bottom:20px}.py-6{padding-top:24px;padding-bottom:24px}.py-8{padding-top:32px;padding-bottom:32px}.pb-1{padding-bottom:4px}.pb-3{padding-bottom:12px}.pb-4{padding-bottom:16px}.pl-3{padding-left:12px}.pl-4{padding-left:16px}.pl-5{padding-left:20px}.pl-8{padding-left:32px}.pr-10{padding-right:40px}.pr-3{padding-right:12px}.pr-4{padding-right:16px}.pt-0{padding-top:0}.pt-1{padding-top:4px}.pt-2\\.5{padding-top:10px}.pt-4{padding-top:16px}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.font-display{font-family:var(--font-display),ui-sans-serif,system-ui,sans-serif}.font-mono{font-family:var(--font-mono),ui-monospace,SFMono-Regular,Menlo,monospace}.font-sans{font-family:var(--font-sans),ui-sans-serif,system-ui,sans-serif}.text-2xs{font-size:clamp(10.5px,10.19px + .082vw,11.5px);line-height:1.333}.text-\\[0\\.72rem\\]{font-size:11.52px}.text-\\[1\\.45rem\\]{font-size:23.2px}.text-\\[1\\.75rem\\]{font-size:28px}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.text-base{font-size:clamp(14px,13.39px + .163vw,16px);line-height:1.5}.text-lg{font-size:clamp(17px,16.39px + .163vw,19px);line-height:1.471}.text-sm{font-size:clamp(13px,12.54px + .122vw,14.5px);line-height:1.462}.text-xl{font-size:clamp(20px,19.08px + .245vw,23px);line-height:1.45}.text-xs{font-size:clamp(12px,11.69px + .082vw,13px);line-height:1.333}.font-black{font-weight:900}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.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:16px}.leading-5{line-height:20px}.leading-8{line-height:32px}.leading-\\[1\\.55\\]{line-height:1.55}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.text-\\[hsl\\(145_5\\%_42\\%\\)\\]{--tw-text-opacity: 1;color:hsl(145 5% 42% / var(--tw-text-opacity, 1))}.text-brand{--tw-text-opacity: 1;color:hsl(var(--brand-hsl) / var(--tw-text-opacity, 1))}.text-brand-fg{color:var(--brand-fg)}.text-brand\\/50{color:hsl(var(--brand-hsl) / .5)}.text-danger{--tw-text-opacity: 1;color:hsl(var(--danger) / var(--tw-text-opacity, 1))}.text-danger\\/80{color:hsl(var(--danger) / .8)}.text-info{--tw-text-opacity: 1;color:hsl(var(--info) / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-success{--tw-text-opacity: 1;color:hsl(var(--success) / var(--tw-text-opacity, 1))}.text-text-disabled{--tw-text-opacity: 1;color:hsl(var(--text-disabled) / var(--tw-text-opacity, 1))}.text-text-inverse{--tw-text-opacity: 1;color:hsl(var(--text-inverse) / var(--tw-text-opacity, 1))}.text-text-primary{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.text-text-secondary{--tw-text-opacity: 1;color:hsl(var(--text-secondary) / var(--tw-text-opacity, 1))}.text-text-tertiary{--tw-text-opacity: 1;color:hsl(var(--text-tertiary) / var(--tw-text-opacity, 1))}.text-transparent{color:transparent}.text-warning{--tw-text-opacity: 1;color:hsl(var(--warning) / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-white\\/90{color:#ffffffe6}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.underline-offset-2{text-underline-offset:2px}.underline-offset-4{text-underline-offset:4px}.accent-brand{accent-color:hsl(var(--brand-hsl) / 1)}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.\\!shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1) !important;--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.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_24px_70px_-28px_rgba\\(16\\,24\\,18\\,0\\.45\\)\\]{--tw-shadow: 0 24px 70px -28px rgba(16,24,18,.45);--tw-shadow-colored: 0 24px 70px -28px 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: var(--shadow-lg);--tw-shadow-colored: var(--shadow-lg);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: var(--shadow-md);--tw-shadow-colored: var(--shadow-md);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: var(--shadow-sm);--tw-shadow-colored: var(--shadow-sm);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: var(--shadow-xl);--tw-shadow-colored: var(--shadow-xl);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xs{--tw-shadow: var(--shadow-xs);--tw-shadow-colored: var(--shadow-xs);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.outline-2{outline-width:2px}.outline-offset-0{outline-offset:0px}.outline-transparent{outline-color:transparent}.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-4{--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(4px + 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-brand{--tw-ring-opacity: 1;--tw-ring-color: hsl(var(--brand-hsl) / var(--tw-ring-opacity, 1))}.ring-brand-subtle{--tw-ring-color: var(--brand-subtle)}.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)}.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-\\[2px\\]{--tw-backdrop-blur: blur(2px);-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-\\[background-color\\,border-color\\,color\\,box-shadow\\]{transition-property:background-color,border-color,color,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[background-color\\,color\\,border-color\\,box-shadow\\,opacity\\]{transition-property:background-color,color,border-color,box-shadow,opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[background-color\\,color\\,border-color\\,box-shadow\\]{transition-property:background-color,color,border-color,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[background-color\\,color\\,box-shadow\\]{transition-property:background-color,color,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[background-color\\,color\\]{transition-property:background-color,color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[border-color\\,box-shadow\\,background-color\\]{transition-property:border-color,box-shadow,background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[border-color\\,outline-color\\,box-shadow\\,background-color\\,transform\\]{transition-property:border-color,outline-color,box-shadow,background-color,transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[max-width\\,height\\,box-shadow\\,background-color\\,border-color\\,transform\\,opacity\\]{transition-property:max-width,height,box-shadow,background-color,border-color,transform,opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[max-width\\]{transition-property:max-width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[opacity\\,transform\\]{transition-property:opacity,transform;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-300{transition-duration:.3s}.duration-\\[var\\(--issue-marker-expand-duration\\)\\]{transition-duration:var(--issue-marker-expand-duration)}.duration-fast{transition-duration:var(--duration-fast)}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-in-out{transition-timing-function:var(--ease-in-out)}.ease-out{transition-timing-function:var(--ease-out)}@keyframes float-gentle{0%,to{transform:translateY(0)}50%{transform:translateY(-2px)}}@keyframes toast-slide{0%{opacity:0;transform:translateY(-14px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes gradient-shift{0%,to{background-position:0% 50%}50%{background-position:100% 50%}}.issue-overlay-shell{border:1px solid hsl(var(--border-subtle));border-radius:var(--radius-lg);background:hsl(var(--surface-1));box-shadow:var(--shadow-md)}.issue-marker-breathe{animation:float-gentle 4.8s var(--ease-in-out) infinite}.issue-marker-breathe:hover,.issue-marker-breathe:focus-visible,.issue-marker-breathe:focus-within{animation-play-state:paused}.\\[overflow-wrap\\:anywhere\\]{overflow-wrap:anywhere}.marker\\:text-text-tertiary *::marker{color:hsl(var(--text-tertiary))}.marker\\:text-text-tertiary::marker{color:hsl(var(--text-tertiary))}.file\\:border-0::file-selector-button{border-width:0px}.file\\:bg-transparent::file-selector-button{background-color:transparent}.file\\:text-sm::file-selector-button{font-size:clamp(13px,12.54px + .122vw,14.5px);line-height:1.462}.file\\:font-medium::file-selector-button{font-weight:500}.file\\:text-text-primary::file-selector-button{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.placeholder\\:text-text-tertiary::-moz-placeholder{--tw-text-opacity: 1;color:hsl(var(--text-tertiary) / var(--tw-text-opacity, 1))}.placeholder\\:text-text-tertiary::placeholder{--tw-text-opacity: 1;color:hsl(var(--text-tertiary) / var(--tw-text-opacity, 1))}.first\\:mt-0:first-child{margin-top:0}.first\\:border-t-0:first-child{border-top-width:0px}.first\\:pt-0:first-child{padding-top:0}.focus-within\\:z-\\[10001\\]:focus-within{z-index:10001}.focus-within\\:border-line-focus:focus-within{--tw-border-opacity: 1;border-color:hsl(var(--border-focus) / var(--tw-border-opacity, 1))}.hover\\:z-\\[10001\\]:hover{z-index:10001}.hover\\:border-line:hover{--tw-border-opacity: 1;border-color:hsl(var(--border-default) / var(--tw-border-opacity, 1))}.hover\\:border-line-strong:hover{--tw-border-opacity: 1;border-color:hsl(var(--border-strong) / var(--tw-border-opacity, 1))}.hover\\:border-line-subtle:hover{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}.hover\\:bg-\\[hsl\\(144_8\\%_96\\%\\)\\]:hover{--tw-bg-opacity: 1;background-color:hsl(144 8% 96% / var(--tw-bg-opacity, 1))}.hover\\:bg-blue-500:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.hover\\:bg-brand-hover:hover{background-color:var(--brand-hover)}.hover\\:bg-brand\\/40:hover{background-color:hsl(var(--brand-hsl) / .4)}.hover\\:bg-danger-subtle:hover{background-color:hsl(var(--danger-subtle))}.hover\\:bg-danger\\/10:hover{background-color:hsl(var(--danger) / .1)}.hover\\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.hover\\:bg-slate-50:hover{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.hover\\:bg-surface-2:hover{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.hover\\:bg-surface-2\\/60:hover{background-color:hsl(var(--surface-2) / .6)}.hover\\:bg-surface-3:hover{--tw-bg-opacity: 1;background-color:hsl(var(--surface-3) / var(--tw-bg-opacity, 1))}.hover\\:bg-surface-inset:hover{--tw-bg-opacity: 1;background-color:hsl(var(--surface-inset) / var(--tw-bg-opacity, 1))}.hover\\:bg-transparent:hover{background-color:transparent}.hover\\:bg-white\\/20:hover{background-color:#fff3}.hover\\:text-\\[hsl\\(150_10\\%_12\\%\\)\\]:hover{--tw-text-opacity: 1;color:hsl(150 10% 12% / var(--tw-text-opacity, 1))}.hover\\:text-brand-hover:hover{color:var(--brand-hover)}.hover\\:text-danger:hover{--tw-text-opacity: 1;color:hsl(var(--danger) / var(--tw-text-opacity, 1))}.hover\\:text-slate-900:hover{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.hover\\:text-text-primary:hover{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.hover\\:text-text-secondary:hover{--tw-text-opacity: 1;color:hsl(var(--text-secondary) / var(--tw-text-opacity, 1))}.hover\\:underline:hover{text-decoration-line:underline}.hover\\:opacity-90:hover{opacity:.9}.focus\\:border-brand:focus{--tw-border-opacity: 1;border-color:hsl(var(--brand-hsl) / var(--tw-border-opacity, 1))}.focus\\:bg-surface-2:focus{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.focus\\:text-text-primary:focus{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.focus\\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus-visible\\:h-\\[var\\(--issue-sticker-hover-size\\)\\]:focus-visible{height:var(--issue-sticker-hover-size)}.focus-visible\\:max-w-\\[160px\\]:focus-visible{max-width:160px}.focus-visible\\:max-w-\\[480px\\]:focus-visible{max-width:480px}.focus-visible\\:border-line-focus:focus-visible{--tw-border-opacity: 1;border-color:hsl(var(--border-focus) / var(--tw-border-opacity, 1))}.focus-visible\\:border-transparent:focus-visible{border-color:transparent}.focus-visible\\:bg-slate-50:focus-visible{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.focus-visible\\:bg-surface-1:focus-visible{--tw-bg-opacity: 1;background-color:hsl(var(--surface-1) / var(--tw-bg-opacity, 1))}.focus-visible\\:bg-surface-2:focus-visible{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.focus-visible\\:text-text-primary:focus-visible{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.focus-visible\\:shadow-focus:focus-visible{--tw-shadow: var(--shadow-focus);--tw-shadow-colored: var(--shadow-focus);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus-visible\\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\\:outline-line-focus:focus-visible{outline-color:hsl(var(--border-focus) / 1)}.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-4: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(4px + 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-brand-subtle:focus-visible{--tw-ring-color: var(--brand-subtle)}.focus-visible\\:ring-white\\/40:focus-visible{--tw-ring-color: rgb(255 255 255 / .4)}.active\\:bg-brand-active:active{background-color:var(--brand-active)}.active\\:bg-brand\\/60:active{background-color:hsl(var(--brand-hsl) / .6)}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-40:disabled{opacity:.4}.disabled\\:opacity-50:disabled{opacity:.5}.group\\/marker:hover .group-hover\\/marker\\:h-\\[var\\(--issue-sticker-hover-size\\)\\]{height:var(--issue-sticker-hover-size)}.group\\/marker:hover .group-hover\\/marker\\:max-w-\\[160px\\]{max-width:160px}.group\\/marker:hover .group-hover\\/marker\\:max-w-\\[480px\\]{max-width:480px}.group\\/marker:hover .group-hover\\/marker\\:translate-x-0{--tw-translate-x: 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))}.group\\/marker:hover .group-hover\\/marker\\:bg-brand-hover{background-color:var(--brand-hover)}.group\\/marker:hover .group-hover\\/marker\\:opacity-100{opacity:1}.group\\/marker:hover .group-hover\\/marker\\:shadow-xl{--tw-shadow: var(--shadow-xl);--tw-shadow-colored: var(--shadow-xl);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.group:focus-visible .group-focus-visible\\:translate-x-0{--tw-translate-x: 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))}.group:focus-visible .group-focus-visible\\:opacity-100{opacity:1}.group.toaster .group-\\[\\.toaster\\]\\:isolate{isolation:isolate}.group.toast .group-\\[\\.toast\\]\\:rounded-md,.group.toaster .group-\\[\\.toaster\\]\\:rounded-md{border-radius:var(--radius-md)}.group.toaster .group-\\[\\.toaster\\]\\:border{border-width:1px}.group.toaster .group-\\[\\.toaster\\]\\:\\!border-danger\\/30{border-color:hsl(var(--danger) / .3)!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!border-info\\/30{border-color:hsl(var(--info) / .3)!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!border-success\\/30{border-color:hsl(var(--success) / .3)!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!border-warning\\/30{border-color:hsl(var(--warning) / .3)!important}.group.toaster .group-\\[\\.toaster\\]\\:border-line-subtle{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}.group.toast .group-\\[\\.toast\\]\\:bg-brand{--tw-bg-opacity: 1;background-color:hsl(var(--brand-hsl) / var(--tw-bg-opacity, 1))}.group.toast .group-\\[\\.toast\\]\\:bg-surface-2{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:\\!bg-danger-subtle{background-color:hsl(var(--danger-subtle))!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!bg-info-subtle{background-color:hsl(var(--info-subtle))!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!bg-success-surface{background-color:hsl(var(--success-surface))!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!bg-warning-subtle{background-color:hsl(var(--warning-subtle))!important}.group.toaster .group-\\[\\.toaster\\]\\:bg-surface-1{--tw-bg-opacity: 1;background-color:hsl(var(--surface-1) / var(--tw-bg-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:px-4{padding-left:16px;padding-right:16px}.group.toaster .group-\\[\\.toaster\\]\\:py-3{padding-top:12px;padding-bottom:12px}.group.toast .group-\\[\\.toast\\]\\:text-sm{font-size:clamp(13px,12.54px + .122vw,14.5px);line-height:1.462}.group.toast .group-\\[\\.toast\\]\\:text-xs{font-size:clamp(12px,11.69px + .082vw,13px);line-height:1.333}.group.toast .group-\\[\\.toast\\]\\:font-medium{font-weight:500}.group.toast .group-\\[\\.toast\\]\\:text-brand-fg{color:var(--brand-fg)}.group.toast .group-\\[\\.toast\\]\\:text-text-primary{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.group.toast .group-\\[\\.toast\\]\\:text-text-secondary{--tw-text-opacity: 1;color:hsl(var(--text-secondary) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:text-text-primary{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:shadow-sm{--tw-shadow: var(--shadow-sm);--tw-shadow-colored: var(--shadow-sm);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.group.toaster .group-\\[\\.toaster\\]\\:before\\:absolute:before{content:var(--tw-content);position:absolute}.group.toaster .group-\\[\\.toaster\\]\\:before\\:inset-0:before{content:var(--tw-content);top:0;right:0;bottom:0;left:0}.group.toaster .group-\\[\\.toaster\\]\\:before\\:-z-10:before{content:var(--tw-content);z-index:-10}.group.toaster .group-\\[\\.toaster\\]\\:before\\:rounded-md:before{content:var(--tw-content);border-radius:var(--radius-md)}.group.toaster .group-\\[\\.toaster\\]\\:before\\:bg-surface-1:before{content:var(--tw-content);--tw-bg-opacity: 1;background-color:hsl(var(--surface-1) / var(--tw-bg-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:before\\:content-\\[\\'\\'\\]:before{--tw-content: "";content:var(--tw-content)}.peer:focus-visible~.peer-focus-visible\\:shadow-focus{--tw-shadow: var(--shadow-focus);--tw-shadow-colored: var(--shadow-focus);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.peer:disabled~.peer-disabled\\:cursor-not-allowed{cursor:not-allowed}.peer:disabled~.peer-disabled\\:opacity-60{opacity:.6}.aria-disabled\\:pointer-events-none[aria-disabled=true]{pointer-events:none}.aria-disabled\\:opacity-40[aria-disabled=true]{opacity:.4}.data-\\[disabled\\]\\:pointer-events-none[data-disabled]{pointer-events:none}@keyframes dialog-out{0%{opacity:1;transform:translate(-50%,-50%) scale(1)}to{opacity:0;transform:translate(-50%,calc(-50% + 8px)) scale(.985)}}.data-\\[state\\=closed\\]\\:animate-dialog-out[data-state=closed]{animation:dialog-out var(--duration-out) var(--ease-out) forwards}@keyframes fade-out{0%{opacity:1}to{opacity:0}}.data-\\[state\\=closed\\]\\:animate-fade-out[data-state=closed]{animation:fade-out var(--duration-out) var(--ease-out) forwards}@keyframes scale-out{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.97)}}.data-\\[state\\=closed\\]\\:animate-scale-out[data-state=closed]{animation:scale-out var(--duration-out) var(--ease-out) forwards}@keyframes sheet-out-left{0%{transform:translate(0)}to{transform:translate(-100%);opacity:.6}}.data-\\[state\\=closed\\]\\:animate-sheet-out-left[data-state=closed]{animation:sheet-out-left var(--duration-base) var(--ease-out) forwards}@keyframes sheet-out-right{0%{transform:translate(0);opacity:1}to{transform:translate(100%);opacity:.6}}.data-\\[state\\=closed\\]\\:animate-sheet-out-right[data-state=closed]{animation:sheet-out-right var(--duration-base) var(--ease-out) forwards}.data-\\[state\\=delayed-open\\]\\:animate-scale-in[data-state=delayed-open]{animation:scale-in var(--duration-base) var(--ease-out) forwards}@keyframes dialog-in{0%{opacity:0;transform:translate(-50%,calc(-50% + 12px)) scale(.985)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}.data-\\[state\\=open\\]\\:animate-dialog-in[data-state=open]{animation:dialog-in var(--duration-base) var(--ease-out) forwards}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.data-\\[state\\=open\\]\\:animate-fade-in[data-state=open]{animation:fade-in var(--duration-base) var(--ease-out) forwards}@keyframes scale-in{0%{opacity:0;transform:scale(.98)}to{opacity:1;transform:scale(1)}}.data-\\[state\\=open\\]\\:animate-scale-in[data-state=open]{animation:scale-in var(--duration-base) var(--ease-out) forwards}@keyframes sheet-in-left{0%{transform:translate(-100%);opacity:.6}to{transform:translate(0);opacity:1}}.data-\\[state\\=open\\]\\:animate-sheet-in-left[data-state=open]{animation:sheet-in-left var(--duration-base) var(--ease-out) forwards}@keyframes sheet-in-right{0%{transform:translate(100%);opacity:.6}to{transform:translate(0)}}.data-\\[state\\=open\\]\\:animate-sheet-in-right[data-state=open]{animation:sheet-in-right var(--duration-base) var(--ease-out) forwards}.data-\\[range-end\\=true\\]\\:rounded-md[data-range-end=true]{border-radius:var(--radius-md)}.data-\\[range-middle\\=true\\]\\:rounded-none[data-range-middle=true]{border-radius:0}.data-\\[range-start\\=true\\]\\:rounded-md[data-range-start=true]{border-radius:var(--radius-md)}.data-\\[state\\=open\\]\\:border-line-focus[data-state=open]{--tw-border-opacity: 1;border-color:hsl(var(--border-focus) / var(--tw-border-opacity, 1))}.data-\\[highlighted\\]\\:bg-surface-2[data-highlighted]{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.data-\\[range-end\\=true\\]\\:bg-brand[data-range-end=true]{--tw-bg-opacity: 1;background-color:hsl(var(--brand-hsl) / var(--tw-bg-opacity, 1))}.data-\\[range-middle\\=true\\]\\:bg-transparent[data-range-middle=true]{background-color:transparent}.data-\\[range-start\\=true\\]\\:bg-brand[data-range-start=true],.data-\\[selected-single\\=true\\]\\:bg-brand[data-selected-single=true]{--tw-bg-opacity: 1;background-color:hsl(var(--brand-hsl) / var(--tw-bg-opacity, 1))}.data-\\[state\\=selected\\]\\:bg-brand-subtle[data-state=selected]{background-color:var(--brand-subtle)}.data-\\[today\\=true\\]\\:font-semibold[data-today=true]{font-weight:600}.data-\\[highlighted\\]\\:text-text-primary[data-highlighted]{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.data-\\[placeholder\\]\\:text-text-tertiary[data-placeholder]{--tw-text-opacity: 1;color:hsl(var(--text-tertiary) / var(--tw-text-opacity, 1))}.data-\\[range-end\\=true\\]\\:text-brand-fg[data-range-end=true]{color:var(--brand-fg)}.data-\\[range-middle\\=true\\]\\:text-text-primary[data-range-middle=true]{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.data-\\[range-start\\=true\\]\\:text-brand-fg[data-range-start=true],.data-\\[selected-single\\=true\\]\\:text-brand-fg[data-selected-single=true]{color:var(--brand-fg)}.data-\\[state\\=active\\]\\:text-text-primary[data-state=active],.data-\\[state\\=checked\\]\\:text-text-primary[data-state=checked]{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.data-\\[today\\=true\\]\\:text-brand[data-today=true]{--tw-text-opacity: 1;color:hsl(var(--brand-hsl) / var(--tw-text-opacity, 1))}.data-\\[disabled\\]\\:opacity-50[data-disabled]{opacity:.5}.data-\\[state\\=open\\]\\:shadow-focus[data-state=open]{--tw-shadow: var(--shadow-focus);--tw-shadow-colored: var(--shadow-focus);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.data-\\[range-end\\=true\\]\\:hover\\:bg-brand-hover:hover[data-range-end=true],.data-\\[range-start\\=true\\]\\:hover\\:bg-brand-hover:hover[data-range-start=true],.data-\\[selected-single\\=true\\]\\:hover\\:bg-brand-hover:hover[data-selected-single=true]{background-color:var(--brand-hover)}.data-\\[range-end\\=true\\]\\:hover\\:text-brand-fg:hover[data-range-end=true],.data-\\[range-start\\=true\\]\\:hover\\:text-brand-fg:hover[data-range-start=true],.data-\\[selected-single\\=true\\]\\:hover\\:text-brand-fg:hover[data-selected-single=true]{color:var(--brand-fg)}@media(prefers-reduced-motion:reduce){.motion-reduce\\:animate-none{animation:none}}@media(min-width:640px){.sm\\:flex-row{flex-direction:row}.sm\\:items-start{align-items:flex-start}.sm\\:items-center{align-items:center}.sm\\:justify-end{justify-content:flex-end}.sm\\:justify-between{justify-content:space-between}.sm\\:gap-2\\.5{gap:10px}.sm\\:p-5{padding:20px}.sm\\:p-6{padding:24px}.sm\\:text-2xl{font-size:clamp(26px,24.78px + .327vw,30px);line-height:1.308}.sm\\:text-\\[2\\.1rem\\]{font-size:33.6px}}@media(min-width:768px){.md\\:flex{display:flex}.md\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\\:grid-cols-\\[minmax\\(0\\,1fr\\)_minmax\\(260px\\,340px\\)\\]{grid-template-columns:minmax(0,1fr) minmax(260px,340px)}}.\\[\\&\\>\\*\\:not\\(summary\\)\\]\\:pl-4>*:not(summary){padding-left:16px}.\\[\\&\\>span\\]\\:line-clamp-1>span{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.\\[\\&\\>tr\\]\\:last\\:border-b-0:last-child>tr{border-bottom-width:0px}.\\[\\&\\[data-state\\=open\\]\\>span\\[data-chevron\\]\\]\\:rotate-180[data-state=open]>span[data-chevron]{--tw-rotate: 180deg;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.toaster .group-\\[\\.toaster\\]\\:\\[\\&_\\[data-icon\\]\\]\\:text-danger [data-icon]{--tw-text-opacity: 1;color:hsl(var(--danger) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:\\[\\&_\\[data-icon\\]\\]\\:text-info [data-icon]{--tw-text-opacity: 1;color:hsl(var(--info) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:\\[\\&_\\[data-icon\\]\\]\\:text-success [data-icon]{--tw-text-opacity: 1;color:hsl(var(--success) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:\\[\\&_\\[data-icon\\]\\]\\:text-warning [data-icon]{--tw-text-opacity: 1;color:hsl(var(--warning) / var(--tw-text-opacity, 1))}.\\[\\&_tr\\]\\:border-b tr{border-bottom-width:1px}.\\[\\&_tr\\]\\:border-line-subtle tr{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}`;
40249
+ const globalsCSS = `:root,:host{color-scheme:light;--brand-h: 150;--brand-s: 100%;--brand-l: 34%;--brand-hsl: var(--brand-h) var(--brand-s) var(--brand-l);--brand: hsl(var(--brand-hsl));--brand-hover: hsl(var(--brand-h) calc(var(--brand-s) + 3%) calc(var(--brand-l) - 4%));--brand-active: hsl(var(--brand-h) calc(var(--brand-s) + 2%) calc(var(--brand-l) - 8%));--brand-subtle: hsl(var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .14);--brand-border: hsl(var(--brand-h) calc(var(--brand-s) + 8%) calc(var(--brand-l) + 8%) / .34);--brand-fg: hsl(0 0% 100%);--brand-ring: hsl(var(--brand-h) calc(var(--brand-s) + 12%) calc(var(--brand-l) + 10%) / .22);--font-sans: "Pretendard", -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif;--font-display: var(--font-sans);--font-mono: var(--font-sans);--surface-0: 0 0% 99%;--surface-1: 0 0% 100%;--surface-2: 144 8% 96%;--surface-3: 144 6% 93%;--surface-inset: 144 6% 95%;--overlay-backdrop: hsl(0 0% 0% / .24);--overlay-backdrop-strong: hsl(0 0% 0% / .48);--text-primary: 150 10% 12%;--text-secondary: 148 6% 36%;--text-tertiary: 145 5% 42%;--text-disabled: 145 4% 70%;--text-inverse: 0 0% 100%;--border-subtle: 144 8% 91%;--border-default: 144 6% 85%;--border-strong: 144 5% 72%;--border-focus: var(--brand-h) var(--brand-s) var(--brand-l);--success: var(--brand-h) var(--brand-s) var(--brand-l);--success-subtle: var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .14;--success-surface: var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .24;--warning: 34 82% 52%;--warning-subtle: 34 82% 52% / .14;--danger: 3 68% 56%;--danger-subtle: 3 68% 56% / .12;--danger-deep: 3 62% 40%;--info: 202 52% 44%;--info-subtle: 202 52% 44% / .12;--accent-terra: 13 52% 47%;--accent-terra-subtle: 13 52% 47% / .1;--accent-terra-deep: 13 48% 44%;--accent-blue: 213 86% 56%;--accent-blue-subtle: 213 92% 56% / .12;--accent-blue-deep: 216 78% 40%;--accent-blue-border: 213 86% 62% / .36;--accent-cream: 38 52% 88%;--accent-cream-warm: 40 56% 95%;--accent-cream-deep: 38 48% 82%;--accent-highlight: 55 96% 70%;--accent-ink: 32 13% 11%;--radius-xs: 4px;--radius-sm: 8px;--radius-md: 12px;--radius-lg: 16px;--radius-xl: 20px;--radius-2xl: 24px;--radius-pill: 9999px;--shadow-xs: 0 1px 2px 0 hsl(0 0% 0% / .04);--shadow-sm: 0 1px 3px 0 hsl(0 0% 0% / .06), 0 1px 2px -1px hsl(0 0% 0% / .06);--shadow-md: 0 4px 6px -1px hsl(0 0% 0% / .06), 0 2px 4px -2px hsl(0 0% 0% / .04);--shadow-lg: 0 10px 15px -3px hsl(0 0% 0% / .06), 0 4px 6px -4px hsl(0 0% 0% / .04);--shadow-xl: 0 20px 25px -5px hsl(0 0% 0% / .06), 0 8px 10px -6px hsl(0 0% 0% / .04);--shadow-focus: 0 0 0 3px var(--brand-ring);--shadow-inset: inset 0 1px 2px 0 hsl(0 0% 0% / .04);--shadow-brand: 0 2px 8px hsl(var(--brand-h) calc(var(--brand-s) - 60%) calc(var(--brand-l) - 14%) / .24), 0 6px 20px hsl(var(--brand-h) calc(var(--brand-s) - 70%) calc(var(--brand-l) - 19%) / .16);--duration-instant: 90ms;--duration-fast: .16s;--duration-base: .26s;--duration-out: .18s;--duration-slow: .36s;--ease-out: cubic-bezier(.23, 1, .32, 1);--ease-in-out: cubic-bezier(.45, 0, .15, 1);--ease-spring: cubic-bezier(.18, .94, .32, 1.08);--grid-line: 0 0% 92%}.dark,:host(.dark){color-scheme:dark;--brand-l: 34%;--brand-fg: hsl(0 0% 100%);--surface-0: 150 8% 7%;--surface-1: 150 6% 10%;--surface-2: 150 5% 14%;--surface-3: 150 4% 18%;--surface-inset: 150 6% 6%;--overlay-backdrop: hsl(0 0% 0% / .56);--overlay-backdrop-strong: hsl(0 0% 0% / .8);--text-primary: 40 16% 93%;--text-secondary: 36 8% 68%;--text-tertiary: 34 6% 50%;--text-disabled: 30 5% 34%;--text-inverse: 150 8% 10%;--border-subtle: 150 6% 16%;--border-default: 150 5% 22%;--border-strong: 150 4% 34%;--success: var(--brand-h) var(--brand-s) var(--brand-l);--success-subtle: var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .14;--success-surface: var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 14%) / .24;--warning: 34 82% 62%;--danger: 2 70% 64%;--danger-deep: 2 80% 76%;--info: 202 54% 62%;--accent-terra: 13 56% 62%;--accent-terra-subtle: 13 56% 62% / .14;--accent-terra-deep: 13 52% 56%;--accent-blue: 210 92% 68%;--accent-blue-subtle: 210 92% 68% / .18;--accent-blue-deep: 209 100% 78%;--accent-blue-border: 210 92% 72% / .44;--accent-cream: 38 30% 26%;--accent-cream-warm: 38 22% 18%;--accent-cream-deep: 38 26% 32%;--accent-highlight: 55 96% 70%;--accent-ink: 32 13% 8%;--shadow-xs: 0 1px 2px 0 hsl(0 0% 0% / .2);--shadow-sm: 0 1px 3px 0 hsl(0 0% 0% / .3), 0 1px 2px -1px hsl(0 0% 0% / .24);--shadow-md: 0 4px 6px -1px hsl(0 0% 0% / .34), 0 2px 4px -2px hsl(0 0% 0% / .2);--shadow-lg: 0 10px 15px -3px hsl(0 0% 0% / .38), 0 4px 6px -4px hsl(0 0% 0% / .24);--shadow-xl: 0 20px 25px -5px hsl(0 0% 0% / .44), 0 8px 10px -6px hsl(0 0% 0% / .28);--shadow-inset: inset 0 1px 2px 0 hsl(0 0% 0% / .16);--shadow-brand: 0 2px 8px hsl(var(--brand-h) calc(var(--brand-s) - 60%) calc(var(--brand-l) - 24%) / .44), 0 6px 20px hsl(0 0% 0% / .32);--grid-line: 150 6% 14%}*{border-color:hsl(var(--border-default))}html{font-family:var(--font-sans),ui-sans-serif,system-ui,-apple-system,sans-serif;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;font-feature-settings:"cv11","ss01","ss03";background-color:hsl(var(--surface-0))}body{margin:0;min-height:100vh;color:hsl(var(--text-primary));background-color:hsl(var(--surface-0))}::-moz-selection{background-color:hsl(var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 16%) / .22);color:hsl(var(--text-primary))}::selection{background-color:hsl(var(--brand-h) calc(var(--brand-s) + 6%) calc(var(--brand-l) + 16%) / .22);color:hsl(var(--text-primary))}code,kbd,samp,pre{font-family:var(--font-mono),ui-monospace,SFMono-Regular,Menlo,monospace;font-feature-settings:"ss01","ss02","cv11"}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:hsl(var(--border-strong) / .52);border-radius:var(--radius-pill);border:2px solid transparent;background-clip:padding-box}::-webkit-scrollbar-thumb:hover{background:hsl(var(--border-strong) / .9);background-clip:padding-box;border:2px solid transparent}.app-canvas,.grid-canvas{background-color:hsl(var(--surface-0))}.onboarding-canvas{word-break:keep-all;overflow-wrap:break-word;--surface-0: var(--brand-h) var(--brand-s) var(--brand-l);--surface-1: 0 0% 100%;--surface-2: var(--brand-h) 62% 28%;--surface-3: var(--brand-h) 60% 25%;--surface-inset: var(--brand-h) 62% 28%;--text-primary: 0 0% 100%;--text-secondary: var(--brand-h) 46% 90%;--text-tertiary: var(--brand-h) 34% 84%;--text-disabled: var(--brand-h) 20% 72%;--border-subtle: var(--brand-h) 44% 52%;--border-default: var(--brand-h) 40% 58%;--border-strong: var(--brand-h) 36% 70%;--border-focus: 0 0% 100%;--brand-hsl: 0 0% 100%;--brand: hsl(var(--brand-hsl));--brand-hover: hsl(var(--brand-h) 24% 94%);--brand-active: hsl(var(--brand-h) 20% 88%);--brand-fg: hsl(var(--brand-h) var(--brand-s) 24%);--brand-ring: hsl(0 0% 100% / .4);--danger: 6 96% 86%;--danger-subtle: 6 96% 86% / .18;--danger-deep: 6 96% 92%;--warning: 42 96% 82%;--warning-subtle: 42 96% 82% / .18}.onboarding-canvas .bg-surface-1,.onboarding-canvas input,.onboarding-canvas textarea,.onboarding-canvas [role=combobox]{--text-primary: 150 10% 12%;--text-secondary: 148 6% 36%;--text-tertiary: 145 5% 42%;--surface-2: 144 8% 96%;--surface-inset: 144 6% 95%;--border-subtle: 144 8% 91%;--border-default: 144 6% 85%;--brand-hsl: var(--brand-h) var(--brand-s) var(--brand-l);--brand: hsl(var(--brand-hsl));--brand-hover: hsl(var(--brand-h) calc(var(--brand-s) + 3%) calc(var(--brand-l) - 4%));--brand-active: hsl(var(--brand-h) calc(var(--brand-s) + 2%) calc(var(--brand-l) - 8%));--brand-fg: hsl(0 0% 100%);--brand-ring: hsl(var(--brand-h) calc(var(--brand-s) + 12%) calc(var(--brand-l) + 10%) / .22);--warning: 34 82% 52%;--warning-subtle: 34 82% 52% / .14;--danger: 3 68% 56%;--danger-subtle: 3 68% 56% / .12;--danger-deep: 3 62% 40%}@keyframes onboarding-step-in{0%{opacity:0;transform:translate(96px)}to{opacity:1;transform:translate(0)}}.onboarding-step-in{animation:onboarding-step-in var(--duration-slow) var(--ease-out) forwards}@keyframes onboarding-enter-up{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.onboarding-enter{position:fixed;top:0;right:0;bottom:0;left:0;overflow-x:hidden;overflow-y:auto;animation:onboarding-enter-up var(--duration-base) var(--ease-out) forwards}body:has(.onboarding-canvas){background-color:hsl(var(--brand-h) var(--brand-s) var(--brand-l))}.panel-shell,.surface-shell{border:1px solid hsl(var(--border-subtle));border-radius:var(--radius-xl);background:hsl(var(--surface-1));box-shadow:var(--shadow-sm)}.panel-shell-muted,.surface-shell-muted{background:hsl(var(--surface-2));box-shadow:var(--shadow-xs)}.panel-shell-subtle{border:1px solid hsl(var(--border-subtle));border-radius:var(--radius-lg);background:hsl(var(--surface-1));box-shadow:var(--shadow-xs)}.panel-shell-elevated{border:1px solid hsl(var(--border-default));border-radius:var(--radius-xl);background:hsl(var(--surface-1));box-shadow:var(--shadow-md)}.utility-chip,.floating-chip{display:inline-flex;align-items:center;gap:8px;border:1px solid hsl(var(--border-default));border-radius:var(--radius-pill);background:hsl(var(--surface-1));box-shadow:var(--shadow-xs)}.hairline{border-bottom:1px solid hsl(var(--border-subtle))}.mono-label{font-family:var(--font-mono),ui-monospace,monospace;font-size:11px;text-transform:uppercase;color:hsl(var(--text-tertiary))}*,: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:var(--font-sans),ui-sans-serif,system-ui,sans-serif;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:var(--font-mono),ui-monospace,SFMono-Regular,Menlo,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}:root,:host{--font-sans: "Pretendard", -apple-system, BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", sans-serif;--font-mono: var(--font-sans);--issue-marker-expand-duration: .52s;--surface-0: 0 0% 99%;--surface-1: 0 0% 100%;--surface-2: 144 8% 96%;--surface-3: 144 6% 93%;--surface-inset: 144 6% 95%;--overlay-backdrop: hsl(0 0% 0% / .24);--overlay-backdrop-strong: hsl(0 0% 0% / .48);--text-primary: 150 10% 12%;--text-secondary: 148 6% 36%;--text-tertiary: 145 5% 52%;--text-disabled: 145 4% 70%;--border-subtle: 144 8% 91%;--border-default: 144 6% 85%;--border-strong: 144 5% 72%;--grid-line: 0 0% 92%;--shadow-xs: 0 1px 2px 0 hsl(0 0% 0% / .04);--shadow-sm: 0 1px 3px 0 hsl(0 0% 0% / .06), 0 1px 2px -1px hsl(0 0% 0% / .06);--shadow-md: 0 4px 6px -1px hsl(0 0% 0% / .06), 0 2px 4px -2px hsl(0 0% 0% / .04);--shadow-lg: 0 10px 15px -3px hsl(0 0% 0% / .06), 0 4px 6px -4px hsl(0 0% 0% / .04);--shadow-xl: 0 20px 25px -5px hsl(0 0% 0% / .06), 0 8px 10px -6px hsl(0 0% 0% / .04);--shadow-focus: 0 0 0 4px var(--brand-ring);--shadow-inset: inset 0 1px 2px 0 hsl(0 0% 0% / .04)}*{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}#issue-sticker-shadow-root{all:initial;display:block;background-color:transparent;--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1));font-family:var(--font-sans);line-height:1.5}.\\!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}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.inset-x-0{left:0;right:0}.inset-x-1{left:4px;right:4px}.inset-y-0{top:0;bottom:0}.-bottom-px{bottom:-1px}.bottom-0{bottom:0}.bottom-4{bottom:16px}.bottom-6{bottom:24px}.left-0{left:0}.left-1\\/2{left:50%}.left-2{left:8px}.left-4{left:16px}.left-\\[50\\%\\]{left:50%}.right-0{right:0}.right-2{right:8px}.right-3{right:12px}.right-4{right:16px}.right-5{right:20px}.right-6{right:24px}.top-0{top:0}.top-1{top:4px}.top-1\\/2{top:50%}.top-2{top:8px}.top-3{top:12px}.top-4{top:16px}.top-5{top:20px}.top-\\[50\\%\\]{top:50%}.top-\\[calc\\(\\(3\\.5rem-1\\.75rem\\)\\/2\\)\\]{top:14px}.top-full{top:100%}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-\\[1000000\\]{z-index:1000000}.z-\\[1000003\\]{z-index:1000003}.z-\\[1000004\\]{z-index:1000004}.z-\\[1000005\\]{z-index:1000005}.z-\\[1000006\\]{z-index:1000006}.z-\\[1000007\\]{z-index:1000007}.z-\\[1000008\\]{z-index:1000008}.z-\\[1000010\\]{z-index:1000010}.z-\\[1000011\\]{z-index:1000011}.z-\\[10001\\]{z-index:10001}.z-\\[999999\\]{z-index:999999}.z-\\[9999\\]{z-index:9999}.m-0{margin:0}.-mx-2{margin-left:-8px;margin-right:-8px}.mx-3{margin-left:12px;margin-right:12px}.my-1{margin-top:4px;margin-bottom:4px}.my-2{margin-top:8px;margin-bottom:8px}.my-2\\.5{margin-top:10px;margin-bottom:10px}.my-3{margin-top:12px;margin-bottom:12px}.my-4{margin-top:16px;margin-bottom:16px}.mb-0\\.5{margin-bottom:2px}.mb-1{margin-bottom:4px}.mb-2{margin-bottom:8px}.mb-3{margin-bottom:12px}.mb-5{margin-bottom:20px}.ml-0\\.5{margin-left:2px}.ml-4{margin-left:16px}.mr-1\\.5{margin-right:6px}.mr-2{margin-right:8px}.mt-0{margin-top:0}.mt-0\\.5{margin-top:2px}.mt-1{margin-top:4px}.mt-2{margin-top:8px}.mt-3{margin-top:12px}.mt-4{margin-top:16px}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.hidden{display:none}.aspect-square{aspect-ratio:1 / 1}.\\!h-auto{height:auto!important}.h-1\\.5{height:6px}.h-10{height:40px}.h-11{height:44px}.h-2{height:8px}.h-24{height:96px}.h-3{height:12px}.h-3\\.5{height:14px}.h-4{height:16px}.h-5{height:20px}.h-6{height:24px}.h-7{height:28px}.h-8{height:32px}.h-9{height:36px}.h-\\[1\\.4rem\\]{height:22.4px}.h-\\[100vh\\]{height:100vh}.h-\\[18px\\]{height:18px}.h-\\[220px\\]{height:220px}.h-\\[22px\\]{height:22px}.h-\\[30px\\]{height:30px}.h-\\[min\\(36vh\\,320px\\)\\]{height:min(36vh,320px)}.h-\\[min\\(480px\\,calc\\(100vh-64px\\)\\)\\]{height:min(480px,calc(100vh - 64px))}.h-\\[min\\(54vh\\,520px\\)\\]{height:min(54vh,520px)}.h-\\[min\\(560px\\,calc\\(100vh-32px\\)\\)\\]{height:min(560px,calc(100vh - 32px))}.h-\\[var\\(--issue-sticker-size\\)\\]{height:var(--issue-sticker-size)}.h-\\[var\\(--radix-select-trigger-height\\)\\]{height:var(--radix-select-trigger-height)}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.max-h-24{max-height:96px}.max-h-40{max-height:160px}.max-h-56{max-height:224px}.max-h-80{max-height:320px}.max-h-96{max-height:384px}.max-h-\\[150px\\]{max-height:150px}.max-h-\\[220px\\]{max-height:220px}.max-h-\\[320px\\]{max-height:320px}.max-h-\\[420px\\]{max-height:420px}.max-h-\\[90vh\\]{max-height:90vh}.max-h-\\[calc\\(100vh-3rem\\)\\]{max-height:calc(100vh - 48px)}.max-h-\\[min\\(80vh\\,640px\\)\\]{max-height:min(80vh,640px)}.min-h-0{min-height:0px}.min-h-11{min-height:44px}.min-h-\\[108px\\]{min-height:108px}.min-h-\\[120px\\]{min-height:120px}.min-h-\\[140px\\]{min-height:140px}.min-h-\\[220px\\]{min-height:220px}.w-0\\.5{width:2px}.w-1{width:4px}.w-1\\.5{width:6px}.w-1\\/2{width:50%}.w-10{width:40px}.w-12{width:48px}.w-14{width:56px}.w-16{width:64px}.w-2{width:8px}.w-3{width:12px}.w-3\\.5{width:14px}.w-4{width:16px}.w-5{width:20px}.w-6{width:24px}.w-7{width:28px}.w-72{width:288px}.w-8{width:32px}.w-80{width:320px}.w-9{width:36px}.w-\\[1\\.4rem\\]{width:22.4px}.w-\\[18px\\]{width:18px}.w-\\[22\\.5rem\\]{width:360px}.w-\\[22rem\\]{width:352px}.w-\\[30px\\]{width:30px}.w-\\[38px\\]{width:38px}.w-\\[calc\\(100vw-32px\\)\\]{width:calc(100vw - 32px)}.w-\\[min\\(24rem\\,calc\\(100vw_-_1\\.5rem\\)\\)\\]{width:min(384px,calc(100vw - 24px))}.w-\\[min\\(30rem\\,calc\\(100vw_-_1\\.5rem\\)\\)\\]{width:min(480px,calc(100vw - 24px))}.w-\\[min\\(560px\\,calc\\(100vw-32px\\)\\)\\]{width:min(560px,calc(100vw - 32px))}.w-\\[var\\(--radix-popover-trigger-width\\)\\]{width:var(--radix-popover-trigger-width)}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-max{width:-moz-max-content;width:max-content}.min-w-0{min-width:0px}.min-w-9{min-width:36px}.min-w-\\[12rem\\]{min-width:192px}.min-w-\\[200px\\]{min-width:200px}.min-w-\\[var\\(--radix-popover-trigger-width\\)\\]{min-width:var(--radix-popover-trigger-width)}.min-w-\\[var\\(--radix-select-trigger-width\\)\\]{min-width:var(--radix-select-trigger-width)}.max-w-\\[10rem\\]{max-width:160px}.max-w-\\[120px\\]{max-width:120px}.max-w-\\[160px\\]{max-width:160px}.max-w-\\[16rem\\]{max-width:256px}.max-w-\\[260px\\]{max-width:260px}.max-w-\\[280px\\]{max-width:280px}.max-w-\\[28rem\\]{max-width:448px}.max-w-\\[300px\\]{max-width:300px}.max-w-\\[360px\\]{max-width:360px}.max-w-\\[36rem\\]{max-width:576px}.max-w-\\[400px\\]{max-width:400px}.max-w-\\[420px\\]{max-width:420px}.max-w-\\[428px\\]{max-width:428px}.max-w-\\[480px\\]{max-width:480px}.max-w-\\[62ch\\]{max-width:62ch}.max-w-\\[640px\\]{max-width:640px}.max-w-\\[70ch\\]{max-width:70ch}.max-w-\\[90vw\\]{max-width:90vw}.max-w-\\[960px\\]{max-width:960px}.max-w-\\[calc\\(100vw-24px\\)\\]{max-width:calc(100vw - 24px)}.max-w-\\[var\\(--issue-sticker-size\\)\\]{max-width:var(--issue-sticker-size)}.max-w-full{max-width:100%}.max-w-md{max-width:448px}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.grow{flex-grow:1}.caption-bottom{caption-side:bottom}.border-collapse{border-collapse:collapse}.-translate-x-1{--tw-translate-x: -4px;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-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{--tw-translate-x: 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-x-1{--tw-translate-x: 4px;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-\\[-50\\%\\]{--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-x-\\[18px\\]{--tw-translate-x: 18px;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-\\[2px\\]{--tw-translate-x: 2px;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-\\[-50\\%\\]{--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))}.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 pulse-ring{0%,to{box-shadow:0 0 0 0 var(--brand-ring)}50%{box-shadow:0 0 0 8px transparent}}.animate-pulse-ring{animation:pulse-ring 1.8s var(--ease-in-out) infinite}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-col-resize{cursor:col-resize}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize-none{resize:none}.resize-y{resize:vertical}.resize{resize:both}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-row-reverse{flex-direction:row-reverse}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.content-center{align-content:center}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0px}.gap-0\\.5{gap:2px}.gap-1{gap:4px}.gap-1\\.5{gap:6px}.gap-2{gap:8px}.gap-2\\.5{gap:10px}.gap-3{gap:12px}.gap-3\\.5{gap:14px}.gap-4{gap:16px}.gap-5{gap:20px}.gap-6{gap:24px}.gap-x-5{-moz-column-gap:20px;column-gap:20px}.gap-y-2{row-gap:8px}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(4px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(4px * var(--tw-space-y-reverse))}.space-y-1\\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(6px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(6px * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(8px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(8px * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(12px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(12px * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(16px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(16px * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(20px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(20px * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(24px * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(24px * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-line-subtle>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-divide-opacity, 1))}.self-start{align-self:flex-start}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-normal{white-space:normal}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-line{white-space:pre-line}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.break-keep{word-break:keep-all}.\\!rounded-none{border-radius:0!important}.rounded{border-radius:4px}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-\\[18px\\]{border-radius:18px}.rounded-\\[20px\\]{border-radius:20px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-none{border-radius:0}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-xs{border-radius:var(--radius-xs)}.rounded-b-md{border-bottom-right-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.border{border-width:1px}.border-0{border-width:0px}.border-2{border-width:2px}.border-y{border-top-width:1px;border-bottom-width:1px}.border-b{border-bottom-width:1px}.border-b-2{border-bottom-width:2px}.border-l{border-left-width:1px}.border-l-2{border-left-width:2px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-t-0{border-top-width:0px}.border-dashed{border-style:dashed}.border-\\[hsl\\(144_8\\%_91\\%\\)\\]{--tw-border-opacity: 1;border-color:hsl(144 8% 91% / var(--tw-border-opacity, 1))}.border-brand{--tw-border-opacity: 1;border-color:hsl(var(--brand-hsl) / var(--tw-border-opacity, 1))}.border-brand-border{border-color:var(--brand-border)}.border-brand\\/30{border-color:hsl(var(--brand-hsl) / .3)}.border-brand\\/40{border-color:hsl(var(--brand-hsl) / .4)}.border-danger\\/20{border-color:hsl(var(--danger) / .2)}.border-danger\\/30{border-color:hsl(var(--danger) / .3)}.border-info\\/20{border-color:hsl(var(--info) / .2)}.border-info\\/30{border-color:hsl(var(--info) / .3)}.border-line{--tw-border-opacity: 1;border-color:hsl(var(--border-default) / var(--tw-border-opacity, 1))}.border-line-focus{--tw-border-opacity: 1;border-color:hsl(var(--border-focus) / var(--tw-border-opacity, 1))}.border-line-strong{--tw-border-opacity: 1;border-color:hsl(var(--border-strong) / var(--tw-border-opacity, 1))}.border-line-subtle{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}.border-line-subtle\\/50{border-color:hsl(var(--border-subtle) / .5)}.border-line-subtle\\/90{border-color:hsl(var(--border-subtle) / .9)}.border-slate-100{--tw-border-opacity: 1;border-color:rgb(241 245 249 / var(--tw-border-opacity, 1))}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-success{--tw-border-opacity: 1;border-color:hsl(var(--success) / var(--tw-border-opacity, 1))}.border-success\\/20{border-color:hsl(var(--success) / .2)}.border-success\\/30{border-color:hsl(var(--success) / .3)}.border-text-primary{--tw-border-opacity: 1;border-color:hsl(var(--text-primary) / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.border-warning\\/20{border-color:hsl(var(--warning) / .2)}.border-warning\\/30{border-color:hsl(var(--warning) / .3)}.border-white\\/70{border-color:#ffffffb3}.border-white\\/80{border-color:#fffc}.border-white\\/90{border-color:#ffffffe6}.border-l-brand{--tw-border-opacity: 1;border-left-color:hsl(var(--brand-hsl) / var(--tw-border-opacity, 1))}.\\!bg-success-surface{background-color:hsl(var(--success-surface))!important}.bg-\\[var\\(--overlay-backdrop-strong\\)\\]{background-color:var(--overlay-backdrop-strong)}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity, 1))}.bg-black\\/10{background-color:#0000001a}.bg-black\\/40{background-color:#0006}.bg-black\\/80{background-color:#000c}.bg-brand{--tw-bg-opacity: 1;background-color:hsl(var(--brand-hsl) / var(--tw-bg-opacity, 1))}.bg-brand-subtle{background-color:var(--brand-subtle)}.bg-brand\\/10{background-color:hsl(var(--brand-hsl) / .1)}.bg-brand\\/5{background-color:hsl(var(--brand-hsl) / .05)}.bg-danger{--tw-bg-opacity: 1;background-color:hsl(var(--danger) / var(--tw-bg-opacity, 1))}.bg-danger-subtle{background-color:hsl(var(--danger-subtle))}.bg-danger\\/10{background-color:hsl(var(--danger) / .1)}.bg-info-subtle{background-color:hsl(var(--info-subtle))}.bg-line{--tw-bg-opacity: 1;background-color:hsl(var(--border-default) / var(--tw-bg-opacity, 1))}.bg-line-subtle{--tw-bg-opacity: 1;background-color:hsl(var(--border-subtle) / var(--tw-bg-opacity, 1))}.bg-success{--tw-bg-opacity: 1;background-color:hsl(var(--success) / var(--tw-bg-opacity, 1))}.bg-success-subtle{background-color:hsl(var(--success-subtle))}.bg-success-surface{background-color:hsl(var(--success-surface))}.bg-surface-0{--tw-bg-opacity: 1;background-color:hsl(var(--surface-0) / var(--tw-bg-opacity, 1))}.bg-surface-1{--tw-bg-opacity: 1;background-color:hsl(var(--surface-1) / var(--tw-bg-opacity, 1))}.bg-surface-2{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.bg-surface-3{--tw-bg-opacity: 1;background-color:hsl(var(--surface-3) / var(--tw-bg-opacity, 1))}.bg-surface-inset{--tw-bg-opacity: 1;background-color:hsl(var(--surface-inset) / var(--tw-bg-opacity, 1))}.bg-text-primary{--tw-bg-opacity: 1;background-color:hsl(var(--text-primary) / var(--tw-bg-opacity, 1))}.bg-text-tertiary{--tw-bg-opacity: 1;background-color:hsl(var(--text-tertiary) / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-warning{--tw-bg-opacity: 1;background-color:hsl(var(--warning) / var(--tw-bg-opacity, 1))}.bg-warning-subtle{background-color:hsl(var(--warning-subtle))}.bg-warning\\/10{background-color:hsl(var(--warning) / .1)}.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\\/25{background-color:#ffffff40}.fill-text-primary{fill:hsl(var(--text-primary) / 1)}.stroke-\\[3\\]{stroke-width:3}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.\\!p-0{padding:0!important}.p-0{padding:0}.p-0\\.5{padding:2px}.p-1{padding:4px}.p-1\\.5{padding:6px}.p-2{padding:8px}.p-3{padding:12px}.p-3\\.5{padding:14px}.p-4{padding:16px}.p-5{padding:20px}.p-6{padding:24px}.p-7{padding:28px}.p-8{padding:32px}.p-\\[18px\\]{padding:18px}.px-0{padding-left:0;padding-right:0}.px-1\\.5{padding-left:6px;padding-right:6px}.px-2{padding-left:8px;padding-right:8px}.px-2\\.5{padding-left:10px;padding-right:10px}.px-3{padding-left:12px;padding-right:12px}.px-4{padding-left:16px;padding-right:16px}.px-5{padding-left:20px;padding-right:20px}.px-6{padding-left:24px;padding-right:24px}.px-9{padding-left:36px;padding-right:36px}.py-0\\.5{padding-top:2px;padding-bottom:2px}.py-1{padding-top:4px;padding-bottom:4px}.py-1\\.5{padding-top:6px;padding-bottom:6px}.py-10{padding-top:40px;padding-bottom:40px}.py-16{padding-top:64px;padding-bottom:64px}.py-2{padding-top:8px;padding-bottom:8px}.py-2\\.5{padding-top:10px;padding-bottom:10px}.py-3{padding-top:12px;padding-bottom:12px}.py-3\\.5{padding-top:14px;padding-bottom:14px}.py-4{padding-top:16px;padding-bottom:16px}.py-5{padding-top:20px;padding-bottom:20px}.py-6{padding-top:24px;padding-bottom:24px}.py-8{padding-top:32px;padding-bottom:32px}.pb-1{padding-bottom:4px}.pb-3{padding-bottom:12px}.pb-4{padding-bottom:16px}.pl-0{padding-left:0}.pl-3{padding-left:12px}.pl-4{padding-left:16px}.pl-5{padding-left:20px}.pl-8{padding-left:32px}.pr-10{padding-right:40px}.pr-3{padding-right:12px}.pr-4{padding-right:16px}.pt-0{padding-top:0}.pt-1{padding-top:4px}.pt-2\\.5{padding-top:10px}.pt-4{padding-top:16px}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.font-display{font-family:var(--font-display),ui-sans-serif,system-ui,sans-serif}.font-mono{font-family:var(--font-mono),ui-monospace,SFMono-Regular,Menlo,monospace}.font-sans{font-family:var(--font-sans),ui-sans-serif,system-ui,sans-serif}.text-2xs{font-size:clamp(10.5px,10.19px + .082vw,11.5px);line-height:1.333}.text-\\[0\\.72rem\\]{font-size:11.52px}.text-\\[1\\.45rem\\]{font-size:23.2px}.text-\\[1\\.75rem\\]{font-size:28px}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.text-base{font-size:clamp(14px,13.39px + .163vw,16px);line-height:1.5}.text-lg{font-size:clamp(17px,16.39px + .163vw,19px);line-height:1.471}.text-sm{font-size:clamp(13px,12.54px + .122vw,14.5px);line-height:1.462}.text-xl{font-size:clamp(20px,19.08px + .245vw,23px);line-height:1.45}.text-xs{font-size:clamp(12px,11.69px + .082vw,13px);line-height:1.333}.font-black{font-weight:900}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.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:16px}.leading-5{line-height:20px}.leading-8{line-height:32px}.leading-\\[1\\.55\\]{line-height:1.55}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.text-\\[hsl\\(145_5\\%_42\\%\\)\\]{--tw-text-opacity: 1;color:hsl(145 5% 42% / var(--tw-text-opacity, 1))}.text-brand{--tw-text-opacity: 1;color:hsl(var(--brand-hsl) / var(--tw-text-opacity, 1))}.text-brand-fg{color:var(--brand-fg)}.text-brand\\/50{color:hsl(var(--brand-hsl) / .5)}.text-danger{--tw-text-opacity: 1;color:hsl(var(--danger) / var(--tw-text-opacity, 1))}.text-danger\\/80{color:hsl(var(--danger) / .8)}.text-info{--tw-text-opacity: 1;color:hsl(var(--info) / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-success{--tw-text-opacity: 1;color:hsl(var(--success) / var(--tw-text-opacity, 1))}.text-text-disabled{--tw-text-opacity: 1;color:hsl(var(--text-disabled) / var(--tw-text-opacity, 1))}.text-text-inverse{--tw-text-opacity: 1;color:hsl(var(--text-inverse) / var(--tw-text-opacity, 1))}.text-text-primary{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.text-text-secondary{--tw-text-opacity: 1;color:hsl(var(--text-secondary) / var(--tw-text-opacity, 1))}.text-text-tertiary{--tw-text-opacity: 1;color:hsl(var(--text-tertiary) / var(--tw-text-opacity, 1))}.text-transparent{color:transparent}.text-warning{--tw-text-opacity: 1;color:hsl(var(--warning) / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-white\\/90{color:#ffffffe6}.underline{text-decoration-line:underline}.line-through{text-decoration-line:line-through}.underline-offset-2{text-underline-offset:2px}.underline-offset-4{text-underline-offset:4px}.accent-brand{accent-color:hsl(var(--brand-hsl) / 1)}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-70{opacity:.7}.opacity-80{opacity:.8}.\\!shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1) !important;--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color) !important;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)!important}.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_24px_70px_-28px_rgba\\(16\\,24\\,18\\,0\\.45\\)\\]{--tw-shadow: 0 24px 70px -28px rgba(16,24,18,.45);--tw-shadow-colored: 0 24px 70px -28px 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: var(--shadow-lg);--tw-shadow-colored: var(--shadow-lg);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: var(--shadow-md);--tw-shadow-colored: var(--shadow-md);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: var(--shadow-sm);--tw-shadow-colored: var(--shadow-sm);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: var(--shadow-xl);--tw-shadow-colored: var(--shadow-xl);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xs{--tw-shadow: var(--shadow-xs);--tw-shadow-colored: var(--shadow-xs);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.outline-2{outline-width:2px}.outline-offset-0{outline-offset:0px}.outline-transparent{outline-color:transparent}.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-4{--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(4px + 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-brand{--tw-ring-opacity: 1;--tw-ring-color: hsl(var(--brand-hsl) / var(--tw-ring-opacity, 1))}.ring-brand-subtle{--tw-ring-color: var(--brand-subtle)}.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)}.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-\\[2px\\]{--tw-backdrop-blur: blur(2px);-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-\\[background-color\\,border-color\\,color\\,box-shadow\\]{transition-property:background-color,border-color,color,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[background-color\\,color\\,border-color\\,box-shadow\\,opacity\\]{transition-property:background-color,color,border-color,box-shadow,opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[background-color\\,color\\,border-color\\,box-shadow\\]{transition-property:background-color,color,border-color,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[background-color\\,color\\,box-shadow\\]{transition-property:background-color,color,box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[background-color\\,color\\]{transition-property:background-color,color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[border-color\\,box-shadow\\,background-color\\]{transition-property:border-color,box-shadow,background-color;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[border-color\\,outline-color\\,box-shadow\\,background-color\\,transform\\]{transition-property:border-color,outline-color,box-shadow,background-color,transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[max-width\\,height\\,box-shadow\\,background-color\\,border-color\\,transform\\,opacity\\]{transition-property:max-width,height,box-shadow,background-color,border-color,transform,opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[max-width\\]{transition-property:max-width;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-\\[opacity\\,transform\\]{transition-property:opacity,transform;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-300{transition-duration:.3s}.duration-\\[var\\(--issue-marker-expand-duration\\)\\]{transition-duration:var(--issue-marker-expand-duration)}.duration-fast{transition-duration:var(--duration-fast)}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-in-out{transition-timing-function:var(--ease-in-out)}.ease-out{transition-timing-function:var(--ease-out)}@keyframes float-gentle{0%,to{transform:translateY(0)}50%{transform:translateY(-2px)}}@keyframes toast-slide{0%{opacity:0;transform:translateY(-14px) scale(.98)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes gradient-shift{0%,to{background-position:0% 50%}50%{background-position:100% 50%}}.issue-overlay-shell{border:1px solid hsl(var(--border-subtle));border-radius:var(--radius-lg);background:hsl(var(--surface-1));box-shadow:var(--shadow-md)}.issue-marker-breathe{animation:float-gentle 4.8s var(--ease-in-out) infinite}.issue-marker-breathe:hover,.issue-marker-breathe:focus-visible,.issue-marker-breathe:focus-within{animation-play-state:paused}.\\[overflow-wrap\\:anywhere\\]{overflow-wrap:anywhere}.marker\\:text-text-tertiary *::marker{color:hsl(var(--text-tertiary))}.marker\\:text-text-tertiary::marker{color:hsl(var(--text-tertiary))}.file\\:border-0::file-selector-button{border-width:0px}.file\\:bg-transparent::file-selector-button{background-color:transparent}.file\\:text-sm::file-selector-button{font-size:clamp(13px,12.54px + .122vw,14.5px);line-height:1.462}.file\\:font-medium::file-selector-button{font-weight:500}.file\\:text-text-primary::file-selector-button{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.placeholder\\:text-text-tertiary::-moz-placeholder{--tw-text-opacity: 1;color:hsl(var(--text-tertiary) / var(--tw-text-opacity, 1))}.placeholder\\:text-text-tertiary::placeholder{--tw-text-opacity: 1;color:hsl(var(--text-tertiary) / var(--tw-text-opacity, 1))}.first\\:mt-0:first-child{margin-top:0}.first\\:border-t-0:first-child{border-top-width:0px}.first\\:pt-0:first-child{padding-top:0}.focus-within\\:z-\\[10001\\]:focus-within{z-index:10001}.focus-within\\:border-line-focus:focus-within{--tw-border-opacity: 1;border-color:hsl(var(--border-focus) / var(--tw-border-opacity, 1))}.hover\\:z-\\[10001\\]:hover{z-index:10001}.hover\\:border-line:hover{--tw-border-opacity: 1;border-color:hsl(var(--border-default) / var(--tw-border-opacity, 1))}.hover\\:border-line-strong:hover{--tw-border-opacity: 1;border-color:hsl(var(--border-strong) / var(--tw-border-opacity, 1))}.hover\\:border-line-subtle:hover{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}.hover\\:bg-\\[hsl\\(144_8\\%_96\\%\\)\\]:hover{--tw-bg-opacity: 1;background-color:hsl(144 8% 96% / var(--tw-bg-opacity, 1))}.hover\\:bg-blue-500:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.hover\\:bg-brand-hover:hover{background-color:var(--brand-hover)}.hover\\:bg-brand\\/40:hover{background-color:hsl(var(--brand-hsl) / .4)}.hover\\:bg-danger-subtle:hover{background-color:hsl(var(--danger-subtle))}.hover\\:bg-danger\\/10:hover{background-color:hsl(var(--danger) / .1)}.hover\\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.hover\\:bg-slate-50:hover{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.hover\\:bg-surface-2:hover{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.hover\\:bg-surface-2\\/60:hover{background-color:hsl(var(--surface-2) / .6)}.hover\\:bg-surface-3:hover{--tw-bg-opacity: 1;background-color:hsl(var(--surface-3) / var(--tw-bg-opacity, 1))}.hover\\:bg-surface-inset:hover{--tw-bg-opacity: 1;background-color:hsl(var(--surface-inset) / var(--tw-bg-opacity, 1))}.hover\\:bg-transparent:hover{background-color:transparent}.hover\\:bg-white\\/20:hover{background-color:#fff3}.hover\\:text-\\[hsl\\(150_10\\%_12\\%\\)\\]:hover{--tw-text-opacity: 1;color:hsl(150 10% 12% / var(--tw-text-opacity, 1))}.hover\\:text-brand-hover:hover{color:var(--brand-hover)}.hover\\:text-danger:hover{--tw-text-opacity: 1;color:hsl(var(--danger) / var(--tw-text-opacity, 1))}.hover\\:text-slate-900:hover{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.hover\\:text-text-primary:hover{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.hover\\:text-text-secondary:hover{--tw-text-opacity: 1;color:hsl(var(--text-secondary) / var(--tw-text-opacity, 1))}.hover\\:underline:hover{text-decoration-line:underline}.hover\\:opacity-90:hover{opacity:.9}.focus\\:border-brand:focus{--tw-border-opacity: 1;border-color:hsl(var(--brand-hsl) / var(--tw-border-opacity, 1))}.focus\\:bg-surface-2:focus{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.focus\\:text-text-primary:focus{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.focus\\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus-visible\\:h-\\[var\\(--issue-sticker-hover-size\\)\\]:focus-visible{height:var(--issue-sticker-hover-size)}.focus-visible\\:max-w-\\[160px\\]:focus-visible{max-width:160px}.focus-visible\\:max-w-\\[480px\\]:focus-visible{max-width:480px}.focus-visible\\:border-line-focus:focus-visible{--tw-border-opacity: 1;border-color:hsl(var(--border-focus) / var(--tw-border-opacity, 1))}.focus-visible\\:border-transparent:focus-visible{border-color:transparent}.focus-visible\\:bg-slate-50:focus-visible{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.focus-visible\\:bg-surface-1:focus-visible{--tw-bg-opacity: 1;background-color:hsl(var(--surface-1) / var(--tw-bg-opacity, 1))}.focus-visible\\:bg-surface-2:focus-visible{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.focus-visible\\:text-text-primary:focus-visible{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.focus-visible\\:shadow-focus:focus-visible{--tw-shadow: var(--shadow-focus);--tw-shadow-colored: var(--shadow-focus);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.focus-visible\\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\\:outline-line-focus:focus-visible{outline-color:hsl(var(--border-focus) / 1)}.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-4: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(4px + 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-brand-subtle:focus-visible{--tw-ring-color: var(--brand-subtle)}.focus-visible\\:ring-white\\/40:focus-visible{--tw-ring-color: rgb(255 255 255 / .4)}.active\\:bg-brand-active:active{background-color:var(--brand-active)}.active\\:bg-brand\\/60:active{background-color:hsl(var(--brand-hsl) / .6)}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-40:disabled{opacity:.4}.disabled\\:opacity-50:disabled{opacity:.5}.group\\/marker:hover .group-hover\\/marker\\:h-\\[var\\(--issue-sticker-hover-size\\)\\]{height:var(--issue-sticker-hover-size)}.group\\/marker:hover .group-hover\\/marker\\:max-w-\\[160px\\]{max-width:160px}.group\\/marker:hover .group-hover\\/marker\\:max-w-\\[480px\\]{max-width:480px}.group\\/marker:hover .group-hover\\/marker\\:translate-x-0{--tw-translate-x: 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))}.group\\/marker:hover .group-hover\\/marker\\:bg-brand-hover{background-color:var(--brand-hover)}.group\\/marker:hover .group-hover\\/marker\\:opacity-100{opacity:1}.group\\/marker:hover .group-hover\\/marker\\:shadow-xl{--tw-shadow: var(--shadow-xl);--tw-shadow-colored: var(--shadow-xl);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.group:focus-visible .group-focus-visible\\:translate-x-0{--tw-translate-x: 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))}.group:focus-visible .group-focus-visible\\:opacity-100{opacity:1}.group.toaster .group-\\[\\.toaster\\]\\:isolate{isolation:isolate}.group.toast .group-\\[\\.toast\\]\\:rounded-md,.group.toaster .group-\\[\\.toaster\\]\\:rounded-md{border-radius:var(--radius-md)}.group.toaster .group-\\[\\.toaster\\]\\:border{border-width:1px}.group.toaster .group-\\[\\.toaster\\]\\:\\!border-danger\\/30{border-color:hsl(var(--danger) / .3)!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!border-info\\/30{border-color:hsl(var(--info) / .3)!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!border-success\\/30{border-color:hsl(var(--success) / .3)!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!border-warning\\/30{border-color:hsl(var(--warning) / .3)!important}.group.toaster .group-\\[\\.toaster\\]\\:border-line-subtle{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}.group.toast .group-\\[\\.toast\\]\\:bg-brand{--tw-bg-opacity: 1;background-color:hsl(var(--brand-hsl) / var(--tw-bg-opacity, 1))}.group.toast .group-\\[\\.toast\\]\\:bg-surface-2{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:\\!bg-danger-subtle{background-color:hsl(var(--danger-subtle))!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!bg-info-subtle{background-color:hsl(var(--info-subtle))!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!bg-success-surface{background-color:hsl(var(--success-surface))!important}.group.toaster .group-\\[\\.toaster\\]\\:\\!bg-warning-subtle{background-color:hsl(var(--warning-subtle))!important}.group.toaster .group-\\[\\.toaster\\]\\:bg-surface-1{--tw-bg-opacity: 1;background-color:hsl(var(--surface-1) / var(--tw-bg-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:px-4{padding-left:16px;padding-right:16px}.group.toaster .group-\\[\\.toaster\\]\\:py-3{padding-top:12px;padding-bottom:12px}.group.toast .group-\\[\\.toast\\]\\:text-sm{font-size:clamp(13px,12.54px + .122vw,14.5px);line-height:1.462}.group.toast .group-\\[\\.toast\\]\\:text-xs{font-size:clamp(12px,11.69px + .082vw,13px);line-height:1.333}.group.toast .group-\\[\\.toast\\]\\:font-medium{font-weight:500}.group.toast .group-\\[\\.toast\\]\\:text-brand-fg{color:var(--brand-fg)}.group.toast .group-\\[\\.toast\\]\\:text-text-primary{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.group.toast .group-\\[\\.toast\\]\\:text-text-secondary{--tw-text-opacity: 1;color:hsl(var(--text-secondary) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:text-text-primary{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:shadow-sm{--tw-shadow: var(--shadow-sm);--tw-shadow-colored: var(--shadow-sm);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.group.toaster .group-\\[\\.toaster\\]\\:before\\:absolute:before{content:var(--tw-content);position:absolute}.group.toaster .group-\\[\\.toaster\\]\\:before\\:inset-0:before{content:var(--tw-content);top:0;right:0;bottom:0;left:0}.group.toaster .group-\\[\\.toaster\\]\\:before\\:-z-10:before{content:var(--tw-content);z-index:-10}.group.toaster .group-\\[\\.toaster\\]\\:before\\:rounded-md:before{content:var(--tw-content);border-radius:var(--radius-md)}.group.toaster .group-\\[\\.toaster\\]\\:before\\:bg-surface-1:before{content:var(--tw-content);--tw-bg-opacity: 1;background-color:hsl(var(--surface-1) / var(--tw-bg-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:before\\:content-\\[\\'\\'\\]:before{--tw-content: "";content:var(--tw-content)}.peer:focus-visible~.peer-focus-visible\\:shadow-focus{--tw-shadow: var(--shadow-focus);--tw-shadow-colored: var(--shadow-focus);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.peer:disabled~.peer-disabled\\:cursor-not-allowed{cursor:not-allowed}.peer:disabled~.peer-disabled\\:opacity-60{opacity:.6}.aria-disabled\\:pointer-events-none[aria-disabled=true]{pointer-events:none}.aria-disabled\\:opacity-40[aria-disabled=true]{opacity:.4}.data-\\[disabled\\]\\:pointer-events-none[data-disabled]{pointer-events:none}@keyframes dialog-out{0%{opacity:1;transform:translate(-50%,-50%) scale(1)}to{opacity:0;transform:translate(-50%,calc(-50% + 8px)) scale(.985)}}.data-\\[state\\=closed\\]\\:animate-dialog-out[data-state=closed]{animation:dialog-out var(--duration-out) var(--ease-out) forwards}@keyframes fade-out{0%{opacity:1}to{opacity:0}}.data-\\[state\\=closed\\]\\:animate-fade-out[data-state=closed]{animation:fade-out var(--duration-out) var(--ease-out) forwards}@keyframes scale-out{0%{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(.97)}}.data-\\[state\\=closed\\]\\:animate-scale-out[data-state=closed]{animation:scale-out var(--duration-out) var(--ease-out) forwards}@keyframes sheet-out-left{0%{transform:translate(0)}to{transform:translate(-100%);opacity:.6}}.data-\\[state\\=closed\\]\\:animate-sheet-out-left[data-state=closed]{animation:sheet-out-left var(--duration-base) var(--ease-out) forwards}@keyframes sheet-out-right{0%{transform:translate(0);opacity:1}to{transform:translate(100%);opacity:.6}}.data-\\[state\\=closed\\]\\:animate-sheet-out-right[data-state=closed]{animation:sheet-out-right var(--duration-base) var(--ease-out) forwards}.data-\\[state\\=delayed-open\\]\\:animate-scale-in[data-state=delayed-open]{animation:scale-in var(--duration-base) var(--ease-out) forwards}@keyframes dialog-in{0%{opacity:0;transform:translate(-50%,calc(-50% + 12px)) scale(.985)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}.data-\\[state\\=open\\]\\:animate-dialog-in[data-state=open]{animation:dialog-in var(--duration-base) var(--ease-out) forwards}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.data-\\[state\\=open\\]\\:animate-fade-in[data-state=open]{animation:fade-in var(--duration-base) var(--ease-out) forwards}@keyframes scale-in{0%{opacity:0;transform:scale(.98)}to{opacity:1;transform:scale(1)}}.data-\\[state\\=open\\]\\:animate-scale-in[data-state=open]{animation:scale-in var(--duration-base) var(--ease-out) forwards}@keyframes sheet-in-left{0%{transform:translate(-100%);opacity:.6}to{transform:translate(0);opacity:1}}.data-\\[state\\=open\\]\\:animate-sheet-in-left[data-state=open]{animation:sheet-in-left var(--duration-base) var(--ease-out) forwards}@keyframes sheet-in-right{0%{transform:translate(100%);opacity:.6}to{transform:translate(0)}}.data-\\[state\\=open\\]\\:animate-sheet-in-right[data-state=open]{animation:sheet-in-right var(--duration-base) var(--ease-out) forwards}.data-\\[range-end\\=true\\]\\:rounded-md[data-range-end=true]{border-radius:var(--radius-md)}.data-\\[range-middle\\=true\\]\\:rounded-none[data-range-middle=true]{border-radius:0}.data-\\[range-start\\=true\\]\\:rounded-md[data-range-start=true]{border-radius:var(--radius-md)}.data-\\[state\\=open\\]\\:border-line-focus[data-state=open]{--tw-border-opacity: 1;border-color:hsl(var(--border-focus) / var(--tw-border-opacity, 1))}.data-\\[highlighted\\]\\:bg-surface-2[data-highlighted]{--tw-bg-opacity: 1;background-color:hsl(var(--surface-2) / var(--tw-bg-opacity, 1))}.data-\\[range-end\\=true\\]\\:bg-brand[data-range-end=true]{--tw-bg-opacity: 1;background-color:hsl(var(--brand-hsl) / var(--tw-bg-opacity, 1))}.data-\\[range-middle\\=true\\]\\:bg-transparent[data-range-middle=true]{background-color:transparent}.data-\\[range-start\\=true\\]\\:bg-brand[data-range-start=true],.data-\\[selected-single\\=true\\]\\:bg-brand[data-selected-single=true]{--tw-bg-opacity: 1;background-color:hsl(var(--brand-hsl) / var(--tw-bg-opacity, 1))}.data-\\[state\\=selected\\]\\:bg-brand-subtle[data-state=selected]{background-color:var(--brand-subtle)}.data-\\[today\\=true\\]\\:font-semibold[data-today=true]{font-weight:600}.data-\\[highlighted\\]\\:text-text-primary[data-highlighted]{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.data-\\[placeholder\\]\\:text-text-tertiary[data-placeholder]{--tw-text-opacity: 1;color:hsl(var(--text-tertiary) / var(--tw-text-opacity, 1))}.data-\\[range-end\\=true\\]\\:text-brand-fg[data-range-end=true]{color:var(--brand-fg)}.data-\\[range-middle\\=true\\]\\:text-text-primary[data-range-middle=true]{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.data-\\[range-start\\=true\\]\\:text-brand-fg[data-range-start=true],.data-\\[selected-single\\=true\\]\\:text-brand-fg[data-selected-single=true]{color:var(--brand-fg)}.data-\\[state\\=active\\]\\:text-text-primary[data-state=active],.data-\\[state\\=checked\\]\\:text-text-primary[data-state=checked]{--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.data-\\[today\\=true\\]\\:text-brand[data-today=true]{--tw-text-opacity: 1;color:hsl(var(--brand-hsl) / var(--tw-text-opacity, 1))}.data-\\[disabled\\]\\:opacity-50[data-disabled]{opacity:.5}.data-\\[state\\=open\\]\\:shadow-focus[data-state=open]{--tw-shadow: var(--shadow-focus);--tw-shadow-colored: var(--shadow-focus);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.data-\\[range-end\\=true\\]\\:hover\\:bg-brand-hover:hover[data-range-end=true],.data-\\[range-start\\=true\\]\\:hover\\:bg-brand-hover:hover[data-range-start=true],.data-\\[selected-single\\=true\\]\\:hover\\:bg-brand-hover:hover[data-selected-single=true]{background-color:var(--brand-hover)}.data-\\[range-end\\=true\\]\\:hover\\:text-brand-fg:hover[data-range-end=true],.data-\\[range-start\\=true\\]\\:hover\\:text-brand-fg:hover[data-range-start=true],.data-\\[selected-single\\=true\\]\\:hover\\:text-brand-fg:hover[data-selected-single=true]{color:var(--brand-fg)}@media(prefers-reduced-motion:reduce){.motion-reduce\\:animate-none{animation:none}}@media(min-width:640px){.sm\\:flex-row{flex-direction:row}.sm\\:items-start{align-items:flex-start}.sm\\:items-center{align-items:center}.sm\\:justify-end{justify-content:flex-end}.sm\\:justify-between{justify-content:space-between}.sm\\:gap-2\\.5{gap:10px}.sm\\:p-5{padding:20px}.sm\\:p-6{padding:24px}.sm\\:text-2xl{font-size:clamp(26px,24.78px + .327vw,30px);line-height:1.308}.sm\\:text-\\[2\\.1rem\\]{font-size:33.6px}}@media(min-width:768px){.md\\:flex{display:flex}.md\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\\:grid-cols-\\[minmax\\(0\\,1fr\\)_minmax\\(260px\\,340px\\)\\]{grid-template-columns:minmax(0,1fr) minmax(260px,340px)}}.\\[\\&\\>\\*\\:not\\(summary\\)\\]\\:pl-4>*:not(summary){padding-left:16px}.\\[\\&\\>span\\]\\:line-clamp-1>span{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.\\[\\&\\>tr\\]\\:last\\:border-b-0:last-child>tr{border-bottom-width:0px}.\\[\\&\\[data-state\\=open\\]\\>span\\[data-chevron\\]\\]\\:rotate-180[data-state=open]>span[data-chevron]{--tw-rotate: 180deg;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.toaster .group-\\[\\.toaster\\]\\:\\[\\&_\\[data-icon\\]\\]\\:text-danger [data-icon]{--tw-text-opacity: 1;color:hsl(var(--danger) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:\\[\\&_\\[data-icon\\]\\]\\:text-info [data-icon]{--tw-text-opacity: 1;color:hsl(var(--info) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:\\[\\&_\\[data-icon\\]\\]\\:text-success [data-icon]{--tw-text-opacity: 1;color:hsl(var(--success) / var(--tw-text-opacity, 1))}.group.toaster .group-\\[\\.toaster\\]\\:\\[\\&_\\[data-icon\\]\\]\\:text-warning [data-icon]{--tw-text-opacity: 1;color:hsl(var(--warning) / var(--tw-text-opacity, 1))}.\\[\\&_tr\\]\\:border-b tr{border-bottom-width:1px}.\\[\\&_tr\\]\\:border-line-subtle tr{--tw-border-opacity: 1;border-color:hsl(var(--border-subtle) / var(--tw-border-opacity, 1))}li .\\[li_\\&\\]\\:pl-5{padding-left:20px}`;
39888
40250
  const sdkShadowCSS = ".issue-sticker-marker{pointer-events:auto}@keyframes highlight-pulse{0%,to{transform:scale(1);box-shadow:var(--shadow-md)}50%{transform:scale(1.3);box-shadow:var(--shadow-focus),var(--shadow-lg)}}.issue-sticker-marker.highlight-animation{animation:highlight-pulse .7s ease-in-out 3}";
39889
40251
  const contentPageCSS = `@layer issue-sticker-mode{html:has(>body.issue-sticker-mode-active),body.issue-sticker-mode-active,body.issue-sticker-mode-active *{cursor:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32'%3E%3Cpath d='M3 29 C3 22 3 20 3 15 a12 12 0 0 1 12-12 h2 a12 12 0 0 1 12 12 a12 12 0 0 1-12 12 H12 Z' fill='%231C221F' fill-opacity='0.35' stroke='%23ffffff' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E") 3 29,crosshair!important}body.issue-sticker-mode-active iframe{pointer-events:none!important}body.issue-sticker-mode-active .issue-sticker-mode-highlight{outline:2px solid hsl(160 64% 34%)!important;outline-offset:2px!important;background-color:#1f8e691f!important;transition:outline .1s ease,background-color .1s ease!important}}`;
39890
40252
  const PAGE_STYLE_ID = "issue-sticker-page-style";
39891
40253
  let root = null;
39892
40254
  let mountContainer = null;
40255
+ let detachHostGuards = null;
39893
40256
  function renderWidget(config) {
39894
40257
  if (!root || !mountContainer) {
39895
40258
  return;
@@ -39920,9 +40283,13 @@ function mountWidget(config) {
39920
40283
  }
39921
40284
  document.body.appendChild(hostElement);
39922
40285
  const shadow = createShadowRoot(hostElement, [globalsCSS, sdkShadowCSS]);
39923
- attachHostTypingGuard(shadow.shadowRoot);
39924
- attachHostPointerGuard(shadow.shadowRoot);
39925
- attachHostInteractionGuard(shadow.shadowRoot);
40286
+ detachHostGuards == null ? void 0 : detachHostGuards();
40287
+ const guards = [
40288
+ attachHostTypingGuard(shadow.shadowRoot),
40289
+ attachHostPointerGuard(shadow.shadowRoot),
40290
+ attachHostInteractionGuard(shadow.shadowRoot)
40291
+ ];
40292
+ detachHostGuards = () => guards.forEach((detach) => detach());
39926
40293
  mountContainer = shadow.mountContainer;
39927
40294
  mountContainer.style.width = "0";
39928
40295
  mountContainer.style.height = "0";
@@ -39938,6 +40305,8 @@ function unmountWidget() {
39938
40305
  root = null;
39939
40306
  }
39940
40307
  mountContainer = null;
40308
+ detachHostGuards == null ? void 0 : detachHostGuards();
40309
+ detachHostGuards = null;
39941
40310
  const host = document.getElementById(ISSUE_STICKER_HOST_ELEMENT_ID);
39942
40311
  if (host && getIssueStickerRuntimeOwner(host) !== ISSUE_STICKER_RUNTIME_OWNER.extension) {
39943
40312
  host.remove();