@campfire-interactive/shell-header 0.13.2 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -198,10 +198,22 @@ interface BugReportPayload {
198
198
  * The host should also call installBugReportCapture() at app boot so the
199
199
  * console/network ring buffers have content by the time a bug is filed.
200
200
  */
201
+ /** What `onSubmit` may return so the success screen can link the new issue.
202
+ * Returning nothing is fine — the modal then just shows a thank-you. */
203
+ interface BugReportSubmitResult {
204
+ /** Permalink to the created issue (opens in a new tab; copyable). Hosts
205
+ * typically build `<issuesUrl base>/<created id>`. */
206
+ issueUrl?: string;
207
+ }
201
208
  interface BugReportConfig {
202
209
  context: BugReportContext;
203
- /** Rejection keeps the modal open and shows the error message. */
204
- onSubmit: (report: BugReportPayload) => Promise<void>;
210
+ /**
211
+ * Persist the report (host owns the transport — typically dms-client).
212
+ * Return the created issue's permalink as `{ issueUrl }` to light up the
213
+ * "view it here" link on the success screen; returning void just shows a
214
+ * thank-you. Rejection keeps the modal open and shows the error message.
215
+ */
216
+ onSubmit: (report: BugReportPayload) => Promise<void | BugReportSubmitResult>;
205
217
  }
206
218
  /**
207
219
  * Subset of the platform-notifications `Notification` shape that the bell UI
@@ -382,4 +394,4 @@ declare function getEnvSegment(host: string): string;
382
394
  */
383
395
  declare function getAppUrl(app: AppDefinition): string;
384
396
 
385
- export { type AboutInfo, type AppDefinition, type BugReportConfig, type BugReportContext, type BugReportPayload, type CurrencyOption, type LocaleOption, LocaleSwitcher, type NotificationItem, ShellHeader, type ShellHeaderProps, type ShellUser, type VersionInfo, appCatalog, getAppUrl, getEnvSegment, installBugReportCapture };
397
+ export { type AboutInfo, type AppDefinition, type BugReportConfig, type BugReportContext, type BugReportPayload, type BugReportSubmitResult, type CurrencyOption, type LocaleOption, LocaleSwitcher, type NotificationItem, ShellHeader, type ShellHeaderProps, type ShellUser, type VersionInfo, appCatalog, getAppUrl, getEnvSegment, installBugReportCapture };
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ function styleInject(css, { insertAt } = {}) {
24
24
  }
25
25
 
26
26
  // src/styles.css
27
- styleInject(".cfi-sh-header {\n display: flex;\n align-items: center;\n height: var(--cfi-shell-header-height, 48px);\n padding: 0 var(--cfi-spacing-md, 1rem);\n background: white;\n color: var(--cfi-color-gray-900, #111827);\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n position: relative;\n z-index: 1000;\n}\n.cfi-sh-left {\n display: flex;\n align-items: center;\n flex: 1;\n gap: var(--cfi-spacing-md, 1rem);\n overflow: hidden;\n}\n.cfi-sh-app-brand {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n color: white;\n font-size: 14px;\n font-weight: 700;\n font-family: inherit;\n border-radius: var(--cfi-radius-md, 0.375rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-base, 1rem);\n color: var(--cfi-color-gray-900, #111827);\n white-space: nowrap;\n}\n.cfi-sh-suite-logo {\n height: 22px;\n width: auto;\n display: block;\n}\n.cfi-sh-right {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n flex-shrink: 0;\n}\n.cfi-sh-icon-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: transparent;\n border: none;\n border-radius: 50%;\n color: var(--cfi-color-gray-600, #4b5563);\n cursor: pointer;\n transition: background 150ms;\n}\n.cfi-sh-icon-btn:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--cfi-color-error, #ef4444);\n color: white;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n border-radius: 99px;\n}\n.cfi-sh-app-switcher {\n position: relative;\n}\n.cfi-sh-app-grid {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem);\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n min-width: 280px;\n}\n.cfi-sh-app-grid-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-xs, 0.25rem);\n border-radius: var(--cfi-radius-md, 0.375rem);\n color: var(--cfi-color-gray-700, #374151);\n text-decoration: none;\n cursor: pointer;\n transition: background 100ms;\n font-family: inherit;\n}\n.cfi-sh-app-grid-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-app-grid-item-active {\n background: var(--cfi-color-primary-50, #fff7ed);\n color: var(--cfi-color-primary-700, #c2410c);\n}\n.cfi-sh-app-grid-item-active:hover {\n background: var(--cfi-color-primary-100, #ffedd5);\n}\n.cfi-sh-app-grid-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n}\n.cfi-sh-app-grid-label {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-align: center;\n line-height: 1.35;\n max-width: 80px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n white-space: normal;\n overflow: hidden;\n min-height: 2.7em;\n}\n.cfi-sh-user-menu {\n position: relative;\n}\n.cfi-sh-avatar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: var(--cfi-color-primary-600, #ea580c);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: opacity 150ms;\n}\n.cfi-sh-avatar-btn:hover {\n opacity: 0.85;\n}\n.cfi-sh-avatar-img {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n object-fit: cover;\n}\n.cfi-sh-avatar-initials {\n color: white;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n font-family: inherit;\n}\n.cfi-sh-user-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n min-width: 200px;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n}\n.cfi-sh-user-header {\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n}\n.cfi-sh-user-name {\n font-weight: 500;\n color: var(--cfi-color-gray-900, #111827);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-user-email {\n color: var(--cfi-color-gray-500, #6b7280);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n}\n.cfi-sh-divider {\n height: 1px;\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-menu-item {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n width: 100%;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n background: none;\n border: none;\n color: var(--cfi-color-gray-700, #374151);\n cursor: pointer;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-menu-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-menu-item:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-sh-locale-switcher {\n position: relative;\n}\n.cfi-sh-locale-btn {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n height: 32px;\n padding: 0 var(--cfi-spacing-sm, 0.5rem);\n background: transparent;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 0.375rem);\n color: var(--cfi-color-gray-700, #374151);\n cursor: pointer;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-locale-btn:hover:not(:disabled) {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-locale-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-sh-locale-label {\n letter-spacing: 0.02em;\n}\n.cfi-sh-locale-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n min-width: 180px;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n padding: var(--cfi-spacing-xs, 0.25rem) 0;\n}\n.cfi-sh-locale-dropdown .cfi-sh-menu-item {\n justify-content: space-between;\n}\n.cfi-sh-locale-item-active {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-locale-item-label {\n flex: 1;\n text-align: left;\n}\n.cfi-sh-locale-item-code {\n color: var(--cfi-color-gray-400, #9ca3af);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n letter-spacing: 0.02em;\n}\n.cfi-sh-locale-row {\n justify-content: flex-start;\n}\n.cfi-sh-locale-row-label {\n flex: 1;\n text-align: left;\n}\n.cfi-sh-locale-row-current {\n color: var(--cfi-color-gray-500, #6b7280);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n margin-right: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-locale-chevron {\n transition: transform 150ms ease;\n flex-shrink: 0;\n}\n.cfi-sh-locale-chevron-open {\n transform: rotate(180deg);\n}\n.cfi-sh-locale-sublist {\n border-top: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-sh-locale-sub-item {\n padding-left: calc(var(--cfi-spacing-md, 1rem) + var(--cfi-spacing-md, 1rem));\n justify-content: space-between;\n}\n.cfi-sh-tenant-static {\n cursor: default;\n pointer-events: none;\n}\n.cfi-sh-tenant-check {\n color: var(--cfi-color-violet-600, #7c3aed);\n}\n.cfi-sh-notif {\n position: relative;\n}\n.cfi-sh-notif-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n width: 360px;\n max-height: 480px;\n display: flex;\n flex-direction: column;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n overflow: hidden;\n}\n.cfi-sh-notif-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n flex-shrink: 0;\n}\n.cfi-sh-notif-title {\n font-weight: 600;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-notif-mark-all {\n background: none;\n border: none;\n color: var(--cfi-color-primary-600, #ea580c);\n cursor: pointer;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-family: inherit;\n padding: 0;\n}\n.cfi-sh-notif-mark-all:hover {\n text-decoration: underline;\n}\n.cfi-sh-notif-list {\n overflow-y: auto;\n flex: 1;\n}\n.cfi-sh-notif-empty {\n padding: var(--cfi-spacing-lg, 1.5rem) var(--cfi-spacing-md, 1rem);\n color: var(--cfi-color-gray-500, #6b7280);\n text-align: center;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-notif-item {\n display: flex;\n align-items: flex-start;\n gap: var(--cfi-spacing-sm, 0.5rem);\n width: 100%;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n background: none;\n border: none;\n border-bottom: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n text-align: left;\n cursor: pointer;\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-notif-item:hover {\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-sh-notif-item:last-child {\n border-bottom: none;\n}\n.cfi-sh-notif-dot {\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n background: var(--cfi-color-primary-600, #ea580c);\n border-radius: 50%;\n}\n.cfi-sh-notif-dot-placeholder {\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n}\n.cfi-sh-notif-content {\n flex: 1;\n min-width: 0;\n}\n.cfi-sh-notif-item-title {\n font-weight: 500;\n color: var(--cfi-color-gray-900, #111827);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n margin-bottom: 2px;\n}\n.cfi-sh-notif-item-unread .cfi-sh-notif-item-title {\n font-weight: 600;\n}\n.cfi-sh-notif-item-body {\n color: var(--cfi-color-gray-600, #4b5563);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.cfi-sh-notif-item-time {\n color: var(--cfi-color-gray-400, #9ca3af);\n font-size: 11px;\n margin-top: 4px;\n}\n.cfi-sh-about-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1100;\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n}\n.cfi-sh-about-card {\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n min-width: 360px;\n max-width: 500px;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-header {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-about-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-lg, 1.125rem);\n flex: 1;\n}\n.cfi-sh-about-env {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n padding: 2px 8px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n font-weight: 600;\n}\n.cfi-sh-about-close {\n background: none;\n border: none;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n color: var(--cfi-color-gray-500, #6b7280);\n padding: 0 4px;\n font-family: inherit;\n}\n.cfi-sh-about-close:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-body {\n padding: var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 1rem);\n}\n.cfi-sh-about-section-title {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n margin-bottom: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-about-list {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: var(--cfi-spacing-xs, 0.25rem) var(--cfi-spacing-md, 1rem);\n margin: 0;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-about-list dt {\n color: var(--cfi-color-gray-600, #4b5563);\n font-weight: 500;\n}\n.cfi-sh-about-list dd {\n margin: 0;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-list code {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Consolas,\n monospace;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n background: var(--cfi-color-gray-100, #f3f4f6);\n padding: 1px 6px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n}\n.cfi-sh-about-date {\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-about-footer {\n display: flex;\n justify-content: flex-end;\n padding: var(--cfi-spacing-md, 1rem);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-about-copy {\n background: var(--cfi-color-gray-100, #f3f4f6);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n padding: 6px 12px;\n border-radius: var(--cfi-radius-md, 0.375rem);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 150ms;\n}\n.cfi-sh-about-copy:hover {\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1100;\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n}\n.cfi-sh-bug-card {\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n width: 480px;\n max-width: calc(100vw - 32px);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n}\n.cfi-sh-bug-card-wide {\n width: min(1100px, calc(100vw - 64px));\n}\n.cfi-sh-bug-header {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-lg, 1.125rem);\n flex: 1;\n}\n.cfi-sh-bug-env {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n padding: 2px 8px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n font-weight: 600;\n}\n.cfi-sh-bug-close {\n background: none;\n border: none;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n color: var(--cfi-color-gray-500, #6b7280);\n padding: 0 4px;\n font-family: inherit;\n}\n.cfi-sh-bug-close:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-bug-body {\n padding: var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 0.5rem);\n}\n.cfi-sh-bug-label {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-input,\n.cfi-sh-bug-textarea {\n font-family: inherit;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n color: var(--cfi-color-gray-900, #111827);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 0.375rem);\n padding: 8px 10px;\n outline: none;\n}\n.cfi-sh-bug-input:focus,\n.cfi-sh-bug-textarea:focus {\n border-color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-textarea {\n resize: vertical;\n min-height: 72px;\n}\n.cfi-sh-bug-shot {\n display: flex;\n align-items: flex-start;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-wrap: wrap;\n padding-top: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-thumb {\n max-width: 200px;\n max-height: 120px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-sm, 0.25rem);\n display: block;\n}\n.cfi-sh-bug-shot-actions {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-files {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding-top: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-file-row {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n max-width: 100%;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-sh-bug-file-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.cfi-sh-bug-file-size {\n flex-shrink: 0;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-file-remove {\n flex-shrink: 0;\n border: none;\n background: none;\n padding: 0 0.25rem;\n cursor: pointer;\n font-size: var(--cfi-font-size-md, 1rem);\n line-height: 1;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-file-remove:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-bug-meta {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--cfi-spacing-sm, 0.5rem);\n}\n.cfi-sh-bug-modes {\n display: flex;\n gap: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-hint {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-canvas-wrap {\n overflow: auto;\n max-height: 65vh;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-sm, 0.25rem);\n background: var(--cfi-color-gray-100, #f3f4f6);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.cfi-sh-bug-canvas {\n max-width: 100%;\n max-height: 65vh;\n cursor: crosshair;\n touch-action: none;\n display: block;\n}\n.cfi-sh-bug-footer {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-btn {\n background: var(--cfi-color-gray-100, #f3f4f6);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n padding: 6px 12px;\n border-radius: var(--cfi-radius-md, 0.375rem);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 150ms;\n}\n.cfi-sh-bug-btn:hover {\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-btn:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.cfi-sh-bug-btn-primary {\n background: var(--cfi-color-gray-900, #111827);\n border-color: var(--cfi-color-gray-900, #111827);\n color: white;\n}\n.cfi-sh-bug-btn-primary:hover:not(:disabled) {\n background: var(--cfi-color-gray-700, #374151);\n}\n.cfi-sh-bug-btn-active {\n background: var(--cfi-color-gray-900, #111827);\n border-color: var(--cfi-color-gray-900, #111827);\n color: white;\n}\n.cfi-sh-bug-error {\n color: var(--cfi-color-red-600, #dc2626);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n margin-right: auto;\n}\n.cfi-sh-bug-success {\n color: var(--cfi-color-green-600, #16a34a);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n}\n.cfi-sh-bug-issues-link {\n color: var(--cfi-color-gray-600, #4b5563);\n text-decoration: underline;\n}\n.cfi-sh-bug-issues-link:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n");
27
+ styleInject(".cfi-sh-header {\n display: flex;\n align-items: center;\n height: var(--cfi-shell-header-height, 48px);\n padding: 0 var(--cfi-spacing-md, 1rem);\n background: white;\n color: var(--cfi-color-gray-900, #111827);\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n position: relative;\n z-index: 1000;\n}\n.cfi-sh-left {\n display: flex;\n align-items: center;\n flex: 1;\n gap: var(--cfi-spacing-md, 1rem);\n overflow: hidden;\n}\n.cfi-sh-app-brand {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n color: white;\n font-size: 14px;\n font-weight: 700;\n font-family: inherit;\n border-radius: var(--cfi-radius-md, 0.375rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-base, 1rem);\n color: var(--cfi-color-gray-900, #111827);\n white-space: nowrap;\n}\n.cfi-sh-suite-logo {\n height: 22px;\n width: auto;\n display: block;\n}\n.cfi-sh-right {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n flex-shrink: 0;\n}\n.cfi-sh-icon-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: transparent;\n border: none;\n border-radius: 50%;\n color: var(--cfi-color-gray-600, #4b5563);\n cursor: pointer;\n transition: background 150ms;\n}\n.cfi-sh-icon-btn:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--cfi-color-error, #ef4444);\n color: white;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n border-radius: 99px;\n}\n.cfi-sh-app-switcher {\n position: relative;\n}\n.cfi-sh-app-grid {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem);\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n min-width: 280px;\n}\n.cfi-sh-app-grid-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-xs, 0.25rem);\n border-radius: var(--cfi-radius-md, 0.375rem);\n color: var(--cfi-color-gray-700, #374151);\n text-decoration: none;\n cursor: pointer;\n transition: background 100ms;\n font-family: inherit;\n}\n.cfi-sh-app-grid-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-app-grid-item-active {\n background: var(--cfi-color-primary-50, #fff7ed);\n color: var(--cfi-color-primary-700, #c2410c);\n}\n.cfi-sh-app-grid-item-active:hover {\n background: var(--cfi-color-primary-100, #ffedd5);\n}\n.cfi-sh-app-grid-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n}\n.cfi-sh-app-grid-label {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-align: center;\n line-height: 1.35;\n max-width: 80px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n white-space: normal;\n overflow: hidden;\n min-height: 2.7em;\n}\n.cfi-sh-user-menu {\n position: relative;\n}\n.cfi-sh-avatar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: var(--cfi-color-primary-600, #ea580c);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: opacity 150ms;\n}\n.cfi-sh-avatar-btn:hover {\n opacity: 0.85;\n}\n.cfi-sh-avatar-img {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n object-fit: cover;\n}\n.cfi-sh-avatar-initials {\n color: white;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n font-family: inherit;\n}\n.cfi-sh-user-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n min-width: 200px;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n}\n.cfi-sh-user-header {\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n}\n.cfi-sh-user-name {\n font-weight: 500;\n color: var(--cfi-color-gray-900, #111827);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-user-email {\n color: var(--cfi-color-gray-500, #6b7280);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n}\n.cfi-sh-divider {\n height: 1px;\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-menu-item {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n width: 100%;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n background: none;\n border: none;\n color: var(--cfi-color-gray-700, #374151);\n cursor: pointer;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-menu-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-menu-item:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-sh-locale-switcher {\n position: relative;\n}\n.cfi-sh-locale-btn {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n height: 32px;\n padding: 0 var(--cfi-spacing-sm, 0.5rem);\n background: transparent;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-md, 0.375rem);\n color: var(--cfi-color-gray-700, #374151);\n cursor: pointer;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-locale-btn:hover:not(:disabled) {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-locale-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.cfi-sh-locale-label {\n letter-spacing: 0.02em;\n}\n.cfi-sh-locale-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n min-width: 180px;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n padding: var(--cfi-spacing-xs, 0.25rem) 0;\n}\n.cfi-sh-locale-dropdown .cfi-sh-menu-item {\n justify-content: space-between;\n}\n.cfi-sh-locale-item-active {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-locale-item-label {\n flex: 1;\n text-align: left;\n}\n.cfi-sh-locale-item-code {\n color: var(--cfi-color-gray-400, #9ca3af);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n letter-spacing: 0.02em;\n}\n.cfi-sh-locale-row {\n justify-content: flex-start;\n}\n.cfi-sh-locale-row-label {\n flex: 1;\n text-align: left;\n}\n.cfi-sh-locale-row-current {\n color: var(--cfi-color-gray-500, #6b7280);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n margin-right: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-locale-chevron {\n transition: transform 150ms ease;\n flex-shrink: 0;\n}\n.cfi-sh-locale-chevron-open {\n transform: rotate(180deg);\n}\n.cfi-sh-locale-sublist {\n border-top: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-sh-locale-sub-item {\n padding-left: calc(var(--cfi-spacing-md, 1rem) + var(--cfi-spacing-md, 1rem));\n justify-content: space-between;\n}\n.cfi-sh-tenant-static {\n cursor: default;\n pointer-events: none;\n}\n.cfi-sh-tenant-check {\n color: var(--cfi-color-violet-600, #7c3aed);\n}\n.cfi-sh-notif {\n position: relative;\n}\n.cfi-sh-notif-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n width: 360px;\n max-height: 480px;\n display: flex;\n flex-direction: column;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n overflow: hidden;\n}\n.cfi-sh-notif-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n flex-shrink: 0;\n}\n.cfi-sh-notif-title {\n font-weight: 600;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-notif-mark-all {\n background: none;\n border: none;\n color: var(--cfi-color-primary-600, #ea580c);\n cursor: pointer;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-family: inherit;\n padding: 0;\n}\n.cfi-sh-notif-mark-all:hover {\n text-decoration: underline;\n}\n.cfi-sh-notif-list {\n overflow-y: auto;\n flex: 1;\n}\n.cfi-sh-notif-empty {\n padding: var(--cfi-spacing-lg, 1.5rem) var(--cfi-spacing-md, 1rem);\n color: var(--cfi-color-gray-500, #6b7280);\n text-align: center;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-notif-item {\n display: flex;\n align-items: flex-start;\n gap: var(--cfi-spacing-sm, 0.5rem);\n width: 100%;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n background: none;\n border: none;\n border-bottom: 1px solid var(--cfi-color-gray-100, #f3f4f6);\n text-align: left;\n cursor: pointer;\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-notif-item:hover {\n background: var(--cfi-color-gray-50, #f9fafb);\n}\n.cfi-sh-notif-item:last-child {\n border-bottom: none;\n}\n.cfi-sh-notif-dot {\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n background: var(--cfi-color-primary-600, #ea580c);\n border-radius: 50%;\n}\n.cfi-sh-notif-dot-placeholder {\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n margin-top: 6px;\n}\n.cfi-sh-notif-content {\n flex: 1;\n min-width: 0;\n}\n.cfi-sh-notif-item-title {\n font-weight: 500;\n color: var(--cfi-color-gray-900, #111827);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n margin-bottom: 2px;\n}\n.cfi-sh-notif-item-unread .cfi-sh-notif-item-title {\n font-weight: 600;\n}\n.cfi-sh-notif-item-body {\n color: var(--cfi-color-gray-600, #4b5563);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n line-height: 1.4;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n}\n.cfi-sh-notif-item-time {\n color: var(--cfi-color-gray-400, #9ca3af);\n font-size: 11px;\n margin-top: 4px;\n}\n.cfi-sh-about-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1100;\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n}\n.cfi-sh-about-card {\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n min-width: 360px;\n max-width: 500px;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-header {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-about-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-lg, 1.125rem);\n flex: 1;\n}\n.cfi-sh-about-env {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n padding: 2px 8px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n font-weight: 600;\n}\n.cfi-sh-about-close {\n background: none;\n border: none;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n color: var(--cfi-color-gray-500, #6b7280);\n padding: 0 4px;\n font-family: inherit;\n}\n.cfi-sh-about-close:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-body {\n padding: var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-md, 1rem);\n}\n.cfi-sh-about-section-title {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n margin-bottom: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-about-list {\n display: grid;\n grid-template-columns: auto 1fr;\n gap: var(--cfi-spacing-xs, 0.25rem) var(--cfi-spacing-md, 1rem);\n margin: 0;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-about-list dt {\n color: var(--cfi-color-gray-600, #4b5563);\n font-weight: 500;\n}\n.cfi-sh-about-list dd {\n margin: 0;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-about-list code {\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Consolas,\n monospace;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n background: var(--cfi-color-gray-100, #f3f4f6);\n padding: 1px 6px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n}\n.cfi-sh-about-date {\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-about-footer {\n display: flex;\n justify-content: flex-end;\n padding: var(--cfi-spacing-md, 1rem);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-about-copy {\n background: var(--cfi-color-gray-100, #f3f4f6);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n padding: 6px 12px;\n border-radius: var(--cfi-radius-md, 0.375rem);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 150ms;\n}\n.cfi-sh-about-copy:hover {\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-overlay {\n position: fixed;\n inset: 0;\n background: rgba(0, 0, 0, 0.4);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1100;\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n}\n.cfi-sh-bug-card {\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);\n width: 480px;\n max-width: calc(100vw - 32px);\n color: var(--cfi-color-gray-900, #111827);\n display: flex;\n flex-direction: column;\n}\n.cfi-sh-bug-card-wide {\n width: min(1100px, calc(100vw - 64px));\n}\n.cfi-sh-bug-header {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-lg, 1.125rem);\n flex: 1;\n}\n.cfi-sh-bug-env {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-700, #374151);\n padding: 2px 8px;\n border-radius: var(--cfi-radius-sm, 0.25rem);\n font-weight: 600;\n}\n.cfi-sh-bug-close {\n background: none;\n border: none;\n font-size: 1.5rem;\n line-height: 1;\n cursor: pointer;\n color: var(--cfi-color-gray-500, #6b7280);\n padding: 0 4px;\n font-family: inherit;\n}\n.cfi-sh-bug-close:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-bug-body {\n padding: var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-sm, 0.5rem);\n}\n.cfi-sh-bug-label {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n font-weight: 600;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-input,\n.cfi-sh-bug-textarea {\n font-family: inherit;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n color: var(--cfi-color-gray-900, #111827);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 0.375rem);\n padding: 8px 10px;\n outline: none;\n}\n.cfi-sh-bug-input:focus,\n.cfi-sh-bug-textarea:focus {\n border-color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-textarea {\n resize: vertical;\n min-height: 72px;\n}\n.cfi-sh-bug-shot {\n display: flex;\n align-items: flex-start;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-wrap: wrap;\n padding-top: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-thumb {\n max-width: 200px;\n max-height: 120px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-sm, 0.25rem);\n display: block;\n}\n.cfi-sh-bug-shot-actions {\n display: flex;\n flex-direction: column;\n gap: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-files {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding-top: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-file-row {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n max-width: 100%;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n color: var(--cfi-color-gray-700, #374151);\n}\n.cfi-sh-bug-file-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.cfi-sh-bug-file-size {\n flex-shrink: 0;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-file-remove {\n flex-shrink: 0;\n border: none;\n background: none;\n padding: 0 0.25rem;\n cursor: pointer;\n font-size: var(--cfi-font-size-md, 1rem);\n line-height: 1;\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-file-remove:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-bug-meta {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--cfi-spacing-sm, 0.5rem);\n}\n.cfi-sh-bug-modes {\n display: flex;\n gap: var(--cfi-spacing-xs, 0.25rem);\n}\n.cfi-sh-bug-hint {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n color: var(--cfi-color-gray-500, #6b7280);\n}\n.cfi-sh-bug-canvas-wrap {\n overflow: auto;\n max-height: 65vh;\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n border-radius: var(--cfi-radius-sm, 0.25rem);\n background: var(--cfi-color-gray-100, #f3f4f6);\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.cfi-sh-bug-canvas {\n max-width: 100%;\n max-height: 65vh;\n cursor: crosshair;\n touch-action: none;\n display: block;\n}\n.cfi-sh-bug-footer {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n padding: var(--cfi-spacing-md, 1rem);\n border-top: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-btn {\n background: var(--cfi-color-gray-100, #f3f4f6);\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n color: var(--cfi-color-gray-900, #111827);\n padding: 6px 12px;\n border-radius: var(--cfi-radius-md, 0.375rem);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n cursor: pointer;\n font-family: inherit;\n transition: background 150ms;\n}\n.cfi-sh-bug-btn:hover {\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-bug-btn:disabled {\n opacity: 0.5;\n cursor: default;\n}\n.cfi-sh-bug-btn-primary {\n background: var(--cfi-color-gray-900, #111827);\n border-color: var(--cfi-color-gray-900, #111827);\n color: white;\n}\n.cfi-sh-bug-btn-primary:hover:not(:disabled) {\n background: var(--cfi-color-gray-700, #374151);\n}\n.cfi-sh-bug-btn-active {\n background: var(--cfi-color-gray-900, #111827);\n border-color: var(--cfi-color-gray-900, #111827);\n color: white;\n}\n.cfi-sh-bug-error {\n color: var(--cfi-color-red-600, #dc2626);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n margin-right: auto;\n}\n.cfi-sh-bug-success {\n color: var(--cfi-color-green-600, #16a34a);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-weight: 500;\n}\n.cfi-sh-bug-done {\n gap: var(--cfi-spacing-md, 1rem);\n}\n.cfi-sh-bug-done-msg {\n margin: 0;\n font-size: var(--cfi-font-size-base, 1rem);\n font-weight: 600;\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-bug-done-link {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-wrap: wrap;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n color: var(--cfi-color-gray-600, #4b5563);\n}\n.cfi-sh-bug-done-url {\n color: var(--cfi-color-primary-600, #2563eb);\n text-decoration: underline;\n overflow-wrap: anywhere;\n}\n.cfi-sh-bug-copy-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 4px;\n border: 1px solid var(--cfi-color-gray-300, #d1d5db);\n border-radius: var(--cfi-radius-md, 0.375rem);\n background: white;\n color: var(--cfi-color-gray-600, #4b5563);\n cursor: pointer;\n line-height: 0;\n}\n.cfi-sh-bug-copy-btn:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n color: var(--cfi-color-gray-900, #111827);\n}\n.cfi-sh-bug-issues-link {\n color: var(--cfi-color-gray-600, #4b5563);\n text-decoration: underline;\n}\n.cfi-sh-bug-issues-link:hover {\n color: var(--cfi-color-gray-900, #111827);\n}\n");
28
28
 
29
29
  // src/appCatalog.ts
30
30
  var appCatalog = [
@@ -751,6 +751,7 @@ function useAboutShortcut(enabled) {
751
751
 
752
752
  // src/BugReportModal.tsx
753
753
  import { useCallback, useEffect as useEffect6, useRef as useRef4, useState as useState6 } from "react";
754
+ import { Check as Check2, Copy } from "lucide-react";
754
755
 
755
756
  // src/captureScreenshot.ts
756
757
  async function captureTabScreenshot() {
@@ -892,6 +893,8 @@ function BugReportModal({ config, initialScreenshot, onClose }) {
892
893
  const [captureError, setCaptureError] = useState6(null);
893
894
  const [submitState, setSubmitState] = useState6("idle");
894
895
  const [submitError, setSubmitError] = useState6(null);
896
+ const [issueUrl, setIssueUrl] = useState6(null);
897
+ const [linkCopied, setLinkCopied] = useState6(false);
895
898
  const workCanvasRef = useRef4(null);
896
899
  const originalRef = useRef4(null);
897
900
  const displayCanvasRef = useRef4(null);
@@ -1097,12 +1100,9 @@ function BugReportModal({ config, initialScreenshot, onClose }) {
1097
1100
  attachments
1098
1101
  };
1099
1102
  try {
1100
- await config.onSubmit(payload);
1103
+ const result = await config.onSubmit(payload);
1104
+ setIssueUrl(result && typeof result === "object" ? result.issueUrl ?? null : null);
1101
1105
  setSubmitState("success");
1102
- window.setTimeout(() => {
1103
- if (screenshot) URL.revokeObjectURL(screenshot.previewUrl);
1104
- onClose();
1105
- }, 1500);
1106
1106
  } catch (err) {
1107
1107
  setSubmitState("error");
1108
1108
  setSubmitError(err instanceof Error ? err.message : "Submitting the report failed");
@@ -1120,11 +1120,53 @@ function BugReportModal({ config, initialScreenshot, onClose }) {
1120
1120
  onFocus: (e) => e.stopPropagation(),
1121
1121
  children: /* @__PURE__ */ jsxs6("div", { className: `cfi-sh-bug-card${view === "editor" ? " cfi-sh-bug-card-wide" : ""}`, children: [
1122
1122
  /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-header", children: [
1123
- /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-title", children: view === "editor" ? "New Issue - Attach Screenshot (Optional)" : "Report an issue" }),
1123
+ /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-title", children: submitState === "success" ? "Issue submitted" : view === "editor" ? "New Issue - Attach Screenshot (Optional)" : "Report an issue" }),
1124
1124
  /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-env", children: config.context.environment }),
1125
1125
  /* @__PURE__ */ jsx6("button", { className: "cfi-sh-bug-close", type: "button", onClick: closeUnlessBusy, "aria-label": "Close", children: "\xD7" })
1126
1126
  ] }),
1127
- view === "editor" ? /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-body", children: [
1127
+ submitState === "success" ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
1128
+ /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-body cfi-sh-bug-done", children: [
1129
+ /* @__PURE__ */ jsx6("p", { className: "cfi-sh-bug-done-msg", children: "Thanks for submitting this issue." }),
1130
+ issueUrl ? /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-done-link", children: [
1131
+ /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-done-label", children: "You can view it here:" }),
1132
+ /* @__PURE__ */ jsx6(
1133
+ "a",
1134
+ {
1135
+ href: issueUrl,
1136
+ target: "_blank",
1137
+ rel: "noreferrer",
1138
+ className: "cfi-sh-bug-done-url",
1139
+ children: issueUrl
1140
+ }
1141
+ ),
1142
+ /* @__PURE__ */ jsx6(
1143
+ "button",
1144
+ {
1145
+ type: "button",
1146
+ className: "cfi-sh-bug-copy-btn",
1147
+ title: "Copy link",
1148
+ "aria-label": "Copy link",
1149
+ onClick: () => {
1150
+ void navigator.clipboard.writeText(issueUrl).then(() => {
1151
+ setLinkCopied(true);
1152
+ window.setTimeout(() => setLinkCopied(false), 1500);
1153
+ });
1154
+ },
1155
+ children: linkCopied ? /* @__PURE__ */ jsx6(Check2, { size: 16 }) : /* @__PURE__ */ jsx6(Copy, { size: 16 })
1156
+ }
1157
+ )
1158
+ ] }) : null
1159
+ ] }),
1160
+ /* @__PURE__ */ jsx6("div", { className: "cfi-sh-bug-footer", children: /* @__PURE__ */ jsx6(
1161
+ "button",
1162
+ {
1163
+ type: "button",
1164
+ className: "cfi-sh-bug-btn cfi-sh-bug-btn-primary",
1165
+ onClick: closeUnlessBusy,
1166
+ children: "OK"
1167
+ }
1168
+ ) })
1169
+ ] }) : view === "editor" ? /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-body", children: [
1128
1170
  /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-toolbar", children: [
