@campfire-interactive/shell-header 0.15.1 → 0.15.3

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.
Files changed (2) hide show
  1. package/dist/index.js +256 -180
  2. package/package.json +1 -1
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 text-align: left;\n text-decoration: none;\n box-sizing: border-box;\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");
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 text-align: left;\n text-decoration: none;\n box-sizing: border-box;\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 cursor: grab;\n touch-action: none;\n user-select: none;\n -webkit-user-select: none;\n}\n.cfi-sh-bug-header:active {\n cursor: grabbing;\n}\n.cfi-sh-bug-header .cfi-sh-bug-close {\n cursor: pointer;\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 = [
@@ -843,8 +843,13 @@ async function captureTabScreenshot() {
843
843
  var MAX_ENTRIES = 50;
844
844
  var MAX_MESSAGE_CHARS = 500;
845
845
  var consoleBuffer = [];
846
- var networkBuffer = [];
846
+ var networkFailureBuffer = [];
847
+ var networkSuccessBuffer = [];
847
848
  var installed = false;
849
+ function stripQuery(url) {
850
+ const i = url.indexOf("?");
851
+ return i === -1 ? url : url.slice(0, i);
852
+ }
848
853
  function push(buffer, entry) {
849
854
  buffer.push(entry);
850
855
  if (buffer.length > MAX_ENTRIES) buffer.shift();
@@ -893,7 +898,7 @@ function installBugReportCapture() {
893
898
  try {
894
899
  const res = await originalFetch(input, init);
895
900
  if (!res.ok) {
896
- push(networkBuffer, {
901
+ push(networkFailureBuffer, {
897
902
  at: (/* @__PURE__ */ new Date()).toISOString(),
898
903
  method: method.toUpperCase(),
899
904
  url,
@@ -901,10 +906,19 @@ function installBugReportCapture() {
901
906
  durationMs: Math.round(performance.now() - started),
902
907
  requestId: res.headers.get("x-request-id") ?? void 0
903
908
  });
909
+ } else {
910
+ push(networkSuccessBuffer, {
911
+ at: (/* @__PURE__ */ new Date()).toISOString(),
912
+ method: method.toUpperCase(),
913
+ url: stripQuery(url),
914
+ status: res.status,
915
+ durationMs: Math.round(performance.now() - started),
916
+ requestId: res.headers.get("x-request-id") ?? void 0
917
+ });
904
918
  }
905
919
  return res;
906
920
  } catch (err) {
907
- push(networkBuffer, {
921
+ push(networkFailureBuffer, {
908
922
  at: (/* @__PURE__ */ new Date()).toISOString(),
909
923
  method: method.toUpperCase(),
910
924
  url,
@@ -916,7 +930,10 @@ function installBugReportCapture() {
916
930
  };
917
931
  }
918
932
  function snapshotBugReportCapture() {
919
- return { console: [...consoleBuffer], network: [...networkBuffer] };
933
+ const network = [...networkFailureBuffer, ...networkSuccessBuffer].sort(
934
+ (a, b) => a.at.localeCompare(b.at)
935
+ );
936
+ return { console: [...consoleBuffer], network };
920
937
  }
921
938
 
922
939
  // src/BugReportModal.tsx
@@ -942,6 +959,40 @@ function BugReportModal({ config, initialScreenshot, onClose }) {
942
959
  const [submitError, setSubmitError] = useState6(null);
943
960
  const [issueUrl, setIssueUrl] = useState6(null);
944
961
  const [linkCopied, setLinkCopied] = useState6(false);
962
+ const cardRef = useRef4(null);
963
+ const [cardOffset, setCardOffset] = useState6({ x: 0, y: 0 });
964
+ const headerDragRef = useRef4(null);
965
+ function onHeaderPointerDown(e) {
966
+ if (e.target.closest("button")) return;
967
+ const card = cardRef.current;
968
+ if (!card) return;
969
+ e.currentTarget.setPointerCapture(e.pointerId);
970
+ headerDragRef.current = {
971
+ pointerId: e.pointerId,
972
+ startX: e.clientX,
973
+ startY: e.clientY,
974
+ baseX: cardOffset.x,
975
+ baseY: cardOffset.y,
976
+ rect: card.getBoundingClientRect()
977
+ };
978
+ }
979
+ function onHeaderPointerMove(e) {
980
+ const d = headerDragRef.current;
981
+ if (!d || d.pointerId !== e.pointerId) return;
982
+ let dx = e.clientX - d.startX;
983
+ let dy = e.clientY - d.startY;
984
+ const minX = 80 - d.rect.right;
985
+ const maxX = window.innerWidth - 80 - d.rect.left;
986
+ const minY = -d.rect.top;
987
+ const maxY = window.innerHeight - 48 - d.rect.top;
988
+ dx = Math.min(Math.max(dx, minX), maxX);
989
+ dy = Math.min(Math.max(dy, minY), maxY);
990
+ setCardOffset({ x: d.baseX + dx, y: d.baseY + dy });
991
+ }
992
+ function onHeaderPointerEnd(e) {
993
+ if (headerDragRef.current?.pointerId !== e.pointerId) return;
994
+ headerDragRef.current = null;
995
+ }
945
996
  const workCanvasRef = useRef4(null);
946
997
  const originalRef = useRef4(null);
947
998
  const displayCanvasRef = useRef4(null);
@@ -1165,197 +1216,215 @@ function BugReportModal({ config, initialScreenshot, onClose }) {
1165
1216
  "aria-label": "Report an issue",
1166
1217
  onPointerDown: (e) => e.stopPropagation(),
1167
1218
  onFocus: (e) => e.stopPropagation(),
1168
- children: /* @__PURE__ */ jsxs6("div", { className: `cfi-sh-bug-card${view === "editor" ? " cfi-sh-bug-card-wide" : ""}`, children: [
1169
- /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-header", children: [
1170
- /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-title", children: submitState === "success" ? "Issue submitted" : view === "editor" ? "New Issue - Attach Screenshot (Optional)" : "Report an issue" }),
1171
- /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-env", children: config.context.environment }),
1172
- /* @__PURE__ */ jsx6("button", { className: "cfi-sh-bug-close", type: "button", onClick: closeUnlessBusy, "aria-label": "Close", children: "\xD7" })
1173
- ] }),
1174
- submitState === "success" ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
1175
- /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-body cfi-sh-bug-done", children: [
1176
- /* @__PURE__ */ jsx6("p", { className: "cfi-sh-bug-done-msg", children: "Thanks for submitting this issue." }),
1177
- issueUrl ? /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-done-link", children: [
1178
- /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-done-label", children: "You can view it here:" }),
1179
- /* @__PURE__ */ jsx6(
1180
- "a",
1181
- {
1182
- href: issueUrl,
1183
- target: "_blank",
1184
- rel: "noreferrer",
1185
- className: "cfi-sh-bug-done-url",
1186
- children: issueUrl
1187
- }
1188
- ),
1189
- /* @__PURE__ */ jsx6(
1219
+ children: /* @__PURE__ */ jsxs6(
1220
+ "div",
1221
+ {
1222
+ ref: cardRef,
1223
+ className: `cfi-sh-bug-card${view === "editor" ? " cfi-sh-bug-card-wide" : ""}`,
1224
+ style: cardOffset.x !== 0 || cardOffset.y !== 0 ? { transform: `translate(${cardOffset.x}px, ${cardOffset.y}px)` } : void 0,
1225
+ children: [
1226
+ /* @__PURE__ */ jsxs6(
1227
+ "div",
1228
+ {
1229
+ className: "cfi-sh-bug-header",
1230
+ onPointerDown: onHeaderPointerDown,
1231
+ onPointerMove: onHeaderPointerMove,
1232
+ onPointerUp: onHeaderPointerEnd,
1233
+ onPointerCancel: onHeaderPointerEnd,
1234
+ children: [
1235
+ /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-title", children: submitState === "success" ? "Issue submitted" : view === "editor" ? "New Issue - Attach Screenshot (Optional)" : "Report an issue" }),
1236
+ /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-env", children: config.context.environment }),
1237
+ /* @__PURE__ */ jsx6("button", { className: "cfi-sh-bug-close", type: "button", onClick: closeUnlessBusy, "aria-label": "Close", children: "\xD7" })
1238
+ ]
1239
+ }
1240
+ ),
1241
+ submitState === "success" ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
1242
+ /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-body cfi-sh-bug-done", children: [
1243
+ /* @__PURE__ */ jsx6("p", { className: "cfi-sh-bug-done-msg", children: "Thanks for submitting this issue." }),
1244
+ issueUrl ? /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-done-link", children: [
1245
+ /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-done-label", children: "You can view it here:" }),
1246
+ /* @__PURE__ */ jsx6(
1247
+ "a",
1248
+ {
1249
+ href: issueUrl,
1250
+ target: "_blank",
1251
+ rel: "noreferrer",
1252
+ className: "cfi-sh-bug-done-url",
1253
+ children: issueUrl
1254
+ }
1255
+ ),
1256
+ /* @__PURE__ */ jsx6(
1257
+ "button",
1258
+ {
1259
+ type: "button",
1260
+ className: "cfi-sh-bug-copy-btn",
1261
+ title: "Copy link",
1262
+ "aria-label": "Copy link",
1263
+ onClick: () => {
1264
+ void navigator.clipboard.writeText(issueUrl).then(() => {
1265
+ setLinkCopied(true);
1266
+ window.setTimeout(() => setLinkCopied(false), 1500);
1267
+ });
1268
+ },
1269
+ children: linkCopied ? /* @__PURE__ */ jsx6(Check2, { size: 16 }) : /* @__PURE__ */ jsx6(Copy, { size: 16 })
1270
+ }
1271
+ )
1272
+ ] }) : null
1273
+ ] }),
1274
+ /* @__PURE__ */ jsx6("div", { className: "cfi-sh-bug-footer", children: /* @__PURE__ */ jsx6(
1190
1275
  "button",
1191
1276
  {
1192
1277
  type: "button",
1193
- className: "cfi-sh-bug-copy-btn",
1194
- title: "Copy link",
1195
- "aria-label": "Copy link",
1196
- onClick: () => {
1197
- void navigator.clipboard.writeText(issueUrl).then(() => {
1198
- setLinkCopied(true);
1199
- window.setTimeout(() => setLinkCopied(false), 1500);
1200
- });
1201
- },
1202
- children: linkCopied ? /* @__PURE__ */ jsx6(Check2, { size: 16 }) : /* @__PURE__ */ jsx6(Copy, { size: 16 })
1278
+ className: "cfi-sh-bug-btn cfi-sh-bug-btn-primary",
1279
+ onClick: closeUnlessBusy,
1280
+ children: "OK"
1203
1281
  }
1204
- )
1205
- ] }) : null
1206
- ] }),
1207
- /* @__PURE__ */ jsx6("div", { className: "cfi-sh-bug-footer", children: /* @__PURE__ */ jsx6(
1208
- "button",
1209
- {
1210
- type: "button",
1211
- className: "cfi-sh-bug-btn cfi-sh-bug-btn-primary",
1212
- onClick: closeUnlessBusy,
1213
- children: "OK"
1214
- }
1215
- ) })
1216
- ] }) : view === "editor" ? /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-body", children: [
1217
- /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-toolbar", children: [
1218
- /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-modes", children: [
1282
+ ) })
1283
+ ] }) : view === "editor" ? /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-body", children: [
1284
+ /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-toolbar", children: [
1285
+ /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-modes", children: [
1286
+ /* @__PURE__ */ jsx6(
1287
+ "button",
1288
+ {
1289
+ type: "button",
1290
+ className: `cfi-sh-bug-btn${mode === "crop" ? " cfi-sh-bug-btn-active" : ""}`,
1291
+ onClick: () => setMode("crop"),
1292
+ children: "Crop"
1293
+ }
1294
+ ),
1295
+ /* @__PURE__ */ jsx6(
1296
+ "button",
1297
+ {
1298
+ type: "button",
1299
+ className: `cfi-sh-bug-btn${mode === "redact" ? " cfi-sh-bug-btn-active" : ""}`,
1300
+ onClick: () => setMode("redact"),
1301
+ children: "Redact"
1302
+ }
1303
+ )
1304
+ ] }),
1305
+ /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-hint", children: mode === "crop" ? "Drag to crop to a region" : "Drag to black out sensitive data" }),
1306
+ /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-modes", children: [
1307
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: () => setView("form"), children: "Skip" }),
1308
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: handleEditorReset, children: "Reset" }),
1309
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn cfi-sh-bug-btn-primary", onClick: handleEditorDone, children: "Done" })
1310
+ ] })
1311
+ ] }),
1312
+ /* @__PURE__ */ jsx6("div", { className: "cfi-sh-bug-canvas-wrap", children: /* @__PURE__ */ jsx6(
1313
+ "canvas",
1314
+ {
1315
+ ref: displayCanvasRef,
1316
+ className: "cfi-sh-bug-canvas",
1317
+ onPointerDown: handlePointerDown,
1318
+ onPointerMove: handlePointerMove,
1319
+ onPointerUp: handlePointerUp
1320
+ }
1321
+ ) })
1322
+ ] }) : /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-body", children: [
1323
+ /* @__PURE__ */ jsx6("label", { className: "cfi-sh-bug-label", htmlFor: "cfi-sh-bug-title-input", children: "Title" }),
1219
1324
  /* @__PURE__ */ jsx6(
1220
- "button",
1325
+ "input",
1221
1326
  {
1222
- type: "button",
1223
- className: `cfi-sh-bug-btn${mode === "crop" ? " cfi-sh-bug-btn-active" : ""}`,
1224
- onClick: () => setMode("crop"),
1225
- children: "Crop"
1327
+ id: "cfi-sh-bug-title-input",
1328
+ className: "cfi-sh-bug-input",
1329
+ value: title,
1330
+ onChange: (e) => setTitle(e.target.value),
1331
+ placeholder: "What went wrong?",
1332
+ maxLength: 200,
1333
+ autoFocus: true
1226
1334
  }
1227
1335
  ),
