issue-sticker 0.4.0 → 0.5.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,14 +15,14 @@ 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 { A as trimLogBackupPayload, B as createSafeLogBackup, D as getLogBackupSessionId, N as NetworkCollector, C as ConsoleCollector, E as createIndexedDbLogBackup, e as buildJiraCreateFields, P as Popover, F as PopoverTrigger, I as Input, G as PopoverContent, L as Label, H as Select, J as SelectTrigger, K as SelectValue, M as SelectContent, O as SelectItem, Q as getJiraMetadata, R as buildJiraIssueFields, T as Button, U as Root2$2, V as Trigger$2, W as ChevronDown, X as Portal, Y as Content2$1, Z as Check, _ as X$1, $ as DatePicker, f as buildNotionCreateFields, a0 as getNotionPageMetadata, a1 as buildNotionFieldViews, c as captureWithModernScreenshot, p as pristineFetch, d as directUploadToSignedUrl, a2 as DirectUploadError, a as uploadSignedMediaWithApi, v as sanitizeString, a3 as getRegisteredUploadId, h as buildGuestOwnerQuery, j as devLogger, w as getCurrentPageUrl, a4 as subscribe, a5 as getSnapshot, a6 as toast, a7 as ChevronRight, a8 as getExposedJiraFields, a9 as isJiraFieldExposed, n as normalizeExposedJiraFields, y as preloadModernScreenshot, u as uploadScreenshotDataUrls, k as filterExcludeServiceRelatedLogs, l as filterExcludeServiceRelatedConsoleLogs, s as selectNetworkLogsForSubmit, m as compactNetworkLogsForTransport, o as CONSOLE_LOG_SUBMIT_LIMIT, g as getElementPosition, q as buildExternalUserPayload, r as shrinkNetworkLogsToFit, t as measureJsonBytes, i as buildIssueIntegrationsPayload, x as SessionReplayCaptureController, aa as getPrimaryJiraMapping, ab as createCollection, ac as useDirection, ad as ReactRemoveScroll, ae as hideOthers, af as useFocusGuards, ag as FocusScope, ah as getPrimaryNotionMapping, ai as buttonVariants, aj as findElementBySelector, ak as findElementByXPath, S as ScreenRecordingController, al as OnboardingProvider, am as useOnboardingTarget, an as useOnboardingFlow, ao as ISSUE_STICKER_HOST_ELEMENT_ID, ap as getIssueStickerRuntimeOwner, aq as ISSUE_STICKER_RUNTIME_OWNER, z as isIssueStickerExtensionRuntimeActive, ar as createRuntimeHostElement, as as attachHostTypingGuard, at as ISSUE_STICKER_EXTENSION_RUNTIME_READY_EVENT } from "./externalUserPayload-BVNl_35M.js";
18
+ import { A as trimLogBackupPayload, B as createSafeLogBackup, D as getLogBackupSessionId, N as NetworkCollector, C as ConsoleCollector, E as createIndexedDbLogBackup, e 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 getJiraMetadata, T as buildJiraIssueFields, U as Button, V as Root2$2, W as Trigger$2, X as ChevronDown, Y as Portal, Z as Content2$1, _ as Check, $ as X$1, a0 as DatePicker, f as buildNotionCreateFields, a1 as getNotionPageMetadata, a2 as buildNotionFieldViews, c as captureWithModernScreenshot, p as pristineFetch, d as directUploadToSignedUrl, a3 as DirectUploadError, a4 as toast, a5 as getSnapshot, a6 as subscribe, a as uploadSignedMediaWithApi, v as sanitizeString, a7 as getRegisteredUploadId, h as buildGuestOwnerQuery, j as devLogger, w as getCurrentPageUrl, a8 as ChevronRight, a9 as ReactRemoveScroll, aa as hideOthers, ab as useFocusGuards, ac as FocusScope, ad as getExposedJiraFields, ae as isJiraFieldExposed, n as normalizeExposedJiraFields, y as preloadModernScreenshot, u as uploadScreenshotDataUrls, k as filterExcludeServiceRelatedLogs, l as filterExcludeServiceRelatedConsoleLogs, s as selectNetworkLogsForSubmit, m as compactNetworkLogsForTransport, o as CONSOLE_LOG_SUBMIT_LIMIT, g as getElementPosition, q as buildExternalUserPayload, r as shrinkNetworkLogsToFit, t as measureJsonBytes, i as buildIssueIntegrationsPayload, x as SessionReplayCaptureController, af as getPrimaryJiraMapping, ag as createCollection, ah as useDirection, ai as getPrimaryNotionMapping, aj as buttonVariants, ak as findElementBySelector, al as findElementByXPath, S as ScreenRecordingController, am as OnboardingProvider, an as useOnboardingTarget, ao as useOnboardingFlow, ap as ISSUE_STICKER_HOST_ELEMENT_ID, aq as getIssueStickerRuntimeOwner, ar as ISSUE_STICKER_RUNTIME_OWNER, z as isIssueStickerExtensionRuntimeActive, as as createRuntimeHostElement, at as attachHostTypingGuard, au as ISSUE_STICKER_EXTENSION_RUNTIME_READY_EVENT } from "./externalUserPayload-zu5IXBjn.js";
19
19
  import * as React from "react";
20
20
  import { useRef, useState, useEffect, useId, useLayoutEffect, useCallback, forwardRef, createElement, createContext, useContext, Component, Suspense, useInsertionEffect, useMemo, Children, isValidElement, Fragment as Fragment$1, useSyncExternalStore } from "react";