1129
1171
  /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-modes", children: [
1130
1172
  /* @__PURE__ */ jsx6(
@@ -1252,36 +1294,19 @@ function BugReportModal({ config, initialScreenshot, onClose }) {
1252
1294
  ] })
1253
1295
  ] })
1254
1296
  ] }),
1255
- view === "form" && /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-footer", children: [
1297
+ view === "form" && submitState !== "success" && /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-footer", children: [
1256
1298
  submitState === "error" && submitError && /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-error", children: submitError }),
1257
- submitState === "success" ? /* @__PURE__ */ jsxs6("span", { className: "cfi-sh-bug-success", children: [
1258
- "Report submitted \u2014 thank you!",
1259
- config.context.issuesUrl && /* @__PURE__ */ jsxs6(Fragment3, { children: [
1260
- " ",
1261
- /* @__PURE__ */ jsx6(
1262
- "a",
1263
- {
1264
- className: "cfi-sh-bug-issues-link",
1265
- href: config.context.issuesUrl,
1266
- target: "_blank",
1267
- rel: "noreferrer",
1268
- children: "View it on the issues page"
1269
- }
1270
- )
1271
- ] })
1272
- ] }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
1273
- /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: closeUnlessBusy, children: "Cancel" }),
1274
- /* @__PURE__ */ jsx6(
1275
- "button",
1276
- {
1277
- type: "button",
1278
- className: "cfi-sh-bug-btn cfi-sh-bug-btn-primary",
1279
- onClick: handleSubmit,
1280
- disabled: !title.trim() || submitState === "submitting",
1281
- children: submitState === "submitting" ? "Submitting\u2026" : "Submit report"
1282
- }
1283
- )
1284
- ] })
1299
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: closeUnlessBusy, children: "Cancel" }),
1300
+ /* @__PURE__ */ jsx6(
1301
+ "button",
1302
+ {
1303
+ type: "button",
1304
+ className: "cfi-sh-bug-btn cfi-sh-bug-btn-primary",
1305
+ onClick: handleSubmit,
1306
+ disabled: !title.trim() || submitState === "submitting",
1307
+ children: submitState === "submitting" ? "Submitting\u2026" : "Submit report"
1308
+ }
1309
+ )
1285
1310
  ] })
1286
1311
  ] })
1287
1312
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campfire-interactive/shell-header",
3
- "version": "0.13.2",
3
+ "version": "0.14.0",
4
4
  "description": "Shared shell header with app switcher for Campfire Suite",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",