1336
+ /* @__PURE__ */ jsx6("label", { className: "cfi-sh-bug-label", htmlFor: "cfi-sh-bug-desc-input", children: "Details" }),
1228
1337
  /* @__PURE__ */ jsx6(
1229
- "button",
1338
+ "textarea",
1230
1339
  {
1231
- type: "button",
1232
- className: `cfi-sh-bug-btn${mode === "redact" ? " cfi-sh-bug-btn-active" : ""}`,
1233
- onClick: () => setMode("redact"),
1234
- children: "Redact"
1340
+ id: "cfi-sh-bug-desc-input",
1341
+ className: "cfi-sh-bug-textarea",
1342
+ value: description,
1343
+ onChange: (e) => setDescription(e.target.value),
1344
+ placeholder: "What did you expect? What happened instead? Steps to reproduce\u2026",
1345
+ rows: 4,
1346
+ maxLength: 1e4
1235
1347
  }
1236
- )
1237
- ] }),
1238
- /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-hint", children: mode === "crop" ? "Drag to crop to a region" : "Drag to black out sensitive data" }),
1239
- /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-modes", children: [
1240
- /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: () => setView("form"), children: "Skip" }),
1241
- /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: handleEditorReset, children: "Reset" }),
1242
- /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn cfi-sh-bug-btn-primary", onClick: handleEditorDone, children: "Done" })
1243
- ] })
1244
- ] }),
1245
- /* @__PURE__ */ jsx6("div", { className: "cfi-sh-bug-canvas-wrap", children: /* @__PURE__ */ jsx6(
1246
- "canvas",
1247
- {
1248
- ref: displayCanvasRef,
1249
- className: "cfi-sh-bug-canvas",
1250
- onPointerDown: handlePointerDown,
1251
- onPointerMove: handlePointerMove,
1252
- onPointerUp: handlePointerUp
1253
- }
1254
- ) })
1255
- ] }) : /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-body", children: [
1256
- /* @__PURE__ */ jsx6("label", { className: "cfi-sh-bug-label", htmlFor: "cfi-sh-bug-title-input", children: "Title" }),
1257
- /* @__PURE__ */ jsx6(
1258
- "input",
1259
- {
1260
- id: "cfi-sh-bug-title-input",
1261
- className: "cfi-sh-bug-input",
1262
- value: title,
1263
- onChange: (e) => setTitle(e.target.value),
1264
- placeholder: "What went wrong?",
1265
- maxLength: 200,
1266
- autoFocus: true
1267
- }
1268
- ),
1269
- /* @__PURE__ */ jsx6("label", { className: "cfi-sh-bug-label", htmlFor: "cfi-sh-bug-desc-input", children: "Details" }),
1270
- /* @__PURE__ */ jsx6(
1271
- "textarea",
1272
- {
1273
- id: "cfi-sh-bug-desc-input",
1274
- className: "cfi-sh-bug-textarea",
1275
- value: description,
1276
- onChange: (e) => setDescription(e.target.value),
1277
- placeholder: "What did you expect? What happened instead? Steps to reproduce\u2026",
1278
- rows: 4,
1279
- maxLength: 1e4
1280
- }
1281
- ),
1282
- /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-shot", children: [
1283
- screenshot ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
1284
- /* @__PURE__ */ jsx6("img", { className: "cfi-sh-bug-thumb", src: screenshot.previewUrl, alt: "Screenshot preview" }),
1285
- /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-shot-actions", children: [
1286
- /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: handleCapture, children: "Retake" }),
1287
- /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: handleRemoveScreenshot, children: "Remove" })
1348
+ ),
1349
+ /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-shot", children: [
1350
+ screenshot ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
1351
+ /* @__PURE__ */ jsx6("img", { className: "cfi-sh-bug-thumb", src: screenshot.previewUrl, alt: "Screenshot preview" }),
1352
+ /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-shot-actions", children: [
1353
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: handleCapture, children: "Retake" }),
1354
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: handleRemoveScreenshot, children: "Remove" })
1355
+ ] })
1356
+ ] }) : /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: handleCapture, children: "Capture screenshot" }),
1357
+ captureError && /* @__PURE__ */ jsx6("div", { className: "cfi-sh-bug-error", children: captureError })
1358
+ ] }),
1359
+ /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-files", children: [
1360
+ attachments.map((file, i) => /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-file-row", children: [
1361
+ /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-file-name", title: file.name, children: file.name }),
1362
+ /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-file-size", children: formatFileSize(file.size) }),
1363
+ /* @__PURE__ */ jsx6(
1364
+ "button",
1365
+ {
1366
+ type: "button",
1367
+ className: "cfi-sh-bug-file-remove",
1368
+ onClick: () => handleRemoveAttachment(i),
1369
+ "aria-label": `Remove ${file.name}`,
1370
+ children: "\xD7"
1371
+ }
1372
+ )
1373
+ ] }, `${file.name}-${file.size}-${i}`)),
1374
+ /* @__PURE__ */ jsx6(
1375
+ "button",
1376
+ {
1377
+ type: "button",
1378
+ className: "cfi-sh-bug-btn",
1379
+ onClick: () => fileInputRef.current?.click(),
1380
+ children: "Attach files\u2026"
1381
+ }
1382
+ ),
1383
+ /* @__PURE__ */ jsx6(
1384
+ "input",
1385
+ {
1386
+ ref: fileInputRef,
1387
+ type: "file",
1388
+ multiple: true,
1389
+ style: { display: "none" },
1390
+ onChange: (e) => handleFilesPicked(e.target.files)
1391
+ }
1392
+ )
1393
+ ] }),
1394
+ /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-meta", children: [
1395
+ "Includes: URL, app version, recent console errors and failed requests.",
1396
+ config.context.issuesUrl && /* @__PURE__ */ jsxs6(Fragment3, { children: [
1397
+ " ",
1398
+ /* @__PURE__ */ jsx6(
1399
+ "a",
1400
+ {
1401
+ className: "cfi-sh-bug-issues-link",
1402
+ href: config.context.issuesUrl,
1403
+ target: "_blank",
1404
+ rel: "noreferrer",
1405
+ children: "View known issues"
1406
+ }
1407
+ )
1408
+ ] })
1288
1409
  ] })