21
21
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
22
- import { c as createLucideIcon$1, b as usePortalContainer, a as cn$1, O as OVERLAY_LAYER, s as stopEscapePropagation, d as OVERLAY_LAYER_INDEX, e as useControllableState, P as Primitive, f as useId$1, g as composeEventHandlers, h as Presence, i as createContextScope, j as useComposedRefs$1, k as useLayoutEffect2, l as useCallbackRef, m as useDismissableLayerSurface, n as Portal$1, o as createSlot, D as DismissableLayer, p as PortalContainerProvider } from "./createLucideIcon-C0Ldhp96.js";
22
+ import { c as createLucideIcon$1, b as usePortalContainer, a as cn$1, O as OVERLAY_LAYER, s as stopEscapePropagation, d as OVERLAY_LAYER_INDEX, P as Presence, e as Primitive, f as composeEventHandlers, g as useDismissableLayerSurface, h as useComposedRefs$1, i as Portal$1, j as createContextScope, k as createSlot, D as DismissableLayer, l as useControllableState, m as useId$1, n as useLayoutEffect2, o as useCallbackRef, p as PortalContainerProvider } from "./createLucideIcon-BzRMP02h.js";
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-CEc_RGfI.js";
25
+ import { T as TooltipProvider, a as Tooltip, b as TooltipTrigger, c as TooltipContent } from "./tooltip-B6UPO-U8.js";
26
26
  function readReleaseMarker() {
27
27
  try {
28
28
  const g = globalThis.__ISSUE_STICKER_RELEASE__;
@@ -211,6 +211,15 @@ function buildAdminIssueUrl(issueId, options) {
211
211
  if (!adminBaseUrl) return null;
212
212
  return new URL(`/issues/${encodeURIComponent(normalizedIssueId)}`, adminBaseUrl).toString();
213
213
  }
214
+ function buildAdminProjectTitlePatternUrl(projectId, options) {
215
+ const normalizedProjectId = projectId.trim();
216
+ if (!normalizedProjectId) return null;
217
+ const adminBaseUrl = resolveAdminBaseUrl(options);
218
+ if (!adminBaseUrl) return null;
219
+ const url = new URL(`/projects/${encodeURIComponent(normalizedProjectId)}`, adminBaseUrl);
220
+ url.searchParams.set("tab", "title-pattern");
221
+ return url.toString();
222
+ }
214
223
  const FAILED_ACTION_TEXT = {
215
224
  jira: "Jira 이슈를 생성하지 못했습니다.",
216
225
  notion: "Notion 페이지를 생성하지 못했습니다.",
@@ -491,6 +500,16 @@ function AsyncSearchSelect({
491
500
  }
492
501
  );
493
502
  }
503
+ /**
504
+ * @license lucide-react v0.468.0 - ISC
505
+ *
506
+ * This source code is licensed under the ISC license.
507
+ * See the LICENSE file in the root directory of this source tree.
508
+ */
509
+ const ArrowUp = createLucideIcon$1("ArrowUp", [
510
+ ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
511
+ ["path", { d: "M12 19V5", key: "x0mq9r" }]
512
+ ]);
494
513
  /**
495
514
  * @license lucide-react v0.468.0 - ISC
496
515
  *
@@ -684,6 +703,22 @@ const MapPin = createLucideIcon$1("MapPin", [
684
703
  ],
685
704
  ["circle", { cx: "12", cy: "10", r: "3", key: "ilqhr7" }]
686
705
  ]);
706
+ /**
707
+ * @license lucide-react v0.468.0 - ISC
708
+ *
709
+ * This source code is licensed under the ISC license.
710
+ * See the LICENSE file in the root directory of this source tree.
711
+ */
712
+ const PenLine = createLucideIcon$1("PenLine", [
713
+ ["path", { d: "M12 20h9", key: "t2du7b" }],
714
+ [
715
+ "path",
716
+ {
717
+ d: "M16.376 3.622a1 1 0 0 1 3.002 3.002L7.368 18.635a2 2 0 0 1-.855.506l-2.872.838a.5.5 0 0 1-.62-.62l.838-2.872a2 2 0 0 1 .506-.854z",
718
+ key: "1ykcvy"
719
+ }
720
+ ]
721
+ ]);
687
722
  /**
688
723
  * @license lucide-react v0.468.0 - ISC
689
724
  *
@@ -696,6 +731,25 @@ const RefreshCw = createLucideIcon$1("RefreshCw", [
696
731
  ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
697
732
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
698
733
  ]);
734
+ /**
735
+ * @license lucide-react v0.468.0 - ISC
736
+ *
737
+ * This source code is licensed under the ISC license.
738
+ * See the LICENSE file in the root directory of this source tree.
739
+ */
740
+ const Sparkles = createLucideIcon$1("Sparkles", [
741
+ [
742
+ "path",
743
+ {
744
+ d: "M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z",
745
+ key: "4pj2yx"
746
+ }
747
+ ],
748
+ ["path", { d: "M20 3v4", key: "1olli1" }],
749
+ ["path", { d: "M22 5h-4", key: "1gvqau" }],
750
+ ["path", { d: "M4 17v2", key: "vumght" }],
751
+ ["path", { d: "M5 18H3", key: "zchphs" }]
752
+ ]);
699
753
  /**
700
754
  * @license lucide-react v0.468.0 - ISC
701
755
  *
@@ -735,6 +789,28 @@ const TriangleAlert = createLucideIcon$1("TriangleAlert", [
735
789
  ["path", { d: "M12 9v4", key: "juzpu7" }],
736
790
  ["path", { d: "M12 17h.01", key: "p32p05" }]
737
791
  ]);
792
+ /**
793
+ * @license lucide-react v0.468.0 - ISC
794
+ *
795
+ * This source code is licensed under the ISC license.
796
+ * See the LICENSE file in the root directory of this source tree.
797
+ */
798
+ const WandSparkles = createLucideIcon$1("WandSparkles", [
799
+ [
800
+ "path",
801
+ {
802
+ d: "m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72",
803
+ key: "ul74o6"
804
+ }
805
+ ],
806
+ ["path", { d: "m14 7 3 3", key: "1r5n42" }],
807
+ ["path", { d: "M5 6v4", key: "ilb8ba" }],
808
+ ["path", { d: "M19 14v4", key: "blhpug" }],
809
+ ["path", { d: "M10 2v2", key: "7u0qdc" }],
810
+ ["path", { d: "M7 8H3", key: "zfb6yr" }],
811
+ ["path", { d: "M21 16h-4", key: "1cnmox" }],
812
+ ["path", { d: "M11 3H9", key: "1obp7u" }]
813
+ ]);
738
814
  const EMPTY_SELECT_VALUE$1 = "__ISSUE_STICKER_EMPTY__";
739
815
  const JIRA_REQUIRED_FIELD_IDS = /* @__PURE__ */ new Set(["priority"]);
740
816
  function JiraReadonlyField({ field }) {
@@ -1816,9 +1892,9 @@ var FocusManager = (_b = class extends Subscribable {
1816
1892
  }
1817
1893
  }
1818
1894
  onFocus() {
1819
- const isFocused = this.isFocused();
1895
+ const isFocused2 = this.isFocused();
1820
1896
  this.listeners.forEach((listener) => {
1821
- listener(isFocused);
1897
+ listener(isFocused2);
1822
1898
  });
1823
1899
  }
1824
1900
  isFocused() {
@@ -4537,9 +4613,10 @@ function useMutation(options, queryClient2) {
4537
4613
  return { ...result, mutate, mutateAsync: result.mutate };
4538
4614
  }
4539
4615
  const BODY_SCROLLBAR_WIDTH_CSS_VAR = "--issue-sticker-scrollbar-width";
4540
- const useIsomorphicLayoutEffect$1 = typeof window === "undefined" ? useEffect : useLayoutEffect;
4541
- function useDisableBodyScroll() {
4542
- useIsomorphicLayoutEffect$1(() => {
4616
+ const useIsomorphicLayoutEffect$2 = typeof window === "undefined" ? useEffect : useLayoutEffect;
4617
+ function useDisableBodyScroll(enabled = true) {
4618
+ useIsomorphicLayoutEffect$2(() => {
4619
+ if (!enabled) return;
4543
4620
  const body = document.body;
4544
4621
  const root2 = document.documentElement;
4545
4622
  const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
@@ -4560,7 +4637,7 @@ function useDisableBodyScroll() {
4560
4637
  root2.style.removeProperty(BODY_SCROLLBAR_WIDTH_CSS_VAR);
4561
4638
  }
4562
4639
  };
4563
- }, []);
4640
+ }, [enabled]);
4564
4641
  }
4565
4642
  function useGuardedCallback(callback) {
4566
4643
  const guardRef = useRef(false);
@@ -5904,355 +5981,22 @@ function DefaultErrorFallback({ resetErrorBoundary }) {
5904
5981
  /* @__PURE__ */ jsx(Button, { variant: "outline", className: "mt-3", onClick: resetErrorBoundary, children: "다시 시도" })
5905
5982
  ] });
5906
5983
  }
5907
- function QueryBoundary({ children, onError, loadingFallback }) {
5908
- const ErrorFallback = onError ?? DefaultErrorFallback;
5909
- return /* @__PURE__ */ jsx(QueryErrorResetBoundary, { children: ({ reset }) => /* @__PURE__ */ jsx(m, { FallbackComponent: ErrorFallback, onReset: reset, children: /* @__PURE__ */ jsx(Suspense, { fallback: loadingFallback ?? /* @__PURE__ */ jsx(Skeleton, {}), children }) }) });
5910
- }
5911
- async function uploadSignedMedia(file, mediaType, issueId) {
5912
- return uploadSignedMediaWithApi(
5913
- {
5914
- post: (endpoint, body) => apiClient.post(endpoint, body),
5915
- directUpload
5916
- },
5917
- file,
5918
- mediaType,
5919
- { issueId }
5920
- );
5921
- }
5922
- function issuesEndpoint() {
5923
- return "/api/sdk/issues";
5924
- }
5925
- function guestOwnerQuery() {
5926
- var _a;
5927
- const mode = getSdkMode();
5928
- if (mode !== "public") return "";
5929
- return buildGuestOwnerQuery(mode, (_a = SDKManager.getInstance().config.user) == null ? void 0 : _a.id);
5930
- }
5931
- let issuesCache = null;
5932
- const CACHE_DURATION_MS = 30 * 1e3;
5933
- const STICKER_PAGE_SIZE = 500;
5934
- const STICKER_FETCH_LIMIT = 2e3;
5935
- function getFilterKey(filters) {
5936
- var _a;
5937
- const normalizeArray = (value) => {
5938
- if (value === "all" || !value) return "all";
5939
- if (Array.isArray(value)) {
5940
- return value.length === 0 ? "all" : [...value].sort().join(",");
5941
- }
5942
- return String(value);
5943
- };
5944
- const normalizeRecord = (record) => {
5945
- if (!record) return "";
5946
- const entries = Object.entries(record).map(([k, v]) => [k, [...v].sort()]).sort(([a], [b]) => a.localeCompare(b));
5947
- return JSON.stringify(entries);
5948
- };
5949
- return JSON.stringify({
5950
- sdkMode: getSdkMode() || "public",
5951
- url: normalizeArray(filters.url),
5952
- projectId: filters.projectId || "all",
5953
- externalUserId: filters.externalUserId || "",
5954
- search: ((_a = filters.search) == null ? void 0 : _a.trim()) || "",
5955
- dateFrom: filters.dateFrom || "",
5956
- dateTo: filters.dateTo || "",
5957
- page: filters.page ?? 0,
5958
- pageSize: filters.pageSize ?? 0,
5959
- custom: normalizeRecord(filters.customFieldValues),
5960
- jira: normalizeRecord(filters.jiraFieldValues),
5961
- notion: normalizeRecord(filters.notionFieldValues),
5962
- sortOrder: filters.sortOrder || ""
5984
+ let reloadToastId = null;
5985
+ function showReloadToast() {
5986
+ if (reloadToastId && getSnapshot().some((t) => t.id === reloadToastId)) return;
5987
+ reloadToastId = toast.error("이슈 정보를 불러오지 못했습니다. 페이지를 새로고침해주세요.", {
5988
+ // 사용자가 새로고침하거나 닫을 때까지 남긴다.
5989
+ duration: 0,
5990
+ action: { label: "새로고침", onClick: () => window.location.reload() }
5963
5991
  });
5964
5992
  }
5965
- function invalidateIssuesCache() {
5966
- issuesCache = null;
5967
- }
5968
- function recordToFilterArray(record, keyFieldName) {
5969
- if (!record) return null;
5970
- const entries = Object.entries(record).filter(([, values]) => values.length > 0);
5971
- if (entries.length === 0) return null;
5972
- return entries.map(
5973
- ([key, values]) => ({ [keyFieldName]: key, values })
5974
- );
5975
- }
5976
- function buildFilterQueryParams(filters, options = {}) {
5977
- var _a;
5978
- const params = new URLSearchParams();
5979
- if (filters.projectId) {
5980
- params.set("project_id", filters.projectId);
5981
- }
5982
- if (filters.url && filters.url !== "all") {
5983
- if (Array.isArray(filters.url) && filters.url.length > 0) {
5984
- params.set("url", filters.url.join(","));
5985
- } else if (typeof filters.url === "string") {
5986
- params.set("url", filters.url);
5987
- }
5988
- }
5989
- if (options.includeListFilters) {
5990
- const search2 = (_a = filters.search) == null ? void 0 : _a.trim();
5991
- if (search2) {
5992
- params.set("search", search2);
5993
- }
5994
- if (filters.dateFrom) {
5995
- params.set("date_from", filters.dateFrom);
5996
- }
5997
- if (filters.dateTo) {
5998
- params.set("date_to", filters.dateTo);
5999
- }
6000
- const customArr = recordToFilterArray(filters.customFieldValues, "fieldDefinitionId");
6001
- if (customArr) {
6002
- params.set("custom_field_filters", JSON.stringify(customArr));
6003
- }
6004
- const jiraArr = recordToFilterArray(filters.jiraFieldValues, "fieldName");
6005
- if (jiraArr) {
6006
- params.set("jira_field_filters", JSON.stringify(jiraArr));
6007
- }
6008
- const notionArr = recordToFilterArray(filters.notionFieldValues, "fieldName");
6009
- if (notionArr) {
6010
- params.set("notion_field_filters", JSON.stringify(notionArr));
6011
- }
6012
- }
6013
- if (filters.externalUserId) {
6014
- params.set("external_user_id", filters.externalUserId);
6015
- }
6016
- if (typeof filters.page === "number" && filters.page > 0) {
6017
- params.set("page", String(filters.page));
6018
- }
6019
- if (typeof filters.pageSize === "number" && filters.pageSize > 0) {
6020
- params.set("page_size", String(filters.pageSize));
6021
- }
6022
- if (filters.sortOrder) {
6023
- params.set("sort_order", filters.sortOrder);
6024
- }
6025
- const queryString = params.toString();
6026
- return queryString ? `?${queryString}` : "";
6027
- }
6028
- const issueService = {
6029
- async createIssue(issueData) {
6030
- const sanitizedData = sanitizeString(issueData);
6031
- const screenshotUploadIds = (sanitizedData.screenshot || []).map((url) => getRegisteredUploadId(url, "screenshot")).filter((id2) => typeof id2 === "string" && id2.length > 0);
6032
- const videoUploadId = sanitizedData.video ? getRegisteredUploadId(sanitizedData.video, "video") : void 0;
6033
- if (screenshotUploadIds.length > 0) {
6034
- sanitizedData.screenshot_upload_ids = screenshotUploadIds;
6035
- }
6036
- if (videoUploadId) {
6037
- sanitizedData.video_upload_id = videoUploadId;
6038
- }
6039
- const issue = await apiClient.post(issuesEndpoint(), sanitizedData);
6040
- invalidateIssuesCache();
6041
- return issue;
6042
- },
6043
- async getIssues(filters = {}, options = {}) {
6044
- if (!filters.projectId) {
6045
- throw new Error("프로젝트 ID가 필요합니다. 로그인 상태를 확인해주세요.");
6046
- }
6047
- const filterKey = getFilterKey(filters);
6048
- const now2 = Date.now();
6049
- if (!options.forceRefresh && issuesCache && issuesCache.filterKey === filterKey && now2 - issuesCache.timestamp < CACHE_DURATION_MS) {
6050
- return issuesCache.data;
6051
- }
6052
- const queryParams = buildFilterQueryParams(filters, { includeListFilters: true });
6053
- const { items: issues = [] } = await apiClient.get(
6054
- `${issuesEndpoint()}${queryParams}`
6055
- );
6056
- issuesCache = {
6057
- data: issues,
6058
- timestamp: now2,
6059
- filterKey
6060
- };
6061
- return issues;
6062
- },
6063
- async getIssueStickers(filters = {}, options = {}) {
6064
- var _a, _b2;
6065
- if (!filters.projectId) {
6066
- throw new Error("프로젝트 ID가 필요합니다. 로그인 상태를 확인해주세요.");
6067
- }
6068
- const filterKey = `${getFilterKey(filters)}:stickers`;
6069
- const now2 = Date.now();
6070
- if (!options.forceRefresh && issuesCache && issuesCache.filterKey === filterKey && now2 - issuesCache.timestamp < CACHE_DURATION_MS) {
6071
- return issuesCache.data;
6072
- }
6073
- const issues = [];
6074
- let page = 1;
6075
- let hasMore = true;
6076
- while (hasMore && issues.length <= STICKER_FETCH_LIMIT) {
6077
- const response = await apiClient.getResponse(
6078
- `${issuesEndpoint()}/stickers${buildFilterQueryParams({
6079
- ...filters,
6080
- page,
6081
- pageSize: STICKER_PAGE_SIZE
6082
- })}`
6083
- );
6084
- const pageItems = ((_a = response.data) == null ? void 0 : _a.items) ?? [];
6085
- issues.push(...pageItems);
6086
- hasMore = Boolean((_b2 = response.data) == null ? void 0 : _b2.hasMore) && pageItems.length > 0;
6087
- page += 1;
6088
- }
6089
- issuesCache = {
6090
- data: issues,
6091
- timestamp: now2,
6092
- filterKey
6093
- };
6094
- return issues;
6095
- },
6096
- invalidateCache() {
6097
- invalidateIssuesCache();
6098
- },
6099
- // 계약 정본: 백엔드 GET /api/sdk/issues/:id 는 back#101부터 읽기-시점-스크럽된
6100
- // llm_prompt 를 상세 응답에 포함한다(목록 응답에는 없음) — 스코프를 이 반환 타입에만 한정한다.
6101
- async getIssue(id2) {
6102
- return apiClient.get(
6103
- `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`
6104
- );
6105
- },
6106
- async updateIssue(id2, updates) {
6107
- const sanitizedUpdates = sanitizeString(updates);
6108
- const issue = await apiClient.put(
6109
- `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`,
6110
- sanitizedUpdates
6111
- );
6112
- invalidateIssuesCache();
6113
- return issue;
6114
- },
6115
- async deleteIssue(id2, options) {
6116
- const endpoint = `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`;
6117
- if (options == null ? void 0 : options.deleteExternal) {
6118
- await apiClient.delete(endpoint, {
6119
- body: { deleteExternal: true }
6120
- });
6121
- } else {
6122
- await apiClient.delete(endpoint);
6123
- }
6124
- invalidateIssuesCache();
6125
- }
6126
- };
6127
- async function loadIssuesFromServer(url, projectId, externalUserId, options = {}) {
6128
- if (!projectId) return [];
6129
- try {
6130
- return await issueService.getIssueStickers(
6131
- {
6132
- url,
6133
- projectId,
6134
- ...externalUserId ? { externalUserId } : {}
6135
- },
6136
- options
6137
- ) || [];
6138
- } catch (error) {
6139
- devLogger.error("useIssues", "Failed to load issues:", error);
6140
- return [];
6141
- }
6142
- }
6143
- const contentProjectIdQueryKey = ["contentProjectId"];
6144
- const contentIssuesQueryRoot = ["contentIssues"];
6145
- function contentIssuesQueryKey({
6146
- currentUrl,
6147
- projectId,
6148
- isMember,
6149
- externalUserId
6150
- }) {
6151
- return [...contentIssuesQueryRoot, currentUrl, projectId, isMember, externalUserId];
6152
- }
6153
- function fetchContentIssues({
6154
- currentUrl,
6155
- projectId,
6156
- isMember,
6157
- externalUserId,
6158
- forceRefresh
6159
- }) {
6160
- return loadIssuesFromServer(currentUrl, projectId, isMember ? void 0 : externalUserId, {
6161
- forceRefresh
6162
- });
6163
- }
6164
- function useIssues(currentUrl) {
6165
- var _a;
6166
- const { isMember } = useAuthContext();
6167
- const config = SDKManager.getInstance().config;
6168
- const sessionIssuesRef = useRef([]);
6169
- const projectIdQuery = useSuspenseQuery({
6170
- queryKey: contentProjectIdQueryKey,
6171
- queryFn: async () => {
6172
- const accountInfo = await getAccountInfo();
6173
- return (accountInfo == null ? void 0 : accountInfo.projectId) ?? null;
6174
- }
6175
- });
6176
- const projectId = projectIdQuery.data;
6177
- const { data: serverIssues = [] } = useSuspenseQuery({
6178
- queryKey: contentIssuesQueryKey({
6179
- currentUrl,
6180
- projectId,
6181
- isMember,
6182
- externalUserId: (_a = config.user) == null ? void 0 : _a.id
6183
- }),
6184
- queryFn: () => {
6185
- var _a2;
6186
- return fetchContentIssues({
6187
- currentUrl,
6188
- projectId,
6189
- isMember,
6190
- externalUserId: (_a2 = config.user) == null ? void 0 : _a2.id
6191
- });
6192
- }
6193
- });
6194
- const issues = !isMember && !config.user ? [...serverIssues, ...sessionIssuesRef.current] : serverIssues;
6195
- const addSessionIssue = useCallback((issue) => {
6196
- sessionIssuesRef.current = [...sessionIssuesRef.current, issue];
6197
- }, []);
6198
- const loadIssues = useCallback(async () => {
6199
- issueService.invalidateCache();
6200
- await Promise.all([
6201
- queryClient.invalidateQueries({ queryKey: contentIssuesQueryRoot }),
6202
- queryClient.invalidateQueries({ queryKey: contentProjectIdQueryKey })
6203
- ]);
6204
- }, []);
6205
- return {
6206
- issues,
6207
- loadIssues,
6208
- addSessionIssue
6209
- };
6210
- }
6211
- function readCurrentUrl() {
6212
- return getCurrentPageUrl();
5993
+ function OverlayErrorFallback() {
5994
+ useEffect(showReloadToast, []);
5995
+ return null;
6213
5996
  }
6214
- function usePrefetchContentIssues() {
6215
- const { isAuthenticated, isLoading, isMember, projectId, accountId, token } = useAuthContext();
6216
- const lastFetchKeyRef = useRef(null);
6217
- useEffect(() => {
6218
- var _a;
6219
- if (isLoading || !isAuthenticated || !projectId) {
6220
- return;
6221
- }
6222
- const currentUrl = readCurrentUrl();
6223
- const externalUserId = (_a = SDKManager.getInstance().config.user) == null ? void 0 : _a.id;
6224
- const fetchKey = [
6225
- currentUrl,
6226
- projectId,
6227
- isMember ? "member" : "public",
6228
- accountId ?? "",
6229
- token ?? "",
6230
- externalUserId ?? ""
6231
- ].join("|");
6232
- if (lastFetchKeyRef.current === fetchKey) {
6233
- return;
6234
- }
6235
- lastFetchKeyRef.current = fetchKey;
6236
- queryClient.setQueryData(contentProjectIdQueryKey, projectId);
6237
- void queryClient.fetchQuery({
6238
- queryKey: contentIssuesQueryKey({
6239
- currentUrl,
6240
- projectId,
6241
- isMember,
6242
- externalUserId
6243
- }),
6244
- queryFn: () => fetchContentIssues({
6245
- currentUrl,
6246
- projectId,
6247
- isMember,
6248
- externalUserId,
6249
- forceRefresh: true
6250
- }),
6251
- staleTime: 0
6252
- }).catch((error) => {
6253
- devLogger.error("usePrefetchContentIssues", "Failed to prefetch issues:", error);
6254
- });
6255
- }, [accountId, isAuthenticated, isLoading, isMember, projectId, token]);
5997
+ function QueryBoundary({ children, onError, loadingFallback }) {
5998
+ const ErrorFallback = onError ?? DefaultErrorFallback;
5999
+ return /* @__PURE__ */ jsx(QueryErrorResetBoundary, { children: ({ reset }) => /* @__PURE__ */ jsx(m, { FallbackComponent: ErrorFallback, onReset: reset, children: /* @__PURE__ */ jsx(Suspense, { fallback: loadingFallback ?? /* @__PURE__ */ jsx(Skeleton, {}), children }) }) });
6256
6000
  }
6257
6001
  const LayoutGroupContext = createContext({});
6258
6002
  function useConstant(init) {
@@ -6263,7 +6007,7 @@ function useConstant(init) {
6263
6007
  return ref.current;
6264
6008
  }
6265
6009
  const isBrowser$1 = typeof window !== "undefined";
6266
- const useIsomorphicLayoutEffect = isBrowser$1 ? useLayoutEffect : useEffect;
6010
+ const useIsomorphicLayoutEffect$1 = isBrowser$1 ? useLayoutEffect : useEffect;
6267
6011
  const PresenceContext = /* @__PURE__ */ createContext(null);
6268
6012
  function addUniqueItem(arr, item) {
6269
6013
  if (arr.indexOf(item) === -1)
@@ -12530,7 +12274,7 @@ const PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, p
12530
12274
  const id2 = useId();
12531
12275
  const isPresentRef = useRef(isPresent);
12532
12276
  const onExitCompleteRef = useRef(onExitComplete);
12533
- useIsomorphicLayoutEffect(() => {
12277
+ useIsomorphicLayoutEffect$1(() => {
12534
12278
  isPresentRef.current = isPresent;
12535
12279
  onExitCompleteRef.current = onExitComplete;
12536
12280
  });
@@ -12608,7 +12352,7 @@ const AnimatePresence = ({ children, custom, initial = true, onExitComplete, pre
12608
12352
  const exitingComponents = useRef(/* @__PURE__ */ new Set());
12609
12353
  const [diffedChildren, setDiffedChildren] = useState(presentChildren);
12610
12354
  const [renderedChildren, setRenderedChildren] = useState(presentChildren);
12611
- useIsomorphicLayoutEffect(() => {
12355
+ useIsomorphicLayoutEffect$1(() => {
12612
12356
  isInitialRender.current = false;
12613
12357
  pendingPresentChildren.current = presentChildren;
12614
12358
  for (let i = 0; i < renderedChildren.length; i++) {
@@ -13061,7 +12805,7 @@ function useVisualElement(Component2, visualState, props, createVisualElement, P
13061
12805
  });
13062
12806
  const optimisedAppearId = props[optimizedAppearDataAttribute];
13063
12807
  const wantsHandoff = useRef(Boolean(optimisedAppearId) && typeof window !== "undefined" && !((_a = window.MotionHandoffIsComplete) == null ? void 0 : _a.call(window, optimisedAppearId)) && ((_b2 = window.MotionHasOptimisedAnimation) == null ? void 0 : _b2.call(window, optimisedAppearId)));
13064
- useIsomorphicLayoutEffect(() => {
12808
+ useIsomorphicLayoutEffect$1(() => {
13065
12809
  hasMountedOnce.current = true;
13066
12810
  if (!visualElement)
13067
12811
  return;
@@ -14391,6 +14135,11 @@ const featureBundle = {
14391
14135
  ...layout
14392
14136
  };
14393
14137
  const motion$1 = /* @__PURE__ */ createMotionProxy(featureBundle, createDomVisualElement);
14138
+ function useReducedMotion() {
14139
+ !hasReducedMotionListener.current && initPrefersReducedMotion();
14140
+ const [shouldReduceMotion] = useState(prefersReducedMotion.current);
14141
+ return shouldReduceMotion;
14142
+ }
14394
14143
  const motion = motion$1;
14395
14144
  const TYPE_STYLES = {
14396
14145
  default: {
@@ -14504,6 +14253,407 @@ function ToastContainer({ position: position2 = "top-right" }) {
14504
14253
  if (typeof document === "undefined") return null;
14505
14254
  return createPortal(content2, portalContainer ?? document.body);
14506
14255
  }
14256
+ const POLL_INTERVAL_MS = 3e3;
14257
+ const MAX_POLLS = 10;
14258
+ function isGeneratingStatus(status) {
14259
+ return status === "pending" || status === "processing";
14260
+ }
14261
+ function useGenerationPolling({
14262
+ status,
14263
+ onRefetch,
14264
+ maxPolls = MAX_POLLS,
14265
+ intervalMs = POLL_INTERVAL_MS,
14266
+ restartKey
14267
+ }) {
14268
+ const refetchRef = useRef(onRefetch);
14269
+ refetchRef.current = onRefetch;
14270
+ useEffect(() => {
14271
+ if (status !== "pending" && status !== "processing") return;
14272
+ let polls = 0;
14273
+ const timer = setInterval(() => {
14274
+ polls += 1;
14275
+ refetchRef.current();
14276
+ if (polls >= maxPolls) clearInterval(timer);
14277
+ }, intervalMs);
14278
+ return () => clearInterval(timer);
14279
+ }, [status, restartKey, maxPolls, intervalMs]);
14280
+ }
14281
+ function useIssueListGenerationPolling({
14282
+ issues,
14283
+ onRefetch
14284
+ }) {
14285
+ const generatingIds = issues.filter((issue) => isGeneratingStatus(issue.generation_status)).map((issue) => issue.id).sort().join(",");
14286
+ useGenerationPolling({
14287
+ status: generatingIds ? "pending" : null,
14288
+ restartKey: generatingIds,
14289
+ onRefetch
14290
+ });
14291
+ }
14292
+ async function uploadSignedMedia(file, mediaType, issueId) {
14293
+ return uploadSignedMediaWithApi(
14294
+ {
14295
+ post: (endpoint, body) => apiClient.post(endpoint, body),
14296
+ directUpload
14297
+ },
14298
+ file,
14299
+ mediaType,
14300
+ { issueId }
14301
+ );
14302
+ }
14303
+ function issuesEndpoint() {
14304
+ return "/api/sdk/issues";
14305
+ }
14306
+ function guestOwnerQuery() {
14307
+ var _a;
14308
+ const mode = getSdkMode();
14309
+ if (mode !== "public") return "";
14310
+ return buildGuestOwnerQuery(mode, (_a = SDKManager.getInstance().config.user) == null ? void 0 : _a.id);
14311
+ }
14312
+ let issuesCache = null;
14313
+ const CACHE_DURATION_MS = 30 * 1e3;
14314
+ const STICKER_PAGE_SIZE = 500;
14315
+ const STICKER_FETCH_LIMIT = 2e3;
14316
+ function getFilterKey(filters) {
14317
+ var _a;
14318
+ const normalizeArray = (value) => {
14319
+ if (value === "all" || !value) return "all";
14320
+ if (Array.isArray(value)) {
14321
+ return value.length === 0 ? "all" : [...value].sort().join(",");
14322
+ }
14323
+ return String(value);
14324
+ };
14325
+ const normalizeRecord = (record) => {
14326
+ if (!record) return "";
14327
+ const entries = Object.entries(record).map(([k, v]) => [k, [...v].sort()]).sort(([a], [b]) => a.localeCompare(b));
14328
+ return JSON.stringify(entries);
14329
+ };
14330
+ return JSON.stringify({
14331
+ sdkMode: getSdkMode() || "public",
14332
+ url: normalizeArray(filters.url),
14333
+ projectId: filters.projectId || "all",
14334
+ externalUserId: filters.externalUserId || "",
14335
+ search: ((_a = filters.search) == null ? void 0 : _a.trim()) || "",
14336
+ dateFrom: filters.dateFrom || "",
14337
+ dateTo: filters.dateTo || "",
14338
+ page: filters.page ?? 0,
14339
+ pageSize: filters.pageSize ?? 0,
14340
+ custom: normalizeRecord(filters.customFieldValues),
14341
+ jira: normalizeRecord(filters.jiraFieldValues),
14342
+ notion: normalizeRecord(filters.notionFieldValues),
14343
+ sortOrder: filters.sortOrder || ""
14344
+ });
14345
+ }
14346
+ function invalidateIssuesCache() {
14347
+ issuesCache = null;
14348
+ }
14349
+ function recordToFilterArray(record, keyFieldName) {
14350
+ if (!record) return null;
14351
+ const entries = Object.entries(record).filter(([, values]) => values.length > 0);
14352
+ if (entries.length === 0) return null;
14353
+ return entries.map(
14354
+ ([key, values]) => ({ [keyFieldName]: key, values })
14355
+ );
14356
+ }
14357
+ function buildFilterQueryParams(filters, options = {}) {
14358
+ var _a;
14359
+ const params = new URLSearchParams();
14360
+ if (filters.projectId) {
14361
+ params.set("project_id", filters.projectId);
14362
+ }
14363
+ if (filters.url && filters.url !== "all") {
14364
+ if (Array.isArray(filters.url) && filters.url.length > 0) {
14365
+ params.set("url", filters.url.join(","));
14366
+ } else if (typeof filters.url === "string") {
14367
+ params.set("url", filters.url);
14368
+ }
14369
+ }
14370
+ if (options.includeListFilters) {
14371
+ const search2 = (_a = filters.search) == null ? void 0 : _a.trim();
14372
+ if (search2) {
14373
+ params.set("search", search2);
14374
+ }
14375
+ if (filters.dateFrom) {
14376
+ params.set("date_from", filters.dateFrom);
14377
+ }
14378
+ if (filters.dateTo) {
14379
+ params.set("date_to", filters.dateTo);
14380
+ }
14381
+ const customArr = recordToFilterArray(filters.customFieldValues, "fieldDefinitionId");
14382
+ if (customArr) {
14383
+ params.set("custom_field_filters", JSON.stringify(customArr));
14384
+ }
14385
+ const jiraArr = recordToFilterArray(filters.jiraFieldValues, "fieldName");
14386
+ if (jiraArr) {
14387
+ params.set("jira_field_filters", JSON.stringify(jiraArr));
14388
+ }
14389
+ const notionArr = recordToFilterArray(filters.notionFieldValues, "fieldName");
14390
+ if (notionArr) {
14391
+ params.set("notion_field_filters", JSON.stringify(notionArr));
14392
+ }
14393
+ }
14394
+ if (filters.externalUserId) {
14395
+ params.set("external_user_id", filters.externalUserId);
14396
+ }
14397
+ if (typeof filters.page === "number" && filters.page > 0) {
14398
+ params.set("page", String(filters.page));
14399
+ }
14400
+ if (typeof filters.pageSize === "number" && filters.pageSize > 0) {
14401
+ params.set("page_size", String(filters.pageSize));
14402
+ }
14403
+ if (filters.sortOrder) {
14404
+ params.set("sort_order", filters.sortOrder);
14405
+ }
14406
+ const queryString = params.toString();
14407
+ return queryString ? `?${queryString}` : "";
14408
+ }
14409
+ const issueService = {
14410
+ async createIssue(issueData) {
14411
+ const sanitizedData = sanitizeString(issueData);
14412
+ const screenshotUploadIds = (sanitizedData.screenshot || []).map((url) => getRegisteredUploadId(url, "screenshot")).filter((id2) => typeof id2 === "string" && id2.length > 0);
14413
+ const videoUploadId = sanitizedData.video ? getRegisteredUploadId(sanitizedData.video, "video") : void 0;
14414
+ if (screenshotUploadIds.length > 0) {
14415
+ sanitizedData.screenshot_upload_ids = screenshotUploadIds;
14416
+ }
14417
+ if (videoUploadId) {
14418
+ sanitizedData.video_upload_id = videoUploadId;
14419
+ }
14420
+ const issue = await apiClient.post(issuesEndpoint(), sanitizedData);
14421
+ invalidateIssuesCache();
14422
+ return issue;
14423
+ },
14424
+ async getIssues(filters = {}, options = {}) {
14425
+ if (!filters.projectId) {
14426
+ throw new Error("프로젝트 ID가 필요합니다. 로그인 상태를 확인해주세요.");
14427
+ }
14428
+ const filterKey = getFilterKey(filters);
14429
+ const now2 = Date.now();
14430
+ if (!options.forceRefresh && issuesCache && issuesCache.filterKey === filterKey && now2 - issuesCache.timestamp < CACHE_DURATION_MS) {
14431
+ return issuesCache.data;
14432
+ }
14433
+ const queryParams = buildFilterQueryParams(filters, { includeListFilters: true });
14434
+ const { items: issues = [] } = await apiClient.get(
14435
+ `${issuesEndpoint()}${queryParams}`
14436
+ );
14437
+ issuesCache = {
14438
+ data: issues,
14439
+ timestamp: now2,
14440
+ filterKey
14441
+ };
14442
+ return issues;
14443
+ },
14444
+ async getIssueStickers(filters = {}, options = {}) {
14445
+ var _a, _b2;
14446
+ if (!filters.projectId) {
14447
+ throw new Error("프로젝트 ID가 필요합니다. 로그인 상태를 확인해주세요.");
14448
+ }
14449
+ const filterKey = `${getFilterKey(filters)}:stickers`;
14450
+ const now2 = Date.now();
14451
+ if (!options.forceRefresh && issuesCache && issuesCache.filterKey === filterKey && now2 - issuesCache.timestamp < CACHE_DURATION_MS) {
14452
+ return issuesCache.data;
14453
+ }
14454
+ const issues = [];
14455
+ let page = 1;
14456
+ let hasMore = true;
14457
+ while (hasMore && issues.length <= STICKER_FETCH_LIMIT) {
14458
+ const response = await apiClient.getResponse(
14459
+ `${issuesEndpoint()}/stickers${buildFilterQueryParams({
14460
+ ...filters,
14461
+ page,
14462
+ pageSize: STICKER_PAGE_SIZE
14463
+ })}`
14464
+ );
14465
+ const pageItems = ((_a = response.data) == null ? void 0 : _a.items) ?? [];
14466
+ issues.push(...pageItems);
14467
+ hasMore = Boolean((_b2 = response.data) == null ? void 0 : _b2.hasMore) && pageItems.length > 0;
14468
+ page += 1;
14469
+ }
14470
+ issuesCache = {
14471
+ data: issues,
14472
+ timestamp: now2,
14473
+ filterKey
14474
+ };
14475
+ return issues;
14476
+ },
14477
+ invalidateCache() {
14478
+ invalidateIssuesCache();
14479
+ },
14480
+ // 계약 정본: 백엔드 GET /api/sdk/issues/:id 는 back#101부터 읽기-시점-스크럽된
14481
+ // llm_prompt 를 상세 응답에 포함한다(목록 응답에는 없음) — 스코프를 이 반환 타입에만 한정한다.
14482
+ async getIssue(id2) {
14483
+ return apiClient.get(
14484
+ `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`
14485
+ );
14486
+ },
14487
+ async updateIssue(id2, updates) {
14488
+ const sanitizedUpdates = sanitizeString(updates);
14489
+ const issue = await apiClient.put(
14490
+ `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`,
14491
+ sanitizedUpdates
14492
+ );
14493
+ invalidateIssuesCache();
14494
+ return issue;
14495
+ },
14496
+ /**
14497
+ * 재생성. 스펙상 세 표면 모두에서 되고 역할과 무관하다 — 게이트는 역할이 아니라
14498
+ * 그 이슈에 접근할 수 있는지다(백엔드가 판정한다).
14499
+ *
14500
+ * 응답으로 갱신된 이슈가 오지만 상태는 다시 pending 이다. 호출부는 응답을
14501
+ * 그대로 쓰지 말고 폴링으로 이어받아야 한다.
14502
+ */
14503
+ async regenerateIssue(id2) {
14504
+ const issue = await apiClient.post(
14505
+ `${issuesEndpoint()}/${encodeURIComponent(id2)}/regenerate${guestOwnerQuery()}`,
14506
+ {}
14507
+ );
14508
+ invalidateIssuesCache();
14509
+ return issue;
14510
+ },
14511
+ async deleteIssue(id2, options) {
14512
+ const endpoint = `${issuesEndpoint()}/${id2}${guestOwnerQuery()}`;
14513
+ if (options == null ? void 0 : options.deleteExternal) {
14514
+ await apiClient.delete(endpoint, {
14515
+ body: { deleteExternal: true }
14516
+ });
14517
+ } else {
14518
+ await apiClient.delete(endpoint);
14519
+ }
14520
+ invalidateIssuesCache();
14521
+ }
14522
+ };
14523
+ async function loadIssuesFromServer(url, projectId, externalUserId, options = {}) {
14524
+ if (!projectId) return [];
14525
+ try {
14526
+ return await issueService.getIssueStickers(
14527
+ {
14528
+ url,
14529
+ projectId,
14530
+ ...externalUserId ? { externalUserId } : {}
14531
+ },
14532
+ options
14533
+ ) || [];
14534
+ } catch (error) {
14535
+ devLogger.error("useIssues", "Failed to load issues:", error);
14536
+ return [];
14537
+ }
14538
+ }
14539
+ const contentProjectIdQueryKey = ["contentProjectId"];
14540
+ const contentIssuesQueryRoot = ["contentIssues"];
14541
+ function contentIssuesQueryKey({
14542
+ currentUrl,
14543
+ projectId,
14544
+ isMember,
14545
+ externalUserId
14546
+ }) {
14547
+ return [...contentIssuesQueryRoot, currentUrl, projectId, isMember, externalUserId];
14548
+ }
14549
+ function fetchContentIssues({
14550
+ currentUrl,
14551
+ projectId,
14552
+ isMember,
14553
+ externalUserId,
14554
+ forceRefresh
14555
+ }) {
14556
+ return loadIssuesFromServer(currentUrl, projectId, isMember ? void 0 : externalUserId, {
14557
+ forceRefresh
14558
+ });
14559
+ }
14560
+ function useIssues(currentUrl) {
14561
+ var _a;
14562
+ const { isMember } = useAuthContext();
14563
+ const config = SDKManager.getInstance().config;
14564
+ const sessionIssuesRef = useRef([]);
14565
+ const projectIdQuery = useSuspenseQuery({
14566
+ queryKey: contentProjectIdQueryKey,
14567
+ queryFn: async () => {
14568
+ const accountInfo = await getAccountInfo();
14569
+ return (accountInfo == null ? void 0 : accountInfo.projectId) ?? null;
14570
+ }
14571
+ });
14572
+ const projectId = projectIdQuery.data;
14573
+ const { data: serverIssues = [] } = useSuspenseQuery({
14574
+ queryKey: contentIssuesQueryKey({
14575
+ currentUrl,
14576
+ projectId,
14577
+ isMember,
14578
+ externalUserId: (_a = config.user) == null ? void 0 : _a.id
14579
+ }),
14580
+ queryFn: () => {
14581
+ var _a2;
14582
+ return fetchContentIssues({
14583
+ currentUrl,
14584
+ projectId,
14585
+ isMember,
14586
+ externalUserId: (_a2 = config.user) == null ? void 0 : _a2.id
14587
+ });
14588
+ }
14589
+ });
14590
+ const issues = !isMember && !config.user ? [...serverIssues, ...sessionIssuesRef.current] : serverIssues;
14591
+ const addSessionIssue = useCallback((issue) => {
14592
+ sessionIssuesRef.current = [...sessionIssuesRef.current, issue];
14593
+ }, []);
14594
+ const loadIssues = useCallback(async () => {
14595
+ issueService.invalidateCache();
14596
+ await Promise.all([
14597
+ queryClient.invalidateQueries({ queryKey: contentIssuesQueryRoot }),
14598
+ queryClient.invalidateQueries({ queryKey: contentProjectIdQueryKey })
14599
+ ]);
14600
+ }, []);
14601
+ useIssueListGenerationPolling({
14602
+ issues: serverIssues,
14603
+ onRefetch: () => void loadIssues()
14604
+ });
14605
+ return {
14606
+ issues,
14607
+ loadIssues,
14608
+ addSessionIssue
14609
+ };
14610
+ }
14611
+ function readCurrentUrl() {
14612
+ return getCurrentPageUrl();
14613
+ }
14614
+ function usePrefetchContentIssues() {
14615
+ const { isAuthenticated, isLoading, isMember, projectId, accountId, token } = useAuthContext();
14616
+ const lastFetchKeyRef = useRef(null);
14617
+ useEffect(() => {
14618
+ var _a;
14619
+ if (isLoading || !isAuthenticated || !projectId) {
14620
+ return;
14621
+ }
14622
+ const currentUrl = readCurrentUrl();
14623
+ const externalUserId = (_a = SDKManager.getInstance().config.user) == null ? void 0 : _a.id;
14624
+ const fetchKey = [
14625
+ currentUrl,
14626
+ projectId,
14627
+ isMember ? "member" : "public",
14628
+ accountId ?? "",
14629
+ token ?? "",
14630
+ externalUserId ?? ""
14631
+ ].join("|");
14632
+ if (lastFetchKeyRef.current === fetchKey) {
14633
+ return;
14634
+ }
14635
+ lastFetchKeyRef.current = fetchKey;
14636
+ queryClient.setQueryData(contentProjectIdQueryKey, projectId);
14637
+ void queryClient.fetchQuery({
14638
+ queryKey: contentIssuesQueryKey({
14639
+ currentUrl,
14640
+ projectId,
14641
+ isMember,
14642
+ externalUserId
14643
+ }),
14644
+ queryFn: () => fetchContentIssues({
14645
+ currentUrl,
14646
+ projectId,
14647
+ isMember,
14648
+ externalUserId,
14649
+ forceRefresh: true
14650
+ }),
14651
+ staleTime: 0
14652
+ }).catch((error) => {
14653
+ devLogger.error("usePrefetchContentIssues", "Failed to prefetch issues:", error);
14654
+ });
14655
+ }, [accountId, isAuthenticated, isLoading, isMember, projectId, token]);
14656
+ }
14507
14657
  function UnrenderedStickerDialog({
14508
14658
  open,
14509
14659
  items,
@@ -14587,6 +14737,74 @@ function UnrenderedStickerDialog({
14587
14737
  }
14588
14738
  );
14589
14739
  }
14740
+ function getDeepActiveElement(root2 = document) {
14741
+ var _a;
14742
+ let active = root2.activeElement;
14743
+ while ((_a = active == null ? void 0 : active.shadowRoot) == null ? void 0 : _a.activeElement) {
14744
+ active = active.shadowRoot.activeElement;
14745
+ }
14746
+ return active;
14747
+ }
14748
+ const FOCUSABLE_SELECTOR = [
14749
+ "a[href]",
14750
+ "button:not([disabled])",
14751
+ "input:not([disabled])",
14752
+ "select:not([disabled])",
14753
+ "textarea:not([disabled])",
14754
+ '[tabindex]:not([tabindex="-1"])'
14755
+ ].join(",");
14756
+ function isVisible(element2, container) {
14757
+ if (getComputedStyle(element2).visibility === "hidden") return false;
14758
+ let node2 = element2;
14759
+ while (node2) {
14760
+ if (getComputedStyle(node2).display === "none") return false;
14761
+ if (node2 === container) break;
14762
+ node2 = node2.parentElement;
14763
+ }
14764
+ return true;
14765
+ }
14766
+ function tabbables(container) {
14767
+ return Array.from(container.querySelectorAll(FOCUSABLE_SELECTOR)).filter(
14768
+ (element2) => element2.tabIndex >= 0 && isVisible(element2, container)
14769
+ );
14770
+ }
14771
+ function useOverlayFocus({
14772
+ enabled,
14773
+ container,
14774
+ initialFocusRef,
14775
+ initialFocus = "first"
14776
+ }) {
14777
+ useEffect(() => {
14778
+ if (!enabled || !container) return;
14779
+ const restoreTo = getDeepActiveElement();
14780
+ const target = (initialFocusRef == null ? void 0 : initialFocusRef.current) ?? (initialFocus === "container" ? container : tabbables(container)[0] ?? container);
14781
+ target.focus({ preventScroll: true });
14782
+ const handleKeyDown = (event) => {
14783
+ if (event.key !== "Tab") return;
14784
+ const items = tabbables(container);
14785
+ const first = items[0];
14786
+ const last = items[items.length - 1];
14787
+ if (!first || !last) {
14788
+ event.preventDefault();
14789
+ return;
14790
+ }
14791
+ const active = getDeepActiveElement();
14792
+ const outside = !active || !container.contains(active);
14793
+ if (!event.shiftKey && (outside || active === last)) {
14794
+ event.preventDefault();
14795
+ first.focus({ preventScroll: true });
14796
+ } else if (event.shiftKey && (outside || active === first)) {
14797
+ event.preventDefault();
14798
+ last.focus({ preventScroll: true });
14799
+ }
14800
+ };
14801
+ container.addEventListener("keydown", handleKeyDown);
14802
+ return () => {
14803
+ container.removeEventListener("keydown", handleKeyDown);
14804
+ if (restoreTo == null ? void 0 : restoreTo.isConnected) restoreTo.focus({ preventScroll: true });
14805
+ };
14806
+ }, [enabled, container, initialFocusRef, initialFocus]);
14807
+ }
14590
14808
  function OverlayShell({
14591
14809
  open,
14592
14810
  children,
@@ -14598,6 +14816,8 @@ function OverlayShell({
14598
14816
  }) {
14599
14817
  const onCloseRef = useRef(onClose);
14600
14818
  onCloseRef.current = onClose;
14819
+ const [shell, setShell] = useState(null);
14820
+ useOverlayFocus({ enabled: open, container: shell, initialFocus: "container" });
14601
14821
  useEffect(() => {
14602
14822
  if (!open) return;
14603
14823
  const handleKeyDown = (e) => {
@@ -14632,12 +14852,14 @@ function OverlayShell({
14632
14852
  children: /* @__PURE__ */ jsx(
14633
14853
  motion.div,
14634
14854
  {
14855
+ ref: setShell,
14856
+ tabIndex: -1,
14635
14857
  initial: { opacity: 0, y: 12, scale: 0.98 },
14636
14858
  animate: { opacity: 1, y: 0, scale: 1 },
14637
14859
  exit: { opacity: 0, y: 8, scale: 0.98 },
14638
14860
  transition: { duration: 0.2, ease: [0.34, 1.2, 0.64, 1] },
14639
14861
  className: cn$1(
14640
- "issue-overlay-shell flex w-full flex-col overflow-hidden",
14862
+ "issue-overlay-shell flex w-full flex-col overflow-hidden focus:outline-none",
14641
14863
  shellClassName
14642
14864
  ),
14643
14865
  onClick: (e) => e.stopPropagation(),
@@ -14649,6 +14871,670 @@ function OverlayShell({
14649
14871
  "overlay-backdrop"
14650
14872
  ) : null });
14651
14873
  }
14874
+ const ISSUE_DRAFT_DISABLED_MESSAGE = "지금은 AI 작성을 사용할 수 없습니다. 제목과 설명을 직접 작성해주세요.";
14875
+ const LABEL = "기대한 동작";
14876
+ const PLACEHOLDER = "예: 할인 쿠폰을 적용하면 결제 금액에서 즉시 차감되어야 합니다";
14877
+ const SWITCH_TO_MANUAL = "직접 작성";
14878
+ const SUBMIT = "보내기";
14879
+ const MAX_INPUT_HEIGHT = 160;
14880
+ const FOCUS_RETRY_BUDGET_MS = 1e3;
14881
+ function isFocused(node2) {
14882
+ const root2 = node2.getRootNode();
14883
+ return root2 instanceof ShadowRoot ? root2.activeElement === node2 : document.activeElement === node2;
14884
+ }
14885
+ function IssueIntentBubble({
14886
+ value,
14887
+ onChange,
14888
+ onSubmit,
14889
+ onSwitchToManual,
14890
+ submitting = false,
14891
+ error = null
14892
+ }) {
14893
+ const inputRef = useRef(null);
14894
+ const canSubmit = !submitting && value.trim().length > 0;
14895
+ useEffect(() => {
14896
+ const node2 = inputRef.current;
14897
+ if (!node2) return;
14898
+ const deadline = Date.now() + FOCUS_RETRY_BUDGET_MS;
14899
+ let frame2 = 0;
14900
+ let abandoned = false;
14901
+ const abandon = () => {
14902
+ abandoned = true;
14903
+ };
14904
+ const attempt = () => {
14905
+ frame2 = 0;
14906
+ if (abandoned || isFocused(node2)) return;
14907
+ node2.focus({ preventScroll: true });
14908
+ if (isFocused(node2) || Date.now() >= deadline) return;
14909
+ frame2 = requestAnimationFrame(attempt);
14910
+ };
14911
+ window.addEventListener("pointerdown", abandon, { capture: true });
14912
+ window.addEventListener("keydown", abandon, { capture: true });
14913
+ attempt();
14914
+ return () => {
14915
+ window.removeEventListener("pointerdown", abandon, { capture: true });
14916
+ window.removeEventListener("keydown", abandon, { capture: true });
14917
+ if (frame2) cancelAnimationFrame(frame2);
14918
+ };
14919
+ }, []);
14920
+ useLayoutEffect(() => {
14921
+ const node2 = inputRef.current;
14922
+ if (!node2) return;
14923
+ node2.style.height = "auto";
14924
+ node2.style.height = `${Math.min(node2.scrollHeight, MAX_INPUT_HEIGHT)}px`;
14925
+ }, [value]);
14926
+ return (
14927
+ /*
14928
+ * 테두리는 포커스일 때만 브랜드 색으로 간다. 이 리포의 입력 컨트롤 관례가 그렇다
14929
+ * (ui/input.tsx, ui/textarea.tsx: 평소 border-line-subtle, 포커스에 line-focus).
14930
+ * `line-focus` 는 `--border-focus` = 브랜드 색상값이다(tokens.css).
14931
+ *
14932
+ * 관례는 `focus-visible:outline-line-focus` 지만 여기서는 border 로 바꾼다.
14933
+ * outline 은 border 상자 바깥에 그려지는데 말풍선 상자가 `overflow-hidden`
14934
+ * (IssueIntentBubbleAnchor)이라 잘린다. focus 가 아니라 focus-within 인 것은
14935
+ * 테두리가 카드에 있고 실제로 포커스를 받는 것은 그 안의 textarea 이기 때문이다.
14936
+ */
14937
+ /* @__PURE__ */ jsxs(
14938
+ "div",
14939
+ {
14940
+ className: `${ISSUE_STICKER_REPORT_FORM_CLASS} w-80 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`,
14941
+ children: [
14942
+ /* @__PURE__ */ jsxs("div", { className: "flex items-end gap-1.5", children: [
14943
+ /* @__PURE__ */ jsx(
14944
+ "textarea",
14945
+ {
14946
+ ref: inputRef,
14947
+ "aria-label": LABEL,
14948
+ rows: 1,
14949
+ className: "max-h-40 flex-1 resize-none overflow-y-auto bg-transparent px-1.5 py-1 text-sm text-text-primary outline-none placeholder:text-text-tertiary disabled:opacity-50",
14950
+ placeholder: PLACEHOLDER,
14951
+ value,
14952
+ disabled: submitting,
14953
+ onChange: (event) => onChange(event.target.value)
14954
+ }
14955
+ ),
14956
+ /* @__PURE__ */ jsx(
14957
+ "button",
14958
+ {
14959
+ type: "button",
14960
+ "aria-label": SUBMIT,
14961
+ className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-brand text-brand-fg disabled:opacity-50",
14962
+ disabled: !canSubmit,
14963
+ onClick: () => canSubmit && onSubmit(),
14964
+ children: /* @__PURE__ */ jsx(ArrowUp, { className: "h-4 w-4" })
14965
+ }
14966
+ )
14967
+ ] }),
14968
+ error ? /* @__PURE__ */ jsx("p", { className: "text-xs text-danger", children: error }) : null,
14969
+ /* @__PURE__ */ jsxs(Button, { type: "button", variant: "secondary", size: "sm", onClick: onSwitchToManual, children: [
14970
+ /* @__PURE__ */ jsx(PenLine, { className: "h-3.5 w-3.5" }),
14971
+ SWITCH_TO_MANUAL
14972
+ ] })
14973
+ ]
14974
+ }
14975
+ )
14976
+ );
14977
+ }
14978
+ var DIALOG_NAME = "Dialog";
14979
+ var [createDialogContext] = createContextScope(DIALOG_NAME);
14980
+ var [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);
14981
+ var Dialog$1 = (props) => {
14982
+ const {
14983
+ __scopeDialog,
14984
+ children,
14985
+ open: openProp,
14986
+ defaultOpen,
14987
+ onOpenChange,
14988
+ modal = true
14989
+ } = props;
14990
+ const triggerRef = React.useRef(null);
14991
+ const contentRef = React.useRef(null);
14992
+ const [open, setOpen] = useControllableState({
14993
+ prop: openProp,
14994
+ defaultProp: defaultOpen ?? false,
14995
+ onChange: onOpenChange,
14996
+ caller: DIALOG_NAME
14997
+ });
14998
+ return /* @__PURE__ */ jsx(
14999
+ DialogProvider,
15000
+ {
15001
+ scope: __scopeDialog,
15002
+ triggerRef,
15003
+ contentRef,
15004
+ contentId: useId$1(),
15005
+ titleId: useId$1(),
15006
+ descriptionId: useId$1(),
15007
+ open,
15008
+ onOpenChange: setOpen,
15009
+ onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
15010
+ modal,
15011
+ children
15012
+ }
15013
+ );
15014
+ };
15015
+ Dialog$1.displayName = DIALOG_NAME;
15016
+ var TRIGGER_NAME$3 = "DialogTrigger";
15017
+ var DialogTrigger = React.forwardRef(
15018
+ (props, forwardedRef) => {
15019
+ const { __scopeDialog, ...triggerProps } = props;
15020
+ const context = useDialogContext(TRIGGER_NAME$3, __scopeDialog);
15021
+ const composedTriggerRef = useComposedRefs$1(forwardedRef, context.triggerRef);
15022
+ return /* @__PURE__ */ jsx(
15023
+ Primitive.button,
15024
+ {
15025
+ type: "button",
15026
+ "aria-haspopup": "dialog",
15027
+ "aria-expanded": context.open,
15028
+ "aria-controls": context.open ? context.contentId : void 0,
15029
+ "data-state": getState$2(context.open),
15030
+ ...triggerProps,
15031
+ ref: composedTriggerRef,
15032
+ onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
15033
+ }
15034
+ );
15035
+ }
15036
+ );
15037
+ DialogTrigger.displayName = TRIGGER_NAME$3;
15038
+ var PORTAL_NAME = "DialogPortal";
15039
+ var [PortalProvider, usePortalContext] = createDialogContext(PORTAL_NAME, {
15040
+ forceMount: void 0
15041
+ });
15042
+ var DialogPortal$1 = (props) => {
15043
+ const { __scopeDialog, forceMount, children, container } = props;
15044
+ const context = useDialogContext(PORTAL_NAME, __scopeDialog);
15045
+ return /* @__PURE__ */ jsx(PortalProvider, { scope: __scopeDialog, forceMount, children: React.Children.map(children, (child) => /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(Portal$1, { asChild: true, container, children: child }) })) });
15046
+ };
15047
+ DialogPortal$1.displayName = PORTAL_NAME;
15048
+ var OVERLAY_NAME = "DialogOverlay";
15049
+ var DialogOverlay$1 = React.forwardRef(
15050
+ (props, forwardedRef) => {
15051
+ const portalContext = usePortalContext(OVERLAY_NAME, props.__scopeDialog);
15052
+ const { forceMount = portalContext.forceMount, ...overlayProps } = props;
15053
+ const context = useDialogContext(OVERLAY_NAME, props.__scopeDialog);
15054
+ return context.modal ? /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(DialogOverlayImpl, { ...overlayProps, ref: forwardedRef }) }) : null;
15055
+ }
15056
+ );
15057
+ DialogOverlay$1.displayName = OVERLAY_NAME;
15058
+ var Slot = createSlot("DialogOverlay.RemoveScroll");
15059
+ var DialogOverlayImpl = React.forwardRef(
15060
+ (props, forwardedRef) => {
15061
+ const { __scopeDialog, ...overlayProps } = props;
15062
+ const context = useDialogContext(OVERLAY_NAME, __scopeDialog);
15063
+ const registerDismissableSurface = useDismissableLayerSurface();
15064
+ const composedRefs = useComposedRefs$1(forwardedRef, registerDismissableSurface);
15065
+ return (
15066
+ // Make sure `Content` is scrollable even when it doesn't live inside `RemoveScroll`
15067
+ // ie. when `Overlay` and `Content` are siblings
15068
+ /* @__PURE__ */ jsx(ReactRemoveScroll, { as: Slot, allowPinchZoom: true, shards: [context.contentRef], children: /* @__PURE__ */ jsx(
15069
+ Primitive.div,
15070
+ {
15071
+ "data-state": getState$2(context.open),
15072
+ ...overlayProps,
15073
+ ref: composedRefs,
15074
+ style: { pointerEvents: "auto", ...overlayProps.style }
15075
+ }
15076
+ ) })
15077
+ );
15078
+ }
15079
+ );
15080
+ var CONTENT_NAME$3 = "DialogContent";
15081
+ var DialogContent$1 = React.forwardRef(
15082
+ (props, forwardedRef) => {
15083
+ const portalContext = usePortalContext(CONTENT_NAME$3, props.__scopeDialog);
15084
+ const { forceMount = portalContext.forceMount, ...contentProps } = props;
15085
+ const context = useDialogContext(CONTENT_NAME$3, props.__scopeDialog);
15086
+ return /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: context.modal ? /* @__PURE__ */ jsx(DialogContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(DialogContentNonModal, { ...contentProps, ref: forwardedRef }) });
15087
+ }
15088
+ );
15089
+ DialogContent$1.displayName = CONTENT_NAME$3;
15090
+ var DialogContentModal = React.forwardRef(
15091
+ (props, forwardedRef) => {
15092
+ const context = useDialogContext(CONTENT_NAME$3, props.__scopeDialog);
15093
+ const contentRef = React.useRef(null);
15094
+ const composedRefs = useComposedRefs$1(forwardedRef, context.contentRef, contentRef);
15095
+ React.useEffect(() => {
15096
+ const content2 = contentRef.current;
15097
+ if (content2) return hideOthers(content2);
15098
+ }, []);
15099
+ return /* @__PURE__ */ jsx(
15100
+ DialogContentImpl,
15101
+ {
15102
+ ...props,
15103
+ ref: composedRefs,
15104
+ trapFocus: context.open,
15105
+ disableOutsidePointerEvents: context.open,
15106
+ onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {
15107
+ var _a;
15108
+ event.preventDefault();
15109
+ (_a = context.triggerRef.current) == null ? void 0 : _a.focus();
15110
+ }),
15111
+ onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event) => {
15112
+ const originalEvent = event.detail.originalEvent;
15113
+ const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;
15114
+ const isRightClick = originalEvent.button === 2 || ctrlLeftClick;
15115
+ if (isRightClick) event.preventDefault();
15116
+ }),
15117
+ onFocusOutside: composeEventHandlers(
15118
+ props.onFocusOutside,
15119
+ (event) => event.preventDefault()
15120
+ )
15121
+ }
15122
+ );
15123
+ }
15124
+ );
15125
+ var DialogContentNonModal = React.forwardRef(
15126
+ (props, forwardedRef) => {
15127
+ const context = useDialogContext(CONTENT_NAME$3, props.__scopeDialog);
15128
+ const hasInteractedOutsideRef = React.useRef(false);
15129
+ const hasPointerDownOutsideRef = React.useRef(false);
15130
+ return /* @__PURE__ */ jsx(
15131
+ DialogContentImpl,
15132
+ {
15133
+ ...props,
15134
+ ref: forwardedRef,
15135
+ trapFocus: false,
15136
+ disableOutsidePointerEvents: false,
15137
+ onCloseAutoFocus: (event) => {
15138
+ var _a, _b2;
15139
+ (_a = props.onCloseAutoFocus) == null ? void 0 : _a.call(props, event);
15140
+ if (!event.defaultPrevented) {
15141
+ if (!hasInteractedOutsideRef.current) (_b2 = context.triggerRef.current) == null ? void 0 : _b2.focus();
15142
+ event.preventDefault();
15143
+ }
15144
+ hasInteractedOutsideRef.current = false;
15145
+ hasPointerDownOutsideRef.current = false;
15146
+ },
15147
+ onInteractOutside: (event) => {
15148
+ var _a, _b2;
15149
+ (_a = props.onInteractOutside) == null ? void 0 : _a.call(props, event);
15150
+ if (!event.defaultPrevented) {
15151
+ hasInteractedOutsideRef.current = true;
15152
+ if (event.detail.originalEvent.type === "pointerdown") {
15153
+ hasPointerDownOutsideRef.current = true;
15154
+ }
15155
+ }
15156
+ const target = event.target;
15157
+ const targetIsTrigger = (_b2 = context.triggerRef.current) == null ? void 0 : _b2.contains(target);
15158
+ if (targetIsTrigger) event.preventDefault();
15159
+ if (event.detail.originalEvent.type === "focusin" && hasPointerDownOutsideRef.current) {
15160
+ event.preventDefault();
15161
+ }
15162
+ }
15163
+ }
15164
+ );
15165
+ }
15166
+ );
15167
+ var DialogContentImpl = React.forwardRef(
15168
+ (props, forwardedRef) => {
15169
+ const { __scopeDialog, trapFocus, onOpenAutoFocus, onCloseAutoFocus, ...contentProps } = props;
15170
+ const context = useDialogContext(CONTENT_NAME$3, __scopeDialog);
15171
+ useFocusGuards();
15172
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
15173
+ FocusScope,
15174
+ {
15175
+ asChild: true,
15176
+ loop: true,
15177
+ trapped: trapFocus,
15178
+ onMountAutoFocus: onOpenAutoFocus,
15179
+ onUnmountAutoFocus: onCloseAutoFocus,
15180
+ children: /* @__PURE__ */ jsx(
15181
+ DismissableLayer,
15182
+ {
15183
+ role: "dialog",
15184
+ id: context.contentId,
15185
+ "aria-describedby": context.descriptionId,
15186
+ "aria-labelledby": context.titleId,
15187
+ "data-state": getState$2(context.open),
15188
+ ...contentProps,
15189
+ ref: forwardedRef,
15190
+ deferPointerDownOutside: true,
15191
+ onDismiss: () => context.onOpenChange(false)
15192
+ }
15193
+ )
15194
+ }
15195
+ ) });
15196
+ }
15197
+ );
15198
+ var TITLE_NAME = "DialogTitle";
15199
+ var DialogTitle$1 = React.forwardRef(
15200
+ (props, forwardedRef) => {
15201
+ const { __scopeDialog, ...titleProps } = props;
15202
+ const context = useDialogContext(TITLE_NAME, __scopeDialog);
15203
+ return /* @__PURE__ */ jsx(Primitive.h2, { id: context.titleId, ...titleProps, ref: forwardedRef });
15204
+ }
15205
+ );
15206
+ DialogTitle$1.displayName = TITLE_NAME;
15207
+ var DESCRIPTION_NAME = "DialogDescription";
15208
+ var DialogDescription$1 = React.forwardRef(
15209
+ (props, forwardedRef) => {
15210
+ const { __scopeDialog, ...descriptionProps } = props;
15211
+ const context = useDialogContext(DESCRIPTION_NAME, __scopeDialog);
15212
+ return /* @__PURE__ */ jsx(Primitive.p, { id: context.descriptionId, ...descriptionProps, ref: forwardedRef });
15213
+ }
15214
+ );
15215
+ DialogDescription$1.displayName = DESCRIPTION_NAME;
15216
+ var CLOSE_NAME = "DialogClose";
15217
+ var DialogClose$1 = React.forwardRef(
15218
+ (props, forwardedRef) => {
15219
+ const { __scopeDialog, ...closeProps } = props;
15220
+ const context = useDialogContext(CLOSE_NAME, __scopeDialog);
15221
+ return /* @__PURE__ */ jsx(
15222
+ Primitive.button,
15223
+ {
15224
+ type: "button",
15225
+ ...closeProps,
15226
+ ref: forwardedRef,
15227
+ onClick: composeEventHandlers(props.onClick, () => context.onOpenChange(false))
15228
+ }
15229
+ );
15230
+ }
15231
+ );
15232
+ DialogClose$1.displayName = CLOSE_NAME;
15233
+ function getState$2(open) {
15234
+ return open ? "open" : "closed";
15235
+ }
15236
+ const Dialog = Dialog$1;
15237
+ const DialogClose = DialogClose$1;
15238
+ const DialogPortal = ({ children }) => {
15239
+ const portalContainer = usePortalContainer();
15240
+ return /* @__PURE__ */ jsx(DialogPortal$1, { container: portalContainer, children });
15241
+ };
15242
+ const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
15243
+ DialogOverlay$1,
15244
+ {
15245
+ ref,
15246
+ className: cn$1(
15247
+ `fixed inset-0 ${OVERLAY_LAYER.dialogOverlay} bg-black/24`,
15248
+ "data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out",
15249
+ "motion-reduce:animate-none",
15250
+ className
15251
+ ),
15252
+ ...props
15253
+ }
15254
+ ));
15255
+ DialogOverlay.displayName = DialogOverlay$1.displayName;
15256
+ const DialogContent = React.forwardRef(
15257
+ ({
15258
+ className,
15259
+ children,
15260
+ hideCloseButton = false,
15261
+ initialFocusRef,
15262
+ onEscapeKeyDown,
15263
+ onOpenAutoFocus,
15264
+ onCloseAutoFocus,
15265
+ style,
15266
+ ...props
15267
+ }, ref) => {
15268
+ const [content2, setContent] = React.useState(null);
15269
+ const composedRef = React.useCallback(
15270
+ (node2) => {
15271
+ setContent(node2);
15272
+ if (typeof ref === "function") ref(node2);
15273
+ else if (ref) ref.current = node2;
15274
+ },
15275
+ [ref]
15276
+ );
15277
+ useOverlayFocus({ enabled: true, container: content2, initialFocusRef });
15278
+ return /* @__PURE__ */ jsxs(DialogPortal, { children: [
15279
+ /* @__PURE__ */ jsx(DialogOverlay, {}),
15280
+ /* @__PURE__ */ jsxs(
15281
+ DialogContent$1,
15282
+ {
15283
+ ref: composedRef,
15284
+ onEscapeKeyDown: stopEscapePropagation(onEscapeKeyDown),
15285
+ onOpenAutoFocus: (event) => {
15286
+ onOpenAutoFocus == null ? void 0 : onOpenAutoFocus(event);
15287
+ event.preventDefault();
15288
+ },
15289
+ onCloseAutoFocus: (event) => {
15290
+ onCloseAutoFocus == null ? void 0 : onCloseAutoFocus(event);
15291
+ event.preventDefault();
15292
+ },
15293
+ style: {
15294
+ left: `calc(50% - (var(${BODY_SCROLLBAR_WIDTH_CSS_VAR}, 0px) / 2))`,
15295
+ ...style
15296
+ },
15297
+ className: cn$1(
15298
+ `panel-shell fixed left-[50%] top-[50%] ${OVERLAY_LAYER.dialogContent} grid w-full max-w-[36rem] translate-x-[-50%] translate-y-[-50%] gap-5 rounded-2xl p-7 shadow-lg`,
15299
+ "focus:outline-none",
15300
+ "data-[state=open]:animate-dialog-in data-[state=closed]:animate-dialog-out",
15301
+ "motion-reduce:animate-none",
15302
+ className
15303
+ ),
15304
+ ...props,
15305
+ children: [
15306
+ children,
15307
+ !hideCloseButton ? /* @__PURE__ */ jsxs(
15308
+ DialogClose$1,
15309
+ {
15310
+ className: cn$1(
15311
+ "absolute right-4 top-4 rounded-md border border-transparent bg-surface-2 p-1.5 text-text-tertiary",
15312
+ "transition-colors duration-fast",
15313
+ "hover:border-line-subtle hover:bg-surface-3 hover:text-text-primary",
15314
+ "focus-visible:outline-none focus-visible:shadow-focus"
15315
+ ),
15316
+ children: [
15317
+ /* @__PURE__ */ jsx(X$1, { className: "h-4 w-4" }),
15318
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "닫기" })
15319
+ ]
15320
+ }
15321
+ ) : null
15322
+ ]
15323
+ }
15324
+ )
15325
+ ] });
15326
+ }
15327
+ );
15328
+ DialogContent.displayName = DialogContent$1.displayName;
15329
+ const DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn$1("flex flex-col space-y-2 text-left", className), ...props });
15330
+ const DialogTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
15331
+ DialogTitle$1,
15332
+ {
15333
+ ref,
15334
+ className: cn$1("text-lg font-semibold text-text-primary", className),
15335
+ ...props
15336
+ }
15337
+ ));
15338
+ DialogTitle.displayName = DialogTitle$1.displayName;
15339
+ const DialogDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
15340
+ DialogDescription$1,
15341
+ {
15342
+ ref,
15343
+ className: cn$1("text-sm leading-relaxed text-text-secondary", className),
15344
+ ...props
15345
+ }
15346
+ ));
15347
+ DialogDescription.displayName = DialogDescription$1.displayName;
15348
+ const VIEWPORT_MARGIN = 12;
15349
+ const PREVIEW_STICKER_SIZE = 32;
15350
+ const STICKER_GAP = 8;
15351
+ const BUBBLE_OFFSET = PREVIEW_STICKER_SIZE / 2 + STICKER_GAP;
15352
+ const DISCARD_MESSAGE = "지금 닫으면 작성 중인 내용이 사라집니다. 닫으시겠습니까?";
15353
+ const DISCARD_CANCEL = "취소";
15354
+ const DISCARD_CONFIRM = "닫기";
15355
+ function clampBubblePosition(x, y, width, height, viewportWidth, viewportHeight, margin = VIEWPORT_MARGIN) {
15356
+ const maxLeft = Math.max(margin, viewportWidth - width - margin);
15357
+ const maxTop = Math.max(margin, viewportHeight - height - margin);
15358
+ return {
15359
+ left: Math.min(Math.max(x, margin), maxLeft),
15360
+ top: Math.min(Math.max(y, margin), maxTop)
15361
+ };
15362
+ }
15363
+ function resolveBubbleLayout(stickerLeft, stickerTop, width, height, viewportWidth, viewportHeight, margin = VIEWPORT_MARGIN) {
15364
+ const rightLeft = stickerLeft + BUBBLE_OFFSET;
15365
+ const leftLeft = stickerLeft - BUBBLE_OFFSET - width;
15366
+ const side = rightLeft + width <= viewportWidth - margin ? "right" : leftLeft >= margin ? "left" : "right";
15367
+ const { left, top } = clampBubblePosition(
15368
+ side === "right" ? rightLeft : leftLeft,
15369
+ stickerTop - PREVIEW_STICKER_SIZE / 2,
15370
+ width,
15371
+ height,
15372
+ viewportWidth,
15373
+ viewportHeight,
15374
+ margin
15375
+ );
15376
+ return { left, top, side };
15377
+ }
15378
+ function IssueIntentBubbleAnchor({
15379
+ x,
15380
+ y,
15381
+ children,
15382
+ onClose,
15383
+ dirty = false,
15384
+ open = true,
15385
+ onExitComplete
15386
+ }) {
15387
+ const contentRef = useRef(null);
15388
+ const onCloseRef = useRef(onClose);
15389
+ onCloseRef.current = onClose;
15390
+ const dirtyRef = useRef(dirty);
15391
+ dirtyRef.current = dirty;
15392
+ const [confirmingDiscard, setConfirmingDiscard] = useState(false);
15393
+ const discardCancelRef = useRef(null);
15394
+ const confirmingDiscardRef = useRef(confirmingDiscard);
15395
+ confirmingDiscardRef.current = confirmingDiscard;
15396
+ const [layout2, setLayout] = useState(null);
15397
+ const reduceMotion = useReducedMotion();
15398
+ useLayoutEffect(() => {
15399
+ let frame2 = 0;
15400
+ const apply = () => {
15401
+ frame2 = 0;
15402
+ const node2 = contentRef.current;
15403
+ if (!node2) return;
15404
+ const { width, height } = node2.getBoundingClientRect();
15405
+ const stickerLeft = x - window.scrollX;
15406
+ const stickerTop = y - window.scrollY;
15407
+ const placement = resolveBubbleLayout(
15408
+ stickerLeft,
15409
+ stickerTop,
15410
+ width,
15411
+ height,
15412
+ window.innerWidth,
15413
+ window.innerHeight
15414
+ );
15415
+ setLayout({
15416
+ stickerLeft,
15417
+ stickerTop,
15418
+ bubbleTop: placement.top,
15419
+ // 왼쪽에 열 때는 right 를 고정해야 너비가 스티커 쪽으로 자란다.
15420
+ bubbleLeft: placement.side === "right" ? placement.left : null,
15421
+ bubbleRight: placement.side === "right" ? null : window.innerWidth - (placement.left + width)
15422
+ });
15423
+ };
15424
+ const schedule = () => {
15425
+ if (frame2) return;
15426
+ frame2 = window.requestAnimationFrame(apply);
15427
+ };
15428
+ apply();
15429
+ window.addEventListener("scroll", schedule, { capture: true, passive: true });
15430
+ window.addEventListener("resize", schedule, { passive: true });
15431
+ let contentObserver = null;
15432
+ if (contentRef.current && typeof ResizeObserver !== "undefined") {
15433
+ contentObserver = new ResizeObserver(schedule);
15434
+ contentObserver.observe(contentRef.current);
15435
+ }
15436
+ return () => {
15437
+ window.removeEventListener("scroll", schedule, { capture: true });
15438
+ window.removeEventListener("resize", schedule);
15439
+ contentObserver == null ? void 0 : contentObserver.disconnect();
15440
+ if (frame2) window.cancelAnimationFrame(frame2);
15441
+ };
15442
+ }, [x, y]);
15443
+ useEffect(() => {
15444
+ const handleKeyDown = (event) => {
15445
+ if (event.key !== "Escape") return;
15446
+ event.preventDefault();
15447
+ if (confirmingDiscardRef.current) return;
15448
+ if (dirtyRef.current) {
15449
+ setConfirmingDiscard(true);
15450
+ return;
15451
+ }
15452
+ onCloseRef.current();
15453
+ };
15454
+ window.addEventListener("keydown", handleKeyDown, { capture: true });
15455
+ return () => window.removeEventListener("keydown", handleKeyDown, { capture: true });
15456
+ }, []);
15457
+ useDisableBodyScroll(confirmingDiscard);
15458
+ const visibility = layout2 ? "visible" : "hidden";
15459
+ const stickerTransition = reduceMotion ? { duration: 0 } : { duration: 0.18, ease: [0.34, 1.2, 0.64, 1] };
15460
+ const bubbleTransition = reduceMotion ? { duration: 0 } : { duration: 0.22, ease: [0.34, 1.2, 0.64, 1] };
15461
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
15462
+ /* @__PURE__ */ jsx(AnimatePresence, { onExitComplete, children: open ? [
15463
+ /* @__PURE__ */ jsx(
15464
+ motion.div,
15465
+ {
15466
+ "data-issue-sticker-preview": "",
15467
+ "aria-hidden": "true",
15468
+ className: `pointer-events-none fixed ${OVERLAY_LAYER.shell} flex h-8 w-8 items-center justify-center rounded-full border border-white/80 bg-brand text-sm font-black leading-none text-white`,
15469
+ style: {
15470
+ left: (layout2 == null ? void 0 : layout2.stickerLeft) ?? x,
15471
+ top: (layout2 == null ? void 0 : layout2.stickerTop) ?? y,
15472
+ visibility
15473
+ },
15474
+ initial: { opacity: 0, scale: 0.5, x: "-50%", y: "-50%" },
15475
+ animate: { opacity: 1, scale: 1, x: "-50%", y: "-50%" },
15476
+ exit: { opacity: 0, scale: 0.5, x: "-50%", y: "-50%" },
15477
+ transition: stickerTransition,
15478
+ children: "!"
15479
+ },
15480
+ "preview-sticker"
15481
+ ),
15482
+ /* @__PURE__ */ jsx(
15483
+ motion.div,
15484
+ {
15485
+ "data-issue-sticker-bubble": "",
15486
+ className: `pointer-events-auto fixed overflow-hidden ${OVERLAY_LAYER.shell}`,
15487
+ style: {
15488
+ left: (layout2 == null ? void 0 : layout2.bubbleLeft) ?? void 0,
15489
+ right: (layout2 == null ? void 0 : layout2.bubbleRight) ?? void 0,
15490
+ top: (layout2 == null ? void 0 : layout2.bubbleTop) ?? y
15491
+ },
15492
+ initial: { width: 0, height: 0, opacity: 0 },
15493
+ animate: layout2 ? { width: "auto", height: "auto", opacity: 1 } : { width: 0, height: 0, opacity: 0 },
15494
+ exit: { width: 0, height: 0, opacity: 0 },
15495
+ transition: bubbleTransition,
15496
+ children: /* @__PURE__ */ jsx("div", { ref: contentRef, className: "w-max", children })
15497
+ },
15498
+ "bubble"
15499
+ )
15500
+ ] : null }),
15501
+ /* @__PURE__ */ jsx(
15502
+ Dialog,
15503
+ {
15504
+ open: confirmingDiscard,
15505
+ onOpenChange: (nextOpen) => {
15506
+ if (!nextOpen) setConfirmingDiscard(false);
15507
+ },
15508
+ children: /* @__PURE__ */ jsxs(
15509
+ DialogContent,
15510
+ {
15511
+ hideCloseButton: true,
15512
+ initialFocusRef: discardCancelRef,
15513
+ "aria-describedby": void 0,
15514
+ className: "w-[calc(100vw-32px)] max-w-[360px] gap-4 rounded-md p-5",
15515
+ children: [
15516
+ /* @__PURE__ */ jsx(DialogTitle, { className: "text-sm font-normal leading-relaxed", children: DISCARD_MESSAGE }),
15517
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
15518
+ /* @__PURE__ */ jsx(
15519
+ Button,
15520
+ {
15521
+ ref: discardCancelRef,
15522
+ type: "button",
15523
+ variant: "secondary",
15524
+ size: "sm",
15525
+ onClick: () => setConfirmingDiscard(false),
15526
+ children: DISCARD_CANCEL
15527
+ }
15528
+ ),
15529
+ /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", onClick: () => onClose(), children: DISCARD_CONFIRM })
15530
+ ] })
15531
+ ]
15532
+ }
15533
+ )
15534
+ }
15535
+ )
15536
+ ] });
15537
+ }
14652
15538
  function useProject() {
14653
15539
  const auth = useAuthContext();
14654
15540
  return {
@@ -14831,6 +15717,12 @@ function useJiraConnectNudge(projectId, enabled) {
14831
15717
  function useIssueFormState({ initialDescription } = {}) {
14832
15718
  const [title, setTitle] = useState("");
14833
15719
  const [description, setDescription] = useState(initialDescription || "");
15720
+ const [mode, setMode] = useState("ai");
15721
+ const [renderedMode, setRenderedMode] = useState("ai");
15722
+ const [intent, setIntent] = useState("");
15723
+ const modeRef = useRef(mode);
15724
+ modeRef.current = mode;
15725
+ const finishModeTransition = useCallback(() => setRenderedMode(modeRef.current), []);
14834
15726
  useEffect(() => {
14835
15727
  if (initialDescription !== void 0) {
14836
15728
  setDescription(initialDescription);
@@ -14840,7 +15732,13 @@ function useIssueFormState({ initialDescription } = {}) {
14840
15732
  title,
14841
15733
  description,
14842
15734
  setTitle,
14843
- setDescription
15735
+ setDescription,
15736
+ mode,
15737
+ setMode,
15738
+ renderedMode,
15739
+ finishModeTransition,
15740
+ intent,
15741
+ setIntent
14844
15742
  };
14845
15743
  }
14846
15744
  function useDebouncedMutation({
@@ -14979,6 +15877,12 @@ const SCREENSHOT_EXCLUDE_SELECTORS = [
14979
15877
  '[data-issue-sticker-capture-ignore="true"]',
14980
15878
  "#issue-sticker-host"
14981
15879
  ];
15880
+ const CAPTURE_START_DELAY_MS = 300;
15881
+ function waitForFormOpen() {
15882
+ return new Promise((resolve) => {
15883
+ setTimeout(resolve, CAPTURE_START_DELAY_MS);
15884
+ });
15885
+ }
14982
15886
  function useClickPosition(isCreatingIssueRef, recordedVideoFile) {
14983
15887
  const [clickPosition, setClickPosition] = useState(null);
14984
15888
  const clickPositionRef = useRef(null);
@@ -15052,6 +15956,7 @@ function useClickPosition(isCreatingIssueRef, recordedVideoFile) {
15052
15956
  }, [recordedVideoFile]);
15053
15957
  useEffect(() => {
15054
15958
  const captureScreenshotsInBackground = async (position2) => {
15959
+ await waitForFormOpen();
15055
15960
  const [fullScreenshotDataUrl, elementScreenshotDataUrl] = await pauseNetworkLogCollectionWhile(
15056
15961
  () => Promise.all([
15057
15962
  captureScreenshot({ excludeSelectors: SCREENSHOT_EXCLUDE_SELECTORS }),
@@ -15213,6 +16118,14 @@ async function uploadSessionReplay(snapshot) {
15213
16118
  return null;
15214
16119
  }
15215
16120
  }
16121
+ function assertSubmittable(data) {
16122
+ var _a, _b2, _c2;
16123
+ const hasIntent = Boolean((_a = data.intent) == null ? void 0 : _a.trim());
16124
+ const hasManual = Boolean((_b2 = data.title) == null ? void 0 : _b2.trim()) && Boolean((_c2 = data.description) == null ? void 0 : _c2.trim());
16125
+ if (!hasIntent && !hasManual) {
16126
+ throw new Error("제목과 설명을 입력하거나 기대한 동작을 적어주세요.");
16127
+ }
16128
+ }
15216
16129
  function useIssueSubmission({
15217
16130
  position: position2,
15218
16131
  onSubmit,
@@ -15232,13 +16145,8 @@ function useIssueSubmission({
15232
16145
  const { upload: uploadVideo2 } = useVideoUpload();
15233
16146
  const createIssueMutation = useDebouncedMutation({
15234
16147
  mutationFn: async (data) => {
15235
- var _a, _b2;
15236
- if (!data.title.trim()) {
15237
- throw new Error("제목을 입력해주세요.");
15238
- }
15239
- if (!data.description.trim()) {
15240
- throw new Error("설명을 입력해주세요.");
15241
- }
16148
+ var _a, _b2, _c2, _d2, _e2, _f2;
16149
+ assertSubmittable(data);
15242
16150
  let screenshotUrls;
15243
16151
  let videoUrl;
15244
16152
  if (data.videoFile) {
@@ -15272,8 +16180,9 @@ function useIssueSubmission({
15272
16180
  const currentUrl = getCurrentPageUrl();
15273
16181
  const issueData = {
15274
16182
  url: currentUrl,
15275
- title: data.title.trim(),
15276
- description: data.description.trim(),
16183
+ title: ((_b2 = data.title) == null ? void 0 : _b2.trim()) || void 0,
16184
+ description: ((_c2 = data.description) == null ? void 0 : _c2.trim()) || void 0,
16185
+ intent: ((_d2 = data.intent) == null ? void 0 : _d2.trim()) || void 0,
15277
16186
  position: {
15278
16187
  x: data.position.x,
15279
16188
  y: data.position.y,
@@ -15294,10 +16203,10 @@ function useIssueSubmission({
15294
16203
  // 비어 있는 값은 보내지 않는다 — 저장해봐야 값 없음과 같고 요청만 커진다.
15295
16204
  custom_field_values: Object.entries(customFieldValues ?? {}).filter(([, value]) => value !== null && value !== void 0 && value !== "").map(([field_definition_id, value]) => ({ field_definition_id, value }))
15296
16205
  };
15297
- if (((_b2 = issueData.custom_field_values) == null ? void 0 : _b2.length) === 0) {
16206
+ if (((_e2 = issueData.custom_field_values) == null ? void 0 : _e2.length) === 0) {
15298
16207
  delete issueData.custom_field_values;
15299
16208
  }
15300
- if ((sessionReplay == null ? void 0 : sessionReplay.preferOn) && sessionReplay.canAttach) {
16209
+ if (sessionReplay == null ? void 0 : sessionReplay.canAttach) {
15301
16210
  try {
15302
16211
  const snapshot = await sessionReplay.takeSnapshot();
15303
16212
  if (snapshot) {
@@ -15336,6 +16245,9 @@ function useIssueSubmission({
15336
16245
  toast.error(getIntegrationFailureMessage(service));
15337
16246
  }
15338
16247
  failedServicesRef.current = createdIssue.failed_services ?? [];
16248
+ if (((_f2 = data.intent) == null ? void 0 : _f2.trim()) && createdIssue.generation_status === "skipped") {
16249
+ toast.warning(ISSUE_DRAFT_DISABLED_MESSAGE);
16250
+ }
15339
16251
  return createdIssue;
15340
16252
  },
15341
16253
  onSuccess: (createdIssue) => {
@@ -15352,11 +16264,12 @@ function useIssueSubmission({
15352
16264
  }
15353
16265
  });
15354
16266
  const doSubmit = useCallback(
15355
- async (title, description) => {
16267
+ async ({ title, description, intent }) => {
15356
16268
  failedServicesRef.current = [];
15357
16269
  await createIssueMutation.mutateAsync({
15358
16270
  title,
15359
16271
  description,
16272
+ intent,
15360
16273
  position: position2,
15361
16274
  jiraFields,
15362
16275
  notionFields,
@@ -15390,12 +16303,6 @@ function useSessionReplayController() {
15390
16303
  controller.destroy();
15391
16304
  };
15392
16305
  }, [controller]);
15393
- const setPreferOn = useCallback(
15394
- (next) => {
15395
- controller.setEnabled(next);
15396
- },
15397
- [controller]
15398
- );
15399
16306
  const takeSnapshot = useCallback(async () => {
15400
16307
  return controller.takeSnapshot();
15401
16308
  }, [controller]);
@@ -15404,8 +16311,6 @@ function useSessionReplayController() {
15404
16311
  return {
15405
16312
  available: snapshot.available,
15406
16313
  canAttach: snapshot.canAttach,
15407
- preferOn: snapshot.enabled,
15408
- setPreferOn,
15409
16314
  takeSnapshot,
15410
16315
  markReportStart,
15411
16316
  clearReportStart
@@ -15414,9 +16319,6 @@ function useSessionReplayController() {
15414
16319
  const DISABLED_CONTROLLER = {
15415
16320
  available: false,
15416
16321
  canAttach: false,
15417
- preferOn: false,
15418
- setPreferOn: () => {
15419
- },
15420
16322
  takeSnapshot: async () => null,
15421
16323
  markReportStart: () => {
15422
16324
  },
@@ -15737,12 +16639,7 @@ function IssueFormCustomFields({
15737
16639
  queryKey: ["customFieldDefinitions", projectId],
15738
16640
  queryFn: () => fetchCustomFieldDefinitions(projectId)
15739
16641
  });
15740
- const defaultsAppliedRef = useRef(false);
15741
- useEffect(() => {
15742
- if (defaultsAppliedRef.current || fields.length === 0) return;
15743
- defaultsAppliedRef.current = true;
15744
- onDefaultsResolved(getCustomFieldDefaultValues(fields));
15745
- }, [fields, onDefaultsResolved]);
16642
+ useCustomFieldDefaults(fields, onDefaultsResolved);
15746
16643
  return /* @__PURE__ */ jsx(
15747
16644
  CustomFieldsSection,
15748
16645
  {
@@ -15754,12 +16651,57 @@ function IssueFormCustomFields({
15754
16651
  }
15755
16652
  );
15756
16653
  }
16654
+ function useCustomFieldDefaults(fields, onDefaultsResolved) {
16655
+ const defaultsAppliedRef = useRef(false);
16656
+ useEffect(() => {
16657
+ if (defaultsAppliedRef.current || fields.length === 0) return;
16658
+ defaultsAppliedRef.current = true;
16659
+ onDefaultsResolved(getCustomFieldDefaultValues(fields));
16660
+ }, [fields, onDefaultsResolved]);
16661
+ }
16662
+ function IssueFormCustomFieldDefaults({
16663
+ projectId,
16664
+ onDefaultsResolved
16665
+ }) {
16666
+ const { data: fields } = useQuery({
16667
+ queryKey: ["customFieldDefinitions", projectId],
16668
+ queryFn: () => fetchCustomFieldDefinitions(projectId)
16669
+ });
16670
+ useCustomFieldDefaults(fields ?? [], onDefaultsResolved);
16671
+ return null;
16672
+ }
16673
+ const useIsomorphicLayoutEffect = typeof window === "undefined" ? React.useEffect : React.useLayoutEffect;
15757
16674
  const Textarea = React.forwardRef(
15758
- ({ className, ...props }, ref) => {
16675
+ ({ className, autoGrow, ...props }, ref) => {
16676
+ const innerRef = React.useRef(null);
16677
+ React.useImperativeHandle(ref, () => innerRef.current);
16678
+ const grow = React.useCallback(() => {
16679
+ const element2 = innerRef.current;
16680
+ if (!element2) return;
16681
+ const style = getComputedStyle(element2);
16682
+ const borders = (parseFloat(style.borderTopWidth) || 0) + (parseFloat(style.borderBottomWidth) || 0);
16683
+ element2.style.height = "0px";
16684
+ element2.style.height = `${element2.scrollHeight + borders}px`;
16685
+ }, []);
16686
+ useIsomorphicLayoutEffect(() => {
16687
+ if (autoGrow) grow();
16688
+ });
16689
+ useIsomorphicLayoutEffect(() => {
16690
+ const element2 = innerRef.current;
16691
+ if (!autoGrow || !element2 || typeof ResizeObserver === "undefined") return;
16692
+ let lastWidth = element2.clientWidth;
16693
+ const observer2 = new ResizeObserver(() => {
16694
+ if (element2.clientWidth === lastWidth) return;
16695
+ lastWidth = element2.clientWidth;
16696
+ grow();
16697
+ });
16698
+ observer2.observe(element2);
16699
+ return () => observer2.disconnect();
16700
+ }, [autoGrow, grow]);
15759
16701
  return /* @__PURE__ */ jsx(
15760
16702
  "textarea",
15761
16703
  {
15762
- ref,
16704
+ ref: innerRef,
15763
16705
  className: cn$1(
15764
16706
  "flex min-h-[108px] w-full rounded-md border border-line-subtle bg-surface-1 px-4 py-3 text-sm text-text-primary",
15765
16707
  "transition-[border-color,outline-color,box-shadow,background-color,transform] duration-fast ease-out",
@@ -15768,6 +16710,7 @@ const Textarea = React.forwardRef(
15768
16710
  "focus-visible:border-transparent focus-visible:outline-line-focus focus-visible:bg-surface-1",
15769
16711
  "disabled:cursor-not-allowed disabled:opacity-50",
15770
16712
  "resize-y",
16713
+ autoGrow && "min-h-0 resize-none overflow-hidden",
15771
16714
  className
15772
16715
  ),
15773
16716
  ...props
@@ -15803,12 +16746,57 @@ function IssueFormDescriptionField({
15803
16746
  function IssueFormError({ error }) {
15804
16747
  return /* @__PURE__ */ jsx("div", { className: "rounded-[18px] border border-danger/20 bg-danger-subtle px-4 py-3 text-sm text-danger", children: error });
15805
16748
  }
15806
- function IssueFormHeader({ title, onClose }) {
16749
+ const SWITCH_TO_AI = "AI 작성으로 돌아가기";
16750
+ function IssueFormHeader({ title, onClose, onSwitchToAi }) {
15807
16751
  return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
15808
16752
  /* @__PURE__ */ jsx("h2", { className: "m-0 text-lg font-semibold text-text-primary", children: title }),
15809
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: onClose, "aria-label": "닫기", children: /* @__PURE__ */ jsx(X$1, { className: "h-4 w-4" }) })
16753
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
16754
+ onSwitchToAi ? /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 240, skipDelayDuration: 120, disableHoverableContent: true, children: /* @__PURE__ */ jsxs(Tooltip, { children: [
16755
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
16756
+ Button,
16757
+ {
16758
+ type: "button",
16759
+ variant: "ghost",
16760
+ size: "icon",
16761
+ onClick: onSwitchToAi,
16762
+ "aria-label": SWITCH_TO_AI,
16763
+ children: /* @__PURE__ */ jsx(Sparkles, { className: "h-4 w-4" })
16764
+ }
16765
+ ) }),
16766
+ /* @__PURE__ */ jsx(TooltipContent, { side: "top", sideOffset: 10, children: SWITCH_TO_AI })
16767
+ ] }) }) : null,
16768
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon", onClick: onClose, "aria-label": "닫기", children: /* @__PURE__ */ jsx(X$1, { className: "h-4 w-4" }) })
16769
+ ] })
15810
16770
  ] });
15811
16771
  }
16772
+ function useDraftCapability() {
16773
+ const { data } = useQuery({
16774
+ queryKey: ["issueDraftCapability"],
16775
+ queryFn: () => apiClient.get("/api/sdk/issues/capabilities/draft")
16776
+ });
16777
+ const capability = data == null ? void 0 : data.draft.canGenerateDraft;
16778
+ return {
16779
+ /** 응답을 실제로 받았을 때만 true. 조회 전·실패·null 응답에서는 false다. */
16780
+ resolved: Boolean(capability),
16781
+ enabled: (capability == null ? void 0 : capability.enabled) ?? true,
16782
+ titlePatternMissing: (data == null ? void 0 : data.draft.titlePatternMissing) ?? false
16783
+ };
16784
+ }
16785
+ function IssueFormDraftCapabilityGate({
16786
+ onResolved
16787
+ }) {
16788
+ const { resolved, enabled, titlePatternMissing } = useDraftCapability();
16789
+ useEffect(() => {
16790
+ if (!resolved) {
16791
+ return;
16792
+ }
16793
+ onResolved({
16794
+ disabledReason: enabled ? null : ISSUE_DRAFT_DISABLED_MESSAGE,
16795
+ titlePatternMissing
16796
+ });
16797
+ }, [resolved, enabled, titlePatternMissing, onResolved]);
16798
+ return null;
16799
+ }
15812
16800
  function useJiraFieldSearchConfig(projectId) {
15813
16801
  return useMemo(
15814
16802
  () => createJiraFieldSearchConfig(
@@ -15845,13 +16833,7 @@ function IssueFormJiraFields({
15845
16833
  const { getAuthInfo } = useAuthInfo();
15846
16834
  const { fields: fieldDefinitions, exposedFields } = useJiraIntegrationFields(integrationId);
15847
16835
  const getSearchConfig = useJiraFieldSearchConfig(getAuthInfo().projectId);
15848
- const appliedForRef = useRef(null);
15849
- useEffect(() => {
15850
- if (!onDefaultsResolved) return;
15851
- if (appliedForRef.current === integrationId) return;
15852
- appliedForRef.current = integrationId;
15853
- onDefaultsResolved(getJiraFieldDefaultValues(exposedFields, fieldDefinitions));
15854
- }, [integrationId, exposedFields, fieldDefinitions, onDefaultsResolved]);
16836
+ useJiraFieldDefaults(integrationId, exposedFields, fieldDefinitions, onDefaultsResolved);
15855
16837
  return /* @__PURE__ */ jsx(
15856
16838
  JiraFormFieldsSection,
15857
16839
  {
@@ -15864,6 +16846,36 @@ function IssueFormJiraFields({
15864
16846
  }
15865
16847
  );
15866
16848
  }
16849
+ function useJiraFieldDefaults(integrationId, exposedFields, fieldDefinitions, onDefaultsResolved, ready = true) {
16850
+ const appliedForRef = useRef(null);
16851
+ useEffect(() => {
16852
+ if (!onDefaultsResolved || !ready) return;
16853
+ if (appliedForRef.current === integrationId) return;
16854
+ appliedForRef.current = integrationId;
16855
+ onDefaultsResolved(getJiraFieldDefaultValues(exposedFields, fieldDefinitions));
16856
+ }, [integrationId, exposedFields, fieldDefinitions, onDefaultsResolved, ready]);
16857
+ }
16858
+ function IssueFormJiraFieldDefaults({
16859
+ integrationId,
16860
+ onDefaultsResolved
16861
+ }) {
16862
+ const { data } = useQuery({
16863
+ queryKey: ["jiraIntegrationFields", integrationId],
16864
+ queryFn: () => jiraService.loadIntegrationFields(integrationId)
16865
+ });
16866
+ useEffect(() => {
16867
+ if (!data) return;
16868
+ jiraService.updateExposedFields(integrationId, data.exposedFields);
16869
+ }, [data, integrationId]);
16870
+ useJiraFieldDefaults(
16871
+ integrationId,
16872
+ data == null ? void 0 : data.exposedFields,
16873
+ data == null ? void 0 : data.fields,
16874
+ onDefaultsResolved,
16875
+ Boolean(data)
16876
+ );
16877
+ return null;
16878
+ }
15867
16879
  function JiraConnectNudge({ onConnect, isConnecting }) {
15868
16880
  return /* @__PURE__ */ jsx("div", { className: "rounded-[18px] border border-warning/20 bg-warning-subtle px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
15869
16881
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
@@ -15940,83 +16952,14 @@ function IssueFormTitleField({
15940
16952
  )
15941
16953
  ] });
15942
16954
  }
15943
- function switchTrackClassName(checked) {
15944
- return cn$1(
15945
- "relative inline-flex h-[22px] w-[38px] shrink-0 items-center rounded-full",
15946
- "transition-colors duration-fast ease-out",
15947
- checked ? "bg-brand" : "bg-line"
15948
- );
15949
- }
15950
- function switchThumbClassName(checked) {
15951
- return cn$1(
15952
- "pointer-events-none block h-[18px] w-[18px] rounded-full bg-surface-1 shadow-sm",
15953
- "transition-transform duration-fast ease-out",
15954
- checked ? "translate-x-[18px]" : "translate-x-[2px]"
15955
- );
15956
- }
15957
- const Switch = React.forwardRef(
15958
- ({ checked, onCheckedChange, disabled = false, id: id2, className, ...aria2 }, ref) => /* @__PURE__ */ jsx(
15959
- "button",
15960
- {
15961
- ref,
15962
- id: id2,
15963
- type: "button",
15964
- role: "switch",
15965
- "aria-checked": checked,
15966
- disabled,
15967
- onClick: () => onCheckedChange(!checked),
15968
- className: cn$1(
15969
- switchTrackClassName(checked),
15970
- "outline-none",
15971
- "focus-visible:shadow-focus",
15972
- "disabled:cursor-not-allowed disabled:opacity-50",
15973
- className
15974
- ),
15975
- ...aria2,
15976
- children: /* @__PURE__ */ jsx("span", { className: switchThumbClassName(checked) })
15977
- }
15978
- )
15979
- );
15980
- Switch.displayName = "Switch";
15981
- function SessionReplayAttachToggle({
16955
+ function SessionReplayLimitNotice({
15982
16956
  available,
15983
- canAttach,
15984
- preferOn,
15985
- onPreferOnChange
16957
+ canAttach
15986
16958
  }) {
15987
- if (!available) {
16959
+ if (!available || canAttach) {
15988
16960
  return null;
15989
16961
  }
15990
- return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5 border-b border-line-subtle pb-3", children: [
15991
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
15992
- /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
15993
- /* @__PURE__ */ jsx(Label, { htmlFor: "session-replay-attach", children: "세션 리플레이 첨부" }),
15994
- /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [
15995
- /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
15996
- "button",
15997
- {
15998
- type: "button",
15999
- "aria-label": "세션 리플레이 첨부 안내",
16000
- className: "text-text-tertiary",
16001
- children: /* @__PURE__ */ jsx(CircleHelp, { className: "h-3.5 w-3.5" })
16002
- }
16003
- ) }),
16004
- /* @__PURE__ */ jsx(TooltipContent, { className: "max-w-[240px] whitespace-normal", children: "제출 직전 최근 2분 화면 조작을 함께 기록합니다. 입력값·민감 텍스트는 자동으로 마스킹됩니다." })
16005
- ] }) })
16006
- ] }),
16007
- /* @__PURE__ */ jsx(
16008
- Switch,
16009
- {
16010
- id: "session-replay-attach",
16011
- checked: canAttach && preferOn,
16012
- disabled: !canAttach,
16013
- onCheckedChange: onPreferOnChange,
16014
- "aria-label": "세션 리플레이 첨부"
16015
- }
16016
- )
16017
- ] }),
16018
- !canAttach ? /* @__PURE__ */ jsx("p", { className: "text-xs text-warning", children: "이번 달 리플레이 한도를 모두 사용했습니다. 다음 달에 한도가 초기화되거나, 플랜을 업그레이드하면 다시 첨부할 수 있습니다." }) : null
16019
- ] });
16962
+ return /* @__PURE__ */ jsx("p", { className: "text-xs text-warning", children: "이번 달 리플레이 한도를 모두 사용했습니다. 다음 달에 한도가 초기화되거나, 플랜을 업그레이드하면 다시 첨부할 수 있습니다." });
16020
16963
  }
16021
16964
  function IssueForm({
16022
16965
  position: position2,
@@ -16038,6 +16981,19 @@ function IssueForm({
16038
16981
  const [jiraFields, setJiraFields] = useState(
16039
16982
  {}
16040
16983
  );
16984
+ const [draftDisabledReason, setDraftDisabledReason] = useState(null);
16985
+ const intentRef = useRef(formState.intent);
16986
+ intentRef.current = formState.intent;
16987
+ const setFormMode = formState.setMode;
16988
+ const handleDraftCapabilityResolved = useCallback(
16989
+ ({ disabledReason }) => {
16990
+ setDraftDisabledReason(disabledReason);
16991
+ if (disabledReason && intentRef.current.trim().length === 0) {
16992
+ setFormMode("manual");
16993
+ }
16994
+ },
16995
+ [setFormMode]
16996
+ );
16041
16997
  const [notionFields, setNotionFields] = useState({});
16042
16998
  const [customFieldValues, setCustomFieldValues] = useState({});
16043
16999
  const { selectedProjectId } = useProject();
@@ -16059,6 +17015,10 @@ function IssueForm({
16059
17015
  const issueSubmission = useIssueSubmission({
16060
17016
  position: position2,
16061
17017
  onSubmit: (hasIntegrationFailure) => {
17018
+ if (formState.mode === "ai") {
17019
+ onSubmit(hasIntegrationFailure);
17020
+ return;
17021
+ }
16062
17022
  submitSucceededRef.current = true;
16063
17023
  hadIntegrationFailureRef.current = hasIntegrationFailure;
16064
17024
  setIsOpen(false);
@@ -16071,8 +17031,9 @@ function IssueForm({
16071
17031
  videoFile: position2.videoFile,
16072
17032
  sessionReplay
16073
17033
  });
16074
- useDisableBodyScroll();
17034
+ useDisableBodyScroll(formState.mode !== "ai");
16075
17035
  useEffect(() => {
17036
+ if (formState.mode === "ai") return;
16076
17037
  const handleKeyDown = (e) => {
16077
17038
  const path2 = e.composedPath();
16078
17039
  const actualTarget = path2.find(
@@ -16099,22 +17060,86 @@ function IssueForm({
16099
17060
  };
16100
17061
  window.addEventListener("keydown", handleKeyDown, { passive: false });
16101
17062
  return () => window.removeEventListener("keydown", handleKeyDown);
16102
- }, []);
17063
+ }, [formState.mode]);
17064
+ const submitCurrentMode = async () => {
17065
+ if (formState.mode === "ai") {
17066
+ await issueSubmission.submitIssue({ intent: formState.intent });
17067
+ } else {
17068
+ await issueSubmission.submitIssue({
17069
+ title: formState.title,
17070
+ description: formState.description
17071
+ });
17072
+ }
17073
+ };
16103
17074
  const handleSubmit = async (e) => {
16104
17075
  e.preventDefault();
16105
17076
  e.stopPropagation();
16106
- await issueSubmission.submitIssue(formState.title, formState.description);
17077
+ await submitCurrentMode();
16107
17078
  };
16108
- const handleClose = () => setIsOpen(false);
17079
+ const handleClose = () => {
17080
+ if (formState.mode === "ai") {
17081
+ onCancel();
17082
+ return;
17083
+ }
17084
+ setIsOpen(false);
17085
+ };
17086
+ if (formState.renderedMode === "ai") {
17087
+ return createPortal(
17088
+ /* @__PURE__ */ jsxs(
17089
+ IssueIntentBubbleAnchor,
17090
+ {
17091
+ x: position2.x,
17092
+ y: position2.y,
17093
+ onClose: handleClose,
17094
+ dirty: formState.intent.trim().length > 0,
17095
+ open: formState.mode === "ai",
17096
+ onExitComplete: formState.finishModeTransition,
17097
+ children: [
17098
+ showJiraFields ? /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: null, onError: () => null, children: /* @__PURE__ */ jsx(
17099
+ IssueFormJiraFieldDefaults,
17100
+ {
17101
+ integrationId: jiraIntegrationId,
17102
+ onDefaultsResolved: (defaults) => setJiraFields((current) => ({ ...defaults, ...current }))
17103
+ }
17104
+ ) }) : null,
17105
+ showCustomFields ? /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: null, onError: () => null, children: /* @__PURE__ */ jsx(
17106
+ IssueFormCustomFieldDefaults,
17107
+ {
17108
+ projectId: selectedProjectId,
17109
+ onDefaultsResolved: (defaults) => setCustomFieldValues((current) => ({ ...defaults, ...current }))
17110
+ }
17111
+ ) }) : null,
17112
+ /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: null, onError: () => null, children: /* @__PURE__ */ jsx(IssueFormDraftCapabilityGate, { onResolved: handleDraftCapabilityResolved }) }),
17113
+ /* @__PURE__ */ jsx(
17114
+ IssueIntentBubble,
17115
+ {
17116
+ value: formState.intent,
17117
+ onChange: formState.setIntent,
17118
+ onSubmit: () => void submitCurrentMode(),
17119
+ onSwitchToManual: () => formState.setMode("manual"),
17120
+ submitting: issueSubmission.isSubmitting,
17121
+ error: issueSubmission.error
17122
+ }
17123
+ )
17124
+ ]
17125
+ }
17126
+ ),
17127
+ getPortalContainer()
17128
+ );
17129
+ }
16109
17130
  return createPortal(
16110
17131
  /* @__PURE__ */ jsx(
16111
17132
  OverlayShell,
16112
17133
  {
16113
- open: isOpen,
17134
+ open: isOpen && formState.mode === "manual",
16114
17135
  shellClassName: "h-auto max-h-[min(80vh,640px)] max-w-[480px]",
16115
17136
  closeOnBackdropClick: false,
16116
17137
  onClose: handleClose,
16117
17138
  onExitComplete: () => {
17139
+ if (formState.mode === "ai") {
17140
+ formState.finishModeTransition();
17141
+ return;
17142
+ }
16118
17143
  if (submitSucceededRef.current) {
16119
17144
  onSubmit(hadIntegrationFailureRef.current);
16120
17145
  } else {
@@ -16127,19 +17152,24 @@ function IssueForm({
16127
17152
  className: `${ISSUE_STICKER_REPORT_FORM_CLASS} flex min-h-0 flex-1 flex-col`,
16128
17153
  onSubmit: handleSubmit,
16129
17154
  children: [
16130
- /* @__PURE__ */ jsx("div", { className: "border-b border-line-subtle px-4 py-3", children: /* @__PURE__ */ jsx(IssueFormHeader, { title: "이슈 생성", onClose: handleClose }) }),
17155
+ /* @__PURE__ */ jsx("div", { className: "border-b border-line-subtle px-4 py-3", children: /* @__PURE__ */ jsx(
17156
+ IssueFormHeader,
17157
+ {
17158
+ title: "이슈 생성",
17159
+ onClose: handleClose,
17160
+ onSwitchToAi: draftDisabledReason ? void 0 : () => formState.setMode("ai")
17161
+ }
17162
+ ) }),
16131
17163
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-h-0 space-y-3 overflow-y-auto px-4 py-3", children: [
17164
+ issueSubmission.error && /* @__PURE__ */ jsx(IssueFormError, { error: issueSubmission.error }),
16132
17165
  hasJiraIntegration && jiraConnect.needsConnect ? /* @__PURE__ */ jsx(JiraConnectNudge, { onConnect: () => void jiraConnect.connect() }) : null,
16133
- /* @__PURE__ */ jsx(
16134
- SessionReplayAttachToggle,
17166
+ isMember ? /* @__PURE__ */ jsx(
17167
+ SessionReplayLimitNotice,
16135
17168
  {
16136
17169
  available: sessionReplay.available,
16137
- canAttach: sessionReplay.canAttach,
16138
- preferOn: sessionReplay.preferOn,
16139
- onPreferOnChange: sessionReplay.setPreferOn
17170
+ canAttach: sessionReplay.canAttach
16140
17171
  }
16141
- ),
16142
- issueSubmission.error && /* @__PURE__ */ jsx(IssueFormError, { error: issueSubmission.error }),
17172
+ ) : null,
16143
17173
  /* @__PURE__ */ jsx(
16144
17174
  IssueFormTitleField,
16145
17175
  {
@@ -16156,6 +17186,7 @@ function IssueForm({
16156
17186
  disabled: issueSubmission.isSubmitting
16157
17187
  }
16158
17188
  ),
17189
+ draftDisabledReason ? /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary", children: draftDisabledReason }) : null,
16159
17190
  showIntegrationSkeleton ? /* @__PURE__ */ jsx(IntegrationFieldsSkeleton, {}) : null,
16160
17191
  showJiraFields ? /* @__PURE__ */ jsx(
16161
17192
  QueryBoundary,
@@ -16288,6 +17319,11 @@ function getAdminIssueUrl(issueId) {
16288
17319
  adminBaseUrl: readViteEnv("VITE_ADMIN_BASE_URL")
16289
17320
  });
16290
17321
  }
17322
+ function getAdminProjectTitlePatternUrl(projectId) {
17323
+ return buildAdminProjectTitlePatternUrl(projectId, {
17324
+ adminBaseUrl: readViteEnv("VITE_ADMIN_BASE_URL")
17325
+ });
17326
+ }
16291
17327
  function BrowserInfo({ userAgent }) {
16292
17328
  return /* @__PURE__ */ jsxs("div", { children: [
16293
17329
  /* @__PURE__ */ jsx("h4", { className: "mb-2 text-base font-medium text-text-secondary", children: "브라우저 정보" }),
@@ -16324,7 +17360,7 @@ var Collapsible = React.forwardRef(
16324
17360
  children: /* @__PURE__ */ jsx(
16325
17361
  Primitive.div,
16326
17362
  {
16327
- "data-state": getState$2(open),
17363
+ "data-state": getState$1(open),
16328
17364
  "data-disabled": disabled ? "" : void 0,
16329
17365
  ...collapsibleProps,
16330
17366
  ref: forwardedRef
@@ -16335,18 +17371,18 @@ var Collapsible = React.forwardRef(
16335
17371
  }
16336
17372
  );
16337
17373
  Collapsible.displayName = COLLAPSIBLE_NAME;
16338
- var TRIGGER_NAME$3 = "CollapsibleTrigger";
17374
+ var TRIGGER_NAME$2 = "CollapsibleTrigger";
16339
17375
  var CollapsibleTrigger = React.forwardRef(
16340
17376
  (props, forwardedRef) => {
16341
17377
  const { __scopeCollapsible, ...triggerProps } = props;
16342
- const context = useCollapsibleContext(TRIGGER_NAME$3, __scopeCollapsible);
17378
+ const context = useCollapsibleContext(TRIGGER_NAME$2, __scopeCollapsible);
16343
17379
  return /* @__PURE__ */ jsx(
16344
17380
  Primitive.button,
16345
17381
  {
16346
17382
  type: "button",
16347
17383
  "aria-controls": context.open ? context.contentId : void 0,
16348
17384
  "aria-expanded": context.open || false,
16349
- "data-state": getState$2(context.open),
17385
+ "data-state": getState$1(context.open),
16350
17386
  "data-disabled": context.disabled ? "" : void 0,
16351
17387
  disabled: context.disabled,
16352
17388
  ...triggerProps,
@@ -16356,19 +17392,19 @@ var CollapsibleTrigger = React.forwardRef(
16356
17392
  );
16357
17393
  }
16358
17394
  );
16359
- CollapsibleTrigger.displayName = TRIGGER_NAME$3;
16360
- var CONTENT_NAME$3 = "CollapsibleContent";
17395
+ CollapsibleTrigger.displayName = TRIGGER_NAME$2;
17396
+ var CONTENT_NAME$2 = "CollapsibleContent";
16361
17397
  var CollapsibleContent = React.forwardRef(
16362
17398
  (props, forwardedRef) => {
16363
17399
  const { forceMount, ...contentProps } = props;
16364
- const context = useCollapsibleContext(CONTENT_NAME$3, props.__scopeCollapsible);
17400
+ const context = useCollapsibleContext(CONTENT_NAME$2, props.__scopeCollapsible);
16365
17401
  return /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: ({ present }) => /* @__PURE__ */ jsx(CollapsibleContentImpl, { ...contentProps, ref: forwardedRef, present }) });
16366
17402
  }
16367
17403
  );
16368
- CollapsibleContent.displayName = CONTENT_NAME$3;
17404
+ CollapsibleContent.displayName = CONTENT_NAME$2;
16369
17405
  var CollapsibleContentImpl = React.forwardRef((props, forwardedRef) => {
16370
17406
  const { __scopeCollapsible, present, children, ...contentProps } = props;
16371
- const context = useCollapsibleContext(CONTENT_NAME$3, __scopeCollapsible);
17407
+ const context = useCollapsibleContext(CONTENT_NAME$2, __scopeCollapsible);
16372
17408
  const [isPresent, setIsPresent] = React.useState(present);
16373
17409
  const ref = React.useRef(null);
16374
17410
  const composedRefs = useComposedRefs$1(forwardedRef, ref);
@@ -16405,7 +17441,7 @@ var CollapsibleContentImpl = React.forwardRef((props, forwardedRef) => {
16405
17441
  return /* @__PURE__ */ jsx(
16406
17442
  Primitive.div,
16407
17443
  {
16408
- "data-state": getState$2(context.open),
17444
+ "data-state": getState$1(context.open),
16409
17445
  "data-disabled": context.disabled ? "" : void 0,
16410
17446
  id: context.contentId,
16411
17447
  hidden: !isOpen,
@@ -16420,7 +17456,7 @@ var CollapsibleContentImpl = React.forwardRef((props, forwardedRef) => {
16420
17456
  }
16421
17457
  );
16422
17458
  });
16423
- function getState$2(open) {
17459
+ function getState$1(open) {
16424
17460
  return open ? "open" : "closed";
16425
17461
  }
16426
17462
  var Root$1 = Collapsible;
@@ -16626,7 +17662,7 @@ var AccordionItem$1 = React.forwardRef(
16626
17662
  Root$1,
16627
17663
  {
16628
17664
  "data-orientation": accordionContext.orientation,
16629
- "data-state": getState$1(open),
17665
+ "data-state": getState(open),
16630
17666
  ...collapsibleScope,
16631
17667
  ...accordionItemProps,
16632
17668
  ref: forwardedRef,
@@ -16656,7 +17692,7 @@ var AccordionHeader = React.forwardRef(
16656
17692
  Primitive.h3,
16657
17693
  {
16658
17694
  "data-orientation": accordionContext.orientation,
16659
- "data-state": getState$1(itemContext.open),
17695
+ "data-state": getState(itemContext.open),
16660
17696
  "data-disabled": itemContext.disabled ? "" : void 0,
16661
17697
  ...headerProps,
16662
17698
  ref: forwardedRef
@@ -16665,13 +17701,13 @@ var AccordionHeader = React.forwardRef(
16665
17701
  }
16666
17702
  );
16667
17703
  AccordionHeader.displayName = HEADER_NAME;
16668
- var TRIGGER_NAME$2 = "AccordionTrigger";
17704
+ var TRIGGER_NAME$1 = "AccordionTrigger";
16669
17705
  var AccordionTrigger$1 = React.forwardRef(
16670
17706
  (props, forwardedRef) => {
16671
17707
  const { __scopeAccordion, ...triggerProps } = props;
16672
17708
  const accordionContext = useAccordionContext(ACCORDION_NAME, __scopeAccordion);
16673
- const itemContext = useAccordionItemContext(TRIGGER_NAME$2, __scopeAccordion);
16674
- const collapsibleContext = useAccordionCollapsibleContext(TRIGGER_NAME$2, __scopeAccordion);
17709
+ const itemContext = useAccordionItemContext(TRIGGER_NAME$1, __scopeAccordion);
17710
+ const collapsibleContext = useAccordionCollapsibleContext(TRIGGER_NAME$1, __scopeAccordion);
16675
17711
  const collapsibleScope = useCollapsibleScope(__scopeAccordion);
16676
17712
  return /* @__PURE__ */ jsx(Collection$1.ItemSlot, { scope: __scopeAccordion, children: /* @__PURE__ */ jsx(
16677
17713
  Trigger$1,
@@ -16686,13 +17722,13 @@ var AccordionTrigger$1 = React.forwardRef(
16686
17722
  ) });
16687
17723
  }
16688
17724
  );
16689
- AccordionTrigger$1.displayName = TRIGGER_NAME$2;
16690
- var CONTENT_NAME$2 = "AccordionContent";
17725
+ AccordionTrigger$1.displayName = TRIGGER_NAME$1;
17726
+ var CONTENT_NAME$1 = "AccordionContent";
16691
17727
  var AccordionContent$1 = React.forwardRef(
16692
17728
  (props, forwardedRef) => {
16693
17729
  const { __scopeAccordion, ...contentProps } = props;
16694
17730
  const accordionContext = useAccordionContext(ACCORDION_NAME, __scopeAccordion);
16695
- const itemContext = useAccordionItemContext(CONTENT_NAME$2, __scopeAccordion);
17731
+ const itemContext = useAccordionItemContext(CONTENT_NAME$1, __scopeAccordion);
16696
17732
  const collapsibleScope = useCollapsibleScope(__scopeAccordion);
16697
17733
  return /* @__PURE__ */ jsx(
16698
17734
  Content$1,
@@ -16712,8 +17748,8 @@ var AccordionContent$1 = React.forwardRef(
16712
17748
  );
16713
17749
  }
16714
17750
  );
16715
- AccordionContent$1.displayName = CONTENT_NAME$2;
16716
- function getState$1(open) {
17751
+ AccordionContent$1.displayName = CONTENT_NAME$1;
17752
+ function getState(open) {
16717
17753
  return open ? "open" : "closed";
16718
17754
  }
16719
17755
  var Root2$1 = Accordion$1;
@@ -17458,11 +18494,11 @@ var TabsList$1 = React.forwardRef(
17458
18494
  }
17459
18495
  );
17460
18496
  TabsList$1.displayName = TAB_LIST_NAME;
17461
- var TRIGGER_NAME$1 = "TabsTrigger";
18497
+ var TRIGGER_NAME = "TabsTrigger";
17462
18498
  var TabsTrigger$1 = React.forwardRef(
17463
18499
  (props, forwardedRef) => {
17464
18500
  const { __scopeTabs, value, disabled = false, ...triggerProps } = props;
17465
- const context = useTabsContext(TRIGGER_NAME$1, __scopeTabs);
18501
+ const context = useTabsContext(TRIGGER_NAME, __scopeTabs);
17466
18502
  const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeTabs);
17467
18503
  const triggerId = makeTriggerId(context.baseId, value);
17468
18504
  const contentId = makeContentId(context.baseId, value);
@@ -17509,12 +18545,12 @@ var TabsTrigger$1 = React.forwardRef(
17509
18545
  );
17510
18546
  }
17511
18547
  );
17512
- TabsTrigger$1.displayName = TRIGGER_NAME$1;
17513
- var CONTENT_NAME$1 = "TabsContent";
18548
+ TabsTrigger$1.displayName = TRIGGER_NAME;
18549
+ var CONTENT_NAME = "TabsContent";
17514
18550
  var TabsContent$1 = React.forwardRef(
17515
18551
  (props, forwardedRef) => {
17516
18552
  const { __scopeTabs, value, forceMount, children, ...contentProps } = props;
17517
- const context = useTabsContext(CONTENT_NAME$1, __scopeTabs);
18553
+ const context = useTabsContext(CONTENT_NAME, __scopeTabs);
17518
18554
  const triggerId = makeTriggerId(context.baseId, value);
17519
18555
  const contentId = makeContentId(context.baseId, value);
17520
18556
  const isSelected = value === context.value;
@@ -17544,7 +18580,7 @@ var TabsContent$1 = React.forwardRef(
17544
18580
  ) });
17545
18581
  }
17546
18582
  );
17547
- TabsContent$1.displayName = CONTENT_NAME$1;
18583
+ TabsContent$1.displayName = CONTENT_NAME;
17548
18584
  function makeTriggerId(baseId, value) {
17549
18585
  return `${baseId}-trigger-${value}`;
17550
18586
  }
@@ -32944,343 +33980,6 @@ function IssueDescription({
32944
33980
  error ? /* @__PURE__ */ jsx("p", { className: "text-xs text-danger", children: error }) : null
32945
33981
  ] });
32946
33982
  }
32947
- var DIALOG_NAME = "Dialog";
32948
- var [createDialogContext] = createContextScope(DIALOG_NAME);
32949
- var [DialogProvider, useDialogContext] = createDialogContext(DIALOG_NAME);
32950
- var Dialog$1 = (props) => {
32951
- const {
32952
- __scopeDialog,
32953
- children,
32954
- open: openProp,
32955
- defaultOpen,
32956
- onOpenChange,
32957
- modal = true
32958
- } = props;
32959
- const triggerRef = React.useRef(null);
32960
- const contentRef = React.useRef(null);
32961
- const [open, setOpen] = useControllableState({
32962
- prop: openProp,
32963
- defaultProp: defaultOpen ?? false,
32964
- onChange: onOpenChange,
32965
- caller: DIALOG_NAME
32966
- });
32967
- return /* @__PURE__ */ jsx(
32968
- DialogProvider,
32969
- {
32970
- scope: __scopeDialog,
32971
- triggerRef,
32972
- contentRef,
32973
- contentId: useId$1(),
32974
- titleId: useId$1(),
32975
- descriptionId: useId$1(),
32976
- open,
32977
- onOpenChange: setOpen,
32978
- onOpenToggle: React.useCallback(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
32979
- modal,
32980
- children
32981
- }
32982
- );
32983
- };
32984
- Dialog$1.displayName = DIALOG_NAME;
32985
- var TRIGGER_NAME = "DialogTrigger";
32986
- var DialogTrigger = React.forwardRef(
32987
- (props, forwardedRef) => {
32988
- const { __scopeDialog, ...triggerProps } = props;
32989
- const context = useDialogContext(TRIGGER_NAME, __scopeDialog);
32990
- const composedTriggerRef = useComposedRefs$1(forwardedRef, context.triggerRef);
32991
- return /* @__PURE__ */ jsx(
32992
- Primitive.button,
32993
- {
32994
- type: "button",
32995
- "aria-haspopup": "dialog",
32996
- "aria-expanded": context.open,
32997
- "aria-controls": context.open ? context.contentId : void 0,
32998
- "data-state": getState(context.open),
32999
- ...triggerProps,
33000
- ref: composedTriggerRef,
33001
- onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
33002
- }
33003
- );
33004
- }
33005
- );
33006
- DialogTrigger.displayName = TRIGGER_NAME;
33007
- var PORTAL_NAME = "DialogPortal";
33008
- var [PortalProvider, usePortalContext] = createDialogContext(PORTAL_NAME, {
33009
- forceMount: void 0
33010
- });
33011
- var DialogPortal$1 = (props) => {
33012
- const { __scopeDialog, forceMount, children, container } = props;
33013
- const context = useDialogContext(PORTAL_NAME, __scopeDialog);
33014
- return /* @__PURE__ */ jsx(PortalProvider, { scope: __scopeDialog, forceMount, children: React.Children.map(children, (child) => /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(Portal$1, { asChild: true, container, children: child }) })) });
33015
- };
33016
- DialogPortal$1.displayName = PORTAL_NAME;
33017
- var OVERLAY_NAME = "DialogOverlay";
33018
- var DialogOverlay$1 = React.forwardRef(
33019
- (props, forwardedRef) => {
33020
- const portalContext = usePortalContext(OVERLAY_NAME, props.__scopeDialog);
33021
- const { forceMount = portalContext.forceMount, ...overlayProps } = props;
33022
- const context = useDialogContext(OVERLAY_NAME, props.__scopeDialog);
33023
- return context.modal ? /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: /* @__PURE__ */ jsx(DialogOverlayImpl, { ...overlayProps, ref: forwardedRef }) }) : null;
33024
- }
33025
- );
33026
- DialogOverlay$1.displayName = OVERLAY_NAME;
33027
- var Slot = createSlot("DialogOverlay.RemoveScroll");
33028
- var DialogOverlayImpl = React.forwardRef(
33029
- (props, forwardedRef) => {
33030
- const { __scopeDialog, ...overlayProps } = props;
33031
- const context = useDialogContext(OVERLAY_NAME, __scopeDialog);
33032
- const registerDismissableSurface = useDismissableLayerSurface();
33033
- const composedRefs = useComposedRefs$1(forwardedRef, registerDismissableSurface);
33034
- return (
33035
- // Make sure `Content` is scrollable even when it doesn't live inside `RemoveScroll`
33036
- // ie. when `Overlay` and `Content` are siblings
33037
- /* @__PURE__ */ jsx(ReactRemoveScroll, { as: Slot, allowPinchZoom: true, shards: [context.contentRef], children: /* @__PURE__ */ jsx(
33038
- Primitive.div,
33039
- {
33040
- "data-state": getState(context.open),
33041
- ...overlayProps,
33042
- ref: composedRefs,
33043
- style: { pointerEvents: "auto", ...overlayProps.style }
33044
- }
33045
- ) })
33046
- );
33047
- }
33048
- );
33049
- var CONTENT_NAME = "DialogContent";
33050
- var DialogContent$1 = React.forwardRef(
33051
- (props, forwardedRef) => {
33052
- const portalContext = usePortalContext(CONTENT_NAME, props.__scopeDialog);
33053
- const { forceMount = portalContext.forceMount, ...contentProps } = props;
33054
- const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);
33055
- return /* @__PURE__ */ jsx(Presence, { present: forceMount || context.open, children: context.modal ? /* @__PURE__ */ jsx(DialogContentModal, { ...contentProps, ref: forwardedRef }) : /* @__PURE__ */ jsx(DialogContentNonModal, { ...contentProps, ref: forwardedRef }) });
33056
- }
33057
- );
33058
- DialogContent$1.displayName = CONTENT_NAME;
33059
- var DialogContentModal = React.forwardRef(
33060
- (props, forwardedRef) => {
33061
- const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);
33062
- const contentRef = React.useRef(null);
33063
- const composedRefs = useComposedRefs$1(forwardedRef, context.contentRef, contentRef);
33064
- React.useEffect(() => {
33065
- const content2 = contentRef.current;
33066
- if (content2) return hideOthers(content2);
33067
- }, []);
33068
- return /* @__PURE__ */ jsx(
33069
- DialogContentImpl,
33070
- {
33071
- ...props,
33072
- ref: composedRefs,
33073
- trapFocus: context.open,
33074
- disableOutsidePointerEvents: context.open,
33075
- onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {
33076
- var _a;
33077
- event.preventDefault();
33078
- (_a = context.triggerRef.current) == null ? void 0 : _a.focus();
33079
- }),
33080
- onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event) => {
33081
- const originalEvent = event.detail.originalEvent;
33082
- const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;
33083
- const isRightClick = originalEvent.button === 2 || ctrlLeftClick;
33084
- if (isRightClick) event.preventDefault();
33085
- }),
33086
- onFocusOutside: composeEventHandlers(
33087
- props.onFocusOutside,
33088
- (event) => event.preventDefault()
33089
- )
33090
- }
33091
- );
33092
- }
33093
- );
33094
- var DialogContentNonModal = React.forwardRef(
33095
- (props, forwardedRef) => {
33096
- const context = useDialogContext(CONTENT_NAME, props.__scopeDialog);
33097
- const hasInteractedOutsideRef = React.useRef(false);
33098
- const hasPointerDownOutsideRef = React.useRef(false);
33099
- return /* @__PURE__ */ jsx(
33100
- DialogContentImpl,
33101
- {
33102
- ...props,
33103
- ref: forwardedRef,
33104
- trapFocus: false,
33105
- disableOutsidePointerEvents: false,
33106
- onCloseAutoFocus: (event) => {
33107
- var _a, _b2;
33108
- (_a = props.onCloseAutoFocus) == null ? void 0 : _a.call(props, event);
33109
- if (!event.defaultPrevented) {
33110
- if (!hasInteractedOutsideRef.current) (_b2 = context.triggerRef.current) == null ? void 0 : _b2.focus();
33111
- event.preventDefault();
33112
- }
33113
- hasInteractedOutsideRef.current = false;
33114
- hasPointerDownOutsideRef.current = false;
33115
- },
33116
- onInteractOutside: (event) => {
33117
- var _a, _b2;
33118
- (_a = props.onInteractOutside) == null ? void 0 : _a.call(props, event);
33119
- if (!event.defaultPrevented) {
33120
- hasInteractedOutsideRef.current = true;
33121
- if (event.detail.originalEvent.type === "pointerdown") {
33122
- hasPointerDownOutsideRef.current = true;
33123
- }
33124
- }
33125
- const target = event.target;
33126
- const targetIsTrigger = (_b2 = context.triggerRef.current) == null ? void 0 : _b2.contains(target);
33127
- if (targetIsTrigger) event.preventDefault();
33128
- if (event.detail.originalEvent.type === "focusin" && hasPointerDownOutsideRef.current) {
33129
- event.preventDefault();
33130
- }
33131
- }
33132
- }
33133
- );
33134
- }
33135
- );
33136
- var DialogContentImpl = React.forwardRef(
33137
- (props, forwardedRef) => {
33138
- const { __scopeDialog, trapFocus, onOpenAutoFocus, onCloseAutoFocus, ...contentProps } = props;
33139
- const context = useDialogContext(CONTENT_NAME, __scopeDialog);
33140
- useFocusGuards();
33141
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
33142
- FocusScope,
33143
- {
33144
- asChild: true,
33145
- loop: true,
33146
- trapped: trapFocus,
33147
- onMountAutoFocus: onOpenAutoFocus,
33148
- onUnmountAutoFocus: onCloseAutoFocus,
33149
- children: /* @__PURE__ */ jsx(
33150
- DismissableLayer,
33151
- {
33152
- role: "dialog",
33153
- id: context.contentId,
33154
- "aria-describedby": context.descriptionId,
33155
- "aria-labelledby": context.titleId,
33156
- "data-state": getState(context.open),
33157
- ...contentProps,
33158
- ref: forwardedRef,
33159
- deferPointerDownOutside: true,
33160
- onDismiss: () => context.onOpenChange(false)
33161
- }
33162
- )
33163
- }
33164
- ) });
33165
- }
33166
- );
33167
- var TITLE_NAME = "DialogTitle";
33168
- var DialogTitle$1 = React.forwardRef(
33169
- (props, forwardedRef) => {
33170
- const { __scopeDialog, ...titleProps } = props;
33171
- const context = useDialogContext(TITLE_NAME, __scopeDialog);
33172
- return /* @__PURE__ */ jsx(Primitive.h2, { id: context.titleId, ...titleProps, ref: forwardedRef });
33173
- }
33174
- );
33175
- DialogTitle$1.displayName = TITLE_NAME;
33176
- var DESCRIPTION_NAME = "DialogDescription";
33177
- var DialogDescription$1 = React.forwardRef(
33178
- (props, forwardedRef) => {
33179
- const { __scopeDialog, ...descriptionProps } = props;
33180
- const context = useDialogContext(DESCRIPTION_NAME, __scopeDialog);
33181
- return /* @__PURE__ */ jsx(Primitive.p, { id: context.descriptionId, ...descriptionProps, ref: forwardedRef });
33182
- }
33183
- );
33184
- DialogDescription$1.displayName = DESCRIPTION_NAME;
33185
- var CLOSE_NAME = "DialogClose";
33186
- var DialogClose$1 = React.forwardRef(
33187
- (props, forwardedRef) => {
33188
- const { __scopeDialog, ...closeProps } = props;
33189
- const context = useDialogContext(CLOSE_NAME, __scopeDialog);
33190
- return /* @__PURE__ */ jsx(
33191
- Primitive.button,
33192
- {
33193
- type: "button",
33194
- ...closeProps,
33195
- ref: forwardedRef,
33196
- onClick: composeEventHandlers(props.onClick, () => context.onOpenChange(false))
33197
- }
33198
- );
33199
- }
33200
- );
33201
- DialogClose$1.displayName = CLOSE_NAME;
33202
- function getState(open) {
33203
- return open ? "open" : "closed";
33204
- }
33205
- const Dialog = Dialog$1;
33206
- const DialogClose = DialogClose$1;
33207
- const DialogPortal = ({ children }) => {
33208
- const portalContainer = usePortalContainer();
33209
- return /* @__PURE__ */ jsx(DialogPortal$1, { container: portalContainer, children });
33210
- };
33211
- const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33212
- DialogOverlay$1,
33213
- {
33214
- ref,
33215
- className: cn$1(
33216
- `fixed inset-0 ${OVERLAY_LAYER.dialogOverlay} bg-black/24`,
33217
- "data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out",
33218
- "motion-reduce:animate-none",
33219
- className
33220
- ),
33221
- ...props
33222
- }
33223
- ));
33224
- DialogOverlay.displayName = DialogOverlay$1.displayName;
33225
- const DialogContent = React.forwardRef(({ className, children, hideCloseButton = false, onEscapeKeyDown, style, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
33226
- /* @__PURE__ */ jsx(DialogOverlay, {}),
33227
- /* @__PURE__ */ jsxs(
33228
- DialogContent$1,
33229
- {
33230
- ref,
33231
- onEscapeKeyDown: stopEscapePropagation(onEscapeKeyDown),
33232
- style: {
33233
- left: `calc(50% - (var(${BODY_SCROLLBAR_WIDTH_CSS_VAR}, 0px) / 2))`,
33234
- ...style
33235
- },
33236
- className: cn$1(
33237
- `panel-shell fixed left-[50%] top-[50%] ${OVERLAY_LAYER.dialogContent} grid w-full max-w-[36rem] translate-x-[-50%] translate-y-[-50%] gap-5 rounded-2xl p-7 shadow-lg`,
33238
- "data-[state=open]:animate-dialog-in data-[state=closed]:animate-dialog-out",
33239
- "motion-reduce:animate-none",
33240
- className
33241
- ),
33242
- ...props,
33243
- children: [
33244
- children,
33245
- !hideCloseButton ? /* @__PURE__ */ jsxs(
33246
- DialogClose$1,
33247
- {
33248
- className: cn$1(
33249
- "absolute right-4 top-4 rounded-md border border-transparent bg-surface-2 p-1.5 text-text-tertiary",
33250
- "transition-colors duration-fast",
33251
- "hover:border-line-subtle hover:bg-surface-3 hover:text-text-primary",
33252
- "focus-visible:outline-none focus-visible:shadow-focus"
33253
- ),
33254
- children: [
33255
- /* @__PURE__ */ jsx(X$1, { className: "h-4 w-4" }),
33256
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "닫기" })
33257
- ]
33258
- }
33259
- ) : null
33260
- ]
33261
- }
33262
- )
33263
- ] }));
33264
- DialogContent.displayName = DialogContent$1.displayName;
33265
- const DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn$1("flex flex-col space-y-2 text-left", className), ...props });
33266
- const DialogTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33267
- DialogTitle$1,
33268
- {
33269
- ref,
33270
- className: cn$1("text-lg font-semibold text-text-primary", className),
33271
- ...props
33272
- }
33273
- ));
33274
- DialogTitle.displayName = DialogTitle$1.displayName;
33275
- const DialogDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
33276
- DialogDescription$1,
33277
- {
33278
- ref,
33279
- className: cn$1("text-sm leading-relaxed text-text-secondary", className),
33280
- ...props
33281
- }
33282
- ));
33283
- DialogDescription.displayName = DialogDescription$1.displayName;
33284
33983
  function getServiceDisplayName(serviceType) {
33285
33984
  switch (serviceType) {
33286
33985
  case "JIRA":
@@ -33470,13 +34169,78 @@ function IssueDeleteActions({
33470
34169
  }
33471
34170
  );
33472
34171
  }
34172
+ function IssueGenerationFailure$1({
34173
+ isRegenerating,
34174
+ regenerate
34175
+ }) {
34176
+ const handleClick = async () => {
34177
+ const success = await regenerate();
34178
+ if (!success) {
34179
+ toast.error("재생성에 실패했습니다. 잠시 후 다시 시도해주세요.");
34180
+ }
34181
+ };
34182
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3 text-sm", children: [
34183
+ /* @__PURE__ */ jsx("span", { className: "text-danger", children: "제목과 설명을 생성하지 못했습니다. 입력한 내용은 그대로 남아 있습니다." }),
34184
+ /* @__PURE__ */ jsx(
34185
+ Button,
34186
+ {
34187
+ type: "button",
34188
+ variant: "outline",
34189
+ size: "sm",
34190
+ onClick: handleClick,
34191
+ disabled: isRegenerating,
34192
+ children: "다시 생성"
34193
+ }
34194
+ )
34195
+ ] });
34196
+ }
34197
+ function useRegenerateIssue(issueId, onUpdated) {
34198
+ const [isRegenerating, setIsRegenerating] = useState(false);
34199
+ const regenerate = useCallback(async () => {
34200
+ setIsRegenerating(true);
34201
+ try {
34202
+ await issueService.regenerateIssue(issueId);
34203
+ applyIssueMutationEffects(issueId);
34204
+ onUpdated == null ? void 0 : onUpdated();
34205
+ return true;
34206
+ } catch {
34207
+ return false;
34208
+ } finally {
34209
+ setIsRegenerating(false);
34210
+ }
34211
+ }, [issueId, onUpdated]);
34212
+ return { isRegenerating, regenerate };
34213
+ }
34214
+ function IssueGenerationFailure({
34215
+ issueId,
34216
+ onUpdated
34217
+ }) {
34218
+ const { isRegenerating, regenerate } = useRegenerateIssue(issueId, onUpdated);
34219
+ return /* @__PURE__ */ jsx(IssueGenerationFailure$1, { isRegenerating, regenerate });
34220
+ }
34221
+ function IssueGenerationBadge({ status }) {
34222
+ if (status === "pending" || status === "processing") {
34223
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-1.5 rounded-md bg-warning-subtle px-2 py-0.5 text-2xs font-medium text-warning", children: [
34224
+ /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-md bg-warning" }),
34225
+ "제목 생성 중"
34226
+ ] });
34227
+ }
34228
+ if (status === "failed") {
34229
+ return /* @__PURE__ */ jsxs("span", { className: "inline-flex shrink-0 items-center gap-1.5 rounded-md bg-danger-subtle px-2 py-0.5 text-2xs font-medium text-danger", children: [
34230
+ /* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 rounded-md bg-danger" }),
34231
+ "제목 생성 실패"
34232
+ ] });
34233
+ }
34234
+ return null;
34235
+ }
33473
34236
  function IssueHeader({
33474
34237
  issueId,
33475
34238
  title,
33476
34239
  adminIssueUrl,
33477
34240
  onClose,
33478
34241
  onUpdated,
33479
- readOnly = false
34242
+ readOnly = false,
34243
+ generationStatus
33480
34244
  }) {
33481
34245
  const [draftTitle, setDraftTitle] = useState(title);
33482
34246
  const [isEditing, setIsEditing] = useState(false);
@@ -33532,6 +34296,7 @@ function IssueHeader({
33532
34296
  }
33533
34297
  ) : /* @__PURE__ */ jsxs("div", { className: "flex max-w-full min-w-0 items-center gap-1", children: [
33534
34298
  /* @__PURE__ */ jsx("h2", { className: "m-0 min-w-0 max-w-[28rem] truncate text-xl font-semibold text-text-primary", children: title }),
34299
+ /* @__PURE__ */ jsx(IssueGenerationBadge, { status: generationStatus }),
33535
34300
  !readOnly ? /* @__PURE__ */ jsx(
33536
34301
  Button,
33537
34302
  {
@@ -34493,7 +35258,7 @@ function IssuePopover({ issueId, onClose, onUpdate }) {
34493
35258
  const { isMember } = useAuthContext();
34494
35259
  const canWriteContent = canWriteIssueContent(isMember, (_a = SDKManager.getInstance().config.user) == null ? void 0 : _a.id);
34495
35260
  const { selectedProjectId } = useProject();
34496
- const { data: issue } = useSuspenseQuery({
35261
+ const { data: issue, refetch } = useSuspenseQuery({
34497
35262
  queryKey: ["issue", issueId, selectedProjectId],
34498
35263
  queryFn: async () => {
34499
35264
  const issueData = await issueService.getIssue(issueId);
@@ -34501,6 +35266,7 @@ function IssuePopover({ issueId, onClose, onUpdate }) {
34501
35266
  }
34502
35267
  });
34503
35268
  const adminIssueUrl = getAdminIssueUrl(issue.id);
35269
+ useGenerationPolling({ status: issue.generation_status, onRefetch: refetch });
34504
35270
  useDisableBodyScroll();
34505
35271
  const mapping = getPrimaryJiraMapping(issue);
34506
35272
  const meta = getJiraMetadata(mapping);
@@ -34534,10 +35300,12 @@ function IssuePopover({ issueId, onClose, onUpdate }) {
34534
35300
  adminIssueUrl,
34535
35301
  onClose: handleClose,
34536
35302
  onUpdated: onUpdate,
34537
- readOnly: !canWriteContent
35303
+ readOnly: !canWriteContent,
35304
+ generationStatus: issue.generation_status
34538
35305
  }
34539
35306
  ) }),
34540
35307
  /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-y-auto px-4 py-3", children: /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
35308
+ issue.generation_status === "failed" ? /* @__PURE__ */ jsx(IssueGenerationFailure, { issueId: issue.id, onUpdated: onUpdate }) : null,
34541
35309
  /* @__PURE__ */ jsx(
34542
35310
  IssueDescription,
34543
35311
  {
@@ -34994,6 +35762,7 @@ function getEstimatedExpandedWidth(title) {
34994
35762
  STICKER_MAX_WIDTH
34995
35763
  );
34996
35764
  }
35765
+ const GENERATING_LABEL = "제목 생성 중";
34997
35766
  function IssueSticker$1({
34998
35767
  issue,
34999
35768
  isPopoverOpen,
@@ -35005,7 +35774,11 @@ function IssueSticker$1({
35005
35774
  clusterStackIndex = 0
35006
35775
  }) {
35007
35776
  const position2 = documentPosition;
35008
- const expandedWidth = getEstimatedExpandedWidth(issue.title);
35777
+ const resolvedClusterCount = clusterCount ?? 0;
35778
+ const isCluster = resolvedClusterCount > 1;
35779
+ const generating = isGeneratingStatus(issue.generation_status) && !isCluster;
35780
+ const visibleTitle = isCluster ? `스티커 ${resolvedClusterCount}개 펼치기` : generating ? GENERATING_LABEL : issue.title;
35781
+ const expandedWidth = getEstimatedExpandedWidth(visibleTitle);
35009
35782
  const viewportWidth = typeof window === "undefined" ? Number.POSITIVE_INFINITY : window.innerWidth;
35010
35783
  const scrollX = typeof window === "undefined" ? 0 : window.scrollX || window.pageXOffset || 0;
35011
35784
  const viewportX = position2.x - scrollX;
@@ -35018,10 +35791,7 @@ function IssueSticker$1({
35018
35791
  transform: shouldExpandLeft ? "translate3d(calc(-100% + 16px), -50%, 0)" : "translate3d(-16px, -50%, 0)"
35019
35792
  };
35020
35793
  const wrapperClassName = isPopoverOpen ? "z-[10001]" : "z-[9999] hover:z-[10001] focus-within:z-[10001]";
35021
- const resolvedClusterCount = clusterCount ?? 0;
35022
- const isCluster = resolvedClusterCount > 1;
35023
- const buttonClassName = `issue-sticker-marker issue-marker-breathe group flex h-8 w-max cursor-pointer items-center overflow-hidden rounded-full border text-white shadow-lg outline-none transition-[max-width,box-shadow,background-color,border-color,transform,opacity] duration-[var(--issue-marker-expand-duration)] ease-out focus-visible:ring-4 ${isCluster ? "max-w-8 border-white/80 bg-brand shadow-lg ring-2 ring-brand-subtle hover:max-w-[160px] hover:bg-brand-hover hover:shadow-xl focus-visible:max-w-[160px] focus-visible:ring-brand-subtle" : "max-w-8 border-white/80 bg-brand hover:max-w-[480px] hover:bg-brand-hover hover:shadow-xl focus-visible:max-w-[480px] focus-visible:ring-brand-subtle"} ${shouldExpandLeft ? "flex-row-reverse" : ""} ${isPopoverOpen ? "shadow-xl ring-4 ring-brand-subtle" : ""}`;
35024
- const visibleTitle = isCluster ? `스티커 ${resolvedClusterCount}개 펼치기` : issue.title;
35794
+ const buttonClassName = `issue-sticker-marker ${generating ? "" : "issue-marker-breathe"} group flex h-8 w-max cursor-pointer items-center overflow-hidden rounded-full border text-white shadow-lg outline-none transition-[max-width,box-shadow,background-color,border-color,transform,opacity] duration-[var(--issue-marker-expand-duration)] ease-out focus-visible:ring-4 ${isCluster ? "max-w-8 border-white/80 bg-brand shadow-lg ring-2 ring-brand-subtle hover:max-w-[160px] hover:bg-brand-hover hover:shadow-xl focus-visible:max-w-[160px] focus-visible:ring-brand-subtle" : `max-w-8 bg-brand hover:max-w-[480px] hover:bg-brand-hover hover:shadow-xl focus-visible:max-w-[480px] focus-visible:ring-brand-subtle ${generating ? "border-dashed border-white/70" : "border-white/80"}`} ${shouldExpandLeft ? "flex-row-reverse" : ""} ${isPopoverOpen ? "shadow-xl ring-4 ring-brand-subtle" : ""}`;
35025
35795
  const buttonStyle = clusterStackAnimation ? {
35026
35796
  animation: clusterStackAnimation === "enter" ? "issue-sticker-cluster-sticker-enter 240ms cubic-bezier(0.34, 1.2, 0.64, 1) both" : "issue-sticker-cluster-sticker-exit 220ms ease-in both",
35027
35797
  animationDelay: clusterStackAnimation === "enter" ? `${clusterStackIndex * 24}ms` : void 0
@@ -35043,14 +35813,14 @@ function IssueSticker$1({
35043
35813
  "data-cluster-count": isCluster ? resolvedClusterCount : void 0,
35044
35814
  "data-expand-side": expandSide,
35045
35815
  onClick: handleClick,
35046
- "aria-label": isCluster ? `겹친 스티커 ${resolvedClusterCount}개 펼치기` : `이슈 열기: ${issue.title}`,
35816
+ "aria-label": isCluster ? `겹친 스티커 ${resolvedClusterCount}개 펼치기` : `이슈 열기: ${visibleTitle}`,
35047
35817
  children: [
35048
35818
  /* @__PURE__ */ jsx(
35049
35819
  "span",
35050
35820
  {
35051
- className: "flex h-8 w-8 shrink-0 items-center justify-center text-sm font-black leading-none",
35821
+ className: "flex aspect-square h-full shrink-0 items-center justify-center text-sm font-black leading-none",
35052
35822
  "aria-hidden": "true",
35053
- children: isCluster ? `+${resolvedClusterCount}` : "!"
35823
+ children: isCluster ? `+${resolvedClusterCount}` : generating ? /* @__PURE__ */ jsx(LoaderCircle, { className: "h-4 w-4 animate-spin" }) : "!"
35054
35824
  }
35055
35825
  ),
35056
35826
  /* @__PURE__ */ jsx(
@@ -36780,6 +37550,8 @@ function useToolbarDrag({
36780
37550
  );
36781
37551
  return { isDragging: isDragging2, onPointerDown };
36782
37552
  }
37553
+ const TITLE_PATTERN_MISSING_MESSAGE = "제목 패턴을 아직 추출하지 않아 팀 형식이 적용되지 않습니다. 누르면 프로젝트 설정이 새 탭으로 열립니다.";
37554
+ const TITLE_PATTERN_EXTRACT_LABEL = "패턴 추출하기";
36783
37555
  function formatElapsed(startedAt, now2) {
36784
37556
  const seconds = startedAt === null ? 0 : Math.max(0, Math.floor((now2 - startedAt) / 1e3));
36785
37557
  const mm = String(Math.floor(seconds / 60)).padStart(2, "0");
@@ -36805,7 +37577,8 @@ function Toolbar({
36805
37577
  onboardingEnabled = true,
36806
37578
  targets,
36807
37579
  account,
36808
- blocked
37580
+ blocked,
37581
+ titlePatternExtract
36809
37582
  }) {
36810
37583
  const rootRef = useRef(null);
36811
37584
  const [internalOpen, setInternalOpen] = useState(false);
@@ -36941,6 +37714,19 @@ function Toolbar({
36941
37714
  getShortcutLabel("CAPTURE_VIDEO")
36942
37715
  ] })
36943
37716
  ] }),
37717
+ titlePatternExtract ? /* @__PURE__ */ jsxs(Tooltip, { children: [
37718
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
37719
+ "button",
37720
+ {
37721
+ type: "button",
37722
+ className: "toolbar-btn",
37723
+ "aria-label": TITLE_PATTERN_EXTRACT_LABEL,
37724
+ onClick: titlePatternExtract.onClick,
37725
+ children: /* @__PURE__ */ jsx(WandSparkles, { size: 15 })
37726
+ }
37727
+ ) }),
37728
+ /* @__PURE__ */ jsx(TooltipContent, { side: "top", sideOffset: 10, className: "whitespace-normal text-left", children: TITLE_PATTERN_MISSING_MESSAGE })
37729
+ ] }) : null,
36944
37730
  /* @__PURE__ */ jsx("div", { className: "toolbar-divider" }),
36945
37731
  /* @__PURE__ */ jsxs(
36946
37732
  "button",
@@ -37060,9 +37846,15 @@ const SDK_TOOLBAR_TARGETS = {
37060
37846
  menuSession: "sdk-more-session"
37061
37847
  };
37062
37848
  function SdkToolbar(props) {
37063
- const { isMember, login, logout } = useAuthContext();
37849
+ const { isMember, projectId, login, logout } = useAuthContext();
37064
37850
  const [error, setError] = useState("");
37065
37851
  const [loading, setLoading] = useState(false);
37852
+ const [titlePatternMissing, setTitlePatternMissing] = useState(false);
37853
+ const handleDraftCapabilityResolved = useCallback(
37854
+ ({ titlePatternMissing: missing }) => setTitlePatternMissing(missing),
37855
+ []
37856
+ );
37857
+ const titlePatternUrl = isMember && titlePatternMissing && projectId ? getAdminProjectTitlePatternUrl(projectId) : null;
37066
37858
  const handleLogin = async () => {
37067
37859
  var _a;
37068
37860
  setError("");
@@ -37081,21 +37873,25 @@ function SdkToolbar(props) {
37081
37873
  await logout();
37082
37874
  (_a = props.onMenuOpenChange) == null ? void 0 : _a.call(props, false);
37083
37875
  };
37084
- return /* @__PURE__ */ jsx(
37085
- Toolbar,
37086
- {
37087
- ...props,
37088
- targets: SDK_TOOLBAR_TARGETS,
37089
- account: {
37090
- isMember,
37091
- canLogin: !isDemoMode,
37092
- loading,
37093
- error,
37094
- onLogin: () => void handleLogin(),
37095
- onLogout: () => void handleLogout()
37876
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
37877
+ isMember ? /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: null, onError: () => null, children: /* @__PURE__ */ jsx(IssueFormDraftCapabilityGate, { onResolved: handleDraftCapabilityResolved }) }) : null,
37878
+ /* @__PURE__ */ jsx(
37879
+ Toolbar,
37880
+ {
37881
+ ...props,
37882
+ targets: SDK_TOOLBAR_TARGETS,
37883
+ titlePatternExtract: titlePatternUrl ? { onClick: () => window.open(titlePatternUrl, "_blank", "noopener,noreferrer") } : void 0,
37884
+ account: {
37885
+ isMember,
37886
+ canLogin: !isDemoMode,
37887
+ loading,
37888
+ error,
37889
+ onLogin: () => void handleLogin(),
37890
+ onLogout: () => void handleLogout()
37891
+ }
37096
37892
  }
37097
- }
37098
- );
37893
+ )
37894
+ ] });
37099
37895
  }
37100
37896
  function ContentAppWrapper({
37101
37897
  fabEnabled,
@@ -37150,7 +37946,6 @@ function ContentAppWrapper({
37150
37946
  onBeforeStart: handleBeforeOnboardingStart,
37151
37947
  isCreatingIssueFlow: isCreatingIssue || clickPosition !== null,
37152
37948
  children: [
37153
- /* @__PURE__ */ jsx(ToastContainer, { position: "top-right" }),
37154
37949
  fabEnabled && /* @__PURE__ */ jsx(
37155
37950
  SdkToolbar,
37156
37951
  {
@@ -37172,7 +37967,7 @@ function ContentAppWrapper({
37172
37967
  onMenuOpenChange: setMoreMenuOpen
37173
37968
  }
37174
37969
  ),
37175
- /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: /* @__PURE__ */ jsx(Fragment, {}), children: /* @__PURE__ */ jsx(
37970
+ /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: /* @__PURE__ */ jsx(Fragment, {}), onError: OverlayErrorFallback, children: /* @__PURE__ */ jsx(
37176
37971
  IssueStickersContainer,
37177
37972
  {
37178
37973
  issues,
@@ -37194,7 +37989,7 @@ function ContentAppWrapper({
37194
37989
  renderMode
37195
37990
  }
37196
37991
  ),
37197
- openPopoverIssueId && isExtensionEnabled && /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: /* @__PURE__ */ jsx(Fragment, {}), children: /* @__PURE__ */ jsx(
37992
+ openPopoverIssueId && isExtensionEnabled && /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: /* @__PURE__ */ jsx(Fragment, {}), onError: OverlayErrorFallback, children: /* @__PURE__ */ jsx(
37198
37993
  IssuePopover,
37199
37994
  {
37200
37995
  issueId: openPopoverIssueId,
@@ -37202,7 +37997,7 @@ function ContentAppWrapper({
37202
37997
  onUpdate: loadIssues
37203
37998
  }
37204
37999
  ) }),
37205
- clickPosition && isExtensionEnabled && /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: /* @__PURE__ */ jsx(Fragment, {}), children: /* @__PURE__ */ jsx(
38000
+ clickPosition && isExtensionEnabled && /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: /* @__PURE__ */ jsx(Fragment, {}), onError: OverlayErrorFallback, children: /* @__PURE__ */ jsx(
37206
38001
  IssueForm,
37207
38002
  {
37208
38003
  position: clickPosition,
@@ -37247,18 +38042,21 @@ function AuthGate() {
37247
38042
  if (!isAuthenticated) {
37248
38043
  return null;
37249
38044
  }
37250
- return /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: /* @__PURE__ */ jsx(Fragment, {}), children: /* @__PURE__ */ jsx(
37251
- ContentAppWrapper,
37252
- {
37253
- fabEnabled,
37254
- toolbar: sdk.config.toolbar,
37255
- onboarding
37256
- }
37257
- ) });
38045
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
38046
+ /* @__PURE__ */ jsx(ToastContainer, { position: "top-right" }),
38047
+ /* @__PURE__ */ jsx(QueryBoundary, { loadingFallback: /* @__PURE__ */ jsx(Fragment, {}), onError: OverlayErrorFallback, children: /* @__PURE__ */ jsx(
38048
+ ContentAppWrapper,
38049
+ {
38050
+ fabEnabled,
38051
+ toolbar: sdk.config.toolbar,
38052
+ onboarding
38053
+ }
38054
+ ) })
38055
+ ] });
37258
38056
  }
37259
- 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;--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%;--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{--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;--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%;--border-subtle: 144 8% 91%;--border-default: 144 6% 85%}@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}@keyframes onboarding-confetti-x{0%{transform:translate(0)}to{transform:translate(var(--confetti-x))}}@keyframes onboarding-confetti-y{0%{transform:translateY(0);animation-timing-function:cubic-bezier(.12,.66,.32,1)}42%{transform:translateY(var(--confetti-lift));animation-timing-function:cubic-bezier(.58,0,.86,.32)}to{transform:translateY(var(--confetti-drop))}}@keyframes onboarding-confetti-piece{0%{opacity:0;transform:scale(.7) rotate(0)}6%{opacity:1}72%{opacity:1}to{opacity:0;transform:scale(1) rotate(var(--confetti-spin))}}.onboarding-confetti-x,.onboarding-confetti-y,.onboarding-confetti-piece{--confetti-duration: 1.9s;animation-duration:var(--confetti-duration);animation-delay:var(--confetti-delay, 0ms);animation-fill-mode:both}.onboarding-confetti-x{animation-name:onboarding-confetti-x;animation-timing-function:cubic-bezier(.08,.62,.3,1)}.onboarding-confetti-y{animation-name:onboarding-confetti-y;animation-timing-function:linear}.onboarding-confetti-piece{width:var(--confetti-size);height:var(--confetti-size);border-radius:var(--radius-pill) var(--radius-xs) var(--radius-pill) var(--radius-pill);animation-name:onboarding-confetti-piece;animation-timing-function:linear}@media(prefers-reduced-motion:reduce){.onboarding-confetti-x,.onboarding-confetti-y,.onboarding-confetti-piece{animation:none;opacity:0}}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:.5rem;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{background-color:transparent;--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.container{width:100%}@media(min-width:640px){.container{max-width:640px}}@media(min-width:768px){.container{max-width:768px}}@media(min-width:1024px){.container{max-width:1024px}}@media(min-width:1280px){.container{max-width:1280px}}@media(min-width:1536px){.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:.25rem;right:.25rem}.inset-y-0{top:0;bottom:0}.-bottom-px{bottom:-1px}.bottom-0{bottom:0}.bottom-4{bottom:1rem}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1\\/2{left:50%}.left-2{left:.5rem}.left-4{left:1rem}.left-\\[50\\%\\]{left:50%}.right-0{right:0}.right-2{right:.5rem}.right-3{right:.75rem}.right-4{right:1rem}.right-5{right:1.25rem}.right-6{right:1.5rem}.top-0{top:0}.top-1{top:.25rem}.top-1\\/2{top:50%}.top-2{top:.5rem}.top-3{top:.75rem}.top-4{top:1rem}.top-5{top:1.25rem}.top-\\[50\\%\\]{top:50%}.top-\\[calc\\(\\(3\\.5rem-1\\.75rem\\)\\/2\\)\\]{top:.875rem}.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:-.5rem;margin-right:-.5rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-2\\.5{margin-top:.625rem;margin-bottom:.625rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-0\\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-5{margin-bottom:1.25rem}.ml-0\\.5{margin-left:.125rem}.ml-4{margin-left:1rem}.mr-1\\.5{margin-right:.375rem}.mt-0{margin-top:0}.mt-0\\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.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-10{height:2.5rem}.h-11{height:2.75rem}.h-2{height:.5rem}.h-24{height:6rem}.h-3{height:.75rem}.h-3\\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\\[1\\.4rem\\]{height:1.4rem}.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\\(--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:6rem}.max-h-56{max-height:14rem}.max-h-96{max-height:24rem}.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 - 3rem)}.max-h-\\[min\\(80vh\\,640px\\)\\]{max-height:min(80vh,640px)}.min-h-0{min-height:0px}.min-h-11{min-height:2.75rem}.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:.125rem}.w-1{width:.25rem}.w-1\\/2{width:50%}.w-10{width:2.5rem}.w-14{width:3.5rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-3\\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\\[1\\.4rem\\]{width:1.4rem}.w-\\[18px\\]{width:18px}.w-\\[21rem\\]{width:21rem}.w-\\[22rem\\]{width:22rem}.w-\\[30px\\]{width:30px}.w-\\[38px\\]{width:38px}.w-\\[calc\\(100vw-32px\\)\\]{width:calc(100vw - 32px)}.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:2.25rem}.min-w-\\[12rem\\]{min-width:12rem}.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-8{max-width:2rem}.max-w-\\[120px\\]{max-width:120px}.max-w-\\[160px\\]{max-width:160px}.max-w-\\[240px\\]{max-width:240px}.max-w-\\[280px\\]{max-width:280px}.max-w-\\[28rem\\]{max-width:28rem}.max-w-\\[300px\\]{max-width:300px}.max-w-\\[360px\\]{max-width:360px}.max-w-\\[36rem\\]{max-width:36rem}.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-full{max-width:100%}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.caption-bottom{caption-side:bottom}.border-collapse{border-collapse:collapse}.-translate-x-1{--tw-translate-x: -.25rem;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-1{--tw-translate-x: .25rem;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-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:.125rem}.gap-1{gap:.25rem}.gap-1\\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-3\\.5{gap:.875rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-x-5{-moz-column-gap:1.25rem;column-gap:1.25rem}.gap-y-2{row-gap:.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * 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-all{word-break:break-all}.\\!rounded-none{border-radius:0!important}.rounded{border-radius:.25rem}.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-\\[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-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\\/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-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-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}.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:.125rem}.p-1{padding:.25rem}.p-1\\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-3\\.5{padding:.875rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-7{padding:1.75rem}.p-8{padding:2rem}.p-\\[18px\\]{padding:18px}.px-0{padding-left:0;padding-right:0}.px-1\\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-9{padding-left:2.25rem;padding-right:2.25rem}.py-0\\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-1{padding-bottom:.25rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-5{padding-left:1.25rem}.pl-8{padding-left:2rem}.pr-10{padding-right:2.5rem}.pr-3{padding-right:.75rem}.pr-4{padding-right:1rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-2\\.5{padding-top:.625rem}.pt-4{padding-top:1rem}.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:10.5px;line-height:14px}.text-\\[0\\.72rem\\]{font-size:.72rem}.text-\\[1\\.45rem\\]{font-size:1.45rem}.text-\\[1\\.75rem\\]{font-size:1.75rem}.text-\\[10px\\]{font-size:10px}.text-base{font-size:14px;line-height:21px}.text-lg{font-size:17px;line-height:25px}.text-sm{font-size:13px;line-height:19px}.text-xl{font-size:20px;line-height:29px}.text-xs{font-size:12px;line-height:16px}.font-black{font-weight:900}.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:1rem}.leading-5{line-height:1.25rem}.leading-8{line-height:2rem}.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}.\\!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\\,box-shadow\\,background-color\\,border-color\\,transform\\,opacity\\]{transition-property:max-width,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}.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:13px;line-height:19px}.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))}.focus-within\\:z-\\[10001\\]:focus-within{z-index:10001}.hover\\:z-\\[10001\\]:hover{z-index:10001}.hover\\:max-w-\\[160px\\]:hover{max-width:160px}.hover\\:max-w-\\[480px\\]:hover{max-width:480px}.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}.hover\\:shadow-xl:hover{--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)}.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\\: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-50:disabled{opacity:.5}.group:hover .group-hover\\: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:hover .group-hover\\:opacity-100{opacity:1}.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:1rem;padding-right:1rem}.group.toaster .group-\\[\\.toaster\\]\\:py-3{padding-top:.75rem;padding-bottom:.75rem}.group.toast .group-\\[\\.toast\\]\\:text-sm{font-size:13px;line-height:19px}.group.toast .group-\\[\\.toast\\]\\:text-xs{font-size:12px;line-height:16px}.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:.625rem}.sm\\:p-5{padding:1.25rem}.sm\\:p-6{padding:1.5rem}.sm\\:text-2xl{font-size:26px;line-height:34px}.sm\\:text-\\[2\\.1rem\\]{font-size:2.1rem}}@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:1rem}.\\[\\&\\>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))}`;
38057
+ 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;--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%;--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{--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;--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)}@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}@keyframes onboarding-confetti-x{0%{transform:translate(0)}to{transform:translate(var(--confetti-x))}}@keyframes onboarding-confetti-y{0%{transform:translateY(0);animation-timing-function:cubic-bezier(.12,.66,.32,1)}42%{transform:translateY(var(--confetti-lift));animation-timing-function:cubic-bezier(.58,0,.86,.32)}to{transform:translateY(var(--confetti-drop))}}@keyframes onboarding-confetti-piece{0%{opacity:0;transform:scale(.7) rotate(0)}6%{opacity:1}72%{opacity:1}to{opacity:0;transform:scale(1) rotate(var(--confetti-spin))}}.onboarding-confetti-x,.onboarding-confetti-y,.onboarding-confetti-piece{--confetti-duration: 1.9s;animation-duration:var(--confetti-duration);animation-delay:var(--confetti-delay, 0ms);animation-fill-mode:both}.onboarding-confetti-x{animation-name:onboarding-confetti-x;animation-timing-function:cubic-bezier(.08,.62,.3,1)}.onboarding-confetti-y{animation-name:onboarding-confetti-y;animation-timing-function:linear}.onboarding-confetti-piece{width:var(--confetti-size);height:var(--confetti-size);border-radius:var(--radius-pill) var(--radius-xs) var(--radius-pill) var(--radius-pill);animation-name:onboarding-confetti-piece;animation-timing-function:linear}@media(prefers-reduced-motion:reduce){.onboarding-confetti-x,.onboarding-confetti-y,.onboarding-confetti-piece{animation:none;opacity:0}}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:.5rem;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{background-color:transparent;--tw-text-opacity: 1;color:hsl(var(--text-primary) / var(--tw-text-opacity, 1))}.\\!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:.25rem;right:.25rem}.inset-y-0{top:0;bottom:0}.-bottom-px{bottom:-1px}.bottom-0{bottom:0}.bottom-4{bottom:1rem}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1\\/2{left:50%}.left-2{left:.5rem}.left-4{left:1rem}.left-\\[50\\%\\]{left:50%}.right-0{right:0}.right-2{right:.5rem}.right-3{right:.75rem}.right-4{right:1rem}.right-5{right:1.25rem}.right-6{right:1.5rem}.top-0{top:0}.top-1{top:.25rem}.top-1\\/2{top:50%}.top-2{top:.5rem}.top-3{top:.75rem}.top-4{top:1rem}.top-5{top:1.25rem}.top-\\[50\\%\\]{top:50%}.top-\\[calc\\(\\(3\\.5rem-1\\.75rem\\)\\/2\\)\\]{top:.875rem}.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:-.5rem;margin-right:-.5rem}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-2{margin-top:.5rem;margin-bottom:.5rem}.my-2\\.5{margin-top:.625rem;margin-bottom:.625rem}.my-3{margin-top:.75rem;margin-bottom:.75rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-0\\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-5{margin-bottom:1.25rem}.ml-0\\.5{margin-left:.125rem}.ml-4{margin-left:1rem}.mr-1\\.5{margin-right:.375rem}.mt-0{margin-top:0}.mt-0\\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.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:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-2{height:.5rem}.h-24{height:6rem}.h-3{height:.75rem}.h-3\\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\\[1\\.4rem\\]{height:1.4rem}.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\\(--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:6rem}.max-h-40{max-height:10rem}.max-h-56{max-height:14rem}.max-h-96{max-height:24rem}.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 - 3rem)}.max-h-\\[min\\(80vh\\,640px\\)\\]{max-height:min(80vh,640px)}.min-h-0{min-height:0px}.min-h-11{min-height:2.75rem}.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:.125rem}.w-1{width:.25rem}.w-1\\.5{width:.375rem}.w-1\\/2{width:50%}.w-10{width:2.5rem}.w-14{width:3.5rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-3\\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-72{width:18rem}.w-8{width:2rem}.w-80{width:20rem}.w-9{width:2.25rem}.w-\\[1\\.4rem\\]{width:1.4rem}.w-\\[18px\\]{width:18px}.w-\\[21rem\\]{width:21rem}.w-\\[22rem\\]{width:22rem}.w-\\[30px\\]{width:30px}.w-\\[38px\\]{width:38px}.w-\\[calc\\(100vw-32px\\)\\]{width:calc(100vw - 32px)}.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:2.25rem}.min-w-\\[12rem\\]{min-width:12rem}.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-8{max-width:2rem}.max-w-\\[120px\\]{max-width:120px}.max-w-\\[160px\\]{max-width:160px}.max-w-\\[280px\\]{max-width:280px}.max-w-\\[28rem\\]{max-width:28rem}.max-w-\\[300px\\]{max-width:300px}.max-w-\\[360px\\]{max-width:360px}.max-w-\\[36rem\\]{max-width:36rem}.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-full{max-width:100%}.max-w-md{max-width:28rem}.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: -.25rem;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-1{--tw-translate-x: .25rem;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-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:.125rem}.gap-1{gap:.25rem}.gap-1\\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-3\\.5{gap:.875rem}.gap-4{gap:1rem}.gap-5{gap:1.25rem}.gap-6{gap:1.5rem}.gap-x-5{-moz-column-gap:1.25rem;column-gap:1.25rem}.gap-y-2{row-gap:.5rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * 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-all{word-break:break-all}.\\!rounded-none{border-radius:0!important}.rounded{border-radius:.25rem}.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}.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:.125rem}.p-1{padding:.25rem}.p-1\\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-3\\.5{padding:.875rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-7{padding:1.75rem}.p-8{padding:2rem}.p-\\[18px\\]{padding:18px}.px-0{padding-left:0;padding-right:0}.px-1\\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-9{padding-left:2.25rem;padding-right:2.25rem}.py-0\\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\\.5{padding-top:.375rem;padding-bottom:.375rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-3\\.5{padding-top:.875rem;padding-bottom:.875rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-1{padding-bottom:.25rem}.pb-3{padding-bottom:.75rem}.pb-4{padding-bottom:1rem}.pl-3{padding-left:.75rem}.pl-4{padding-left:1rem}.pl-5{padding-left:1.25rem}.pl-8{padding-left:2rem}.pr-10{padding-right:2.5rem}.pr-3{padding-right:.75rem}.pr-4{padding-right:1rem}.pt-0{padding-top:0}.pt-1{padding-top:.25rem}.pt-2\\.5{padding-top:.625rem}.pt-4{padding-top:1rem}.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:10.5px;line-height:14px}.text-\\[0\\.72rem\\]{font-size:.72rem}.text-\\[1\\.45rem\\]{font-size:1.45rem}.text-\\[1\\.75rem\\]{font-size:1.75rem}.text-\\[10px\\]{font-size:10px}.text-base{font-size:14px;line-height:21px}.text-lg{font-size:17px;line-height:25px}.text-sm{font-size:13px;line-height:19px}.text-xl{font-size:20px;line-height:29px}.text-xs{font-size:12px;line-height:16px}.font-black{font-weight:900}.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:1rem}.leading-5{line-height:1.25rem}.leading-8{line-height:2rem}.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}.\\!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\\,box-shadow\\,background-color\\,border-color\\,transform\\,opacity\\]{transition-property:max-width,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}.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:13px;line-height:19px}.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))}.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\\:max-w-\\[160px\\]:hover{max-width:160px}.hover\\:max-w-\\[480px\\]:hover{max-width:480px}.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}.hover\\:shadow-xl:hover{--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)}.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\\: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-50:disabled{opacity:.5}.group:hover .group-hover\\: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:hover .group-hover\\:opacity-100{opacity:1}.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:1rem;padding-right:1rem}.group.toaster .group-\\[\\.toaster\\]\\:py-3{padding-top:.75rem;padding-bottom:.75rem}.group.toast .group-\\[\\.toast\\]\\:text-sm{font-size:13px;line-height:19px}.group.toast .group-\\[\\.toast\\]\\:text-xs{font-size:12px;line-height:16px}.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:.625rem}.sm\\:p-5{padding:1.25rem}.sm\\:p-6{padding:1.5rem}.sm\\:text-2xl{font-size:26px;line-height:34px}.sm\\:text-\\[2\\.1rem\\]{font-size:2.1rem}}@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:1rem}.\\[\\&\\>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))}`;
37260
38058
  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}";
37261
- const contentPageCSS = `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='%2300AD57' stroke='%23ffffff' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E") 3 29,crosshair!important}body.issue-sticker-mode-active .issue-sticker-marker{cursor:default!important}body.issue-sticker-mode-active button,body.issue-sticker-mode-active a,body.issue-sticker-mode-active input,body.issue-sticker-mode-active textarea,body.issue-sticker-mode-active select{cursor:pointer!important}.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}`;
38059
+ const contentPageCSS = `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' stroke='%23ffffff' stroke-width='2' stroke-linejoin='round'/%3E%3C/svg%3E") 3 29,crosshair!important}body.issue-sticker-mode-active .issue-sticker-marker{cursor:default!important}body.issue-sticker-mode-active button,body.issue-sticker-mode-active a,body.issue-sticker-mode-active input,body.issue-sticker-mode-active textarea,body.issue-sticker-mode-active select{cursor:pointer!important}.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}`;
37262
38060
  const PAGE_STYLE_ID = "issue-sticker-page-style";
37263
38061
  let root = null;
37264
38062
  let mountContainer = null;