1289
- ] }) : /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: handleCapture, children: "Capture screenshot" }),
1290
- captureError && /* @__PURE__ */ jsx6("div", { className: "cfi-sh-bug-error", children: captureError })
1291
- ] }),
1292
- /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-files", children: [
1293
- attachments.map((file, i) => /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-file-row", children: [
1294
- /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-file-name", title: file.name, children: file.name }),
1295
- /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-file-size", children: formatFileSize(file.size) }),
1410
+ ] }),
1411
+ view === "form" && submitState !== "success" && /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-footer", children: [
1412
+ submitState === "error" && submitError && /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-error", children: submitError }),
1413
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: closeUnlessBusy, children: "Cancel" }),
1296
1414
  /* @__PURE__ */ jsx6(
1297
1415
  "button",
1298
1416
  {
1299
1417
  type: "button",
1300
- className: "cfi-sh-bug-file-remove",
1301
- onClick: () => handleRemoveAttachment(i),
1302
- "aria-label": `Remove ${file.name}`,
1303
- children: "\xD7"
1304
- }
1305
- )
1306
- ] }, `${file.name}-${file.size}-${i}`)),
1307
- /* @__PURE__ */ jsx6(
1308
- "button",
1309
- {
1310
- type: "button",
1311
- className: "cfi-sh-bug-btn",
1312
- onClick: () => fileInputRef.current?.click(),
1313
- children: "Attach files\u2026"
1314
- }
1315
- ),
1316
- /* @__PURE__ */ jsx6(
1317
- "input",
1318
- {
1319
- ref: fileInputRef,
1320
- type: "file",
1321
- multiple: true,
1322
- style: { display: "none" },
1323
- onChange: (e) => handleFilesPicked(e.target.files)
1324
- }
1325
- )
1326
- ] }),
1327
- /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-meta", children: [
1328
- "Includes: URL, app version, recent console errors and failed requests.",
1329
- config.context.issuesUrl && /* @__PURE__ */ jsxs6(Fragment3, { children: [
1330
- " ",
1331
- /* @__PURE__ */ jsx6(
1332
- "a",
1333
- {
1334
- className: "cfi-sh-bug-issues-link",
1335
- href: config.context.issuesUrl,
1336
- target: "_blank",
1337
- rel: "noreferrer",
1338
- children: "View known issues"
1418
+ className: "cfi-sh-bug-btn cfi-sh-bug-btn-primary",
1419
+ onClick: handleSubmit,
1420
+ disabled: !title.trim() || submitState === "submitting",
1421
+ children: submitState === "submitting" ? "Submitting\u2026" : "Submit report"
1339
1422
  }
1340
1423
  )
1341
1424
  ] })
1342
- ] })
1343
- ] }),
1344
- view === "form" && submitState !== "success" && /* @__PURE__ */ jsxs6("div", { className: "cfi-sh-bug-footer", children: [
1345
- submitState === "error" && submitError && /* @__PURE__ */ jsx6("span", { className: "cfi-sh-bug-error", children: submitError }),
1346
- /* @__PURE__ */ jsx6("button", { type: "button", className: "cfi-sh-bug-btn", onClick: closeUnlessBusy, children: "Cancel" }),
1347
- /* @__PURE__ */ jsx6(
1348
- "button",
1349
- {
1350
- type: "button",
1351
- className: "cfi-sh-bug-btn cfi-sh-bug-btn-primary",
1352
- onClick: handleSubmit,
1353
- disabled: !title.trim() || submitState === "submitting",
1354
- children: submitState === "submitting" ? "Submitting\u2026" : "Submit report"
1355
- }
1356
- )
1357
- ] })
1358
- ] })
1425
+ ]
1426
+ }
1427
+ )
1359
1428
  }
1360
1429
  );
1361
1430
  }
@@ -1394,14 +1463,16 @@ function useBugReportShortcut(enabled, onShortcut) {
1394
1463
  function handleKeyDown(e) {
1395
1464
  const platformMod = e.ctrlKey || e.metaKey;
1396
1465
  if (!platformMod || !e.altKey || e.shiftKey) return;
1397
- if (e.code !== "KeyB" && e.key.toLowerCase() !== "b") return;
1466
+ const isB = e.code === "KeyB" || e.key.toLowerCase() === "b";
1467
+ const isS = e.code === "KeyS" || e.key.toLowerCase() === "s";
1468
+ if (!isB && !isS) return;
1398
1469
  const target = e.target;
1399
1470
  if (target) {
1400
1471
  const tag = target.tagName;
1401
1472
  if (tag === "INPUT" || tag === "TEXTAREA" || target.isContentEditable) return;
1402
1473
  }
1403
1474
  e.preventDefault();
1404
- handlerRef.current();
1475
+ handlerRef.current(isS ? "screenshot" : "plain");
1405
1476
  }
1406
1477
  document.addEventListener("keydown", handleKeyDown);
1407
1478
  return () => document.removeEventListener("keydown", handleKeyDown);
@@ -1450,12 +1521,17 @@ function ShellHeader({
1450
1521
  const [bugOpen, setBugOpen] = useState7(false);
1451
1522
  const [bugShot, setBugShot] = useState7(null);
1452
1523
  const bugCaptureBusy = useRef6(false);
1453
- useBugReportShortcut(bugReport !== void 0, () => {
1524
+ useBugReportShortcut(bugReport !== void 0, (variant) => {
1454
1525
  if (bugOpen) {
1455
1526
  setBugOpen(false);
1456
1527
  return;
1457
1528
  }
1458
1529
  if (bugCaptureBusy.current) return;
1530
+ if (variant === "plain") {
1531
+ setBugShot(null);
1532
+ setBugOpen(true);
1533
+ return;
1534
+ }
1459
1535
  bugCaptureBusy.current = true;
1460
1536
  captureTabScreenshot().then((shot) => setBugShot(shot)).catch(() => setBugShot(null)).finally(() => {
1461
1537
  bugCaptureBusy.current = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@campfire-interactive/shell-header",
3
- "version": "0.15.1",
3
+ "version": "0.15.3",
4
4
  "description": "Shared shell header with app switcher for Campfire Suite",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",