diff --git a/README.md b/README.md index 1663b5b..6cf9fac 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,22 @@ If identity or roles cannot be validated, only these two features stay disabled; other opportunity features continue. Reload the page to refresh identity/roles. The unused identity token is discarded and redacted from debug responses. +Consumer token recovery also handles HTTP 401/403, in addition to HTTP 200 with +invalid JSON. It opens the existing SPA session URL in an inactive temporary tab, +preserves the originating window and Firefox cookie store, and retries within +the same five-attempt limit. Debug entries retain the HTTP status and recovery +reason. The auxiliary tab is closed after valid JSON or exhausted retries. + After a completed product-loading cycle with fresh API results, `resquestCrmServiceRequest` fetches all pages of `CRMServiceRequest` records with `SVC_PENDING_DELIVERY` and `ORA_SVC_MY_SR_TEAM_SRS`, using the existing general tokenrelay Bearer. It uses the Fusion `searchResources/latest` query endpoint, independently of the opportunity query version. Calls appear in the Service Requests debug category with masked credentials. +After a complete successful SR query (HTTP 200 with valid responses on all pages), +its result is reused for subsequent Reference/product cycles in the current page +session. Refresh all explicitly clears it. Failed pages are retried up to five +total attempts each; completed pages are not requested again. Resetting the query +stops further retries from the previous run. Records are linked by `OpportunityName_Id_c.OptyNumber`. A green SR badge indicates one or more matches; its tooltip lists each SR number, title, reported hours, owner, @@ -60,7 +71,8 @@ Products loaded from cache restore matching activity entries without network cal Missing, expired or mismatched entries are not treated as confirmed empty results; they wait for a real product refresh before a new activity query is allowed. Empty and entirely failed product cycles do not query activities. In mixed cycles, -only fresh products permit activity API calls on cache misses; SR refreshes once. +only fresh products permit activity API calls on cache misses; an already-loaded +SR result is reused and associated with the new product update. Activity lookups do not advance the existing Last update timestamp. Closing and reopening the modal preserves results and does not reload products or trigger these lookups. Already-running product requests may @@ -68,6 +80,12 @@ finish in the background and update their related activities. ## Workload Actions +The missing Act badge includes a separate plus control that opens an Action form +with Team, Start date, End Date, Status, Complexity and Notes. This is currently +UI-only: Save is disabled and the form never submits a request. Cancel or +Escape dismisses the form. Creation options and API integration are pending; +the form is unavailable to SALES_REP users, like the other Action features. + SR and Action filter badges appear before Status for users allowed to view these activities. They filter the loaded data without issuing requests and combine with the existing opportunity filters. The SR below 4h option replaces the other SR @@ -78,7 +96,11 @@ with both positive and negative options selected, all activity states remain visible. These selections are kept in memory, not persisted. Workload Actions are queried in the background after the product cycle completes, -using only fresh API results. Each distinct `RevnId` uses `requestWlActions` with +and only after SR has completed successfully (or was restored/reused). If SR is +unavailable, Actions are not requested and remain unknown rather than absent. +Each failed workload lookup gets up to five total attempts, stopping on success +or when its session is superseded. Cached products still do not trigger network +lookups. Each distinct `RevnId` uses `requestWlActions` with the `WWB-TS` credential in `Wwb-Provider-Authorization`. The Act badge beside SR aggregates all products: green means an action's `owner` matches the general tokenrelay response's `principal`; red means no matching owner was found. `Act ?` diff --git a/dist/chromium/background.js b/dist/chromium/background.js index 5ef13dd..3b85841 100644 --- a/dist/chromium/background.js +++ b/dist/chromium/background.js @@ -250,14 +250,22 @@ function createAuthConsumerSession({ const isHtmlFallback = error && error.code === "INVALID_JSON_RESPONSE" && error.httpStatus === 200; + const isSessionUnauthorized = error && (error.httpStatus === 401 || error.httpStatus === 403); + const needsSessionRecovery = isHtmlFallback || isSessionUnauthorized; + const retryReason = isSessionUnauthorized + ? `HTTP ${error.httpStatus} response requires SPA session recovery` + : "HTTP 200 response did not contain valid JSON"; const debugEntry = debugRequests[debugRequests.length - 1]; - if (!isHtmlFallback || attempt >= CUSTOMER_TOKEN_MAX_ATTEMPTS) { + if (!needsSessionRecovery || attempt >= CUSTOMER_TOKEN_MAX_ATTEMPTS) { if (debugEntry) { debugEntry.metadata.attempt = String(attempt); - if (isHtmlFallback) { + if (needsSessionRecovery) { debugEntry.metadata.retryLimitReached = "true"; - debugEntry.error = `requestConsumerTokenService returned invalid JSON after ${CUSTOMER_TOKEN_MAX_ATTEMPTS} attempts.`; + debugEntry.metadata.retryReason = retryReason; + debugEntry.error = isHtmlFallback + ? `requestConsumerTokenService returned invalid JSON after ${CUSTOMER_TOKEN_MAX_ATTEMPTS} attempts.` + : `requestConsumerTokenService failed with status ${error.httpStatus} after ${CUSTOMER_TOKEN_MAX_ATTEMPTS} attempts.`; error.message = debugEntry.error; } } @@ -285,7 +293,7 @@ function createAuthConsumerSession({ const retryDelayMs = getConsumerTokenRetryDelay(attempt); if (debugEntry) { debugEntry.metadata.attempt = String(attempt); - debugEntry.metadata.retryReason = "HTTP 200 response did not contain valid JSON"; + debugEntry.metadata.retryReason = retryReason; debugEntry.metadata.nextRetryDelayMs = String(retryDelayMs); } @@ -874,7 +882,10 @@ function createHttpBackgroundJson({ appendBackgroundDebugEntry(debugRequests, debugEntry); if (!response.ok) { - throw new Error(`${requestName} failed with status ${response.status}.`); + const error = new Error(`${requestName} failed with status ${response.status}.`); + error.httpStatus = response.status; + debugEntry.error = error.message; + throw error; } if (responsePayload.error) { diff --git a/dist/chromium/content.js b/dist/chromium/content.js index 8e3d853..f976c44 100644 --- a/dist/chromium/content.js +++ b/dist/chromium/content.js @@ -1,6 +1,6 @@ (function () { "use strict"; -const redwoodStyles = "\n .opportunities-extension-scroll-lock {\n overflow: hidden !important;\n }\n\n .opportunities-extension-modal,\n .opportunities-extension-modal * {\n box-sizing: border-box;\n font-family: \"Oracle Sans\", Arial, Helvetica, sans-serif;\n }\n\n .opportunities-extension-modal {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n background: #f5f4f2;\n color: #000000;\n }\n\n .opportunities-extension-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-shell {\n height: 100vh;\n min-height: 0;\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n background: #f5f4f2;\n }\n\n .opportunities-extension-header {\n position: relative;\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 24px;\n padding: 28px 40px 22px;\n border-bottom: 1px solid #dedbd7;\n background:\n linear-gradient(90deg, #8f624a 0 11%, #c74634 11% 23%, #6f5a7f 23% 36%, #00758f 36% 51%, #d4b06a 51% 63%, transparent 63% 100%) top left / 100% 6px no-repeat,\n #ffffff;\n }\n\n .opportunities-extension-header::before {\n position: absolute;\n left: 40px;\n bottom: -1px;\n width: 64px;\n height: 3px;\n background: #00758f;\n content: \"\";\n }\n\n .opportunities-extension-header h1 {\n margin: 0;\n color: #000000;\n font-size: 24px;\n font-weight: 700;\n line-height: 1.2;\n letter-spacing: 0;\n }\n\n .opportunities-extension-header p {\n margin: 0;\n color: #5f5a55;\n font-size: 14px;\n line-height: 1.4;\n }\n\n .opportunities-extension-subtitle-row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n margin-top: 6px;\n }\n\n .opportunities-extension-auth-badge {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n color: #ffffff;\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-auth-badge-authenticated {\n background: #3f6f17;\n }\n\n .opportunities-extension-auth-badge-unauthenticated {\n background: #c5331f;\n }\n\n .opportunities-extension-auth-badge-pending {\n background: #6f5a7f;\n }\n\n .opportunities-extension-products-progress {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n background: #e8f4f6;\n color: #006d7a;\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-products-progress[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-products-cache-timestamp {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n background: #f0eeeb;\n color: #5f5a55;\n font-size: 11px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .opportunities-extension-products-cache-timestamp[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-products-progress[data-state=\"running\"]::before {\n width: 12px;\n height: 12px;\n margin-right: 6px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n content: \"\";\n animation: opportunities-extension-spin .8s linear infinite;\n }\n\n .opportunities-extension-products-progress[data-state=\"complete\"] {\n background: #e2f2e5;\n color: #356d19;\n }\n\n .opportunities-extension-products-progress[data-state=\"complete-with-errors\"],\n .opportunities-extension-products-progress[data-state=\"error\"] {\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n @keyframes opportunities-extension-spin {\n to { transform: rotate(360deg); }\n }\n\n .opportunities-extension-icon-button {\n width: 36px;\n height: 36px;\n flex: 0 0 36px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 18px;\n font-weight: 600;\n line-height: 1;\n cursor: pointer;\n }\n\n .opportunities-extension-header-actions {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n\n .opportunities-extension-icon-button svg {\n width: 18px;\n height: 18px;\n vertical-align: middle;\n }\n\n .opportunities-extension-icon-button .opportunities-extension-settings-icon {\n width: 20px;\n height: 20px;\n }\n\n .opportunities-extension-icon-button:hover,\n .opportunities-extension-icon-button:focus {\n border-color: #b8b2ad;\n background: #f5f4f2;\n outline: none;\n }\n\n .opportunities-extension-body {\n display: grid;\n min-height: 0;\n grid-template-rows: auto auto minmax(0, 1fr);\n gap: 16px;\n padding: 22px 40px 36px;\n background: #f5f4f2;\n overflow: hidden;\n }\n\n .opportunities-extension-form {\n display: flex;\n align-items: end;\n flex-wrap: wrap;\n gap: 24px;\n min-height: 82px;\n max-width: none;\n margin: 0;\n padding: 14px 16px;\n border: 1px solid #dedbd7;\n border-radius: 4px;\n background: #ffffff;\n }\n\n .opportunities-extension-field {\n display: grid;\n max-width: max-content;\n min-width: 270px;\n width: max-content;\n gap: 6px;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-stage-dashboard {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 12px;\n }\n\n .opportunities-extension-stage-dashboard-card {\n display: grid;\n gap: 6px;\n min-width: 0;\n padding: 12px 16px;\n border: 1px solid #dedbd7;\n border-top: 3px solid #5f5a55;\n border-radius: 4px;\n background: #ffffff;\n }\n\n .opportunities-extension-stage-dashboard-card span {\n color: #5f5a55;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-stage-dashboard-value {\n overflow: hidden;\n color: #312d2a;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.2;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"SQL\"] {\n border-top-color: #008aa6;\n }\n\n .opportunities-extension-total-dashboard-card {\n border-top-color: #312d2a;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"PIPELINE\"] {\n border-top-color: #6f6863;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"UPSIDE\"] {\n border-top-color: #c87b00;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"FORECAST\"] {\n border-top-color: #755b8b;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"WON\"] {\n border-top-color: #4b7f22;\n }\n\n .opportunities-extension-stage-filter {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 0;\n }\n\n .opportunities-extension-stage-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-stage-filter-controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n }\n\n .opportunities-extension-stage-filter-button {\n min-height: 36px;\n padding: 6px 12px;\n border: 1px solid currentColor;\n border-radius: 18px;\n background: #ffffff;\n color: #5f5a55;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"SQL\"] {\n color: #006b84;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"PIPELINE\"] {\n color: #5f5a55;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"UPSIDE\"] {\n color: #945400;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"FORECAST\"] {\n color: #624e74;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"WON\"] {\n color: #3f6f17;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"SQL\"] {\n border-color: #006b84;\n background: #006b84;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"PIPELINE\"] {\n border-color: #5f5a55;\n background: #5f5a55;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"UPSIDE\"] {\n border-color: #945400;\n background: #945400;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"FORECAST\"] {\n border-color: #624e74;\n background: #624e74;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"WON\"] {\n border-color: #3f6f17;\n background: #3f6f17;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-status-filter {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 0;\n }\n\n .opportunities-extension-status-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-status-filter-controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n }\n\n .opportunities-extension-status-filter-button {\n min-height: 36px;\n padding: 6px 12px;\n border: 1px solid currentColor;\n border-radius: 18px;\n background: #ffffff;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"OPEN\"] {\n color: #197a3d;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"CLOSED\"] {\n color: #4b5563;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"LOST\"] {\n color: #b13b34;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"WON\"] {\n color: #1f5f99;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"OPEN\"] {\n border-color: #197a3d;\n background: #197a3d;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"CLOSED\"] {\n border-color: #4b5563;\n background: #4b5563;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"LOST\"] {\n border-color: #b13b34;\n background: #b13b34;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"WON\"] {\n border-color: #1f5f99;\n background: #1f5f99;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-customer-filter {\n position: relative;\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 220px;\n }\n\n .opportunities-extension-customer-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-customer-filter-trigger {\n position: relative;\n min-width: 220px;\n min-height: 44px;\n padding: 10px 38px 10px 12px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.3;\n text-align: left;\n cursor: pointer;\n }\n\n .opportunities-extension-customer-filter-trigger::after {\n position: absolute;\n top: 50%;\n right: 16px;\n width: 0;\n height: 0;\n border-top: 6px solid #312d2a;\n border-right: 5px solid transparent;\n border-left: 5px solid transparent;\n content: \"\";\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n .opportunities-extension-customer-filter-trigger:disabled {\n cursor: not-allowed;\n background: #f5f4f2;\n color: #7d7772;\n }\n\n .opportunities-extension-customer-filter-trigger:focus-visible {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-customer-filter-panel {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n z-index: 4;\n display: grid;\n width: min(360px, calc(100vw - 80px));\n gap: 10px;\n padding: 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .18);\n }\n\n .opportunities-extension-customer-filter-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-customer-filter-search {\n width: 100%;\n min-height: 40px;\n padding: 8px 10px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n }\n\n .opportunities-extension-customer-filter-search:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-customer-filter-option {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-customer-filter-select-all {\n min-height: 32px;\n padding-bottom: 8px;\n border-bottom: 1px solid #dedbd7;\n font-weight: 700;\n }\n\n .opportunities-extension-customer-filter-panel input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n flex: 0 0 16px;\n accent-color: #00758f;\n }\n\n .opportunities-extension-customer-filter-list {\n display: block;\n max-height: 250px;\n overflow: auto;\n }\n\n .opportunities-extension-customer-filter-option {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: start;\n min-height: 0;\n height: auto !important;\n padding: 8px 4px;\n cursor: pointer;\n }\n\n .opportunities-extension-customer-filter-option input[type=\"checkbox\"] {\n margin-top: 1px;\n }\n\n .opportunities-extension-customer-filter-option span {\n display: block;\n min-width: 0;\n line-height: 18px;\n overflow-wrap: anywhere;\n white-space: normal;\n }\n\n .opportunities-extension-customer-filter-option:hover {\n background: #f5f4f2;\n }\n\n .opportunities-extension-customer-filter-empty {\n margin: 4px 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-table-search-field {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n width: 260px;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-table-search-field input {\n width: 100%;\n min-height: 44px;\n padding: 10px 12px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.3;\n }\n\n .opportunities-extension-table-search-field input:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-select-wrap {\n position: relative;\n display: block;\n width: 270px;\n max-width: 100%;\n }\n\n .opportunities-extension-select-wrap::after {\n position: absolute;\n top: 50%;\n right: 16px;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-top: 6px solid #000000;\n content: \"\";\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n .opportunities-extension-field select {\n width: 100%;\n min-width: 0;\n max-width: 100%;\n min-height: 44px;\n box-sizing: border-box;\n appearance: none;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #000000;\n font-size: 14px;\n line-height: 1.3;\n padding: 11px 44px 11px 12px;\n }\n\n .opportunities-extension-field select:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-table-surface {\n min-height: 0;\n height: 100%;\n border: 1px solid #dedbd7;\n border-radius: 4px;\n background: #ffffff;\n overflow-x: auto;\n overflow-y: auto;\n }\n\n .opportunities-extension-table {\n width: 100%;\n min-width: 0;\n border-collapse: collapse;\n table-layout: fixed;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-table thead {\n background: #faf9f8;\n }\n\n .opportunities-extension-table th {\n position: sticky;\n top: 0;\n z-index: 1;\n height: 44px;\n border-bottom: 1px solid #b8b2ad;\n background: #faf9f8;\n color: #312d2a;\n font-size: 12px;\n font-weight: 700;\n text-align: left;\n white-space: nowrap;\n }\n\n .opportunities-extension-table td {\n min-height: 48px;\n padding: 12px 16px;\n border-bottom: 1px solid #ebe8e5;\n vertical-align: middle;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-table th:nth-child(1) {\n width: 16%;\n }\n\n .opportunities-extension-table th:nth-child(2) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 18%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 11%;\n }\n\n .opportunities-extension-table th:nth-child(5) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(8) {\n width: 6%;\n }\n\n .opportunities-extension-table th:nth-child(9) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(11) {\n width: 4%;\n }\n\n .opportunities-extension-table td:nth-child(2),\n .opportunities-extension-table td:nth-child(5),\n .opportunities-extension-table td:nth-child(6),\n .opportunities-extension-table td:nth-child(8) {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .opportunities-extension-table td:nth-child(9) {\n padding-right: 6px;\n padding-left: 6px;\n white-space: nowrap;\n overflow: visible;\n }\n\n .opportunities-extension-table td:nth-child(7) {\n padding-right: 6px;\n padding-left: 6px;\n white-space: nowrap;\n overflow: visible;\n }\n\n .opportunities-extension-table td:nth-child(10) {\n padding-right: 6px;\n padding-left: 6px;\n font-size: 12px;\n white-space: nowrap;\n }\n\n .opportunities-extension-table td:nth-child(11) {\n padding-right: 6px;\n padding-left: 6px;\n text-align: center;\n white-space: nowrap;\n }\n\n .opportunities-extension-table tbody tr:hover {\n background: #f7f6f4;\n }\n\n .opportunities-extension-table tbody tr:last-child td {\n border-bottom: 0;\n }\n\n .opportunities-extension-table a {\n color: #006b84;\n text-decoration: underline;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n }\n\n .opportunities-extension-table a:hover {\n color: #004f63;\n }\n\n .opportunities-extension-opty-number-content {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n max-width: 100%;\n }\n\n .opportunities-extension-name-content {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n }\n\n .opportunities-extension-name-content > a {\n min-width: 0;\n }\n\n .opportunities-extension-actions-content {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n white-space: nowrap;\n }\n\n .opportunities-extension-products-count {\n display: inline-grid;\n width: auto;\n min-width: 20px;\n height: 20px;\n place-items: center;\n flex: 0 0 auto;\n box-sizing: border-box;\n padding: 0 3px;\n border: 1px solid #7ca7b2;\n border-radius: 999px;\n background: #e8f4f6;\n color: #006d7a;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n }\n\n .opportunities-extension-products-count:hover,\n .opportunities-extension-products-count:focus-visible,\n .opportunities-extension-products-count[aria-expanded=\"true\"] {\n border-color: #00758f;\n background: #00758f;\n color: #ffffff;\n outline: none;\n }\n\n .opportunities-extension-products-count-error {\n border-color: #d8887e;\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n .opportunities-extension-products-detail-row:hover {\n background: transparent !important;\n }\n\n .opportunities-extension-products-detail-cell {\n padding: 0 !important;\n }\n\n .opportunities-extension-products-detail {\n padding: 14px 20px 18px;\n border-bottom: 1px solid #c9c5c1;\n background: #f0eeeb;\n }\n\n .opportunities-extension-products-detail-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 10px;\n color: #312d2a;\n }\n\n .opportunities-extension-ai-summary {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n margin: 0 0 12px;\n padding: 12px 16px;\n border: 1px solid #dedbd7;\n border-radius: 6px;\n background: #ffffff;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.5;\n text-align: left;\n white-space: normal;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-ai-summary strong {\n display: block;\n font-size: 13px;\n font-weight: 600;\n }\n\n .opportunities-extension-ai-summary p {\n margin: 4px 0 0;\n font: inherit;\n white-space: pre-wrap;\n }\n\n .opportunities-extension-ai-summary-error {\n color: #b42318;\n border-color: #d9928b;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-ai-summary {\n background: #292827;\n color: #f6f4f2;\n border-color: #5f5a55;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-ai-summary-error {\n color: #ffb4ab;\n border-color: #a45c55;\n }\n\n .opportunities-extension-products-detail-heading strong {\n font-size: 13px;\n }\n\n .opportunities-extension-products-detail-heading span {\n color: #5f5a55;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n }\n\n .opportunities-extension-products-table {\n width: 100%;\n table-layout: fixed;\n border-collapse: collapse;\n border: 1px solid #dedbd7;\n background: #ffffff;\n font-size: 12px;\n }\n\n .opportunities-extension-products-table th,\n .opportunities-extension-products-table td {\n position: static;\n height: auto;\n padding: 8px 10px;\n border-bottom: 1px solid #ebe8e5;\n background: transparent;\n overflow-wrap: anywhere;\n vertical-align: middle;\n white-space: normal;\n }\n\n .opportunities-extension-products-table th {\n background: #faf9f8;\n font-size: 11px;\n }\n\n .opportunities-extension-products-table th:nth-child(1) { width: 16%; }\n .opportunities-extension-products-table th:nth-child(2) { width: 16%; }\n .opportunities-extension-products-table th:nth-child(3) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(4) { width: 10%; }\n .opportunities-extension-products-table th:nth-child(5) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(6) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(7) { width: 7%; }\n .opportunities-extension-products-table th:nth-child(8) { width: 10%; }\n .opportunities-extension-products-table th:nth-child(9) { width: 12%; }\n .opportunities-extension-products-table th:nth-child(10) { width: 5%; }\n\n .opportunities-extension-products-empty {\n margin: 0;\n padding: 10px 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-copy-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 24px;\n height: 24px;\n padding: 3px;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-copy-button svg {\n width: 16px;\n height: 16px;\n fill: currentColor;\n }\n\n .opportunities-extension-copy-button:hover,\n .opportunities-extension-copy-button:focus-visible {\n background: #e8f4f6;\n color: #004f63;\n outline: none;\n }\n\n .opportunities-extension-action-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 5px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-action-button svg {\n width: 21px;\n height: 21px;\n }\n\n .opportunities-extension-action-button:hover,\n .opportunities-extension-action-button:focus-visible {\n border-color: #7ca7b2;\n background: #e8f4f6;\n color: #004f63;\n outline: none;\n }\n\n .opportunities-extension-action-button:disabled {\n cursor: wait;\n opacity: .72;\n }\n\n .opportunities-extension-action-button-loading svg {\n animation: opportunities-extension-pulse 1s ease-in-out infinite;\n }\n\n @keyframes opportunities-extension-pulse {\n 50% { opacity: .35; }\n }\n\n .opportunities-extension-copy-toast {\n position: fixed;\n right: 28px;\n bottom: 28px;\n z-index: 3;\n max-width: min(360px, calc(100vw - 56px));\n padding: 12px 16px;\n border-radius: 4px;\n background: #2f6f18;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .18);\n color: #ffffff;\n font-size: 13px;\n font-weight: 700;\n }\n\n .opportunities-extension-copy-toast-error {\n background: #a52b1c;\n }\n\n .opportunities-extension-copy-toast[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-stage-badge {\n display: inline-flex;\n align-items: center;\n min-height: 24px;\n padding: 3px 8px;\n border-radius: 12px;\n background: #ebe8e5;\n color: #312d2a;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"SQL\"] {\n background: #d9f0f5;\n color: #006b84;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"PIPELINE\"] {\n background: #ebe8e5;\n color: #5f5a55;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"UPSIDE\"] {\n background: #fff0d8;\n color: #945400;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"FORECAST\"] {\n background: #eee8f5;\n color: #624e74;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"WON\"] {\n background: #e5f1d9;\n color: #3f6f17;\n }\n\n .opportunities-extension-status-badge {\n display: inline-flex;\n align-items: center;\n min-height: 24px;\n padding: 3px 8px;\n border-radius: 12px;\n background: #ebe8e5;\n color: #312d2a;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n }\n\n .opportunities-extension-status-badge[data-status=\"OPEN\"] {\n background: #e2f2e5;\n color: #197a3d;\n }\n\n .opportunities-extension-status-badge[data-status=\"CLOSED\"] {\n background: #e5e7eb;\n color: #4b5563;\n }\n\n .opportunities-extension-status-badge[data-status=\"LOST\"] {\n background: #f9e3e1;\n color: #b13b34;\n }\n\n .opportunities-extension-status-badge[data-status=\"WON\"] {\n background: #e3edf8;\n color: #1f5f99;\n }\n\n .opportunities-extension-sort-button {\n position: relative;\n display: inline-flex;\n align-items: center;\n width: 100%;\n min-height: 44px;\n padding: 8px 42px 8px 16px;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: inherit;\n letter-spacing: 0;\n line-height: 1.2;\n text-align: left;\n white-space: normal;\n cursor: pointer;\n }\n\n .opportunities-extension-table-header-label {\n display: inline-flex;\n align-items: center;\n min-height: 44px;\n padding: 8px 6px;\n }\n\n .opportunities-extension-sort-button::after {\n position: absolute;\n right: 15px;\n color: #5f5a55;\n content: \"↕\";\n font-size: 16px;\n font-weight: 400;\n }\n\n .opportunities-extension-sort-button[data-sort-direction=\"ascending\"]::after {\n color: #00758f;\n content: \"↑\";\n }\n\n .opportunities-extension-sort-button[data-sort-direction=\"descending\"]::after {\n color: #00758f;\n content: \"↓\";\n }\n\n .opportunities-extension-sort-button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-sort-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n }\n\n .opportunities-extension-table-status {\n height: 152px;\n color: #5f5a55;\n font-size: 14px;\n text-align: center;\n }\n\n .opportunities-extension-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n .opportunities-extension-preferences-modal {\n position: absolute;\n inset: 0;\n z-index: 3;\n display: grid;\n place-items: center;\n padding: 24px;\n background: rgba(0, 0, 0, .42);\n }\n\n .opportunities-extension-preferences-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plans-modal {\n position: absolute;\n inset: 0;\n z-index: 4;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(0, 0, 0, .42);\n }\n\n .opportunities-extension-account-plans-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plans-dialog {\n display: grid;\n width: min(1180px, 100%);\n height: min(760px, calc(100vh - 24px));\n min-width: 0;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-columns: minmax(0, 1fr);\n overflow: hidden;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, .24);\n color: #312d2a;\n }\n\n .opportunities-extension-account-plans-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n padding: 14px 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-header h2 {\n margin: 0;\n font-size: 20px;\n line-height: 1.2;\n }\n\n .opportunities-extension-account-plans-header p {\n margin: 5px 0 0;\n color: #5f5a55;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-account-plans-content {\n display: grid;\n min-width: 0;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-columns: minmax(0, 1fr);\n min-height: 0;\n overflow: hidden;\n }\n\n .opportunities-extension-account-plans-content > .opportunities-extension-account-plans-skeleton {\n grid-row: 1 / -1;\n }\n\n .opportunities-extension-account-plans-tabs-navigation {\n position: relative;\n min-width: 0;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-tabs-navigation .opportunities-extension-account-plans-tab-navigation-button[hidden] {\n display: none;\n }\n\n .opportunities-extension-account-plans-tabs {\n display: flex;\n min-width: 0;\n gap: 4px;\n overflow-x: auto;\n padding: 8px 20px 0;\n scrollbar-width: none;\n }\n\n .opportunities-extension-account-plans-tabs::-webkit-scrollbar {\n display: none;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button {\n display: grid;\n position: absolute;\n z-index: 1;\n top: 50%;\n width: 32px;\n height: 32px;\n place-items: center;\n padding: 0;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n box-shadow: 0 2px 6px rgba(0, 0, 0, .16);\n transform: translateY(-50%);\n cursor: pointer;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:first-child {\n left: 8px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:last-child {\n right: 8px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:hover:not(:disabled) {\n border-color: #00758f;\n background: #f0eeeb;\n color: #005e73;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:disabled {\n border-color: #dedbd7;\n color: #b8b2ad;\n cursor: default;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button svg {\n width: 18px;\n height: 18px;\n }\n\n .opportunities-extension-account-plans-panels {\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n }\n\n .opportunities-extension-account-plan-tab {\n min-height: 38px;\n flex: 0 0 auto;\n padding: 7px 12px;\n border: 0;\n border-bottom: 3px solid transparent;\n background: transparent;\n color: #5f5a55;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n }\n\n .opportunities-extension-account-plan-tab:hover {\n background: #f0eeeb;\n color: #312d2a;\n }\n\n .opportunities-extension-account-plan-tab[aria-selected=\"true\"] {\n border-bottom-color: #00758f;\n color: #006d7a;\n }\n\n .opportunities-extension-account-plan-tab:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n }\n\n .opportunities-extension-account-plan-panel {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n box-sizing: border-box;\n padding: 16px 20px;\n }\n\n .opportunities-extension-account-plan-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plan-details {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0 24px;\n margin: 0;\n }\n\n .opportunities-extension-account-plan-details > div {\n display: grid;\n grid-template-columns: minmax(104px, 38%) minmax(0, 1fr);\n gap: 10px;\n min-height: 42px;\n align-items: center;\n padding: 7px 0;\n border-bottom: 1px solid #ebe8e5;\n }\n\n .opportunities-extension-account-plan-details dt {\n color: #5f5a55;\n font-size: 12px;\n font-weight: 700;\n }\n\n .opportunities-extension-account-plan-details dd {\n min-width: 0;\n margin: 0;\n color: #312d2a;\n font-size: 13px;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-consumption-trend {\n display: grid;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n margin-top: 14px;\n padding-top: 12px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-consumption-trend-header {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 24px;\n }\n\n .opportunities-extension-consumption-periods {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .opportunities-extension-consumption-periods button {\n min-height: 38px;\n padding: 7px 14px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-periods button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-consumption-periods button[aria-pressed=\"true\"] {\n border-color: #00758f;\n background: #e7f6f8;\n color: #005e73;\n }\n\n .opportunities-extension-consumption-periods button:focus-visible,\n .opportunities-extension-consumption-navigation-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-consumption-chart {\n display: grid;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n margin-top: 4px;\n }\n\n .opportunities-extension-consumption-navigation {\n display: grid;\n grid-template-columns: 36px minmax(130px, auto) 36px;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-height: 40px;\n margin-bottom: 2px;\n }\n\n .opportunities-extension-consumption-navigation strong {\n color: #312d2a;\n font-size: 13px;\n text-align: center;\n }\n\n .opportunities-extension-consumption-navigation-button {\n display: grid;\n width: 36px;\n height: 36px;\n place-items: center;\n padding: 0;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-navigation-button:hover:not(:disabled) {\n border-color: #00758f;\n background: #f0eeeb;\n color: #005e73;\n }\n\n .opportunities-extension-consumption-navigation-button:disabled {\n border-color: #dedbd7;\n color: #b8b2ad;\n cursor: default;\n }\n\n .opportunities-extension-consumption-navigation-button svg {\n width: 18px;\n height: 18px;\n }\n\n .opportunities-extension-consumption-figure {\n position: relative;\n min-width: 0;\n min-height: 0;\n margin: 0;\n scrollbar-width: none;\n }\n\n .opportunities-extension-consumption-figure::-webkit-scrollbar {\n display: none;\n }\n\n .opportunities-extension-consumption-visual {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-columns: minmax(0, 1fr) 176px;\n align-items: center;\n gap: 16px;\n }\n\n .opportunities-extension-consumption-svg {\n display: block;\n width: 100%;\n height: 300px;\n min-height: 0;\n overflow: visible;\n }\n\n .opportunities-extension-consumption-svg .consumption-grid-line {\n stroke: #dedbd7;\n stroke-width: 1;\n shape-rendering: crispEdges;\n }\n\n .opportunities-extension-consumption-svg .consumption-axis-label,\n .opportunities-extension-consumption-svg .consumption-x-label {\n fill: #5f5a55;\n font-family: Arial, sans-serif;\n font-size: 12px;\n }\n\n .opportunities-extension-consumption-svg .consumption-value-label {\n fill: #312d2a;\n font-family: Arial, sans-serif;\n font-size: 12px;\n font-weight: 700;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-funded {\n fill: #b77888;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-overage {\n fill: #de7907;\n }\n\n .opportunities-extension-consumption-svg .consumption-average-line {\n stroke: #de7907;\n stroke-width: 1.5;\n stroke-dasharray: 6 6;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group {\n cursor: default;\n outline: none;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group rect {\n transition: filter .16s ease, opacity .16s ease, stroke .16s ease;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group:hover rect,\n .opportunities-extension-consumption-svg .consumption-bar-group:focus rect {\n filter: brightness(1.06);\n stroke: #312d2a;\n stroke-width: 1.5;\n }\n\n .opportunities-extension-consumption-svg .consumption-animated-label {\n opacity: 0;\n animation: opportunities-extension-consumption-label-in .24s ease-out forwards;\n }\n\n .opportunities-extension-consumption-svg .consumption-animated-average {\n opacity: 0;\n animation: opportunities-extension-consumption-average-in .35s .32s ease-out forwards;\n }\n\n @keyframes opportunities-extension-consumption-label-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n @keyframes opportunities-extension-consumption-average-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n .opportunities-extension-consumption-legend {\n display: grid;\n align-content: center;\n gap: 4px;\n }\n\n .opportunities-extension-consumption-legend button {\n display: grid;\n min-width: 0;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n padding: 6px 4px;\n border: 0;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 12px;\n line-height: 1.25;\n text-align: left;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-legend button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-consumption-legend button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 1px;\n }\n\n .opportunities-extension-consumption-legend button[aria-pressed=\"false\"] {\n color: #77726d;\n opacity: .55;\n }\n\n .opportunities-extension-consumption-legend-swatch {\n display: block;\n width: 12px;\n height: 12px;\n justify-self: center;\n }\n\n .opportunities-extension-consumption-legend-funded {\n background: #b77888;\n }\n\n .opportunities-extension-consumption-legend-overage {\n background: #de7907;\n }\n\n .opportunities-extension-consumption-legend-average {\n height: 0;\n border-top: 2px dashed #de7907;\n }\n\n .opportunities-extension-consumption-tooltip {\n position: absolute;\n z-index: 2;\n display: grid;\n min-width: 190px;\n max-width: 260px;\n gap: 4px;\n padding: 10px 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .2);\n color: #312d2a;\n font-size: 12px;\n line-height: 1.3;\n pointer-events: none;\n }\n\n .opportunities-extension-consumption-tooltip[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-consumption-tooltip strong {\n margin-bottom: 2px;\n font-size: 13px;\n }\n\n .opportunities-extension-consumption-chart-skeleton {\n height: 100%;\n min-height: 0;\n padding: 34px 62px 24px;\n box-sizing: border-box;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot {\n display: flex;\n height: 100%;\n min-height: 220px;\n align-items: flex-end;\n justify-content: space-around;\n gap: 12px;\n padding: 0 14px;\n border-bottom: 1px solid #dedbd7;\n border-left: 1px solid #dedbd7;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot span {\n width: min(38px, 6%);\n border-radius: 2px 2px 0 0;\n background: #dedbd7;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-consumption-chart-empty,\n .opportunities-extension-consumption-chart-error {\n display: grid;\n min-height: 220px;\n place-items: center;\n margin: 0;\n color: #5f5a55;\n font-size: 14px;\n text-align: center;\n }\n\n .opportunities-extension-consumption-chart-error {\n color: #9f2d20;\n }\n\n .opportunities-extension-account-plan-status-indicator {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #9b9691;\n box-shadow: 0 0 0 3px #efedeb;\n vertical-align: middle;\n }\n\n .opportunities-extension-account-plan-status-indicator[data-active=\"true\"] {\n background: #3f6f17;\n box-shadow: 0 0 0 3px #e2f2e5;\n }\n\n .opportunities-extension-account-plan-tab .opportunities-extension-account-plan-status-indicator {\n margin-right: 8px;\n }\n\n .opportunities-extension-account-plans-skeleton-tabs {\n display: flex;\n min-height: 46px;\n align-items: center;\n padding: 0 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n overflow: hidden;\n }\n\n .opportunities-extension-account-plans-skeleton-panel {\n padding: 16px 20px;\n }\n\n .opportunities-extension-account-plans-skeleton-tab {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n min-height: 38px;\n padding: 0 12px;\n border-bottom: 3px solid #00758f;\n }\n\n .opportunities-extension-account-plans-skeleton-status {\n display: block;\n width: 10px;\n height: 10px;\n flex: 0 0 auto;\n border-radius: 50%;\n background: #dedbd7;\n box-shadow: 0 0 0 3px #efedeb;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-account-plans-skeleton-details {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0 24px;\n padding: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details > div {\n display: grid;\n grid-template-columns: minmax(104px, 38%) minmax(0, 1fr);\n align-items: center;\n gap: 10px;\n min-height: 42px;\n padding: 7px 0;\n border-bottom: 1px solid #ebe8e5;\n }\n\n .opportunities-extension-account-plans-skeleton-bar {\n display: block;\n height: 12px;\n border-radius: 3px;\n background: #dedbd7;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-account-plans-skeleton-tabs .opportunities-extension-account-plans-skeleton-bar {\n height: 14px;\n }\n\n .opportunities-extension-account-plans-skeleton-label {\n width: 74%;\n height: 10px;\n }\n\n .opportunities-extension-account-plans-skeleton-trend {\n display: grid;\n min-height: 0;\n grid-template-rows: auto auto minmax(0, 1fr);\n margin: 14px 0 0;\n padding-top: 12px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton-trend-header {\n display: flex;\n justify-content: flex-end;\n min-height: 38px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods .opportunities-extension-account-plans-skeleton-bar {\n height: 12px;\n }\n\n .opportunities-extension-account-plans-skeleton-period-active {\n height: 38px !important;\n border: 1px solid #8cc8d3;\n background: #e7f6f8;\n }\n\n .opportunities-extension-account-plans-skeleton-navigation {\n display: grid;\n grid-template-columns: 32px 124px 32px;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-height: 54px;\n }\n\n .opportunities-extension-account-plans-skeleton-navigation .opportunities-extension-account-plans-skeleton-bar {\n justify-self: center;\n }\n\n .opportunities-extension-account-plans-skeleton-chart {\n display: grid;\n min-height: 0;\n grid-template-columns: minmax(0, 1fr) 150px;\n align-items: center;\n gap: 28px;\n padding: 12px 14px 0 62px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot {\n display: flex;\n position: relative;\n height: 300px;\n min-height: 0;\n box-sizing: border-box;\n align-items: flex-end;\n justify-content: space-around;\n gap: 12px;\n padding: 0 14px 64px;\n background: repeating-linear-gradient(to bottom, transparent 0, transparent 58px, #ebe8e5 58px, #ebe8e5 59px) left top / 100% 236px no-repeat;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::before,\n .opportunities-extension-account-plans-skeleton-plot::after {\n position: absolute;\n display: block;\n content: \"\";\n background: #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::before {\n top: 0;\n bottom: 64px;\n left: 0;\n width: 1px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::after {\n right: 0;\n bottom: 64px;\n left: 0;\n height: 1px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot .opportunities-extension-account-plans-skeleton-bar {\n width: min(38px, 7%);\n flex: 0 1 38px;\n border-radius: 2px 2px 0 0;\n }\n\n .opportunities-extension-account-plans-skeleton-legend {\n display: grid;\n align-content: center;\n gap: 18px;\n min-height: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-legend .opportunities-extension-account-plans-skeleton-bar {\n height: 11px;\n }\n\n @keyframes opportunities-extension-skeleton-pulse {\n from { opacity: .48; }\n to { opacity: 1; }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .opportunities-extension-account-plans-skeleton-bar,\n .opportunities-extension-consumption-chart-skeleton-plot span,\n .opportunities-extension-consumption-svg .consumption-animated-label,\n .opportunities-extension-consumption-svg .consumption-animated-average {\n animation: none;\n opacity: 1;\n }\n }\n\n .opportunities-extension-account-plans-empty,\n .opportunities-extension-account-plans-error {\n margin: 0;\n padding: 28px 20px;\n color: #5f5a55;\n font-size: 14px;\n }\n\n .opportunities-extension-account-plans-error {\n color: #9f2d20;\n }\n\n .opportunities-extension-preferences-dialog {\n display: grid;\n width: min(680px, 100%);\n max-height: min(720px, calc(100vh - 48px));\n grid-template-rows: auto minmax(0, 1fr) auto;\n overflow: hidden;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, .24);\n color: #312d2a;\n }\n\n .opportunities-extension-preferences-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 18px 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-preferences-header h2 {\n margin: 0;\n font-size: 20px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-preferences-content {\n min-height: 0;\n overflow: auto;\n padding: 20px;\n }\n\n .opportunities-extension-preferences-fieldset {\n min-width: 0;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n .opportunities-extension-preferences-fieldset legend {\n margin-bottom: 12px;\n padding: 0;\n color: #312d2a;\n font-size: 15px;\n font-weight: 700;\n line-height: 1.3;\n }\n\n .opportunities-extension-preferences-options {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 4px 20px;\n }\n\n .opportunities-extension-preferences-option {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 0;\n padding: 9px 8px;\n border-radius: 4px;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.35;\n cursor: pointer;\n }\n\n .opportunities-extension-preferences-option:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-preferences-option input {\n width: 18px;\n height: 18px;\n flex: 0 0 18px;\n margin: 0;\n accent-color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-preferences-cache-field {\n display: grid;\n width: min(280px, 100%);\n gap: 6px;\n margin-top: 24px;\n color: #312d2a;\n font-size: 14px;\n font-weight: 700;\n }\n\n .opportunities-extension-preferences-cache-field select {\n width: 100%;\n height: 40px;\n padding: 0 36px 0 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n font-weight: 400;\n }\n\n .opportunities-extension-preferences-cache-field select:focus {\n border-color: #00758f;\n outline: 2px solid #bde7ee;\n outline-offset: 0;\n }\n\n .opportunities-extension-preferences-footer {\n display: flex;\n justify-content: flex-end;\n padding: 14px 20px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-button {\n min-width: 88px;\n min-height: 36px;\n padding: 7px 16px;\n border: 1px solid transparent;\n border-radius: 4px;\n font-size: 14px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-button-primary {\n border-color: #00758f;\n background: #00758f;\n color: #ffffff;\n }\n\n .opportunities-extension-button-primary:hover,\n .opportunities-extension-button-primary:focus-visible {\n border-color: #005e73;\n background: #005e73;\n outline: none;\n }\n\n .opportunities-extension-debug-panel {\n position: fixed;\n right: 24px;\n bottom: 24px;\n z-index: 1;\n width: min(640px, calc(100vw - 48px));\n max-height: min(560px, calc(100vh - 120px));\n overflow: auto;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 2px 8px rgba(0, 0, 0, .16);\n padding: 16px;\n color: #000000;\n }\n\n .opportunities-extension-debug-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-debug-panel h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n line-height: 1.25;\n }\n\n .opportunities-extension-debug-panel p {\n margin: 4px 0 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-debug-panel-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 12px;\n }\n\n .opportunities-extension-debug-visibility-button {\n width: 34px;\n height: 34px;\n flex: 0 0 34px;\n color: #312d2a;\n }\n\n .opportunities-extension-debug-visibility-button svg {\n width: 20px;\n height: 20px;\n }\n\n .opportunities-extension-debug-list {\n display: grid;\n gap: 10px;\n }\n\n .opportunities-extension-debug-item {\n border: 1px solid #dedbd7;\n border-left-width: 4px;\n border-radius: 4px;\n background: #faf9f8;\n }\n\n .opportunities-extension-debug-item[open] {\n background: #ffffff;\n }\n\n .opportunities-extension-debug-item-success {\n border-left-color: #3f6f17;\n }\n\n .opportunities-extension-debug-item-success .opportunities-extension-debug-status {\n background: #e2f2e5;\n color: #356d19;\n }\n\n .opportunities-extension-debug-item-failed {\n border-left-color: #c5331f;\n }\n\n .opportunities-extension-debug-item-failed .opportunities-extension-debug-status {\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n .opportunities-extension-debug-item-pending {\n border-left-color: #6f5a7f;\n }\n\n .opportunities-extension-debug-item-pending .opportunities-extension-debug-status {\n background: #eee8f2;\n color: #6f5a7f;\n }\n\n .opportunities-extension-debug-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n min-height: 42px;\n padding: 9px 12px 9px 10px;\n cursor: pointer;\n list-style: none;\n }\n\n .opportunities-extension-debug-heading::-webkit-details-marker {\n display: none;\n }\n\n .opportunities-extension-debug-heading::before {\n content: \"⌄\";\n width: 14px;\n color: #5f5a55;\n font-size: 16px;\n line-height: 1;\n transform: rotate(-90deg);\n transition: transform .15s ease;\n }\n\n .opportunities-extension-debug-item[open] .opportunities-extension-debug-heading::before {\n transform: rotate(0deg);\n }\n\n .opportunities-extension-debug-summary-meta {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n }\n\n .opportunities-extension-debug-http-status,\n .opportunities-extension-debug-status {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n line-height: 1;\n text-transform: uppercase;\n }\n\n .opportunities-extension-debug-http-status {\n background: #e8f4f6;\n color: #006d7a;\n }\n\n .opportunities-extension-debug-status {\n background: #ebe8e5;\n color: #5f5a55;\n }\n\n .opportunities-extension-debug-heading strong {\n font-size: 13px;\n }\n\n .opportunities-extension-debug-item pre {\n margin: 0;\n padding: 8px 12px 12px;\n color: #312d2a;\n font-family: Consolas, \"Courier New\", monospace;\n font-size: 12px;\n line-height: 1.45;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .opportunities-extension-debug-empty {\n padding: 14px;\n border: 1px dashed #b8b2ad;\n border-radius: 4px;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] {\n background: #1f1f1f;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-shell,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-body {\n background: #1f1f1f;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header {\n border-bottom-color: #4e4a46;\n background:\n linear-gradient(90deg, #a8795d 0 11%, #dd5a47 11% 23%, #876e9b 23% 36%, #00a6be 36% 51%, #dfbd76 51% 63%, transparent 63% 100%) top left / 100% 6px no-repeat,\n #292827;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header h1,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-value,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-field,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card span,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail-heading span,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details dt,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-empty {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-error {\n color: #ffb4a8;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-error {\n color: #ffb4a8;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-bar {\n background: #5b5753;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-status {\n background: #5b5753;\n box-shadow: 0 0 0 3px #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-period-active {\n border-color: #3f7580;\n background: #23474e;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-skeleton-plot span {\n background: #5b5753;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-status-indicator {\n background: #8f8a85;\n box-shadow: 0 0 0 3px #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-status-indicator[data-active=\"true\"] {\n background: #7fb05b;\n box-shadow: 0 0 0 3px #314527;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-form,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-surface,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-panel,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-dialog,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-dialog,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item[open] {\n border-color: #4e4a46;\n background: #292827;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-search,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field input,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-field select,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-cache-field select,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger::after {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-select-wrap::after {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger:disabled {\n background: #292827;\n color: #918b86;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-search::placeholder,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field input::placeholder {\n color: #b5b0ab;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-option,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-header h2,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header h2,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-fieldset legend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-cache-field,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail-heading,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details dd,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-heading,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item pre,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel h2 {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation strong {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-empty {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table th {\n border-bottom-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-header,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-footer,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tabs-navigation,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tabs,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details > div,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-tabs,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-details > div {\n border-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-trend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-skeleton-plot,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-trend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot {\n border-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot {\n background: repeating-linear-gradient(to bottom, transparent 0, transparent 58px, #4e4a46 58px, #4e4a46 59px) left top / 100% 236px no-repeat;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot::before,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot::after {\n background: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab:hover {\n background: #3b3937;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab[aria-selected=\"true\"] {\n border-bottom-color: #43c4d5;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button[aria-pressed=\"true\"] {\n border-color: #43c4d5;\n background: #173e43;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button:hover:not(:disabled),\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button:hover:not(:disabled) {\n border-color: #43c4d5;\n background: #3b3937;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button:disabled,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button:disabled {\n border-color: #4e4a46;\n color: #746f6a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-grid-line {\n stroke: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-axis-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-x-label {\n fill: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-value-label {\n fill: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-funded {\n fill: #ca8798;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-overage {\n fill: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-average-line {\n stroke: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-group:hover rect,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-group:focus rect {\n stroke: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button[aria-pressed=\"false\"] {\n color: #a8a39e;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-funded {\n background: #ca8798;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-overage {\n background: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-average {\n border-top-color: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-tooltip {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option input {\n accent-color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary {\n border-color: #00a6be;\n background: #008aa6;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary:focus-visible {\n border-color: #43c4d5;\n background: #006d7a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-option:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table tbody tr:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sort-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button:focus {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table thead,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table th,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table th {\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table td {\n border-bottom-color: #3f3c39;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail {\n border-bottom-color: #4e4a46;\n background: #252423;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table th,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table td {\n border-bottom-color: #3f3c39;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count {\n border-color: #2f9bae;\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count:focus-visible,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count[aria-expanded=\"true\"] {\n border-color: #43c4d5;\n background: #008aa6;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"running\"] {\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"complete\"] {\n background: #244f2e;\n color: #a8dfb7;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"complete-with-errors\"],\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"error\"],\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count-error {\n border-color: #b13b34;\n background: #5f2926;\n color: #ffb4ad;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-cache-timestamp {\n background: #3b3937;\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table a,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button {\n color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table a:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button:focus-visible,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button:focus-visible {\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"SQL\"] {\n color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"PIPELINE\"] {\n color: #d1cbc6;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"UPSIDE\"] {\n color: #ffbf62;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"FORECAST\"] {\n color: #d2b7e9;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"WON\"] {\n color: #9bd46a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"SQL\"] {\n border-top-color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-total-dashboard-card {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"PIPELINE\"] {\n border-top-color: #c0b9b3;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"UPSIDE\"] {\n border-top-color: #ffb84d;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"FORECAST\"] {\n border-top-color: #cba7e7;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"WON\"] {\n border-top-color: #92cf5b;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"SQL\"] {\n border-color: #008aa6;\n background: #008aa6;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"PIPELINE\"] {\n border-color: #6f6863;\n background: #6f6863;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"UPSIDE\"] {\n border-color: #b96e00;\n background: #b96e00;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"FORECAST\"] {\n border-color: #755b8b;\n background: #755b8b;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"WON\"] {\n border-color: #4b7f22;\n background: #4b7f22;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"OPEN\"] {\n color: #69c985;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"CLOSED\"] {\n color: #c3cad3;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"LOST\"] {\n color: #ff9d94;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"WON\"] {\n color: #83bfff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"OPEN\"] {\n border-color: #197a3d;\n background: #197a3d;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"CLOSED\"] {\n border-color: #4b5563;\n background: #4b5563;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"LOST\"] {\n border-color: #b13b34;\n background: #b13b34;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"WON\"] {\n border-color: #1f5f99;\n background: #1f5f99;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item {\n border-color: #4e4a46;\n background: #252423;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button {\n color: #f6f4f2;\n }\n\n @media (min-width: 1201px) and (max-width: 1450px) {\n .opportunities-extension-table th:nth-child(1) {\n width: 16%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 18%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 12%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 10%;\n }\n }\n\n @media (max-width: 1200px) {\n .opportunities-extension-table {\n min-width: 1180px;\n }\n\n .opportunities-extension-table th:nth-child(1) {\n width: 15%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 17%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 13%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 6%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 9%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 11%;\n }\n }\n\n @media (max-width: 700px) {\n .opportunities-extension-header {\n padding: 24px 20px 18px;\n }\n\n .opportunities-extension-header::before {\n left: 20px;\n }\n\n .opportunities-extension-header h1 {\n font-size: 22px;\n }\n\n .opportunities-extension-header p {\n font-size: 14px;\n }\n\n .opportunities-extension-body {\n padding: 16px 20px 24px;\n }\n\n .opportunities-extension-form {\n align-items: stretch;\n flex-wrap: wrap;\n gap: 14px;\n min-height: auto;\n padding: 12px;\n }\n\n .opportunities-extension-field {\n max-width: none;\n width: 100%;\n }\n\n .opportunities-extension-customer-filter {\n width: 100%;\n }\n\n .opportunities-extension-customer-filter-trigger {\n width: 100%;\n }\n\n .opportunities-extension-customer-filter-panel {\n width: min(360px, calc(100vw - 64px));\n }\n\n .opportunities-extension-table-search-field {\n width: 100%;\n }\n\n .opportunities-extension-stage-dashboard {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .opportunities-extension-stage-dashboard-value {\n font-size: 18px;\n }\n\n .opportunities-extension-preferences-modal {\n padding: 12px;\n }\n\n .opportunities-extension-account-plans-modal {\n padding: 12px;\n }\n\n .opportunities-extension-preferences-dialog {\n max-height: calc(100vh - 24px);\n }\n\n .opportunities-extension-account-plans-dialog {\n height: calc(100vh - 24px);\n }\n\n .opportunities-extension-account-plan-panel {\n padding: 12px 14px;\n }\n\n .opportunities-extension-account-plan-details {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0 14px;\n }\n\n .opportunities-extension-account-plan-details > div {\n grid-template-columns: 1fr;\n align-content: center;\n gap: 3px;\n min-height: 54px;\n padding: 5px 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0 14px;\n padding: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details > div {\n grid-template-columns: 1fr;\n align-content: center;\n gap: 5px;\n min-height: 54px;\n padding: 5px 0;\n }\n\n .opportunities-extension-account-plans-skeleton-trend {\n margin: 14px 0 0;\n }\n\n .opportunities-extension-account-plans-skeleton-periods {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n align-items: center;\n gap: 6px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods .opportunities-extension-account-plans-skeleton-bar {\n width: 100% !important;\n }\n\n .opportunities-extension-account-plans-skeleton-chart {\n grid-template-columns: minmax(0, 1fr);\n gap: 12px;\n padding: 12px 8px 0 34px;\n }\n\n .opportunities-extension-account-plans-skeleton-legend {\n display: flex;\n min-height: 24px;\n align-items: center;\n justify-content: center;\n gap: 12px;\n }\n\n .opportunities-extension-consumption-trend-header {\n align-items: stretch;\n }\n\n .opportunities-extension-consumption-periods {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 3px;\n }\n\n .opportunities-extension-consumption-periods button {\n min-width: 0;\n padding: 7px 4px;\n font-size: 12px;\n }\n\n .opportunities-extension-consumption-chart {\n min-height: 0;\n }\n\n .opportunities-extension-consumption-svg {\n width: 760px;\n height: 245px;\n }\n\n .opportunities-extension-consumption-visual {\n width: 920px;\n grid-template-columns: 760px 144px;\n gap: 12px;\n }\n\n .opportunities-extension-consumption-figure {\n overflow-x: auto;\n overscroll-behavior-inline: contain;\n }\n\n .opportunities-extension-consumption-chart-skeleton {\n min-height: 0;\n padding: 24px 18px 18px;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot {\n min-height: 180px;\n gap: 4px;\n padding: 0 6px;\n }\n\n .opportunities-extension-preferences-options {\n grid-template-columns: 1fr;\n }\n\n .opportunities-extension-stage-filter-controls {\n gap: 6px;\n }\n\n .opportunities-extension-status-filter-controls {\n gap: 6px;\n }\n\n .opportunities-extension-table-surface {\n min-width: 0;\n min-height: calc(100vh - 230px);\n }\n\n .opportunities-extension-debug-panel {\n right: 12px;\n bottom: 12px;\n width: calc(100vw - 24px);\n max-height: calc(100vh - 96px);\n }\n }\n \n/* Full-page diagnostics, scoped to the extension and its current theme. */\n.opportunities-extension-modal .opportunities-extension-debug-panel {\n --debug-surface: #fff;\n --debug-code: #f5f6f7;\n --debug-text: #312d2a;\n --debug-muted: #5f5a55;\n --debug-border: #dedbd7;\n --debug-success: #22613b;\n --debug-success-bg: #e1f1e5;\n --debug-failed: #a12721;\n --debug-failed-bg: #fce8e6;\n --debug-pending: #805000;\n --debug-pending-bg: #fff1ce;\n --debug-info: #075e87;\n --debug-info-bg: #e5f1fa;\n --debug-key: #075e87;\n --debug-string: #22613b;\n --debug-number: #865000;\n --debug-literal: #73429b;\n position: fixed;\n inset: 0;\n z-index: 50;\n display: grid;\n grid-template-rows: auto auto minmax(0, 1fr);\n width: auto;\n height: auto;\n max-height: none;\n min-width: 0;\n box-sizing: border-box;\n overflow: hidden;\n margin: 0;\n padding: 20px;\n border: 0;\n border-radius: 0;\n background: var(--debug-surface);\n color: var(--debug-text);\n color-scheme: light;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel {\n --debug-surface: #292827;\n --debug-code: #222120;\n --debug-text: #f6f4f2;\n --debug-muted: #c9c5c1;\n --debug-border: #514c47;\n --debug-success: #a9e3bd;\n --debug-success-bg: #214d34;\n --debug-failed: #ffb4ab;\n --debug-failed-bg: #582c2a;\n --debug-pending: #ffe099;\n --debug-pending-bg: #59441e;\n --debug-info: #a8d9ff;\n --debug-info-bg: #233f52;\n --debug-key: #8ed6f0;\n --debug-string: #a9e3bd;\n --debug-number: #ffe099;\n --debug-literal: #d6b7f1;\n color: #f6f4f2;\n color-scheme: dark;\n}\n.opportunities-extension-debug-actions { display: flex; gap: 8px; flex: 0 0 auto; }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-list {\n overflow: auto;\n min-height: 0;\n min-width: 0;\n align-content: start;\n scrollbar-gutter: stable;\n padding: 2px 8px 12px 2px;\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item {\n --debug-state: var(--debug-info);\n --debug-state-bg: var(--debug-info-bg);\n border-color: var(--debug-border);\n border-left-color: var(--debug-state);\n background: var(--debug-surface);\n min-width: 0;\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-success { --debug-state: var(--debug-success); --debug-state-bg: var(--debug-success-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-failed { --debug-state: var(--debug-failed); --debug-state-bg: var(--debug-failed-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-pending { --debug-state: var(--debug-pending); --debug-state-bg: var(--debug-pending-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-status {\n color: var(--debug-state);\n background: var(--debug-state-bg);\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status,\n.opportunities-extension-debug-method {\n color: var(--debug-info);\n background: var(--debug-info-bg);\n}\n.opportunities-extension-debug-method {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 0 8px;\n border-radius: 4px;\n font: 700 11px/1.2 Consolas, monospace;\n}\n.opportunities-extension-debug-method[data-method=\"POST\"] { color: var(--debug-literal); background: var(--debug-code); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"2\"] { color: var(--debug-success); background: var(--debug-success-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"4\"],\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"5\"] { color: var(--debug-failed); background: var(--debug-failed-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"pending\"] { color: var(--debug-pending); background: var(--debug-pending-bg); }\n.opportunities-extension-debug-details { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; padding: 0 14px 16px; }\n.opportunities-extension-debug-block { min-width: 0; border-left: 2px solid var(--debug-info); padding-left: 10px; }\n.opportunities-extension-debug-block[data-direction=\"response\"] { border-left-color: var(--debug-success); }\n.opportunities-extension-modal .opportunities-extension-debug-block h3 { margin: 0 0 8px; color: var(--debug-info); font-size: 12px; }\n.opportunities-extension-modal .opportunities-extension-debug-block[data-direction=\"response\"] h3 { color: var(--debug-success); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item pre {\n min-width: 0;\n margin: 0;\n padding: 12px;\n max-height: 380px;\n overflow: auto;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: var(--debug-text);\n background: var(--debug-code);\n line-height: 1.6;\n tab-size: 2;\n}\n.opportunities-extension-debug-json-key { color: var(--debug-key); }\n.opportunities-extension-debug-json-string { color: var(--debug-string); }\n.opportunities-extension-debug-json-number { color: var(--debug-number); }\n.opportunities-extension-debug-json-literal { color: var(--debug-literal); }\n@media (max-width: 760px) {\n .opportunities-extension-modal .opportunities-extension-debug-panel { padding: 12px; }\n .opportunities-extension-debug-details { grid-template-columns: minmax(0, 1fr); }\n}\n.opportunities-extension-debug-tabs {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #dedbd7;\n}\n\n.opportunities-extension-debug-tabs button {\n max-width: 100%;\n min-height: 32px;\n padding: 6px 8px;\n border: 0;\n border-bottom: 2px solid transparent;\n border-radius: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-size: 12px;\n line-height: 1.35;\n overflow-wrap: anywhere;\n cursor: pointer;\n}\n\n.opportunities-extension-debug-tabs button:hover {\n background: #f5f4f2;\n}\n\n.opportunities-extension-debug-tabs button[aria-selected=\"true\"] {\n border-bottom-color: #00758f;\n background: #e8f4f6;\n color: #006b84;\n font-weight: 700;\n}\n\n.opportunities-extension-debug-tabs button:focus-visible,\n.opportunities-extension-debug-list[role=\"tabpanel\"]:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n}\n\n.opportunities-extension-debug-time {\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.opportunities-extension-debug-heading {\n flex-wrap: wrap;\n}\n\n.opportunities-extension-debug-heading strong {\n flex: 1 1 180px;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-debug-summary-meta {\n flex-wrap: wrap;\n justify-content: flex-end;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button {\n color: #f6f4f2;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-heading::before {\n color: #c9c5c1;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs {\n border-bottom-color: #514c47;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button:hover {\n background: #383633;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button[aria-selected=\"true\"] {\n background: #173f48;\n border-bottom-color: #8cc8d3;\n color: #bde7ee;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button:focus-visible,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-list[role=\"tabpanel\"]:focus-visible {\n outline-color: #8cc8d3;\n}\n.opportunities-extension-debug-duration {\n color: #55514d;\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-duration { color: #d6d2ce; }\n\n/* Compact filters use available CSS width, including Windows display scaling. */\n.opportunities-extension-products-progress,\n.opportunities-extension-auth-badge { opacity: 1; transition: opacity 300ms ease; }\n.opportunities-extension-products-progress[data-fading=\"true\"],\n.opportunities-extension-auth-badge[data-fading=\"true\"] { opacity: 0; }\n.opportunities-extension-auth-badge[hidden] { display: none; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-products-progress,\n .opportunities-extension-auth-badge { transition: none; }\n}\n.opportunities-extension-crm-sr-badge {\n flex: 0 0 auto;\n padding: 0 6px;\n border: 1px solid #408254;\n border-radius: 8px;\n font-size: 10px;\n line-height: 18px;\n font-weight: 600;\n white-space: nowrap;\n color: #185b30;\n background: #e1f1e5;\n}\n.opportunities-extension-crm-sr-badge[data-state=\"missing\"] { color: #9f201b; background: #fde8e7; border-color: #c74640; }\n.opportunities-extension-crm-sr-badge[data-state=\"error\"] { color: #785000; background: #fff0cd; border-color: #987021; }\n.opportunities-extension-wl-actions-badge[data-state=\"loading\"] { color: #5f5a55; background: #eceae8; border-color: #8f8a85; }\n.opportunities-extension-crm-sr-badge:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge { color: #b8e4c6; background: #214d34; border-color: #6eac82; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge[data-state=\"missing\"] { color: #ffd9d5; background: #542824; border-color: #ef938b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge[data-state=\"error\"] { color: #ffe0a3; background: #584219; border-color: #c99b4b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-wl-actions-badge[data-state=\"loading\"] { color: #dedbd7; background: #484541; border-color: #8f8a85; }\n\n.opportunities-extension-form {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr)) max-content max-content;\n align-items: end;\n gap: 12px;\n min-height: 0;\n padding: 12px;\n}\n\n.opportunities-extension-form > *,\n.opportunities-extension-badge-filters > section {\n min-width: 0;\n width: 100%;\n max-width: none;\n grid-template-rows: auto 32px;\n gap: 4px;\n font-size: 12px;\n}\n\n.opportunities-extension-form > * > span:first-child,\n.opportunities-extension-badge-filters > section > span:first-child {\n font-size: 12px;\n line-height: 16px;\n}\n\n.opportunities-extension-form .opportunities-extension-select-wrap {\n width: 100%;\n}\n\n.opportunities-extension-form .opportunities-extension-field select,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger,\n.opportunities-extension-form .opportunities-extension-table-search-field input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 32px;\n min-height: 32px;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 20px;\n}\n\n.opportunities-extension-form .opportunities-extension-field select,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger {\n padding-right: 26px;\n}\n\n.opportunities-extension-form .opportunities-extension-select-wrap::after,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger::after {\n right: 10px;\n border-left-width: 4px;\n border-right-width: 4px;\n border-top-width: 5px;\n}\n\n.opportunities-extension-form .opportunities-extension-stage-filter-controls,\n.opportunities-extension-form .opportunities-extension-status-filter-controls {\n flex-wrap: nowrap;\n gap: 4px;\n}\n\n.opportunities-extension-form .opportunities-extension-stage-filter-button,\n.opportunities-extension-form .opportunities-extension-status-filter-button {\n min-height: 28px;\n padding: 4px 7px;\n font-size: 11px;\n line-height: 18px;\n white-space: nowrap;\n}\n\n@media (max-width: 1150px) {\n .opportunities-extension-form {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter {\n grid-column: span 2;\n }\n}\n\n@media (max-width: 700px) {\n .opportunities-extension-form {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .opportunities-extension-form .opportunities-extension-stage-filter-controls,\n .opportunities-extension-form .opportunities-extension-status-filter-controls {\n flex-wrap: wrap;\n }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter {\n grid-template-rows: auto auto;\n }\n}\n\n@media (max-width: 420px) {\n .opportunities-extension-form { grid-template-columns: minmax(0, 1fr); }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter { grid-column: auto; }\n}\n\n.opportunities-extension-badge-filters { display: contents; }\n.opportunities-extension-activity-filter { display: grid; }\n.opportunities-extension-activity-filter[hidden] { display: none; }\n.opportunities-extension-activity-filter-controls { display: flex; align-items: center; flex-wrap: nowrap; gap: 4px; }\n/* Flexible fields share the space left by the four compact badge groups. */\n.opportunities-extension-form[data-activity-filters=\"true\"] {\n grid-template-columns: repeat(4, minmax(0, 1fr)) repeat(4, max-content);\n column-gap: 8px;\n}\n.opportunities-extension-activity-filter-button {\n border: 1px solid currentColor;\n border-radius: 18px;\n min-height: 28px;\n padding: 4px 7px;\n font: inherit;\n font-size: 11px;\n font-weight: 600;\n line-height: 18px;\n white-space: nowrap;\n color: #185b30;\n background: transparent;\n cursor: pointer;\n}\n.opportunities-extension-activity-filter-button[data-value=\"missing\"] { color: #9f201b; }\n.opportunities-extension-activity-filter-button[data-value=\"under4\"] { color: #005f7d; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"] { color: #fff; background: #25653a; border-color: #25653a; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"][data-value=\"missing\"] { background: #a12d27; border-color: #a12d27; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"][data-value=\"under4\"] { background: #006b86; border-color: #006b86; }\n.opportunities-extension-activity-filter-button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter { color: #eeeae6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button { color: #b8e4c6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[data-value=\"missing\"] { color: #ffd9d5; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[data-value=\"under4\"] { color: #b5e9fc; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[aria-pressed=\"true\"] { border-color: currentColor; }\n@media (max-width: 1350px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }\n .opportunities-extension-form[data-activity-filters=\"true\"] .opportunities-extension-badge-filters {\n display: flex;\n grid-column: 1 / -1;\n flex-wrap: wrap;\n align-items: start;\n gap: 12px 20px;\n }\n .opportunities-extension-form[data-activity-filters=\"true\"] .opportunities-extension-badge-filters > section {\n width: auto;\n max-width: 100%;\n grid-template-rows: auto auto;\n }\n}\n@media (max-width: 700px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n .opportunities-extension-activity-filter-controls { flex-wrap: wrap; }\n}\n@media (max-width: 420px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: minmax(0, 1fr); }\n}\n\n/* Keep layout rules on the outer table, never on expanded product tables. */\n.opportunities-extension-table[data-opportunities-layout=\"inline-actions\"] {\n width: 100%;\n min-width: 1120px;\n table-layout: fixed;\n}\n\n/* Fixed table layout shares leftover width only between the two auto columns. */\n.opportunities-extension-table > thead > tr > th[data-column=\"name\"] { width: auto; }\n.opportunities-extension-table > thead > tr > th[data-column=\"customer\"] { width: auto; }\n.opportunities-extension-table > thead > tr > th[data-column=\"owner\"] { width: 132px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"optyNumber\"] { width: 106px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"revenue\"] { width: 124px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"closeDate\"] { width: 100px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"status\"] { width: 114px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"winProbability\"] { width: 110px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"stage\"] { width: 94px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"lastUpdateDate\"] { width: 136px; }\n\n.opportunities-extension-table > tbody > tr > td[data-column] {\n padding: 10px 8px;\n overflow: visible;\n text-overflow: clip;\n white-space: normal;\n font-variant-numeric: tabular-nums;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"name\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"customer\"] {\n position: relative;\n padding-right: 16px;\n padding-left: 12px;\n padding-bottom: 38px;\n vertical-align: top;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"owner\"] {\n padding-right: 16px;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"closeDate\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"lastUpdateDate\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"status\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"stage\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"winProbability\"] {\n white-space: nowrap;\n}\n\n.opportunities-extension-cell-content {\n display: block;\n min-width: 0;\n min-height: 2.7em;\n line-height: 1.35;\n}\n\n.opportunities-extension-cell-content > :first-child {\n display: block;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-cell-actions {\n position: absolute;\n left: 12px;\n right: 16px;\n bottom: 10px;\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 6px;\n height: 24px;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-action-button {\n flex: 0 0 24px;\n width: 24px;\n height: 24px;\n padding: 2px;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"customer\"] .opportunities-extension-cell-actions {\n min-width: 84px;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-action-button svg {\n width: 18px;\n height: 18px;\n}\n\n.opportunities-extension-cell-actions button:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n}\n\n.opportunities-extension-products-ramp {\n display: inline-block;\n min-width: 0;\n max-width: 100%;\n padding: 0 6px;\n border: 1px solid #bba5cf;\n border-radius: 8px;\n background: #f0e8f7;\n color: #63358a;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-ramp {\n background: #43334f;\n color: #ead5fc;\n border-color: #9372ac;\n}\n\n.opportunities-extension-products-ramp[data-missing=\"true\"] {\n background: #fde8e7;\n color: #9f201b;\n border-color: #c74640;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-ramp[data-missing=\"true\"] {\n background: #542824;\n color: #ffd9d5;\n border-color: #ef938b;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column] .opportunities-extension-sort-button {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 12px;\n gap: 6px;\n padding: 10px 8px;\n align-items: center;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column=\"name\"] .opportunities-extension-sort-button,\n.opportunities-extension-table > thead > tr > th[data-column=\"customer\"] .opportunities-extension-sort-button {\n padding-left: 12px;\n padding-right: 16px;\n}\n\n.opportunities-extension-sort-label {\n min-width: 0;\n white-space: normal;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column] .opportunities-extension-sort-button::after {\n position: static;\n justify-self: end;\n}\n.opportunities-extension-crm-sr-badge[type=\"button\"] { cursor: pointer; font-family: inherit; }\n.opportunities-extension-sr-popover {\n position: fixed; z-index: 8; box-sizing: border-box; overflow: auto;\n padding: 12px; border: 1px solid #b9b5b0; border-radius: 6px;\n background: #fff; color: #302e2b; box-shadow: 0 6px 24px #0003;\n font: 12px/1.5 Arial, sans-serif; text-align: left; overflow-wrap: anywhere;\n}\n.opportunities-extension-sr-popover section { padding: 8px 0; }\n.opportunities-extension-sr-popover section + section { border-top: 1px solid #dedbd7; }\n.opportunities-extension-sr-number { display: flex; align-items: center; gap: 8px; padding-right: 30px; font-weight: 600; }\n.opportunities-extension-sr-popover a { color: #00677d; text-decoration: underline; }\n.opportunities-extension-sr-details { white-space: pre-wrap; margin-top: 6px; }\n.opportunities-extension-sr-dismiss {\n position: absolute; top: 6px; right: 6px; width: 28px; height: 28px;\n display: grid; place-items: center; padding: 4px; border: 0;\n background: transparent; color: inherit; cursor: pointer;\n}\n.opportunities-extension-sr-dismiss svg { width: 16px; height: 16px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover { background: #292827; color: #f1efec; border-color: #77716b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover section + section { border-color: #5f5953; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover a { color: #7ddced; }\n.opportunities-extension-title-row {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px 16px;\n min-width: 0;\n flex: 1;\n}\n.opportunities-extension-title-row h1 {\n display: block;\n margin: 0;\n padding: 0;\n line-height: 1;\n}\n.opportunities-extension-title-row .opportunities-extension-subtitle-row {\n display: flex;\n align-items: center;\n align-self: center;\n flex-wrap: wrap;\n gap: 8px;\n margin: 0;\n padding: 0;\n min-width: 0;\n}\n.opportunities-extension-title-row .opportunities-extension-subtitle-row > span {\n box-sizing: border-box;\n margin: 0;\n min-height: 22px;\n line-height: 16px;\n}\n.opportunities-extension-title-row + .opportunities-extension-header-actions { flex-shrink: 0; }\n.opportunities-extension-refresh-all:disabled { opacity: .65; cursor: wait; }\n.opportunities-extension-refresh-all:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-refresh-all[aria-busy=\"true\"] svg { animation: opportunities-refresh-spin 1s linear infinite; }\n@keyframes opportunities-refresh-spin { to { transform: rotate(360deg); } }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-refresh-all[aria-busy=\"true\"] svg { animation: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-install-base-dialog {\n width: min(1700px, 100%);\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header {\n padding: 10px 12px;\n gap: 12px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header h2 {\n font-size: 16px;\n line-height: 22px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header p {\n font-size: 12px;\n line-height: 16px;\n margin-top: 3px;\n overflow-wrap: anywhere;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-icon-button {\n width: 28px;\n height: 28px;\n min-width: 28px;\n min-height: 28px;\n padding: 4px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-customer-table-toolbar {\n padding: 8px 12px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-customer-table-search {\n width: min(320px, 100%);\n height: 32px;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 20px;\n}\n.opportunities-extension-install-base-content {\n min-width: 0;\n min-height: 0;\n overflow: auto;\n scrollbar-gutter: stable;\n}\n.opportunities-extension-install-base-message { margin: 10px 12px; font-size: 12px; line-height: 16px; }\n.opportunities-extension-install-base-table {\n width: 100%; min-width: 1120px; table-layout: fixed; border-collapse: collapse; font-size: 11px;\n}\n.opportunities-extension-install-base-table col { width: 7%; }\n.opportunities-extension-install-base-table .install-base-col-partyName { width: 12%; }\n.opportunities-extension-install-base-table .install-base-col-productGroupName { width: 13%; }\n.opportunities-extension-install-base-table .install-base-col-productName { width: 13%; }\n.opportunities-extension-install-base-table .install-base-col-quantity { width: 5%; }\n.opportunities-extension-install-base-table .install-base-col-quantityType { width: 8%; }\n.opportunities-extension-install-base-table th,\n.opportunities-extension-install-base-table td {\n padding: 8px 6px; text-align: left; vertical-align: middle; overflow-wrap: anywhere;\n border-bottom: 1px solid #e8e5e1; line-height: 1.4;\n}\n.opportunities-extension-install-base-table th { position: sticky; top: 0; z-index: 1; background: #faf9f8; }\n.opportunities-extension-install-base-table td[data-format=\"amount\"],\n.opportunities-extension-install-base-table td[data-format=\"quantity\"] { text-align: right; font-variant-numeric: tabular-nums; }\n.opportunities-extension-install-base-table td[data-format=\"date\"] { white-space: nowrap; }\n.opportunities-extension-install-base-status {\n display: inline-block; padding: 2px 5px; border-radius: 12px; font-size: 10px; font-weight: 600;\n color: #5f5a55; background: #eceae8; white-space: nowrap;\n}\n.opportunities-extension-install-base-status[data-status=\"ACTIVE\"] { color: #17693a; background: #e1f1e5; }\n.opportunities-extension-install-base-status[data-status=\"UNSUPPORTED\"] { color: #855300; background: #fff0d6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-content,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table td { color: #f6f4f2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-message { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-message[role=\"alert\"] { color: #ffb4ab; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th { background: #353331; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table td { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status[data-status=\"ACTIVE\"] { color: #b8e4c6; background: #214d34; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status[data-status=\"UNSUPPORTED\"] { color: #ffdfa2; background: #614418; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-install-base-table .opportunities-extension-account-plans-skeleton-bar { animation: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-service-requests-dialog { width: min(1700px, 100%); }\n.opportunities-extension-service-requests-content { min-width: 0; min-height: 0; overflow: auto; scrollbar-gutter: stable; }\n.opportunities-extension-service-requests-message { margin: 16px; font-size: 13px; }\n.opportunities-extension-service-requests-table {\n width: 100%; min-width: 1200px; table-layout: fixed; border-collapse: collapse; font-size: 12px;\n}\n.opportunities-extension-service-requests-table col { width: 7%; }\n.opportunities-extension-service-requests-table .service-requests-col-name { width: 17%; }\n.opportunities-extension-service-requests-table .service-requests-col-id { width: 10%; }\n.opportunities-extension-service-requests-table .service-requests-col-severity { width: 5%; }\n.opportunities-extension-service-requests-table .service-requests-col-subStatus { width: 14%; }\n.opportunities-extension-service-requests-table .service-requests-col-productName { width: 12%; }\n.opportunities-extension-service-requests-table th,\n.opportunities-extension-service-requests-table td {\n padding: 12px 8px; text-align: left; vertical-align: middle; overflow-wrap: anywhere;\n border-bottom: 1px solid #e8e5e1; line-height: 1.4;\n}\n.opportunities-extension-service-requests-table th { position: sticky; top: 0; z-index: 1; background: #faf9f8; }\n.opportunities-extension-service-requests-table td[data-field=\"created\"],\n.opportunities-extension-service-requests-table td[data-field=\"lastUpdated\"],\n.opportunities-extension-service-requests-table td[data-field=\"id\"] { white-space: nowrap; font-variant-numeric: tabular-nums; }\n.opportunities-extension-service-request-status {\n display: inline-block; padding: 3px 6px; border-radius: 12px; font-size: 10px; font-weight: 600;\n color: #5f5a55; background: #eceae8;\n}\n.opportunities-extension-service-request-status[data-status=\"OPEN\"] { color: #17693a; background: #e1f1e5; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-content,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table td { color: #f6f4f2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-message { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-message[role=\"alert\"] { color: #ffb4ab; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th { background: #353331; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table td { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-request-status { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-request-status[data-status=\"OPEN\"] { color: #b8e4c6; background: #214d34; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-service-requests-table .opportunities-extension-account-plans-skeleton-bar { animation: none; }\n}\n\n/* Scope sizing to Cloud Consumption, not other dialogs sharing its components. */\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header { padding: 10px 12px; gap: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header h2 { font-size: 16px; line-height: 22px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header p { font-size: 12px; line-height: 16px; margin-top: 3px; overflow-wrap: anywhere; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-icon-button { width: 28px; height: 28px; min-width: 28px; min-height: 28px; padding: 4px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-tabs { padding: 4px 12px 0; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-tab { min-height: 30px; padding: 4px 8px; font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-panel { padding: 8px 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details { gap: 0 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details > div { grid-template-columns: minmax(85px, 35%) minmax(0, 1fr); min-height: 32px; padding: 4px 0; gap: 6px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details dt { font-size: 11px; line-height: 16px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details dd { font-size: 12px; line-height: 16px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-trend { margin-top: 8px; padding-top: 6px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-periods button { min-height: 28px; padding: 4px 8px; font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation { grid-template-columns: 28px minmax(120px, auto) 28px; min-height: 30px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation strong { font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation-button { width: 28px; height: 28px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-visual { grid-template-columns: minmax(0, 1fr) 150px; gap: 8px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-svg { height: 100%; max-height: 100%; min-width: 0; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-legend button { font-size: 11px; padding: 4px; gap: 5px; }\n\n/* Small viewports must scroll rather than clip details or collapse the chart. */\n@media (max-height: 560px), (max-width: 700px) {\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-panels { overflow: auto; }\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-panel { height: auto; min-height: 100%; grid-template-rows: auto minmax(280px, 1fr); }\n}\n@media (max-width: 700px) {\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details { grid-template-columns: minmax(0, 1fr); }\n [data-consumption-layout=\"compact\"] .opportunities-extension-consumption-visual { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }\n [data-consumption-layout=\"compact\"] .opportunities-extension-consumption-legend { display: flex; flex-wrap: wrap; }\n}\n\n.opportunities-extension-plan-detail-badges { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }\n.opportunities-extension-consumption-trend-header { align-items: center; justify-content: space-between; gap: 12px; }\n.opportunities-extension-consumption-trend-header > .opportunities-extension-plan-detail-badges { min-width: 0; }\n.opportunities-extension-plan-detail-skeleton { width: 64px; height: 20px; }\n.opportunities-extension-projection-badge {\n display: inline-flex; align-items: center; justify-content: center; border: 1px solid transparent;\n padding: 3px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; line-height: 1.3;\n color: #5f5a55; background: #eceae8; white-space: nowrap;\n}\nbutton.opportunities-extension-projection-badge { cursor: pointer; }\n.opportunities-extension-projection-badge[data-status=\"forfeit\"] { color: #a12424; background: #fbe5e5; }\n.opportunities-extension-projection-badge[data-status=\"overage\"] { color: #185a9d; background: #e0edfc; }\n.opportunities-extension-projection-badge:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-projection-popover {\n position: fixed; z-index: 8; box-sizing: border-box; padding: 14px; overflow: auto; overscroll-behavior: contain;\n border: 1px solid #b9b4ae; border-radius: 4px; background: #ffffff; color: #312d2a;\n box-shadow: 0 4px 16px #0003; font-size: 12px; line-height: 1.4; overflow-wrap: anywhere;\n}\n.opportunities-extension-projection-popover[hidden] { display: none; }\n.opportunities-extension-projection-popover .opportunities-extension-projection-dismiss {\n display: grid; place-items: center; width: 24px; height: 24px; margin-left: auto; margin-bottom: 8px; padding: 4px; border: 1px solid #b9b4ae;\n border-radius: 4px; background: transparent; color: inherit; cursor: pointer; font-size: 12px;\n}\n.opportunities-extension-projection-dismiss svg { width: 14px; height: 14px; }\n.opportunities-extension-projection-line h3 { margin: 0 0 8px; font-size: 12px; }\n.opportunities-extension-projection-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 16px; margin: 0; }\n.opportunities-extension-projection-fields > div { min-width: 0; }\n.opportunities-extension-projection-fields dt { font-weight: 600; color: #5f5a55; font-size: 11px; }\n.opportunities-extension-projection-fields dd { margin: 2px 0 0; font-variant-numeric: tabular-nums; }\n.opportunities-extension-projection-fields a { color: #006d7a; text-decoration: underline; }\n.opportunities-extension-projection-children { margin-top: 14px; padding-left: 12px; border-left: 2px solid #dedbd7; }\n.opportunities-extension-projection-children > section + section { margin-top: 16px; }\n.opportunities-extension-plan-detail-error { color: #a12424; font-size: 12px; }\n.opportunities-extension-projection-empty { color: #5f5a55; font-size: 12px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-popover { color: #f1efec; background: #302e2b; border-color: #716b64; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge[data-status=\"forfeit\"] { color: #ffb9b9; background: #682e32; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge[data-status=\"overage\"] { color: #c5dfff; background: #224b76; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-fields dt,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-empty { color: #cec9c2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-fields a { color: #76dbea; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-plan-detail-error { color: #ffb9b9; }\n@media (max-width: 480px) { .opportunities-extension-projection-fields { grid-template-columns: minmax(0, 1fr); } }\n@media (max-width: 480px) {\n .opportunities-extension-consumption-trend-header > .opportunities-extension-consumption-periods { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n@media (prefers-reduced-motion: reduce) { .opportunities-extension-plan-detail-skeleton { animation: none; } }\n\n.opportunities-extension-account-plan-details > .opportunities-extension-contract-row {\n align-items: center;\n}\n.opportunities-extension-contract-row > dt,\n.opportunities-extension-contract-row > dd,\n.opportunities-extension-contract-ratecard > span {\n line-height: 20px;\n}\n.opportunities-extension-contract-ratecard {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px 10px;\n}\n.opportunities-extension-ratecard-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n align-self: center;\n box-sizing: border-box;\n height: 28px;\n margin: 0;\n flex: 0 0 auto;\n padding: 0 8px;\n border: 1px solid #8aaeb9;\n border-radius: 4px;\n background: #fff;\n color: #006b80;\n font: inherit;\n font-size: 12px;\n font-weight: 600;\n line-height: 20px;\n cursor: pointer;\n}\n.opportunities-extension-ratecard-button:hover { background: #e8f4f6; }\n.opportunities-extension-ratecard-overlay {\n position: absolute;\n inset: 0;\n z-index: 8;\n display: flex;\n justify-content: flex-end;\n overflow: hidden;\n overflow: clip;\n background: rgba(0, 0, 0, 0);\n transition: background-color 320ms ease;\n}\n.opportunities-extension-ratecard-overlay[data-open=\"true\"] { background: rgba(0, 0, 0, .32); }\n.opportunities-extension-ratecard-drawer {\n --ratecard-bg: #fff;\n --ratecard-heading: #faf9f8;\n --ratecard-text: #312d2a;\n --ratecard-muted: #615a55;\n --ratecard-border: #dedbd8;\n --ratecard-accent: #00758f;\n --ratecard-skeleton: #eae7e4;\n display: grid;\n grid-template-rows: auto auto auto minmax(0, 1fr);\n width: min(1520px, calc(100% - 48px));\n height: 100%;\n min-width: 0;\n box-sizing: border-box;\n overflow: hidden;\n background: var(--ratecard-bg);\n color: var(--ratecard-text);\n box-shadow: -6px 0 24px rgba(0, 0, 0, .2);\n transform: translateX(100%);\n transition: transform 320ms cubic-bezier(.22, .61, .36, 1);\n}\n.opportunities-extension-ratecard-overlay[data-open=\"true\"] .opportunities-extension-ratecard-drawer { transform: translateX(0); }\n.opportunities-extension-ratecard-header > div { min-width: 0; overflow-wrap: anywhere; }\n.opportunities-extension-ratecard-plan-details { padding: 12px 20px 0; }\n.opportunities-extension-ratecard-toolbar { display: flex; align-items: center; gap: 16px; padding: 12px 20px; }\n.opportunities-extension-ratecard-search {\n width: min(360px, 100%);\n min-width: 0;\n box-sizing: border-box;\n padding: 9px 12px;\n border: 1px solid var(--ratecard-muted);\n border-radius: 4px;\n background: var(--ratecard-bg);\n color: var(--ratecard-text);\n font: inherit;\n font-size: 13px;\n}\n.opportunities-extension-ratecard-search::placeholder { color: var(--ratecard-muted); opacity: 1; }\n.opportunities-extension-ratecard-count { color: var(--ratecard-muted); font-size: 12px; white-space: nowrap; }\n.opportunities-extension-ratecard-viewport { overflow: auto; min-height: 0; min-width: 0; scrollbar-gutter: stable; }\n.opportunities-extension-ratecard-table { width: 100%; min-width: 1100px; table-layout: fixed; border-collapse: separate; border-spacing: 0; font-size: 12px; }\n.opportunities-extension-ratecard-table th, .opportunities-extension-ratecard-table td {\n padding: 11px 10px;\n border-bottom: 1px solid var(--ratecard-border);\n vertical-align: top;\n overflow-wrap: anywhere;\n text-align: left;\n}\n.opportunities-extension-ratecard-table th { position: sticky; top: 0; z-index: 1; background: var(--ratecard-heading); }\n.opportunities-extension-ratecard-sort {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 12px;\n align-items: center;\n gap: 5px;\n width: 100%;\n padding: 0;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: 600;\n text-align: left;\n cursor: pointer;\n}\n.opportunities-extension-ratecard-sort-icon { color: var(--ratecard-accent); text-align: center; }\n.opportunities-extension-ratecard-table .opportunities-extension-ratecard-numeric { text-align: right; font-variant-numeric: tabular-nums; }\n.opportunities-extension-ratecard-table .opportunities-extension-ratecard-notice { padding: 28px 20px; text-align: center; }\n.opportunities-extension-ratecard-notice [role=\"alert\"] { color: #b3261e; }\n.opportunities-extension-ratecard-skeleton { display: block; width: 85%; height: 14px; border-radius: 3px; background: var(--ratecard-skeleton); animation: opportunities-ratecard-pulse 1.1s ease-in-out infinite alternate; }\n.opportunities-extension-ratecard-drawer :focus-visible, .opportunities-extension-ratecard-button:focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-ratecard-overlay[data-closing=\"true\"] { pointer-events: none; background: rgba(0, 0, 0, 0); transition-duration: 180ms; }\n.opportunities-extension-ratecard-overlay[data-closing=\"true\"] .opportunities-extension-ratecard-drawer { transform: translateX(100%); transition-duration: 180ms; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-drawer {\n --ratecard-bg: #292725;\n --ratecard-heading: #35322f;\n --ratecard-text: #f5f3f1;\n --ratecard-muted: #c2bcb6;\n --ratecard-border: #514c47;\n --ratecard-accent: #59d1e5;\n --ratecard-skeleton: #514c47;\n}\n[data-theme=\"dark\"] .opportunities-extension-ratecard-button { color: #59d1e5; border-color: #6298a2; background: #292725; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-button:hover { background: #313f40; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-notice [role=\"alert\"] { color: #ffb4ab; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-drawer :focus-visible, [data-theme=\"dark\"] .opportunities-extension-ratecard-button:focus-visible { outline-color: #59d1e5; }\n@keyframes opportunities-ratecard-pulse { from { opacity: .45; } to { opacity: 1; } }\n@media (max-width: 720px) {\n .opportunities-extension-ratecard-drawer { width: 100%; }\n .opportunities-extension-ratecard-toolbar { flex-wrap: wrap; gap: 8px; }\n}\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-ratecard-overlay, .opportunities-extension-ratecard-drawer, .opportunities-extension-ratecard-skeleton,\n .opportunities-extension-ratecard-overlay[data-closing=\"true\"], .opportunities-extension-ratecard-overlay[data-closing=\"true\"] .opportunities-extension-ratecard-drawer { animation: none; transition: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-install-base-dialog,\n.opportunities-extension-account-plans-dialog.opportunities-extension-service-requests-dialog {\n grid-template-rows: auto auto minmax(0, 1fr);\n}\n.opportunities-extension-customer-table-toolbar { padding: 12px 16px; border-bottom: 1px solid #dedbd7; }\n.opportunities-extension-customer-table-search {\n box-sizing: border-box;\n width: min(420px, 100%);\n min-width: 0;\n height: 38px;\n padding: 8px 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #fff;\n color: #312d2a;\n font: inherit;\n font-size: 13px;\n}\n.opportunities-extension-customer-table-search::placeholder { color: #5f5a55; opacity: 1; }\n.opportunities-extension-customer-table-search:focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-toolbar { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search { background: #353331; color: #f6f4f2; border-color: #8f8a85; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search::placeholder { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search:focus-visible { outline-color: #59d1e5; }\n"; +const redwoodStyles = "\n .opportunities-extension-scroll-lock {\n overflow: hidden !important;\n }\n\n .opportunities-extension-modal,\n .opportunities-extension-modal * {\n box-sizing: border-box;\n font-family: \"Oracle Sans\", Arial, Helvetica, sans-serif;\n }\n\n .opportunities-extension-modal {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n background: #f5f4f2;\n color: #000000;\n }\n\n .opportunities-extension-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-shell {\n height: 100vh;\n min-height: 0;\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n background: #f5f4f2;\n }\n\n .opportunities-extension-header {\n position: relative;\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 24px;\n padding: 28px 40px 22px;\n border-bottom: 1px solid #dedbd7;\n background:\n linear-gradient(90deg, #8f624a 0 11%, #c74634 11% 23%, #6f5a7f 23% 36%, #00758f 36% 51%, #d4b06a 51% 63%, transparent 63% 100%) top left / 100% 6px no-repeat,\n #ffffff;\n }\n\n .opportunities-extension-header::before {\n position: absolute;\n left: 40px;\n bottom: -1px;\n width: 64px;\n height: 3px;\n background: #00758f;\n content: \"\";\n }\n\n .opportunities-extension-header h1 {\n margin: 0;\n color: #000000;\n font-size: 24px;\n font-weight: 700;\n line-height: 1.2;\n letter-spacing: 0;\n }\n\n .opportunities-extension-header p {\n margin: 0;\n color: #5f5a55;\n font-size: 14px;\n line-height: 1.4;\n }\n\n .opportunities-extension-subtitle-row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n margin-top: 6px;\n }\n\n .opportunities-extension-auth-badge {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n color: #ffffff;\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-auth-badge-authenticated {\n background: #3f6f17;\n }\n\n .opportunities-extension-auth-badge-unauthenticated {\n background: #c5331f;\n }\n\n .opportunities-extension-auth-badge-pending {\n background: #6f5a7f;\n }\n\n .opportunities-extension-products-progress {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n background: #e8f4f6;\n color: #006d7a;\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-products-progress[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-products-cache-timestamp {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n background: #f0eeeb;\n color: #5f5a55;\n font-size: 11px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .opportunities-extension-products-cache-timestamp[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-products-progress[data-state=\"running\"]::before {\n width: 12px;\n height: 12px;\n margin-right: 6px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n content: \"\";\n animation: opportunities-extension-spin .8s linear infinite;\n }\n\n .opportunities-extension-products-progress[data-state=\"complete\"] {\n background: #e2f2e5;\n color: #356d19;\n }\n\n .opportunities-extension-products-progress[data-state=\"complete-with-errors\"],\n .opportunities-extension-products-progress[data-state=\"error\"] {\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n @keyframes opportunities-extension-spin {\n to { transform: rotate(360deg); }\n }\n\n .opportunities-extension-icon-button {\n width: 36px;\n height: 36px;\n flex: 0 0 36px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 18px;\n font-weight: 600;\n line-height: 1;\n cursor: pointer;\n }\n\n .opportunities-extension-header-actions {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n\n .opportunities-extension-icon-button svg {\n width: 18px;\n height: 18px;\n vertical-align: middle;\n }\n\n .opportunities-extension-icon-button .opportunities-extension-settings-icon {\n width: 20px;\n height: 20px;\n }\n\n .opportunities-extension-icon-button:hover,\n .opportunities-extension-icon-button:focus {\n border-color: #b8b2ad;\n background: #f5f4f2;\n outline: none;\n }\n\n .opportunities-extension-body {\n display: grid;\n min-height: 0;\n grid-template-rows: auto auto minmax(0, 1fr);\n gap: 16px;\n padding: 22px 40px 36px;\n background: #f5f4f2;\n overflow: hidden;\n }\n\n .opportunities-extension-form {\n display: flex;\n align-items: end;\n flex-wrap: wrap;\n gap: 24px;\n min-height: 82px;\n max-width: none;\n margin: 0;\n padding: 14px 16px;\n border: 1px solid #dedbd7;\n border-radius: 4px;\n background: #ffffff;\n }\n\n .opportunities-extension-field {\n display: grid;\n max-width: max-content;\n min-width: 270px;\n width: max-content;\n gap: 6px;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-stage-dashboard {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 12px;\n }\n\n .opportunities-extension-stage-dashboard-card {\n display: grid;\n gap: 6px;\n min-width: 0;\n padding: 12px 16px;\n border: 1px solid #dedbd7;\n border-top: 3px solid #5f5a55;\n border-radius: 4px;\n background: #ffffff;\n }\n\n .opportunities-extension-stage-dashboard-card span {\n color: #5f5a55;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-stage-dashboard-value {\n overflow: hidden;\n color: #312d2a;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.2;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"SQL\"] {\n border-top-color: #008aa6;\n }\n\n .opportunities-extension-total-dashboard-card {\n border-top-color: #312d2a;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"PIPELINE\"] {\n border-top-color: #6f6863;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"UPSIDE\"] {\n border-top-color: #c87b00;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"FORECAST\"] {\n border-top-color: #755b8b;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"WON\"] {\n border-top-color: #4b7f22;\n }\n\n .opportunities-extension-stage-filter {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 0;\n }\n\n .opportunities-extension-stage-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-stage-filter-controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n }\n\n .opportunities-extension-stage-filter-button {\n min-height: 36px;\n padding: 6px 12px;\n border: 1px solid currentColor;\n border-radius: 18px;\n background: #ffffff;\n color: #5f5a55;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"SQL\"] {\n color: #006b84;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"PIPELINE\"] {\n color: #5f5a55;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"UPSIDE\"] {\n color: #945400;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"FORECAST\"] {\n color: #624e74;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"WON\"] {\n color: #3f6f17;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"SQL\"] {\n border-color: #006b84;\n background: #006b84;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"PIPELINE\"] {\n border-color: #5f5a55;\n background: #5f5a55;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"UPSIDE\"] {\n border-color: #945400;\n background: #945400;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"FORECAST\"] {\n border-color: #624e74;\n background: #624e74;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"WON\"] {\n border-color: #3f6f17;\n background: #3f6f17;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-status-filter {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 0;\n }\n\n .opportunities-extension-status-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-status-filter-controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n }\n\n .opportunities-extension-status-filter-button {\n min-height: 36px;\n padding: 6px 12px;\n border: 1px solid currentColor;\n border-radius: 18px;\n background: #ffffff;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"OPEN\"] {\n color: #197a3d;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"CLOSED\"] {\n color: #4b5563;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"LOST\"] {\n color: #b13b34;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"WON\"] {\n color: #1f5f99;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"OPEN\"] {\n border-color: #197a3d;\n background: #197a3d;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"CLOSED\"] {\n border-color: #4b5563;\n background: #4b5563;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"LOST\"] {\n border-color: #b13b34;\n background: #b13b34;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"WON\"] {\n border-color: #1f5f99;\n background: #1f5f99;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-customer-filter {\n position: relative;\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 220px;\n }\n\n .opportunities-extension-customer-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-customer-filter-trigger {\n position: relative;\n min-width: 220px;\n min-height: 44px;\n padding: 10px 38px 10px 12px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.3;\n text-align: left;\n cursor: pointer;\n }\n\n .opportunities-extension-customer-filter-trigger::after {\n position: absolute;\n top: 50%;\n right: 16px;\n width: 0;\n height: 0;\n border-top: 6px solid #312d2a;\n border-right: 5px solid transparent;\n border-left: 5px solid transparent;\n content: \"\";\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n .opportunities-extension-customer-filter-trigger:disabled {\n cursor: not-allowed;\n background: #f5f4f2;\n color: #7d7772;\n }\n\n .opportunities-extension-customer-filter-trigger:focus-visible {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-customer-filter-panel {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n z-index: 4;\n display: grid;\n width: min(360px, calc(100vw - 80px));\n gap: 10px;\n padding: 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .18);\n }\n\n .opportunities-extension-customer-filter-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-customer-filter-search {\n width: 100%;\n min-height: 40px;\n padding: 8px 10px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n }\n\n .opportunities-extension-customer-filter-search:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-customer-filter-option {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-customer-filter-select-all {\n min-height: 32px;\n padding-bottom: 8px;\n border-bottom: 1px solid #dedbd7;\n font-weight: 700;\n }\n\n .opportunities-extension-customer-filter-panel input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n flex: 0 0 16px;\n accent-color: #00758f;\n }\n\n .opportunities-extension-customer-filter-list {\n display: block;\n max-height: 250px;\n overflow: auto;\n }\n\n .opportunities-extension-customer-filter-option {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: start;\n min-height: 0;\n height: auto !important;\n padding: 8px 4px;\n cursor: pointer;\n }\n\n .opportunities-extension-customer-filter-option input[type=\"checkbox\"] {\n margin-top: 1px;\n }\n\n .opportunities-extension-customer-filter-option span {\n display: block;\n min-width: 0;\n line-height: 18px;\n overflow-wrap: anywhere;\n white-space: normal;\n }\n\n .opportunities-extension-customer-filter-option:hover {\n background: #f5f4f2;\n }\n\n .opportunities-extension-customer-filter-empty {\n margin: 4px 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-table-search-field {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n width: 260px;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-table-search-field input {\n width: 100%;\n min-height: 44px;\n padding: 10px 12px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.3;\n }\n\n .opportunities-extension-table-search-field input:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-select-wrap {\n position: relative;\n display: block;\n width: 270px;\n max-width: 100%;\n }\n\n .opportunities-extension-select-wrap::after {\n position: absolute;\n top: 50%;\n right: 16px;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-top: 6px solid #000000;\n content: \"\";\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n .opportunities-extension-field select {\n width: 100%;\n min-width: 0;\n max-width: 100%;\n min-height: 44px;\n box-sizing: border-box;\n appearance: none;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #000000;\n font-size: 14px;\n line-height: 1.3;\n padding: 11px 44px 11px 12px;\n }\n\n .opportunities-extension-field select:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-table-surface {\n min-height: 0;\n height: 100%;\n border: 1px solid #dedbd7;\n border-radius: 4px;\n background: #ffffff;\n overflow-x: auto;\n overflow-y: auto;\n }\n\n .opportunities-extension-table {\n width: 100%;\n min-width: 0;\n border-collapse: collapse;\n table-layout: fixed;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-table thead {\n background: #faf9f8;\n }\n\n .opportunities-extension-table th {\n position: sticky;\n top: 0;\n z-index: 1;\n height: 44px;\n border-bottom: 1px solid #b8b2ad;\n background: #faf9f8;\n color: #312d2a;\n font-size: 12px;\n font-weight: 700;\n text-align: left;\n white-space: nowrap;\n }\n\n .opportunities-extension-table td {\n min-height: 48px;\n padding: 12px 16px;\n border-bottom: 1px solid #ebe8e5;\n vertical-align: middle;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-table th:nth-child(1) {\n width: 16%;\n }\n\n .opportunities-extension-table th:nth-child(2) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 18%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 11%;\n }\n\n .opportunities-extension-table th:nth-child(5) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(8) {\n width: 6%;\n }\n\n .opportunities-extension-table th:nth-child(9) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(11) {\n width: 4%;\n }\n\n .opportunities-extension-table td:nth-child(2),\n .opportunities-extension-table td:nth-child(5),\n .opportunities-extension-table td:nth-child(6),\n .opportunities-extension-table td:nth-child(8) {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .opportunities-extension-table td:nth-child(9) {\n padding-right: 6px;\n padding-left: 6px;\n white-space: nowrap;\n overflow: visible;\n }\n\n .opportunities-extension-table td:nth-child(7) {\n padding-right: 6px;\n padding-left: 6px;\n white-space: nowrap;\n overflow: visible;\n }\n\n .opportunities-extension-table td:nth-child(10) {\n padding-right: 6px;\n padding-left: 6px;\n font-size: 12px;\n white-space: nowrap;\n }\n\n .opportunities-extension-table td:nth-child(11) {\n padding-right: 6px;\n padding-left: 6px;\n text-align: center;\n white-space: nowrap;\n }\n\n .opportunities-extension-table tbody tr:hover {\n background: #f7f6f4;\n }\n\n .opportunities-extension-table tbody tr:last-child td {\n border-bottom: 0;\n }\n\n .opportunities-extension-table a {\n color: #006b84;\n text-decoration: underline;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n }\n\n .opportunities-extension-table a:hover {\n color: #004f63;\n }\n\n .opportunities-extension-opty-number-content {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n max-width: 100%;\n }\n\n .opportunities-extension-name-content {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n }\n\n .opportunities-extension-name-content > a {\n min-width: 0;\n }\n\n .opportunities-extension-actions-content {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n white-space: nowrap;\n }\n\n .opportunities-extension-products-count {\n display: inline-grid;\n width: auto;\n min-width: 20px;\n height: 20px;\n place-items: center;\n flex: 0 0 auto;\n box-sizing: border-box;\n padding: 0 3px;\n border: 1px solid #7ca7b2;\n border-radius: 999px;\n background: #e8f4f6;\n color: #006d7a;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n }\n\n .opportunities-extension-products-count:hover,\n .opportunities-extension-products-count:focus-visible,\n .opportunities-extension-products-count[aria-expanded=\"true\"] {\n border-color: #00758f;\n background: #00758f;\n color: #ffffff;\n outline: none;\n }\n\n .opportunities-extension-products-count-error {\n border-color: #d8887e;\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n .opportunities-extension-products-detail-row:hover {\n background: transparent !important;\n }\n\n .opportunities-extension-products-detail-cell {\n padding: 0 !important;\n }\n\n .opportunities-extension-products-detail {\n padding: 14px 20px 18px;\n border-bottom: 1px solid #c9c5c1;\n background: #f0eeeb;\n }\n\n .opportunities-extension-products-detail-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 10px;\n color: #312d2a;\n }\n\n .opportunities-extension-ai-summary {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n margin: 0 0 12px;\n padding: 12px 16px;\n border: 1px solid #dedbd7;\n border-radius: 6px;\n background: #ffffff;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.5;\n text-align: left;\n white-space: normal;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-ai-summary strong {\n display: block;\n font-size: 13px;\n font-weight: 600;\n }\n\n .opportunities-extension-ai-summary p {\n margin: 4px 0 0;\n font: inherit;\n white-space: pre-wrap;\n }\n\n .opportunities-extension-ai-summary-error {\n color: #b42318;\n border-color: #d9928b;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-ai-summary {\n background: #292827;\n color: #f6f4f2;\n border-color: #5f5a55;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-ai-summary-error {\n color: #ffb4ab;\n border-color: #a45c55;\n }\n\n .opportunities-extension-products-detail-heading strong {\n font-size: 13px;\n }\n\n .opportunities-extension-products-detail-heading span {\n color: #5f5a55;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n }\n\n .opportunities-extension-products-table {\n width: 100%;\n table-layout: fixed;\n border-collapse: collapse;\n border: 1px solid #dedbd7;\n background: #ffffff;\n font-size: 12px;\n }\n\n .opportunities-extension-products-table th,\n .opportunities-extension-products-table td {\n position: static;\n height: auto;\n padding: 8px 10px;\n border-bottom: 1px solid #ebe8e5;\n background: transparent;\n overflow-wrap: anywhere;\n vertical-align: middle;\n white-space: normal;\n }\n\n .opportunities-extension-products-table th {\n background: #faf9f8;\n font-size: 11px;\n }\n\n .opportunities-extension-products-table th:nth-child(1) { width: 16%; }\n .opportunities-extension-products-table th:nth-child(2) { width: 16%; }\n .opportunities-extension-products-table th:nth-child(3) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(4) { width: 10%; }\n .opportunities-extension-products-table th:nth-child(5) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(6) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(7) { width: 7%; }\n .opportunities-extension-products-table th:nth-child(8) { width: 10%; }\n .opportunities-extension-products-table th:nth-child(9) { width: 12%; }\n .opportunities-extension-products-table th:nth-child(10) { width: 5%; }\n\n .opportunities-extension-products-empty {\n margin: 0;\n padding: 10px 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-copy-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 24px;\n height: 24px;\n padding: 3px;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-copy-button svg {\n width: 16px;\n height: 16px;\n fill: currentColor;\n }\n\n .opportunities-extension-copy-button:hover,\n .opportunities-extension-copy-button:focus-visible {\n background: #e8f4f6;\n color: #004f63;\n outline: none;\n }\n\n .opportunities-extension-action-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 5px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-action-button svg {\n width: 21px;\n height: 21px;\n }\n\n .opportunities-extension-action-button:hover,\n .opportunities-extension-action-button:focus-visible {\n border-color: #7ca7b2;\n background: #e8f4f6;\n color: #004f63;\n outline: none;\n }\n\n .opportunities-extension-action-button:disabled {\n cursor: wait;\n opacity: .72;\n }\n\n .opportunities-extension-action-button-loading svg {\n animation: opportunities-extension-pulse 1s ease-in-out infinite;\n }\n\n @keyframes opportunities-extension-pulse {\n 50% { opacity: .35; }\n }\n\n .opportunities-extension-copy-toast {\n position: fixed;\n right: 28px;\n bottom: 28px;\n z-index: 3;\n max-width: min(360px, calc(100vw - 56px));\n padding: 12px 16px;\n border-radius: 4px;\n background: #2f6f18;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .18);\n color: #ffffff;\n font-size: 13px;\n font-weight: 700;\n }\n\n .opportunities-extension-copy-toast-error {\n background: #a52b1c;\n }\n\n .opportunities-extension-copy-toast[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-stage-badge {\n display: inline-flex;\n align-items: center;\n min-height: 24px;\n padding: 3px 8px;\n border-radius: 12px;\n background: #ebe8e5;\n color: #312d2a;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"SQL\"] {\n background: #d9f0f5;\n color: #006b84;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"PIPELINE\"] {\n background: #ebe8e5;\n color: #5f5a55;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"UPSIDE\"] {\n background: #fff0d8;\n color: #945400;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"FORECAST\"] {\n background: #eee8f5;\n color: #624e74;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"WON\"] {\n background: #e5f1d9;\n color: #3f6f17;\n }\n\n .opportunities-extension-status-badge {\n display: inline-flex;\n align-items: center;\n min-height: 24px;\n padding: 3px 8px;\n border-radius: 12px;\n background: #ebe8e5;\n color: #312d2a;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n }\n\n .opportunities-extension-status-badge[data-status=\"OPEN\"] {\n background: #e2f2e5;\n color: #197a3d;\n }\n\n .opportunities-extension-status-badge[data-status=\"CLOSED\"] {\n background: #e5e7eb;\n color: #4b5563;\n }\n\n .opportunities-extension-status-badge[data-status=\"LOST\"] {\n background: #f9e3e1;\n color: #b13b34;\n }\n\n .opportunities-extension-status-badge[data-status=\"WON\"] {\n background: #e3edf8;\n color: #1f5f99;\n }\n\n .opportunities-extension-sort-button {\n position: relative;\n display: inline-flex;\n align-items: center;\n width: 100%;\n min-height: 44px;\n padding: 8px 42px 8px 16px;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: inherit;\n letter-spacing: 0;\n line-height: 1.2;\n text-align: left;\n white-space: normal;\n cursor: pointer;\n }\n\n .opportunities-extension-table-header-label {\n display: inline-flex;\n align-items: center;\n min-height: 44px;\n padding: 8px 6px;\n }\n\n .opportunities-extension-sort-button::after {\n position: absolute;\n right: 15px;\n color: #5f5a55;\n content: \"↕\";\n font-size: 16px;\n font-weight: 400;\n }\n\n .opportunities-extension-sort-button[data-sort-direction=\"ascending\"]::after {\n color: #00758f;\n content: \"↑\";\n }\n\n .opportunities-extension-sort-button[data-sort-direction=\"descending\"]::after {\n color: #00758f;\n content: \"↓\";\n }\n\n .opportunities-extension-sort-button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-sort-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n }\n\n .opportunities-extension-table-status {\n height: 152px;\n color: #5f5a55;\n font-size: 14px;\n text-align: center;\n }\n\n .opportunities-extension-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n .opportunities-extension-preferences-modal {\n position: absolute;\n inset: 0;\n z-index: 3;\n display: grid;\n place-items: center;\n padding: 24px;\n background: rgba(0, 0, 0, .42);\n }\n\n .opportunities-extension-preferences-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plans-modal {\n position: absolute;\n inset: 0;\n z-index: 4;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(0, 0, 0, .42);\n }\n\n .opportunities-extension-account-plans-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plans-dialog {\n display: grid;\n width: min(1180px, 100%);\n height: min(760px, calc(100vh - 24px));\n min-width: 0;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-columns: minmax(0, 1fr);\n overflow: hidden;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, .24);\n color: #312d2a;\n }\n\n .opportunities-extension-account-plans-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n padding: 14px 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-header h2 {\n margin: 0;\n font-size: 20px;\n line-height: 1.2;\n }\n\n .opportunities-extension-account-plans-header p {\n margin: 5px 0 0;\n color: #5f5a55;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-account-plans-content {\n display: grid;\n min-width: 0;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-columns: minmax(0, 1fr);\n min-height: 0;\n overflow: hidden;\n }\n\n .opportunities-extension-account-plans-content > .opportunities-extension-account-plans-skeleton {\n grid-row: 1 / -1;\n }\n\n .opportunities-extension-account-plans-tabs-navigation {\n position: relative;\n min-width: 0;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-tabs-navigation .opportunities-extension-account-plans-tab-navigation-button[hidden] {\n display: none;\n }\n\n .opportunities-extension-account-plans-tabs {\n display: flex;\n min-width: 0;\n gap: 4px;\n overflow-x: auto;\n padding: 8px 20px 0;\n scrollbar-width: none;\n }\n\n .opportunities-extension-account-plans-tabs::-webkit-scrollbar {\n display: none;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button {\n display: grid;\n position: absolute;\n z-index: 1;\n top: 50%;\n width: 32px;\n height: 32px;\n place-items: center;\n padding: 0;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n box-shadow: 0 2px 6px rgba(0, 0, 0, .16);\n transform: translateY(-50%);\n cursor: pointer;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:first-child {\n left: 8px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:last-child {\n right: 8px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:hover:not(:disabled) {\n border-color: #00758f;\n background: #f0eeeb;\n color: #005e73;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:disabled {\n border-color: #dedbd7;\n color: #b8b2ad;\n cursor: default;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button svg {\n width: 18px;\n height: 18px;\n }\n\n .opportunities-extension-account-plans-panels {\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n }\n\n .opportunities-extension-account-plan-tab {\n min-height: 38px;\n flex: 0 0 auto;\n padding: 7px 12px;\n border: 0;\n border-bottom: 3px solid transparent;\n background: transparent;\n color: #5f5a55;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n }\n\n .opportunities-extension-account-plan-tab:hover {\n background: #f0eeeb;\n color: #312d2a;\n }\n\n .opportunities-extension-account-plan-tab[aria-selected=\"true\"] {\n border-bottom-color: #00758f;\n color: #006d7a;\n }\n\n .opportunities-extension-account-plan-tab:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n }\n\n .opportunities-extension-account-plan-panel {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n box-sizing: border-box;\n padding: 16px 20px;\n }\n\n .opportunities-extension-account-plan-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plan-details {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0 24px;\n margin: 0;\n }\n\n .opportunities-extension-account-plan-details > div {\n display: grid;\n grid-template-columns: minmax(104px, 38%) minmax(0, 1fr);\n gap: 10px;\n min-height: 42px;\n align-items: center;\n padding: 7px 0;\n border-bottom: 1px solid #ebe8e5;\n }\n\n .opportunities-extension-account-plan-details dt {\n color: #5f5a55;\n font-size: 12px;\n font-weight: 700;\n }\n\n .opportunities-extension-account-plan-details dd {\n min-width: 0;\n margin: 0;\n color: #312d2a;\n font-size: 13px;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-consumption-trend {\n display: grid;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n margin-top: 14px;\n padding-top: 12px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-consumption-trend-header {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 24px;\n }\n\n .opportunities-extension-consumption-periods {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .opportunities-extension-consumption-periods button {\n min-height: 38px;\n padding: 7px 14px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-periods button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-consumption-periods button[aria-pressed=\"true\"] {\n border-color: #00758f;\n background: #e7f6f8;\n color: #005e73;\n }\n\n .opportunities-extension-consumption-periods button:focus-visible,\n .opportunities-extension-consumption-navigation-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-consumption-chart {\n display: grid;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n margin-top: 4px;\n }\n\n .opportunities-extension-consumption-navigation {\n display: grid;\n grid-template-columns: 36px minmax(130px, auto) 36px;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-height: 40px;\n margin-bottom: 2px;\n }\n\n .opportunities-extension-consumption-navigation strong {\n color: #312d2a;\n font-size: 13px;\n text-align: center;\n }\n\n .opportunities-extension-consumption-navigation-button {\n display: grid;\n width: 36px;\n height: 36px;\n place-items: center;\n padding: 0;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-navigation-button:hover:not(:disabled) {\n border-color: #00758f;\n background: #f0eeeb;\n color: #005e73;\n }\n\n .opportunities-extension-consumption-navigation-button:disabled {\n border-color: #dedbd7;\n color: #b8b2ad;\n cursor: default;\n }\n\n .opportunities-extension-consumption-navigation-button svg {\n width: 18px;\n height: 18px;\n }\n\n .opportunities-extension-consumption-figure {\n position: relative;\n min-width: 0;\n min-height: 0;\n margin: 0;\n scrollbar-width: none;\n }\n\n .opportunities-extension-consumption-figure::-webkit-scrollbar {\n display: none;\n }\n\n .opportunities-extension-consumption-visual {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-columns: minmax(0, 1fr) 176px;\n align-items: center;\n gap: 16px;\n }\n\n .opportunities-extension-consumption-svg {\n display: block;\n width: 100%;\n height: 300px;\n min-height: 0;\n overflow: visible;\n }\n\n .opportunities-extension-consumption-svg .consumption-grid-line {\n stroke: #dedbd7;\n stroke-width: 1;\n shape-rendering: crispEdges;\n }\n\n .opportunities-extension-consumption-svg .consumption-axis-label,\n .opportunities-extension-consumption-svg .consumption-x-label {\n fill: #5f5a55;\n font-family: Arial, sans-serif;\n font-size: 12px;\n }\n\n .opportunities-extension-consumption-svg .consumption-value-label {\n fill: #312d2a;\n font-family: Arial, sans-serif;\n font-size: 12px;\n font-weight: 700;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-funded {\n fill: #b77888;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-overage {\n fill: #de7907;\n }\n\n .opportunities-extension-consumption-svg .consumption-average-line {\n stroke: #de7907;\n stroke-width: 1.5;\n stroke-dasharray: 6 6;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group {\n cursor: default;\n outline: none;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group rect {\n transition: filter .16s ease, opacity .16s ease, stroke .16s ease;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group:hover rect,\n .opportunities-extension-consumption-svg .consumption-bar-group:focus rect {\n filter: brightness(1.06);\n stroke: #312d2a;\n stroke-width: 1.5;\n }\n\n .opportunities-extension-consumption-svg .consumption-animated-label {\n opacity: 0;\n animation: opportunities-extension-consumption-label-in .24s ease-out forwards;\n }\n\n .opportunities-extension-consumption-svg .consumption-animated-average {\n opacity: 0;\n animation: opportunities-extension-consumption-average-in .35s .32s ease-out forwards;\n }\n\n @keyframes opportunities-extension-consumption-label-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n @keyframes opportunities-extension-consumption-average-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n .opportunities-extension-consumption-legend {\n display: grid;\n align-content: center;\n gap: 4px;\n }\n\n .opportunities-extension-consumption-legend button {\n display: grid;\n min-width: 0;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n padding: 6px 4px;\n border: 0;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 12px;\n line-height: 1.25;\n text-align: left;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-legend button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-consumption-legend button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 1px;\n }\n\n .opportunities-extension-consumption-legend button[aria-pressed=\"false\"] {\n color: #77726d;\n opacity: .55;\n }\n\n .opportunities-extension-consumption-legend-swatch {\n display: block;\n width: 12px;\n height: 12px;\n justify-self: center;\n }\n\n .opportunities-extension-consumption-legend-funded {\n background: #b77888;\n }\n\n .opportunities-extension-consumption-legend-overage {\n background: #de7907;\n }\n\n .opportunities-extension-consumption-legend-average {\n height: 0;\n border-top: 2px dashed #de7907;\n }\n\n .opportunities-extension-consumption-tooltip {\n position: absolute;\n z-index: 2;\n display: grid;\n min-width: 190px;\n max-width: 260px;\n gap: 4px;\n padding: 10px 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .2);\n color: #312d2a;\n font-size: 12px;\n line-height: 1.3;\n pointer-events: none;\n }\n\n .opportunities-extension-consumption-tooltip[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-consumption-tooltip strong {\n margin-bottom: 2px;\n font-size: 13px;\n }\n\n .opportunities-extension-consumption-chart-skeleton {\n height: 100%;\n min-height: 0;\n padding: 34px 62px 24px;\n box-sizing: border-box;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot {\n display: flex;\n height: 100%;\n min-height: 220px;\n align-items: flex-end;\n justify-content: space-around;\n gap: 12px;\n padding: 0 14px;\n border-bottom: 1px solid #dedbd7;\n border-left: 1px solid #dedbd7;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot span {\n width: min(38px, 6%);\n border-radius: 2px 2px 0 0;\n background: #dedbd7;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-consumption-chart-empty,\n .opportunities-extension-consumption-chart-error {\n display: grid;\n min-height: 220px;\n place-items: center;\n margin: 0;\n color: #5f5a55;\n font-size: 14px;\n text-align: center;\n }\n\n .opportunities-extension-consumption-chart-error {\n color: #9f2d20;\n }\n\n .opportunities-extension-account-plan-status-indicator {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #9b9691;\n box-shadow: 0 0 0 3px #efedeb;\n vertical-align: middle;\n }\n\n .opportunities-extension-account-plan-status-indicator[data-active=\"true\"] {\n background: #3f6f17;\n box-shadow: 0 0 0 3px #e2f2e5;\n }\n\n .opportunities-extension-account-plan-tab .opportunities-extension-account-plan-status-indicator {\n margin-right: 8px;\n }\n\n .opportunities-extension-account-plans-skeleton-tabs {\n display: flex;\n min-height: 46px;\n align-items: center;\n padding: 0 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n overflow: hidden;\n }\n\n .opportunities-extension-account-plans-skeleton-panel {\n padding: 16px 20px;\n }\n\n .opportunities-extension-account-plans-skeleton-tab {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n min-height: 38px;\n padding: 0 12px;\n border-bottom: 3px solid #00758f;\n }\n\n .opportunities-extension-account-plans-skeleton-status {\n display: block;\n width: 10px;\n height: 10px;\n flex: 0 0 auto;\n border-radius: 50%;\n background: #dedbd7;\n box-shadow: 0 0 0 3px #efedeb;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-account-plans-skeleton-details {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0 24px;\n padding: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details > div {\n display: grid;\n grid-template-columns: minmax(104px, 38%) minmax(0, 1fr);\n align-items: center;\n gap: 10px;\n min-height: 42px;\n padding: 7px 0;\n border-bottom: 1px solid #ebe8e5;\n }\n\n .opportunities-extension-account-plans-skeleton-bar {\n display: block;\n height: 12px;\n border-radius: 3px;\n background: #dedbd7;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-account-plans-skeleton-tabs .opportunities-extension-account-plans-skeleton-bar {\n height: 14px;\n }\n\n .opportunities-extension-account-plans-skeleton-label {\n width: 74%;\n height: 10px;\n }\n\n .opportunities-extension-account-plans-skeleton-trend {\n display: grid;\n min-height: 0;\n grid-template-rows: auto auto minmax(0, 1fr);\n margin: 14px 0 0;\n padding-top: 12px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton-trend-header {\n display: flex;\n justify-content: flex-end;\n min-height: 38px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods .opportunities-extension-account-plans-skeleton-bar {\n height: 12px;\n }\n\n .opportunities-extension-account-plans-skeleton-period-active {\n height: 38px !important;\n border: 1px solid #8cc8d3;\n background: #e7f6f8;\n }\n\n .opportunities-extension-account-plans-skeleton-navigation {\n display: grid;\n grid-template-columns: 32px 124px 32px;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-height: 54px;\n }\n\n .opportunities-extension-account-plans-skeleton-navigation .opportunities-extension-account-plans-skeleton-bar {\n justify-self: center;\n }\n\n .opportunities-extension-account-plans-skeleton-chart {\n display: grid;\n min-height: 0;\n grid-template-columns: minmax(0, 1fr) 150px;\n align-items: center;\n gap: 28px;\n padding: 12px 14px 0 62px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot {\n display: flex;\n position: relative;\n height: 300px;\n min-height: 0;\n box-sizing: border-box;\n align-items: flex-end;\n justify-content: space-around;\n gap: 12px;\n padding: 0 14px 64px;\n background: repeating-linear-gradient(to bottom, transparent 0, transparent 58px, #ebe8e5 58px, #ebe8e5 59px) left top / 100% 236px no-repeat;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::before,\n .opportunities-extension-account-plans-skeleton-plot::after {\n position: absolute;\n display: block;\n content: \"\";\n background: #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::before {\n top: 0;\n bottom: 64px;\n left: 0;\n width: 1px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::after {\n right: 0;\n bottom: 64px;\n left: 0;\n height: 1px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot .opportunities-extension-account-plans-skeleton-bar {\n width: min(38px, 7%);\n flex: 0 1 38px;\n border-radius: 2px 2px 0 0;\n }\n\n .opportunities-extension-account-plans-skeleton-legend {\n display: grid;\n align-content: center;\n gap: 18px;\n min-height: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-legend .opportunities-extension-account-plans-skeleton-bar {\n height: 11px;\n }\n\n @keyframes opportunities-extension-skeleton-pulse {\n from { opacity: .48; }\n to { opacity: 1; }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .opportunities-extension-account-plans-skeleton-bar,\n .opportunities-extension-consumption-chart-skeleton-plot span,\n .opportunities-extension-consumption-svg .consumption-animated-label,\n .opportunities-extension-consumption-svg .consumption-animated-average {\n animation: none;\n opacity: 1;\n }\n }\n\n .opportunities-extension-account-plans-empty,\n .opportunities-extension-account-plans-error {\n margin: 0;\n padding: 28px 20px;\n color: #5f5a55;\n font-size: 14px;\n }\n\n .opportunities-extension-account-plans-error {\n color: #9f2d20;\n }\n\n .opportunities-extension-preferences-dialog {\n display: grid;\n width: min(680px, 100%);\n max-height: min(720px, calc(100vh - 48px));\n grid-template-rows: auto minmax(0, 1fr) auto;\n overflow: hidden;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, .24);\n color: #312d2a;\n }\n\n .opportunities-extension-preferences-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 18px 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-preferences-header h2 {\n margin: 0;\n font-size: 20px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-preferences-content {\n min-height: 0;\n overflow: auto;\n padding: 20px;\n }\n\n .opportunities-extension-preferences-fieldset {\n min-width: 0;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n .opportunities-extension-preferences-fieldset legend {\n margin-bottom: 12px;\n padding: 0;\n color: #312d2a;\n font-size: 15px;\n font-weight: 700;\n line-height: 1.3;\n }\n\n .opportunities-extension-preferences-options {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 4px 20px;\n }\n\n .opportunities-extension-preferences-option {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 0;\n padding: 9px 8px;\n border-radius: 4px;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.35;\n cursor: pointer;\n }\n\n .opportunities-extension-preferences-option:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-preferences-option input {\n width: 18px;\n height: 18px;\n flex: 0 0 18px;\n margin: 0;\n accent-color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-preferences-cache-field {\n display: grid;\n width: min(280px, 100%);\n gap: 6px;\n margin-top: 24px;\n color: #312d2a;\n font-size: 14px;\n font-weight: 700;\n }\n\n .opportunities-extension-preferences-cache-field select {\n width: 100%;\n height: 40px;\n padding: 0 36px 0 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n font-weight: 400;\n }\n\n .opportunities-extension-preferences-cache-field select:focus {\n border-color: #00758f;\n outline: 2px solid #bde7ee;\n outline-offset: 0;\n }\n\n .opportunities-extension-preferences-footer {\n display: flex;\n justify-content: flex-end;\n padding: 14px 20px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-button {\n min-width: 88px;\n min-height: 36px;\n padding: 7px 16px;\n border: 1px solid transparent;\n border-radius: 4px;\n font-size: 14px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-button-primary {\n border-color: #00758f;\n background: #00758f;\n color: #ffffff;\n }\n\n .opportunities-extension-button-primary:hover,\n .opportunities-extension-button-primary:focus-visible {\n border-color: #005e73;\n background: #005e73;\n outline: none;\n }\n\n .opportunities-extension-debug-panel {\n position: fixed;\n right: 24px;\n bottom: 24px;\n z-index: 1;\n width: min(640px, calc(100vw - 48px));\n max-height: min(560px, calc(100vh - 120px));\n overflow: auto;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 2px 8px rgba(0, 0, 0, .16);\n padding: 16px;\n color: #000000;\n }\n\n .opportunities-extension-debug-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-debug-panel h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n line-height: 1.25;\n }\n\n .opportunities-extension-debug-panel p {\n margin: 4px 0 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-debug-panel-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 12px;\n }\n\n .opportunities-extension-debug-visibility-button {\n width: 34px;\n height: 34px;\n flex: 0 0 34px;\n color: #312d2a;\n }\n\n .opportunities-extension-debug-visibility-button svg {\n width: 20px;\n height: 20px;\n }\n\n .opportunities-extension-debug-list {\n display: grid;\n gap: 10px;\n }\n\n .opportunities-extension-debug-item {\n border: 1px solid #dedbd7;\n border-left-width: 4px;\n border-radius: 4px;\n background: #faf9f8;\n }\n\n .opportunities-extension-debug-item[open] {\n background: #ffffff;\n }\n\n .opportunities-extension-debug-item-success {\n border-left-color: #3f6f17;\n }\n\n .opportunities-extension-debug-item-success .opportunities-extension-debug-status {\n background: #e2f2e5;\n color: #356d19;\n }\n\n .opportunities-extension-debug-item-failed {\n border-left-color: #c5331f;\n }\n\n .opportunities-extension-debug-item-failed .opportunities-extension-debug-status {\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n .opportunities-extension-debug-item-pending {\n border-left-color: #6f5a7f;\n }\n\n .opportunities-extension-debug-item-pending .opportunities-extension-debug-status {\n background: #eee8f2;\n color: #6f5a7f;\n }\n\n .opportunities-extension-debug-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n min-height: 42px;\n padding: 9px 12px 9px 10px;\n cursor: pointer;\n list-style: none;\n }\n\n .opportunities-extension-debug-heading::-webkit-details-marker {\n display: none;\n }\n\n .opportunities-extension-debug-heading::before {\n content: \"⌄\";\n width: 14px;\n color: #5f5a55;\n font-size: 16px;\n line-height: 1;\n transform: rotate(-90deg);\n transition: transform .15s ease;\n }\n\n .opportunities-extension-debug-item[open] .opportunities-extension-debug-heading::before {\n transform: rotate(0deg);\n }\n\n .opportunities-extension-debug-summary-meta {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n }\n\n .opportunities-extension-debug-http-status,\n .opportunities-extension-debug-status {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n line-height: 1;\n text-transform: uppercase;\n }\n\n .opportunities-extension-debug-http-status {\n background: #e8f4f6;\n color: #006d7a;\n }\n\n .opportunities-extension-debug-status {\n background: #ebe8e5;\n color: #5f5a55;\n }\n\n .opportunities-extension-debug-heading strong {\n font-size: 13px;\n }\n\n .opportunities-extension-debug-item pre {\n margin: 0;\n padding: 8px 12px 12px;\n color: #312d2a;\n font-family: Consolas, \"Courier New\", monospace;\n font-size: 12px;\n line-height: 1.45;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .opportunities-extension-debug-empty {\n padding: 14px;\n border: 1px dashed #b8b2ad;\n border-radius: 4px;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] {\n background: #1f1f1f;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-shell,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-body {\n background: #1f1f1f;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header {\n border-bottom-color: #4e4a46;\n background:\n linear-gradient(90deg, #a8795d 0 11%, #dd5a47 11% 23%, #876e9b 23% 36%, #00a6be 36% 51%, #dfbd76 51% 63%, transparent 63% 100%) top left / 100% 6px no-repeat,\n #292827;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header h1,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-value,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-field,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card span,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail-heading span,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details dt,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-empty {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-error {\n color: #ffb4a8;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-error {\n color: #ffb4a8;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-bar {\n background: #5b5753;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-status {\n background: #5b5753;\n box-shadow: 0 0 0 3px #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-period-active {\n border-color: #3f7580;\n background: #23474e;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-skeleton-plot span {\n background: #5b5753;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-status-indicator {\n background: #8f8a85;\n box-shadow: 0 0 0 3px #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-status-indicator[data-active=\"true\"] {\n background: #7fb05b;\n box-shadow: 0 0 0 3px #314527;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-form,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-surface,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-panel,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-dialog,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-dialog,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item[open] {\n border-color: #4e4a46;\n background: #292827;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-search,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field input,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-field select,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-cache-field select,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger::after {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-select-wrap::after {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger:disabled {\n background: #292827;\n color: #918b86;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-search::placeholder,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field input::placeholder {\n color: #b5b0ab;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-option,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-header h2,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header h2,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-fieldset legend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-cache-field,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail-heading,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details dd,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-heading,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item pre,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel h2 {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation strong {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-empty {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table th {\n border-bottom-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-header,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-footer,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tabs-navigation,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tabs,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details > div,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-tabs,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-details > div {\n border-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-trend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-skeleton-plot,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-trend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot {\n border-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot {\n background: repeating-linear-gradient(to bottom, transparent 0, transparent 58px, #4e4a46 58px, #4e4a46 59px) left top / 100% 236px no-repeat;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot::before,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot::after {\n background: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab:hover {\n background: #3b3937;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab[aria-selected=\"true\"] {\n border-bottom-color: #43c4d5;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button[aria-pressed=\"true\"] {\n border-color: #43c4d5;\n background: #173e43;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button:hover:not(:disabled),\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button:hover:not(:disabled) {\n border-color: #43c4d5;\n background: #3b3937;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button:disabled,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button:disabled {\n border-color: #4e4a46;\n color: #746f6a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-grid-line {\n stroke: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-axis-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-x-label {\n fill: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-value-label {\n fill: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-funded {\n fill: #ca8798;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-overage {\n fill: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-average-line {\n stroke: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-group:hover rect,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-group:focus rect {\n stroke: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button[aria-pressed=\"false\"] {\n color: #a8a39e;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-funded {\n background: #ca8798;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-overage {\n background: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-average {\n border-top-color: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-tooltip {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option input {\n accent-color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary {\n border-color: #00a6be;\n background: #008aa6;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary:focus-visible {\n border-color: #43c4d5;\n background: #006d7a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-option:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table tbody tr:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sort-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button:focus {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table thead,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table th,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table th {\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table td {\n border-bottom-color: #3f3c39;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail {\n border-bottom-color: #4e4a46;\n background: #252423;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table th,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table td {\n border-bottom-color: #3f3c39;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count {\n border-color: #2f9bae;\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count:focus-visible,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count[aria-expanded=\"true\"] {\n border-color: #43c4d5;\n background: #008aa6;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"running\"] {\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"complete\"] {\n background: #244f2e;\n color: #a8dfb7;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"complete-with-errors\"],\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"error\"],\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count-error {\n border-color: #b13b34;\n background: #5f2926;\n color: #ffb4ad;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-cache-timestamp {\n background: #3b3937;\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table a,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button {\n color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table a:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button:focus-visible,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button:focus-visible {\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"SQL\"] {\n color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"PIPELINE\"] {\n color: #d1cbc6;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"UPSIDE\"] {\n color: #ffbf62;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"FORECAST\"] {\n color: #d2b7e9;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"WON\"] {\n color: #9bd46a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"SQL\"] {\n border-top-color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-total-dashboard-card {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"PIPELINE\"] {\n border-top-color: #c0b9b3;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"UPSIDE\"] {\n border-top-color: #ffb84d;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"FORECAST\"] {\n border-top-color: #cba7e7;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"WON\"] {\n border-top-color: #92cf5b;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"SQL\"] {\n border-color: #008aa6;\n background: #008aa6;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"PIPELINE\"] {\n border-color: #6f6863;\n background: #6f6863;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"UPSIDE\"] {\n border-color: #b96e00;\n background: #b96e00;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"FORECAST\"] {\n border-color: #755b8b;\n background: #755b8b;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"WON\"] {\n border-color: #4b7f22;\n background: #4b7f22;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"OPEN\"] {\n color: #69c985;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"CLOSED\"] {\n color: #c3cad3;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"LOST\"] {\n color: #ff9d94;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"WON\"] {\n color: #83bfff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"OPEN\"] {\n border-color: #197a3d;\n background: #197a3d;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"CLOSED\"] {\n border-color: #4b5563;\n background: #4b5563;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"LOST\"] {\n border-color: #b13b34;\n background: #b13b34;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"WON\"] {\n border-color: #1f5f99;\n background: #1f5f99;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item {\n border-color: #4e4a46;\n background: #252423;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button {\n color: #f6f4f2;\n }\n\n @media (min-width: 1201px) and (max-width: 1450px) {\n .opportunities-extension-table th:nth-child(1) {\n width: 16%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 18%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 12%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 10%;\n }\n }\n\n @media (max-width: 1200px) {\n .opportunities-extension-table {\n min-width: 1180px;\n }\n\n .opportunities-extension-table th:nth-child(1) {\n width: 15%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 17%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 13%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 6%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 9%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 11%;\n }\n }\n\n @media (max-width: 700px) {\n .opportunities-extension-header {\n padding: 24px 20px 18px;\n }\n\n .opportunities-extension-header::before {\n left: 20px;\n }\n\n .opportunities-extension-header h1 {\n font-size: 22px;\n }\n\n .opportunities-extension-header p {\n font-size: 14px;\n }\n\n .opportunities-extension-body {\n padding: 16px 20px 24px;\n }\n\n .opportunities-extension-form {\n align-items: stretch;\n flex-wrap: wrap;\n gap: 14px;\n min-height: auto;\n padding: 12px;\n }\n\n .opportunities-extension-field {\n max-width: none;\n width: 100%;\n }\n\n .opportunities-extension-customer-filter {\n width: 100%;\n }\n\n .opportunities-extension-customer-filter-trigger {\n width: 100%;\n }\n\n .opportunities-extension-customer-filter-panel {\n width: min(360px, calc(100vw - 64px));\n }\n\n .opportunities-extension-table-search-field {\n width: 100%;\n }\n\n .opportunities-extension-stage-dashboard {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .opportunities-extension-stage-dashboard-value {\n font-size: 18px;\n }\n\n .opportunities-extension-preferences-modal {\n padding: 12px;\n }\n\n .opportunities-extension-account-plans-modal {\n padding: 12px;\n }\n\n .opportunities-extension-preferences-dialog {\n max-height: calc(100vh - 24px);\n }\n\n .opportunities-extension-account-plans-dialog {\n height: calc(100vh - 24px);\n }\n\n .opportunities-extension-account-plan-panel {\n padding: 12px 14px;\n }\n\n .opportunities-extension-account-plan-details {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0 14px;\n }\n\n .opportunities-extension-account-plan-details > div {\n grid-template-columns: 1fr;\n align-content: center;\n gap: 3px;\n min-height: 54px;\n padding: 5px 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0 14px;\n padding: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details > div {\n grid-template-columns: 1fr;\n align-content: center;\n gap: 5px;\n min-height: 54px;\n padding: 5px 0;\n }\n\n .opportunities-extension-account-plans-skeleton-trend {\n margin: 14px 0 0;\n }\n\n .opportunities-extension-account-plans-skeleton-periods {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n align-items: center;\n gap: 6px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods .opportunities-extension-account-plans-skeleton-bar {\n width: 100% !important;\n }\n\n .opportunities-extension-account-plans-skeleton-chart {\n grid-template-columns: minmax(0, 1fr);\n gap: 12px;\n padding: 12px 8px 0 34px;\n }\n\n .opportunities-extension-account-plans-skeleton-legend {\n display: flex;\n min-height: 24px;\n align-items: center;\n justify-content: center;\n gap: 12px;\n }\n\n .opportunities-extension-consumption-trend-header {\n align-items: stretch;\n }\n\n .opportunities-extension-consumption-periods {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 3px;\n }\n\n .opportunities-extension-consumption-periods button {\n min-width: 0;\n padding: 7px 4px;\n font-size: 12px;\n }\n\n .opportunities-extension-consumption-chart {\n min-height: 0;\n }\n\n .opportunities-extension-consumption-svg {\n width: 760px;\n height: 245px;\n }\n\n .opportunities-extension-consumption-visual {\n width: 920px;\n grid-template-columns: 760px 144px;\n gap: 12px;\n }\n\n .opportunities-extension-consumption-figure {\n overflow-x: auto;\n overscroll-behavior-inline: contain;\n }\n\n .opportunities-extension-consumption-chart-skeleton {\n min-height: 0;\n padding: 24px 18px 18px;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot {\n min-height: 180px;\n gap: 4px;\n padding: 0 6px;\n }\n\n .opportunities-extension-preferences-options {\n grid-template-columns: 1fr;\n }\n\n .opportunities-extension-stage-filter-controls {\n gap: 6px;\n }\n\n .opportunities-extension-status-filter-controls {\n gap: 6px;\n }\n\n .opportunities-extension-table-surface {\n min-width: 0;\n min-height: calc(100vh - 230px);\n }\n\n .opportunities-extension-debug-panel {\n right: 12px;\n bottom: 12px;\n width: calc(100vw - 24px);\n max-height: calc(100vh - 96px);\n }\n }\n \n/* Full-page diagnostics, scoped to the extension and its current theme. */\n.opportunities-extension-modal .opportunities-extension-debug-panel {\n --debug-surface: #fff;\n --debug-code: #f5f6f7;\n --debug-text: #312d2a;\n --debug-muted: #5f5a55;\n --debug-border: #dedbd7;\n --debug-success: #22613b;\n --debug-success-bg: #e1f1e5;\n --debug-failed: #a12721;\n --debug-failed-bg: #fce8e6;\n --debug-pending: #805000;\n --debug-pending-bg: #fff1ce;\n --debug-info: #075e87;\n --debug-info-bg: #e5f1fa;\n --debug-key: #075e87;\n --debug-string: #22613b;\n --debug-number: #865000;\n --debug-literal: #73429b;\n position: fixed;\n inset: 0;\n z-index: 50;\n display: grid;\n grid-template-rows: auto auto minmax(0, 1fr);\n width: auto;\n height: auto;\n max-height: none;\n min-width: 0;\n box-sizing: border-box;\n overflow: hidden;\n margin: 0;\n padding: 20px;\n border: 0;\n border-radius: 0;\n background: var(--debug-surface);\n color: var(--debug-text);\n color-scheme: light;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel {\n --debug-surface: #292827;\n --debug-code: #222120;\n --debug-text: #f6f4f2;\n --debug-muted: #c9c5c1;\n --debug-border: #514c47;\n --debug-success: #a9e3bd;\n --debug-success-bg: #214d34;\n --debug-failed: #ffb4ab;\n --debug-failed-bg: #582c2a;\n --debug-pending: #ffe099;\n --debug-pending-bg: #59441e;\n --debug-info: #a8d9ff;\n --debug-info-bg: #233f52;\n --debug-key: #8ed6f0;\n --debug-string: #a9e3bd;\n --debug-number: #ffe099;\n --debug-literal: #d6b7f1;\n color: #f6f4f2;\n color-scheme: dark;\n}\n.opportunities-extension-debug-actions { display: flex; gap: 8px; flex: 0 0 auto; }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-list {\n overflow: auto;\n min-height: 0;\n min-width: 0;\n align-content: start;\n scrollbar-gutter: stable;\n padding: 2px 8px 12px 2px;\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item {\n --debug-state: var(--debug-info);\n --debug-state-bg: var(--debug-info-bg);\n border-color: var(--debug-border);\n border-left-color: var(--debug-state);\n background: var(--debug-surface);\n min-width: 0;\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-success { --debug-state: var(--debug-success); --debug-state-bg: var(--debug-success-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-failed { --debug-state: var(--debug-failed); --debug-state-bg: var(--debug-failed-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-pending { --debug-state: var(--debug-pending); --debug-state-bg: var(--debug-pending-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-status {\n color: var(--debug-state);\n background: var(--debug-state-bg);\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status,\n.opportunities-extension-debug-method {\n color: var(--debug-info);\n background: var(--debug-info-bg);\n}\n.opportunities-extension-debug-method {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 0 8px;\n border-radius: 4px;\n font: 700 11px/1.2 Consolas, monospace;\n}\n.opportunities-extension-debug-method[data-method=\"POST\"] { color: var(--debug-literal); background: var(--debug-code); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"2\"] { color: var(--debug-success); background: var(--debug-success-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"4\"],\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"5\"] { color: var(--debug-failed); background: var(--debug-failed-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"pending\"] { color: var(--debug-pending); background: var(--debug-pending-bg); }\n.opportunities-extension-debug-details { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; padding: 0 14px 16px; }\n.opportunities-extension-debug-block { min-width: 0; border-left: 2px solid var(--debug-info); padding-left: 10px; }\n.opportunities-extension-debug-block[data-direction=\"response\"] { border-left-color: var(--debug-success); }\n.opportunities-extension-modal .opportunities-extension-debug-block h3 { margin: 0 0 8px; color: var(--debug-info); font-size: 12px; }\n.opportunities-extension-modal .opportunities-extension-debug-block[data-direction=\"response\"] h3 { color: var(--debug-success); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item pre {\n min-width: 0;\n margin: 0;\n padding: 12px;\n max-height: 380px;\n overflow: auto;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: var(--debug-text);\n background: var(--debug-code);\n line-height: 1.6;\n tab-size: 2;\n}\n.opportunities-extension-debug-json-key { color: var(--debug-key); }\n.opportunities-extension-debug-json-string { color: var(--debug-string); }\n.opportunities-extension-debug-json-number { color: var(--debug-number); }\n.opportunities-extension-debug-json-literal { color: var(--debug-literal); }\n@media (max-width: 760px) {\n .opportunities-extension-modal .opportunities-extension-debug-panel { padding: 12px; }\n .opportunities-extension-debug-details { grid-template-columns: minmax(0, 1fr); }\n}\n.opportunities-extension-debug-tabs {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #dedbd7;\n}\n\n.opportunities-extension-debug-tabs button {\n max-width: 100%;\n min-height: 32px;\n padding: 6px 8px;\n border: 0;\n border-bottom: 2px solid transparent;\n border-radius: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-size: 12px;\n line-height: 1.35;\n overflow-wrap: anywhere;\n cursor: pointer;\n}\n\n.opportunities-extension-debug-tabs button:hover {\n background: #f5f4f2;\n}\n\n.opportunities-extension-debug-tabs button[aria-selected=\"true\"] {\n border-bottom-color: #00758f;\n background: #e8f4f6;\n color: #006b84;\n font-weight: 700;\n}\n\n.opportunities-extension-debug-tabs button:focus-visible,\n.opportunities-extension-debug-list[role=\"tabpanel\"]:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n}\n\n.opportunities-extension-debug-time {\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.opportunities-extension-debug-heading {\n flex-wrap: wrap;\n}\n\n.opportunities-extension-debug-heading strong {\n flex: 1 1 180px;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-debug-summary-meta {\n flex-wrap: wrap;\n justify-content: flex-end;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button {\n color: #f6f4f2;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-heading::before {\n color: #c9c5c1;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs {\n border-bottom-color: #514c47;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button:hover {\n background: #383633;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button[aria-selected=\"true\"] {\n background: #173f48;\n border-bottom-color: #8cc8d3;\n color: #bde7ee;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button:focus-visible,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-list[role=\"tabpanel\"]:focus-visible {\n outline-color: #8cc8d3;\n}\n.opportunities-extension-debug-duration {\n color: #55514d;\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-duration { color: #d6d2ce; }\n\n/* Compact filters use available CSS width, including Windows display scaling. */\n.opportunities-extension-products-progress,\n.opportunities-extension-auth-badge { opacity: 1; transition: opacity 300ms ease; }\n.opportunities-extension-products-progress[data-fading=\"true\"],\n.opportunities-extension-auth-badge[data-fading=\"true\"] { opacity: 0; }\n.opportunities-extension-auth-badge[hidden] { display: none; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-products-progress,\n .opportunities-extension-auth-badge { transition: none; }\n}\n.opportunities-extension-crm-sr-badge {\n border: 1px solid #408254;\n color: #185b30;\n background: #e1f1e5;\n}\n.opportunities-extension-crm-sr-badge[data-state=\"missing\"] { color: #9f201b; background: #fde8e7; border-color: #c74640; }\n.opportunities-extension-crm-sr-badge[data-state=\"error\"] { color: #785000; background: #fff0cd; border-color: #987021; }\n.opportunities-extension-wl-actions-badge[data-state=\"loading\"] { color: #5f5a55; background: #eceae8; border-color: #8f8a85; }\n.opportunities-extension-crm-sr-badge:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge { color: #b8e4c6; background: #214d34; border-color: #6eac82; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge[data-state=\"missing\"] { color: #ffd9d5; background: #542824; border-color: #ef938b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge[data-state=\"error\"] { color: #ffe0a3; background: #584219; border-color: #c99b4b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-wl-actions-badge[data-state=\"loading\"] { color: #dedbd7; background: #484541; border-color: #8f8a85; }\n\n.opportunities-extension-form {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr)) max-content max-content;\n align-items: end;\n gap: 12px;\n min-height: 0;\n padding: 12px;\n}\n\n.opportunities-extension-form > *,\n.opportunities-extension-badge-filters > section {\n min-width: 0;\n width: 100%;\n max-width: none;\n grid-template-rows: auto 32px;\n gap: 4px;\n font-size: 12px;\n}\n\n.opportunities-extension-form > * > span:first-child,\n.opportunities-extension-badge-filters > section > span:first-child {\n font-size: 12px;\n line-height: 16px;\n}\n\n.opportunities-extension-form .opportunities-extension-select-wrap {\n width: 100%;\n}\n\n.opportunities-extension-form .opportunities-extension-field select,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger,\n.opportunities-extension-form .opportunities-extension-table-search-field input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 32px;\n min-height: 32px;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 20px;\n}\n\n.opportunities-extension-form .opportunities-extension-field select,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger {\n padding-right: 26px;\n}\n\n.opportunities-extension-form .opportunities-extension-select-wrap::after,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger::after {\n right: 10px;\n border-left-width: 4px;\n border-right-width: 4px;\n border-top-width: 5px;\n}\n\n.opportunities-extension-form .opportunities-extension-stage-filter-controls,\n.opportunities-extension-form .opportunities-extension-status-filter-controls {\n flex-wrap: nowrap;\n gap: 4px;\n}\n\n.opportunities-extension-form .opportunities-extension-stage-filter-button,\n.opportunities-extension-form .opportunities-extension-status-filter-button,\n.opportunities-extension-form .opportunities-extension-activity-filter-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n height: 28px;\n min-height: 28px;\n padding: 4px 7px;\n border: 1px solid currentColor;\n border-radius: 18px;\n font-family: inherit;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 18px;\n white-space: nowrap;\n}\n\n.opportunities-extension-cell-actions > .opportunities-extension-products-count,\n.opportunities-extension-cell-actions > .opportunities-extension-products-ramp,\n.opportunities-extension-cell-actions > .opportunities-extension-crm-sr-badge {\n display: inline-flex;\n align-items: center;\n justify-content: flex-start;\n box-sizing: border-box;\n flex: 0 0 auto;\n gap: 4px;\n height: 20px;\n min-height: 20px;\n margin: 0;\n padding: 0 6px;\n border-width: 1px;\n border-style: solid;\n border-radius: 8px;\n font-family: inherit;\n font-size: 10px;\n font-style: normal;\n font-weight: 600;\n line-height: 16px;\n letter-spacing: 0;\n text-align: center;\n vertical-align: middle;\n white-space: nowrap;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-badge-icon,\n.opportunities-extension-activity-filter-button .opportunities-extension-badge-icon {\n display: block;\n order: -1;\n flex: 0 0 16px;\n width: 16px;\n height: 16px;\n margin: 0;\n padding: 0;\n border: 0;\n color: inherit;\n fill: none;\n stroke: currentColor;\n stroke-width: 2.25;\n stroke-linecap: round;\n stroke-linejoin: round;\n pointer-events: none;\n}\n\n@media (max-width: 1150px) {\n .opportunities-extension-form {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter {\n grid-column: span 2;\n }\n}\n\n@media (max-width: 700px) {\n .opportunities-extension-form {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .opportunities-extension-form .opportunities-extension-stage-filter-controls,\n .opportunities-extension-form .opportunities-extension-status-filter-controls {\n flex-wrap: wrap;\n }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter {\n grid-template-rows: auto auto;\n }\n}\n\n@media (max-width: 420px) {\n .opportunities-extension-form { grid-template-columns: minmax(0, 1fr); }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter { grid-column: auto; }\n}\n\n.opportunities-extension-badge-filters { display: contents; }\n.opportunities-extension-activity-filter { display: grid; }\n.opportunities-extension-activity-filter[hidden] { display: none; }\n.opportunities-extension-activity-filter-controls { display: flex; align-items: center; flex-wrap: nowrap; gap: 4px; }\n/* Flexible fields share the space left by the four compact badge groups. */\n.opportunities-extension-form[data-activity-filters=\"true\"] {\n grid-template-columns: repeat(4, minmax(0, 1fr)) repeat(4, max-content);\n column-gap: 8px;\n}\n.opportunities-extension-activity-filter-button {\n min-width: 32px;\n gap: 4px;\n color: #185b30;\n background: #fff;\n cursor: pointer;\n}\n.opportunities-extension-activity-filter-button[data-value=\"missing\"] { color: #9f201b; }\n.opportunities-extension-activity-filter-button[data-value=\"under4\"] { color: #005f7d; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"] { color: #fff; background: #25653a; border-color: #25653a; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"][data-value=\"missing\"] { background: #a12d27; border-color: #a12d27; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"][data-value=\"under4\"] { background: #006b86; border-color: #006b86; }\n.opportunities-extension-activity-filter-button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter { color: #eeeae6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button { color: #b8e4c6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button:not([aria-pressed=\"true\"]) { background: #333130; border-color: #6a6560; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[data-value=\"missing\"] { color: #ffd9d5; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[data-value=\"under4\"] { color: #b5e9fc; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[aria-pressed=\"true\"] { border-color: currentColor; }\n@media (max-width: 1350px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }\n .opportunities-extension-form[data-activity-filters=\"true\"] .opportunities-extension-badge-filters {\n display: flex;\n grid-column: 1 / -1;\n flex-wrap: wrap;\n align-items: start;\n gap: 12px 20px;\n }\n .opportunities-extension-form[data-activity-filters=\"true\"] .opportunities-extension-badge-filters > section {\n width: auto;\n max-width: 100%;\n grid-template-rows: auto auto;\n }\n}\n@media (max-width: 700px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n .opportunities-extension-activity-filter-controls { flex-wrap: wrap; }\n}\n@media (max-width: 420px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: minmax(0, 1fr); }\n}\n\n.opportunities-extension-add-action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n flex: 0 0 16px;\n width: 16px;\n height: 16px;\n padding: 0;\n margin: 0 0 0 2px;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\n.opportunities-extension-add-action:hover { background: rgba(127, 127, 127, .2); }\n.opportunities-extension-add-action:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-action-form-modal {\n position: absolute;\n inset: 0;\n z-index: 5;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(0, 0, 0, .42);\n}\n.opportunities-extension-action-form-dialog {\n box-sizing: border-box;\n width: min(560px, 100%);\n max-height: calc(100vh - 24px);\n overflow-y: auto;\n background: #fff;\n color: #312d2a;\n border: 1px solid #b9b4ae;\n border-radius: 6px;\n box-shadow: 0 12px 36px rgba(0, 0, 0, .25);\n}\n.opportunities-extension-action-form {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 14px;\n padding: 18px;\n}\n.opportunities-extension-action-form-heading { min-width: 0; overflow-wrap: anywhere; }\n.opportunities-extension-action-form-context {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n gap: 6px 12px;\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n}\n.opportunities-extension-action-form-context dt { font-weight: 600; }\n.opportunities-extension-action-form-context dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }\n.opportunities-extension-action-form-field { display: grid; gap: 6px; min-width: 0; font-size: 13px; }\n.opportunities-extension-action-form-wide,\n.opportunities-extension-action-form-footer { grid-column: 1 / -1; }\n.opportunities-extension-action-form-field input,\n.opportunities-extension-action-form-field textarea {\n box-sizing: border-box;\n min-width: 0;\n width: 100%;\n border: 1px solid #8f8983;\n border-radius: 4px;\n padding: 8px;\n font: inherit;\n line-height: 20px;\n color: inherit;\n background: #fff;\n}\n.opportunities-extension-action-form-field textarea { resize: vertical; min-height: 96px; }\n.opportunities-extension-action-form-footer { display: flex; justify-content: flex-end; gap: 8px; }\n.opportunities-extension-action-form-footer button {\n border: 1px solid #8f8983;\n border-radius: 4px;\n padding: 7px 14px;\n font: inherit;\n font-size: 13px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n.opportunities-extension-action-form-footer button:disabled { opacity: .55; cursor: not-allowed; }\n.opportunities-extension-action-form :focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-form-dialog {\n color-scheme: dark;\n background: #292725;\n color: #eeeae6;\n border-color: #756f68;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-form-field input,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-form-field textarea { background: #211f1d; border-color: #918a82; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-form :focus-visible { outline-color: #80d6e8; }\n@media (max-width: 420px) {\n .opportunities-extension-action-form { grid-template-columns: minmax(0, 1fr); }\n}\n\n/* Keep layout rules on the outer table, never on expanded product tables. */\n.opportunities-extension-table[data-opportunities-layout=\"inline-actions\"] {\n width: 100%;\n min-width: 1120px;\n table-layout: fixed;\n}\n\n/* Fixed table layout shares leftover width only between the two auto columns. */\n.opportunities-extension-table > thead > tr > th[data-column=\"name\"] { width: auto; }\n.opportunities-extension-table > thead > tr > th[data-column=\"customer\"] { width: auto; }\n.opportunities-extension-table > thead > tr > th[data-column=\"owner\"] { width: 132px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"optyNumber\"] { width: 106px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"revenue\"] { width: 124px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"closeDate\"] { width: 100px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"status\"] { width: 114px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"winProbability\"] { width: 110px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"stage\"] { width: 94px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"lastUpdateDate\"] { width: 136px; }\n\n.opportunities-extension-table > tbody > tr > td[data-column] {\n padding: 10px 8px;\n overflow: visible;\n text-overflow: clip;\n white-space: normal;\n font-variant-numeric: tabular-nums;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"name\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"customer\"] {\n position: relative;\n padding-right: 16px;\n padding-left: 12px;\n padding-bottom: 38px;\n vertical-align: top;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"owner\"] {\n padding-right: 16px;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"closeDate\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"lastUpdateDate\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"status\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"stage\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"winProbability\"] {\n white-space: nowrap;\n}\n\n.opportunities-extension-cell-content {\n display: block;\n min-width: 0;\n min-height: 2.7em;\n line-height: 1.35;\n}\n\n.opportunities-extension-cell-content > :first-child {\n display: block;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-cell-actions {\n position: absolute;\n left: 12px;\n right: 16px;\n bottom: 10px;\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 6px;\n height: 24px;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-action-button {\n flex: 0 0 24px;\n width: 24px;\n height: 24px;\n padding: 2px;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"customer\"] .opportunities-extension-cell-actions {\n min-width: 84px;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-action-button svg {\n width: 18px;\n height: 18px;\n}\n\n.opportunities-extension-cell-actions button:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n}\n\n.opportunities-extension-products-ramp {\n min-width: 0;\n max-width: 100%;\n border: 1px solid #bba5cf;\n background: #f0e8f7;\n color: #63358a;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-ramp {\n background: #43334f;\n color: #ead5fc;\n border-color: #9372ac;\n}\n\n.opportunities-extension-products-ramp[data-missing=\"true\"] {\n background: #fde8e7;\n color: #9f201b;\n border-color: #c74640;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-ramp[data-missing=\"true\"] {\n background: #542824;\n color: #ffd9d5;\n border-color: #ef938b;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column] .opportunities-extension-sort-button {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 12px;\n gap: 6px;\n padding: 10px 8px;\n align-items: center;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column=\"name\"] .opportunities-extension-sort-button,\n.opportunities-extension-table > thead > tr > th[data-column=\"customer\"] .opportunities-extension-sort-button {\n padding-left: 12px;\n padding-right: 16px;\n}\n\n.opportunities-extension-sort-label {\n min-width: 0;\n white-space: normal;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column] .opportunities-extension-sort-button::after {\n position: static;\n justify-self: end;\n}\n.opportunities-extension-crm-sr-badge[type=\"button\"] { cursor: pointer; font-family: inherit; }\n.opportunities-extension-sr-popover {\n position: fixed; z-index: 8; box-sizing: border-box; overflow: auto;\n padding: 12px; border: 1px solid #b9b5b0; border-radius: 6px;\n background: #fff; color: #302e2b; box-shadow: 0 6px 24px #0003;\n font: 12px/1.5 Arial, sans-serif; text-align: left; overflow-wrap: anywhere;\n}\n.opportunities-extension-sr-popover section { padding: 8px 0; }\n.opportunities-extension-sr-popover section + section { border-top: 1px solid #dedbd7; }\n.opportunities-extension-sr-number { display: flex; align-items: center; gap: 8px; padding-right: 30px; font-weight: 600; }\n.opportunities-extension-sr-popover a { color: #00677d; text-decoration: underline; }\n.opportunities-extension-sr-details { white-space: pre-wrap; margin-top: 6px; }\n.opportunities-extension-sr-dismiss {\n position: absolute; top: 6px; right: 6px; width: 28px; height: 28px;\n display: grid; place-items: center; padding: 4px; border: 0;\n background: transparent; color: inherit; cursor: pointer;\n}\n.opportunities-extension-sr-dismiss svg { width: 16px; height: 16px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover { background: #292827; color: #f1efec; border-color: #77716b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover section + section { border-color: #5f5953; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover a { color: #7ddced; }\n.opportunities-extension-title-row {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px 16px;\n min-width: 0;\n flex: 1;\n}\n.opportunities-extension-title-row h1 {\n display: block;\n margin: 0;\n padding: 0;\n line-height: 1;\n}\n.opportunities-extension-title-row .opportunities-extension-subtitle-row {\n display: flex;\n align-items: center;\n align-self: center;\n flex-wrap: wrap;\n gap: 8px;\n margin: 0;\n padding: 0;\n min-width: 0;\n}\n.opportunities-extension-title-row .opportunities-extension-subtitle-row > span {\n box-sizing: border-box;\n margin: 0;\n min-height: 22px;\n line-height: 16px;\n}\n.opportunities-extension-title-row + .opportunities-extension-header-actions { flex-shrink: 0; }\n.opportunities-extension-refresh-all:disabled { opacity: .65; cursor: wait; }\n.opportunities-extension-refresh-all:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-refresh-all[aria-busy=\"true\"] svg { animation: opportunities-refresh-spin 1s linear infinite; }\n@keyframes opportunities-refresh-spin { to { transform: rotate(360deg); } }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-refresh-all[aria-busy=\"true\"] svg { animation: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-install-base-dialog {\n width: min(1700px, 100%);\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header {\n padding: 10px 12px;\n gap: 12px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header h2 {\n font-size: 16px;\n line-height: 22px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header p {\n font-size: 12px;\n line-height: 16px;\n margin-top: 3px;\n overflow-wrap: anywhere;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-icon-button {\n width: 28px;\n height: 28px;\n min-width: 28px;\n min-height: 28px;\n padding: 4px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-customer-table-toolbar {\n padding: 8px 12px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-customer-table-search {\n width: min(320px, 100%);\n height: 32px;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 20px;\n}\n.opportunities-extension-install-base-content {\n min-width: 0;\n min-height: 0;\n overflow: auto;\n scrollbar-gutter: stable;\n}\n.opportunities-extension-install-base-message { margin: 10px 12px; font-size: 12px; line-height: 16px; }\n.opportunities-extension-install-base-table {\n width: 100%; min-width: 1120px; table-layout: fixed; border-collapse: collapse; font-size: 11px;\n}\n.opportunities-extension-install-base-table col { width: 7%; }\n.opportunities-extension-install-base-table .install-base-col-partyName { width: 12%; }\n.opportunities-extension-install-base-table .install-base-col-productGroupName { width: 13%; }\n.opportunities-extension-install-base-table .install-base-col-productName { width: 13%; }\n.opportunities-extension-install-base-table .install-base-col-quantity { width: 5%; }\n.opportunities-extension-install-base-table .install-base-col-quantityType { width: 8%; }\n.opportunities-extension-install-base-table th,\n.opportunities-extension-install-base-table td {\n padding: 8px 6px; text-align: left; vertical-align: middle; overflow-wrap: anywhere;\n border-bottom: 1px solid #e8e5e1; line-height: 1.4;\n}\n.opportunities-extension-install-base-table th { position: sticky; top: 0; z-index: 1; background: #faf9f8; }\n.opportunities-extension-install-base-table td[data-format=\"amount\"],\n.opportunities-extension-install-base-table td[data-format=\"quantity\"] { text-align: right; font-variant-numeric: tabular-nums; }\n.opportunities-extension-install-base-table td[data-format=\"date\"] { white-space: nowrap; }\n.opportunities-extension-install-base-status {\n display: inline-block; padding: 2px 5px; border-radius: 12px; font-size: 10px; font-weight: 600;\n color: #5f5a55; background: #eceae8; white-space: nowrap;\n}\n.opportunities-extension-install-base-status[data-status=\"ACTIVE\"] { color: #17693a; background: #e1f1e5; }\n.opportunities-extension-install-base-status[data-status=\"UNSUPPORTED\"] { color: #855300; background: #fff0d6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-content,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table td { color: #f6f4f2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-message { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-message[role=\"alert\"] { color: #ffb4ab; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th { background: #353331; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table td { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status[data-status=\"ACTIVE\"] { color: #b8e4c6; background: #214d34; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status[data-status=\"UNSUPPORTED\"] { color: #ffdfa2; background: #614418; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-install-base-table .opportunities-extension-account-plans-skeleton-bar { animation: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-service-requests-dialog { width: min(1700px, 100%); }\n.opportunities-extension-service-requests-content { min-width: 0; min-height: 0; overflow: auto; scrollbar-gutter: stable; }\n.opportunities-extension-service-requests-message { margin: 16px; font-size: 13px; }\n.opportunities-extension-service-requests-table {\n width: 100%; min-width: 1200px; table-layout: fixed; border-collapse: collapse; font-size: 12px;\n}\n.opportunities-extension-service-requests-table col { width: 7%; }\n.opportunities-extension-service-requests-table .service-requests-col-name { width: 17%; }\n.opportunities-extension-service-requests-table .service-requests-col-id { width: 10%; }\n.opportunities-extension-service-requests-table .service-requests-col-severity { width: 5%; }\n.opportunities-extension-service-requests-table .service-requests-col-subStatus { width: 14%; }\n.opportunities-extension-service-requests-table .service-requests-col-productName { width: 12%; }\n.opportunities-extension-service-requests-table th,\n.opportunities-extension-service-requests-table td {\n padding: 12px 8px; text-align: left; vertical-align: middle; overflow-wrap: anywhere;\n border-bottom: 1px solid #e8e5e1; line-height: 1.4;\n}\n.opportunities-extension-service-requests-table th { position: sticky; top: 0; z-index: 1; background: #faf9f8; }\n.opportunities-extension-service-requests-table td[data-field=\"created\"],\n.opportunities-extension-service-requests-table td[data-field=\"lastUpdated\"],\n.opportunities-extension-service-requests-table td[data-field=\"id\"] { white-space: nowrap; font-variant-numeric: tabular-nums; }\n.opportunities-extension-service-request-status {\n display: inline-block; padding: 3px 6px; border-radius: 12px; font-size: 10px; font-weight: 600;\n color: #5f5a55; background: #eceae8;\n}\n.opportunities-extension-service-request-status[data-status=\"OPEN\"] { color: #17693a; background: #e1f1e5; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-content,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table td { color: #f6f4f2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-message { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-message[role=\"alert\"] { color: #ffb4ab; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th { background: #353331; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table td { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-request-status { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-request-status[data-status=\"OPEN\"] { color: #b8e4c6; background: #214d34; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-service-requests-table .opportunities-extension-account-plans-skeleton-bar { animation: none; }\n}\n\n/* Scope sizing to Cloud Consumption, not other dialogs sharing its components. */\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header { padding: 10px 12px; gap: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header h2 { font-size: 16px; line-height: 22px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header p { font-size: 12px; line-height: 16px; margin-top: 3px; overflow-wrap: anywhere; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-icon-button { width: 28px; height: 28px; min-width: 28px; min-height: 28px; padding: 4px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-tabs { padding: 4px 12px 0; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-tab { min-height: 30px; padding: 4px 8px; font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-panel { padding: 8px 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details { gap: 0 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details > div { grid-template-columns: minmax(85px, 35%) minmax(0, 1fr); min-height: 32px; padding: 4px 0; gap: 6px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details dt { font-size: 11px; line-height: 16px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details dd { font-size: 12px; line-height: 16px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-trend { margin-top: 8px; padding-top: 6px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-periods button { min-height: 28px; padding: 4px 8px; font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation { grid-template-columns: 28px minmax(120px, auto) 28px; min-height: 30px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation strong { font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation-button { width: 28px; height: 28px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-visual { grid-template-columns: minmax(0, 1fr) 150px; gap: 8px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-svg { height: 100%; max-height: 100%; min-width: 0; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-legend button { font-size: 11px; padding: 4px; gap: 5px; }\n\n/* Small viewports must scroll rather than clip details or collapse the chart. */\n@media (max-height: 560px), (max-width: 700px) {\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-panels { overflow: auto; }\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-panel { height: auto; min-height: 100%; grid-template-rows: auto minmax(280px, 1fr); }\n}\n@media (max-width: 700px) {\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details { grid-template-columns: minmax(0, 1fr); }\n [data-consumption-layout=\"compact\"] .opportunities-extension-consumption-visual { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }\n [data-consumption-layout=\"compact\"] .opportunities-extension-consumption-legend { display: flex; flex-wrap: wrap; }\n}\n\n.opportunities-extension-plan-detail-badges { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }\n.opportunities-extension-consumption-trend-header { align-items: center; justify-content: space-between; gap: 12px; }\n.opportunities-extension-consumption-trend-header > .opportunities-extension-plan-detail-badges { min-width: 0; }\n.opportunities-extension-plan-detail-skeleton { width: 64px; height: 20px; }\n.opportunities-extension-projection-badge {\n display: inline-flex; align-items: center; justify-content: center; border: 1px solid transparent;\n padding: 3px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; line-height: 1.3;\n color: #5f5a55; background: #eceae8; white-space: nowrap;\n}\nbutton.opportunities-extension-projection-badge { cursor: pointer; }\n.opportunities-extension-projection-badge[data-status=\"forfeit\"] { color: #a12424; background: #fbe5e5; }\n.opportunities-extension-projection-badge[data-status=\"overage\"] { color: #185a9d; background: #e0edfc; }\n.opportunities-extension-projection-badge:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-projection-popover {\n position: fixed; z-index: 8; box-sizing: border-box; padding: 14px; overflow: auto; overscroll-behavior: contain;\n border: 1px solid #b9b4ae; border-radius: 4px; background: #ffffff; color: #312d2a;\n box-shadow: 0 4px 16px #0003; font-size: 12px; line-height: 1.4; overflow-wrap: anywhere;\n}\n.opportunities-extension-projection-popover[hidden] { display: none; }\n.opportunities-extension-projection-popover .opportunities-extension-projection-dismiss {\n display: grid; place-items: center; width: 24px; height: 24px; margin-left: auto; margin-bottom: 8px; padding: 4px; border: 1px solid #b9b4ae;\n border-radius: 4px; background: transparent; color: inherit; cursor: pointer; font-size: 12px;\n}\n.opportunities-extension-projection-dismiss svg { width: 14px; height: 14px; }\n.opportunities-extension-projection-line h3 { margin: 0 0 8px; font-size: 12px; }\n.opportunities-extension-projection-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 16px; margin: 0; }\n.opportunities-extension-projection-fields > div { min-width: 0; }\n.opportunities-extension-projection-fields dt { font-weight: 600; color: #5f5a55; font-size: 11px; }\n.opportunities-extension-projection-fields dd { margin: 2px 0 0; font-variant-numeric: tabular-nums; }\n.opportunities-extension-projection-fields a { color: #006d7a; text-decoration: underline; }\n.opportunities-extension-projection-children { margin-top: 14px; padding-left: 12px; border-left: 2px solid #dedbd7; }\n.opportunities-extension-projection-children > section + section { margin-top: 16px; }\n.opportunities-extension-plan-detail-error { color: #a12424; font-size: 12px; }\n.opportunities-extension-projection-empty { color: #5f5a55; font-size: 12px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-popover { color: #f1efec; background: #302e2b; border-color: #716b64; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge[data-status=\"forfeit\"] { color: #ffb9b9; background: #682e32; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge[data-status=\"overage\"] { color: #c5dfff; background: #224b76; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-fields dt,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-empty { color: #cec9c2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-fields a { color: #76dbea; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-plan-detail-error { color: #ffb9b9; }\n@media (max-width: 480px) { .opportunities-extension-projection-fields { grid-template-columns: minmax(0, 1fr); } }\n@media (max-width: 480px) {\n .opportunities-extension-consumption-trend-header > .opportunities-extension-consumption-periods { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n@media (prefers-reduced-motion: reduce) { .opportunities-extension-plan-detail-skeleton { animation: none; } }\n\n.opportunities-extension-account-plan-details > .opportunities-extension-contract-row {\n align-items: center;\n}\n.opportunities-extension-contract-row > dt,\n.opportunities-extension-contract-row > dd,\n.opportunities-extension-contract-ratecard > span {\n line-height: 20px;\n}\n.opportunities-extension-contract-ratecard {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px 10px;\n}\n.opportunities-extension-ratecard-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n align-self: center;\n box-sizing: border-box;\n height: 28px;\n margin: 0;\n flex: 0 0 auto;\n padding: 0 8px;\n border: 1px solid #8aaeb9;\n border-radius: 4px;\n background: #fff;\n color: #006b80;\n font: inherit;\n font-size: 12px;\n font-weight: 600;\n line-height: 20px;\n cursor: pointer;\n}\n.opportunities-extension-ratecard-button:hover { background: #e8f4f6; }\n.opportunities-extension-ratecard-overlay {\n position: absolute;\n inset: 0;\n z-index: 8;\n display: flex;\n justify-content: flex-end;\n overflow: hidden;\n overflow: clip;\n background: rgba(0, 0, 0, 0);\n transition: background-color 320ms ease;\n}\n.opportunities-extension-ratecard-overlay[data-open=\"true\"] { background: rgba(0, 0, 0, .32); }\n.opportunities-extension-ratecard-drawer {\n --ratecard-bg: #fff;\n --ratecard-heading: #faf9f8;\n --ratecard-text: #312d2a;\n --ratecard-muted: #615a55;\n --ratecard-border: #dedbd8;\n --ratecard-accent: #00758f;\n --ratecard-skeleton: #eae7e4;\n display: grid;\n grid-template-rows: auto auto auto minmax(0, 1fr);\n width: min(1520px, calc(100% - 48px));\n height: 100%;\n min-width: 0;\n box-sizing: border-box;\n overflow: hidden;\n background: var(--ratecard-bg);\n color: var(--ratecard-text);\n box-shadow: -6px 0 24px rgba(0, 0, 0, .2);\n transform: translateX(100%);\n transition: transform 320ms cubic-bezier(.22, .61, .36, 1);\n}\n.opportunities-extension-ratecard-overlay[data-open=\"true\"] .opportunities-extension-ratecard-drawer { transform: translateX(0); }\n.opportunities-extension-ratecard-header > div { min-width: 0; overflow-wrap: anywhere; }\n.opportunities-extension-ratecard-plan-details { padding: 12px 20px 0; }\n.opportunities-extension-ratecard-toolbar { display: flex; align-items: center; gap: 16px; padding: 12px 20px; }\n.opportunities-extension-ratecard-search {\n width: min(360px, 100%);\n min-width: 0;\n box-sizing: border-box;\n padding: 9px 12px;\n border: 1px solid var(--ratecard-muted);\n border-radius: 4px;\n background: var(--ratecard-bg);\n color: var(--ratecard-text);\n font: inherit;\n font-size: 13px;\n}\n.opportunities-extension-ratecard-search::placeholder { color: var(--ratecard-muted); opacity: 1; }\n.opportunities-extension-ratecard-count { color: var(--ratecard-muted); font-size: 12px; white-space: nowrap; }\n.opportunities-extension-ratecard-viewport { overflow: auto; min-height: 0; min-width: 0; scrollbar-gutter: stable; }\n.opportunities-extension-ratecard-table { width: 100%; min-width: 1100px; table-layout: fixed; border-collapse: separate; border-spacing: 0; font-size: 12px; }\n.opportunities-extension-ratecard-table th, .opportunities-extension-ratecard-table td {\n padding: 11px 10px;\n border-bottom: 1px solid var(--ratecard-border);\n vertical-align: top;\n overflow-wrap: anywhere;\n text-align: left;\n}\n.opportunities-extension-ratecard-table th { position: sticky; top: 0; z-index: 1; background: var(--ratecard-heading); }\n.opportunities-extension-ratecard-sort {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 12px;\n align-items: center;\n gap: 5px;\n width: 100%;\n padding: 0;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: 600;\n text-align: left;\n cursor: pointer;\n}\n.opportunities-extension-ratecard-sort-icon { color: var(--ratecard-accent); text-align: center; }\n.opportunities-extension-ratecard-table .opportunities-extension-ratecard-numeric { text-align: right; font-variant-numeric: tabular-nums; }\n.opportunities-extension-ratecard-table .opportunities-extension-ratecard-notice { padding: 28px 20px; text-align: center; }\n.opportunities-extension-ratecard-notice [role=\"alert\"] { color: #b3261e; }\n.opportunities-extension-ratecard-skeleton { display: block; width: 85%; height: 14px; border-radius: 3px; background: var(--ratecard-skeleton); animation: opportunities-ratecard-pulse 1.1s ease-in-out infinite alternate; }\n.opportunities-extension-ratecard-drawer :focus-visible, .opportunities-extension-ratecard-button:focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-ratecard-overlay[data-closing=\"true\"] { pointer-events: none; background: rgba(0, 0, 0, 0); transition-duration: 180ms; }\n.opportunities-extension-ratecard-overlay[data-closing=\"true\"] .opportunities-extension-ratecard-drawer { transform: translateX(100%); transition-duration: 180ms; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-drawer {\n --ratecard-bg: #292725;\n --ratecard-heading: #35322f;\n --ratecard-text: #f5f3f1;\n --ratecard-muted: #c2bcb6;\n --ratecard-border: #514c47;\n --ratecard-accent: #59d1e5;\n --ratecard-skeleton: #514c47;\n}\n[data-theme=\"dark\"] .opportunities-extension-ratecard-button { color: #59d1e5; border-color: #6298a2; background: #292725; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-button:hover { background: #313f40; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-notice [role=\"alert\"] { color: #ffb4ab; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-drawer :focus-visible, [data-theme=\"dark\"] .opportunities-extension-ratecard-button:focus-visible { outline-color: #59d1e5; }\n@keyframes opportunities-ratecard-pulse { from { opacity: .45; } to { opacity: 1; } }\n@media (max-width: 720px) {\n .opportunities-extension-ratecard-drawer { width: 100%; }\n .opportunities-extension-ratecard-toolbar { flex-wrap: wrap; gap: 8px; }\n}\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-ratecard-overlay, .opportunities-extension-ratecard-drawer, .opportunities-extension-ratecard-skeleton,\n .opportunities-extension-ratecard-overlay[data-closing=\"true\"], .opportunities-extension-ratecard-overlay[data-closing=\"true\"] .opportunities-extension-ratecard-drawer { animation: none; transition: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-install-base-dialog,\n.opportunities-extension-account-plans-dialog.opportunities-extension-service-requests-dialog {\n grid-template-rows: auto auto minmax(0, 1fr);\n}\n.opportunities-extension-customer-table-toolbar { padding: 12px 16px; border-bottom: 1px solid #dedbd7; }\n.opportunities-extension-customer-table-search {\n box-sizing: border-box;\n width: min(420px, 100%);\n min-width: 0;\n height: 38px;\n padding: 8px 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #fff;\n color: #312d2a;\n font: inherit;\n font-size: 13px;\n}\n.opportunities-extension-customer-table-search::placeholder { color: #5f5a55; opacity: 1; }\n.opportunities-extension-customer-table-search:focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-toolbar { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search { background: #353331; color: #f6f4f2; border-color: #8f8a85; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search::placeholder { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search:focus-visible { outline-color: #59d1e5; }\n"; // Source: src/shared/messages.js /** Stable wire names. All payloads remain plain, serializable objects. */ function createMessageTypes() { @@ -304,6 +304,71 @@ function createOpportunitiesColumns({ formatOracleResponseDate, formatRevenue, f ]; } +// Source: src/features/opportunities/badge-content.js +/* + * Lucide icons: package, chart-no-axes-column-increasing, clipboard-list, list-checks. + * https://github.com/lucide-icons/lucide (ISC License) + * Copyright (c) 2026 Lucide Icons and Contributors + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +function createOpportunityBadgeContent({ environment }) { + const shapes = { + products: [ + ["path", { d: "M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z" }], + ["path", { d: "M12 22V12" }], + ["polyline", { points: "3.29 7 12 12 20.71 7" }], + ["path", { d: "m7.5 4.27 9 5.15" }] + ], + ramp: [ + ["path", { d: "M5 21v-6" }], + ["path", { d: "M12 21V9" }], + ["path", { d: "M19 21V3" }] + ], + sr: [ + ["rect", { width: "8", height: "4", x: "8", y: "2", rx: "1", ry: "1" }], + ["path", { d: "M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" }], + ["path", { d: "M12 11h4" }], + ["path", { d: "M12 16h4" }], + ["path", { d: "M8 11h.01" }], + ["path", { d: "M8 16h.01" }] + ], + actions: [ + ["path", { d: "M13 5h8" }], + ["path", { d: "M13 12h8" }], + ["path", { d: "M13 19h8" }], + ["path", { d: "m3 17 2 2 4-4" }], + ["path", { d: "m3 7 2 2 4-4" }] + ] + }; + function setContent(badge, kind, value) { + badge.textContent = String(value); + const namespace = "http://www.w3.org/2000/svg"; + const icon = environment.document.createElementNS(namespace, "svg"); + for (const [name, attribute] of Object.entries({ + class: "opportunities-extension-badge-icon", viewBox: "0 0 24 24", + width: "16", height: "16", fill: "none", stroke: "currentColor", + "stroke-width": "2.25", "stroke-linecap": "round", "stroke-linejoin": "round", + "aria-hidden": "true", focusable: "false", "data-badge-icon": kind + })) icon.setAttribute(name, attribute); + for (const [tag, attributes] of shapes[kind]) { + const shape = environment.document.createElementNS(namespace, tag); + for (const [name, attribute] of Object.entries(attributes)) shape.setAttribute(name, attribute); + icon.append(shape); + } + badge.append(icon); + } + return { setContent }; +} + // Source: src/content/fusion-page.js function createContentFusionPage({ ADD_ICON_SELECTOR, @@ -444,6 +509,7 @@ function createContentModal({ closeAccountPlansModal, closeInstallBaseModal, closeServiceRequestsModal, + closeActionForm, closeCustomerFilterPanel, closeOwnerFilterPanel, closePreferencesModal, @@ -886,6 +952,7 @@ function createContentModal({ closeAccountPlansModal(); closeInstallBaseModal(); closeServiceRequestsModal(); + closeActionForm(false); modal.hidden = true; } @@ -914,6 +981,10 @@ function createContentModal({ } if (event.key === "Escape") { + if (closeActionForm()) { + event.preventDefault(); + return; + } if (closeServiceRequestsModal()) { event.preventDefault(); return; @@ -1928,6 +1999,7 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest, async function requestCrmServiceRequest(token, version, isActive = () => isCurrentPeriodRequest(version), onProgress = () => {}) { const items = []; let offset = 0; + let attempt = 1; while (isActive()) { const payload = createPayload(offset); const headers = { @@ -1935,31 +2007,33 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest, Origin: "https://eeho.fa.us2.oraclecloud.com", Preference: "transient" }; const entry = logRequestStart({ name: "resquestCrmServiceRequest", method: "POST", url, - headers: { ...headers, Authorization: `Bearer ${maskToken(token)}` }, body: JSON.stringify(payload, null, 2), metadata: { offset } }); + headers: { ...headers, Authorization: `Bearer ${maskToken(token)}` }, body: JSON.stringify(payload, null, 2), metadata: { offset, attempt } }); try { const response = await fetch(url, { method: "POST", credentials: "include", headers, body: JSON.stringify(payload) }); logRequestSuccess(entry, response, await readResponseBodyForDebug(response)); - if (!response.ok) throw new Error(`CRM service request query failed with status ${response.status}.`); + if (response.status !== 200) throw new Error(`CRM service request query failed with status ${response.status}.`); const data = await response.json(); if (!data || !Array.isArray(data.items) || typeof data.hasMore !== "boolean") { throw new Error("CRM service request query returned an invalid response."); } if (!isActive()) return null; + const received = data.count === undefined ? data.items.length : Number(data.count); + const current = data.offset === undefined ? offset : Number(data.offset); + if (data.hasMore && (!data.items.length || !Number.isInteger(received) || received <= 0 || !Number.isInteger(current) + || current !== offset || current + received <= offset)) { + throw new Error("CRM service request pagination did not advance."); + } items.push(...data.items); onProgress(items.length, Number.isFinite(data.totalResults) && data.totalResults >= items.length ? data.totalResults : null); if (!data.hasMore) return items; - const received = data.count === undefined ? data.items.length : Number(data.count); - const current = data.offset === undefined ? offset : Number(data.offset); - if (!data.items.length || !Number.isInteger(received) || received <= 0 || !Number.isInteger(current) - || current !== offset || current + received <= offset) { - throw new Error("CRM service request pagination did not advance."); - } offset = current + received; + attempt = 1; } catch (error) { logRequestFailure(entry, error.message || "CRM service request query failed."); - throw error; + if (attempt === 5) throw error; + attempt += 1; } } return null; @@ -1968,15 +2042,23 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest, } // Source: src/features/opportunities/crm-service-requests.js -function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, allowsCrmActivities, reportProgress, activityCache, environment }) { +function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, allowsCrmActivities, reportProgress, activityCache, setBadgeContent, environment }) { let status = "idle"; let byOpportunity = new Map(); let pending = null; let generation = 0; - function reset() { closePopover(); generation += 1; pending = null; status = "idle"; byOpportunity = new Map(); reportProgress("idle"); } + let loadedItems = []; + function reset() { closePopover(); generation += 1; pending = null; status = "idle"; byOpportunity = new Map(); loadedItems = []; reportProgress("idle"); } function load(token, version, cacheOptions = null) { if (!allowsCrmActivities() || !isCurrentPeriodRequest(version)) return; - if (!pending) pending = run(token, version, generation, cacheOptions); + if (status === "ready") { + return Promise.resolve(cacheOptions ? activityCache.write("sr", "all", cacheOptions.cachedAt, loadedItems) : undefined).then(() => true); + } + if (!pending) { + const request = run(token, version, generation, cacheOptions); + pending = request; + request.finally(() => { if (pending === request) pending = null; }); + } return pending; } async function run(token, version, currentGeneration, cacheOptions) { @@ -1984,8 +2066,8 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre status = "loading"; try { const cached = cacheOptions ? await activityCache.read("sr", "all", cacheOptions.cachedAt) : null; - if (!isActive()) return; - if (!cached && cacheOptions?.cacheOnly) { status = "idle"; return; } + if (!isActive()) return false; + if (!cached && cacheOptions?.cacheOnly) { status = "idle"; return false; } let items = cached?.items; if (!items) { reportProgress("running", 0); @@ -1994,7 +2076,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre }); if (items && isActive() && cacheOptions) await activityCache.write("sr", "all", cacheOptions.cachedAt, items); } - if (!items || !isActive()) return; + if (!items || !isActive()) return false; const grouped = new Map(); for (const item of items) { const number = item?.OpportunityName_Id_c?.OptyNumber; @@ -2004,10 +2086,13 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre grouped.get(key).push(item); } byOpportunity = grouped; + loadedItems = items; status = "ready"; if (!cached) reportProgress("complete", items.length, items.length); + return true; } catch { if (isActive()) { status = "error"; reportProgress("error"); } + return false; } } function getSummary(optyNumber) { @@ -2032,7 +2117,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre const reportedHours = summary.reportedHours !== null ? new Intl.NumberFormat("en-US", { useGrouping: false, maximumFractionDigits: 10 }).format(summary.reportedHours) : "N/D"; - badge.textContent = status === "error" ? "SR ?" : items.length ? `\u2705 SR (${reportedHours}${reportedHours === "N/D" ? "" : "h"})` : "\u26d4 SR"; + setBadgeContent(badge, "sr", status === "error" ? "?" : items.length ? `${reportedHours}${reportedHours === "N/D" ? "" : "h"}` : "0h"); const display = value => value === null || value === undefined || value === "" ? "N/D" : String(value); const descriptions = items.map(item => [ `Title: ${display(item.Title)}`, @@ -2046,8 +2131,8 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre : !items.length ? "No matching CRM service request with status SVC_PENDING_DELIVERY in your SR team." : items.map((item, index) => `SR Number: ${display(item.SrNumber)}\n${descriptions[index]}`).join("\n\n"); badge.setAttribute("aria-label", description); + badge.title = "Whether a Service Request has been created for the opportunities."; if (items.length && status === "ready") bindPopover(badge, items, descriptions); - else badge.title = description; badge.tabIndex = 0; return badge; } @@ -2055,8 +2140,8 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre } // Source: src/features/opportunities/product-activities.js -function createProductActivities({ productsContentState, opportunitiesQueryState, resetCrm, - loadCrm, loadActions, render }) { +function createProductActivities({ productsContentState, opportunitiesQueryState, + loadCrm, loadActions, blockActions, render }) { let cycle = null; function begin(requestId, token) { cycle = { requestId, token, version: opportunitiesQueryState.periodRequestVersion, completed: false }; @@ -2068,26 +2153,32 @@ function createProductActivities({ productsContentState, opportunitiesQueryState current.completed = true; const products = [...productsContentState.opptyProductsByNumber.values()].filter(result => !result.error); if (!products.length) return; - resetCrm(); - const pending = []; - const seen = new Set(); - for (const result of products) { - const items = result.items.filter(item => { - const id = String(item?.RevnId ?? ""); - if (seen.has(id)) return false; - seen.add(id); - return true; - }); - pending.push(loadActions({ ...result, items }, true, { cachedAt: result.cachedAt, cacheOnly: result.fromCache === true })); - } const cachedAt = Math.max(...products.map(result => Number(result.cachedAt) || 0)); - pending.push(loadCrm(current.token, current.version, { cachedAt, cacheOnly: products.every(result => result.fromCache) })); - return Promise.allSettled(pending).then(() => { - if (cycle !== current || productsContentState.currentProductsRequestId !== requestId - || opportunitiesQueryState.periodRequestVersion !== current.version) return; + const isActive = () => cycle === current && productsContentState.currentProductsRequestId === requestId + && opportunitiesQueryState.periodRequestVersion === current.version; + return Promise.resolve(loadCrm(current.token, current.version, { cachedAt, cacheOnly: products.every(result => result.fromCache) })).then(async success => { + if (!isActive()) return; + if (success === false) { + products.forEach(blockActions); + render(); + return; + } + const pending = []; + const seen = new Set(); + for (const result of products) { + const items = result.items.filter(item => { + const id = String(item?.RevnId ?? ""); + if (seen.has(id)) return false; + seen.add(id); + return true; + }); + pending.push(loadActions({ ...result, items }, true, { cachedAt: result.cachedAt, cacheOnly: result.fromCache === true })); + } + await Promise.allSettled(pending); + if (!isActive()) return; if (cachedAt > 0) productsContentState.productsLastCachedAt = cachedAt; render(); - }).catch(() => {}); + }).catch(() => { if (isActive()) { products.forEach(blockActions); render(); } }); } return { begin, complete }; } @@ -2253,7 +2344,7 @@ function createActivityProgress({ MODAL_ID, environment }) { } // Source: src/features/opportunities/activity-filters.js -function createActivityFilters({ allowsCrmActivities, getSrSummary, getActionSummary, renderTable, environment }) { +function createActivityFilters({ allowsCrmActivities, getSrSummary, getActionSummary, renderTable, setBadgeContent, environment }) { const selections = { sr: new Set(["matched", "missing"]), actions: new Set(["matched", "missing"]) }; let container = null; let form = null; @@ -2267,24 +2358,32 @@ function createActivityFilters({ allowsCrmActivities, getSrSummary, getActionSum container = environment.document.createElement("div"); container.className = "opportunities-extension-badge-filters"; for (const [kind, title, options] of [ - ["sr", "Service Request", [["matched", "\u2705 SR"], ["under4", "\u2705 SR < 4h"], ["missing", "\u26d4 SR"]]], - ["actions", "Actions", [["matched", "\u2705 Action"], ["missing", "\u26d4 Action"]]] + ["sr", "Service Request", ["matched", "under4", "missing"]], + ["actions", "Act", ["matched", "missing"]] ]) { const section = environment.document.createElement("section"); section.className = "opportunities-extension-activity-filter"; const label = environment.document.createElement("span"); label.textContent = title; + const tooltip = kind === "sr" + ? "Whether a Service Request has been created for the opportunities." + : "Whether the Action is registered in Workload Workbench."; + label.title = tooltip; const controls = environment.document.createElement("div"); controls.className = "opportunities-extension-activity-filter-controls"; controls.setAttribute("role", "group"); controls.setAttribute("aria-label", `Filter by ${title}`); - for (const [value, text] of options) { + for (const value of options) { const button = environment.document.createElement("button"); button.type = "button"; button.className = "opportunities-extension-activity-filter-button"; button.setAttribute("data-value", value); - button.textContent = text; - if (value === "under4") button.title = "At least one SR with reported hours below 4; replaces other SR filters."; + setBadgeContent(button, kind, value === "under4" ? "< 4h" : ""); + const description = value === "under4" + ? "At least one SR with reported hours below 4; replaces other SR filters." + : `${kind === "sr" ? "Service Request" : "Action"} ${value === "matched" ? "registered" : "not registered"}`; + button.title = `${tooltip}\n${description}`; + button.setAttribute("aria-label", description); button.addEventListener("click", () => toggle(kind, value)); buttons.push({ button, kind, value }); controls.append(button); @@ -2469,7 +2568,7 @@ function createCrmSrPopover({ MODAL_ID, createCopyButton, createCloseIcon, envir // Source: src/features/opportunities/workload-actions.js function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivities, requestConsumerTokenServiceOnce, sendRuntimeMessage, - appendBackgroundRequestLog, queueProductsTableRender, productsContentState, messageTypes, reportProgress, activityCache, environment }) { + appendBackgroundRequestLog, queueProductsTableRender, productsContentState, messageTypes, reportProgress, activityCache, createActionButton, closeActionForm, setBadgeContent, environment }) { let session = newSession(); function newSession() { return { enabled: true, records: new Map(), queue: [], running: 0, progress: new Set() }; } function updateProgress(current) { @@ -2480,6 +2579,7 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie reportProgress(completed < records.length ? "running" : failed ? "complete-with-errors" : "complete", completed, records.length); } function reset(enabled = true) { + closeActionForm(false); session.enabled = false; for (const job of session.queue) job.record.resolveCompletion(); session.queue.length = 0; @@ -2516,6 +2616,12 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie for (const products of productsContentState.opptyProductsByNumber.values()) loadProducts(products); queueProductsTableRender(); } + function blockProducts(products) { + if (!allowsCrmActivities()) return; + for (const id of idsFor(products)) { + session.records.set(id, { status: "error", actions: [], hasNext: false, error: "CRM service requests unavailable." }); + } + } function pump(current) { while (current.enabled && current === session && current.running < 4 && current.queue.length) { const job = current.queue.shift(); @@ -2536,12 +2642,21 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie if (cacheOptions?.cacheOnly) { record.status = "error"; record.error = "No matching activity cache for this product update."; return; } current.progress.add(record); updateProgress(current); - const authorizations = await requestConsumerTokenServiceOnce(); - if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; - const result = await sendRuntimeMessage({ type: messageTypes.requestWlActions, revnId, authorization: authorizations?.workloadActions }); - if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; - appendBackgroundRequestLog(result?.debugRequests); - if (!result?.ok) throw new Error(result?.error || "Unable to load workload actions."); + let result; + for (let attempt = 1; attempt <= 5; attempt += 1) { + try { + if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; + const authorizations = await requestConsumerTokenServiceOnce(); + if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; + result = await sendRuntimeMessage({ type: messageTypes.requestWlActions, revnId, authorization: authorizations?.workloadActions }); + if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; + appendBackgroundRequestLog(result?.debugRequests); + if (!result?.ok) throw new Error(result?.error || "Unable to load workload actions."); + break; + } catch (error) { + if (attempt === 5) throw error; + } + } record.actions = result.actions; record.hasNext = result.hasNext; record.status = "ready"; @@ -2577,7 +2692,7 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie const badge = environment.document.createElement("span"); badge.className = "opportunities-extension-crm-sr-badge opportunities-extension-wl-actions-badge"; badge.setAttribute("data-state", state); - badge.textContent = state === "matched" ? "\u2705 Act" : state === "missing" ? "\u26d4 Act" : state === "loading" ? "Act ..." : "Act ?"; + setBadgeContent(badge, "actions", state === "matched" || state === "missing" ? actions.length : state === "loading" ? "..." : "?"); badge.title = actions.length ? actions.map(action => [ `Action: ${action.name ?? "N/D"}`, `ID: ${action.id ?? "N/D"}`, `Status: ${action.status ?? "N/D"}`, `Owner: ${action.owner || "N/D"}`, `Email: ${action.ownerEmail || "N/D"}`, `Workload: ${action.workloadName || "N/D"}`, @@ -2590,9 +2705,123 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie if (actions.length && (pending || uncertain)) badge.title += "\nSome workloads are still loading or could not be fully checked."; badge.tabIndex = 0; badge.setAttribute("aria-label", badge.title); + if (state === "missing") badge.append(createActionButton(String(optyNumber))); return badge; } - return { reset, reopen, loadProducts, createBadge, getSummary }; + return { reset, reopen, loadProducts, blockProducts, createBadge, getSummary }; +} + +// Source: src/features/opportunities/workload-action-form.js +function createWorkloadActionForm({ MODAL_ID, allowsCrmActivities, isMissingAction, getOpportunity, formatDate, createCloseIcon, environment }) { + const { document } = environment; + let active = null; + function element(tag, className, text) { + const node = document.createElement(tag); + if (className) node.className = className; + if (text !== undefined) node.textContent = text; + return node; + } + function close(restoreFocus = true) { + if (!active) return false; + const previous = active; + active = null; + previous.modal.remove(); + if (restoreFocus && previous.trigger?.isConnected) previous.trigger.focus(); + return true; + } + function createButton(optyNumber) { + const button = element("button", "opportunities-extension-add-action", "+"); + button.type = "button"; + button.title = "Add Action"; + button.setAttribute("aria-label", `Add Action for ${optyNumber}`); + button.setAttribute("aria-haspopup", "dialog"); + button.addEventListener("click", event => { + event.preventDefault(); + event.stopPropagation(); + open(optyNumber, button); + }); + return button; + } + function open(optyNumber, trigger) { + if (!allowsCrmActivities() || !isMissingAction(optyNumber)) return; + const host = document.getElementById(MODAL_ID); + if (!host || host.hidden) return; + close(false); + const modal = element("section", "opportunities-extension-action-form-modal"); + modal.setAttribute("role", "dialog"); + modal.setAttribute("aria-modal", "true"); + modal.setAttribute("aria-labelledby", "opportunities-extension-action-form-title"); + const dialog = element("div", "opportunities-extension-action-form-dialog"); + const header = element("header", "opportunities-extension-account-plans-header"); + const heading = element("div", "opportunities-extension-action-form-heading"); + const title = element("h2", "", "Add Action"); + title.id = "opportunities-extension-action-form-title"; + heading.append(title, element("p", "", String(optyNumber))); + const opportunity = getOpportunity(optyNumber); + const details = element("dl", "opportunities-extension-action-form-context"); + for (const [label, value] of [ + ["Customer", opportunity?.CustomerAccount?.PartyUniqueName], + ["Name", opportunity?.Name], + ["Close Date", formatDate(opportunity?.EffectiveDate)] + ]) { + details.append(element("dt", "", label), element("dd", "", value == null || value === "" ? "-" : String(value))); + } + heading.append(details); + const dismiss = element("button", "opportunities-extension-icon-button"); + dismiss.type = "button"; + dismiss.title = "Close"; + dismiss.setAttribute("aria-label", "Close Action form"); + dismiss.append(createCloseIcon()); + dismiss.addEventListener("click", () => close()); + header.append(heading, dismiss); + const form = element("form", "opportunities-extension-action-form"); + // Form-only version: never submit or navigate until the API contract is provided. + form.addEventListener("submit", event => event.preventDefault()); + const fields = []; + for (const [name, label, type] of [ + ["team", "Team", "text"], ["startDate", "Start date", "date"], + ["endDate", "End Date", "date"], ["status", "Status", "text"], + ["complexity", "Complexity", "text"], ["notes", "Notes", "textarea"] + ]) { + const field = element("label", "opportunities-extension-action-form-field"); + const input = element(type === "textarea" ? "textarea" : "input"); + if (type !== "textarea") input.type = type; + else input.rows = 5; + input.name = name; + input.id = `opportunities-extension-action-form-${name}`; + field.htmlFor = input.id; + if (name === "notes" || name === "team") field.className += " opportunities-extension-action-form-wide"; + field.append(element("span", "", label), input); + form.append(field); + fields.push(input); + } + const footer = element("footer", "opportunities-extension-action-form-footer"); + const save = element("button", "opportunities-extension-action-form-save", "Save"); + save.type = "submit"; + save.disabled = true; + save.title = "Gravacao ainda nao disponivel"; + const cancel = element("button", "", "Cancel"); + cancel.type = "button"; + cancel.addEventListener("click", () => close()); + footer.append(save, cancel); + form.append(footer); + dialog.append(header, form); + modal.append(dialog); + host.append(modal); + active = { modal, trigger }; + modal.addEventListener("click", event => { if (event.target === modal) close(); }); + modal.addEventListener("keydown", event => { + if (event.key !== "Tab") return; + const controls = [dismiss, ...fields, cancel]; + const index = controls.indexOf(document.activeElement); + if (index === -1 || (!event.shiftKey && index === controls.length - 1) || (event.shiftKey && index === 0)) { + event.preventDefault(); + controls[event.shiftKey ? controls.length - 1 : 0].focus(); + } + }); + fields[0].focus(); + } + return { createButton, open, close }; } // Source: src/features/opportunities/fiscal-periods.js @@ -2756,7 +2985,7 @@ function createOpportunitiesTable({ const tableBody = document.createElement("tbody"); const items = getSortedOpportunities(); - renderStageDashboard(items); + renderStageDashboard(items, opportunitiesTableState.opportunitiesTableState.items.length); if (opportunitiesTableState.opportunitiesTableState.status === "loading" || opportunitiesTableState.opportunitiesTableState.status === "error" || opportunitiesTableState.opportunitiesTableState.status === "empty" || (opportunitiesTableState.opportunitiesTableState.status === "ready" && items.length === 0)) { const row = document.createElement("tr"); @@ -2862,7 +3091,7 @@ function createOpportunitiesDashboard({ environment }) { const { document, requestAnimationFrame, performance } = environment; - function renderStageDashboard(items) { + function renderStageDashboard(items, totalCount = items.length) { const dashboard = document.getElementById(STAGE_DASHBOARD_ID); if (!dashboard) { @@ -2879,12 +3108,12 @@ function createOpportunitiesDashboard({ totalCard.setAttribute("data-stage", "TOTAL"); totalLabel.textContent = "Total Opportunities"; totalValue.className = "opportunities-extension-stage-dashboard-value"; - totalValue.setAttribute("aria-label", "Total opportunities"); + totalValue.setAttribute("aria-label", `${items.length} filtered opportunities out of ${totalCount} total`); animateStageDashboardValue( totalValue, "TOTAL", items.length, - (amount) => Math.round(amount).toLocaleString() + (amount) => `${Math.round(amount).toLocaleString()}/${totalCount.toLocaleString()}` ); totalCard.append(totalLabel, totalValue); dashboard.append(totalCard); @@ -3313,11 +3542,14 @@ function createOpportunitiesFilters({ function getSortedOpportunities() { const normalizedSearch = opportunitiesFilterState.tableSearch.trim().toLocaleLowerCase(); + const allStages = STAGE_OPTIONS.every(stage => opportunitiesFilterState.selectedStages.has(stage)); + const allCustomers = getCustomerOptions().every(option => opportunitiesFilterState.selectedCustomerKeys.has(option.key)); + const allOwners = getOwnerOptions().every(option => opportunitiesFilterState.selectedOwnerKeys.has(option.key)); const items = opportunitiesTableState.opportunitiesTableState.items.filter((item) => { - return opportunitiesFilterState.selectedStages.has(item.ForecastGroup_c) + return (allStages || opportunitiesFilterState.selectedStages.has(item.ForecastGroup_c)) && matchesSelectedStatus(item.StatusCode) - && opportunitiesFilterState.selectedCustomerKeys.has(getCustomerKey(item)) - && opportunitiesFilterState.selectedOwnerKeys.has(getOwnerKey(item)) + && (allCustomers || opportunitiesFilterState.selectedCustomerKeys.has(getCustomerKey(item))) + && (allOwners || opportunitiesFilterState.selectedOwnerKeys.has(getOwnerKey(item))) && matchesTableSearch(item, normalizedSearch) && matchesActivities(item); }); @@ -3370,6 +3602,7 @@ function createOpportunitiesFilters({ } function matchesSelectedStatus(statusCode) { + if (STATUS_OPTIONS.every(status => opportunitiesFilterState.selectedStatuses.has(status))) return true; if (statusCode === "WON_PENDING") { return opportunitiesFilterState.selectedStatuses.has("WON"); } @@ -3462,7 +3695,7 @@ function createOpportunitiesFormatters({ (items || opportunitiesTableState.opportunitiesTableState.items).forEach((item) => { const key = getOwnerKey(item); - const label = getOwnerName(item); + const label = String(getOwnerName(item)).trim() || "-"; if (key && label && !optionsByKey.has(key)) { optionsByKey.set(key, { key, label: String(label) }); @@ -3479,7 +3712,9 @@ function createOpportunitiesFormatters({ function getOwnerKey(item) { const owner = item.Owner; const partyId = owner && typeof owner === "object" ? owner.PartyId : ""; - const name = getOwnerName(item); + const name = String(getOwnerName(item)).trim(); + + if (!name) return "owner:unassigned"; if (partyId !== null && partyId !== undefined && partyId !== "") { return `party:${partyId}`; @@ -4178,6 +4413,7 @@ function createProductsContentJobs({ // Source: src/features/products/details.js function createProductsDetails({ OPPORTUNITIES_COLUMNS, + setBadgeContent, createAiSummaryAlert, formatOracleResponseDate, productsContentState, @@ -4195,7 +4431,7 @@ function createProductsDetails({ const badge = document.createElement("span"); badge.className = "opportunities-extension-products-ramp"; badge.setAttribute("data-missing", String(values.includes("N/D"))); - badge.textContent = `RM ${values.join(",")}`; + setBadgeContent(badge, "ramp", values.join(",")); badge.title = `Ramp Months: ${values.join(", ")}`; badge.setAttribute("aria-label", badge.title); return badge; @@ -4209,7 +4445,7 @@ function createProductsDetails({ button.type = "button"; button.className = "opportunities-extension-products-count"; - button.textContent = String(count); + setBadgeContent(button, "products", count); button.setAttribute("aria-expanded", String(isExpanded)); button.setAttribute("aria-label", `${count} product${count === 1 ? "" : "s"} for opportunity ${normalizedOptyNumber}`); button.title = productsResult.error ? productsResult.error : `${count} product${count === 1 ? "" : "s"}`; @@ -7266,6 +7502,7 @@ function createContentApplication(overrides = {}) { environment }); const contentModal = createContentModal({ + closeActionForm: (...args) => workloadActionForm.close(...args), createActivityFilterControls: (...args) => activityFilters.createControls(...args), closeCrmSrPopover: () => crmSrPopover.close(), ensureCurrentUser: () => currentUser.ensure(), @@ -7431,7 +7668,9 @@ function createContentApplication(overrides = {}) { createCopyButton: (...args) => opportunitiesLinks.createCopyOpportunityButton(...args), createCloseIcon: (...args) => contentIcons.createCloseIcon(...args), environment }); + const opportunityBadgeContent = createOpportunityBadgeContent({ environment }); const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), activityCache, reportProgress: (...args) => activityProgress.update("sr", ...args), allowsCrmActivities: () => currentUser.allowsCrmActivities(), @@ -7567,6 +7806,7 @@ function createContentApplication(overrides = {}) { }); const activityProgress = createActivityProgress({ MODAL_ID: contracts.MODAL_ID, environment }); const activityFilters = createActivityFilters({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), allowsCrmActivities: () => currentUser.allowsCrmActivities(), getSrSummary: number => opportunityCrmServiceRequests.getSummary(number), getActionSummary: number => opportunityWorkloadActions.getSummary(number), @@ -7575,9 +7815,9 @@ function createContentApplication(overrides = {}) { }); const productActivities = createProductActivities({ productsContentState, opportunitiesQueryState, - resetCrm: () => opportunityCrmServiceRequests.reset(), loadCrm: (...args) => opportunityCrmServiceRequests.load(...args), loadActions: (...args) => opportunityWorkloadActions.loadProducts(...args), + blockActions: products => opportunityWorkloadActions.blockProducts(products), render: () => { productsContentJobs.renderProductsProgress(); productsContentJobs.queueProductsTableRender(); @@ -7597,7 +7837,19 @@ function createContentApplication(overrides = {}) { sendRuntimeMessage: (...args) => platformContentMessages.sendRuntimeMessage(...args), environment }); + const workloadActionForm = createWorkloadActionForm({ + getOpportunity: number => opportunitiesTableState.opportunitiesTableState.items.find(item => String(item.OptyNumber) === String(number)), + formatDate: value => opportunitiesFormatters.formatOracleResponseDate(value), + MODAL_ID: contracts.MODAL_ID, + allowsCrmActivities: () => currentUser.allowsCrmActivities(), + isMissingAction: number => opportunityWorkloadActions.getSummary(number)?.state === "missing", + createCloseIcon: () => contentIcons.createCloseIcon(), + environment + }); const opportunityWorkloadActions = createOpportunityWorkloadActions({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), + createActionButton: number => workloadActionForm.createButton(number), + closeActionForm: (...args) => workloadActionForm.close(...args), activityCache, reportProgress: (...args) => activityProgress.update("actions", ...args), allowsCrmActivities: () => currentUser.allowsCrmActivities(), @@ -7609,6 +7861,7 @@ function createContentApplication(overrides = {}) { productsContentState, messageTypes, environment }); const productsDetails = createProductsDetails({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), OPPORTUNITIES_COLUMNS: columns, createAiSummaryAlert: (...args) => aiSummaryContent.createAiSummaryAlert(...args), formatOracleResponseDate: (...args) => opportunitiesFormatters.formatOracleResponseDate(...args), @@ -7772,6 +8025,7 @@ function createContentApplication(overrides = {}) { startContentApplication({ environment, page: contentFusionPage, styles: contentStyles, products: productsContentJobs }); } return { + workloadActionForm, activityFilters, start, contracts, opportunityWorkloadActions, diff --git a/dist/firefox/background.js b/dist/firefox/background.js index 5ef13dd..3b85841 100644 --- a/dist/firefox/background.js +++ b/dist/firefox/background.js @@ -250,14 +250,22 @@ function createAuthConsumerSession({ const isHtmlFallback = error && error.code === "INVALID_JSON_RESPONSE" && error.httpStatus === 200; + const isSessionUnauthorized = error && (error.httpStatus === 401 || error.httpStatus === 403); + const needsSessionRecovery = isHtmlFallback || isSessionUnauthorized; + const retryReason = isSessionUnauthorized + ? `HTTP ${error.httpStatus} response requires SPA session recovery` + : "HTTP 200 response did not contain valid JSON"; const debugEntry = debugRequests[debugRequests.length - 1]; - if (!isHtmlFallback || attempt >= CUSTOMER_TOKEN_MAX_ATTEMPTS) { + if (!needsSessionRecovery || attempt >= CUSTOMER_TOKEN_MAX_ATTEMPTS) { if (debugEntry) { debugEntry.metadata.attempt = String(attempt); - if (isHtmlFallback) { + if (needsSessionRecovery) { debugEntry.metadata.retryLimitReached = "true"; - debugEntry.error = `requestConsumerTokenService returned invalid JSON after ${CUSTOMER_TOKEN_MAX_ATTEMPTS} attempts.`; + debugEntry.metadata.retryReason = retryReason; + debugEntry.error = isHtmlFallback + ? `requestConsumerTokenService returned invalid JSON after ${CUSTOMER_TOKEN_MAX_ATTEMPTS} attempts.` + : `requestConsumerTokenService failed with status ${error.httpStatus} after ${CUSTOMER_TOKEN_MAX_ATTEMPTS} attempts.`; error.message = debugEntry.error; } } @@ -285,7 +293,7 @@ function createAuthConsumerSession({ const retryDelayMs = getConsumerTokenRetryDelay(attempt); if (debugEntry) { debugEntry.metadata.attempt = String(attempt); - debugEntry.metadata.retryReason = "HTTP 200 response did not contain valid JSON"; + debugEntry.metadata.retryReason = retryReason; debugEntry.metadata.nextRetryDelayMs = String(retryDelayMs); } @@ -874,7 +882,10 @@ function createHttpBackgroundJson({ appendBackgroundDebugEntry(debugRequests, debugEntry); if (!response.ok) { - throw new Error(`${requestName} failed with status ${response.status}.`); + const error = new Error(`${requestName} failed with status ${response.status}.`); + error.httpStatus = response.status; + debugEntry.error = error.message; + throw error; } if (responsePayload.error) { diff --git a/dist/firefox/content.js b/dist/firefox/content.js index 8e3d853..f976c44 100644 --- a/dist/firefox/content.js +++ b/dist/firefox/content.js @@ -1,6 +1,6 @@ (function () { "use strict"; -const redwoodStyles = "\n .opportunities-extension-scroll-lock {\n overflow: hidden !important;\n }\n\n .opportunities-extension-modal,\n .opportunities-extension-modal * {\n box-sizing: border-box;\n font-family: \"Oracle Sans\", Arial, Helvetica, sans-serif;\n }\n\n .opportunities-extension-modal {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n background: #f5f4f2;\n color: #000000;\n }\n\n .opportunities-extension-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-shell {\n height: 100vh;\n min-height: 0;\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n background: #f5f4f2;\n }\n\n .opportunities-extension-header {\n position: relative;\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 24px;\n padding: 28px 40px 22px;\n border-bottom: 1px solid #dedbd7;\n background:\n linear-gradient(90deg, #8f624a 0 11%, #c74634 11% 23%, #6f5a7f 23% 36%, #00758f 36% 51%, #d4b06a 51% 63%, transparent 63% 100%) top left / 100% 6px no-repeat,\n #ffffff;\n }\n\n .opportunities-extension-header::before {\n position: absolute;\n left: 40px;\n bottom: -1px;\n width: 64px;\n height: 3px;\n background: #00758f;\n content: \"\";\n }\n\n .opportunities-extension-header h1 {\n margin: 0;\n color: #000000;\n font-size: 24px;\n font-weight: 700;\n line-height: 1.2;\n letter-spacing: 0;\n }\n\n .opportunities-extension-header p {\n margin: 0;\n color: #5f5a55;\n font-size: 14px;\n line-height: 1.4;\n }\n\n .opportunities-extension-subtitle-row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n margin-top: 6px;\n }\n\n .opportunities-extension-auth-badge {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n color: #ffffff;\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-auth-badge-authenticated {\n background: #3f6f17;\n }\n\n .opportunities-extension-auth-badge-unauthenticated {\n background: #c5331f;\n }\n\n .opportunities-extension-auth-badge-pending {\n background: #6f5a7f;\n }\n\n .opportunities-extension-products-progress {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n background: #e8f4f6;\n color: #006d7a;\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-products-progress[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-products-cache-timestamp {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n background: #f0eeeb;\n color: #5f5a55;\n font-size: 11px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .opportunities-extension-products-cache-timestamp[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-products-progress[data-state=\"running\"]::before {\n width: 12px;\n height: 12px;\n margin-right: 6px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n content: \"\";\n animation: opportunities-extension-spin .8s linear infinite;\n }\n\n .opportunities-extension-products-progress[data-state=\"complete\"] {\n background: #e2f2e5;\n color: #356d19;\n }\n\n .opportunities-extension-products-progress[data-state=\"complete-with-errors\"],\n .opportunities-extension-products-progress[data-state=\"error\"] {\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n @keyframes opportunities-extension-spin {\n to { transform: rotate(360deg); }\n }\n\n .opportunities-extension-icon-button {\n width: 36px;\n height: 36px;\n flex: 0 0 36px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 18px;\n font-weight: 600;\n line-height: 1;\n cursor: pointer;\n }\n\n .opportunities-extension-header-actions {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n\n .opportunities-extension-icon-button svg {\n width: 18px;\n height: 18px;\n vertical-align: middle;\n }\n\n .opportunities-extension-icon-button .opportunities-extension-settings-icon {\n width: 20px;\n height: 20px;\n }\n\n .opportunities-extension-icon-button:hover,\n .opportunities-extension-icon-button:focus {\n border-color: #b8b2ad;\n background: #f5f4f2;\n outline: none;\n }\n\n .opportunities-extension-body {\n display: grid;\n min-height: 0;\n grid-template-rows: auto auto minmax(0, 1fr);\n gap: 16px;\n padding: 22px 40px 36px;\n background: #f5f4f2;\n overflow: hidden;\n }\n\n .opportunities-extension-form {\n display: flex;\n align-items: end;\n flex-wrap: wrap;\n gap: 24px;\n min-height: 82px;\n max-width: none;\n margin: 0;\n padding: 14px 16px;\n border: 1px solid #dedbd7;\n border-radius: 4px;\n background: #ffffff;\n }\n\n .opportunities-extension-field {\n display: grid;\n max-width: max-content;\n min-width: 270px;\n width: max-content;\n gap: 6px;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-stage-dashboard {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 12px;\n }\n\n .opportunities-extension-stage-dashboard-card {\n display: grid;\n gap: 6px;\n min-width: 0;\n padding: 12px 16px;\n border: 1px solid #dedbd7;\n border-top: 3px solid #5f5a55;\n border-radius: 4px;\n background: #ffffff;\n }\n\n .opportunities-extension-stage-dashboard-card span {\n color: #5f5a55;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-stage-dashboard-value {\n overflow: hidden;\n color: #312d2a;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.2;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"SQL\"] {\n border-top-color: #008aa6;\n }\n\n .opportunities-extension-total-dashboard-card {\n border-top-color: #312d2a;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"PIPELINE\"] {\n border-top-color: #6f6863;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"UPSIDE\"] {\n border-top-color: #c87b00;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"FORECAST\"] {\n border-top-color: #755b8b;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"WON\"] {\n border-top-color: #4b7f22;\n }\n\n .opportunities-extension-stage-filter {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 0;\n }\n\n .opportunities-extension-stage-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-stage-filter-controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n }\n\n .opportunities-extension-stage-filter-button {\n min-height: 36px;\n padding: 6px 12px;\n border: 1px solid currentColor;\n border-radius: 18px;\n background: #ffffff;\n color: #5f5a55;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"SQL\"] {\n color: #006b84;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"PIPELINE\"] {\n color: #5f5a55;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"UPSIDE\"] {\n color: #945400;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"FORECAST\"] {\n color: #624e74;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"WON\"] {\n color: #3f6f17;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"SQL\"] {\n border-color: #006b84;\n background: #006b84;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"PIPELINE\"] {\n border-color: #5f5a55;\n background: #5f5a55;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"UPSIDE\"] {\n border-color: #945400;\n background: #945400;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"FORECAST\"] {\n border-color: #624e74;\n background: #624e74;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"WON\"] {\n border-color: #3f6f17;\n background: #3f6f17;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-status-filter {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 0;\n }\n\n .opportunities-extension-status-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-status-filter-controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n }\n\n .opportunities-extension-status-filter-button {\n min-height: 36px;\n padding: 6px 12px;\n border: 1px solid currentColor;\n border-radius: 18px;\n background: #ffffff;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"OPEN\"] {\n color: #197a3d;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"CLOSED\"] {\n color: #4b5563;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"LOST\"] {\n color: #b13b34;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"WON\"] {\n color: #1f5f99;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"OPEN\"] {\n border-color: #197a3d;\n background: #197a3d;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"CLOSED\"] {\n border-color: #4b5563;\n background: #4b5563;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"LOST\"] {\n border-color: #b13b34;\n background: #b13b34;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"WON\"] {\n border-color: #1f5f99;\n background: #1f5f99;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-customer-filter {\n position: relative;\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 220px;\n }\n\n .opportunities-extension-customer-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-customer-filter-trigger {\n position: relative;\n min-width: 220px;\n min-height: 44px;\n padding: 10px 38px 10px 12px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.3;\n text-align: left;\n cursor: pointer;\n }\n\n .opportunities-extension-customer-filter-trigger::after {\n position: absolute;\n top: 50%;\n right: 16px;\n width: 0;\n height: 0;\n border-top: 6px solid #312d2a;\n border-right: 5px solid transparent;\n border-left: 5px solid transparent;\n content: \"\";\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n .opportunities-extension-customer-filter-trigger:disabled {\n cursor: not-allowed;\n background: #f5f4f2;\n color: #7d7772;\n }\n\n .opportunities-extension-customer-filter-trigger:focus-visible {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-customer-filter-panel {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n z-index: 4;\n display: grid;\n width: min(360px, calc(100vw - 80px));\n gap: 10px;\n padding: 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .18);\n }\n\n .opportunities-extension-customer-filter-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-customer-filter-search {\n width: 100%;\n min-height: 40px;\n padding: 8px 10px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n }\n\n .opportunities-extension-customer-filter-search:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-customer-filter-option {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-customer-filter-select-all {\n min-height: 32px;\n padding-bottom: 8px;\n border-bottom: 1px solid #dedbd7;\n font-weight: 700;\n }\n\n .opportunities-extension-customer-filter-panel input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n flex: 0 0 16px;\n accent-color: #00758f;\n }\n\n .opportunities-extension-customer-filter-list {\n display: block;\n max-height: 250px;\n overflow: auto;\n }\n\n .opportunities-extension-customer-filter-option {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: start;\n min-height: 0;\n height: auto !important;\n padding: 8px 4px;\n cursor: pointer;\n }\n\n .opportunities-extension-customer-filter-option input[type=\"checkbox\"] {\n margin-top: 1px;\n }\n\n .opportunities-extension-customer-filter-option span {\n display: block;\n min-width: 0;\n line-height: 18px;\n overflow-wrap: anywhere;\n white-space: normal;\n }\n\n .opportunities-extension-customer-filter-option:hover {\n background: #f5f4f2;\n }\n\n .opportunities-extension-customer-filter-empty {\n margin: 4px 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-table-search-field {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n width: 260px;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-table-search-field input {\n width: 100%;\n min-height: 44px;\n padding: 10px 12px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.3;\n }\n\n .opportunities-extension-table-search-field input:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-select-wrap {\n position: relative;\n display: block;\n width: 270px;\n max-width: 100%;\n }\n\n .opportunities-extension-select-wrap::after {\n position: absolute;\n top: 50%;\n right: 16px;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-top: 6px solid #000000;\n content: \"\";\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n .opportunities-extension-field select {\n width: 100%;\n min-width: 0;\n max-width: 100%;\n min-height: 44px;\n box-sizing: border-box;\n appearance: none;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #000000;\n font-size: 14px;\n line-height: 1.3;\n padding: 11px 44px 11px 12px;\n }\n\n .opportunities-extension-field select:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-table-surface {\n min-height: 0;\n height: 100%;\n border: 1px solid #dedbd7;\n border-radius: 4px;\n background: #ffffff;\n overflow-x: auto;\n overflow-y: auto;\n }\n\n .opportunities-extension-table {\n width: 100%;\n min-width: 0;\n border-collapse: collapse;\n table-layout: fixed;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-table thead {\n background: #faf9f8;\n }\n\n .opportunities-extension-table th {\n position: sticky;\n top: 0;\n z-index: 1;\n height: 44px;\n border-bottom: 1px solid #b8b2ad;\n background: #faf9f8;\n color: #312d2a;\n font-size: 12px;\n font-weight: 700;\n text-align: left;\n white-space: nowrap;\n }\n\n .opportunities-extension-table td {\n min-height: 48px;\n padding: 12px 16px;\n border-bottom: 1px solid #ebe8e5;\n vertical-align: middle;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-table th:nth-child(1) {\n width: 16%;\n }\n\n .opportunities-extension-table th:nth-child(2) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 18%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 11%;\n }\n\n .opportunities-extension-table th:nth-child(5) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(8) {\n width: 6%;\n }\n\n .opportunities-extension-table th:nth-child(9) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(11) {\n width: 4%;\n }\n\n .opportunities-extension-table td:nth-child(2),\n .opportunities-extension-table td:nth-child(5),\n .opportunities-extension-table td:nth-child(6),\n .opportunities-extension-table td:nth-child(8) {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .opportunities-extension-table td:nth-child(9) {\n padding-right: 6px;\n padding-left: 6px;\n white-space: nowrap;\n overflow: visible;\n }\n\n .opportunities-extension-table td:nth-child(7) {\n padding-right: 6px;\n padding-left: 6px;\n white-space: nowrap;\n overflow: visible;\n }\n\n .opportunities-extension-table td:nth-child(10) {\n padding-right: 6px;\n padding-left: 6px;\n font-size: 12px;\n white-space: nowrap;\n }\n\n .opportunities-extension-table td:nth-child(11) {\n padding-right: 6px;\n padding-left: 6px;\n text-align: center;\n white-space: nowrap;\n }\n\n .opportunities-extension-table tbody tr:hover {\n background: #f7f6f4;\n }\n\n .opportunities-extension-table tbody tr:last-child td {\n border-bottom: 0;\n }\n\n .opportunities-extension-table a {\n color: #006b84;\n text-decoration: underline;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n }\n\n .opportunities-extension-table a:hover {\n color: #004f63;\n }\n\n .opportunities-extension-opty-number-content {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n max-width: 100%;\n }\n\n .opportunities-extension-name-content {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n }\n\n .opportunities-extension-name-content > a {\n min-width: 0;\n }\n\n .opportunities-extension-actions-content {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n white-space: nowrap;\n }\n\n .opportunities-extension-products-count {\n display: inline-grid;\n width: auto;\n min-width: 20px;\n height: 20px;\n place-items: center;\n flex: 0 0 auto;\n box-sizing: border-box;\n padding: 0 3px;\n border: 1px solid #7ca7b2;\n border-radius: 999px;\n background: #e8f4f6;\n color: #006d7a;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n }\n\n .opportunities-extension-products-count:hover,\n .opportunities-extension-products-count:focus-visible,\n .opportunities-extension-products-count[aria-expanded=\"true\"] {\n border-color: #00758f;\n background: #00758f;\n color: #ffffff;\n outline: none;\n }\n\n .opportunities-extension-products-count-error {\n border-color: #d8887e;\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n .opportunities-extension-products-detail-row:hover {\n background: transparent !important;\n }\n\n .opportunities-extension-products-detail-cell {\n padding: 0 !important;\n }\n\n .opportunities-extension-products-detail {\n padding: 14px 20px 18px;\n border-bottom: 1px solid #c9c5c1;\n background: #f0eeeb;\n }\n\n .opportunities-extension-products-detail-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 10px;\n color: #312d2a;\n }\n\n .opportunities-extension-ai-summary {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n margin: 0 0 12px;\n padding: 12px 16px;\n border: 1px solid #dedbd7;\n border-radius: 6px;\n background: #ffffff;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.5;\n text-align: left;\n white-space: normal;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-ai-summary strong {\n display: block;\n font-size: 13px;\n font-weight: 600;\n }\n\n .opportunities-extension-ai-summary p {\n margin: 4px 0 0;\n font: inherit;\n white-space: pre-wrap;\n }\n\n .opportunities-extension-ai-summary-error {\n color: #b42318;\n border-color: #d9928b;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-ai-summary {\n background: #292827;\n color: #f6f4f2;\n border-color: #5f5a55;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-ai-summary-error {\n color: #ffb4ab;\n border-color: #a45c55;\n }\n\n .opportunities-extension-products-detail-heading strong {\n font-size: 13px;\n }\n\n .opportunities-extension-products-detail-heading span {\n color: #5f5a55;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n }\n\n .opportunities-extension-products-table {\n width: 100%;\n table-layout: fixed;\n border-collapse: collapse;\n border: 1px solid #dedbd7;\n background: #ffffff;\n font-size: 12px;\n }\n\n .opportunities-extension-products-table th,\n .opportunities-extension-products-table td {\n position: static;\n height: auto;\n padding: 8px 10px;\n border-bottom: 1px solid #ebe8e5;\n background: transparent;\n overflow-wrap: anywhere;\n vertical-align: middle;\n white-space: normal;\n }\n\n .opportunities-extension-products-table th {\n background: #faf9f8;\n font-size: 11px;\n }\n\n .opportunities-extension-products-table th:nth-child(1) { width: 16%; }\n .opportunities-extension-products-table th:nth-child(2) { width: 16%; }\n .opportunities-extension-products-table th:nth-child(3) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(4) { width: 10%; }\n .opportunities-extension-products-table th:nth-child(5) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(6) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(7) { width: 7%; }\n .opportunities-extension-products-table th:nth-child(8) { width: 10%; }\n .opportunities-extension-products-table th:nth-child(9) { width: 12%; }\n .opportunities-extension-products-table th:nth-child(10) { width: 5%; }\n\n .opportunities-extension-products-empty {\n margin: 0;\n padding: 10px 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-copy-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 24px;\n height: 24px;\n padding: 3px;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-copy-button svg {\n width: 16px;\n height: 16px;\n fill: currentColor;\n }\n\n .opportunities-extension-copy-button:hover,\n .opportunities-extension-copy-button:focus-visible {\n background: #e8f4f6;\n color: #004f63;\n outline: none;\n }\n\n .opportunities-extension-action-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 5px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-action-button svg {\n width: 21px;\n height: 21px;\n }\n\n .opportunities-extension-action-button:hover,\n .opportunities-extension-action-button:focus-visible {\n border-color: #7ca7b2;\n background: #e8f4f6;\n color: #004f63;\n outline: none;\n }\n\n .opportunities-extension-action-button:disabled {\n cursor: wait;\n opacity: .72;\n }\n\n .opportunities-extension-action-button-loading svg {\n animation: opportunities-extension-pulse 1s ease-in-out infinite;\n }\n\n @keyframes opportunities-extension-pulse {\n 50% { opacity: .35; }\n }\n\n .opportunities-extension-copy-toast {\n position: fixed;\n right: 28px;\n bottom: 28px;\n z-index: 3;\n max-width: min(360px, calc(100vw - 56px));\n padding: 12px 16px;\n border-radius: 4px;\n background: #2f6f18;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .18);\n color: #ffffff;\n font-size: 13px;\n font-weight: 700;\n }\n\n .opportunities-extension-copy-toast-error {\n background: #a52b1c;\n }\n\n .opportunities-extension-copy-toast[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-stage-badge {\n display: inline-flex;\n align-items: center;\n min-height: 24px;\n padding: 3px 8px;\n border-radius: 12px;\n background: #ebe8e5;\n color: #312d2a;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"SQL\"] {\n background: #d9f0f5;\n color: #006b84;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"PIPELINE\"] {\n background: #ebe8e5;\n color: #5f5a55;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"UPSIDE\"] {\n background: #fff0d8;\n color: #945400;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"FORECAST\"] {\n background: #eee8f5;\n color: #624e74;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"WON\"] {\n background: #e5f1d9;\n color: #3f6f17;\n }\n\n .opportunities-extension-status-badge {\n display: inline-flex;\n align-items: center;\n min-height: 24px;\n padding: 3px 8px;\n border-radius: 12px;\n background: #ebe8e5;\n color: #312d2a;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n }\n\n .opportunities-extension-status-badge[data-status=\"OPEN\"] {\n background: #e2f2e5;\n color: #197a3d;\n }\n\n .opportunities-extension-status-badge[data-status=\"CLOSED\"] {\n background: #e5e7eb;\n color: #4b5563;\n }\n\n .opportunities-extension-status-badge[data-status=\"LOST\"] {\n background: #f9e3e1;\n color: #b13b34;\n }\n\n .opportunities-extension-status-badge[data-status=\"WON\"] {\n background: #e3edf8;\n color: #1f5f99;\n }\n\n .opportunities-extension-sort-button {\n position: relative;\n display: inline-flex;\n align-items: center;\n width: 100%;\n min-height: 44px;\n padding: 8px 42px 8px 16px;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: inherit;\n letter-spacing: 0;\n line-height: 1.2;\n text-align: left;\n white-space: normal;\n cursor: pointer;\n }\n\n .opportunities-extension-table-header-label {\n display: inline-flex;\n align-items: center;\n min-height: 44px;\n padding: 8px 6px;\n }\n\n .opportunities-extension-sort-button::after {\n position: absolute;\n right: 15px;\n color: #5f5a55;\n content: \"↕\";\n font-size: 16px;\n font-weight: 400;\n }\n\n .opportunities-extension-sort-button[data-sort-direction=\"ascending\"]::after {\n color: #00758f;\n content: \"↑\";\n }\n\n .opportunities-extension-sort-button[data-sort-direction=\"descending\"]::after {\n color: #00758f;\n content: \"↓\";\n }\n\n .opportunities-extension-sort-button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-sort-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n }\n\n .opportunities-extension-table-status {\n height: 152px;\n color: #5f5a55;\n font-size: 14px;\n text-align: center;\n }\n\n .opportunities-extension-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n .opportunities-extension-preferences-modal {\n position: absolute;\n inset: 0;\n z-index: 3;\n display: grid;\n place-items: center;\n padding: 24px;\n background: rgba(0, 0, 0, .42);\n }\n\n .opportunities-extension-preferences-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plans-modal {\n position: absolute;\n inset: 0;\n z-index: 4;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(0, 0, 0, .42);\n }\n\n .opportunities-extension-account-plans-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plans-dialog {\n display: grid;\n width: min(1180px, 100%);\n height: min(760px, calc(100vh - 24px));\n min-width: 0;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-columns: minmax(0, 1fr);\n overflow: hidden;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, .24);\n color: #312d2a;\n }\n\n .opportunities-extension-account-plans-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n padding: 14px 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-header h2 {\n margin: 0;\n font-size: 20px;\n line-height: 1.2;\n }\n\n .opportunities-extension-account-plans-header p {\n margin: 5px 0 0;\n color: #5f5a55;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-account-plans-content {\n display: grid;\n min-width: 0;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-columns: minmax(0, 1fr);\n min-height: 0;\n overflow: hidden;\n }\n\n .opportunities-extension-account-plans-content > .opportunities-extension-account-plans-skeleton {\n grid-row: 1 / -1;\n }\n\n .opportunities-extension-account-plans-tabs-navigation {\n position: relative;\n min-width: 0;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-tabs-navigation .opportunities-extension-account-plans-tab-navigation-button[hidden] {\n display: none;\n }\n\n .opportunities-extension-account-plans-tabs {\n display: flex;\n min-width: 0;\n gap: 4px;\n overflow-x: auto;\n padding: 8px 20px 0;\n scrollbar-width: none;\n }\n\n .opportunities-extension-account-plans-tabs::-webkit-scrollbar {\n display: none;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button {\n display: grid;\n position: absolute;\n z-index: 1;\n top: 50%;\n width: 32px;\n height: 32px;\n place-items: center;\n padding: 0;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n box-shadow: 0 2px 6px rgba(0, 0, 0, .16);\n transform: translateY(-50%);\n cursor: pointer;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:first-child {\n left: 8px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:last-child {\n right: 8px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:hover:not(:disabled) {\n border-color: #00758f;\n background: #f0eeeb;\n color: #005e73;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:disabled {\n border-color: #dedbd7;\n color: #b8b2ad;\n cursor: default;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button svg {\n width: 18px;\n height: 18px;\n }\n\n .opportunities-extension-account-plans-panels {\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n }\n\n .opportunities-extension-account-plan-tab {\n min-height: 38px;\n flex: 0 0 auto;\n padding: 7px 12px;\n border: 0;\n border-bottom: 3px solid transparent;\n background: transparent;\n color: #5f5a55;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n }\n\n .opportunities-extension-account-plan-tab:hover {\n background: #f0eeeb;\n color: #312d2a;\n }\n\n .opportunities-extension-account-plan-tab[aria-selected=\"true\"] {\n border-bottom-color: #00758f;\n color: #006d7a;\n }\n\n .opportunities-extension-account-plan-tab:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n }\n\n .opportunities-extension-account-plan-panel {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n box-sizing: border-box;\n padding: 16px 20px;\n }\n\n .opportunities-extension-account-plan-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plan-details {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0 24px;\n margin: 0;\n }\n\n .opportunities-extension-account-plan-details > div {\n display: grid;\n grid-template-columns: minmax(104px, 38%) minmax(0, 1fr);\n gap: 10px;\n min-height: 42px;\n align-items: center;\n padding: 7px 0;\n border-bottom: 1px solid #ebe8e5;\n }\n\n .opportunities-extension-account-plan-details dt {\n color: #5f5a55;\n font-size: 12px;\n font-weight: 700;\n }\n\n .opportunities-extension-account-plan-details dd {\n min-width: 0;\n margin: 0;\n color: #312d2a;\n font-size: 13px;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-consumption-trend {\n display: grid;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n margin-top: 14px;\n padding-top: 12px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-consumption-trend-header {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 24px;\n }\n\n .opportunities-extension-consumption-periods {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .opportunities-extension-consumption-periods button {\n min-height: 38px;\n padding: 7px 14px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-periods button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-consumption-periods button[aria-pressed=\"true\"] {\n border-color: #00758f;\n background: #e7f6f8;\n color: #005e73;\n }\n\n .opportunities-extension-consumption-periods button:focus-visible,\n .opportunities-extension-consumption-navigation-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-consumption-chart {\n display: grid;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n margin-top: 4px;\n }\n\n .opportunities-extension-consumption-navigation {\n display: grid;\n grid-template-columns: 36px minmax(130px, auto) 36px;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-height: 40px;\n margin-bottom: 2px;\n }\n\n .opportunities-extension-consumption-navigation strong {\n color: #312d2a;\n font-size: 13px;\n text-align: center;\n }\n\n .opportunities-extension-consumption-navigation-button {\n display: grid;\n width: 36px;\n height: 36px;\n place-items: center;\n padding: 0;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-navigation-button:hover:not(:disabled) {\n border-color: #00758f;\n background: #f0eeeb;\n color: #005e73;\n }\n\n .opportunities-extension-consumption-navigation-button:disabled {\n border-color: #dedbd7;\n color: #b8b2ad;\n cursor: default;\n }\n\n .opportunities-extension-consumption-navigation-button svg {\n width: 18px;\n height: 18px;\n }\n\n .opportunities-extension-consumption-figure {\n position: relative;\n min-width: 0;\n min-height: 0;\n margin: 0;\n scrollbar-width: none;\n }\n\n .opportunities-extension-consumption-figure::-webkit-scrollbar {\n display: none;\n }\n\n .opportunities-extension-consumption-visual {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-columns: minmax(0, 1fr) 176px;\n align-items: center;\n gap: 16px;\n }\n\n .opportunities-extension-consumption-svg {\n display: block;\n width: 100%;\n height: 300px;\n min-height: 0;\n overflow: visible;\n }\n\n .opportunities-extension-consumption-svg .consumption-grid-line {\n stroke: #dedbd7;\n stroke-width: 1;\n shape-rendering: crispEdges;\n }\n\n .opportunities-extension-consumption-svg .consumption-axis-label,\n .opportunities-extension-consumption-svg .consumption-x-label {\n fill: #5f5a55;\n font-family: Arial, sans-serif;\n font-size: 12px;\n }\n\n .opportunities-extension-consumption-svg .consumption-value-label {\n fill: #312d2a;\n font-family: Arial, sans-serif;\n font-size: 12px;\n font-weight: 700;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-funded {\n fill: #b77888;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-overage {\n fill: #de7907;\n }\n\n .opportunities-extension-consumption-svg .consumption-average-line {\n stroke: #de7907;\n stroke-width: 1.5;\n stroke-dasharray: 6 6;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group {\n cursor: default;\n outline: none;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group rect {\n transition: filter .16s ease, opacity .16s ease, stroke .16s ease;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group:hover rect,\n .opportunities-extension-consumption-svg .consumption-bar-group:focus rect {\n filter: brightness(1.06);\n stroke: #312d2a;\n stroke-width: 1.5;\n }\n\n .opportunities-extension-consumption-svg .consumption-animated-label {\n opacity: 0;\n animation: opportunities-extension-consumption-label-in .24s ease-out forwards;\n }\n\n .opportunities-extension-consumption-svg .consumption-animated-average {\n opacity: 0;\n animation: opportunities-extension-consumption-average-in .35s .32s ease-out forwards;\n }\n\n @keyframes opportunities-extension-consumption-label-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n @keyframes opportunities-extension-consumption-average-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n .opportunities-extension-consumption-legend {\n display: grid;\n align-content: center;\n gap: 4px;\n }\n\n .opportunities-extension-consumption-legend button {\n display: grid;\n min-width: 0;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n padding: 6px 4px;\n border: 0;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 12px;\n line-height: 1.25;\n text-align: left;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-legend button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-consumption-legend button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 1px;\n }\n\n .opportunities-extension-consumption-legend button[aria-pressed=\"false\"] {\n color: #77726d;\n opacity: .55;\n }\n\n .opportunities-extension-consumption-legend-swatch {\n display: block;\n width: 12px;\n height: 12px;\n justify-self: center;\n }\n\n .opportunities-extension-consumption-legend-funded {\n background: #b77888;\n }\n\n .opportunities-extension-consumption-legend-overage {\n background: #de7907;\n }\n\n .opportunities-extension-consumption-legend-average {\n height: 0;\n border-top: 2px dashed #de7907;\n }\n\n .opportunities-extension-consumption-tooltip {\n position: absolute;\n z-index: 2;\n display: grid;\n min-width: 190px;\n max-width: 260px;\n gap: 4px;\n padding: 10px 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .2);\n color: #312d2a;\n font-size: 12px;\n line-height: 1.3;\n pointer-events: none;\n }\n\n .opportunities-extension-consumption-tooltip[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-consumption-tooltip strong {\n margin-bottom: 2px;\n font-size: 13px;\n }\n\n .opportunities-extension-consumption-chart-skeleton {\n height: 100%;\n min-height: 0;\n padding: 34px 62px 24px;\n box-sizing: border-box;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot {\n display: flex;\n height: 100%;\n min-height: 220px;\n align-items: flex-end;\n justify-content: space-around;\n gap: 12px;\n padding: 0 14px;\n border-bottom: 1px solid #dedbd7;\n border-left: 1px solid #dedbd7;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot span {\n width: min(38px, 6%);\n border-radius: 2px 2px 0 0;\n background: #dedbd7;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-consumption-chart-empty,\n .opportunities-extension-consumption-chart-error {\n display: grid;\n min-height: 220px;\n place-items: center;\n margin: 0;\n color: #5f5a55;\n font-size: 14px;\n text-align: center;\n }\n\n .opportunities-extension-consumption-chart-error {\n color: #9f2d20;\n }\n\n .opportunities-extension-account-plan-status-indicator {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #9b9691;\n box-shadow: 0 0 0 3px #efedeb;\n vertical-align: middle;\n }\n\n .opportunities-extension-account-plan-status-indicator[data-active=\"true\"] {\n background: #3f6f17;\n box-shadow: 0 0 0 3px #e2f2e5;\n }\n\n .opportunities-extension-account-plan-tab .opportunities-extension-account-plan-status-indicator {\n margin-right: 8px;\n }\n\n .opportunities-extension-account-plans-skeleton-tabs {\n display: flex;\n min-height: 46px;\n align-items: center;\n padding: 0 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n overflow: hidden;\n }\n\n .opportunities-extension-account-plans-skeleton-panel {\n padding: 16px 20px;\n }\n\n .opportunities-extension-account-plans-skeleton-tab {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n min-height: 38px;\n padding: 0 12px;\n border-bottom: 3px solid #00758f;\n }\n\n .opportunities-extension-account-plans-skeleton-status {\n display: block;\n width: 10px;\n height: 10px;\n flex: 0 0 auto;\n border-radius: 50%;\n background: #dedbd7;\n box-shadow: 0 0 0 3px #efedeb;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-account-plans-skeleton-details {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0 24px;\n padding: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details > div {\n display: grid;\n grid-template-columns: minmax(104px, 38%) minmax(0, 1fr);\n align-items: center;\n gap: 10px;\n min-height: 42px;\n padding: 7px 0;\n border-bottom: 1px solid #ebe8e5;\n }\n\n .opportunities-extension-account-plans-skeleton-bar {\n display: block;\n height: 12px;\n border-radius: 3px;\n background: #dedbd7;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-account-plans-skeleton-tabs .opportunities-extension-account-plans-skeleton-bar {\n height: 14px;\n }\n\n .opportunities-extension-account-plans-skeleton-label {\n width: 74%;\n height: 10px;\n }\n\n .opportunities-extension-account-plans-skeleton-trend {\n display: grid;\n min-height: 0;\n grid-template-rows: auto auto minmax(0, 1fr);\n margin: 14px 0 0;\n padding-top: 12px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton-trend-header {\n display: flex;\n justify-content: flex-end;\n min-height: 38px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods .opportunities-extension-account-plans-skeleton-bar {\n height: 12px;\n }\n\n .opportunities-extension-account-plans-skeleton-period-active {\n height: 38px !important;\n border: 1px solid #8cc8d3;\n background: #e7f6f8;\n }\n\n .opportunities-extension-account-plans-skeleton-navigation {\n display: grid;\n grid-template-columns: 32px 124px 32px;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-height: 54px;\n }\n\n .opportunities-extension-account-plans-skeleton-navigation .opportunities-extension-account-plans-skeleton-bar {\n justify-self: center;\n }\n\n .opportunities-extension-account-plans-skeleton-chart {\n display: grid;\n min-height: 0;\n grid-template-columns: minmax(0, 1fr) 150px;\n align-items: center;\n gap: 28px;\n padding: 12px 14px 0 62px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot {\n display: flex;\n position: relative;\n height: 300px;\n min-height: 0;\n box-sizing: border-box;\n align-items: flex-end;\n justify-content: space-around;\n gap: 12px;\n padding: 0 14px 64px;\n background: repeating-linear-gradient(to bottom, transparent 0, transparent 58px, #ebe8e5 58px, #ebe8e5 59px) left top / 100% 236px no-repeat;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::before,\n .opportunities-extension-account-plans-skeleton-plot::after {\n position: absolute;\n display: block;\n content: \"\";\n background: #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::before {\n top: 0;\n bottom: 64px;\n left: 0;\n width: 1px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::after {\n right: 0;\n bottom: 64px;\n left: 0;\n height: 1px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot .opportunities-extension-account-plans-skeleton-bar {\n width: min(38px, 7%);\n flex: 0 1 38px;\n border-radius: 2px 2px 0 0;\n }\n\n .opportunities-extension-account-plans-skeleton-legend {\n display: grid;\n align-content: center;\n gap: 18px;\n min-height: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-legend .opportunities-extension-account-plans-skeleton-bar {\n height: 11px;\n }\n\n @keyframes opportunities-extension-skeleton-pulse {\n from { opacity: .48; }\n to { opacity: 1; }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .opportunities-extension-account-plans-skeleton-bar,\n .opportunities-extension-consumption-chart-skeleton-plot span,\n .opportunities-extension-consumption-svg .consumption-animated-label,\n .opportunities-extension-consumption-svg .consumption-animated-average {\n animation: none;\n opacity: 1;\n }\n }\n\n .opportunities-extension-account-plans-empty,\n .opportunities-extension-account-plans-error {\n margin: 0;\n padding: 28px 20px;\n color: #5f5a55;\n font-size: 14px;\n }\n\n .opportunities-extension-account-plans-error {\n color: #9f2d20;\n }\n\n .opportunities-extension-preferences-dialog {\n display: grid;\n width: min(680px, 100%);\n max-height: min(720px, calc(100vh - 48px));\n grid-template-rows: auto minmax(0, 1fr) auto;\n overflow: hidden;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, .24);\n color: #312d2a;\n }\n\n .opportunities-extension-preferences-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 18px 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-preferences-header h2 {\n margin: 0;\n font-size: 20px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-preferences-content {\n min-height: 0;\n overflow: auto;\n padding: 20px;\n }\n\n .opportunities-extension-preferences-fieldset {\n min-width: 0;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n .opportunities-extension-preferences-fieldset legend {\n margin-bottom: 12px;\n padding: 0;\n color: #312d2a;\n font-size: 15px;\n font-weight: 700;\n line-height: 1.3;\n }\n\n .opportunities-extension-preferences-options {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 4px 20px;\n }\n\n .opportunities-extension-preferences-option {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 0;\n padding: 9px 8px;\n border-radius: 4px;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.35;\n cursor: pointer;\n }\n\n .opportunities-extension-preferences-option:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-preferences-option input {\n width: 18px;\n height: 18px;\n flex: 0 0 18px;\n margin: 0;\n accent-color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-preferences-cache-field {\n display: grid;\n width: min(280px, 100%);\n gap: 6px;\n margin-top: 24px;\n color: #312d2a;\n font-size: 14px;\n font-weight: 700;\n }\n\n .opportunities-extension-preferences-cache-field select {\n width: 100%;\n height: 40px;\n padding: 0 36px 0 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n font-weight: 400;\n }\n\n .opportunities-extension-preferences-cache-field select:focus {\n border-color: #00758f;\n outline: 2px solid #bde7ee;\n outline-offset: 0;\n }\n\n .opportunities-extension-preferences-footer {\n display: flex;\n justify-content: flex-end;\n padding: 14px 20px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-button {\n min-width: 88px;\n min-height: 36px;\n padding: 7px 16px;\n border: 1px solid transparent;\n border-radius: 4px;\n font-size: 14px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-button-primary {\n border-color: #00758f;\n background: #00758f;\n color: #ffffff;\n }\n\n .opportunities-extension-button-primary:hover,\n .opportunities-extension-button-primary:focus-visible {\n border-color: #005e73;\n background: #005e73;\n outline: none;\n }\n\n .opportunities-extension-debug-panel {\n position: fixed;\n right: 24px;\n bottom: 24px;\n z-index: 1;\n width: min(640px, calc(100vw - 48px));\n max-height: min(560px, calc(100vh - 120px));\n overflow: auto;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 2px 8px rgba(0, 0, 0, .16);\n padding: 16px;\n color: #000000;\n }\n\n .opportunities-extension-debug-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-debug-panel h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n line-height: 1.25;\n }\n\n .opportunities-extension-debug-panel p {\n margin: 4px 0 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-debug-panel-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 12px;\n }\n\n .opportunities-extension-debug-visibility-button {\n width: 34px;\n height: 34px;\n flex: 0 0 34px;\n color: #312d2a;\n }\n\n .opportunities-extension-debug-visibility-button svg {\n width: 20px;\n height: 20px;\n }\n\n .opportunities-extension-debug-list {\n display: grid;\n gap: 10px;\n }\n\n .opportunities-extension-debug-item {\n border: 1px solid #dedbd7;\n border-left-width: 4px;\n border-radius: 4px;\n background: #faf9f8;\n }\n\n .opportunities-extension-debug-item[open] {\n background: #ffffff;\n }\n\n .opportunities-extension-debug-item-success {\n border-left-color: #3f6f17;\n }\n\n .opportunities-extension-debug-item-success .opportunities-extension-debug-status {\n background: #e2f2e5;\n color: #356d19;\n }\n\n .opportunities-extension-debug-item-failed {\n border-left-color: #c5331f;\n }\n\n .opportunities-extension-debug-item-failed .opportunities-extension-debug-status {\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n .opportunities-extension-debug-item-pending {\n border-left-color: #6f5a7f;\n }\n\n .opportunities-extension-debug-item-pending .opportunities-extension-debug-status {\n background: #eee8f2;\n color: #6f5a7f;\n }\n\n .opportunities-extension-debug-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n min-height: 42px;\n padding: 9px 12px 9px 10px;\n cursor: pointer;\n list-style: none;\n }\n\n .opportunities-extension-debug-heading::-webkit-details-marker {\n display: none;\n }\n\n .opportunities-extension-debug-heading::before {\n content: \"⌄\";\n width: 14px;\n color: #5f5a55;\n font-size: 16px;\n line-height: 1;\n transform: rotate(-90deg);\n transition: transform .15s ease;\n }\n\n .opportunities-extension-debug-item[open] .opportunities-extension-debug-heading::before {\n transform: rotate(0deg);\n }\n\n .opportunities-extension-debug-summary-meta {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n }\n\n .opportunities-extension-debug-http-status,\n .opportunities-extension-debug-status {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n line-height: 1;\n text-transform: uppercase;\n }\n\n .opportunities-extension-debug-http-status {\n background: #e8f4f6;\n color: #006d7a;\n }\n\n .opportunities-extension-debug-status {\n background: #ebe8e5;\n color: #5f5a55;\n }\n\n .opportunities-extension-debug-heading strong {\n font-size: 13px;\n }\n\n .opportunities-extension-debug-item pre {\n margin: 0;\n padding: 8px 12px 12px;\n color: #312d2a;\n font-family: Consolas, \"Courier New\", monospace;\n font-size: 12px;\n line-height: 1.45;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .opportunities-extension-debug-empty {\n padding: 14px;\n border: 1px dashed #b8b2ad;\n border-radius: 4px;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] {\n background: #1f1f1f;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-shell,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-body {\n background: #1f1f1f;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header {\n border-bottom-color: #4e4a46;\n background:\n linear-gradient(90deg, #a8795d 0 11%, #dd5a47 11% 23%, #876e9b 23% 36%, #00a6be 36% 51%, #dfbd76 51% 63%, transparent 63% 100%) top left / 100% 6px no-repeat,\n #292827;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header h1,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-value,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-field,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card span,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail-heading span,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details dt,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-empty {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-error {\n color: #ffb4a8;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-error {\n color: #ffb4a8;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-bar {\n background: #5b5753;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-status {\n background: #5b5753;\n box-shadow: 0 0 0 3px #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-period-active {\n border-color: #3f7580;\n background: #23474e;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-skeleton-plot span {\n background: #5b5753;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-status-indicator {\n background: #8f8a85;\n box-shadow: 0 0 0 3px #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-status-indicator[data-active=\"true\"] {\n background: #7fb05b;\n box-shadow: 0 0 0 3px #314527;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-form,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-surface,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-panel,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-dialog,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-dialog,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item[open] {\n border-color: #4e4a46;\n background: #292827;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-search,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field input,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-field select,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-cache-field select,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger::after {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-select-wrap::after {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger:disabled {\n background: #292827;\n color: #918b86;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-search::placeholder,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field input::placeholder {\n color: #b5b0ab;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-option,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-header h2,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header h2,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-fieldset legend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-cache-field,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail-heading,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details dd,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-heading,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item pre,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel h2 {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation strong {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-empty {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table th {\n border-bottom-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-header,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-footer,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tabs-navigation,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tabs,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details > div,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-tabs,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-details > div {\n border-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-trend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-skeleton-plot,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-trend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot {\n border-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot {\n background: repeating-linear-gradient(to bottom, transparent 0, transparent 58px, #4e4a46 58px, #4e4a46 59px) left top / 100% 236px no-repeat;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot::before,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot::after {\n background: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab:hover {\n background: #3b3937;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab[aria-selected=\"true\"] {\n border-bottom-color: #43c4d5;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button[aria-pressed=\"true\"] {\n border-color: #43c4d5;\n background: #173e43;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button:hover:not(:disabled),\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button:hover:not(:disabled) {\n border-color: #43c4d5;\n background: #3b3937;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button:disabled,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button:disabled {\n border-color: #4e4a46;\n color: #746f6a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-grid-line {\n stroke: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-axis-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-x-label {\n fill: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-value-label {\n fill: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-funded {\n fill: #ca8798;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-overage {\n fill: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-average-line {\n stroke: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-group:hover rect,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-group:focus rect {\n stroke: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button[aria-pressed=\"false\"] {\n color: #a8a39e;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-funded {\n background: #ca8798;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-overage {\n background: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-average {\n border-top-color: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-tooltip {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option input {\n accent-color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary {\n border-color: #00a6be;\n background: #008aa6;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary:focus-visible {\n border-color: #43c4d5;\n background: #006d7a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-option:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table tbody tr:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sort-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button:focus {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table thead,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table th,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table th {\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table td {\n border-bottom-color: #3f3c39;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail {\n border-bottom-color: #4e4a46;\n background: #252423;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table th,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table td {\n border-bottom-color: #3f3c39;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count {\n border-color: #2f9bae;\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count:focus-visible,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count[aria-expanded=\"true\"] {\n border-color: #43c4d5;\n background: #008aa6;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"running\"] {\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"complete\"] {\n background: #244f2e;\n color: #a8dfb7;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"complete-with-errors\"],\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"error\"],\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count-error {\n border-color: #b13b34;\n background: #5f2926;\n color: #ffb4ad;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-cache-timestamp {\n background: #3b3937;\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table a,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button {\n color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table a:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button:focus-visible,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button:focus-visible {\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"SQL\"] {\n color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"PIPELINE\"] {\n color: #d1cbc6;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"UPSIDE\"] {\n color: #ffbf62;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"FORECAST\"] {\n color: #d2b7e9;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"WON\"] {\n color: #9bd46a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"SQL\"] {\n border-top-color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-total-dashboard-card {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"PIPELINE\"] {\n border-top-color: #c0b9b3;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"UPSIDE\"] {\n border-top-color: #ffb84d;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"FORECAST\"] {\n border-top-color: #cba7e7;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"WON\"] {\n border-top-color: #92cf5b;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"SQL\"] {\n border-color: #008aa6;\n background: #008aa6;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"PIPELINE\"] {\n border-color: #6f6863;\n background: #6f6863;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"UPSIDE\"] {\n border-color: #b96e00;\n background: #b96e00;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"FORECAST\"] {\n border-color: #755b8b;\n background: #755b8b;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"WON\"] {\n border-color: #4b7f22;\n background: #4b7f22;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"OPEN\"] {\n color: #69c985;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"CLOSED\"] {\n color: #c3cad3;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"LOST\"] {\n color: #ff9d94;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"WON\"] {\n color: #83bfff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"OPEN\"] {\n border-color: #197a3d;\n background: #197a3d;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"CLOSED\"] {\n border-color: #4b5563;\n background: #4b5563;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"LOST\"] {\n border-color: #b13b34;\n background: #b13b34;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"WON\"] {\n border-color: #1f5f99;\n background: #1f5f99;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item {\n border-color: #4e4a46;\n background: #252423;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button {\n color: #f6f4f2;\n }\n\n @media (min-width: 1201px) and (max-width: 1450px) {\n .opportunities-extension-table th:nth-child(1) {\n width: 16%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 18%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 12%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 10%;\n }\n }\n\n @media (max-width: 1200px) {\n .opportunities-extension-table {\n min-width: 1180px;\n }\n\n .opportunities-extension-table th:nth-child(1) {\n width: 15%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 17%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 13%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 6%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 9%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 11%;\n }\n }\n\n @media (max-width: 700px) {\n .opportunities-extension-header {\n padding: 24px 20px 18px;\n }\n\n .opportunities-extension-header::before {\n left: 20px;\n }\n\n .opportunities-extension-header h1 {\n font-size: 22px;\n }\n\n .opportunities-extension-header p {\n font-size: 14px;\n }\n\n .opportunities-extension-body {\n padding: 16px 20px 24px;\n }\n\n .opportunities-extension-form {\n align-items: stretch;\n flex-wrap: wrap;\n gap: 14px;\n min-height: auto;\n padding: 12px;\n }\n\n .opportunities-extension-field {\n max-width: none;\n width: 100%;\n }\n\n .opportunities-extension-customer-filter {\n width: 100%;\n }\n\n .opportunities-extension-customer-filter-trigger {\n width: 100%;\n }\n\n .opportunities-extension-customer-filter-panel {\n width: min(360px, calc(100vw - 64px));\n }\n\n .opportunities-extension-table-search-field {\n width: 100%;\n }\n\n .opportunities-extension-stage-dashboard {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .opportunities-extension-stage-dashboard-value {\n font-size: 18px;\n }\n\n .opportunities-extension-preferences-modal {\n padding: 12px;\n }\n\n .opportunities-extension-account-plans-modal {\n padding: 12px;\n }\n\n .opportunities-extension-preferences-dialog {\n max-height: calc(100vh - 24px);\n }\n\n .opportunities-extension-account-plans-dialog {\n height: calc(100vh - 24px);\n }\n\n .opportunities-extension-account-plan-panel {\n padding: 12px 14px;\n }\n\n .opportunities-extension-account-plan-details {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0 14px;\n }\n\n .opportunities-extension-account-plan-details > div {\n grid-template-columns: 1fr;\n align-content: center;\n gap: 3px;\n min-height: 54px;\n padding: 5px 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0 14px;\n padding: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details > div {\n grid-template-columns: 1fr;\n align-content: center;\n gap: 5px;\n min-height: 54px;\n padding: 5px 0;\n }\n\n .opportunities-extension-account-plans-skeleton-trend {\n margin: 14px 0 0;\n }\n\n .opportunities-extension-account-plans-skeleton-periods {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n align-items: center;\n gap: 6px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods .opportunities-extension-account-plans-skeleton-bar {\n width: 100% !important;\n }\n\n .opportunities-extension-account-plans-skeleton-chart {\n grid-template-columns: minmax(0, 1fr);\n gap: 12px;\n padding: 12px 8px 0 34px;\n }\n\n .opportunities-extension-account-plans-skeleton-legend {\n display: flex;\n min-height: 24px;\n align-items: center;\n justify-content: center;\n gap: 12px;\n }\n\n .opportunities-extension-consumption-trend-header {\n align-items: stretch;\n }\n\n .opportunities-extension-consumption-periods {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 3px;\n }\n\n .opportunities-extension-consumption-periods button {\n min-width: 0;\n padding: 7px 4px;\n font-size: 12px;\n }\n\n .opportunities-extension-consumption-chart {\n min-height: 0;\n }\n\n .opportunities-extension-consumption-svg {\n width: 760px;\n height: 245px;\n }\n\n .opportunities-extension-consumption-visual {\n width: 920px;\n grid-template-columns: 760px 144px;\n gap: 12px;\n }\n\n .opportunities-extension-consumption-figure {\n overflow-x: auto;\n overscroll-behavior-inline: contain;\n }\n\n .opportunities-extension-consumption-chart-skeleton {\n min-height: 0;\n padding: 24px 18px 18px;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot {\n min-height: 180px;\n gap: 4px;\n padding: 0 6px;\n }\n\n .opportunities-extension-preferences-options {\n grid-template-columns: 1fr;\n }\n\n .opportunities-extension-stage-filter-controls {\n gap: 6px;\n }\n\n .opportunities-extension-status-filter-controls {\n gap: 6px;\n }\n\n .opportunities-extension-table-surface {\n min-width: 0;\n min-height: calc(100vh - 230px);\n }\n\n .opportunities-extension-debug-panel {\n right: 12px;\n bottom: 12px;\n width: calc(100vw - 24px);\n max-height: calc(100vh - 96px);\n }\n }\n \n/* Full-page diagnostics, scoped to the extension and its current theme. */\n.opportunities-extension-modal .opportunities-extension-debug-panel {\n --debug-surface: #fff;\n --debug-code: #f5f6f7;\n --debug-text: #312d2a;\n --debug-muted: #5f5a55;\n --debug-border: #dedbd7;\n --debug-success: #22613b;\n --debug-success-bg: #e1f1e5;\n --debug-failed: #a12721;\n --debug-failed-bg: #fce8e6;\n --debug-pending: #805000;\n --debug-pending-bg: #fff1ce;\n --debug-info: #075e87;\n --debug-info-bg: #e5f1fa;\n --debug-key: #075e87;\n --debug-string: #22613b;\n --debug-number: #865000;\n --debug-literal: #73429b;\n position: fixed;\n inset: 0;\n z-index: 50;\n display: grid;\n grid-template-rows: auto auto minmax(0, 1fr);\n width: auto;\n height: auto;\n max-height: none;\n min-width: 0;\n box-sizing: border-box;\n overflow: hidden;\n margin: 0;\n padding: 20px;\n border: 0;\n border-radius: 0;\n background: var(--debug-surface);\n color: var(--debug-text);\n color-scheme: light;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel {\n --debug-surface: #292827;\n --debug-code: #222120;\n --debug-text: #f6f4f2;\n --debug-muted: #c9c5c1;\n --debug-border: #514c47;\n --debug-success: #a9e3bd;\n --debug-success-bg: #214d34;\n --debug-failed: #ffb4ab;\n --debug-failed-bg: #582c2a;\n --debug-pending: #ffe099;\n --debug-pending-bg: #59441e;\n --debug-info: #a8d9ff;\n --debug-info-bg: #233f52;\n --debug-key: #8ed6f0;\n --debug-string: #a9e3bd;\n --debug-number: #ffe099;\n --debug-literal: #d6b7f1;\n color: #f6f4f2;\n color-scheme: dark;\n}\n.opportunities-extension-debug-actions { display: flex; gap: 8px; flex: 0 0 auto; }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-list {\n overflow: auto;\n min-height: 0;\n min-width: 0;\n align-content: start;\n scrollbar-gutter: stable;\n padding: 2px 8px 12px 2px;\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item {\n --debug-state: var(--debug-info);\n --debug-state-bg: var(--debug-info-bg);\n border-color: var(--debug-border);\n border-left-color: var(--debug-state);\n background: var(--debug-surface);\n min-width: 0;\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-success { --debug-state: var(--debug-success); --debug-state-bg: var(--debug-success-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-failed { --debug-state: var(--debug-failed); --debug-state-bg: var(--debug-failed-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-pending { --debug-state: var(--debug-pending); --debug-state-bg: var(--debug-pending-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-status {\n color: var(--debug-state);\n background: var(--debug-state-bg);\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status,\n.opportunities-extension-debug-method {\n color: var(--debug-info);\n background: var(--debug-info-bg);\n}\n.opportunities-extension-debug-method {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 0 8px;\n border-radius: 4px;\n font: 700 11px/1.2 Consolas, monospace;\n}\n.opportunities-extension-debug-method[data-method=\"POST\"] { color: var(--debug-literal); background: var(--debug-code); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"2\"] { color: var(--debug-success); background: var(--debug-success-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"4\"],\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"5\"] { color: var(--debug-failed); background: var(--debug-failed-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"pending\"] { color: var(--debug-pending); background: var(--debug-pending-bg); }\n.opportunities-extension-debug-details { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; padding: 0 14px 16px; }\n.opportunities-extension-debug-block { min-width: 0; border-left: 2px solid var(--debug-info); padding-left: 10px; }\n.opportunities-extension-debug-block[data-direction=\"response\"] { border-left-color: var(--debug-success); }\n.opportunities-extension-modal .opportunities-extension-debug-block h3 { margin: 0 0 8px; color: var(--debug-info); font-size: 12px; }\n.opportunities-extension-modal .opportunities-extension-debug-block[data-direction=\"response\"] h3 { color: var(--debug-success); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item pre {\n min-width: 0;\n margin: 0;\n padding: 12px;\n max-height: 380px;\n overflow: auto;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: var(--debug-text);\n background: var(--debug-code);\n line-height: 1.6;\n tab-size: 2;\n}\n.opportunities-extension-debug-json-key { color: var(--debug-key); }\n.opportunities-extension-debug-json-string { color: var(--debug-string); }\n.opportunities-extension-debug-json-number { color: var(--debug-number); }\n.opportunities-extension-debug-json-literal { color: var(--debug-literal); }\n@media (max-width: 760px) {\n .opportunities-extension-modal .opportunities-extension-debug-panel { padding: 12px; }\n .opportunities-extension-debug-details { grid-template-columns: minmax(0, 1fr); }\n}\n.opportunities-extension-debug-tabs {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #dedbd7;\n}\n\n.opportunities-extension-debug-tabs button {\n max-width: 100%;\n min-height: 32px;\n padding: 6px 8px;\n border: 0;\n border-bottom: 2px solid transparent;\n border-radius: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-size: 12px;\n line-height: 1.35;\n overflow-wrap: anywhere;\n cursor: pointer;\n}\n\n.opportunities-extension-debug-tabs button:hover {\n background: #f5f4f2;\n}\n\n.opportunities-extension-debug-tabs button[aria-selected=\"true\"] {\n border-bottom-color: #00758f;\n background: #e8f4f6;\n color: #006b84;\n font-weight: 700;\n}\n\n.opportunities-extension-debug-tabs button:focus-visible,\n.opportunities-extension-debug-list[role=\"tabpanel\"]:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n}\n\n.opportunities-extension-debug-time {\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.opportunities-extension-debug-heading {\n flex-wrap: wrap;\n}\n\n.opportunities-extension-debug-heading strong {\n flex: 1 1 180px;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-debug-summary-meta {\n flex-wrap: wrap;\n justify-content: flex-end;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button {\n color: #f6f4f2;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-heading::before {\n color: #c9c5c1;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs {\n border-bottom-color: #514c47;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button:hover {\n background: #383633;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button[aria-selected=\"true\"] {\n background: #173f48;\n border-bottom-color: #8cc8d3;\n color: #bde7ee;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button:focus-visible,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-list[role=\"tabpanel\"]:focus-visible {\n outline-color: #8cc8d3;\n}\n.opportunities-extension-debug-duration {\n color: #55514d;\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-duration { color: #d6d2ce; }\n\n/* Compact filters use available CSS width, including Windows display scaling. */\n.opportunities-extension-products-progress,\n.opportunities-extension-auth-badge { opacity: 1; transition: opacity 300ms ease; }\n.opportunities-extension-products-progress[data-fading=\"true\"],\n.opportunities-extension-auth-badge[data-fading=\"true\"] { opacity: 0; }\n.opportunities-extension-auth-badge[hidden] { display: none; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-products-progress,\n .opportunities-extension-auth-badge { transition: none; }\n}\n.opportunities-extension-crm-sr-badge {\n flex: 0 0 auto;\n padding: 0 6px;\n border: 1px solid #408254;\n border-radius: 8px;\n font-size: 10px;\n line-height: 18px;\n font-weight: 600;\n white-space: nowrap;\n color: #185b30;\n background: #e1f1e5;\n}\n.opportunities-extension-crm-sr-badge[data-state=\"missing\"] { color: #9f201b; background: #fde8e7; border-color: #c74640; }\n.opportunities-extension-crm-sr-badge[data-state=\"error\"] { color: #785000; background: #fff0cd; border-color: #987021; }\n.opportunities-extension-wl-actions-badge[data-state=\"loading\"] { color: #5f5a55; background: #eceae8; border-color: #8f8a85; }\n.opportunities-extension-crm-sr-badge:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge { color: #b8e4c6; background: #214d34; border-color: #6eac82; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge[data-state=\"missing\"] { color: #ffd9d5; background: #542824; border-color: #ef938b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge[data-state=\"error\"] { color: #ffe0a3; background: #584219; border-color: #c99b4b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-wl-actions-badge[data-state=\"loading\"] { color: #dedbd7; background: #484541; border-color: #8f8a85; }\n\n.opportunities-extension-form {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr)) max-content max-content;\n align-items: end;\n gap: 12px;\n min-height: 0;\n padding: 12px;\n}\n\n.opportunities-extension-form > *,\n.opportunities-extension-badge-filters > section {\n min-width: 0;\n width: 100%;\n max-width: none;\n grid-template-rows: auto 32px;\n gap: 4px;\n font-size: 12px;\n}\n\n.opportunities-extension-form > * > span:first-child,\n.opportunities-extension-badge-filters > section > span:first-child {\n font-size: 12px;\n line-height: 16px;\n}\n\n.opportunities-extension-form .opportunities-extension-select-wrap {\n width: 100%;\n}\n\n.opportunities-extension-form .opportunities-extension-field select,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger,\n.opportunities-extension-form .opportunities-extension-table-search-field input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 32px;\n min-height: 32px;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 20px;\n}\n\n.opportunities-extension-form .opportunities-extension-field select,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger {\n padding-right: 26px;\n}\n\n.opportunities-extension-form .opportunities-extension-select-wrap::after,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger::after {\n right: 10px;\n border-left-width: 4px;\n border-right-width: 4px;\n border-top-width: 5px;\n}\n\n.opportunities-extension-form .opportunities-extension-stage-filter-controls,\n.opportunities-extension-form .opportunities-extension-status-filter-controls {\n flex-wrap: nowrap;\n gap: 4px;\n}\n\n.opportunities-extension-form .opportunities-extension-stage-filter-button,\n.opportunities-extension-form .opportunities-extension-status-filter-button {\n min-height: 28px;\n padding: 4px 7px;\n font-size: 11px;\n line-height: 18px;\n white-space: nowrap;\n}\n\n@media (max-width: 1150px) {\n .opportunities-extension-form {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter {\n grid-column: span 2;\n }\n}\n\n@media (max-width: 700px) {\n .opportunities-extension-form {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .opportunities-extension-form .opportunities-extension-stage-filter-controls,\n .opportunities-extension-form .opportunities-extension-status-filter-controls {\n flex-wrap: wrap;\n }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter {\n grid-template-rows: auto auto;\n }\n}\n\n@media (max-width: 420px) {\n .opportunities-extension-form { grid-template-columns: minmax(0, 1fr); }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter { grid-column: auto; }\n}\n\n.opportunities-extension-badge-filters { display: contents; }\n.opportunities-extension-activity-filter { display: grid; }\n.opportunities-extension-activity-filter[hidden] { display: none; }\n.opportunities-extension-activity-filter-controls { display: flex; align-items: center; flex-wrap: nowrap; gap: 4px; }\n/* Flexible fields share the space left by the four compact badge groups. */\n.opportunities-extension-form[data-activity-filters=\"true\"] {\n grid-template-columns: repeat(4, minmax(0, 1fr)) repeat(4, max-content);\n column-gap: 8px;\n}\n.opportunities-extension-activity-filter-button {\n border: 1px solid currentColor;\n border-radius: 18px;\n min-height: 28px;\n padding: 4px 7px;\n font: inherit;\n font-size: 11px;\n font-weight: 600;\n line-height: 18px;\n white-space: nowrap;\n color: #185b30;\n background: transparent;\n cursor: pointer;\n}\n.opportunities-extension-activity-filter-button[data-value=\"missing\"] { color: #9f201b; }\n.opportunities-extension-activity-filter-button[data-value=\"under4\"] { color: #005f7d; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"] { color: #fff; background: #25653a; border-color: #25653a; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"][data-value=\"missing\"] { background: #a12d27; border-color: #a12d27; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"][data-value=\"under4\"] { background: #006b86; border-color: #006b86; }\n.opportunities-extension-activity-filter-button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter { color: #eeeae6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button { color: #b8e4c6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[data-value=\"missing\"] { color: #ffd9d5; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[data-value=\"under4\"] { color: #b5e9fc; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[aria-pressed=\"true\"] { border-color: currentColor; }\n@media (max-width: 1350px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }\n .opportunities-extension-form[data-activity-filters=\"true\"] .opportunities-extension-badge-filters {\n display: flex;\n grid-column: 1 / -1;\n flex-wrap: wrap;\n align-items: start;\n gap: 12px 20px;\n }\n .opportunities-extension-form[data-activity-filters=\"true\"] .opportunities-extension-badge-filters > section {\n width: auto;\n max-width: 100%;\n grid-template-rows: auto auto;\n }\n}\n@media (max-width: 700px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n .opportunities-extension-activity-filter-controls { flex-wrap: wrap; }\n}\n@media (max-width: 420px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: minmax(0, 1fr); }\n}\n\n/* Keep layout rules on the outer table, never on expanded product tables. */\n.opportunities-extension-table[data-opportunities-layout=\"inline-actions\"] {\n width: 100%;\n min-width: 1120px;\n table-layout: fixed;\n}\n\n/* Fixed table layout shares leftover width only between the two auto columns. */\n.opportunities-extension-table > thead > tr > th[data-column=\"name\"] { width: auto; }\n.opportunities-extension-table > thead > tr > th[data-column=\"customer\"] { width: auto; }\n.opportunities-extension-table > thead > tr > th[data-column=\"owner\"] { width: 132px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"optyNumber\"] { width: 106px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"revenue\"] { width: 124px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"closeDate\"] { width: 100px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"status\"] { width: 114px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"winProbability\"] { width: 110px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"stage\"] { width: 94px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"lastUpdateDate\"] { width: 136px; }\n\n.opportunities-extension-table > tbody > tr > td[data-column] {\n padding: 10px 8px;\n overflow: visible;\n text-overflow: clip;\n white-space: normal;\n font-variant-numeric: tabular-nums;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"name\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"customer\"] {\n position: relative;\n padding-right: 16px;\n padding-left: 12px;\n padding-bottom: 38px;\n vertical-align: top;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"owner\"] {\n padding-right: 16px;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"closeDate\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"lastUpdateDate\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"status\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"stage\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"winProbability\"] {\n white-space: nowrap;\n}\n\n.opportunities-extension-cell-content {\n display: block;\n min-width: 0;\n min-height: 2.7em;\n line-height: 1.35;\n}\n\n.opportunities-extension-cell-content > :first-child {\n display: block;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-cell-actions {\n position: absolute;\n left: 12px;\n right: 16px;\n bottom: 10px;\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 6px;\n height: 24px;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-action-button {\n flex: 0 0 24px;\n width: 24px;\n height: 24px;\n padding: 2px;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"customer\"] .opportunities-extension-cell-actions {\n min-width: 84px;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-action-button svg {\n width: 18px;\n height: 18px;\n}\n\n.opportunities-extension-cell-actions button:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n}\n\n.opportunities-extension-products-ramp {\n display: inline-block;\n min-width: 0;\n max-width: 100%;\n padding: 0 6px;\n border: 1px solid #bba5cf;\n border-radius: 8px;\n background: #f0e8f7;\n color: #63358a;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-ramp {\n background: #43334f;\n color: #ead5fc;\n border-color: #9372ac;\n}\n\n.opportunities-extension-products-ramp[data-missing=\"true\"] {\n background: #fde8e7;\n color: #9f201b;\n border-color: #c74640;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-ramp[data-missing=\"true\"] {\n background: #542824;\n color: #ffd9d5;\n border-color: #ef938b;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column] .opportunities-extension-sort-button {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 12px;\n gap: 6px;\n padding: 10px 8px;\n align-items: center;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column=\"name\"] .opportunities-extension-sort-button,\n.opportunities-extension-table > thead > tr > th[data-column=\"customer\"] .opportunities-extension-sort-button {\n padding-left: 12px;\n padding-right: 16px;\n}\n\n.opportunities-extension-sort-label {\n min-width: 0;\n white-space: normal;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column] .opportunities-extension-sort-button::after {\n position: static;\n justify-self: end;\n}\n.opportunities-extension-crm-sr-badge[type=\"button\"] { cursor: pointer; font-family: inherit; }\n.opportunities-extension-sr-popover {\n position: fixed; z-index: 8; box-sizing: border-box; overflow: auto;\n padding: 12px; border: 1px solid #b9b5b0; border-radius: 6px;\n background: #fff; color: #302e2b; box-shadow: 0 6px 24px #0003;\n font: 12px/1.5 Arial, sans-serif; text-align: left; overflow-wrap: anywhere;\n}\n.opportunities-extension-sr-popover section { padding: 8px 0; }\n.opportunities-extension-sr-popover section + section { border-top: 1px solid #dedbd7; }\n.opportunities-extension-sr-number { display: flex; align-items: center; gap: 8px; padding-right: 30px; font-weight: 600; }\n.opportunities-extension-sr-popover a { color: #00677d; text-decoration: underline; }\n.opportunities-extension-sr-details { white-space: pre-wrap; margin-top: 6px; }\n.opportunities-extension-sr-dismiss {\n position: absolute; top: 6px; right: 6px; width: 28px; height: 28px;\n display: grid; place-items: center; padding: 4px; border: 0;\n background: transparent; color: inherit; cursor: pointer;\n}\n.opportunities-extension-sr-dismiss svg { width: 16px; height: 16px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover { background: #292827; color: #f1efec; border-color: #77716b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover section + section { border-color: #5f5953; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover a { color: #7ddced; }\n.opportunities-extension-title-row {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px 16px;\n min-width: 0;\n flex: 1;\n}\n.opportunities-extension-title-row h1 {\n display: block;\n margin: 0;\n padding: 0;\n line-height: 1;\n}\n.opportunities-extension-title-row .opportunities-extension-subtitle-row {\n display: flex;\n align-items: center;\n align-self: center;\n flex-wrap: wrap;\n gap: 8px;\n margin: 0;\n padding: 0;\n min-width: 0;\n}\n.opportunities-extension-title-row .opportunities-extension-subtitle-row > span {\n box-sizing: border-box;\n margin: 0;\n min-height: 22px;\n line-height: 16px;\n}\n.opportunities-extension-title-row + .opportunities-extension-header-actions { flex-shrink: 0; }\n.opportunities-extension-refresh-all:disabled { opacity: .65; cursor: wait; }\n.opportunities-extension-refresh-all:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-refresh-all[aria-busy=\"true\"] svg { animation: opportunities-refresh-spin 1s linear infinite; }\n@keyframes opportunities-refresh-spin { to { transform: rotate(360deg); } }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-refresh-all[aria-busy=\"true\"] svg { animation: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-install-base-dialog {\n width: min(1700px, 100%);\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header {\n padding: 10px 12px;\n gap: 12px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header h2 {\n font-size: 16px;\n line-height: 22px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header p {\n font-size: 12px;\n line-height: 16px;\n margin-top: 3px;\n overflow-wrap: anywhere;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-icon-button {\n width: 28px;\n height: 28px;\n min-width: 28px;\n min-height: 28px;\n padding: 4px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-customer-table-toolbar {\n padding: 8px 12px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-customer-table-search {\n width: min(320px, 100%);\n height: 32px;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 20px;\n}\n.opportunities-extension-install-base-content {\n min-width: 0;\n min-height: 0;\n overflow: auto;\n scrollbar-gutter: stable;\n}\n.opportunities-extension-install-base-message { margin: 10px 12px; font-size: 12px; line-height: 16px; }\n.opportunities-extension-install-base-table {\n width: 100%; min-width: 1120px; table-layout: fixed; border-collapse: collapse; font-size: 11px;\n}\n.opportunities-extension-install-base-table col { width: 7%; }\n.opportunities-extension-install-base-table .install-base-col-partyName { width: 12%; }\n.opportunities-extension-install-base-table .install-base-col-productGroupName { width: 13%; }\n.opportunities-extension-install-base-table .install-base-col-productName { width: 13%; }\n.opportunities-extension-install-base-table .install-base-col-quantity { width: 5%; }\n.opportunities-extension-install-base-table .install-base-col-quantityType { width: 8%; }\n.opportunities-extension-install-base-table th,\n.opportunities-extension-install-base-table td {\n padding: 8px 6px; text-align: left; vertical-align: middle; overflow-wrap: anywhere;\n border-bottom: 1px solid #e8e5e1; line-height: 1.4;\n}\n.opportunities-extension-install-base-table th { position: sticky; top: 0; z-index: 1; background: #faf9f8; }\n.opportunities-extension-install-base-table td[data-format=\"amount\"],\n.opportunities-extension-install-base-table td[data-format=\"quantity\"] { text-align: right; font-variant-numeric: tabular-nums; }\n.opportunities-extension-install-base-table td[data-format=\"date\"] { white-space: nowrap; }\n.opportunities-extension-install-base-status {\n display: inline-block; padding: 2px 5px; border-radius: 12px; font-size: 10px; font-weight: 600;\n color: #5f5a55; background: #eceae8; white-space: nowrap;\n}\n.opportunities-extension-install-base-status[data-status=\"ACTIVE\"] { color: #17693a; background: #e1f1e5; }\n.opportunities-extension-install-base-status[data-status=\"UNSUPPORTED\"] { color: #855300; background: #fff0d6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-content,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table td { color: #f6f4f2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-message { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-message[role=\"alert\"] { color: #ffb4ab; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th { background: #353331; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table td { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status[data-status=\"ACTIVE\"] { color: #b8e4c6; background: #214d34; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status[data-status=\"UNSUPPORTED\"] { color: #ffdfa2; background: #614418; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-install-base-table .opportunities-extension-account-plans-skeleton-bar { animation: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-service-requests-dialog { width: min(1700px, 100%); }\n.opportunities-extension-service-requests-content { min-width: 0; min-height: 0; overflow: auto; scrollbar-gutter: stable; }\n.opportunities-extension-service-requests-message { margin: 16px; font-size: 13px; }\n.opportunities-extension-service-requests-table {\n width: 100%; min-width: 1200px; table-layout: fixed; border-collapse: collapse; font-size: 12px;\n}\n.opportunities-extension-service-requests-table col { width: 7%; }\n.opportunities-extension-service-requests-table .service-requests-col-name { width: 17%; }\n.opportunities-extension-service-requests-table .service-requests-col-id { width: 10%; }\n.opportunities-extension-service-requests-table .service-requests-col-severity { width: 5%; }\n.opportunities-extension-service-requests-table .service-requests-col-subStatus { width: 14%; }\n.opportunities-extension-service-requests-table .service-requests-col-productName { width: 12%; }\n.opportunities-extension-service-requests-table th,\n.opportunities-extension-service-requests-table td {\n padding: 12px 8px; text-align: left; vertical-align: middle; overflow-wrap: anywhere;\n border-bottom: 1px solid #e8e5e1; line-height: 1.4;\n}\n.opportunities-extension-service-requests-table th { position: sticky; top: 0; z-index: 1; background: #faf9f8; }\n.opportunities-extension-service-requests-table td[data-field=\"created\"],\n.opportunities-extension-service-requests-table td[data-field=\"lastUpdated\"],\n.opportunities-extension-service-requests-table td[data-field=\"id\"] { white-space: nowrap; font-variant-numeric: tabular-nums; }\n.opportunities-extension-service-request-status {\n display: inline-block; padding: 3px 6px; border-radius: 12px; font-size: 10px; font-weight: 600;\n color: #5f5a55; background: #eceae8;\n}\n.opportunities-extension-service-request-status[data-status=\"OPEN\"] { color: #17693a; background: #e1f1e5; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-content,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table td { color: #f6f4f2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-message { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-message[role=\"alert\"] { color: #ffb4ab; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th { background: #353331; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table td { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-request-status { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-request-status[data-status=\"OPEN\"] { color: #b8e4c6; background: #214d34; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-service-requests-table .opportunities-extension-account-plans-skeleton-bar { animation: none; }\n}\n\n/* Scope sizing to Cloud Consumption, not other dialogs sharing its components. */\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header { padding: 10px 12px; gap: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header h2 { font-size: 16px; line-height: 22px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header p { font-size: 12px; line-height: 16px; margin-top: 3px; overflow-wrap: anywhere; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-icon-button { width: 28px; height: 28px; min-width: 28px; min-height: 28px; padding: 4px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-tabs { padding: 4px 12px 0; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-tab { min-height: 30px; padding: 4px 8px; font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-panel { padding: 8px 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details { gap: 0 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details > div { grid-template-columns: minmax(85px, 35%) minmax(0, 1fr); min-height: 32px; padding: 4px 0; gap: 6px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details dt { font-size: 11px; line-height: 16px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details dd { font-size: 12px; line-height: 16px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-trend { margin-top: 8px; padding-top: 6px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-periods button { min-height: 28px; padding: 4px 8px; font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation { grid-template-columns: 28px minmax(120px, auto) 28px; min-height: 30px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation strong { font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation-button { width: 28px; height: 28px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-visual { grid-template-columns: minmax(0, 1fr) 150px; gap: 8px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-svg { height: 100%; max-height: 100%; min-width: 0; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-legend button { font-size: 11px; padding: 4px; gap: 5px; }\n\n/* Small viewports must scroll rather than clip details or collapse the chart. */\n@media (max-height: 560px), (max-width: 700px) {\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-panels { overflow: auto; }\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-panel { height: auto; min-height: 100%; grid-template-rows: auto minmax(280px, 1fr); }\n}\n@media (max-width: 700px) {\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details { grid-template-columns: minmax(0, 1fr); }\n [data-consumption-layout=\"compact\"] .opportunities-extension-consumption-visual { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }\n [data-consumption-layout=\"compact\"] .opportunities-extension-consumption-legend { display: flex; flex-wrap: wrap; }\n}\n\n.opportunities-extension-plan-detail-badges { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }\n.opportunities-extension-consumption-trend-header { align-items: center; justify-content: space-between; gap: 12px; }\n.opportunities-extension-consumption-trend-header > .opportunities-extension-plan-detail-badges { min-width: 0; }\n.opportunities-extension-plan-detail-skeleton { width: 64px; height: 20px; }\n.opportunities-extension-projection-badge {\n display: inline-flex; align-items: center; justify-content: center; border: 1px solid transparent;\n padding: 3px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; line-height: 1.3;\n color: #5f5a55; background: #eceae8; white-space: nowrap;\n}\nbutton.opportunities-extension-projection-badge { cursor: pointer; }\n.opportunities-extension-projection-badge[data-status=\"forfeit\"] { color: #a12424; background: #fbe5e5; }\n.opportunities-extension-projection-badge[data-status=\"overage\"] { color: #185a9d; background: #e0edfc; }\n.opportunities-extension-projection-badge:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-projection-popover {\n position: fixed; z-index: 8; box-sizing: border-box; padding: 14px; overflow: auto; overscroll-behavior: contain;\n border: 1px solid #b9b4ae; border-radius: 4px; background: #ffffff; color: #312d2a;\n box-shadow: 0 4px 16px #0003; font-size: 12px; line-height: 1.4; overflow-wrap: anywhere;\n}\n.opportunities-extension-projection-popover[hidden] { display: none; }\n.opportunities-extension-projection-popover .opportunities-extension-projection-dismiss {\n display: grid; place-items: center; width: 24px; height: 24px; margin-left: auto; margin-bottom: 8px; padding: 4px; border: 1px solid #b9b4ae;\n border-radius: 4px; background: transparent; color: inherit; cursor: pointer; font-size: 12px;\n}\n.opportunities-extension-projection-dismiss svg { width: 14px; height: 14px; }\n.opportunities-extension-projection-line h3 { margin: 0 0 8px; font-size: 12px; }\n.opportunities-extension-projection-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 16px; margin: 0; }\n.opportunities-extension-projection-fields > div { min-width: 0; }\n.opportunities-extension-projection-fields dt { font-weight: 600; color: #5f5a55; font-size: 11px; }\n.opportunities-extension-projection-fields dd { margin: 2px 0 0; font-variant-numeric: tabular-nums; }\n.opportunities-extension-projection-fields a { color: #006d7a; text-decoration: underline; }\n.opportunities-extension-projection-children { margin-top: 14px; padding-left: 12px; border-left: 2px solid #dedbd7; }\n.opportunities-extension-projection-children > section + section { margin-top: 16px; }\n.opportunities-extension-plan-detail-error { color: #a12424; font-size: 12px; }\n.opportunities-extension-projection-empty { color: #5f5a55; font-size: 12px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-popover { color: #f1efec; background: #302e2b; border-color: #716b64; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge[data-status=\"forfeit\"] { color: #ffb9b9; background: #682e32; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge[data-status=\"overage\"] { color: #c5dfff; background: #224b76; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-fields dt,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-empty { color: #cec9c2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-fields a { color: #76dbea; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-plan-detail-error { color: #ffb9b9; }\n@media (max-width: 480px) { .opportunities-extension-projection-fields { grid-template-columns: minmax(0, 1fr); } }\n@media (max-width: 480px) {\n .opportunities-extension-consumption-trend-header > .opportunities-extension-consumption-periods { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n@media (prefers-reduced-motion: reduce) { .opportunities-extension-plan-detail-skeleton { animation: none; } }\n\n.opportunities-extension-account-plan-details > .opportunities-extension-contract-row {\n align-items: center;\n}\n.opportunities-extension-contract-row > dt,\n.opportunities-extension-contract-row > dd,\n.opportunities-extension-contract-ratecard > span {\n line-height: 20px;\n}\n.opportunities-extension-contract-ratecard {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px 10px;\n}\n.opportunities-extension-ratecard-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n align-self: center;\n box-sizing: border-box;\n height: 28px;\n margin: 0;\n flex: 0 0 auto;\n padding: 0 8px;\n border: 1px solid #8aaeb9;\n border-radius: 4px;\n background: #fff;\n color: #006b80;\n font: inherit;\n font-size: 12px;\n font-weight: 600;\n line-height: 20px;\n cursor: pointer;\n}\n.opportunities-extension-ratecard-button:hover { background: #e8f4f6; }\n.opportunities-extension-ratecard-overlay {\n position: absolute;\n inset: 0;\n z-index: 8;\n display: flex;\n justify-content: flex-end;\n overflow: hidden;\n overflow: clip;\n background: rgba(0, 0, 0, 0);\n transition: background-color 320ms ease;\n}\n.opportunities-extension-ratecard-overlay[data-open=\"true\"] { background: rgba(0, 0, 0, .32); }\n.opportunities-extension-ratecard-drawer {\n --ratecard-bg: #fff;\n --ratecard-heading: #faf9f8;\n --ratecard-text: #312d2a;\n --ratecard-muted: #615a55;\n --ratecard-border: #dedbd8;\n --ratecard-accent: #00758f;\n --ratecard-skeleton: #eae7e4;\n display: grid;\n grid-template-rows: auto auto auto minmax(0, 1fr);\n width: min(1520px, calc(100% - 48px));\n height: 100%;\n min-width: 0;\n box-sizing: border-box;\n overflow: hidden;\n background: var(--ratecard-bg);\n color: var(--ratecard-text);\n box-shadow: -6px 0 24px rgba(0, 0, 0, .2);\n transform: translateX(100%);\n transition: transform 320ms cubic-bezier(.22, .61, .36, 1);\n}\n.opportunities-extension-ratecard-overlay[data-open=\"true\"] .opportunities-extension-ratecard-drawer { transform: translateX(0); }\n.opportunities-extension-ratecard-header > div { min-width: 0; overflow-wrap: anywhere; }\n.opportunities-extension-ratecard-plan-details { padding: 12px 20px 0; }\n.opportunities-extension-ratecard-toolbar { display: flex; align-items: center; gap: 16px; padding: 12px 20px; }\n.opportunities-extension-ratecard-search {\n width: min(360px, 100%);\n min-width: 0;\n box-sizing: border-box;\n padding: 9px 12px;\n border: 1px solid var(--ratecard-muted);\n border-radius: 4px;\n background: var(--ratecard-bg);\n color: var(--ratecard-text);\n font: inherit;\n font-size: 13px;\n}\n.opportunities-extension-ratecard-search::placeholder { color: var(--ratecard-muted); opacity: 1; }\n.opportunities-extension-ratecard-count { color: var(--ratecard-muted); font-size: 12px; white-space: nowrap; }\n.opportunities-extension-ratecard-viewport { overflow: auto; min-height: 0; min-width: 0; scrollbar-gutter: stable; }\n.opportunities-extension-ratecard-table { width: 100%; min-width: 1100px; table-layout: fixed; border-collapse: separate; border-spacing: 0; font-size: 12px; }\n.opportunities-extension-ratecard-table th, .opportunities-extension-ratecard-table td {\n padding: 11px 10px;\n border-bottom: 1px solid var(--ratecard-border);\n vertical-align: top;\n overflow-wrap: anywhere;\n text-align: left;\n}\n.opportunities-extension-ratecard-table th { position: sticky; top: 0; z-index: 1; background: var(--ratecard-heading); }\n.opportunities-extension-ratecard-sort {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 12px;\n align-items: center;\n gap: 5px;\n width: 100%;\n padding: 0;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: 600;\n text-align: left;\n cursor: pointer;\n}\n.opportunities-extension-ratecard-sort-icon { color: var(--ratecard-accent); text-align: center; }\n.opportunities-extension-ratecard-table .opportunities-extension-ratecard-numeric { text-align: right; font-variant-numeric: tabular-nums; }\n.opportunities-extension-ratecard-table .opportunities-extension-ratecard-notice { padding: 28px 20px; text-align: center; }\n.opportunities-extension-ratecard-notice [role=\"alert\"] { color: #b3261e; }\n.opportunities-extension-ratecard-skeleton { display: block; width: 85%; height: 14px; border-radius: 3px; background: var(--ratecard-skeleton); animation: opportunities-ratecard-pulse 1.1s ease-in-out infinite alternate; }\n.opportunities-extension-ratecard-drawer :focus-visible, .opportunities-extension-ratecard-button:focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-ratecard-overlay[data-closing=\"true\"] { pointer-events: none; background: rgba(0, 0, 0, 0); transition-duration: 180ms; }\n.opportunities-extension-ratecard-overlay[data-closing=\"true\"] .opportunities-extension-ratecard-drawer { transform: translateX(100%); transition-duration: 180ms; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-drawer {\n --ratecard-bg: #292725;\n --ratecard-heading: #35322f;\n --ratecard-text: #f5f3f1;\n --ratecard-muted: #c2bcb6;\n --ratecard-border: #514c47;\n --ratecard-accent: #59d1e5;\n --ratecard-skeleton: #514c47;\n}\n[data-theme=\"dark\"] .opportunities-extension-ratecard-button { color: #59d1e5; border-color: #6298a2; background: #292725; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-button:hover { background: #313f40; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-notice [role=\"alert\"] { color: #ffb4ab; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-drawer :focus-visible, [data-theme=\"dark\"] .opportunities-extension-ratecard-button:focus-visible { outline-color: #59d1e5; }\n@keyframes opportunities-ratecard-pulse { from { opacity: .45; } to { opacity: 1; } }\n@media (max-width: 720px) {\n .opportunities-extension-ratecard-drawer { width: 100%; }\n .opportunities-extension-ratecard-toolbar { flex-wrap: wrap; gap: 8px; }\n}\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-ratecard-overlay, .opportunities-extension-ratecard-drawer, .opportunities-extension-ratecard-skeleton,\n .opportunities-extension-ratecard-overlay[data-closing=\"true\"], .opportunities-extension-ratecard-overlay[data-closing=\"true\"] .opportunities-extension-ratecard-drawer { animation: none; transition: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-install-base-dialog,\n.opportunities-extension-account-plans-dialog.opportunities-extension-service-requests-dialog {\n grid-template-rows: auto auto minmax(0, 1fr);\n}\n.opportunities-extension-customer-table-toolbar { padding: 12px 16px; border-bottom: 1px solid #dedbd7; }\n.opportunities-extension-customer-table-search {\n box-sizing: border-box;\n width: min(420px, 100%);\n min-width: 0;\n height: 38px;\n padding: 8px 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #fff;\n color: #312d2a;\n font: inherit;\n font-size: 13px;\n}\n.opportunities-extension-customer-table-search::placeholder { color: #5f5a55; opacity: 1; }\n.opportunities-extension-customer-table-search:focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-toolbar { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search { background: #353331; color: #f6f4f2; border-color: #8f8a85; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search::placeholder { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search:focus-visible { outline-color: #59d1e5; }\n"; +const redwoodStyles = "\n .opportunities-extension-scroll-lock {\n overflow: hidden !important;\n }\n\n .opportunities-extension-modal,\n .opportunities-extension-modal * {\n box-sizing: border-box;\n font-family: \"Oracle Sans\", Arial, Helvetica, sans-serif;\n }\n\n .opportunities-extension-modal {\n position: fixed;\n inset: 0;\n z-index: 2147483647;\n background: #f5f4f2;\n color: #000000;\n }\n\n .opportunities-extension-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-shell {\n height: 100vh;\n min-height: 0;\n display: grid;\n grid-template-rows: auto minmax(0, 1fr);\n background: #f5f4f2;\n }\n\n .opportunities-extension-header {\n position: relative;\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 24px;\n padding: 28px 40px 22px;\n border-bottom: 1px solid #dedbd7;\n background:\n linear-gradient(90deg, #8f624a 0 11%, #c74634 11% 23%, #6f5a7f 23% 36%, #00758f 36% 51%, #d4b06a 51% 63%, transparent 63% 100%) top left / 100% 6px no-repeat,\n #ffffff;\n }\n\n .opportunities-extension-header::before {\n position: absolute;\n left: 40px;\n bottom: -1px;\n width: 64px;\n height: 3px;\n background: #00758f;\n content: \"\";\n }\n\n .opportunities-extension-header h1 {\n margin: 0;\n color: #000000;\n font-size: 24px;\n font-weight: 700;\n line-height: 1.2;\n letter-spacing: 0;\n }\n\n .opportunities-extension-header p {\n margin: 0;\n color: #5f5a55;\n font-size: 14px;\n line-height: 1.4;\n }\n\n .opportunities-extension-subtitle-row {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n margin-top: 6px;\n }\n\n .opportunities-extension-auth-badge {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n color: #ffffff;\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-auth-badge-authenticated {\n background: #3f6f17;\n }\n\n .opportunities-extension-auth-badge-unauthenticated {\n background: #c5331f;\n }\n\n .opportunities-extension-auth-badge-pending {\n background: #6f5a7f;\n }\n\n .opportunities-extension-products-progress {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n background: #e8f4f6;\n color: #006d7a;\n font-size: 12px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-products-progress[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-products-cache-timestamp {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 2px 8px;\n border-radius: 999px;\n background: #f0eeeb;\n color: #5f5a55;\n font-size: 11px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .opportunities-extension-products-cache-timestamp[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-products-progress[data-state=\"running\"]::before {\n width: 12px;\n height: 12px;\n margin-right: 6px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n content: \"\";\n animation: opportunities-extension-spin .8s linear infinite;\n }\n\n .opportunities-extension-products-progress[data-state=\"complete\"] {\n background: #e2f2e5;\n color: #356d19;\n }\n\n .opportunities-extension-products-progress[data-state=\"complete-with-errors\"],\n .opportunities-extension-products-progress[data-state=\"error\"] {\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n @keyframes opportunities-extension-spin {\n to { transform: rotate(360deg); }\n }\n\n .opportunities-extension-icon-button {\n width: 36px;\n height: 36px;\n flex: 0 0 36px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 18px;\n font-weight: 600;\n line-height: 1;\n cursor: pointer;\n }\n\n .opportunities-extension-header-actions {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n }\n\n .opportunities-extension-icon-button svg {\n width: 18px;\n height: 18px;\n vertical-align: middle;\n }\n\n .opportunities-extension-icon-button .opportunities-extension-settings-icon {\n width: 20px;\n height: 20px;\n }\n\n .opportunities-extension-icon-button:hover,\n .opportunities-extension-icon-button:focus {\n border-color: #b8b2ad;\n background: #f5f4f2;\n outline: none;\n }\n\n .opportunities-extension-body {\n display: grid;\n min-height: 0;\n grid-template-rows: auto auto minmax(0, 1fr);\n gap: 16px;\n padding: 22px 40px 36px;\n background: #f5f4f2;\n overflow: hidden;\n }\n\n .opportunities-extension-form {\n display: flex;\n align-items: end;\n flex-wrap: wrap;\n gap: 24px;\n min-height: 82px;\n max-width: none;\n margin: 0;\n padding: 14px 16px;\n border: 1px solid #dedbd7;\n border-radius: 4px;\n background: #ffffff;\n }\n\n .opportunities-extension-field {\n display: grid;\n max-width: max-content;\n min-width: 270px;\n width: max-content;\n gap: 6px;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-stage-dashboard {\n display: grid;\n grid-template-columns: repeat(6, minmax(0, 1fr));\n gap: 12px;\n }\n\n .opportunities-extension-stage-dashboard-card {\n display: grid;\n gap: 6px;\n min-width: 0;\n padding: 12px 16px;\n border: 1px solid #dedbd7;\n border-top: 3px solid #5f5a55;\n border-radius: 4px;\n background: #ffffff;\n }\n\n .opportunities-extension-stage-dashboard-card span {\n color: #5f5a55;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-stage-dashboard-value {\n overflow: hidden;\n color: #312d2a;\n font-size: 22px;\n font-weight: 700;\n line-height: 1.2;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"SQL\"] {\n border-top-color: #008aa6;\n }\n\n .opportunities-extension-total-dashboard-card {\n border-top-color: #312d2a;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"PIPELINE\"] {\n border-top-color: #6f6863;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"UPSIDE\"] {\n border-top-color: #c87b00;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"FORECAST\"] {\n border-top-color: #755b8b;\n }\n\n .opportunities-extension-stage-dashboard-card[data-stage=\"WON\"] {\n border-top-color: #4b7f22;\n }\n\n .opportunities-extension-stage-filter {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 0;\n }\n\n .opportunities-extension-stage-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-stage-filter-controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n }\n\n .opportunities-extension-stage-filter-button {\n min-height: 36px;\n padding: 6px 12px;\n border: 1px solid currentColor;\n border-radius: 18px;\n background: #ffffff;\n color: #5f5a55;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"SQL\"] {\n color: #006b84;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"PIPELINE\"] {\n color: #5f5a55;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"UPSIDE\"] {\n color: #945400;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"FORECAST\"] {\n color: #624e74;\n }\n\n .opportunities-extension-stage-filter-button[data-stage=\"WON\"] {\n color: #3f6f17;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"SQL\"] {\n border-color: #006b84;\n background: #006b84;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"PIPELINE\"] {\n border-color: #5f5a55;\n background: #5f5a55;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"UPSIDE\"] {\n border-color: #945400;\n background: #945400;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"FORECAST\"] {\n border-color: #624e74;\n background: #624e74;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"WON\"] {\n border-color: #3f6f17;\n background: #3f6f17;\n color: #ffffff;\n }\n\n .opportunities-extension-stage-filter-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-status-filter {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 0;\n }\n\n .opportunities-extension-status-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-status-filter-controls {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n }\n\n .opportunities-extension-status-filter-button {\n min-height: 36px;\n padding: 6px 12px;\n border: 1px solid currentColor;\n border-radius: 18px;\n background: #ffffff;\n font-size: 12px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"OPEN\"] {\n color: #197a3d;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"CLOSED\"] {\n color: #4b5563;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"LOST\"] {\n color: #b13b34;\n }\n\n .opportunities-extension-status-filter-button[data-status=\"WON\"] {\n color: #1f5f99;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"OPEN\"] {\n border-color: #197a3d;\n background: #197a3d;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"CLOSED\"] {\n border-color: #4b5563;\n background: #4b5563;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"LOST\"] {\n border-color: #b13b34;\n background: #b13b34;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"WON\"] {\n border-color: #1f5f99;\n background: #1f5f99;\n color: #ffffff;\n }\n\n .opportunities-extension-status-filter-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-customer-filter {\n position: relative;\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n min-width: 220px;\n }\n\n .opportunities-extension-customer-filter-label {\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-customer-filter-trigger {\n position: relative;\n min-width: 220px;\n min-height: 44px;\n padding: 10px 38px 10px 12px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.3;\n text-align: left;\n cursor: pointer;\n }\n\n .opportunities-extension-customer-filter-trigger::after {\n position: absolute;\n top: 50%;\n right: 16px;\n width: 0;\n height: 0;\n border-top: 6px solid #312d2a;\n border-right: 5px solid transparent;\n border-left: 5px solid transparent;\n content: \"\";\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n .opportunities-extension-customer-filter-trigger:disabled {\n cursor: not-allowed;\n background: #f5f4f2;\n color: #7d7772;\n }\n\n .opportunities-extension-customer-filter-trigger:focus-visible {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-customer-filter-panel {\n position: absolute;\n top: calc(100% + 8px);\n left: 0;\n z-index: 4;\n display: grid;\n width: min(360px, calc(100vw - 80px));\n gap: 10px;\n padding: 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .18);\n }\n\n .opportunities-extension-customer-filter-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-customer-filter-search {\n width: 100%;\n min-height: 40px;\n padding: 8px 10px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n }\n\n .opportunities-extension-customer-filter-search:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-customer-filter-option {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-customer-filter-select-all {\n min-height: 32px;\n padding-bottom: 8px;\n border-bottom: 1px solid #dedbd7;\n font-weight: 700;\n }\n\n .opportunities-extension-customer-filter-panel input[type=\"checkbox\"] {\n width: 16px;\n height: 16px;\n flex: 0 0 16px;\n accent-color: #00758f;\n }\n\n .opportunities-extension-customer-filter-list {\n display: block;\n max-height: 250px;\n overflow: auto;\n }\n\n .opportunities-extension-customer-filter-option {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: start;\n min-height: 0;\n height: auto !important;\n padding: 8px 4px;\n cursor: pointer;\n }\n\n .opportunities-extension-customer-filter-option input[type=\"checkbox\"] {\n margin-top: 1px;\n }\n\n .opportunities-extension-customer-filter-option span {\n display: block;\n min-width: 0;\n line-height: 18px;\n overflow-wrap: anywhere;\n white-space: normal;\n }\n\n .opportunities-extension-customer-filter-option:hover {\n background: #f5f4f2;\n }\n\n .opportunities-extension-customer-filter-empty {\n margin: 4px 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-table-search-field {\n display: grid;\n grid-template-rows: auto 44px;\n gap: 6px;\n width: 260px;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.3;\n }\n\n .opportunities-extension-table-search-field input {\n width: 100%;\n min-height: 44px;\n padding: 10px 12px;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.3;\n }\n\n .opportunities-extension-table-search-field input:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-select-wrap {\n position: relative;\n display: block;\n width: 270px;\n max-width: 100%;\n }\n\n .opportunities-extension-select-wrap::after {\n position: absolute;\n top: 50%;\n right: 16px;\n width: 0;\n height: 0;\n border-left: 5px solid transparent;\n border-right: 5px solid transparent;\n border-top: 6px solid #000000;\n content: \"\";\n pointer-events: none;\n transform: translateY(-50%);\n }\n\n .opportunities-extension-field select {\n width: 100%;\n min-width: 0;\n max-width: 100%;\n min-height: 44px;\n box-sizing: border-box;\n appearance: none;\n border: 1px solid #b8b2ad;\n border-radius: 3px;\n background: #ffffff;\n color: #000000;\n font-size: 14px;\n line-height: 1.3;\n padding: 11px 44px 11px 12px;\n }\n\n .opportunities-extension-field select:focus {\n border-color: #312d2a;\n box-shadow: 0 0 0 1px #312d2a;\n outline: none;\n }\n\n .opportunities-extension-table-surface {\n min-height: 0;\n height: 100%;\n border: 1px solid #dedbd7;\n border-radius: 4px;\n background: #ffffff;\n overflow-x: auto;\n overflow-y: auto;\n }\n\n .opportunities-extension-table {\n width: 100%;\n min-width: 0;\n border-collapse: collapse;\n table-layout: fixed;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-table thead {\n background: #faf9f8;\n }\n\n .opportunities-extension-table th {\n position: sticky;\n top: 0;\n z-index: 1;\n height: 44px;\n border-bottom: 1px solid #b8b2ad;\n background: #faf9f8;\n color: #312d2a;\n font-size: 12px;\n font-weight: 700;\n text-align: left;\n white-space: nowrap;\n }\n\n .opportunities-extension-table td {\n min-height: 48px;\n padding: 12px 16px;\n border-bottom: 1px solid #ebe8e5;\n vertical-align: middle;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-table th:nth-child(1) {\n width: 16%;\n }\n\n .opportunities-extension-table th:nth-child(2) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 18%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 11%;\n }\n\n .opportunities-extension-table th:nth-child(5) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(8) {\n width: 6%;\n }\n\n .opportunities-extension-table th:nth-child(9) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(11) {\n width: 4%;\n }\n\n .opportunities-extension-table td:nth-child(2),\n .opportunities-extension-table td:nth-child(5),\n .opportunities-extension-table td:nth-child(6),\n .opportunities-extension-table td:nth-child(8) {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .opportunities-extension-table td:nth-child(9) {\n padding-right: 6px;\n padding-left: 6px;\n white-space: nowrap;\n overflow: visible;\n }\n\n .opportunities-extension-table td:nth-child(7) {\n padding-right: 6px;\n padding-left: 6px;\n white-space: nowrap;\n overflow: visible;\n }\n\n .opportunities-extension-table td:nth-child(10) {\n padding-right: 6px;\n padding-left: 6px;\n font-size: 12px;\n white-space: nowrap;\n }\n\n .opportunities-extension-table td:nth-child(11) {\n padding-right: 6px;\n padding-left: 6px;\n text-align: center;\n white-space: nowrap;\n }\n\n .opportunities-extension-table tbody tr:hover {\n background: #f7f6f4;\n }\n\n .opportunities-extension-table tbody tr:last-child td {\n border-bottom: 0;\n }\n\n .opportunities-extension-table a {\n color: #006b84;\n text-decoration: underline;\n text-decoration-thickness: 1px;\n text-underline-offset: 2px;\n }\n\n .opportunities-extension-table a:hover {\n color: #004f63;\n }\n\n .opportunities-extension-opty-number-content {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n max-width: 100%;\n }\n\n .opportunities-extension-name-content {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n }\n\n .opportunities-extension-name-content > a {\n min-width: 0;\n }\n\n .opportunities-extension-actions-content {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n white-space: nowrap;\n }\n\n .opportunities-extension-products-count {\n display: inline-grid;\n width: auto;\n min-width: 20px;\n height: 20px;\n place-items: center;\n flex: 0 0 auto;\n box-sizing: border-box;\n padding: 0 3px;\n border: 1px solid #7ca7b2;\n border-radius: 999px;\n background: #e8f4f6;\n color: #006d7a;\n font-size: 10px;\n font-weight: 700;\n line-height: 1;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n }\n\n .opportunities-extension-products-count:hover,\n .opportunities-extension-products-count:focus-visible,\n .opportunities-extension-products-count[aria-expanded=\"true\"] {\n border-color: #00758f;\n background: #00758f;\n color: #ffffff;\n outline: none;\n }\n\n .opportunities-extension-products-count-error {\n border-color: #d8887e;\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n .opportunities-extension-products-detail-row:hover {\n background: transparent !important;\n }\n\n .opportunities-extension-products-detail-cell {\n padding: 0 !important;\n }\n\n .opportunities-extension-products-detail {\n padding: 14px 20px 18px;\n border-bottom: 1px solid #c9c5c1;\n background: #f0eeeb;\n }\n\n .opportunities-extension-products-detail-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 10px;\n color: #312d2a;\n }\n\n .opportunities-extension-ai-summary {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n margin: 0 0 12px;\n padding: 12px 16px;\n border: 1px solid #dedbd7;\n border-radius: 6px;\n background: #ffffff;\n color: #312d2a;\n font-size: 13px;\n line-height: 1.5;\n text-align: left;\n white-space: normal;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-ai-summary strong {\n display: block;\n font-size: 13px;\n font-weight: 600;\n }\n\n .opportunities-extension-ai-summary p {\n margin: 4px 0 0;\n font: inherit;\n white-space: pre-wrap;\n }\n\n .opportunities-extension-ai-summary-error {\n color: #b42318;\n border-color: #d9928b;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-ai-summary {\n background: #292827;\n color: #f6f4f2;\n border-color: #5f5a55;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-ai-summary-error {\n color: #ffb4ab;\n border-color: #a45c55;\n }\n\n .opportunities-extension-products-detail-heading strong {\n font-size: 13px;\n }\n\n .opportunities-extension-products-detail-heading span {\n color: #5f5a55;\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n }\n\n .opportunities-extension-products-table {\n width: 100%;\n table-layout: fixed;\n border-collapse: collapse;\n border: 1px solid #dedbd7;\n background: #ffffff;\n font-size: 12px;\n }\n\n .opportunities-extension-products-table th,\n .opportunities-extension-products-table td {\n position: static;\n height: auto;\n padding: 8px 10px;\n border-bottom: 1px solid #ebe8e5;\n background: transparent;\n overflow-wrap: anywhere;\n vertical-align: middle;\n white-space: normal;\n }\n\n .opportunities-extension-products-table th {\n background: #faf9f8;\n font-size: 11px;\n }\n\n .opportunities-extension-products-table th:nth-child(1) { width: 16%; }\n .opportunities-extension-products-table th:nth-child(2) { width: 16%; }\n .opportunities-extension-products-table th:nth-child(3) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(4) { width: 10%; }\n .opportunities-extension-products-table th:nth-child(5) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(6) { width: 8%; }\n .opportunities-extension-products-table th:nth-child(7) { width: 7%; }\n .opportunities-extension-products-table th:nth-child(8) { width: 10%; }\n .opportunities-extension-products-table th:nth-child(9) { width: 12%; }\n .opportunities-extension-products-table th:nth-child(10) { width: 5%; }\n\n .opportunities-extension-products-empty {\n margin: 0;\n padding: 10px 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-copy-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: 0 0 auto;\n width: 24px;\n height: 24px;\n padding: 3px;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-copy-button svg {\n width: 16px;\n height: 16px;\n fill: currentColor;\n }\n\n .opportunities-extension-copy-button:hover,\n .opportunities-extension-copy-button:focus-visible {\n background: #e8f4f6;\n color: #004f63;\n outline: none;\n }\n\n .opportunities-extension-action-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 5px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-action-button svg {\n width: 21px;\n height: 21px;\n }\n\n .opportunities-extension-action-button:hover,\n .opportunities-extension-action-button:focus-visible {\n border-color: #7ca7b2;\n background: #e8f4f6;\n color: #004f63;\n outline: none;\n }\n\n .opportunities-extension-action-button:disabled {\n cursor: wait;\n opacity: .72;\n }\n\n .opportunities-extension-action-button-loading svg {\n animation: opportunities-extension-pulse 1s ease-in-out infinite;\n }\n\n @keyframes opportunities-extension-pulse {\n 50% { opacity: .35; }\n }\n\n .opportunities-extension-copy-toast {\n position: fixed;\n right: 28px;\n bottom: 28px;\n z-index: 3;\n max-width: min(360px, calc(100vw - 56px));\n padding: 12px 16px;\n border-radius: 4px;\n background: #2f6f18;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .18);\n color: #ffffff;\n font-size: 13px;\n font-weight: 700;\n }\n\n .opportunities-extension-copy-toast-error {\n background: #a52b1c;\n }\n\n .opportunities-extension-copy-toast[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-stage-badge {\n display: inline-flex;\n align-items: center;\n min-height: 24px;\n padding: 3px 8px;\n border-radius: 12px;\n background: #ebe8e5;\n color: #312d2a;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"SQL\"] {\n background: #d9f0f5;\n color: #006b84;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"PIPELINE\"] {\n background: #ebe8e5;\n color: #5f5a55;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"UPSIDE\"] {\n background: #fff0d8;\n color: #945400;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"FORECAST\"] {\n background: #eee8f5;\n color: #624e74;\n }\n\n .opportunities-extension-stage-badge[data-stage=\"WON\"] {\n background: #e5f1d9;\n color: #3f6f17;\n }\n\n .opportunities-extension-status-badge {\n display: inline-flex;\n align-items: center;\n min-height: 24px;\n padding: 3px 8px;\n border-radius: 12px;\n background: #ebe8e5;\n color: #312d2a;\n font-size: 11px;\n font-weight: 700;\n line-height: 1.2;\n white-space: nowrap;\n }\n\n .opportunities-extension-status-badge[data-status=\"OPEN\"] {\n background: #e2f2e5;\n color: #197a3d;\n }\n\n .opportunities-extension-status-badge[data-status=\"CLOSED\"] {\n background: #e5e7eb;\n color: #4b5563;\n }\n\n .opportunities-extension-status-badge[data-status=\"LOST\"] {\n background: #f9e3e1;\n color: #b13b34;\n }\n\n .opportunities-extension-status-badge[data-status=\"WON\"] {\n background: #e3edf8;\n color: #1f5f99;\n }\n\n .opportunities-extension-sort-button {\n position: relative;\n display: inline-flex;\n align-items: center;\n width: 100%;\n min-height: 44px;\n padding: 8px 42px 8px 16px;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: inherit;\n letter-spacing: 0;\n line-height: 1.2;\n text-align: left;\n white-space: normal;\n cursor: pointer;\n }\n\n .opportunities-extension-table-header-label {\n display: inline-flex;\n align-items: center;\n min-height: 44px;\n padding: 8px 6px;\n }\n\n .opportunities-extension-sort-button::after {\n position: absolute;\n right: 15px;\n color: #5f5a55;\n content: \"↕\";\n font-size: 16px;\n font-weight: 400;\n }\n\n .opportunities-extension-sort-button[data-sort-direction=\"ascending\"]::after {\n color: #00758f;\n content: \"↑\";\n }\n\n .opportunities-extension-sort-button[data-sort-direction=\"descending\"]::after {\n color: #00758f;\n content: \"↓\";\n }\n\n .opportunities-extension-sort-button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-sort-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n }\n\n .opportunities-extension-table-status {\n height: 152px;\n color: #5f5a55;\n font-size: 14px;\n text-align: center;\n }\n\n .opportunities-extension-visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n .opportunities-extension-preferences-modal {\n position: absolute;\n inset: 0;\n z-index: 3;\n display: grid;\n place-items: center;\n padding: 24px;\n background: rgba(0, 0, 0, .42);\n }\n\n .opportunities-extension-preferences-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plans-modal {\n position: absolute;\n inset: 0;\n z-index: 4;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(0, 0, 0, .42);\n }\n\n .opportunities-extension-account-plans-modal[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plans-dialog {\n display: grid;\n width: min(1180px, 100%);\n height: min(760px, calc(100vh - 24px));\n min-width: 0;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-columns: minmax(0, 1fr);\n overflow: hidden;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, .24);\n color: #312d2a;\n }\n\n .opportunities-extension-account-plans-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 16px;\n padding: 14px 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-header h2 {\n margin: 0;\n font-size: 20px;\n line-height: 1.2;\n }\n\n .opportunities-extension-account-plans-header p {\n margin: 5px 0 0;\n color: #5f5a55;\n font-size: 13px;\n line-height: 1.35;\n }\n\n .opportunities-extension-account-plans-content {\n display: grid;\n min-width: 0;\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-columns: minmax(0, 1fr);\n min-height: 0;\n overflow: hidden;\n }\n\n .opportunities-extension-account-plans-content > .opportunities-extension-account-plans-skeleton {\n grid-row: 1 / -1;\n }\n\n .opportunities-extension-account-plans-tabs-navigation {\n position: relative;\n min-width: 0;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-tabs-navigation .opportunities-extension-account-plans-tab-navigation-button[hidden] {\n display: none;\n }\n\n .opportunities-extension-account-plans-tabs {\n display: flex;\n min-width: 0;\n gap: 4px;\n overflow-x: auto;\n padding: 8px 20px 0;\n scrollbar-width: none;\n }\n\n .opportunities-extension-account-plans-tabs::-webkit-scrollbar {\n display: none;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button {\n display: grid;\n position: absolute;\n z-index: 1;\n top: 50%;\n width: 32px;\n height: 32px;\n place-items: center;\n padding: 0;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n box-shadow: 0 2px 6px rgba(0, 0, 0, .16);\n transform: translateY(-50%);\n cursor: pointer;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:first-child {\n left: 8px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:last-child {\n right: 8px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:hover:not(:disabled) {\n border-color: #00758f;\n background: #f0eeeb;\n color: #005e73;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:disabled {\n border-color: #dedbd7;\n color: #b8b2ad;\n cursor: default;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-account-plans-tab-navigation-button svg {\n width: 18px;\n height: 18px;\n }\n\n .opportunities-extension-account-plans-panels {\n min-width: 0;\n min-height: 0;\n overflow: hidden;\n }\n\n .opportunities-extension-account-plan-tab {\n min-height: 38px;\n flex: 0 0 auto;\n padding: 7px 12px;\n border: 0;\n border-bottom: 3px solid transparent;\n background: transparent;\n color: #5f5a55;\n font-size: 13px;\n font-weight: 600;\n cursor: pointer;\n }\n\n .opportunities-extension-account-plan-tab:hover {\n background: #f0eeeb;\n color: #312d2a;\n }\n\n .opportunities-extension-account-plan-tab[aria-selected=\"true\"] {\n border-bottom-color: #00758f;\n color: #006d7a;\n }\n\n .opportunities-extension-account-plan-tab:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n }\n\n .opportunities-extension-account-plan-panel {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n box-sizing: border-box;\n padding: 16px 20px;\n }\n\n .opportunities-extension-account-plan-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-account-plan-details {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0 24px;\n margin: 0;\n }\n\n .opportunities-extension-account-plan-details > div {\n display: grid;\n grid-template-columns: minmax(104px, 38%) minmax(0, 1fr);\n gap: 10px;\n min-height: 42px;\n align-items: center;\n padding: 7px 0;\n border-bottom: 1px solid #ebe8e5;\n }\n\n .opportunities-extension-account-plan-details dt {\n color: #5f5a55;\n font-size: 12px;\n font-weight: 700;\n }\n\n .opportunities-extension-account-plan-details dd {\n min-width: 0;\n margin: 0;\n color: #312d2a;\n font-size: 13px;\n overflow-wrap: anywhere;\n }\n\n .opportunities-extension-consumption-trend {\n display: grid;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n margin-top: 14px;\n padding-top: 12px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-consumption-trend-header {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: 24px;\n }\n\n .opportunities-extension-consumption-periods {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .opportunities-extension-consumption-periods button {\n min-height: 38px;\n padding: 7px 14px;\n border: 1px solid transparent;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 13px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-periods button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-consumption-periods button[aria-pressed=\"true\"] {\n border-color: #00758f;\n background: #e7f6f8;\n color: #005e73;\n }\n\n .opportunities-extension-consumption-periods button:focus-visible,\n .opportunities-extension-consumption-navigation-button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 2px;\n }\n\n .opportunities-extension-consumption-chart {\n display: grid;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n margin-top: 4px;\n }\n\n .opportunities-extension-consumption-navigation {\n display: grid;\n grid-template-columns: 36px minmax(130px, auto) 36px;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-height: 40px;\n margin-bottom: 2px;\n }\n\n .opportunities-extension-consumption-navigation strong {\n color: #312d2a;\n font-size: 13px;\n text-align: center;\n }\n\n .opportunities-extension-consumption-navigation-button {\n display: grid;\n width: 36px;\n height: 36px;\n place-items: center;\n padding: 0;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-navigation-button:hover:not(:disabled) {\n border-color: #00758f;\n background: #f0eeeb;\n color: #005e73;\n }\n\n .opportunities-extension-consumption-navigation-button:disabled {\n border-color: #dedbd7;\n color: #b8b2ad;\n cursor: default;\n }\n\n .opportunities-extension-consumption-navigation-button svg {\n width: 18px;\n height: 18px;\n }\n\n .opportunities-extension-consumption-figure {\n position: relative;\n min-width: 0;\n min-height: 0;\n margin: 0;\n scrollbar-width: none;\n }\n\n .opportunities-extension-consumption-figure::-webkit-scrollbar {\n display: none;\n }\n\n .opportunities-extension-consumption-visual {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-columns: minmax(0, 1fr) 176px;\n align-items: center;\n gap: 16px;\n }\n\n .opportunities-extension-consumption-svg {\n display: block;\n width: 100%;\n height: 300px;\n min-height: 0;\n overflow: visible;\n }\n\n .opportunities-extension-consumption-svg .consumption-grid-line {\n stroke: #dedbd7;\n stroke-width: 1;\n shape-rendering: crispEdges;\n }\n\n .opportunities-extension-consumption-svg .consumption-axis-label,\n .opportunities-extension-consumption-svg .consumption-x-label {\n fill: #5f5a55;\n font-family: Arial, sans-serif;\n font-size: 12px;\n }\n\n .opportunities-extension-consumption-svg .consumption-value-label {\n fill: #312d2a;\n font-family: Arial, sans-serif;\n font-size: 12px;\n font-weight: 700;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-funded {\n fill: #b77888;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-overage {\n fill: #de7907;\n }\n\n .opportunities-extension-consumption-svg .consumption-average-line {\n stroke: #de7907;\n stroke-width: 1.5;\n stroke-dasharray: 6 6;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group {\n cursor: default;\n outline: none;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group rect {\n transition: filter .16s ease, opacity .16s ease, stroke .16s ease;\n }\n\n .opportunities-extension-consumption-svg .consumption-bar-group:hover rect,\n .opportunities-extension-consumption-svg .consumption-bar-group:focus rect {\n filter: brightness(1.06);\n stroke: #312d2a;\n stroke-width: 1.5;\n }\n\n .opportunities-extension-consumption-svg .consumption-animated-label {\n opacity: 0;\n animation: opportunities-extension-consumption-label-in .24s ease-out forwards;\n }\n\n .opportunities-extension-consumption-svg .consumption-animated-average {\n opacity: 0;\n animation: opportunities-extension-consumption-average-in .35s .32s ease-out forwards;\n }\n\n @keyframes opportunities-extension-consumption-label-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n\n @keyframes opportunities-extension-consumption-average-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n .opportunities-extension-consumption-legend {\n display: grid;\n align-content: center;\n gap: 4px;\n }\n\n .opportunities-extension-consumption-legend button {\n display: grid;\n min-width: 0;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n gap: 8px;\n padding: 6px 4px;\n border: 0;\n border-radius: 4px;\n background: transparent;\n color: #312d2a;\n font-size: 12px;\n line-height: 1.25;\n text-align: left;\n cursor: pointer;\n }\n\n .opportunities-extension-consumption-legend button:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-consumption-legend button:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: 1px;\n }\n\n .opportunities-extension-consumption-legend button[aria-pressed=\"false\"] {\n color: #77726d;\n opacity: .55;\n }\n\n .opportunities-extension-consumption-legend-swatch {\n display: block;\n width: 12px;\n height: 12px;\n justify-self: center;\n }\n\n .opportunities-extension-consumption-legend-funded {\n background: #b77888;\n }\n\n .opportunities-extension-consumption-legend-overage {\n background: #de7907;\n }\n\n .opportunities-extension-consumption-legend-average {\n height: 0;\n border-top: 2px dashed #de7907;\n }\n\n .opportunities-extension-consumption-tooltip {\n position: absolute;\n z-index: 2;\n display: grid;\n min-width: 190px;\n max-width: 260px;\n gap: 4px;\n padding: 10px 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 4px 12px rgba(0, 0, 0, .2);\n color: #312d2a;\n font-size: 12px;\n line-height: 1.3;\n pointer-events: none;\n }\n\n .opportunities-extension-consumption-tooltip[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-consumption-tooltip strong {\n margin-bottom: 2px;\n font-size: 13px;\n }\n\n .opportunities-extension-consumption-chart-skeleton {\n height: 100%;\n min-height: 0;\n padding: 34px 62px 24px;\n box-sizing: border-box;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot {\n display: flex;\n height: 100%;\n min-height: 220px;\n align-items: flex-end;\n justify-content: space-around;\n gap: 12px;\n padding: 0 14px;\n border-bottom: 1px solid #dedbd7;\n border-left: 1px solid #dedbd7;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot span {\n width: min(38px, 6%);\n border-radius: 2px 2px 0 0;\n background: #dedbd7;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-consumption-chart-empty,\n .opportunities-extension-consumption-chart-error {\n display: grid;\n min-height: 220px;\n place-items: center;\n margin: 0;\n color: #5f5a55;\n font-size: 14px;\n text-align: center;\n }\n\n .opportunities-extension-consumption-chart-error {\n color: #9f2d20;\n }\n\n .opportunities-extension-account-plan-status-indicator {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n background: #9b9691;\n box-shadow: 0 0 0 3px #efedeb;\n vertical-align: middle;\n }\n\n .opportunities-extension-account-plan-status-indicator[data-active=\"true\"] {\n background: #3f6f17;\n box-shadow: 0 0 0 3px #e2f2e5;\n }\n\n .opportunities-extension-account-plan-tab .opportunities-extension-account-plan-status-indicator {\n margin-right: 8px;\n }\n\n .opportunities-extension-account-plans-skeleton-tabs {\n display: flex;\n min-height: 46px;\n align-items: center;\n padding: 0 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton {\n display: grid;\n height: 100%;\n min-height: 0;\n grid-template-rows: auto minmax(0, 1fr);\n overflow: hidden;\n }\n\n .opportunities-extension-account-plans-skeleton-panel {\n padding: 16px 20px;\n }\n\n .opportunities-extension-account-plans-skeleton-tab {\n display: inline-flex;\n align-items: center;\n gap: 9px;\n min-height: 38px;\n padding: 0 12px;\n border-bottom: 3px solid #00758f;\n }\n\n .opportunities-extension-account-plans-skeleton-status {\n display: block;\n width: 10px;\n height: 10px;\n flex: 0 0 auto;\n border-radius: 50%;\n background: #dedbd7;\n box-shadow: 0 0 0 3px #efedeb;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-account-plans-skeleton-details {\n display: grid;\n grid-template-columns: repeat(3, minmax(0, 1fr));\n gap: 0 24px;\n padding: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details > div {\n display: grid;\n grid-template-columns: minmax(104px, 38%) minmax(0, 1fr);\n align-items: center;\n gap: 10px;\n min-height: 42px;\n padding: 7px 0;\n border-bottom: 1px solid #ebe8e5;\n }\n\n .opportunities-extension-account-plans-skeleton-bar {\n display: block;\n height: 12px;\n border-radius: 3px;\n background: #dedbd7;\n animation: opportunities-extension-skeleton-pulse 1.15s ease-in-out infinite alternate;\n }\n\n .opportunities-extension-account-plans-skeleton-tabs .opportunities-extension-account-plans-skeleton-bar {\n height: 14px;\n }\n\n .opportunities-extension-account-plans-skeleton-label {\n width: 74%;\n height: 10px;\n }\n\n .opportunities-extension-account-plans-skeleton-trend {\n display: grid;\n min-height: 0;\n grid-template-rows: auto auto minmax(0, 1fr);\n margin: 14px 0 0;\n padding-top: 12px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton-trend-header {\n display: flex;\n justify-content: flex-end;\n min-height: 38px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods {\n display: flex;\n align-items: center;\n gap: 16px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods .opportunities-extension-account-plans-skeleton-bar {\n height: 12px;\n }\n\n .opportunities-extension-account-plans-skeleton-period-active {\n height: 38px !important;\n border: 1px solid #8cc8d3;\n background: #e7f6f8;\n }\n\n .opportunities-extension-account-plans-skeleton-navigation {\n display: grid;\n grid-template-columns: 32px 124px 32px;\n align-items: center;\n justify-content: center;\n gap: 8px;\n min-height: 54px;\n }\n\n .opportunities-extension-account-plans-skeleton-navigation .opportunities-extension-account-plans-skeleton-bar {\n justify-self: center;\n }\n\n .opportunities-extension-account-plans-skeleton-chart {\n display: grid;\n min-height: 0;\n grid-template-columns: minmax(0, 1fr) 150px;\n align-items: center;\n gap: 28px;\n padding: 12px 14px 0 62px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot {\n display: flex;\n position: relative;\n height: 300px;\n min-height: 0;\n box-sizing: border-box;\n align-items: flex-end;\n justify-content: space-around;\n gap: 12px;\n padding: 0 14px 64px;\n background: repeating-linear-gradient(to bottom, transparent 0, transparent 58px, #ebe8e5 58px, #ebe8e5 59px) left top / 100% 236px no-repeat;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::before,\n .opportunities-extension-account-plans-skeleton-plot::after {\n position: absolute;\n display: block;\n content: \"\";\n background: #dedbd7;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::before {\n top: 0;\n bottom: 64px;\n left: 0;\n width: 1px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot::after {\n right: 0;\n bottom: 64px;\n left: 0;\n height: 1px;\n }\n\n .opportunities-extension-account-plans-skeleton-plot .opportunities-extension-account-plans-skeleton-bar {\n width: min(38px, 7%);\n flex: 0 1 38px;\n border-radius: 2px 2px 0 0;\n }\n\n .opportunities-extension-account-plans-skeleton-legend {\n display: grid;\n align-content: center;\n gap: 18px;\n min-height: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-legend .opportunities-extension-account-plans-skeleton-bar {\n height: 11px;\n }\n\n @keyframes opportunities-extension-skeleton-pulse {\n from { opacity: .48; }\n to { opacity: 1; }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .opportunities-extension-account-plans-skeleton-bar,\n .opportunities-extension-consumption-chart-skeleton-plot span,\n .opportunities-extension-consumption-svg .consumption-animated-label,\n .opportunities-extension-consumption-svg .consumption-animated-average {\n animation: none;\n opacity: 1;\n }\n }\n\n .opportunities-extension-account-plans-empty,\n .opportunities-extension-account-plans-error {\n margin: 0;\n padding: 28px 20px;\n color: #5f5a55;\n font-size: 14px;\n }\n\n .opportunities-extension-account-plans-error {\n color: #9f2d20;\n }\n\n .opportunities-extension-preferences-dialog {\n display: grid;\n width: min(680px, 100%);\n max-height: min(720px, calc(100vh - 48px));\n grid-template-rows: auto minmax(0, 1fr) auto;\n overflow: hidden;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, .24);\n color: #312d2a;\n }\n\n .opportunities-extension-preferences-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 18px 20px;\n border-bottom: 1px solid #dedbd7;\n }\n\n .opportunities-extension-preferences-header h2 {\n margin: 0;\n font-size: 20px;\n font-weight: 700;\n line-height: 1.2;\n }\n\n .opportunities-extension-preferences-content {\n min-height: 0;\n overflow: auto;\n padding: 20px;\n }\n\n .opportunities-extension-preferences-fieldset {\n min-width: 0;\n margin: 0;\n padding: 0;\n border: 0;\n }\n\n .opportunities-extension-preferences-fieldset legend {\n margin-bottom: 12px;\n padding: 0;\n color: #312d2a;\n font-size: 15px;\n font-weight: 700;\n line-height: 1.3;\n }\n\n .opportunities-extension-preferences-options {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 4px 20px;\n }\n\n .opportunities-extension-preferences-option {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 0;\n padding: 9px 8px;\n border-radius: 4px;\n color: #312d2a;\n font-size: 14px;\n line-height: 1.35;\n cursor: pointer;\n }\n\n .opportunities-extension-preferences-option:hover {\n background: #f0eeeb;\n }\n\n .opportunities-extension-preferences-option input {\n width: 18px;\n height: 18px;\n flex: 0 0 18px;\n margin: 0;\n accent-color: #00758f;\n cursor: pointer;\n }\n\n .opportunities-extension-preferences-cache-field {\n display: grid;\n width: min(280px, 100%);\n gap: 6px;\n margin-top: 24px;\n color: #312d2a;\n font-size: 14px;\n font-weight: 700;\n }\n\n .opportunities-extension-preferences-cache-field select {\n width: 100%;\n height: 40px;\n padding: 0 36px 0 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n color: #312d2a;\n font-size: 14px;\n font-weight: 400;\n }\n\n .opportunities-extension-preferences-cache-field select:focus {\n border-color: #00758f;\n outline: 2px solid #bde7ee;\n outline-offset: 0;\n }\n\n .opportunities-extension-preferences-footer {\n display: flex;\n justify-content: flex-end;\n padding: 14px 20px;\n border-top: 1px solid #dedbd7;\n }\n\n .opportunities-extension-button {\n min-width: 88px;\n min-height: 36px;\n padding: 7px 16px;\n border: 1px solid transparent;\n border-radius: 4px;\n font-size: 14px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .opportunities-extension-button-primary {\n border-color: #00758f;\n background: #00758f;\n color: #ffffff;\n }\n\n .opportunities-extension-button-primary:hover,\n .opportunities-extension-button-primary:focus-visible {\n border-color: #005e73;\n background: #005e73;\n outline: none;\n }\n\n .opportunities-extension-debug-panel {\n position: fixed;\n right: 24px;\n bottom: 24px;\n z-index: 1;\n width: min(640px, calc(100vw - 48px));\n max-height: min(560px, calc(100vh - 120px));\n overflow: auto;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #ffffff;\n box-shadow: 0 2px 8px rgba(0, 0, 0, .16);\n padding: 16px;\n color: #000000;\n }\n\n .opportunities-extension-debug-panel[hidden] {\n display: none !important;\n }\n\n .opportunities-extension-debug-panel h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 700;\n line-height: 1.25;\n }\n\n .opportunities-extension-debug-panel p {\n margin: 4px 0 0;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-debug-panel-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 12px;\n margin-bottom: 12px;\n }\n\n .opportunities-extension-debug-visibility-button {\n width: 34px;\n height: 34px;\n flex: 0 0 34px;\n color: #312d2a;\n }\n\n .opportunities-extension-debug-visibility-button svg {\n width: 20px;\n height: 20px;\n }\n\n .opportunities-extension-debug-list {\n display: grid;\n gap: 10px;\n }\n\n .opportunities-extension-debug-item {\n border: 1px solid #dedbd7;\n border-left-width: 4px;\n border-radius: 4px;\n background: #faf9f8;\n }\n\n .opportunities-extension-debug-item[open] {\n background: #ffffff;\n }\n\n .opportunities-extension-debug-item-success {\n border-left-color: #3f6f17;\n }\n\n .opportunities-extension-debug-item-success .opportunities-extension-debug-status {\n background: #e2f2e5;\n color: #356d19;\n }\n\n .opportunities-extension-debug-item-failed {\n border-left-color: #c5331f;\n }\n\n .opportunities-extension-debug-item-failed .opportunities-extension-debug-status {\n background: #f9e3e1;\n color: #a52b1c;\n }\n\n .opportunities-extension-debug-item-pending {\n border-left-color: #6f5a7f;\n }\n\n .opportunities-extension-debug-item-pending .opportunities-extension-debug-status {\n background: #eee8f2;\n color: #6f5a7f;\n }\n\n .opportunities-extension-debug-heading {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n min-height: 42px;\n padding: 9px 12px 9px 10px;\n cursor: pointer;\n list-style: none;\n }\n\n .opportunities-extension-debug-heading::-webkit-details-marker {\n display: none;\n }\n\n .opportunities-extension-debug-heading::before {\n content: \"⌄\";\n width: 14px;\n color: #5f5a55;\n font-size: 16px;\n line-height: 1;\n transform: rotate(-90deg);\n transition: transform .15s ease;\n }\n\n .opportunities-extension-debug-item[open] .opportunities-extension-debug-heading::before {\n transform: rotate(0deg);\n }\n\n .opportunities-extension-debug-summary-meta {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n margin-left: auto;\n }\n\n .opportunities-extension-debug-http-status,\n .opportunities-extension-debug-status {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 0 8px;\n border-radius: 999px;\n font-size: 11px;\n font-weight: 700;\n line-height: 1;\n text-transform: uppercase;\n }\n\n .opportunities-extension-debug-http-status {\n background: #e8f4f6;\n color: #006d7a;\n }\n\n .opportunities-extension-debug-status {\n background: #ebe8e5;\n color: #5f5a55;\n }\n\n .opportunities-extension-debug-heading strong {\n font-size: 13px;\n }\n\n .opportunities-extension-debug-item pre {\n margin: 0;\n padding: 8px 12px 12px;\n color: #312d2a;\n font-family: Consolas, \"Courier New\", monospace;\n font-size: 12px;\n line-height: 1.45;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .opportunities-extension-debug-empty {\n padding: 14px;\n border: 1px dashed #b8b2ad;\n border-radius: 4px;\n color: #5f5a55;\n font-size: 13px;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] {\n background: #1f1f1f;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-shell,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-body {\n background: #1f1f1f;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header {\n border-bottom-color: #4e4a46;\n background:\n linear-gradient(90deg, #a8795d 0 11%, #dd5a47 11% 23%, #876e9b 23% 36%, #00a6be 36% 51%, #dfbd76 51% 63%, transparent 63% 100%) top left / 100% 6px no-repeat,\n #292827;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header h1,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-value,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-field,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-header p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card span,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail-heading span,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-empty,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details dt,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel p,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-empty {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-error {\n color: #ffb4a8;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-error {\n color: #ffb4a8;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-bar {\n background: #5b5753;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-status {\n background: #5b5753;\n box-shadow: 0 0 0 3px #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-period-active {\n border-color: #3f7580;\n background: #23474e;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-skeleton-plot span {\n background: #5b5753;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-status-indicator {\n background: #8f8a85;\n box-shadow: 0 0 0 3px #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-status-indicator[data-active=\"true\"] {\n background: #7fb05b;\n box-shadow: 0 0 0 3px #314527;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-form,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-surface,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-panel,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-dialog,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-dialog,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item[open] {\n border-color: #4e4a46;\n background: #292827;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-search,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field input,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-field select,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-cache-field select,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger::after {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-select-wrap::after {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-trigger:disabled {\n background: #292827;\n color: #918b86;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-search::placeholder,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table-search-field input::placeholder {\n color: #b5b0ab;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-option,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-header h2,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header h2,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-fieldset legend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-cache-field,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail-heading,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details dd,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-heading,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item pre,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel h2 {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation strong {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-empty {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-select-all,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table th {\n border-bottom-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-header,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-footer,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-header,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tabs-navigation,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tabs,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-details > div,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-tabs,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-details > div {\n border-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-trend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-chart-skeleton-plot,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-trend,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot {\n border-color: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot {\n background: repeating-linear-gradient(to bottom, transparent 0, transparent 58px, #4e4a46 58px, #4e4a46 59px) left top / 100% 236px no-repeat;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot::before,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-skeleton-plot::after {\n background: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab {\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab:hover {\n background: #3b3937;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plan-tab[aria-selected=\"true\"] {\n border-bottom-color: #43c4d5;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-periods button[aria-pressed=\"true\"] {\n border-color: #43c4d5;\n background: #173e43;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button:hover:not(:disabled),\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button:hover:not(:disabled) {\n border-color: #43c4d5;\n background: #3b3937;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-navigation-button:disabled,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-account-plans-tab-navigation-button:disabled {\n border-color: #4e4a46;\n color: #746f6a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-grid-line {\n stroke: #4e4a46;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-axis-label,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-x-label {\n fill: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-value-label {\n fill: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-funded {\n fill: #ca8798;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-overage {\n fill: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-average-line {\n stroke: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-group:hover rect,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-svg .consumption-bar-group:focus rect {\n stroke: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button {\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend button[aria-pressed=\"false\"] {\n color: #a8a39e;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-funded {\n background: #ca8798;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-overage {\n background: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-legend-average {\n border-top-color: #f09a32;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-consumption-tooltip {\n border-color: #6a6560;\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option:hover {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-preferences-option input {\n accent-color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary {\n border-color: #00a6be;\n background: #008aa6;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-button-primary:focus-visible {\n border-color: #43c4d5;\n background: #006d7a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-filter-option:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table tbody tr:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sort-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button:focus {\n background: #3b3937;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table thead,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table th,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table th {\n background: #333130;\n color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table td {\n border-bottom-color: #3f3c39;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-detail {\n border-bottom-color: #4e4a46;\n background: #252423;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table th,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-table td {\n border-bottom-color: #3f3c39;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count {\n border-color: #2f9bae;\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count:focus-visible,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count[aria-expanded=\"true\"] {\n border-color: #43c4d5;\n background: #008aa6;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"running\"] {\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"complete\"] {\n background: #244f2e;\n color: #a8dfb7;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"complete-with-errors\"],\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-progress[data-state=\"error\"],\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-count-error {\n border-color: #b13b34;\n background: #5f2926;\n color: #ffb4ad;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-cache-timestamp {\n background: #3b3937;\n color: #c9c5c1;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table a,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button {\n color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-table a:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-copy-button:focus-visible,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button:hover,\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-button:focus-visible {\n background: #1d4e55;\n color: #91e4ed;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"SQL\"] {\n color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"PIPELINE\"] {\n color: #d1cbc6;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"UPSIDE\"] {\n color: #ffbf62;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"FORECAST\"] {\n color: #d2b7e9;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[data-stage=\"WON\"] {\n color: #9bd46a;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"SQL\"] {\n border-top-color: #43c4d5;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-total-dashboard-card {\n border-top-color: #f6f4f2;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"PIPELINE\"] {\n border-top-color: #c0b9b3;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"UPSIDE\"] {\n border-top-color: #ffb84d;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"FORECAST\"] {\n border-top-color: #cba7e7;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-dashboard-card[data-stage=\"WON\"] {\n border-top-color: #92cf5b;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"SQL\"] {\n border-color: #008aa6;\n background: #008aa6;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"PIPELINE\"] {\n border-color: #6f6863;\n background: #6f6863;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"UPSIDE\"] {\n border-color: #b96e00;\n background: #b96e00;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"FORECAST\"] {\n border-color: #755b8b;\n background: #755b8b;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-stage-filter-button[aria-pressed=\"true\"][data-stage=\"WON\"] {\n border-color: #4b7f22;\n background: #4b7f22;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"OPEN\"] {\n color: #69c985;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"CLOSED\"] {\n color: #c3cad3;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"LOST\"] {\n color: #ff9d94;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[data-status=\"WON\"] {\n color: #83bfff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"OPEN\"] {\n border-color: #197a3d;\n background: #197a3d;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"CLOSED\"] {\n border-color: #4b5563;\n background: #4b5563;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"LOST\"] {\n border-color: #b13b34;\n background: #b13b34;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-status-filter-button[aria-pressed=\"true\"][data-status=\"WON\"] {\n border-color: #1f5f99;\n background: #1f5f99;\n color: #ffffff;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-item {\n border-color: #4e4a46;\n background: #252423;\n }\n\n .opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-icon-button {\n color: #f6f4f2;\n }\n\n @media (min-width: 1201px) and (max-width: 1450px) {\n .opportunities-extension-table th:nth-child(1) {\n width: 16%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 18%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 12%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 7%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 8%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 10%;\n }\n }\n\n @media (max-width: 1200px) {\n .opportunities-extension-table {\n min-width: 1180px;\n }\n\n .opportunities-extension-table th:nth-child(1) {\n width: 15%;\n }\n\n .opportunities-extension-table th:nth-child(3) {\n width: 17%;\n }\n\n .opportunities-extension-table th:nth-child(4) {\n width: 13%;\n }\n\n .opportunities-extension-table th:nth-child(6) {\n width: 6%;\n }\n\n .opportunities-extension-table th:nth-child(7) {\n width: 9%;\n }\n\n .opportunities-extension-table th:nth-child(10) {\n width: 11%;\n }\n }\n\n @media (max-width: 700px) {\n .opportunities-extension-header {\n padding: 24px 20px 18px;\n }\n\n .opportunities-extension-header::before {\n left: 20px;\n }\n\n .opportunities-extension-header h1 {\n font-size: 22px;\n }\n\n .opportunities-extension-header p {\n font-size: 14px;\n }\n\n .opportunities-extension-body {\n padding: 16px 20px 24px;\n }\n\n .opportunities-extension-form {\n align-items: stretch;\n flex-wrap: wrap;\n gap: 14px;\n min-height: auto;\n padding: 12px;\n }\n\n .opportunities-extension-field {\n max-width: none;\n width: 100%;\n }\n\n .opportunities-extension-customer-filter {\n width: 100%;\n }\n\n .opportunities-extension-customer-filter-trigger {\n width: 100%;\n }\n\n .opportunities-extension-customer-filter-panel {\n width: min(360px, calc(100vw - 64px));\n }\n\n .opportunities-extension-table-search-field {\n width: 100%;\n }\n\n .opportunities-extension-stage-dashboard {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n\n .opportunities-extension-stage-dashboard-value {\n font-size: 18px;\n }\n\n .opportunities-extension-preferences-modal {\n padding: 12px;\n }\n\n .opportunities-extension-account-plans-modal {\n padding: 12px;\n }\n\n .opportunities-extension-preferences-dialog {\n max-height: calc(100vh - 24px);\n }\n\n .opportunities-extension-account-plans-dialog {\n height: calc(100vh - 24px);\n }\n\n .opportunities-extension-account-plan-panel {\n padding: 12px 14px;\n }\n\n .opportunities-extension-account-plan-details {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0 14px;\n }\n\n .opportunities-extension-account-plan-details > div {\n grid-template-columns: 1fr;\n align-content: center;\n gap: 3px;\n min-height: 54px;\n padding: 5px 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0 14px;\n padding: 0;\n }\n\n .opportunities-extension-account-plans-skeleton-details > div {\n grid-template-columns: 1fr;\n align-content: center;\n gap: 5px;\n min-height: 54px;\n padding: 5px 0;\n }\n\n .opportunities-extension-account-plans-skeleton-trend {\n margin: 14px 0 0;\n }\n\n .opportunities-extension-account-plans-skeleton-periods {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n align-items: center;\n gap: 6px;\n }\n\n .opportunities-extension-account-plans-skeleton-periods .opportunities-extension-account-plans-skeleton-bar {\n width: 100% !important;\n }\n\n .opportunities-extension-account-plans-skeleton-chart {\n grid-template-columns: minmax(0, 1fr);\n gap: 12px;\n padding: 12px 8px 0 34px;\n }\n\n .opportunities-extension-account-plans-skeleton-legend {\n display: flex;\n min-height: 24px;\n align-items: center;\n justify-content: center;\n gap: 12px;\n }\n\n .opportunities-extension-consumption-trend-header {\n align-items: stretch;\n }\n\n .opportunities-extension-consumption-periods {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n gap: 3px;\n }\n\n .opportunities-extension-consumption-periods button {\n min-width: 0;\n padding: 7px 4px;\n font-size: 12px;\n }\n\n .opportunities-extension-consumption-chart {\n min-height: 0;\n }\n\n .opportunities-extension-consumption-svg {\n width: 760px;\n height: 245px;\n }\n\n .opportunities-extension-consumption-visual {\n width: 920px;\n grid-template-columns: 760px 144px;\n gap: 12px;\n }\n\n .opportunities-extension-consumption-figure {\n overflow-x: auto;\n overscroll-behavior-inline: contain;\n }\n\n .opportunities-extension-consumption-chart-skeleton {\n min-height: 0;\n padding: 24px 18px 18px;\n }\n\n .opportunities-extension-consumption-chart-skeleton-plot {\n min-height: 180px;\n gap: 4px;\n padding: 0 6px;\n }\n\n .opportunities-extension-preferences-options {\n grid-template-columns: 1fr;\n }\n\n .opportunities-extension-stage-filter-controls {\n gap: 6px;\n }\n\n .opportunities-extension-status-filter-controls {\n gap: 6px;\n }\n\n .opportunities-extension-table-surface {\n min-width: 0;\n min-height: calc(100vh - 230px);\n }\n\n .opportunities-extension-debug-panel {\n right: 12px;\n bottom: 12px;\n width: calc(100vw - 24px);\n max-height: calc(100vh - 96px);\n }\n }\n \n/* Full-page diagnostics, scoped to the extension and its current theme. */\n.opportunities-extension-modal .opportunities-extension-debug-panel {\n --debug-surface: #fff;\n --debug-code: #f5f6f7;\n --debug-text: #312d2a;\n --debug-muted: #5f5a55;\n --debug-border: #dedbd7;\n --debug-success: #22613b;\n --debug-success-bg: #e1f1e5;\n --debug-failed: #a12721;\n --debug-failed-bg: #fce8e6;\n --debug-pending: #805000;\n --debug-pending-bg: #fff1ce;\n --debug-info: #075e87;\n --debug-info-bg: #e5f1fa;\n --debug-key: #075e87;\n --debug-string: #22613b;\n --debug-number: #865000;\n --debug-literal: #73429b;\n position: fixed;\n inset: 0;\n z-index: 50;\n display: grid;\n grid-template-rows: auto auto minmax(0, 1fr);\n width: auto;\n height: auto;\n max-height: none;\n min-width: 0;\n box-sizing: border-box;\n overflow: hidden;\n margin: 0;\n padding: 20px;\n border: 0;\n border-radius: 0;\n background: var(--debug-surface);\n color: var(--debug-text);\n color-scheme: light;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-panel {\n --debug-surface: #292827;\n --debug-code: #222120;\n --debug-text: #f6f4f2;\n --debug-muted: #c9c5c1;\n --debug-border: #514c47;\n --debug-success: #a9e3bd;\n --debug-success-bg: #214d34;\n --debug-failed: #ffb4ab;\n --debug-failed-bg: #582c2a;\n --debug-pending: #ffe099;\n --debug-pending-bg: #59441e;\n --debug-info: #a8d9ff;\n --debug-info-bg: #233f52;\n --debug-key: #8ed6f0;\n --debug-string: #a9e3bd;\n --debug-number: #ffe099;\n --debug-literal: #d6b7f1;\n color: #f6f4f2;\n color-scheme: dark;\n}\n.opportunities-extension-debug-actions { display: flex; gap: 8px; flex: 0 0 auto; }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-list {\n overflow: auto;\n min-height: 0;\n min-width: 0;\n align-content: start;\n scrollbar-gutter: stable;\n padding: 2px 8px 12px 2px;\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item {\n --debug-state: var(--debug-info);\n --debug-state-bg: var(--debug-info-bg);\n border-color: var(--debug-border);\n border-left-color: var(--debug-state);\n background: var(--debug-surface);\n min-width: 0;\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-success { --debug-state: var(--debug-success); --debug-state-bg: var(--debug-success-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-failed { --debug-state: var(--debug-failed); --debug-state-bg: var(--debug-failed-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item-pending { --debug-state: var(--debug-pending); --debug-state-bg: var(--debug-pending-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-status {\n color: var(--debug-state);\n background: var(--debug-state-bg);\n}\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status,\n.opportunities-extension-debug-method {\n color: var(--debug-info);\n background: var(--debug-info-bg);\n}\n.opportunities-extension-debug-method {\n display: inline-flex;\n align-items: center;\n min-height: 22px;\n padding: 0 8px;\n border-radius: 4px;\n font: 700 11px/1.2 Consolas, monospace;\n}\n.opportunities-extension-debug-method[data-method=\"POST\"] { color: var(--debug-literal); background: var(--debug-code); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"2\"] { color: var(--debug-success); background: var(--debug-success-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"4\"],\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"5\"] { color: var(--debug-failed); background: var(--debug-failed-bg); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-http-status[data-http-class=\"pending\"] { color: var(--debug-pending); background: var(--debug-pending-bg); }\n.opportunities-extension-debug-details { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; padding: 0 14px 16px; }\n.opportunities-extension-debug-block { min-width: 0; border-left: 2px solid var(--debug-info); padding-left: 10px; }\n.opportunities-extension-debug-block[data-direction=\"response\"] { border-left-color: var(--debug-success); }\n.opportunities-extension-modal .opportunities-extension-debug-block h3 { margin: 0 0 8px; color: var(--debug-info); font-size: 12px; }\n.opportunities-extension-modal .opportunities-extension-debug-block[data-direction=\"response\"] h3 { color: var(--debug-success); }\n.opportunities-extension-modal .opportunities-extension-debug-panel .opportunities-extension-debug-item pre {\n min-width: 0;\n margin: 0;\n padding: 12px;\n max-height: 380px;\n overflow: auto;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n color: var(--debug-text);\n background: var(--debug-code);\n line-height: 1.6;\n tab-size: 2;\n}\n.opportunities-extension-debug-json-key { color: var(--debug-key); }\n.opportunities-extension-debug-json-string { color: var(--debug-string); }\n.opportunities-extension-debug-json-number { color: var(--debug-number); }\n.opportunities-extension-debug-json-literal { color: var(--debug-literal); }\n@media (max-width: 760px) {\n .opportunities-extension-modal .opportunities-extension-debug-panel { padding: 12px; }\n .opportunities-extension-debug-details { grid-template-columns: minmax(0, 1fr); }\n}\n.opportunities-extension-debug-tabs {\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n margin-bottom: 12px;\n padding-bottom: 8px;\n border-bottom: 1px solid #dedbd7;\n}\n\n.opportunities-extension-debug-tabs button {\n max-width: 100%;\n min-height: 32px;\n padding: 6px 8px;\n border: 0;\n border-bottom: 2px solid transparent;\n border-radius: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-size: 12px;\n line-height: 1.35;\n overflow-wrap: anywhere;\n cursor: pointer;\n}\n\n.opportunities-extension-debug-tabs button:hover {\n background: #f5f4f2;\n}\n\n.opportunities-extension-debug-tabs button[aria-selected=\"true\"] {\n border-bottom-color: #00758f;\n background: #e8f4f6;\n color: #006b84;\n font-weight: 700;\n}\n\n.opportunities-extension-debug-tabs button:focus-visible,\n.opportunities-extension-debug-list[role=\"tabpanel\"]:focus-visible {\n outline: 2px solid #00758f;\n outline-offset: -2px;\n}\n\n.opportunities-extension-debug-time {\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n\n.opportunities-extension-debug-heading {\n flex-wrap: wrap;\n}\n\n.opportunities-extension-debug-heading strong {\n flex: 1 1 180px;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-debug-summary-meta {\n flex-wrap: wrap;\n justify-content: flex-end;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button {\n color: #f6f4f2;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-heading::before {\n color: #c9c5c1;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs {\n border-bottom-color: #514c47;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button:hover {\n background: #383633;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button[aria-selected=\"true\"] {\n background: #173f48;\n border-bottom-color: #8cc8d3;\n color: #bde7ee;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-tabs button:focus-visible,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-list[role=\"tabpanel\"]:focus-visible {\n outline-color: #8cc8d3;\n}\n.opportunities-extension-debug-duration {\n color: #55514d;\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n white-space: nowrap;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-debug-duration { color: #d6d2ce; }\n\n/* Compact filters use available CSS width, including Windows display scaling. */\n.opportunities-extension-products-progress,\n.opportunities-extension-auth-badge { opacity: 1; transition: opacity 300ms ease; }\n.opportunities-extension-products-progress[data-fading=\"true\"],\n.opportunities-extension-auth-badge[data-fading=\"true\"] { opacity: 0; }\n.opportunities-extension-auth-badge[hidden] { display: none; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-products-progress,\n .opportunities-extension-auth-badge { transition: none; }\n}\n.opportunities-extension-crm-sr-badge {\n border: 1px solid #408254;\n color: #185b30;\n background: #e1f1e5;\n}\n.opportunities-extension-crm-sr-badge[data-state=\"missing\"] { color: #9f201b; background: #fde8e7; border-color: #c74640; }\n.opportunities-extension-crm-sr-badge[data-state=\"error\"] { color: #785000; background: #fff0cd; border-color: #987021; }\n.opportunities-extension-wl-actions-badge[data-state=\"loading\"] { color: #5f5a55; background: #eceae8; border-color: #8f8a85; }\n.opportunities-extension-crm-sr-badge:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge { color: #b8e4c6; background: #214d34; border-color: #6eac82; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge[data-state=\"missing\"] { color: #ffd9d5; background: #542824; border-color: #ef938b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-crm-sr-badge[data-state=\"error\"] { color: #ffe0a3; background: #584219; border-color: #c99b4b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-wl-actions-badge[data-state=\"loading\"] { color: #dedbd7; background: #484541; border-color: #8f8a85; }\n\n.opportunities-extension-form {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr)) max-content max-content;\n align-items: end;\n gap: 12px;\n min-height: 0;\n padding: 12px;\n}\n\n.opportunities-extension-form > *,\n.opportunities-extension-badge-filters > section {\n min-width: 0;\n width: 100%;\n max-width: none;\n grid-template-rows: auto 32px;\n gap: 4px;\n font-size: 12px;\n}\n\n.opportunities-extension-form > * > span:first-child,\n.opportunities-extension-badge-filters > section > span:first-child {\n font-size: 12px;\n line-height: 16px;\n}\n\n.opportunities-extension-form .opportunities-extension-select-wrap {\n width: 100%;\n}\n\n.opportunities-extension-form .opportunities-extension-field select,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger,\n.opportunities-extension-form .opportunities-extension-table-search-field input {\n box-sizing: border-box;\n width: 100%;\n min-width: 0;\n height: 32px;\n min-height: 32px;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 20px;\n}\n\n.opportunities-extension-form .opportunities-extension-field select,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger {\n padding-right: 26px;\n}\n\n.opportunities-extension-form .opportunities-extension-select-wrap::after,\n.opportunities-extension-form .opportunities-extension-customer-filter-trigger::after {\n right: 10px;\n border-left-width: 4px;\n border-right-width: 4px;\n border-top-width: 5px;\n}\n\n.opportunities-extension-form .opportunities-extension-stage-filter-controls,\n.opportunities-extension-form .opportunities-extension-status-filter-controls {\n flex-wrap: nowrap;\n gap: 4px;\n}\n\n.opportunities-extension-form .opportunities-extension-stage-filter-button,\n.opportunities-extension-form .opportunities-extension-status-filter-button,\n.opportunities-extension-form .opportunities-extension-activity-filter-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n height: 28px;\n min-height: 28px;\n padding: 4px 7px;\n border: 1px solid currentColor;\n border-radius: 18px;\n font-family: inherit;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0;\n line-height: 18px;\n white-space: nowrap;\n}\n\n.opportunities-extension-cell-actions > .opportunities-extension-products-count,\n.opportunities-extension-cell-actions > .opportunities-extension-products-ramp,\n.opportunities-extension-cell-actions > .opportunities-extension-crm-sr-badge {\n display: inline-flex;\n align-items: center;\n justify-content: flex-start;\n box-sizing: border-box;\n flex: 0 0 auto;\n gap: 4px;\n height: 20px;\n min-height: 20px;\n margin: 0;\n padding: 0 6px;\n border-width: 1px;\n border-style: solid;\n border-radius: 8px;\n font-family: inherit;\n font-size: 10px;\n font-style: normal;\n font-weight: 600;\n line-height: 16px;\n letter-spacing: 0;\n text-align: center;\n vertical-align: middle;\n white-space: nowrap;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-badge-icon,\n.opportunities-extension-activity-filter-button .opportunities-extension-badge-icon {\n display: block;\n order: -1;\n flex: 0 0 16px;\n width: 16px;\n height: 16px;\n margin: 0;\n padding: 0;\n border: 0;\n color: inherit;\n fill: none;\n stroke: currentColor;\n stroke-width: 2.25;\n stroke-linecap: round;\n stroke-linejoin: round;\n pointer-events: none;\n}\n\n@media (max-width: 1150px) {\n .opportunities-extension-form {\n grid-template-columns: repeat(4, minmax(0, 1fr));\n }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter {\n grid-column: span 2;\n }\n}\n\n@media (max-width: 700px) {\n .opportunities-extension-form {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n }\n .opportunities-extension-form .opportunities-extension-stage-filter-controls,\n .opportunities-extension-form .opportunities-extension-status-filter-controls {\n flex-wrap: wrap;\n }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter {\n grid-template-rows: auto auto;\n }\n}\n\n@media (max-width: 420px) {\n .opportunities-extension-form { grid-template-columns: minmax(0, 1fr); }\n .opportunities-extension-badge-filters > .opportunities-extension-status-filter,\n .opportunities-extension-badge-filters > .opportunities-extension-stage-filter { grid-column: auto; }\n}\n\n.opportunities-extension-badge-filters { display: contents; }\n.opportunities-extension-activity-filter { display: grid; }\n.opportunities-extension-activity-filter[hidden] { display: none; }\n.opportunities-extension-activity-filter-controls { display: flex; align-items: center; flex-wrap: nowrap; gap: 4px; }\n/* Flexible fields share the space left by the four compact badge groups. */\n.opportunities-extension-form[data-activity-filters=\"true\"] {\n grid-template-columns: repeat(4, minmax(0, 1fr)) repeat(4, max-content);\n column-gap: 8px;\n}\n.opportunities-extension-activity-filter-button {\n min-width: 32px;\n gap: 4px;\n color: #185b30;\n background: #fff;\n cursor: pointer;\n}\n.opportunities-extension-activity-filter-button[data-value=\"missing\"] { color: #9f201b; }\n.opportunities-extension-activity-filter-button[data-value=\"under4\"] { color: #005f7d; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"] { color: #fff; background: #25653a; border-color: #25653a; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"][data-value=\"missing\"] { background: #a12d27; border-color: #a12d27; }\n.opportunities-extension-activity-filter-button[aria-pressed=\"true\"][data-value=\"under4\"] { background: #006b86; border-color: #006b86; }\n.opportunities-extension-activity-filter-button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter { color: #eeeae6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button { color: #b8e4c6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button:not([aria-pressed=\"true\"]) { background: #333130; border-color: #6a6560; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[data-value=\"missing\"] { color: #ffd9d5; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[data-value=\"under4\"] { color: #b5e9fc; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-activity-filter-button[aria-pressed=\"true\"] { border-color: currentColor; }\n@media (max-width: 1350px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: repeat(4, minmax(0, 1fr)); }\n .opportunities-extension-form[data-activity-filters=\"true\"] .opportunities-extension-badge-filters {\n display: flex;\n grid-column: 1 / -1;\n flex-wrap: wrap;\n align-items: start;\n gap: 12px 20px;\n }\n .opportunities-extension-form[data-activity-filters=\"true\"] .opportunities-extension-badge-filters > section {\n width: auto;\n max-width: 100%;\n grid-template-rows: auto auto;\n }\n}\n@media (max-width: 700px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n .opportunities-extension-activity-filter-controls { flex-wrap: wrap; }\n}\n@media (max-width: 420px) {\n .opportunities-extension-form[data-activity-filters=\"true\"] { grid-template-columns: minmax(0, 1fr); }\n}\n\n.opportunities-extension-add-action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n box-sizing: border-box;\n flex: 0 0 16px;\n width: 16px;\n height: 16px;\n padding: 0;\n margin: 0 0 0 2px;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: inherit;\n font: inherit;\n cursor: pointer;\n}\n.opportunities-extension-add-action:hover { background: rgba(127, 127, 127, .2); }\n.opportunities-extension-add-action:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-action-form-modal {\n position: absolute;\n inset: 0;\n z-index: 5;\n display: grid;\n place-items: center;\n padding: 12px;\n background: rgba(0, 0, 0, .42);\n}\n.opportunities-extension-action-form-dialog {\n box-sizing: border-box;\n width: min(560px, 100%);\n max-height: calc(100vh - 24px);\n overflow-y: auto;\n background: #fff;\n color: #312d2a;\n border: 1px solid #b9b4ae;\n border-radius: 6px;\n box-shadow: 0 12px 36px rgba(0, 0, 0, .25);\n}\n.opportunities-extension-action-form {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 14px;\n padding: 18px;\n}\n.opportunities-extension-action-form-heading { min-width: 0; overflow-wrap: anywhere; }\n.opportunities-extension-action-form-context {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n gap: 6px 12px;\n margin: 12px 0 0;\n font-size: 12px;\n line-height: 18px;\n}\n.opportunities-extension-action-form-context dt { font-weight: 600; }\n.opportunities-extension-action-form-context dd { margin: 0; min-width: 0; overflow-wrap: anywhere; }\n.opportunities-extension-action-form-field { display: grid; gap: 6px; min-width: 0; font-size: 13px; }\n.opportunities-extension-action-form-wide,\n.opportunities-extension-action-form-footer { grid-column: 1 / -1; }\n.opportunities-extension-action-form-field input,\n.opportunities-extension-action-form-field textarea {\n box-sizing: border-box;\n min-width: 0;\n width: 100%;\n border: 1px solid #8f8983;\n border-radius: 4px;\n padding: 8px;\n font: inherit;\n line-height: 20px;\n color: inherit;\n background: #fff;\n}\n.opportunities-extension-action-form-field textarea { resize: vertical; min-height: 96px; }\n.opportunities-extension-action-form-footer { display: flex; justify-content: flex-end; gap: 8px; }\n.opportunities-extension-action-form-footer button {\n border: 1px solid #8f8983;\n border-radius: 4px;\n padding: 7px 14px;\n font: inherit;\n font-size: 13px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n}\n.opportunities-extension-action-form-footer button:disabled { opacity: .55; cursor: not-allowed; }\n.opportunities-extension-action-form :focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-form-dialog {\n color-scheme: dark;\n background: #292725;\n color: #eeeae6;\n border-color: #756f68;\n}\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-form-field input,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-form-field textarea { background: #211f1d; border-color: #918a82; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-action-form :focus-visible { outline-color: #80d6e8; }\n@media (max-width: 420px) {\n .opportunities-extension-action-form { grid-template-columns: minmax(0, 1fr); }\n}\n\n/* Keep layout rules on the outer table, never on expanded product tables. */\n.opportunities-extension-table[data-opportunities-layout=\"inline-actions\"] {\n width: 100%;\n min-width: 1120px;\n table-layout: fixed;\n}\n\n/* Fixed table layout shares leftover width only between the two auto columns. */\n.opportunities-extension-table > thead > tr > th[data-column=\"name\"] { width: auto; }\n.opportunities-extension-table > thead > tr > th[data-column=\"customer\"] { width: auto; }\n.opportunities-extension-table > thead > tr > th[data-column=\"owner\"] { width: 132px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"optyNumber\"] { width: 106px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"revenue\"] { width: 124px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"closeDate\"] { width: 100px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"status\"] { width: 114px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"winProbability\"] { width: 110px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"stage\"] { width: 94px; }\n.opportunities-extension-table > thead > tr > th[data-column=\"lastUpdateDate\"] { width: 136px; }\n\n.opportunities-extension-table > tbody > tr > td[data-column] {\n padding: 10px 8px;\n overflow: visible;\n text-overflow: clip;\n white-space: normal;\n font-variant-numeric: tabular-nums;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"name\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"customer\"] {\n position: relative;\n padding-right: 16px;\n padding-left: 12px;\n padding-bottom: 38px;\n vertical-align: top;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"owner\"] {\n padding-right: 16px;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"closeDate\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"lastUpdateDate\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"status\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"stage\"],\n.opportunities-extension-table > tbody > tr > td[data-column=\"winProbability\"] {\n white-space: nowrap;\n}\n\n.opportunities-extension-cell-content {\n display: block;\n min-width: 0;\n min-height: 2.7em;\n line-height: 1.35;\n}\n\n.opportunities-extension-cell-content > :first-child {\n display: block;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-cell-actions {\n position: absolute;\n left: 12px;\n right: 16px;\n bottom: 10px;\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 6px;\n height: 24px;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-action-button {\n flex: 0 0 24px;\n width: 24px;\n height: 24px;\n padding: 2px;\n}\n\n.opportunities-extension-table > tbody > tr > td[data-column=\"customer\"] .opportunities-extension-cell-actions {\n min-width: 84px;\n}\n\n.opportunities-extension-cell-actions .opportunities-extension-action-button svg {\n width: 18px;\n height: 18px;\n}\n\n.opportunities-extension-cell-actions button:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n}\n\n.opportunities-extension-products-ramp {\n min-width: 0;\n max-width: 100%;\n border: 1px solid #bba5cf;\n background: #f0e8f7;\n color: #63358a;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-ramp {\n background: #43334f;\n color: #ead5fc;\n border-color: #9372ac;\n}\n\n.opportunities-extension-products-ramp[data-missing=\"true\"] {\n background: #fde8e7;\n color: #9f201b;\n border-color: #c74640;\n}\n\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-products-ramp[data-missing=\"true\"] {\n background: #542824;\n color: #ffd9d5;\n border-color: #ef938b;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column] .opportunities-extension-sort-button {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 12px;\n gap: 6px;\n padding: 10px 8px;\n align-items: center;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column=\"name\"] .opportunities-extension-sort-button,\n.opportunities-extension-table > thead > tr > th[data-column=\"customer\"] .opportunities-extension-sort-button {\n padding-left: 12px;\n padding-right: 16px;\n}\n\n.opportunities-extension-sort-label {\n min-width: 0;\n white-space: normal;\n overflow-wrap: anywhere;\n}\n\n.opportunities-extension-table > thead > tr > th[data-column] .opportunities-extension-sort-button::after {\n position: static;\n justify-self: end;\n}\n.opportunities-extension-crm-sr-badge[type=\"button\"] { cursor: pointer; font-family: inherit; }\n.opportunities-extension-sr-popover {\n position: fixed; z-index: 8; box-sizing: border-box; overflow: auto;\n padding: 12px; border: 1px solid #b9b5b0; border-radius: 6px;\n background: #fff; color: #302e2b; box-shadow: 0 6px 24px #0003;\n font: 12px/1.5 Arial, sans-serif; text-align: left; overflow-wrap: anywhere;\n}\n.opportunities-extension-sr-popover section { padding: 8px 0; }\n.opportunities-extension-sr-popover section + section { border-top: 1px solid #dedbd7; }\n.opportunities-extension-sr-number { display: flex; align-items: center; gap: 8px; padding-right: 30px; font-weight: 600; }\n.opportunities-extension-sr-popover a { color: #00677d; text-decoration: underline; }\n.opportunities-extension-sr-details { white-space: pre-wrap; margin-top: 6px; }\n.opportunities-extension-sr-dismiss {\n position: absolute; top: 6px; right: 6px; width: 28px; height: 28px;\n display: grid; place-items: center; padding: 4px; border: 0;\n background: transparent; color: inherit; cursor: pointer;\n}\n.opportunities-extension-sr-dismiss svg { width: 16px; height: 16px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover { background: #292827; color: #f1efec; border-color: #77716b; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover section + section { border-color: #5f5953; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-sr-popover a { color: #7ddced; }\n.opportunities-extension-title-row {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px 16px;\n min-width: 0;\n flex: 1;\n}\n.opportunities-extension-title-row h1 {\n display: block;\n margin: 0;\n padding: 0;\n line-height: 1;\n}\n.opportunities-extension-title-row .opportunities-extension-subtitle-row {\n display: flex;\n align-items: center;\n align-self: center;\n flex-wrap: wrap;\n gap: 8px;\n margin: 0;\n padding: 0;\n min-width: 0;\n}\n.opportunities-extension-title-row .opportunities-extension-subtitle-row > span {\n box-sizing: border-box;\n margin: 0;\n min-height: 22px;\n line-height: 16px;\n}\n.opportunities-extension-title-row + .opportunities-extension-header-actions { flex-shrink: 0; }\n.opportunities-extension-refresh-all:disabled { opacity: .65; cursor: wait; }\n.opportunities-extension-refresh-all:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-refresh-all[aria-busy=\"true\"] svg { animation: opportunities-refresh-spin 1s linear infinite; }\n@keyframes opportunities-refresh-spin { to { transform: rotate(360deg); } }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-refresh-all[aria-busy=\"true\"] svg { animation: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-install-base-dialog {\n width: min(1700px, 100%);\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header {\n padding: 10px 12px;\n gap: 12px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header h2 {\n font-size: 16px;\n line-height: 22px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-account-plans-header p {\n font-size: 12px;\n line-height: 16px;\n margin-top: 3px;\n overflow-wrap: anywhere;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-icon-button {\n width: 28px;\n height: 28px;\n min-width: 28px;\n min-height: 28px;\n padding: 4px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-customer-table-toolbar {\n padding: 8px 12px;\n}\n.opportunities-extension-install-base-dialog .opportunities-extension-customer-table-search {\n width: min(320px, 100%);\n height: 32px;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 20px;\n}\n.opportunities-extension-install-base-content {\n min-width: 0;\n min-height: 0;\n overflow: auto;\n scrollbar-gutter: stable;\n}\n.opportunities-extension-install-base-message { margin: 10px 12px; font-size: 12px; line-height: 16px; }\n.opportunities-extension-install-base-table {\n width: 100%; min-width: 1120px; table-layout: fixed; border-collapse: collapse; font-size: 11px;\n}\n.opportunities-extension-install-base-table col { width: 7%; }\n.opportunities-extension-install-base-table .install-base-col-partyName { width: 12%; }\n.opportunities-extension-install-base-table .install-base-col-productGroupName { width: 13%; }\n.opportunities-extension-install-base-table .install-base-col-productName { width: 13%; }\n.opportunities-extension-install-base-table .install-base-col-quantity { width: 5%; }\n.opportunities-extension-install-base-table .install-base-col-quantityType { width: 8%; }\n.opportunities-extension-install-base-table th,\n.opportunities-extension-install-base-table td {\n padding: 8px 6px; text-align: left; vertical-align: middle; overflow-wrap: anywhere;\n border-bottom: 1px solid #e8e5e1; line-height: 1.4;\n}\n.opportunities-extension-install-base-table th { position: sticky; top: 0; z-index: 1; background: #faf9f8; }\n.opportunities-extension-install-base-table td[data-format=\"amount\"],\n.opportunities-extension-install-base-table td[data-format=\"quantity\"] { text-align: right; font-variant-numeric: tabular-nums; }\n.opportunities-extension-install-base-table td[data-format=\"date\"] { white-space: nowrap; }\n.opportunities-extension-install-base-status {\n display: inline-block; padding: 2px 5px; border-radius: 12px; font-size: 10px; font-weight: 600;\n color: #5f5a55; background: #eceae8; white-space: nowrap;\n}\n.opportunities-extension-install-base-status[data-status=\"ACTIVE\"] { color: #17693a; background: #e1f1e5; }\n.opportunities-extension-install-base-status[data-status=\"UNSUPPORTED\"] { color: #855300; background: #fff0d6; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-content,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table td { color: #f6f4f2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-message { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-message[role=\"alert\"] { color: #ffb4ab; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th { background: #353331; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-table td { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status[data-status=\"ACTIVE\"] { color: #b8e4c6; background: #214d34; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-install-base-status[data-status=\"UNSUPPORTED\"] { color: #ffdfa2; background: #614418; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-install-base-table .opportunities-extension-account-plans-skeleton-bar { animation: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-service-requests-dialog { width: min(1700px, 100%); }\n.opportunities-extension-service-requests-content { min-width: 0; min-height: 0; overflow: auto; scrollbar-gutter: stable; }\n.opportunities-extension-service-requests-message { margin: 16px; font-size: 13px; }\n.opportunities-extension-service-requests-table {\n width: 100%; min-width: 1200px; table-layout: fixed; border-collapse: collapse; font-size: 12px;\n}\n.opportunities-extension-service-requests-table col { width: 7%; }\n.opportunities-extension-service-requests-table .service-requests-col-name { width: 17%; }\n.opportunities-extension-service-requests-table .service-requests-col-id { width: 10%; }\n.opportunities-extension-service-requests-table .service-requests-col-severity { width: 5%; }\n.opportunities-extension-service-requests-table .service-requests-col-subStatus { width: 14%; }\n.opportunities-extension-service-requests-table .service-requests-col-productName { width: 12%; }\n.opportunities-extension-service-requests-table th,\n.opportunities-extension-service-requests-table td {\n padding: 12px 8px; text-align: left; vertical-align: middle; overflow-wrap: anywhere;\n border-bottom: 1px solid #e8e5e1; line-height: 1.4;\n}\n.opportunities-extension-service-requests-table th { position: sticky; top: 0; z-index: 1; background: #faf9f8; }\n.opportunities-extension-service-requests-table td[data-field=\"created\"],\n.opportunities-extension-service-requests-table td[data-field=\"lastUpdated\"],\n.opportunities-extension-service-requests-table td[data-field=\"id\"] { white-space: nowrap; font-variant-numeric: tabular-nums; }\n.opportunities-extension-service-request-status {\n display: inline-block; padding: 3px 6px; border-radius: 12px; font-size: 10px; font-weight: 600;\n color: #5f5a55; background: #eceae8;\n}\n.opportunities-extension-service-request-status[data-status=\"OPEN\"] { color: #17693a; background: #e1f1e5; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-content,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table td { color: #f6f4f2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-message { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-message[role=\"alert\"] { color: #ffb4ab; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th { background: #353331; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table th,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-requests-table td { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-request-status { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-service-request-status[data-status=\"OPEN\"] { color: #b8e4c6; background: #214d34; }\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-service-requests-table .opportunities-extension-account-plans-skeleton-bar { animation: none; }\n}\n\n/* Scope sizing to Cloud Consumption, not other dialogs sharing its components. */\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header { padding: 10px 12px; gap: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header h2 { font-size: 16px; line-height: 22px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-header p { font-size: 12px; line-height: 16px; margin-top: 3px; overflow-wrap: anywhere; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-icon-button { width: 28px; height: 28px; min-width: 28px; min-height: 28px; padding: 4px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-tabs { padding: 4px 12px 0; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-tab { min-height: 30px; padding: 4px 8px; font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-panel { padding: 8px 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details { gap: 0 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details > div { grid-template-columns: minmax(85px, 35%) minmax(0, 1fr); min-height: 32px; padding: 4px 0; gap: 6px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details dt { font-size: 11px; line-height: 16px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details dd { font-size: 12px; line-height: 16px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-trend { margin-top: 8px; padding-top: 6px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-periods button { min-height: 28px; padding: 4px 8px; font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation { grid-template-columns: 28px minmax(120px, auto) 28px; min-height: 30px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation strong { font-size: 12px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-navigation-button { width: 28px; height: 28px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-visual { grid-template-columns: minmax(0, 1fr) 150px; gap: 8px; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-svg { height: 100%; max-height: 100%; min-width: 0; }\n[data-consumption-layout=\"compact\"] .opportunities-extension-consumption-legend button { font-size: 11px; padding: 4px; gap: 5px; }\n\n/* Small viewports must scroll rather than clip details or collapse the chart. */\n@media (max-height: 560px), (max-width: 700px) {\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plans-panels { overflow: auto; }\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-panel { height: auto; min-height: 100%; grid-template-rows: auto minmax(280px, 1fr); }\n}\n@media (max-width: 700px) {\n [data-consumption-layout=\"compact\"] .opportunities-extension-account-plan-details { grid-template-columns: minmax(0, 1fr); }\n [data-consumption-layout=\"compact\"] .opportunities-extension-consumption-visual { grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr) auto; }\n [data-consumption-layout=\"compact\"] .opportunities-extension-consumption-legend { display: flex; flex-wrap: wrap; }\n}\n\n.opportunities-extension-plan-detail-badges { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }\n.opportunities-extension-consumption-trend-header { align-items: center; justify-content: space-between; gap: 12px; }\n.opportunities-extension-consumption-trend-header > .opportunities-extension-plan-detail-badges { min-width: 0; }\n.opportunities-extension-plan-detail-skeleton { width: 64px; height: 20px; }\n.opportunities-extension-projection-badge {\n display: inline-flex; align-items: center; justify-content: center; border: 1px solid transparent;\n padding: 3px 8px; border-radius: 12px; font-size: 11px; font-weight: 600; line-height: 1.3;\n color: #5f5a55; background: #eceae8; white-space: nowrap;\n}\nbutton.opportunities-extension-projection-badge { cursor: pointer; }\n.opportunities-extension-projection-badge[data-status=\"forfeit\"] { color: #a12424; background: #fbe5e5; }\n.opportunities-extension-projection-badge[data-status=\"overage\"] { color: #185a9d; background: #e0edfc; }\n.opportunities-extension-projection-badge:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }\n.opportunities-extension-projection-popover {\n position: fixed; z-index: 8; box-sizing: border-box; padding: 14px; overflow: auto; overscroll-behavior: contain;\n border: 1px solid #b9b4ae; border-radius: 4px; background: #ffffff; color: #312d2a;\n box-shadow: 0 4px 16px #0003; font-size: 12px; line-height: 1.4; overflow-wrap: anywhere;\n}\n.opportunities-extension-projection-popover[hidden] { display: none; }\n.opportunities-extension-projection-popover .opportunities-extension-projection-dismiss {\n display: grid; place-items: center; width: 24px; height: 24px; margin-left: auto; margin-bottom: 8px; padding: 4px; border: 1px solid #b9b4ae;\n border-radius: 4px; background: transparent; color: inherit; cursor: pointer; font-size: 12px;\n}\n.opportunities-extension-projection-dismiss svg { width: 14px; height: 14px; }\n.opportunities-extension-projection-line h3 { margin: 0 0 8px; font-size: 12px; }\n.opportunities-extension-projection-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 16px; margin: 0; }\n.opportunities-extension-projection-fields > div { min-width: 0; }\n.opportunities-extension-projection-fields dt { font-weight: 600; color: #5f5a55; font-size: 11px; }\n.opportunities-extension-projection-fields dd { margin: 2px 0 0; font-variant-numeric: tabular-nums; }\n.opportunities-extension-projection-fields a { color: #006d7a; text-decoration: underline; }\n.opportunities-extension-projection-children { margin-top: 14px; padding-left: 12px; border-left: 2px solid #dedbd7; }\n.opportunities-extension-projection-children > section + section { margin-top: 16px; }\n.opportunities-extension-plan-detail-error { color: #a12424; font-size: 12px; }\n.opportunities-extension-projection-empty { color: #5f5a55; font-size: 12px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-popover { color: #f1efec; background: #302e2b; border-color: #716b64; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge { color: #dedbd7; background: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge[data-status=\"forfeit\"] { color: #ffb9b9; background: #682e32; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-badge[data-status=\"overage\"] { color: #c5dfff; background: #224b76; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-fields dt,\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-empty { color: #cec9c2; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-projection-fields a { color: #76dbea; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-plan-detail-error { color: #ffb9b9; }\n@media (max-width: 480px) { .opportunities-extension-projection-fields { grid-template-columns: minmax(0, 1fr); } }\n@media (max-width: 480px) {\n .opportunities-extension-consumption-trend-header > .opportunities-extension-consumption-periods { grid-template-columns: repeat(2, minmax(0, 1fr)); }\n}\n@media (prefers-reduced-motion: reduce) { .opportunities-extension-plan-detail-skeleton { animation: none; } }\n\n.opportunities-extension-account-plan-details > .opportunities-extension-contract-row {\n align-items: center;\n}\n.opportunities-extension-contract-row > dt,\n.opportunities-extension-contract-row > dd,\n.opportunities-extension-contract-ratecard > span {\n line-height: 20px;\n}\n.opportunities-extension-contract-ratecard {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px 10px;\n}\n.opportunities-extension-ratecard-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n align-self: center;\n box-sizing: border-box;\n height: 28px;\n margin: 0;\n flex: 0 0 auto;\n padding: 0 8px;\n border: 1px solid #8aaeb9;\n border-radius: 4px;\n background: #fff;\n color: #006b80;\n font: inherit;\n font-size: 12px;\n font-weight: 600;\n line-height: 20px;\n cursor: pointer;\n}\n.opportunities-extension-ratecard-button:hover { background: #e8f4f6; }\n.opportunities-extension-ratecard-overlay {\n position: absolute;\n inset: 0;\n z-index: 8;\n display: flex;\n justify-content: flex-end;\n overflow: hidden;\n overflow: clip;\n background: rgba(0, 0, 0, 0);\n transition: background-color 320ms ease;\n}\n.opportunities-extension-ratecard-overlay[data-open=\"true\"] { background: rgba(0, 0, 0, .32); }\n.opportunities-extension-ratecard-drawer {\n --ratecard-bg: #fff;\n --ratecard-heading: #faf9f8;\n --ratecard-text: #312d2a;\n --ratecard-muted: #615a55;\n --ratecard-border: #dedbd8;\n --ratecard-accent: #00758f;\n --ratecard-skeleton: #eae7e4;\n display: grid;\n grid-template-rows: auto auto auto minmax(0, 1fr);\n width: min(1520px, calc(100% - 48px));\n height: 100%;\n min-width: 0;\n box-sizing: border-box;\n overflow: hidden;\n background: var(--ratecard-bg);\n color: var(--ratecard-text);\n box-shadow: -6px 0 24px rgba(0, 0, 0, .2);\n transform: translateX(100%);\n transition: transform 320ms cubic-bezier(.22, .61, .36, 1);\n}\n.opportunities-extension-ratecard-overlay[data-open=\"true\"] .opportunities-extension-ratecard-drawer { transform: translateX(0); }\n.opportunities-extension-ratecard-header > div { min-width: 0; overflow-wrap: anywhere; }\n.opportunities-extension-ratecard-plan-details { padding: 12px 20px 0; }\n.opportunities-extension-ratecard-toolbar { display: flex; align-items: center; gap: 16px; padding: 12px 20px; }\n.opportunities-extension-ratecard-search {\n width: min(360px, 100%);\n min-width: 0;\n box-sizing: border-box;\n padding: 9px 12px;\n border: 1px solid var(--ratecard-muted);\n border-radius: 4px;\n background: var(--ratecard-bg);\n color: var(--ratecard-text);\n font: inherit;\n font-size: 13px;\n}\n.opportunities-extension-ratecard-search::placeholder { color: var(--ratecard-muted); opacity: 1; }\n.opportunities-extension-ratecard-count { color: var(--ratecard-muted); font-size: 12px; white-space: nowrap; }\n.opportunities-extension-ratecard-viewport { overflow: auto; min-height: 0; min-width: 0; scrollbar-gutter: stable; }\n.opportunities-extension-ratecard-table { width: 100%; min-width: 1100px; table-layout: fixed; border-collapse: separate; border-spacing: 0; font-size: 12px; }\n.opportunities-extension-ratecard-table th, .opportunities-extension-ratecard-table td {\n padding: 11px 10px;\n border-bottom: 1px solid var(--ratecard-border);\n vertical-align: top;\n overflow-wrap: anywhere;\n text-align: left;\n}\n.opportunities-extension-ratecard-table th { position: sticky; top: 0; z-index: 1; background: var(--ratecard-heading); }\n.opportunities-extension-ratecard-sort {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 12px;\n align-items: center;\n gap: 5px;\n width: 100%;\n padding: 0;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-weight: 600;\n text-align: left;\n cursor: pointer;\n}\n.opportunities-extension-ratecard-sort-icon { color: var(--ratecard-accent); text-align: center; }\n.opportunities-extension-ratecard-table .opportunities-extension-ratecard-numeric { text-align: right; font-variant-numeric: tabular-nums; }\n.opportunities-extension-ratecard-table .opportunities-extension-ratecard-notice { padding: 28px 20px; text-align: center; }\n.opportunities-extension-ratecard-notice [role=\"alert\"] { color: #b3261e; }\n.opportunities-extension-ratecard-skeleton { display: block; width: 85%; height: 14px; border-radius: 3px; background: var(--ratecard-skeleton); animation: opportunities-ratecard-pulse 1.1s ease-in-out infinite alternate; }\n.opportunities-extension-ratecard-drawer :focus-visible, .opportunities-extension-ratecard-button:focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-ratecard-overlay[data-closing=\"true\"] { pointer-events: none; background: rgba(0, 0, 0, 0); transition-duration: 180ms; }\n.opportunities-extension-ratecard-overlay[data-closing=\"true\"] .opportunities-extension-ratecard-drawer { transform: translateX(100%); transition-duration: 180ms; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-drawer {\n --ratecard-bg: #292725;\n --ratecard-heading: #35322f;\n --ratecard-text: #f5f3f1;\n --ratecard-muted: #c2bcb6;\n --ratecard-border: #514c47;\n --ratecard-accent: #59d1e5;\n --ratecard-skeleton: #514c47;\n}\n[data-theme=\"dark\"] .opportunities-extension-ratecard-button { color: #59d1e5; border-color: #6298a2; background: #292725; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-button:hover { background: #313f40; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-notice [role=\"alert\"] { color: #ffb4ab; }\n[data-theme=\"dark\"] .opportunities-extension-ratecard-drawer :focus-visible, [data-theme=\"dark\"] .opportunities-extension-ratecard-button:focus-visible { outline-color: #59d1e5; }\n@keyframes opportunities-ratecard-pulse { from { opacity: .45; } to { opacity: 1; } }\n@media (max-width: 720px) {\n .opportunities-extension-ratecard-drawer { width: 100%; }\n .opportunities-extension-ratecard-toolbar { flex-wrap: wrap; gap: 8px; }\n}\n@media (prefers-reduced-motion: reduce) {\n .opportunities-extension-ratecard-overlay, .opportunities-extension-ratecard-drawer, .opportunities-extension-ratecard-skeleton,\n .opportunities-extension-ratecard-overlay[data-closing=\"true\"], .opportunities-extension-ratecard-overlay[data-closing=\"true\"] .opportunities-extension-ratecard-drawer { animation: none; transition: none; }\n}\n\n.opportunities-extension-account-plans-dialog.opportunities-extension-install-base-dialog,\n.opportunities-extension-account-plans-dialog.opportunities-extension-service-requests-dialog {\n grid-template-rows: auto auto minmax(0, 1fr);\n}\n.opportunities-extension-customer-table-toolbar { padding: 12px 16px; border-bottom: 1px solid #dedbd7; }\n.opportunities-extension-customer-table-search {\n box-sizing: border-box;\n width: min(420px, 100%);\n min-width: 0;\n height: 38px;\n padding: 8px 12px;\n border: 1px solid #8f8a85;\n border-radius: 4px;\n background: #fff;\n color: #312d2a;\n font: inherit;\n font-size: 13px;\n}\n.opportunities-extension-customer-table-search::placeholder { color: #5f5a55; opacity: 1; }\n.opportunities-extension-customer-table-search:focus-visible { outline: 2px solid #00758f; outline-offset: 2px; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-toolbar { border-color: #484541; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search { background: #353331; color: #f6f4f2; border-color: #8f8a85; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search::placeholder { color: #c9c5c1; }\n.opportunities-extension-modal[data-theme=\"dark\"] .opportunities-extension-customer-table-search:focus-visible { outline-color: #59d1e5; }\n"; // Source: src/shared/messages.js /** Stable wire names. All payloads remain plain, serializable objects. */ function createMessageTypes() { @@ -304,6 +304,71 @@ function createOpportunitiesColumns({ formatOracleResponseDate, formatRevenue, f ]; } +// Source: src/features/opportunities/badge-content.js +/* + * Lucide icons: package, chart-no-axes-column-increasing, clipboard-list, list-checks. + * https://github.com/lucide-icons/lucide (ISC License) + * Copyright (c) 2026 Lucide Icons and Contributors + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +function createOpportunityBadgeContent({ environment }) { + const shapes = { + products: [ + ["path", { d: "M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z" }], + ["path", { d: "M12 22V12" }], + ["polyline", { points: "3.29 7 12 12 20.71 7" }], + ["path", { d: "m7.5 4.27 9 5.15" }] + ], + ramp: [ + ["path", { d: "M5 21v-6" }], + ["path", { d: "M12 21V9" }], + ["path", { d: "M19 21V3" }] + ], + sr: [ + ["rect", { width: "8", height: "4", x: "8", y: "2", rx: "1", ry: "1" }], + ["path", { d: "M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" }], + ["path", { d: "M12 11h4" }], + ["path", { d: "M12 16h4" }], + ["path", { d: "M8 11h.01" }], + ["path", { d: "M8 16h.01" }] + ], + actions: [ + ["path", { d: "M13 5h8" }], + ["path", { d: "M13 12h8" }], + ["path", { d: "M13 19h8" }], + ["path", { d: "m3 17 2 2 4-4" }], + ["path", { d: "m3 7 2 2 4-4" }] + ] + }; + function setContent(badge, kind, value) { + badge.textContent = String(value); + const namespace = "http://www.w3.org/2000/svg"; + const icon = environment.document.createElementNS(namespace, "svg"); + for (const [name, attribute] of Object.entries({ + class: "opportunities-extension-badge-icon", viewBox: "0 0 24 24", + width: "16", height: "16", fill: "none", stroke: "currentColor", + "stroke-width": "2.25", "stroke-linecap": "round", "stroke-linejoin": "round", + "aria-hidden": "true", focusable: "false", "data-badge-icon": kind + })) icon.setAttribute(name, attribute); + for (const [tag, attributes] of shapes[kind]) { + const shape = environment.document.createElementNS(namespace, tag); + for (const [name, attribute] of Object.entries(attributes)) shape.setAttribute(name, attribute); + icon.append(shape); + } + badge.append(icon); + } + return { setContent }; +} + // Source: src/content/fusion-page.js function createContentFusionPage({ ADD_ICON_SELECTOR, @@ -444,6 +509,7 @@ function createContentModal({ closeAccountPlansModal, closeInstallBaseModal, closeServiceRequestsModal, + closeActionForm, closeCustomerFilterPanel, closeOwnerFilterPanel, closePreferencesModal, @@ -886,6 +952,7 @@ function createContentModal({ closeAccountPlansModal(); closeInstallBaseModal(); closeServiceRequestsModal(); + closeActionForm(false); modal.hidden = true; } @@ -914,6 +981,10 @@ function createContentModal({ } if (event.key === "Escape") { + if (closeActionForm()) { + event.preventDefault(); + return; + } if (closeServiceRequestsModal()) { event.preventDefault(); return; @@ -1928,6 +1999,7 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest, async function requestCrmServiceRequest(token, version, isActive = () => isCurrentPeriodRequest(version), onProgress = () => {}) { const items = []; let offset = 0; + let attempt = 1; while (isActive()) { const payload = createPayload(offset); const headers = { @@ -1935,31 +2007,33 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest, Origin: "https://eeho.fa.us2.oraclecloud.com", Preference: "transient" }; const entry = logRequestStart({ name: "resquestCrmServiceRequest", method: "POST", url, - headers: { ...headers, Authorization: `Bearer ${maskToken(token)}` }, body: JSON.stringify(payload, null, 2), metadata: { offset } }); + headers: { ...headers, Authorization: `Bearer ${maskToken(token)}` }, body: JSON.stringify(payload, null, 2), metadata: { offset, attempt } }); try { const response = await fetch(url, { method: "POST", credentials: "include", headers, body: JSON.stringify(payload) }); logRequestSuccess(entry, response, await readResponseBodyForDebug(response)); - if (!response.ok) throw new Error(`CRM service request query failed with status ${response.status}.`); + if (response.status !== 200) throw new Error(`CRM service request query failed with status ${response.status}.`); const data = await response.json(); if (!data || !Array.isArray(data.items) || typeof data.hasMore !== "boolean") { throw new Error("CRM service request query returned an invalid response."); } if (!isActive()) return null; + const received = data.count === undefined ? data.items.length : Number(data.count); + const current = data.offset === undefined ? offset : Number(data.offset); + if (data.hasMore && (!data.items.length || !Number.isInteger(received) || received <= 0 || !Number.isInteger(current) + || current !== offset || current + received <= offset)) { + throw new Error("CRM service request pagination did not advance."); + } items.push(...data.items); onProgress(items.length, Number.isFinite(data.totalResults) && data.totalResults >= items.length ? data.totalResults : null); if (!data.hasMore) return items; - const received = data.count === undefined ? data.items.length : Number(data.count); - const current = data.offset === undefined ? offset : Number(data.offset); - if (!data.items.length || !Number.isInteger(received) || received <= 0 || !Number.isInteger(current) - || current !== offset || current + received <= offset) { - throw new Error("CRM service request pagination did not advance."); - } offset = current + received; + attempt = 1; } catch (error) { logRequestFailure(entry, error.message || "CRM service request query failed."); - throw error; + if (attempt === 5) throw error; + attempt += 1; } } return null; @@ -1968,15 +2042,23 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest, } // Source: src/features/opportunities/crm-service-requests.js -function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, allowsCrmActivities, reportProgress, activityCache, environment }) { +function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, allowsCrmActivities, reportProgress, activityCache, setBadgeContent, environment }) { let status = "idle"; let byOpportunity = new Map(); let pending = null; let generation = 0; - function reset() { closePopover(); generation += 1; pending = null; status = "idle"; byOpportunity = new Map(); reportProgress("idle"); } + let loadedItems = []; + function reset() { closePopover(); generation += 1; pending = null; status = "idle"; byOpportunity = new Map(); loadedItems = []; reportProgress("idle"); } function load(token, version, cacheOptions = null) { if (!allowsCrmActivities() || !isCurrentPeriodRequest(version)) return; - if (!pending) pending = run(token, version, generation, cacheOptions); + if (status === "ready") { + return Promise.resolve(cacheOptions ? activityCache.write("sr", "all", cacheOptions.cachedAt, loadedItems) : undefined).then(() => true); + } + if (!pending) { + const request = run(token, version, generation, cacheOptions); + pending = request; + request.finally(() => { if (pending === request) pending = null; }); + } return pending; } async function run(token, version, currentGeneration, cacheOptions) { @@ -1984,8 +2066,8 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre status = "loading"; try { const cached = cacheOptions ? await activityCache.read("sr", "all", cacheOptions.cachedAt) : null; - if (!isActive()) return; - if (!cached && cacheOptions?.cacheOnly) { status = "idle"; return; } + if (!isActive()) return false; + if (!cached && cacheOptions?.cacheOnly) { status = "idle"; return false; } let items = cached?.items; if (!items) { reportProgress("running", 0); @@ -1994,7 +2076,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre }); if (items && isActive() && cacheOptions) await activityCache.write("sr", "all", cacheOptions.cachedAt, items); } - if (!items || !isActive()) return; + if (!items || !isActive()) return false; const grouped = new Map(); for (const item of items) { const number = item?.OpportunityName_Id_c?.OptyNumber; @@ -2004,10 +2086,13 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre grouped.get(key).push(item); } byOpportunity = grouped; + loadedItems = items; status = "ready"; if (!cached) reportProgress("complete", items.length, items.length); + return true; } catch { if (isActive()) { status = "error"; reportProgress("error"); } + return false; } } function getSummary(optyNumber) { @@ -2032,7 +2117,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre const reportedHours = summary.reportedHours !== null ? new Intl.NumberFormat("en-US", { useGrouping: false, maximumFractionDigits: 10 }).format(summary.reportedHours) : "N/D"; - badge.textContent = status === "error" ? "SR ?" : items.length ? `\u2705 SR (${reportedHours}${reportedHours === "N/D" ? "" : "h"})` : "\u26d4 SR"; + setBadgeContent(badge, "sr", status === "error" ? "?" : items.length ? `${reportedHours}${reportedHours === "N/D" ? "" : "h"}` : "0h"); const display = value => value === null || value === undefined || value === "" ? "N/D" : String(value); const descriptions = items.map(item => [ `Title: ${display(item.Title)}`, @@ -2046,8 +2131,8 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre : !items.length ? "No matching CRM service request with status SVC_PENDING_DELIVERY in your SR team." : items.map((item, index) => `SR Number: ${display(item.SrNumber)}\n${descriptions[index]}`).join("\n\n"); badge.setAttribute("aria-label", description); + badge.title = "Whether a Service Request has been created for the opportunities."; if (items.length && status === "ready") bindPopover(badge, items, descriptions); - else badge.title = description; badge.tabIndex = 0; return badge; } @@ -2055,8 +2140,8 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre } // Source: src/features/opportunities/product-activities.js -function createProductActivities({ productsContentState, opportunitiesQueryState, resetCrm, - loadCrm, loadActions, render }) { +function createProductActivities({ productsContentState, opportunitiesQueryState, + loadCrm, loadActions, blockActions, render }) { let cycle = null; function begin(requestId, token) { cycle = { requestId, token, version: opportunitiesQueryState.periodRequestVersion, completed: false }; @@ -2068,26 +2153,32 @@ function createProductActivities({ productsContentState, opportunitiesQueryState current.completed = true; const products = [...productsContentState.opptyProductsByNumber.values()].filter(result => !result.error); if (!products.length) return; - resetCrm(); - const pending = []; - const seen = new Set(); - for (const result of products) { - const items = result.items.filter(item => { - const id = String(item?.RevnId ?? ""); - if (seen.has(id)) return false; - seen.add(id); - return true; - }); - pending.push(loadActions({ ...result, items }, true, { cachedAt: result.cachedAt, cacheOnly: result.fromCache === true })); - } const cachedAt = Math.max(...products.map(result => Number(result.cachedAt) || 0)); - pending.push(loadCrm(current.token, current.version, { cachedAt, cacheOnly: products.every(result => result.fromCache) })); - return Promise.allSettled(pending).then(() => { - if (cycle !== current || productsContentState.currentProductsRequestId !== requestId - || opportunitiesQueryState.periodRequestVersion !== current.version) return; + const isActive = () => cycle === current && productsContentState.currentProductsRequestId === requestId + && opportunitiesQueryState.periodRequestVersion === current.version; + return Promise.resolve(loadCrm(current.token, current.version, { cachedAt, cacheOnly: products.every(result => result.fromCache) })).then(async success => { + if (!isActive()) return; + if (success === false) { + products.forEach(blockActions); + render(); + return; + } + const pending = []; + const seen = new Set(); + for (const result of products) { + const items = result.items.filter(item => { + const id = String(item?.RevnId ?? ""); + if (seen.has(id)) return false; + seen.add(id); + return true; + }); + pending.push(loadActions({ ...result, items }, true, { cachedAt: result.cachedAt, cacheOnly: result.fromCache === true })); + } + await Promise.allSettled(pending); + if (!isActive()) return; if (cachedAt > 0) productsContentState.productsLastCachedAt = cachedAt; render(); - }).catch(() => {}); + }).catch(() => { if (isActive()) { products.forEach(blockActions); render(); } }); } return { begin, complete }; } @@ -2253,7 +2344,7 @@ function createActivityProgress({ MODAL_ID, environment }) { } // Source: src/features/opportunities/activity-filters.js -function createActivityFilters({ allowsCrmActivities, getSrSummary, getActionSummary, renderTable, environment }) { +function createActivityFilters({ allowsCrmActivities, getSrSummary, getActionSummary, renderTable, setBadgeContent, environment }) { const selections = { sr: new Set(["matched", "missing"]), actions: new Set(["matched", "missing"]) }; let container = null; let form = null; @@ -2267,24 +2358,32 @@ function createActivityFilters({ allowsCrmActivities, getSrSummary, getActionSum container = environment.document.createElement("div"); container.className = "opportunities-extension-badge-filters"; for (const [kind, title, options] of [ - ["sr", "Service Request", [["matched", "\u2705 SR"], ["under4", "\u2705 SR < 4h"], ["missing", "\u26d4 SR"]]], - ["actions", "Actions", [["matched", "\u2705 Action"], ["missing", "\u26d4 Action"]]] + ["sr", "Service Request", ["matched", "under4", "missing"]], + ["actions", "Act", ["matched", "missing"]] ]) { const section = environment.document.createElement("section"); section.className = "opportunities-extension-activity-filter"; const label = environment.document.createElement("span"); label.textContent = title; + const tooltip = kind === "sr" + ? "Whether a Service Request has been created for the opportunities." + : "Whether the Action is registered in Workload Workbench."; + label.title = tooltip; const controls = environment.document.createElement("div"); controls.className = "opportunities-extension-activity-filter-controls"; controls.setAttribute("role", "group"); controls.setAttribute("aria-label", `Filter by ${title}`); - for (const [value, text] of options) { + for (const value of options) { const button = environment.document.createElement("button"); button.type = "button"; button.className = "opportunities-extension-activity-filter-button"; button.setAttribute("data-value", value); - button.textContent = text; - if (value === "under4") button.title = "At least one SR with reported hours below 4; replaces other SR filters."; + setBadgeContent(button, kind, value === "under4" ? "< 4h" : ""); + const description = value === "under4" + ? "At least one SR with reported hours below 4; replaces other SR filters." + : `${kind === "sr" ? "Service Request" : "Action"} ${value === "matched" ? "registered" : "not registered"}`; + button.title = `${tooltip}\n${description}`; + button.setAttribute("aria-label", description); button.addEventListener("click", () => toggle(kind, value)); buttons.push({ button, kind, value }); controls.append(button); @@ -2469,7 +2568,7 @@ function createCrmSrPopover({ MODAL_ID, createCopyButton, createCloseIcon, envir // Source: src/features/opportunities/workload-actions.js function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivities, requestConsumerTokenServiceOnce, sendRuntimeMessage, - appendBackgroundRequestLog, queueProductsTableRender, productsContentState, messageTypes, reportProgress, activityCache, environment }) { + appendBackgroundRequestLog, queueProductsTableRender, productsContentState, messageTypes, reportProgress, activityCache, createActionButton, closeActionForm, setBadgeContent, environment }) { let session = newSession(); function newSession() { return { enabled: true, records: new Map(), queue: [], running: 0, progress: new Set() }; } function updateProgress(current) { @@ -2480,6 +2579,7 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie reportProgress(completed < records.length ? "running" : failed ? "complete-with-errors" : "complete", completed, records.length); } function reset(enabled = true) { + closeActionForm(false); session.enabled = false; for (const job of session.queue) job.record.resolveCompletion(); session.queue.length = 0; @@ -2516,6 +2616,12 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie for (const products of productsContentState.opptyProductsByNumber.values()) loadProducts(products); queueProductsTableRender(); } + function blockProducts(products) { + if (!allowsCrmActivities()) return; + for (const id of idsFor(products)) { + session.records.set(id, { status: "error", actions: [], hasNext: false, error: "CRM service requests unavailable." }); + } + } function pump(current) { while (current.enabled && current === session && current.running < 4 && current.queue.length) { const job = current.queue.shift(); @@ -2536,12 +2642,21 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie if (cacheOptions?.cacheOnly) { record.status = "error"; record.error = "No matching activity cache for this product update."; return; } current.progress.add(record); updateProgress(current); - const authorizations = await requestConsumerTokenServiceOnce(); - if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; - const result = await sendRuntimeMessage({ type: messageTypes.requestWlActions, revnId, authorization: authorizations?.workloadActions }); - if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; - appendBackgroundRequestLog(result?.debugRequests); - if (!result?.ok) throw new Error(result?.error || "Unable to load workload actions."); + let result; + for (let attempt = 1; attempt <= 5; attempt += 1) { + try { + if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; + const authorizations = await requestConsumerTokenServiceOnce(); + if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; + result = await sendRuntimeMessage({ type: messageTypes.requestWlActions, revnId, authorization: authorizations?.workloadActions }); + if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; + appendBackgroundRequestLog(result?.debugRequests); + if (!result?.ok) throw new Error(result?.error || "Unable to load workload actions."); + break; + } catch (error) { + if (attempt === 5) throw error; + } + } record.actions = result.actions; record.hasNext = result.hasNext; record.status = "ready"; @@ -2577,7 +2692,7 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie const badge = environment.document.createElement("span"); badge.className = "opportunities-extension-crm-sr-badge opportunities-extension-wl-actions-badge"; badge.setAttribute("data-state", state); - badge.textContent = state === "matched" ? "\u2705 Act" : state === "missing" ? "\u26d4 Act" : state === "loading" ? "Act ..." : "Act ?"; + setBadgeContent(badge, "actions", state === "matched" || state === "missing" ? actions.length : state === "loading" ? "..." : "?"); badge.title = actions.length ? actions.map(action => [ `Action: ${action.name ?? "N/D"}`, `ID: ${action.id ?? "N/D"}`, `Status: ${action.status ?? "N/D"}`, `Owner: ${action.owner || "N/D"}`, `Email: ${action.ownerEmail || "N/D"}`, `Workload: ${action.workloadName || "N/D"}`, @@ -2590,9 +2705,123 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie if (actions.length && (pending || uncertain)) badge.title += "\nSome workloads are still loading or could not be fully checked."; badge.tabIndex = 0; badge.setAttribute("aria-label", badge.title); + if (state === "missing") badge.append(createActionButton(String(optyNumber))); return badge; } - return { reset, reopen, loadProducts, createBadge, getSummary }; + return { reset, reopen, loadProducts, blockProducts, createBadge, getSummary }; +} + +// Source: src/features/opportunities/workload-action-form.js +function createWorkloadActionForm({ MODAL_ID, allowsCrmActivities, isMissingAction, getOpportunity, formatDate, createCloseIcon, environment }) { + const { document } = environment; + let active = null; + function element(tag, className, text) { + const node = document.createElement(tag); + if (className) node.className = className; + if (text !== undefined) node.textContent = text; + return node; + } + function close(restoreFocus = true) { + if (!active) return false; + const previous = active; + active = null; + previous.modal.remove(); + if (restoreFocus && previous.trigger?.isConnected) previous.trigger.focus(); + return true; + } + function createButton(optyNumber) { + const button = element("button", "opportunities-extension-add-action", "+"); + button.type = "button"; + button.title = "Add Action"; + button.setAttribute("aria-label", `Add Action for ${optyNumber}`); + button.setAttribute("aria-haspopup", "dialog"); + button.addEventListener("click", event => { + event.preventDefault(); + event.stopPropagation(); + open(optyNumber, button); + }); + return button; + } + function open(optyNumber, trigger) { + if (!allowsCrmActivities() || !isMissingAction(optyNumber)) return; + const host = document.getElementById(MODAL_ID); + if (!host || host.hidden) return; + close(false); + const modal = element("section", "opportunities-extension-action-form-modal"); + modal.setAttribute("role", "dialog"); + modal.setAttribute("aria-modal", "true"); + modal.setAttribute("aria-labelledby", "opportunities-extension-action-form-title"); + const dialog = element("div", "opportunities-extension-action-form-dialog"); + const header = element("header", "opportunities-extension-account-plans-header"); + const heading = element("div", "opportunities-extension-action-form-heading"); + const title = element("h2", "", "Add Action"); + title.id = "opportunities-extension-action-form-title"; + heading.append(title, element("p", "", String(optyNumber))); + const opportunity = getOpportunity(optyNumber); + const details = element("dl", "opportunities-extension-action-form-context"); + for (const [label, value] of [ + ["Customer", opportunity?.CustomerAccount?.PartyUniqueName], + ["Name", opportunity?.Name], + ["Close Date", formatDate(opportunity?.EffectiveDate)] + ]) { + details.append(element("dt", "", label), element("dd", "", value == null || value === "" ? "-" : String(value))); + } + heading.append(details); + const dismiss = element("button", "opportunities-extension-icon-button"); + dismiss.type = "button"; + dismiss.title = "Close"; + dismiss.setAttribute("aria-label", "Close Action form"); + dismiss.append(createCloseIcon()); + dismiss.addEventListener("click", () => close()); + header.append(heading, dismiss); + const form = element("form", "opportunities-extension-action-form"); + // Form-only version: never submit or navigate until the API contract is provided. + form.addEventListener("submit", event => event.preventDefault()); + const fields = []; + for (const [name, label, type] of [ + ["team", "Team", "text"], ["startDate", "Start date", "date"], + ["endDate", "End Date", "date"], ["status", "Status", "text"], + ["complexity", "Complexity", "text"], ["notes", "Notes", "textarea"] + ]) { + const field = element("label", "opportunities-extension-action-form-field"); + const input = element(type === "textarea" ? "textarea" : "input"); + if (type !== "textarea") input.type = type; + else input.rows = 5; + input.name = name; + input.id = `opportunities-extension-action-form-${name}`; + field.htmlFor = input.id; + if (name === "notes" || name === "team") field.className += " opportunities-extension-action-form-wide"; + field.append(element("span", "", label), input); + form.append(field); + fields.push(input); + } + const footer = element("footer", "opportunities-extension-action-form-footer"); + const save = element("button", "opportunities-extension-action-form-save", "Save"); + save.type = "submit"; + save.disabled = true; + save.title = "Gravacao ainda nao disponivel"; + const cancel = element("button", "", "Cancel"); + cancel.type = "button"; + cancel.addEventListener("click", () => close()); + footer.append(save, cancel); + form.append(footer); + dialog.append(header, form); + modal.append(dialog); + host.append(modal); + active = { modal, trigger }; + modal.addEventListener("click", event => { if (event.target === modal) close(); }); + modal.addEventListener("keydown", event => { + if (event.key !== "Tab") return; + const controls = [dismiss, ...fields, cancel]; + const index = controls.indexOf(document.activeElement); + if (index === -1 || (!event.shiftKey && index === controls.length - 1) || (event.shiftKey && index === 0)) { + event.preventDefault(); + controls[event.shiftKey ? controls.length - 1 : 0].focus(); + } + }); + fields[0].focus(); + } + return { createButton, open, close }; } // Source: src/features/opportunities/fiscal-periods.js @@ -2756,7 +2985,7 @@ function createOpportunitiesTable({ const tableBody = document.createElement("tbody"); const items = getSortedOpportunities(); - renderStageDashboard(items); + renderStageDashboard(items, opportunitiesTableState.opportunitiesTableState.items.length); if (opportunitiesTableState.opportunitiesTableState.status === "loading" || opportunitiesTableState.opportunitiesTableState.status === "error" || opportunitiesTableState.opportunitiesTableState.status === "empty" || (opportunitiesTableState.opportunitiesTableState.status === "ready" && items.length === 0)) { const row = document.createElement("tr"); @@ -2862,7 +3091,7 @@ function createOpportunitiesDashboard({ environment }) { const { document, requestAnimationFrame, performance } = environment; - function renderStageDashboard(items) { + function renderStageDashboard(items, totalCount = items.length) { const dashboard = document.getElementById(STAGE_DASHBOARD_ID); if (!dashboard) { @@ -2879,12 +3108,12 @@ function createOpportunitiesDashboard({ totalCard.setAttribute("data-stage", "TOTAL"); totalLabel.textContent = "Total Opportunities"; totalValue.className = "opportunities-extension-stage-dashboard-value"; - totalValue.setAttribute("aria-label", "Total opportunities"); + totalValue.setAttribute("aria-label", `${items.length} filtered opportunities out of ${totalCount} total`); animateStageDashboardValue( totalValue, "TOTAL", items.length, - (amount) => Math.round(amount).toLocaleString() + (amount) => `${Math.round(amount).toLocaleString()}/${totalCount.toLocaleString()}` ); totalCard.append(totalLabel, totalValue); dashboard.append(totalCard); @@ -3313,11 +3542,14 @@ function createOpportunitiesFilters({ function getSortedOpportunities() { const normalizedSearch = opportunitiesFilterState.tableSearch.trim().toLocaleLowerCase(); + const allStages = STAGE_OPTIONS.every(stage => opportunitiesFilterState.selectedStages.has(stage)); + const allCustomers = getCustomerOptions().every(option => opportunitiesFilterState.selectedCustomerKeys.has(option.key)); + const allOwners = getOwnerOptions().every(option => opportunitiesFilterState.selectedOwnerKeys.has(option.key)); const items = opportunitiesTableState.opportunitiesTableState.items.filter((item) => { - return opportunitiesFilterState.selectedStages.has(item.ForecastGroup_c) + return (allStages || opportunitiesFilterState.selectedStages.has(item.ForecastGroup_c)) && matchesSelectedStatus(item.StatusCode) - && opportunitiesFilterState.selectedCustomerKeys.has(getCustomerKey(item)) - && opportunitiesFilterState.selectedOwnerKeys.has(getOwnerKey(item)) + && (allCustomers || opportunitiesFilterState.selectedCustomerKeys.has(getCustomerKey(item))) + && (allOwners || opportunitiesFilterState.selectedOwnerKeys.has(getOwnerKey(item))) && matchesTableSearch(item, normalizedSearch) && matchesActivities(item); }); @@ -3370,6 +3602,7 @@ function createOpportunitiesFilters({ } function matchesSelectedStatus(statusCode) { + if (STATUS_OPTIONS.every(status => opportunitiesFilterState.selectedStatuses.has(status))) return true; if (statusCode === "WON_PENDING") { return opportunitiesFilterState.selectedStatuses.has("WON"); } @@ -3462,7 +3695,7 @@ function createOpportunitiesFormatters({ (items || opportunitiesTableState.opportunitiesTableState.items).forEach((item) => { const key = getOwnerKey(item); - const label = getOwnerName(item); + const label = String(getOwnerName(item)).trim() || "-"; if (key && label && !optionsByKey.has(key)) { optionsByKey.set(key, { key, label: String(label) }); @@ -3479,7 +3712,9 @@ function createOpportunitiesFormatters({ function getOwnerKey(item) { const owner = item.Owner; const partyId = owner && typeof owner === "object" ? owner.PartyId : ""; - const name = getOwnerName(item); + const name = String(getOwnerName(item)).trim(); + + if (!name) return "owner:unassigned"; if (partyId !== null && partyId !== undefined && partyId !== "") { return `party:${partyId}`; @@ -4178,6 +4413,7 @@ function createProductsContentJobs({ // Source: src/features/products/details.js function createProductsDetails({ OPPORTUNITIES_COLUMNS, + setBadgeContent, createAiSummaryAlert, formatOracleResponseDate, productsContentState, @@ -4195,7 +4431,7 @@ function createProductsDetails({ const badge = document.createElement("span"); badge.className = "opportunities-extension-products-ramp"; badge.setAttribute("data-missing", String(values.includes("N/D"))); - badge.textContent = `RM ${values.join(",")}`; + setBadgeContent(badge, "ramp", values.join(",")); badge.title = `Ramp Months: ${values.join(", ")}`; badge.setAttribute("aria-label", badge.title); return badge; @@ -4209,7 +4445,7 @@ function createProductsDetails({ button.type = "button"; button.className = "opportunities-extension-products-count"; - button.textContent = String(count); + setBadgeContent(button, "products", count); button.setAttribute("aria-expanded", String(isExpanded)); button.setAttribute("aria-label", `${count} product${count === 1 ? "" : "s"} for opportunity ${normalizedOptyNumber}`); button.title = productsResult.error ? productsResult.error : `${count} product${count === 1 ? "" : "s"}`; @@ -7266,6 +7502,7 @@ function createContentApplication(overrides = {}) { environment }); const contentModal = createContentModal({ + closeActionForm: (...args) => workloadActionForm.close(...args), createActivityFilterControls: (...args) => activityFilters.createControls(...args), closeCrmSrPopover: () => crmSrPopover.close(), ensureCurrentUser: () => currentUser.ensure(), @@ -7431,7 +7668,9 @@ function createContentApplication(overrides = {}) { createCopyButton: (...args) => opportunitiesLinks.createCopyOpportunityButton(...args), createCloseIcon: (...args) => contentIcons.createCloseIcon(...args), environment }); + const opportunityBadgeContent = createOpportunityBadgeContent({ environment }); const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), activityCache, reportProgress: (...args) => activityProgress.update("sr", ...args), allowsCrmActivities: () => currentUser.allowsCrmActivities(), @@ -7567,6 +7806,7 @@ function createContentApplication(overrides = {}) { }); const activityProgress = createActivityProgress({ MODAL_ID: contracts.MODAL_ID, environment }); const activityFilters = createActivityFilters({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), allowsCrmActivities: () => currentUser.allowsCrmActivities(), getSrSummary: number => opportunityCrmServiceRequests.getSummary(number), getActionSummary: number => opportunityWorkloadActions.getSummary(number), @@ -7575,9 +7815,9 @@ function createContentApplication(overrides = {}) { }); const productActivities = createProductActivities({ productsContentState, opportunitiesQueryState, - resetCrm: () => opportunityCrmServiceRequests.reset(), loadCrm: (...args) => opportunityCrmServiceRequests.load(...args), loadActions: (...args) => opportunityWorkloadActions.loadProducts(...args), + blockActions: products => opportunityWorkloadActions.blockProducts(products), render: () => { productsContentJobs.renderProductsProgress(); productsContentJobs.queueProductsTableRender(); @@ -7597,7 +7837,19 @@ function createContentApplication(overrides = {}) { sendRuntimeMessage: (...args) => platformContentMessages.sendRuntimeMessage(...args), environment }); + const workloadActionForm = createWorkloadActionForm({ + getOpportunity: number => opportunitiesTableState.opportunitiesTableState.items.find(item => String(item.OptyNumber) === String(number)), + formatDate: value => opportunitiesFormatters.formatOracleResponseDate(value), + MODAL_ID: contracts.MODAL_ID, + allowsCrmActivities: () => currentUser.allowsCrmActivities(), + isMissingAction: number => opportunityWorkloadActions.getSummary(number)?.state === "missing", + createCloseIcon: () => contentIcons.createCloseIcon(), + environment + }); const opportunityWorkloadActions = createOpportunityWorkloadActions({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), + createActionButton: number => workloadActionForm.createButton(number), + closeActionForm: (...args) => workloadActionForm.close(...args), activityCache, reportProgress: (...args) => activityProgress.update("actions", ...args), allowsCrmActivities: () => currentUser.allowsCrmActivities(), @@ -7609,6 +7861,7 @@ function createContentApplication(overrides = {}) { productsContentState, messageTypes, environment }); const productsDetails = createProductsDetails({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), OPPORTUNITIES_COLUMNS: columns, createAiSummaryAlert: (...args) => aiSummaryContent.createAiSummaryAlert(...args), formatOracleResponseDate: (...args) => opportunitiesFormatters.formatOracleResponseDate(...args), @@ -7772,6 +8025,7 @@ function createContentApplication(overrides = {}) { startContentApplication({ environment, page: contentFusionPage, styles: contentStyles, products: productsContentJobs }); } return { + workloadActionForm, activityFilters, start, contracts, opportunityWorkloadActions, diff --git a/scripts/sources.cjs b/scripts/sources.cjs index c703768..87afd1a 100644 --- a/scripts/sources.cjs +++ b/scripts/sources.cjs @@ -16,6 +16,7 @@ module.exports = { "src/features/opportunities/dashboard-state.js", "src/features/debug/state.js", "src/features/opportunities/columns.js", + "src/features/opportunities/badge-content.js", "src/content/fusion-page.js", "src/content/modal.js", "src/content/theme.js", @@ -39,6 +40,7 @@ module.exports = { "src/features/opportunities/activity-filters.js", "src/features/opportunities/crm-sr-popover.js", "src/features/opportunities/workload-actions.js", + "src/features/opportunities/workload-action-form.js", "src/features/opportunities/fiscal-periods.js", "src/features/opportunities/table.js", "src/features/opportunities/dashboard.js", diff --git a/src/auth/consumer-session.js b/src/auth/consumer-session.js index f26bd2e..c9e0a59 100644 --- a/src/auth/consumer-session.js +++ b/src/auth/consumer-session.js @@ -103,14 +103,22 @@ function createAuthConsumerSession({ const isHtmlFallback = error && error.code === "INVALID_JSON_RESPONSE" && error.httpStatus === 200; + const isSessionUnauthorized = error && (error.httpStatus === 401 || error.httpStatus === 403); + const needsSessionRecovery = isHtmlFallback || isSessionUnauthorized; + const retryReason = isSessionUnauthorized + ? `HTTP ${error.httpStatus} response requires SPA session recovery` + : "HTTP 200 response did not contain valid JSON"; const debugEntry = debugRequests[debugRequests.length - 1]; - if (!isHtmlFallback || attempt >= CUSTOMER_TOKEN_MAX_ATTEMPTS) { + if (!needsSessionRecovery || attempt >= CUSTOMER_TOKEN_MAX_ATTEMPTS) { if (debugEntry) { debugEntry.metadata.attempt = String(attempt); - if (isHtmlFallback) { + if (needsSessionRecovery) { debugEntry.metadata.retryLimitReached = "true"; - debugEntry.error = `requestConsumerTokenService returned invalid JSON after ${CUSTOMER_TOKEN_MAX_ATTEMPTS} attempts.`; + debugEntry.metadata.retryReason = retryReason; + debugEntry.error = isHtmlFallback + ? `requestConsumerTokenService returned invalid JSON after ${CUSTOMER_TOKEN_MAX_ATTEMPTS} attempts.` + : `requestConsumerTokenService failed with status ${error.httpStatus} after ${CUSTOMER_TOKEN_MAX_ATTEMPTS} attempts.`; error.message = debugEntry.error; } } @@ -138,7 +146,7 @@ function createAuthConsumerSession({ const retryDelayMs = getConsumerTokenRetryDelay(attempt); if (debugEntry) { debugEntry.metadata.attempt = String(attempt); - debugEntry.metadata.retryReason = "HTTP 200 response did not contain valid JSON"; + debugEntry.metadata.retryReason = retryReason; debugEntry.metadata.nextRetryDelayMs = String(retryDelayMs); } diff --git a/src/content/application.js b/src/content/application.js index 1dea28f..6f321c0 100644 --- a/src/content/application.js +++ b/src/content/application.js @@ -55,6 +55,7 @@ function createContentApplication(overrides = {}) { environment }); const contentModal = createContentModal({ + closeActionForm: (...args) => workloadActionForm.close(...args), createActivityFilterControls: (...args) => activityFilters.createControls(...args), closeCrmSrPopover: () => crmSrPopover.close(), ensureCurrentUser: () => currentUser.ensure(), @@ -220,7 +221,9 @@ function createContentApplication(overrides = {}) { createCopyButton: (...args) => opportunitiesLinks.createCopyOpportunityButton(...args), createCloseIcon: (...args) => contentIcons.createCloseIcon(...args), environment }); + const opportunityBadgeContent = createOpportunityBadgeContent({ environment }); const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), activityCache, reportProgress: (...args) => activityProgress.update("sr", ...args), allowsCrmActivities: () => currentUser.allowsCrmActivities(), @@ -356,6 +359,7 @@ function createContentApplication(overrides = {}) { }); const activityProgress = createActivityProgress({ MODAL_ID: contracts.MODAL_ID, environment }); const activityFilters = createActivityFilters({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), allowsCrmActivities: () => currentUser.allowsCrmActivities(), getSrSummary: number => opportunityCrmServiceRequests.getSummary(number), getActionSummary: number => opportunityWorkloadActions.getSummary(number), @@ -364,9 +368,9 @@ function createContentApplication(overrides = {}) { }); const productActivities = createProductActivities({ productsContentState, opportunitiesQueryState, - resetCrm: () => opportunityCrmServiceRequests.reset(), loadCrm: (...args) => opportunityCrmServiceRequests.load(...args), loadActions: (...args) => opportunityWorkloadActions.loadProducts(...args), + blockActions: products => opportunityWorkloadActions.blockProducts(products), render: () => { productsContentJobs.renderProductsProgress(); productsContentJobs.queueProductsTableRender(); @@ -386,7 +390,19 @@ function createContentApplication(overrides = {}) { sendRuntimeMessage: (...args) => platformContentMessages.sendRuntimeMessage(...args), environment }); + const workloadActionForm = createWorkloadActionForm({ + getOpportunity: number => opportunitiesTableState.opportunitiesTableState.items.find(item => String(item.OptyNumber) === String(number)), + formatDate: value => opportunitiesFormatters.formatOracleResponseDate(value), + MODAL_ID: contracts.MODAL_ID, + allowsCrmActivities: () => currentUser.allowsCrmActivities(), + isMissingAction: number => opportunityWorkloadActions.getSummary(number)?.state === "missing", + createCloseIcon: () => contentIcons.createCloseIcon(), + environment + }); const opportunityWorkloadActions = createOpportunityWorkloadActions({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), + createActionButton: number => workloadActionForm.createButton(number), + closeActionForm: (...args) => workloadActionForm.close(...args), activityCache, reportProgress: (...args) => activityProgress.update("actions", ...args), allowsCrmActivities: () => currentUser.allowsCrmActivities(), @@ -398,6 +414,7 @@ function createContentApplication(overrides = {}) { productsContentState, messageTypes, environment }); const productsDetails = createProductsDetails({ + setBadgeContent: (...args) => opportunityBadgeContent.setContent(...args), OPPORTUNITIES_COLUMNS: columns, createAiSummaryAlert: (...args) => aiSummaryContent.createAiSummaryAlert(...args), formatOracleResponseDate: (...args) => opportunitiesFormatters.formatOracleResponseDate(...args), @@ -561,6 +578,7 @@ function createContentApplication(overrides = {}) { startContentApplication({ environment, page: contentFusionPage, styles: contentStyles, products: productsContentJobs }); } return { + workloadActionForm, activityFilters, start, contracts, opportunityWorkloadActions, diff --git a/src/content/modal.js b/src/content/modal.js index c63ce73..49edef8 100644 --- a/src/content/modal.js +++ b/src/content/modal.js @@ -28,6 +28,7 @@ function createContentModal({ closeAccountPlansModal, closeInstallBaseModal, closeServiceRequestsModal, + closeActionForm, closeCustomerFilterPanel, closeOwnerFilterPanel, closePreferencesModal, @@ -470,6 +471,7 @@ function createContentModal({ closeAccountPlansModal(); closeInstallBaseModal(); closeServiceRequestsModal(); + closeActionForm(false); modal.hidden = true; } @@ -498,6 +500,10 @@ function createContentModal({ } if (event.key === "Escape") { + if (closeActionForm()) { + event.preventDefault(); + return; + } if (closeServiceRequestsModal()) { event.preventDefault(); return; diff --git a/src/features/opportunities/activity-filters.js b/src/features/opportunities/activity-filters.js index 95a0c8c..c8191a1 100644 --- a/src/features/opportunities/activity-filters.js +++ b/src/features/opportunities/activity-filters.js @@ -1,4 +1,4 @@ -function createActivityFilters({ allowsCrmActivities, getSrSummary, getActionSummary, renderTable, environment }) { +function createActivityFilters({ allowsCrmActivities, getSrSummary, getActionSummary, renderTable, setBadgeContent, environment }) { const selections = { sr: new Set(["matched", "missing"]), actions: new Set(["matched", "missing"]) }; let container = null; let form = null; @@ -12,24 +12,32 @@ function createActivityFilters({ allowsCrmActivities, getSrSummary, getActionSum container = environment.document.createElement("div"); container.className = "opportunities-extension-badge-filters"; for (const [kind, title, options] of [ - ["sr", "Service Request", [["matched", "\u2705 SR"], ["under4", "\u2705 SR < 4h"], ["missing", "\u26d4 SR"]]], - ["actions", "Actions", [["matched", "\u2705 Action"], ["missing", "\u26d4 Action"]]] + ["sr", "Service Request", ["matched", "under4", "missing"]], + ["actions", "Act", ["matched", "missing"]] ]) { const section = environment.document.createElement("section"); section.className = "opportunities-extension-activity-filter"; const label = environment.document.createElement("span"); label.textContent = title; + const tooltip = kind === "sr" + ? "Whether a Service Request has been created for the opportunities." + : "Whether the Action is registered in Workload Workbench."; + label.title = tooltip; const controls = environment.document.createElement("div"); controls.className = "opportunities-extension-activity-filter-controls"; controls.setAttribute("role", "group"); controls.setAttribute("aria-label", `Filter by ${title}`); - for (const [value, text] of options) { + for (const value of options) { const button = environment.document.createElement("button"); button.type = "button"; button.className = "opportunities-extension-activity-filter-button"; button.setAttribute("data-value", value); - button.textContent = text; - if (value === "under4") button.title = "At least one SR with reported hours below 4; replaces other SR filters."; + setBadgeContent(button, kind, value === "under4" ? "< 4h" : ""); + const description = value === "under4" + ? "At least one SR with reported hours below 4; replaces other SR filters." + : `${kind === "sr" ? "Service Request" : "Action"} ${value === "matched" ? "registered" : "not registered"}`; + button.title = `${tooltip}\n${description}`; + button.setAttribute("aria-label", description); button.addEventListener("click", () => toggle(kind, value)); buttons.push({ button, kind, value }); controls.append(button); diff --git a/src/features/opportunities/badge-content.js b/src/features/opportunities/badge-content.js new file mode 100644 index 0000000..eaf6f50 --- /dev/null +++ b/src/features/opportunities/badge-content.js @@ -0,0 +1,63 @@ +/* + * Lucide icons: package, chart-no-axes-column-increasing, clipboard-list, list-checks. + * https://github.com/lucide-icons/lucide (ISC License) + * Copyright (c) 2026 Lucide Icons and Contributors + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +function createOpportunityBadgeContent({ environment }) { + const shapes = { + products: [ + ["path", { d: "M11 21.73a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73z" }], + ["path", { d: "M12 22V12" }], + ["polyline", { points: "3.29 7 12 12 20.71 7" }], + ["path", { d: "m7.5 4.27 9 5.15" }] + ], + ramp: [ + ["path", { d: "M5 21v-6" }], + ["path", { d: "M12 21V9" }], + ["path", { d: "M19 21V3" }] + ], + sr: [ + ["rect", { width: "8", height: "4", x: "8", y: "2", rx: "1", ry: "1" }], + ["path", { d: "M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2" }], + ["path", { d: "M12 11h4" }], + ["path", { d: "M12 16h4" }], + ["path", { d: "M8 11h.01" }], + ["path", { d: "M8 16h.01" }] + ], + actions: [ + ["path", { d: "M13 5h8" }], + ["path", { d: "M13 12h8" }], + ["path", { d: "M13 19h8" }], + ["path", { d: "m3 17 2 2 4-4" }], + ["path", { d: "m3 7 2 2 4-4" }] + ] + }; + function setContent(badge, kind, value) { + badge.textContent = String(value); + const namespace = "http://www.w3.org/2000/svg"; + const icon = environment.document.createElementNS(namespace, "svg"); + for (const [name, attribute] of Object.entries({ + class: "opportunities-extension-badge-icon", viewBox: "0 0 24 24", + width: "16", height: "16", fill: "none", stroke: "currentColor", + "stroke-width": "2.25", "stroke-linecap": "round", "stroke-linejoin": "round", + "aria-hidden": "true", focusable: "false", "data-badge-icon": kind + })) icon.setAttribute(name, attribute); + for (const [tag, attributes] of shapes[kind]) { + const shape = environment.document.createElementNS(namespace, tag); + for (const [name, attribute] of Object.entries(attributes)) shape.setAttribute(name, attribute); + icon.append(shape); + } + badge.append(icon); + } + return { setContent }; +} diff --git a/src/features/opportunities/crm-service-requests.js b/src/features/opportunities/crm-service-requests.js index f04c5aa..08eec1f 100644 --- a/src/features/opportunities/crm-service-requests.js +++ b/src/features/opportunities/crm-service-requests.js @@ -1,12 +1,20 @@ -function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, allowsCrmActivities, reportProgress, activityCache, environment }) { +function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, allowsCrmActivities, reportProgress, activityCache, setBadgeContent, environment }) { let status = "idle"; let byOpportunity = new Map(); let pending = null; let generation = 0; - function reset() { closePopover(); generation += 1; pending = null; status = "idle"; byOpportunity = new Map(); reportProgress("idle"); } + let loadedItems = []; + function reset() { closePopover(); generation += 1; pending = null; status = "idle"; byOpportunity = new Map(); loadedItems = []; reportProgress("idle"); } function load(token, version, cacheOptions = null) { if (!allowsCrmActivities() || !isCurrentPeriodRequest(version)) return; - if (!pending) pending = run(token, version, generation, cacheOptions); + if (status === "ready") { + return Promise.resolve(cacheOptions ? activityCache.write("sr", "all", cacheOptions.cachedAt, loadedItems) : undefined).then(() => true); + } + if (!pending) { + const request = run(token, version, generation, cacheOptions); + pending = request; + request.finally(() => { if (pending === request) pending = null; }); + } return pending; } async function run(token, version, currentGeneration, cacheOptions) { @@ -14,8 +22,8 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre status = "loading"; try { const cached = cacheOptions ? await activityCache.read("sr", "all", cacheOptions.cachedAt) : null; - if (!isActive()) return; - if (!cached && cacheOptions?.cacheOnly) { status = "idle"; return; } + if (!isActive()) return false; + if (!cached && cacheOptions?.cacheOnly) { status = "idle"; return false; } let items = cached?.items; if (!items) { reportProgress("running", 0); @@ -24,7 +32,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre }); if (items && isActive() && cacheOptions) await activityCache.write("sr", "all", cacheOptions.cachedAt, items); } - if (!items || !isActive()) return; + if (!items || !isActive()) return false; const grouped = new Map(); for (const item of items) { const number = item?.OpportunityName_Id_c?.OptyNumber; @@ -34,10 +42,13 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre grouped.get(key).push(item); } byOpportunity = grouped; + loadedItems = items; status = "ready"; if (!cached) reportProgress("complete", items.length, items.length); + return true; } catch { if (isActive()) { status = "error"; reportProgress("error"); } + return false; } } function getSummary(optyNumber) { @@ -62,7 +73,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre const reportedHours = summary.reportedHours !== null ? new Intl.NumberFormat("en-US", { useGrouping: false, maximumFractionDigits: 10 }).format(summary.reportedHours) : "N/D"; - badge.textContent = status === "error" ? "SR ?" : items.length ? `\u2705 SR (${reportedHours}${reportedHours === "N/D" ? "" : "h"})` : "\u26d4 SR"; + setBadgeContent(badge, "sr", status === "error" ? "?" : items.length ? `${reportedHours}${reportedHours === "N/D" ? "" : "h"}` : "0h"); const display = value => value === null || value === undefined || value === "" ? "N/D" : String(value); const descriptions = items.map(item => [ `Title: ${display(item.Title)}`, @@ -76,8 +87,8 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre : !items.length ? "No matching CRM service request with status SVC_PENDING_DELIVERY in your SR team." : items.map((item, index) => `SR Number: ${display(item.SrNumber)}\n${descriptions[index]}`).join("\n\n"); badge.setAttribute("aria-label", description); + badge.title = "Whether a Service Request has been created for the opportunities."; if (items.length && status === "ready") bindPopover(badge, items, descriptions); - else badge.title = description; badge.tabIndex = 0; return badge; } diff --git a/src/features/opportunities/dashboard.js b/src/features/opportunities/dashboard.js index 322c3ac..6f576e5 100644 --- a/src/features/opportunities/dashboard.js +++ b/src/features/opportunities/dashboard.js @@ -6,7 +6,7 @@ function createOpportunitiesDashboard({ environment }) { const { document, requestAnimationFrame, performance } = environment; - function renderStageDashboard(items) { + function renderStageDashboard(items, totalCount = items.length) { const dashboard = document.getElementById(STAGE_DASHBOARD_ID); if (!dashboard) { @@ -23,12 +23,12 @@ function createOpportunitiesDashboard({ totalCard.setAttribute("data-stage", "TOTAL"); totalLabel.textContent = "Total Opportunities"; totalValue.className = "opportunities-extension-stage-dashboard-value"; - totalValue.setAttribute("aria-label", "Total opportunities"); + totalValue.setAttribute("aria-label", `${items.length} filtered opportunities out of ${totalCount} total`); animateStageDashboardValue( totalValue, "TOTAL", items.length, - (amount) => Math.round(amount).toLocaleString() + (amount) => `${Math.round(amount).toLocaleString()}/${totalCount.toLocaleString()}` ); totalCard.append(totalLabel, totalValue); dashboard.append(totalCard); diff --git a/src/features/opportunities/filters.js b/src/features/opportunities/filters.js index e3a6224..60c731d 100644 --- a/src/features/opportunities/filters.js +++ b/src/features/opportunities/filters.js @@ -336,11 +336,14 @@ function createOpportunitiesFilters({ function getSortedOpportunities() { const normalizedSearch = opportunitiesFilterState.tableSearch.trim().toLocaleLowerCase(); + const allStages = STAGE_OPTIONS.every(stage => opportunitiesFilterState.selectedStages.has(stage)); + const allCustomers = getCustomerOptions().every(option => opportunitiesFilterState.selectedCustomerKeys.has(option.key)); + const allOwners = getOwnerOptions().every(option => opportunitiesFilterState.selectedOwnerKeys.has(option.key)); const items = opportunitiesTableState.opportunitiesTableState.items.filter((item) => { - return opportunitiesFilterState.selectedStages.has(item.ForecastGroup_c) + return (allStages || opportunitiesFilterState.selectedStages.has(item.ForecastGroup_c)) && matchesSelectedStatus(item.StatusCode) - && opportunitiesFilterState.selectedCustomerKeys.has(getCustomerKey(item)) - && opportunitiesFilterState.selectedOwnerKeys.has(getOwnerKey(item)) + && (allCustomers || opportunitiesFilterState.selectedCustomerKeys.has(getCustomerKey(item))) + && (allOwners || opportunitiesFilterState.selectedOwnerKeys.has(getOwnerKey(item))) && matchesTableSearch(item, normalizedSearch) && matchesActivities(item); }); @@ -393,6 +396,7 @@ function createOpportunitiesFilters({ } function matchesSelectedStatus(statusCode) { + if (STATUS_OPTIONS.every(status => opportunitiesFilterState.selectedStatuses.has(status))) return true; if (statusCode === "WON_PENDING") { return opportunitiesFilterState.selectedStatuses.has("WON"); } diff --git a/src/features/opportunities/formatters.js b/src/features/opportunities/formatters.js index 392ec93..f71b57d 100644 --- a/src/features/opportunities/formatters.js +++ b/src/features/opportunities/formatters.js @@ -79,7 +79,7 @@ function createOpportunitiesFormatters({ (items || opportunitiesTableState.opportunitiesTableState.items).forEach((item) => { const key = getOwnerKey(item); - const label = getOwnerName(item); + const label = String(getOwnerName(item)).trim() || "-"; if (key && label && !optionsByKey.has(key)) { optionsByKey.set(key, { key, label: String(label) }); @@ -96,7 +96,9 @@ function createOpportunitiesFormatters({ function getOwnerKey(item) { const owner = item.Owner; const partyId = owner && typeof owner === "object" ? owner.PartyId : ""; - const name = getOwnerName(item); + const name = String(getOwnerName(item)).trim(); + + if (!name) return "owner:unassigned"; if (partyId !== null && partyId !== undefined && partyId !== "") { return `party:${partyId}`; diff --git a/src/features/opportunities/product-activities.js b/src/features/opportunities/product-activities.js index 44b8151..0e8f8cb 100644 --- a/src/features/opportunities/product-activities.js +++ b/src/features/opportunities/product-activities.js @@ -1,5 +1,5 @@ -function createProductActivities({ productsContentState, opportunitiesQueryState, resetCrm, - loadCrm, loadActions, render }) { +function createProductActivities({ productsContentState, opportunitiesQueryState, + loadCrm, loadActions, blockActions, render }) { let cycle = null; function begin(requestId, token) { cycle = { requestId, token, version: opportunitiesQueryState.periodRequestVersion, completed: false }; @@ -11,26 +11,32 @@ function createProductActivities({ productsContentState, opportunitiesQueryState current.completed = true; const products = [...productsContentState.opptyProductsByNumber.values()].filter(result => !result.error); if (!products.length) return; - resetCrm(); - const pending = []; - const seen = new Set(); - for (const result of products) { - const items = result.items.filter(item => { - const id = String(item?.RevnId ?? ""); - if (seen.has(id)) return false; - seen.add(id); - return true; - }); - pending.push(loadActions({ ...result, items }, true, { cachedAt: result.cachedAt, cacheOnly: result.fromCache === true })); - } const cachedAt = Math.max(...products.map(result => Number(result.cachedAt) || 0)); - pending.push(loadCrm(current.token, current.version, { cachedAt, cacheOnly: products.every(result => result.fromCache) })); - return Promise.allSettled(pending).then(() => { - if (cycle !== current || productsContentState.currentProductsRequestId !== requestId - || opportunitiesQueryState.periodRequestVersion !== current.version) return; + const isActive = () => cycle === current && productsContentState.currentProductsRequestId === requestId + && opportunitiesQueryState.periodRequestVersion === current.version; + return Promise.resolve(loadCrm(current.token, current.version, { cachedAt, cacheOnly: products.every(result => result.fromCache) })).then(async success => { + if (!isActive()) return; + if (success === false) { + products.forEach(blockActions); + render(); + return; + } + const pending = []; + const seen = new Set(); + for (const result of products) { + const items = result.items.filter(item => { + const id = String(item?.RevnId ?? ""); + if (seen.has(id)) return false; + seen.add(id); + return true; + }); + pending.push(loadActions({ ...result, items }, true, { cachedAt: result.cachedAt, cacheOnly: result.fromCache === true })); + } + await Promise.allSettled(pending); + if (!isActive()) return; if (cachedAt > 0) productsContentState.productsLastCachedAt = cachedAt; render(); - }).catch(() => {}); + }).catch(() => { if (isActive()) { products.forEach(blockActions); render(); } }); } return { begin, complete }; } diff --git a/src/features/opportunities/styles.css b/src/features/opportunities/styles.css index 1ba7289..b7de88f 100644 --- a/src/features/opportunities/styles.css +++ b/src/features/opportunities/styles.css @@ -9,14 +9,7 @@ .opportunities-extension-auth-badge { transition: none; } } .opportunities-extension-crm-sr-badge { - flex: 0 0 auto; - padding: 0 6px; border: 1px solid #408254; - border-radius: 8px; - font-size: 10px; - line-height: 18px; - font-weight: 600; - white-space: nowrap; color: #185b30; background: #e1f1e5; } @@ -91,14 +84,71 @@ } .opportunities-extension-form .opportunities-extension-stage-filter-button, -.opportunities-extension-form .opportunities-extension-status-filter-button { +.opportunities-extension-form .opportunities-extension-status-filter-button, +.opportunities-extension-form .opportunities-extension-activity-filter-button { + display: inline-flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + height: 28px; min-height: 28px; padding: 4px 7px; + border: 1px solid currentColor; + border-radius: 18px; + font-family: inherit; font-size: 11px; + font-weight: 700; + letter-spacing: 0; line-height: 18px; white-space: nowrap; } +.opportunities-extension-cell-actions > .opportunities-extension-products-count, +.opportunities-extension-cell-actions > .opportunities-extension-products-ramp, +.opportunities-extension-cell-actions > .opportunities-extension-crm-sr-badge { + display: inline-flex; + align-items: center; + justify-content: flex-start; + box-sizing: border-box; + flex: 0 0 auto; + gap: 4px; + height: 20px; + min-height: 20px; + margin: 0; + padding: 0 6px; + border-width: 1px; + border-style: solid; + border-radius: 8px; + font-family: inherit; + font-size: 10px; + font-style: normal; + font-weight: 600; + line-height: 16px; + letter-spacing: 0; + text-align: center; + vertical-align: middle; + white-space: nowrap; +} + +.opportunities-extension-cell-actions .opportunities-extension-badge-icon, +.opportunities-extension-activity-filter-button .opportunities-extension-badge-icon { + display: block; + order: -1; + flex: 0 0 16px; + width: 16px; + height: 16px; + margin: 0; + padding: 0; + border: 0; + color: inherit; + fill: none; + stroke: currentColor; + stroke-width: 2.25; + stroke-linecap: round; + stroke-linejoin: round; + pointer-events: none; +} + @media (max-width: 1150px) { .opportunities-extension-form { grid-template-columns: repeat(4, minmax(0, 1fr)); @@ -139,17 +189,10 @@ column-gap: 8px; } .opportunities-extension-activity-filter-button { - border: 1px solid currentColor; - border-radius: 18px; - min-height: 28px; - padding: 4px 7px; - font: inherit; - font-size: 11px; - font-weight: 600; - line-height: 18px; - white-space: nowrap; + min-width: 32px; + gap: 4px; color: #185b30; - background: transparent; + background: #fff; cursor: pointer; } .opportunities-extension-activity-filter-button[data-value="missing"] { color: #9f201b; } @@ -160,6 +203,7 @@ .opportunities-extension-activity-filter-button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; } .opportunities-extension-modal[data-theme="dark"] .opportunities-extension-activity-filter { color: #eeeae6; } .opportunities-extension-modal[data-theme="dark"] .opportunities-extension-activity-filter-button { color: #b8e4c6; } +.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-activity-filter-button:not([aria-pressed="true"]) { background: #333130; border-color: #6a6560; } .opportunities-extension-modal[data-theme="dark"] .opportunities-extension-activity-filter-button[data-value="missing"] { color: #ffd9d5; } .opportunities-extension-modal[data-theme="dark"] .opportunities-extension-activity-filter-button[data-value="under4"] { color: #b5e9fc; } .opportunities-extension-modal[data-theme="dark"] .opportunities-extension-activity-filter-button[aria-pressed="true"] { border-color: currentColor; } @@ -186,6 +230,105 @@ .opportunities-extension-form[data-activity-filters="true"] { grid-template-columns: minmax(0, 1fr); } } +.opportunities-extension-add-action { + display: inline-flex; + align-items: center; + justify-content: center; + box-sizing: border-box; + flex: 0 0 16px; + width: 16px; + height: 16px; + padding: 0; + margin: 0 0 0 2px; + border: 0; + border-radius: 3px; + background: transparent; + color: inherit; + font: inherit; + cursor: pointer; +} +.opportunities-extension-add-action:hover { background: rgba(127, 127, 127, .2); } +.opportunities-extension-add-action:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; } +.opportunities-extension-action-form-modal { + position: absolute; + inset: 0; + z-index: 5; + display: grid; + place-items: center; + padding: 12px; + background: rgba(0, 0, 0, .42); +} +.opportunities-extension-action-form-dialog { + box-sizing: border-box; + width: min(560px, 100%); + max-height: calc(100vh - 24px); + overflow-y: auto; + background: #fff; + color: #312d2a; + border: 1px solid #b9b4ae; + border-radius: 6px; + box-shadow: 0 12px 36px rgba(0, 0, 0, .25); +} +.opportunities-extension-action-form { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px; + padding: 18px; +} +.opportunities-extension-action-form-heading { min-width: 0; overflow-wrap: anywhere; } +.opportunities-extension-action-form-context { + display: grid; + grid-template-columns: max-content minmax(0, 1fr); + gap: 6px 12px; + margin: 12px 0 0; + font-size: 12px; + line-height: 18px; +} +.opportunities-extension-action-form-context dt { font-weight: 600; } +.opportunities-extension-action-form-context dd { margin: 0; min-width: 0; overflow-wrap: anywhere; } +.opportunities-extension-action-form-field { display: grid; gap: 6px; min-width: 0; font-size: 13px; } +.opportunities-extension-action-form-wide, +.opportunities-extension-action-form-footer { grid-column: 1 / -1; } +.opportunities-extension-action-form-field input, +.opportunities-extension-action-form-field textarea { + box-sizing: border-box; + min-width: 0; + width: 100%; + border: 1px solid #8f8983; + border-radius: 4px; + padding: 8px; + font: inherit; + line-height: 20px; + color: inherit; + background: #fff; +} +.opportunities-extension-action-form-field textarea { resize: vertical; min-height: 96px; } +.opportunities-extension-action-form-footer { display: flex; justify-content: flex-end; gap: 8px; } +.opportunities-extension-action-form-footer button { + border: 1px solid #8f8983; + border-radius: 4px; + padding: 7px 14px; + font: inherit; + font-size: 13px; + background: transparent; + color: inherit; + cursor: pointer; +} +.opportunities-extension-action-form-footer button:disabled { opacity: .55; cursor: not-allowed; } +.opportunities-extension-action-form :focus-visible { outline: 2px solid #00758f; outline-offset: 2px; } +.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-action-form-dialog { + color-scheme: dark; + background: #292725; + color: #eeeae6; + border-color: #756f68; +} +.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-action-form-field input, +.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-action-form-field textarea { background: #211f1d; border-color: #918a82; } +.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-action-form :focus-visible { outline-color: #80d6e8; } +@media (max-width: 420px) { + .opportunities-extension-action-form { grid-template-columns: minmax(0, 1fr); } +} + /* Keep layout rules on the outer table, never on expanded product tables. */ .opportunities-extension-table[data-opportunities-layout="inline-actions"] { width: 100%; @@ -281,18 +424,11 @@ } .opportunities-extension-products-ramp { - display: inline-block; min-width: 0; max-width: 100%; - padding: 0 6px; border: 1px solid #bba5cf; - border-radius: 8px; background: #f0e8f7; color: #63358a; - font-size: 10px; - font-weight: 600; - line-height: 16px; - white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } diff --git a/src/features/opportunities/table.js b/src/features/opportunities/table.js index 9114e3b..c50ebfe 100644 --- a/src/features/opportunities/table.js +++ b/src/features/opportunities/table.js @@ -101,7 +101,7 @@ function createOpportunitiesTable({ const tableBody = document.createElement("tbody"); const items = getSortedOpportunities(); - renderStageDashboard(items); + renderStageDashboard(items, opportunitiesTableState.opportunitiesTableState.items.length); if (opportunitiesTableState.opportunitiesTableState.status === "loading" || opportunitiesTableState.opportunitiesTableState.status === "error" || opportunitiesTableState.opportunitiesTableState.status === "empty" || (opportunitiesTableState.opportunitiesTableState.status === "ready" && items.length === 0)) { const row = document.createElement("tr"); diff --git a/src/features/opportunities/workload-action-form.js b/src/features/opportunities/workload-action-form.js new file mode 100644 index 0000000..56727d2 --- /dev/null +++ b/src/features/opportunities/workload-action-form.js @@ -0,0 +1,111 @@ +function createWorkloadActionForm({ MODAL_ID, allowsCrmActivities, isMissingAction, getOpportunity, formatDate, createCloseIcon, environment }) { + const { document } = environment; + let active = null; + function element(tag, className, text) { + const node = document.createElement(tag); + if (className) node.className = className; + if (text !== undefined) node.textContent = text; + return node; + } + function close(restoreFocus = true) { + if (!active) return false; + const previous = active; + active = null; + previous.modal.remove(); + if (restoreFocus && previous.trigger?.isConnected) previous.trigger.focus(); + return true; + } + function createButton(optyNumber) { + const button = element("button", "opportunities-extension-add-action", "+"); + button.type = "button"; + button.title = "Add Action"; + button.setAttribute("aria-label", `Add Action for ${optyNumber}`); + button.setAttribute("aria-haspopup", "dialog"); + button.addEventListener("click", event => { + event.preventDefault(); + event.stopPropagation(); + open(optyNumber, button); + }); + return button; + } + function open(optyNumber, trigger) { + if (!allowsCrmActivities() || !isMissingAction(optyNumber)) return; + const host = document.getElementById(MODAL_ID); + if (!host || host.hidden) return; + close(false); + const modal = element("section", "opportunities-extension-action-form-modal"); + modal.setAttribute("role", "dialog"); + modal.setAttribute("aria-modal", "true"); + modal.setAttribute("aria-labelledby", "opportunities-extension-action-form-title"); + const dialog = element("div", "opportunities-extension-action-form-dialog"); + const header = element("header", "opportunities-extension-account-plans-header"); + const heading = element("div", "opportunities-extension-action-form-heading"); + const title = element("h2", "", "Add Action"); + title.id = "opportunities-extension-action-form-title"; + heading.append(title, element("p", "", String(optyNumber))); + const opportunity = getOpportunity(optyNumber); + const details = element("dl", "opportunities-extension-action-form-context"); + for (const [label, value] of [ + ["Customer", opportunity?.CustomerAccount?.PartyUniqueName], + ["Name", opportunity?.Name], + ["Close Date", formatDate(opportunity?.EffectiveDate)] + ]) { + details.append(element("dt", "", label), element("dd", "", value == null || value === "" ? "-" : String(value))); + } + heading.append(details); + const dismiss = element("button", "opportunities-extension-icon-button"); + dismiss.type = "button"; + dismiss.title = "Close"; + dismiss.setAttribute("aria-label", "Close Action form"); + dismiss.append(createCloseIcon()); + dismiss.addEventListener("click", () => close()); + header.append(heading, dismiss); + const form = element("form", "opportunities-extension-action-form"); + // Form-only version: never submit or navigate until the API contract is provided. + form.addEventListener("submit", event => event.preventDefault()); + const fields = []; + for (const [name, label, type] of [ + ["team", "Team", "text"], ["startDate", "Start date", "date"], + ["endDate", "End Date", "date"], ["status", "Status", "text"], + ["complexity", "Complexity", "text"], ["notes", "Notes", "textarea"] + ]) { + const field = element("label", "opportunities-extension-action-form-field"); + const input = element(type === "textarea" ? "textarea" : "input"); + if (type !== "textarea") input.type = type; + else input.rows = 5; + input.name = name; + input.id = `opportunities-extension-action-form-${name}`; + field.htmlFor = input.id; + if (name === "notes" || name === "team") field.className += " opportunities-extension-action-form-wide"; + field.append(element("span", "", label), input); + form.append(field); + fields.push(input); + } + const footer = element("footer", "opportunities-extension-action-form-footer"); + const save = element("button", "opportunities-extension-action-form-save", "Save"); + save.type = "submit"; + save.disabled = true; + save.title = "Gravacao ainda nao disponivel"; + const cancel = element("button", "", "Cancel"); + cancel.type = "button"; + cancel.addEventListener("click", () => close()); + footer.append(save, cancel); + form.append(footer); + dialog.append(header, form); + modal.append(dialog); + host.append(modal); + active = { modal, trigger }; + modal.addEventListener("click", event => { if (event.target === modal) close(); }); + modal.addEventListener("keydown", event => { + if (event.key !== "Tab") return; + const controls = [dismiss, ...fields, cancel]; + const index = controls.indexOf(document.activeElement); + if (index === -1 || (!event.shiftKey && index === controls.length - 1) || (event.shiftKey && index === 0)) { + event.preventDefault(); + controls[event.shiftKey ? controls.length - 1 : 0].focus(); + } + }); + fields[0].focus(); + } + return { createButton, open, close }; +} diff --git a/src/features/opportunities/workload-actions.js b/src/features/opportunities/workload-actions.js index cbbd0cb..2a2bb04 100644 --- a/src/features/opportunities/workload-actions.js +++ b/src/features/opportunities/workload-actions.js @@ -1,5 +1,5 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivities, requestConsumerTokenServiceOnce, sendRuntimeMessage, - appendBackgroundRequestLog, queueProductsTableRender, productsContentState, messageTypes, reportProgress, activityCache, environment }) { + appendBackgroundRequestLog, queueProductsTableRender, productsContentState, messageTypes, reportProgress, activityCache, createActionButton, closeActionForm, setBadgeContent, environment }) { let session = newSession(); function newSession() { return { enabled: true, records: new Map(), queue: [], running: 0, progress: new Set() }; } function updateProgress(current) { @@ -10,6 +10,7 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie reportProgress(completed < records.length ? "running" : failed ? "complete-with-errors" : "complete", completed, records.length); } function reset(enabled = true) { + closeActionForm(false); session.enabled = false; for (const job of session.queue) job.record.resolveCompletion(); session.queue.length = 0; @@ -46,6 +47,12 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie for (const products of productsContentState.opptyProductsByNumber.values()) loadProducts(products); queueProductsTableRender(); } + function blockProducts(products) { + if (!allowsCrmActivities()) return; + for (const id of idsFor(products)) { + session.records.set(id, { status: "error", actions: [], hasNext: false, error: "CRM service requests unavailable." }); + } + } function pump(current) { while (current.enabled && current === session && current.running < 4 && current.queue.length) { const job = current.queue.shift(); @@ -66,12 +73,21 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie if (cacheOptions?.cacheOnly) { record.status = "error"; record.error = "No matching activity cache for this product update."; return; } current.progress.add(record); updateProgress(current); - const authorizations = await requestConsumerTokenServiceOnce(); - if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; - const result = await sendRuntimeMessage({ type: messageTypes.requestWlActions, revnId, authorization: authorizations?.workloadActions }); - if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; - appendBackgroundRequestLog(result?.debugRequests); - if (!result?.ok) throw new Error(result?.error || "Unable to load workload actions."); + let result; + for (let attempt = 1; attempt <= 5; attempt += 1) { + try { + if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; + const authorizations = await requestConsumerTokenServiceOnce(); + if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; + result = await sendRuntimeMessage({ type: messageTypes.requestWlActions, revnId, authorization: authorizations?.workloadActions }); + if (!current.enabled || current !== session || current.records.get(revnId) !== record || !allowsCrmActivities()) return; + appendBackgroundRequestLog(result?.debugRequests); + if (!result?.ok) throw new Error(result?.error || "Unable to load workload actions."); + break; + } catch (error) { + if (attempt === 5) throw error; + } + } record.actions = result.actions; record.hasNext = result.hasNext; record.status = "ready"; @@ -107,7 +123,7 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie const badge = environment.document.createElement("span"); badge.className = "opportunities-extension-crm-sr-badge opportunities-extension-wl-actions-badge"; badge.setAttribute("data-state", state); - badge.textContent = state === "matched" ? "\u2705 Act" : state === "missing" ? "\u26d4 Act" : state === "loading" ? "Act ..." : "Act ?"; + setBadgeContent(badge, "actions", state === "matched" || state === "missing" ? actions.length : state === "loading" ? "..." : "?"); badge.title = actions.length ? actions.map(action => [ `Action: ${action.name ?? "N/D"}`, `ID: ${action.id ?? "N/D"}`, `Status: ${action.status ?? "N/D"}`, `Owner: ${action.owner || "N/D"}`, `Email: ${action.ownerEmail || "N/D"}`, `Workload: ${action.workloadName || "N/D"}`, @@ -120,7 +136,8 @@ function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivitie if (actions.length && (pending || uncertain)) badge.title += "\nSome workloads are still loading or could not be fully checked."; badge.tabIndex = 0; badge.setAttribute("aria-label", badge.title); + if (state === "missing") badge.append(createActionButton(String(optyNumber))); return badge; } - return { reset, reopen, loadProducts, createBadge, getSummary }; + return { reset, reopen, loadProducts, blockProducts, createBadge, getSummary }; } diff --git a/src/features/products/details.js b/src/features/products/details.js index 944b117..b17a519 100644 --- a/src/features/products/details.js +++ b/src/features/products/details.js @@ -1,5 +1,6 @@ function createProductsDetails({ OPPORTUNITIES_COLUMNS, + setBadgeContent, createAiSummaryAlert, formatOracleResponseDate, productsContentState, @@ -17,7 +18,7 @@ function createProductsDetails({ const badge = document.createElement("span"); badge.className = "opportunities-extension-products-ramp"; badge.setAttribute("data-missing", String(values.includes("N/D"))); - badge.textContent = `RM ${values.join(",")}`; + setBadgeContent(badge, "ramp", values.join(",")); badge.title = `Ramp Months: ${values.join(", ")}`; badge.setAttribute("aria-label", badge.title); return badge; @@ -31,7 +32,7 @@ function createProductsDetails({ button.type = "button"; button.className = "opportunities-extension-products-count"; - button.textContent = String(count); + setBadgeContent(button, "products", count); button.setAttribute("aria-expanded", String(isExpanded)); button.setAttribute("aria-label", `${count} product${count === 1 ? "" : "s"} for opportunity ${normalizedOptyNumber}`); button.title = productsResult.error ? productsResult.error : `${count} product${count === 1 ? "" : "s"}`; diff --git a/src/services/fusion/crm-service-requests.js b/src/services/fusion/crm-service-requests.js index feddd0b..921b89c 100644 --- a/src/services/fusion/crm-service-requests.js +++ b/src/services/fusion/crm-service-requests.js @@ -21,6 +21,7 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest, async function requestCrmServiceRequest(token, version, isActive = () => isCurrentPeriodRequest(version), onProgress = () => {}) { const items = []; let offset = 0; + let attempt = 1; while (isActive()) { const payload = createPayload(offset); const headers = { @@ -28,31 +29,33 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest, Origin: "https://eeho.fa.us2.oraclecloud.com", Preference: "transient" }; const entry = logRequestStart({ name: "resquestCrmServiceRequest", method: "POST", url, - headers: { ...headers, Authorization: `Bearer ${maskToken(token)}` }, body: JSON.stringify(payload, null, 2), metadata: { offset } }); + headers: { ...headers, Authorization: `Bearer ${maskToken(token)}` }, body: JSON.stringify(payload, null, 2), metadata: { offset, attempt } }); try { const response = await fetch(url, { method: "POST", credentials: "include", headers, body: JSON.stringify(payload) }); logRequestSuccess(entry, response, await readResponseBodyForDebug(response)); - if (!response.ok) throw new Error(`CRM service request query failed with status ${response.status}.`); + if (response.status !== 200) throw new Error(`CRM service request query failed with status ${response.status}.`); const data = await response.json(); if (!data || !Array.isArray(data.items) || typeof data.hasMore !== "boolean") { throw new Error("CRM service request query returned an invalid response."); } if (!isActive()) return null; + const received = data.count === undefined ? data.items.length : Number(data.count); + const current = data.offset === undefined ? offset : Number(data.offset); + if (data.hasMore && (!data.items.length || !Number.isInteger(received) || received <= 0 || !Number.isInteger(current) + || current !== offset || current + received <= offset)) { + throw new Error("CRM service request pagination did not advance."); + } items.push(...data.items); onProgress(items.length, Number.isFinite(data.totalResults) && data.totalResults >= items.length ? data.totalResults : null); if (!data.hasMore) return items; - const received = data.count === undefined ? data.items.length : Number(data.count); - const current = data.offset === undefined ? offset : Number(data.offset); - if (!data.items.length || !Number.isInteger(received) || received <= 0 || !Number.isInteger(current) - || current !== offset || current + received <= offset) { - throw new Error("CRM service request pagination did not advance."); - } offset = current + received; + attempt = 1; } catch (error) { logRequestFailure(entry, error.message || "CRM service request query failed."); - throw error; + if (attempt === 5) throw error; + attempt += 1; } } return null; diff --git a/src/services/http/background-json.js b/src/services/http/background-json.js index af0fa6e..5e371a8 100644 --- a/src/services/http/background-json.js +++ b/src/services/http/background-json.js @@ -25,7 +25,10 @@ function createHttpBackgroundJson({ appendBackgroundDebugEntry(debugRequests, debugEntry); if (!response.ok) { - throw new Error(`${requestName} failed with status ${response.status}.`); + const error = new Error(`${requestName} failed with status ${response.status}.`); + error.httpStatus = response.status; + debugEntry.error = error.message; + throw error; } if (responsePayload.error) { diff --git a/tests/activityCache.test.cjs b/tests/activityCache.test.cjs index 3dd2351..4289726 100644 --- a/tests/activityCache.test.cjs +++ b/tests/activityCache.test.cjs @@ -14,7 +14,9 @@ function setup(family, saved = {}, principal = "user@example.invalid") { remove: (keys, done) => local.remove(keys).then(done) } } } }; - const app = loadApplication("content", { ...api, document: { createElement: () => ({ setAttribute() {}, addEventListener() {} }) } }); + const document = { createElement: () => ({ append() {}, setAttribute() {}, addEventListener() {} }) }; + document.createElementNS = (_, tag) => document.createElement(tag); + const app = loadApplication("content", { ...api, document }); app.authSessionState.principal = principal; app.currentUser.allowsCrmActivities = () => true; app.preferencesState.opptyProductsCacheHours = 24; @@ -59,7 +61,7 @@ for (const family of ["chrome", "firefox"]) { const count = h.calls.length; await h.load(currentStamp, true); assert.equal(h.calls.length, count); - assert.equal(h.app.opportunityCrmServiceRequests.createBadge("OP1").textContent, "\u2705 SR (2h)"); + assert.equal(h.app.opportunityCrmServiceRequests.createBadge("OP1").textContent, "2h"); h.app.opportunitiesTable.renderOpportunitiesTable = () => {}; h.app.activityFilters.toggle("sr", "under4"); assert.equal(h.app.activityFilters.matches({ OptyNumber: "OP1" }), true); @@ -82,15 +84,15 @@ for (const family of ["chrome", "firefox"]) { const restored = setup(family, h.saved); await restored.load(stamp, true); assert.deepEqual(restored.calls, []); - assert.equal(restored.app.opportunityCrmServiceRequests.createBadge("OP1").textContent, "\u2705 SR (4h)"); - assert.equal(restored.app.opportunityWorkloadActions.createBadge("OP1").textContent, "\u2705 Act"); + assert.equal(restored.app.opportunityCrmServiceRequests.createBadge("OP1").textContent, "4h"); + assert.equal(restored.app.opportunityWorkloadActions.createBadge("OP1").textContent, "1"); await restored.load(stamp, false); assert.deepEqual(restored.calls, [], "valid matching cache also deduplicates repeated fresh-product notifications"); const other = setup(family, h.saved, "other@example.invalid"); await other.load(stamp, true); assert.deepEqual(other.calls, []); assert.equal(other.app.opportunityCrmServiceRequests.createBadge("OP1"), null); - assert.equal(other.app.opportunityWorkloadActions.createBadge("OP1").textContent, "Act ?"); + assert.equal(other.app.opportunityWorkloadActions.createBadge("OP1").textContent, "?"); await restored.load(stamp + 1, false); assert.deepEqual(restored.calls, ["sr", "actions"]); }); @@ -133,7 +135,7 @@ test("storage failure does not lose live activity results and failures are never h.local.get = async () => { throw new Error("Synthetic storage read failure"); }; h.local.set = async () => { throw new Error("Synthetic storage write failure"); }; await h.load(Date.now() - 1000, false); - assert.equal(h.app.opportunityCrmServiceRequests.createBadge("OP1").textContent, "\u2705 SR (4h)"); + assert.equal(h.app.opportunityCrmServiceRequests.createBadge("OP1").textContent, "4h"); const failed = setup("firefox"); failed.app.fusionCrmServiceRequests.requestCrmServiceRequest = async () => { throw new Error("Synthetic failure"); }; failed.app.platformContentMessages.sendRuntimeMessage = async () => ({ ok: false }); diff --git a/tests/activityFilters.test.cjs b/tests/activityFilters.test.cjs index 2a1fc40..8b5b4e6 100644 --- a/tests/activityFilters.test.cjs +++ b/tests/activityFilters.test.cjs @@ -11,7 +11,7 @@ class Element { addEventListener(key, handler) { this.listeners[key] = handler; } } function setup() { - const app = loadApplication("content", { document: { createElement: tag => new Element(tag) } }); + const app = loadApplication("content", { document: { createElement: tag => new Element(tag), createElementNS: (_, tag) => new Element(tag) } }); app.currentUser.allowsCrmActivities = () => true; let renders = 0; app.opportunitiesTable.renderOpportunitiesTable = () => { renders += 1; }; @@ -34,9 +34,28 @@ test("activity badge filters precede Status, are accessible and combine without assert.equal(h.controls.children[0].children[1].attributes["aria-label"], "Filter by Service Request"); assert.equal(h.controls.children[3], h.stage); assert.equal(h.form.attributes["data-activity-filters"], "true"); - assert.equal(h.button("sr", "matched").textContent, "\u2705 SR"); - assert.equal(h.button("actions", "missing").textContent, "\u26d4 Action"); + assert.equal(h.button("sr", "matched").textContent, ""); + assert.equal(h.button("actions", "missing").textContent, ""); assert.equal(h.button("actions", "matched").type, "button"); + assert.equal(h.controls.children[1].children[0].textContent, "Act"); + for (const value of ["matched", "missing"]) { + assert.equal(h.button("actions", value).textContent, ""); + assert.ok(h.button("actions", value).title.startsWith("Whether the Action is registered in Workload Workbench.\n")); + assert.ok(h.button("sr", value).title.startsWith("Whether a Service Request has been created for the opportunities.\n")); + for (const kind of ["sr", "actions"]) { + const button = h.button(kind, value); + assert.ok(button.title.endsWith(button.attributes["aria-label"])); + assert.equal(button.children.length, 1); + assert.equal(button.children[0].tag, "svg"); + assert.equal(button.children[0].attributes["data-badge-icon"], kind); + assert.equal(button.children[0].attributes.stroke, "currentColor"); + assert.equal(button.children[0].attributes["aria-hidden"], "true"); + } + } + assert.equal(h.button("sr", "under4").textContent, "< 4h"); + assert.equal(h.button("sr", "under4").children[0].attributes["data-badge-icon"], "sr"); + assert.notEqual(h.button("actions", "matched").attributes["aria-label"], h.button("actions", "missing").attributes["aria-label"]); + assert.notEqual(h.button("sr", "matched").attributes["aria-label"], h.button("sr", "missing").attributes["aria-label"]); h.sr.set("A", { state: "matched" }); h.actions.set("A", { state: "missing" }); h.sr.set("B", { state: "missing" }); @@ -74,6 +93,30 @@ test("SR below four hours is exclusive and regular SR options can replace it", ( assert.equal(h.matches("A"), false); }); +test("filter vectors retain their fixed slot without duplication when selection changes", () => { + const h = setup(); + const options = [["sr", "matched"], ["sr", "under4"], ["sr", "missing"], ["actions", "matched"], ["actions", "missing"]]; + const icons = options.map(([kind, value]) => h.button(kind, value).children[0]); + for (const [kind, value] of options) h.click(kind, value); + h.app.activityFilters.render(); + options.forEach(([kind, value], index) => { + const button = h.button(kind, value); + assert.deepEqual(button.children, [icons[index]]); + assert.equal(icons[index].attributes.viewBox, "0 0 24 24"); + assert.equal(icons[index].attributes.width, "16"); + assert.equal(icons[index].attributes.height, "16"); + assert.equal(icons[index].attributes["stroke-width"], "2.25"); + assert.equal(icons[index].attributes.focusable, "false"); + }); + const css = fs.readFileSync(path.join(__dirname, "../src/features/opportunities/styles.css"), "utf8"); + const shared = css.match(/\.opportunities-extension-cell-actions \.opportunities-extension-badge-icon,\s*\.opportunities-extension-activity-filter-button \.opportunities-extension-badge-icon \{([^}]+)\}/); + assert.ok(shared, "filters and opportunity badges share the same vector positioning"); + for (const rule of ["order: -1;", "flex: 0 0 16px;", "width: 16px;", "height: 16px;", "stroke: currentColor;"]) { + assert.ok(shared[1].includes(rule), rule); + } + assert.match(css, /activity-filter-button \{\s*min-width: 32px;\s*gap: 4px;/); +}); + test("missing filters exclude unknown, loading and error states; SALES_REP bypasses and hides them", () => { const h = setup(); h.click("sr", "matched"); @@ -98,7 +141,7 @@ test("missing filters exclude unknown, loading and error states; SALES_REP bypas for (const [roles, allowed] of [[ ["SALES_REP"], false ], [ ["SIMPLE_USER", "SALES_REP"], false ], [ ["SOLUTION_ENG_NOTERR"], true ]]) { test(`requestCurrentUser roles ${JSON.stringify(roles)} control actual filter visibility`, async () => { - const app = loadApplication("content", { document: { createElement: tag => new Element(tag) } }); + const app = loadApplication("content", { document: { createElement: tag => new Element(tag), createElementNS: (_, tag) => new Element(tag) } }); const calls = []; let finish; app.platformContentMessages.sendRuntimeMessage = message => { @@ -146,7 +189,7 @@ test("SR filter summary uses actual records: zero, decimals, exact four, missing }); test("Action filter summary shares badge ownership and uncertainty rules", async () => { - const app = loadApplication("content", { document: { createElement: tag => new Element(tag) } }); + const app = loadApplication("content", { document: { createElement: tag => new Element(tag), createElementNS: (_, tag) => new Element(tag) } }); app.currentUser.allowsCrmActivities = () => true; app.productsContentJobs.queueProductsTableRender = () => {}; app.authSessionState.principal = "me@example.invalid"; @@ -190,6 +233,16 @@ test("activity filters have theme contrast, visible keyboard focus and responsiv assert.match(css, /badge-filters \{\s*display: flex;[\s\S]*?flex-wrap: wrap;/); }); +test("SR and Act filters share sizing and typography with Status and Stage", () => { + const css = fs.readFileSync(path.join(__dirname, "../src/features/opportunities/styles.css"), "utf8"); + const shared = css.match(/\.opportunities-extension-form \.opportunities-extension-stage-filter-button,\s*\.opportunities-extension-form \.opportunities-extension-status-filter-button,\s*\.opportunities-extension-form \.opportunities-extension-activity-filter-button\s*\{([^}]+)\}/); + assert.ok(shared, "all filter badges use the same presentation rule"); + for (const declaration of ["display: inline-flex;", "align-items: center;", "box-sizing: border-box;", "height: 28px;", + "padding: 4px 7px;", "border-radius: 18px;", "font-size: 11px;", "font-weight: 700;", "line-height: 18px;"]) { + assert.ok(shared[1].includes(declaration), declaration); + } +}); + test("desktop keeps fields and badge groups on one line, wrapping only below the compact breakpoint", () => { const css = fs.readFileSync(path.join(__dirname, "../src/features/opportunities/styles.css"), "utf8"); assert.match(css, /\.opportunities-extension-badge-filters \{ display: contents; \}/); diff --git a/tests/activityProgress.test.cjs b/tests/activityProgress.test.cjs index 32e274c..2b05151 100644 --- a/tests/activityProgress.test.cjs +++ b/tests/activityProgress.test.cjs @@ -56,7 +56,9 @@ test("CRM reports real page counts and Actions reports queued and completed requ pending[0]({ ok: true, actions: [], hasNext: false }); await new Promise(resolve => setImmediate(resolve)); assert.deepEqual(progress.at(-1), ["actions", "running", 1, 2]); - pending[1]({ ok: false, error: "Synthetic failure" }); - await new Promise(resolve => setImmediate(resolve)); + for (let attempt = 1; attempt <= 5; attempt += 1) { + pending[attempt]({ ok: false, error: "Synthetic failure" }); + await new Promise(resolve => setImmediate(resolve)); + } assert.deepEqual(progress.at(-1), ["actions", "complete-with-errors", 2, 2]); }); diff --git a/tests/activityRetries.test.cjs b/tests/activityRetries.test.cjs new file mode 100644 index 0000000..2e08707 --- /dev/null +++ b/tests/activityRetries.test.cjs @@ -0,0 +1,108 @@ +const assert = require("node:assert/strict"); +const { test } = require("node:test"); +const { loadApplication } = require("./support/application.cjs"); +const { response } = require("./support/characterization.cjs"); + +function setup(fetch) { + const app = loadApplication("content", { fetch }); + app.currentUser.allowsCrmActivities = () => true; + app.opportunitiesQueryState.periodRequestVersion = 1; + app.debugContentView.renderDebugPanel = () => {}; + app.activityProgress.update = () => {}; + app.productsContentJobs.renderProductsProgress = () => {}; + app.productsContentJobs.queueProductsTableRender = () => {}; + app.authContentSession.requestConsumerTokenServiceOnce = async () => ({ workloadActions: { value: "synthetic" } }); + const actions = []; + app.platformContentMessages.sendRuntimeMessage = async message => { + actions.push(message); + return { ok: true, actions: [], hasNext: false }; + }; + async function cycle(id) { + app.productsContentState.currentProductsRequestId = id; + app.productsContentState.opptyProductsByNumber.set("A", { items: [{ RevnId: "123" }], cachedAt: Date.now(), fromCache: false }); + app.productActivities.begin(id, "synthetic"); + await app.productActivities.complete(id); + } + return { app, actions, cycle }; +} + +test("SR succeeds on fifth attempt, is shared in flight and reused across Reference/product reloads", async () => { + let calls = 0; + const h = setup(async () => { + calls += 1; + if (calls < 5) throw new Error("Synthetic offline"); + return response({ items: [], hasMore: false }); + }); + const first = h.app.opportunityCrmServiceRequests.load("synthetic", 1); + assert.equal(h.app.opportunityCrmServiceRequests.load("synthetic", 1), first); + assert.equal(await first, true); + assert.equal(calls, 5); + await h.cycle("current-quarter"); + h.app.opportunitiesQueryState.periodRequestVersion += 1; + await h.cycle("next-quarter"); + assert.equal(calls, 5); + assert.equal(h.actions.length, 2); + assert.equal(h.app.debugState.requestLog.filter(entry => entry.name === "resquestCrmServiceRequest").length, 5); + h.app.opportunityCrmServiceRequests.reset(); + await h.cycle("explicit-refresh"); + assert.equal(calls, 6); +}); + +for (const failure of [() => new Response("Denied", { status: 403 }), () => new Response("Login")]) { + test("SR exhausting five attempts blocks Actions and preserves the last completed timestamp", async () => { + let calls = 0; + const h = setup(async () => { calls += 1; return failure(); }); + h.app.productsContentState.productsLastCachedAt = 123; + await h.cycle("failed"); + assert.equal(calls, 5); + assert.equal(h.actions.length, 0); + assert.equal(h.app.opportunityCrmServiceRequests.getSummary("A").state, "error"); + assert.equal(h.app.productsContentState.productsLastCachedAt, 123); + h.app.authSessionState.principal = "synthetic@example.invalid"; + assert.equal(h.app.opportunityWorkloadActions.getSummary("A").state, "error"); + }); +} + +test("pagination retries only the failed SR page, with no duplicate records", async () => { + const offsets = []; + let failures = 0; + const h = setup(async (_url, options) => { + const { offset } = JSON.parse(options.body); + offsets.push(offset); + if (offset === 1 && failures++ < 2) return response({ invalid: true }); + return response({ items: [{ SrNumber: `SR${offset}`, ReportedHours_c: 2, OpportunityName_Id_c: { OptyNumber: "A" } }], + offset, count: 1, hasMore: offset === 0 }); + }); + await h.cycle("paged"); + assert.deepEqual(offsets, [0, 1, 1, 1]); + assert.equal(h.app.opportunityCrmServiceRequests.getSummary("A").reportedHours, 4); + assert.equal(h.actions.length, 1); +}); + +test("Actions retries each workload up to five times and stops as soon as it succeeds", async () => { + const h = setup(async () => response({ items: [], hasMore: false })); + let attempts = 0; + h.app.platformContentMessages.sendRuntimeMessage = async () => { + attempts += 1; + return attempts < 3 ? { ok: false, error: "Synthetic" } : { ok: true, actions: [], hasNext: false }; + }; + await h.cycle("success"); + assert.equal(attempts, 3); + attempts = 0; + h.app.platformContentMessages.sendRuntimeMessage = async () => { attempts += 1; throw new Error("Synthetic"); }; + await h.cycle("failed-actions"); + assert.equal(attempts, 5); +}); + +test("an invalidated SR request does not continue retrying or launch Actions", async () => { + let reject, calls = 0; + const h = setup(() => { calls += 1; return new Promise((_resolve, fail) => { reject = fail; }); }); + const pending = h.cycle("old"); + await new Promise(resolve => setImmediate(resolve)); + h.app.opportunityCrmServiceRequests.reset(); + h.app.productsContentState.currentProductsRequestId = "new"; + reject(new Error("Synthetic")); + await pending; + assert.equal(calls, 1); + assert.equal(h.actions.length, 0); +}); diff --git a/tests/aiSummary.test.cjs b/tests/aiSummary.test.cjs index d7bae4a..a5be4fb 100644 --- a/tests/aiSummary.test.cjs +++ b/tests/aiSummary.test.cjs @@ -29,6 +29,7 @@ function setup(mockSalesToken = true) { const context = { document: { createElement: (tag) => new Element(tag), + createElementNS: (_, tag) => new Element(tag), querySelectorAll: () => visibleAlerts }, fetch: (url, options) => new Promise((resolve, reject) => calls.push({ url, options, resolve, reject })), diff --git a/tests/allOpportunityFilters.test.cjs b/tests/allOpportunityFilters.test.cjs new file mode 100644 index 0000000..d599bff --- /dev/null +++ b/tests/allOpportunityFilters.test.cjs @@ -0,0 +1,68 @@ +const assert = require("node:assert/strict"); +const { test } = require("node:test"); +const { loadApplication } = require("./support/application.cjs"); + +function setup() { + const app = loadApplication("content"); + const normal = { OptyNumber: "normal", Name: "Synthetic", ForecastGroup_c: "FORECAST", StatusCode: "OPEN", + CustomerAccount: { PartyId: "1", PartyUniqueName: "Customer" }, Owner: { PersonFirstName: "Owner" } }; + const items = [normal, + { ...normal, OptyNumber: "stage", ForecastGroup_c: null }, + { ...normal, OptyNumber: "status", StatusCode: "UNLISTED" }, + { ...normal, OptyNumber: "customer", CustomerAccount: null }, + { ...normal, OptyNumber: "owner", Owner: null }]; + app.opportunitiesTableState.opportunitiesTableState.items = items; + app.opportunitiesFilters.resetCustomerFilter(items); + app.opportunitiesFilters.resetOwnerFilter(items); + return { app, items, result: () => Array.from(app.opportunitiesFilters.getSortedOpportunities(), item => item.OptyNumber) }; +} + +test("all selected includes records with missing or unlisted dimensions", () => { + const h = setup(); + assert.equal(h.result().length, h.items.length); + h.app.opportunitiesFilterState.tableSearch = "normal"; + assert.deepEqual(h.result(), ["normal"], "search still restricts results"); +}); + +test("partial and empty selections remain restrictive, including WON_PENDING mapping", () => { + const h = setup(); + const state = h.app.opportunitiesFilterState; + state.selectedStages.delete("SQL"); + assert.equal(h.result().includes("stage"), false); + state.selectedStages.add("SQL"); + state.selectedStatuses.delete("CLOSED"); + assert.equal(h.result().includes("status"), false); + assert.equal(h.app.opportunitiesFilters.matchesSelectedStatus("WON_PENDING"), true); + state.selectedStatuses.clear(); + assert.deepEqual(h.result(), []); +}); + +test("customer and owner exclusions apply only when a narrower selection is made", () => { + const h = setup(); + const state = h.app.opportunitiesFilterState; + state.selectedCustomerKeys.clear(); + assert.deepEqual(h.result(), []); + state.selectedCustomerKeys.add("party:1"); + assert.equal(h.result().includes("customer"), true); + state.selectedOwnerKeys.clear(); + assert.deepEqual(h.result(), []); +}); + +test("Owner offers one dash option for unassigned records and supports selecting it alone", () => { + const h = setup(); + for (const Owner of [undefined, {}, "", " ", { PersonFirstName: " " }]) { + h.items.push({ ...h.items[0], OptyNumber: `missing-${h.items.length}`, Owner }); + } + const options = Array.from(h.app.opportunitiesFormatters.getOwnerOptions()); + const missing = options.filter(option => option.label === "-"); + assert.equal(missing.length, 1); + assert.equal(missing[0].key, "owner:unassigned"); + h.app.opportunitiesFilterState.selectedOwnerKeys = new Set([missing[0].key]); + assert.equal(h.result().length, 6); + assert.equal(h.result().includes("normal"), false); + h.app.opportunitiesFilterState.selectedOwnerKeys = new Set(options.map(option => option.key)); + assert.equal(h.result().length, h.items.length); + h.app.opportunitiesFilterState.selectedOwnerKeys.delete(missing[0].key); + assert.equal(h.result().includes("owner"), false); + assert.equal(h.result().length, 4); +}); diff --git a/tests/badgeIcons.test.cjs b/tests/badgeIcons.test.cjs new file mode 100644 index 0000000..d71f351 --- /dev/null +++ b/tests/badgeIcons.test.cjs @@ -0,0 +1,113 @@ +const assert = require("node:assert/strict"); +const { test } = require("node:test"); +const fs = require("node:fs"); +const path = require("node:path"); +const { loadApplication, composeScript } = require("./support/application.cjs"); + +const root = path.join(__dirname, ".."); +class Element { + constructor(tag) { + this.tag = tag; this.children = []; this.attributes = {}; this.listeners = {}; this.text = ""; + this.classList = { toggle() {} }; + } + set textContent(value) { this.text = String(value); this.children = []; } + get textContent() { return this.text + this.children.map(child => child.textContent).join(""); } + append(...children) { this.children.push(...children); } + setAttribute(key, value) { this.attributes[key] = value; } + addEventListener(key, callback) { this.listeners[key] = callback; } +} +function setup() { + const app = loadApplication("content", { document: { createElement: tag => new Element(tag), getElementById: () => null, + createElementNS: (namespace, tag) => Object.assign(new Element(tag), { namespace }) } }); + app.currentUser.allowsCrmActivities = () => true; + app.productsContentJobs.queueProductsTableRender = () => {}; + app.activityProgress.update = () => {}; + app.authSessionState.principal = "me@example.invalid"; + return app; +} +function checkIcon(badge, kind, value) { + assert.equal(badge.textContent, value); + const images = badge.children.filter(child => child.tag === "svg"); + assert.equal(images.length, 1); + const icon = images[0]; + assert.equal(icon.namespace, "http://www.w3.org/2000/svg"); + assert.equal(icon.attributes.viewBox, "0 0 24 24"); + assert.equal(icon.attributes.fill, "none"); + assert.equal(icon.attributes.stroke, "currentColor"); + assert.equal(icon.attributes["stroke-width"], "2.25"); + assert.equal(icon.attributes["stroke-linecap"], "round"); + assert.equal(icon.attributes["stroke-linejoin"], "round"); + assert.equal(icon.attributes["data-badge-icon"], kind); + assert.equal(icon.attributes["aria-hidden"], "true"); + assert.equal(icon.attributes.focusable, "false"); + assert.equal(icon.attributes.width, "16"); + assert.equal(icon.attributes.height, "16"); + assert.ok(icon.children.length >= 3); + assert.ok(icon.children.every(child => ["path", "rect", "polyline"].includes(child.tag))); + assert.ok(icon.children.every(child => child.namespace === icon.namespace)); + assert.equal(badge.children.some(child => child.tag === "img"), false); +} + +test("consistent inline vectors replace raster icons without parentheses or lost tooltips", async () => { + const app = setup(); + const products = { items: [1, 2, 3].map(RampMonths_c => ({ RampMonths_c, RevnId: "123" })) }; + const count = app.productsDetails.createProductsCountButton("TEST", products); + checkIcon(count, "products", "3"); + assert.equal(count.title, "3 products"); + assert.equal(typeof count.listeners.click, "function"); + const ramp = app.productsDetails.createProductsRampBadge(products); + checkIcon(ramp, "ramp", "1,2,3"); + assert.equal(ramp.title, "Ramp Months: 1, 2, 3"); + const missingRamp = app.productsDetails.createProductsRampBadge({ items: [{ RampMonths_c: null }] }); + checkIcon(missingRamp, "ramp", "N/D"); + assert.equal(missingRamp.attributes["data-missing"], "true"); + + app.fusionCrmServiceRequests.requestCrmServiceRequest = async () => [ + { SrNumber: "SR-TEST", ReportedHours_c: 4, OpportunityName_Id_c: { OptyNumber: "TEST" } } + ]; + await app.opportunityCrmServiceRequests.load("synthetic", app.opportunitiesQueryState.periodRequestVersion); + const sr = app.opportunityCrmServiceRequests.createBadge("TEST"); + checkIcon(sr, "sr", "4h"); + assert.equal(sr.title, "Whether a Service Request has been created for the opportunities."); + assert.equal(typeof sr.listeners.click, "function"); + checkIcon(app.opportunityCrmServiceRequests.createBadge("OTHER"), "sr", "0h"); + + app.productsContentState.opptyProductsByNumber.set("TEST", products); + app.authContentSession.requestConsumerTokenServiceOnce = async () => ({ workloadActions: { value: "synthetic" } }); + app.platformContentMessages.sendRuntimeMessage = async () => ({ ok: true, hasNext: false, actions: [ + { id: 1, owner: "me@example.invalid", name: "My action" }, + { id: 2, owner: "other@example.invalid", name: "Other action" } + ] }); + await app.opportunityWorkloadActions.loadProducts(products); + const actions = app.opportunityWorkloadActions.createBadge("TEST"); + checkIcon(actions, "actions", "2"); + assert.equal(actions.attributes["data-state"], "matched"); + assert.match(actions.title, /My action/); + assert.match(actions.title, /Other action/); + app.currentUser.allowsCrmActivities = () => false; + assert.equal(app.opportunityWorkloadActions.createBadge("TEST"), null); + assert.equal(app.opportunityCrmServiceRequests.createBadge("TEST"), null); +}); + +test("vector shapes and their license ship in both distributions without raster images or requests", () => { + const source = composeScript("content"); + const module = fs.readFileSync(path.join(root, "src/features/opportunities/badge-content.js"), "utf8"); + assert.ok(source.includes(module)); + assert.doesNotMatch(source, /opportunityBadgeImages|data:image\/png;base64/); + for (const target of ["chromium", "firefox"]) { + const bundle = fs.readFileSync(path.join(root, "dist", target, "content.js"), "utf8"); + assert.ok(bundle.includes(module)); + assert.ok(bundle.includes("Copyright (c) 2026 Lucide Icons and Contributors")); + } +}); + +test("icon styles preserve uniform dimensions and provide light, dark and active contrast", () => { + const css = fs.readFileSync(path.join(root, "src/features/opportunities/styles.css"), "utf8"); + const icon = css.match(/\.opportunities-extension-badge-icon \{([^}]+)\}/)[1]; + for (const rule of ["order: -1;", "flex: 0 0 16px;", "width: 16px;", "height: 16px;", "color: inherit;", "stroke: currentColor;", "stroke-width: 2.25;"]) { + assert.ok(icon.includes(rule), rule); + } + assert.doesNotMatch(icon, /filter:|mix-blend-mode:/); + assert.match(css, /gap: 4px;\s*height: 20px;/); + assert.match(css, /cell-actions > \.opportunities-extension-crm-sr-badge \{\s*display: inline-flex;\s*align-items: center;\s*justify-content: flex-start;/); +}); diff --git a/tests/consumerTokenAuthorizationRecovery.test.cjs b/tests/consumerTokenAuthorizationRecovery.test.cjs new file mode 100644 index 0000000..c28fd62 --- /dev/null +++ b/tests/consumerTokenAuthorizationRecovery.test.cjs @@ -0,0 +1,73 @@ +const assert = require("node:assert/strict"); +const { test } = require("node:test"); +const { loadBackground, response } = require("./support/characterization.cjs"); +const tokens = [ + { tokenService: "ACCP-TS", uiaasHeader: { value: "synthetic-account" } }, + { tokenService: "OCICONS-TS", uiaasHeader: { value: "synthetic-consumption" } }, + { tokenService: "WWB-TS", uiaasHeader: { value: "synthetic-actions" } } +]; +const request = { type: "opportunitiesExtension.requestConsumerTokenService" }; + +for (const family of ["chrome", "firefox"]) { + for (const status of [401, 403]) { + test(`${family}: HTTP ${status} opens an inactive SPA session and closes it after valid JSON`, async () => { + let attempts = 0; + const h = loadBackground({ family, fetch: async (_url, options) => { + attempts += 1; + assert.equal(options.credentials, "include"); + if (attempts === 1) return response({ error: "Session unavailable" }, status); + assert.equal(h.tabs.length, 1, "session tab must open before retrying"); + return response(tokens); + } }); + const result = await h.dispatch(request); + assert.equal(result.ok, true); + assert.equal(attempts, 2); + assert.equal(h.tabs.length, 1); + assert.equal(h.tabs[0].active, false); + assert.equal(h.tabs[0].windowId, 3); + assert.equal(h.tabs[0].cookieStoreId, family === "firefox" ? "test-store" : undefined); + assert.equal(h.tabs[0].url, "https://spa.oracle.com/oalcrm/web/api/g2m-consumer-application/ui/index.html"); + assert.deepEqual(h.removedTabs, [91]); + assert.equal(result.debugRequests[0].httpStatus, status); + assert.match(result.debugRequests[0].metadata.retryReason, /SPA session recovery/); + assert.equal(result.debugRequests[1].metadata.sessionBootstrapState, "closed-after-valid-json"); + assert.equal(result.authorizations.workloadActions.value, "synthetic-actions"); + }); + } + test(`${family}: persistent 403 stops after five attempts and removes the auxiliary tab`, async () => { + let attempts = 0; + const h = loadBackground({ family, fetch: async () => { attempts += 1; return response({}, 403); } }); + const result = await h.dispatch(request); + assert.equal(result.ok, false); + assert.equal(attempts, 5); + assert.equal(h.tabs.length, 1); + assert.deepEqual(h.removedTabs, [91]); + assert.match(result.error, /403 after 5 attempts/); + assert.equal(result.debugRequests.at(-1).metadata.retryLimitReached, "true"); + assert.equal(result.debugRequests.at(-1).metadata.sessionBootstrapState, "closed-after-retry-finished"); + }); +} + +test("mixed 403/HTML recovery shares one tab and the existing retry budget", async () => { + let attempts = 0; + const h = loadBackground({ fetch: async () => { + attempts += 1; + if (attempts === 1) return response({}, 403); + if (attempts === 2) return new Response("Login"); + return response(tokens); + } }); + const result = await h.dispatch(request); + assert.equal(result.ok, true); + assert.equal(attempts, 3); + assert.equal(h.tabs.length, 1); + assert.deepEqual(h.removedTabs, [91]); + assert.equal(result.debugRequests[1].metadata.sessionBootstrapState, "waiting-for-valid-session"); +}); + +test("unrelated HTTP failures do not launch the SPA session page", async () => { + const h = loadBackground({ fetch: async () => response({}, 500) }); + const result = await h.dispatch(request); + assert.equal(result.ok, false); + assert.equal(result.debugRequests.length, 1); + assert.equal(h.tabs.length, 0); +}); diff --git a/tests/crmServiceRequests.test.cjs b/tests/crmServiceRequests.test.cjs index 5a06fe3..4c7a41c 100644 --- a/tests/crmServiceRequests.test.cjs +++ b/tests/crmServiceRequests.test.cjs @@ -3,7 +3,8 @@ const { test } = require("node:test"); const { loadApplication } = require("./support/application.cjs"); const response = data => new Response(JSON.stringify(data), { status: 200 }); function setup(fetch) { - const document = { createElement: () => ({ attributes: {}, addEventListener() {}, setAttribute(key, value) { this.attributes[key] = value; } }) }; + const document = { createElement: () => ({ attributes: {}, append() {}, addEventListener() {}, setAttribute(key, value) { this.attributes[key] = value; } }) }; + document.createElementNS = (_, tag) => document.createElement(tag); const app = loadApplication("content", { fetch, document, Intl, Date }); app.currentUser.allowsCrmActivities = () => true; app.debugContentView.renderDebugPanel = () => {}; @@ -18,8 +19,12 @@ test("SR badge shows reported hours, sums linked SRs and preserves missing value for (const [values, expected] of [[[4], "4h"], [[0], "0h"], [[2, "1.5"], "3.5h"], [[0.1, 0.2], "0.3h"], [[null], "N/D"], [[4, null], "N/D"], [[""], "N/D"], [["invalid"], "N/D"]]) { const app = setup(async () => response({ items: values.map((value, index) => ({ ...sr("A", `SR-${index}`), ReportedHours_c: value })), hasMore: false })); await app.opportunityCrmServiceRequests.load("synthetic", 1); - assert.equal(app.opportunityCrmServiceRequests.createBadge("A").textContent, `\u2705 SR (${expected})`); - assert.equal(app.opportunityCrmServiceRequests.createBadge("OTHER").textContent, "\u26d4 SR"); + assert.equal(app.opportunityCrmServiceRequests.createBadge("A").textContent, expected); + assert.equal(app.opportunityCrmServiceRequests.createBadge("OTHER").textContent, "0h"); + assert.equal(app.opportunityCrmServiceRequests.createBadge("A").title, "Whether a Service Request has been created for the opportunities."); + assert.equal(app.opportunityCrmServiceRequests.createBadge("OTHER").title, "Whether a Service Request has been created for the opportunities."); + assert.equal(app.opportunityCrmServiceRequests.createBadge("A").attributes["data-state"], "matched"); + assert.equal(app.opportunityCrmServiceRequests.createBadge("OTHER").attributes["data-state"], "missing"); } }); @@ -89,11 +94,11 @@ test("CRM query preserves payload and pagination after opportunities, uses token assert.equal(app.debugContentView.getRequestCategory(log), "serviceRequests"); } const found = app.opportunityCrmServiceRequests.createBadge("TEST-1"); - assert.equal(found.textContent, "\u2705 SR (0h)"); + assert.equal(found.textContent, "0h"); assert.equal(found.attributes["data-state"], "matched"); for (const detail of ["SR-0", "SR-1", "Reported Hours: 0", "Test Owner", "test@example.invalid", ""]) assert.ok(found.attributes["aria-label"].includes(detail)); - assert.equal(app.opportunityCrmServiceRequests.createBadge("OTHER").textContent, "\u26d4 SR"); + assert.equal(app.opportunityCrmServiceRequests.createBadge("OTHER").textContent, "0h"); assert.equal(app.opportunityCrmServiceRequests.createBadge(null), null); app.opportunityCrmServiceRequests.reset(); assert.equal(app.opportunityCrmServiceRequests.createBadge("TEST-1"), null); @@ -118,7 +123,7 @@ test("CRM failures do not mislabel missing SRs or block the opportunity list", a await app.opportunitiesController.requestOpportunities("token", "Current Quarter", {}, 1); assert.equal(loaded, true); await app.opportunityCrmServiceRequests.load("token", 1); - assert.equal(app.opportunityCrmServiceRequests.createBadge("TEST").textContent, "SR ?"); + assert.equal(app.opportunityCrmServiceRequests.createBadge("TEST").textContent, "?"); assert.equal(app.debugState.requestLog.at(-1).status, "failed"); } }); @@ -133,8 +138,8 @@ test("stale CRM results cannot overwrite a reopened modal or continue pagination await app.opportunityCrmServiceRequests.load("token", 2); resolveOld(response({ items: [sr("OLD")], hasMore: true, count: 1, offset: 0 })); await old; - assert.equal(app.opportunityCrmServiceRequests.createBadge("NEW").textContent, "\u2705 SR (0h)"); - assert.equal(app.opportunityCrmServiceRequests.createBadge("OLD").textContent, "\u26d4 SR"); + assert.equal(app.opportunityCrmServiceRequests.createBadge("NEW").textContent, "0h"); + assert.equal(app.opportunityCrmServiceRequests.createBadge("OLD").textContent, "0h"); assert.equal(app.debugState.requestLog.length, 1); }); @@ -155,8 +160,8 @@ test("Reference changes share pending pagination and reuse completed CRM results app.opportunitiesQueryState.periodRequestVersion = 3; await app.opportunityCrmServiceRequests.load("token", 3); assert.equal(calls, 2); - assert.equal(app.opportunityCrmServiceRequests.createBadge("A").textContent, "\u2705 SR (0h)"); - assert.equal(app.opportunityCrmServiceRequests.createBadge("B").textContent, "\u2705 SR (0h)"); + assert.equal(app.opportunityCrmServiceRequests.createBadge("A").textContent, "0h"); + assert.equal(app.opportunityCrmServiceRequests.createBadge("B").textContent, "0h"); app.opportunityCrmServiceRequests.reset(); await app.opportunityCrmServiceRequests.load("token", 3); assert.equal(calls, 3); diff --git a/tests/dashboardTotals.test.cjs b/tests/dashboardTotals.test.cjs new file mode 100644 index 0000000..7964d76 --- /dev/null +++ b/tests/dashboardTotals.test.cjs @@ -0,0 +1,48 @@ +const assert = require("node:assert/strict"); +const { test } = require("node:test"); +const { loadApplication } = require("./support/application.cjs"); + +class Element { + constructor() { this.children = []; this.attributes = {}; } + set textContent(value) { this.text = value; this.children = []; } + get textContent() { return this.text; } + append(...nodes) { this.children.push(...nodes); } + setAttribute(key, value) { this.attributes[key] = value; } + addEventListener() {} +} + +test("Total Opportunities displays filtered/overall and updates with filters and Reference data", () => { + const dashboard = new Element(), table = new Element(); + const app = loadApplication("content", { + document: { + createElement: () => new Element(), + getElementById: id => id === "opportunities-extension-stage-dashboard" ? dashboard + : id === "opportunities-extension-table" ? table : null + }, + performance: { now: () => 0 }, requestAnimationFrame: tick => tick(480) + }); + // Use real table/dashboard coordination without constructing unrelated row controls. + app.opportunitiesTableState.opportunitiesTableState.status = "loading"; + const items = Array.from({ length: 26 }, () => ({ ForecastGroup_c: "FORECAST" })); + app.opportunitiesTableState.opportunitiesTableState.items = items; + let filtered = items.slice(0, 11); + app.opportunitiesFilters.getSortedOpportunities = () => filtered; + const value = () => dashboard.children[0].children[1]; + app.opportunitiesTable.renderOpportunitiesTable(); + assert.equal(value().textContent, "11/26"); + assert.equal(value().attributes["aria-label"], "11 filtered opportunities out of 26 total"); + filtered = []; + app.opportunitiesTable.renderOpportunitiesTable(); + assert.equal(value().textContent, "0/26"); + filtered = items; + app.opportunitiesTable.renderOpportunitiesTable(); + assert.equal(value().textContent, "26/26"); + app.opportunitiesTableState.opportunitiesTableState.items = items.slice(0, 3); + filtered = items.slice(0, 2); + app.opportunitiesTable.renderOpportunitiesTable(); + assert.equal(value().textContent, "2/3"); + app.opportunitiesTableState.opportunitiesTableState.items = []; + filtered = []; + app.opportunitiesTable.renderOpportunitiesTable(); + assert.equal(value().textContent, "0/0"); +}); diff --git a/tests/opportunityTable.test.cjs b/tests/opportunityTable.test.cjs index 9c59ee6..6dbbbaf 100644 --- a/tests/opportunityTable.test.cjs +++ b/tests/opportunityTable.test.cjs @@ -59,6 +59,7 @@ test("ten columns retain their links and put product/customer controls below the assert.ok(name.children[0].href.endsWith("TEST-1")); assert.equal(name.children[1].children[0].className, "opportunities-extension-products-count"); assert.equal(name.children[1].children[0].textContent, "1"); + assert.equal(name.children[1].children[0].title, "1 product"); assert.equal(customer.children[0].textContent, "Synthetic customer"); assert.ok(customer.children[0].href.endsWith("party%2Fid")); assert.equal(customer.children[1].children[0].title, "View customer consumption"); @@ -82,8 +83,8 @@ test("ramp months preserve zero and flag missing values beside the product count const badge = () => findClass(h.cell("name"), "opportunities-extension-products-ramp"); assert.equal(badge(), undefined); for (const [values, expected] of [ - [[], null], [[null], "RM N/D"], [[null, undefined, "", " "], "RM N/D"], [[6], "RM 6"], - [[0], "RM 0"], [[0, "3", null, " 6 ", 3], "RM 0,3,N/D,6,3"] + [[], null], [[null], "N/D"], [[null, undefined, "", " "], "N/D"], [[6], "6"], + [[0], "0"], [[0, "3", null, " 6 ", 3], "0,3,N/D,6,3"] ]) { h.app.productsContentState.opptyProductsByNumber.set("TEST-1", { fromCache: true, items: values.map(RampMonths_c => ({ RampMonths_c })) @@ -93,10 +94,13 @@ test("ramp months preserve zero and flag missing values beside the product count else { assert.equal(badge().textContent, expected); assert.equal(badge().attributes["data-missing"], String(expected.includes("N/D"))); - assert.match(badge().title, /^Ramp Months:/); + assert.equal(badge().title, `Ramp Months: ${expected.split(",").join(", ")}`); + assert.equal(badge().attributes["aria-label"], badge().title); assert.equal(h.cell("name").children[0].children[1].children[1], badge()); } - assert.equal(findClass(h.cell("name"), "opportunities-extension-products-count").textContent, String(values.length)); + const count = findClass(h.cell("name"), "opportunities-extension-products-count"); + assert.equal(count.textContent, String(values.length)); + assert.equal(count.title, `${values.length} product${values.length === 1 ? "" : "s"}`); } }); @@ -118,6 +122,33 @@ test("products remain expandable with AI summary and a ten-column detail row aft assert.deepEqual(h.summaries, ["B"], "collapsing does not generate another summary"); }); +test("product labels support multiple digits without changing their tooltip", () => { + const h = setup(); + h.app.productsContentState.opptyProductsByNumber.set("TEST-1", { items: Array.from({ length: 12 }, () => ({})) }); + h.app.opportunitiesTable.renderOpportunitiesTable(); + const count = findClass(h.cell("name"), "opportunities-extension-products-count"); + assert.equal(count.textContent, "12"); + assert.equal(count.title, "12 products"); + assert.equal(count.attributes["aria-label"], "12 products for opportunity TEST-1"); +}); + +test("opportunity badges share height, typography and alignment including the Action plus button", () => { + const css = fs.readFileSync(path.join(__dirname, "../src/features/opportunities/styles.css"), "utf8"); + const shared = css.match(/\.opportunities-extension-cell-actions > \.opportunities-extension-products-count,\s*\.opportunities-extension-cell-actions > \.opportunities-extension-products-ramp,\s*\.opportunities-extension-cell-actions > \.opportunities-extension-crm-sr-badge\s*\{([^}]+)\}/); + assert.ok(shared, "P, R, SR and Act share one scoped badge rule"); + for (const declaration of ["display: inline-flex;", "align-items: center;", "justify-content: flex-start;", + "box-sizing: border-box;", "height: 20px;", "min-height: 20px;", "padding: 0 6px;", "margin: 0;", + "border-radius: 8px;", "font-family: inherit;", "font-size: 10px;", "font-weight: 600;", "line-height: 16px;"]) { + assert.ok(shared[1].includes(declaration), declaration); + } + const plus = css.match(/\.opportunities-extension-add-action\s*\{([^}]+)\}/)[1]; + assert.match(plus, /height: 16px;/); + assert.match(plus, /align-items: center;/); + assert.match(plus, /font: inherit;/); + const actions = fs.readFileSync(path.join(__dirname, "../src/features/opportunities/workload-actions.js"), "utf8"); + assert.match(actions, /badge.className = "opportunities-extension-crm-sr-badge opportunities-extension-wl-actions-badge"/); +}); + test("CRM SR badge follows Ramp Months and remains visible while product data is pending", async () => { const h = setup(); h.app.fusionCrmServiceRequests.requestCrmServiceRequest = async () => [{ @@ -125,11 +156,11 @@ test("CRM SR badge follows Ramp Months and remains visible while product data is }]; await h.app.opportunityCrmServiceRequests.load("synthetic", h.app.opportunitiesQueryState.periodRequestVersion); h.app.opportunitiesTable.renderOpportunitiesTable(); - assert.equal(findClass(h.cell("name"), "opportunities-extension-crm-sr-badge").textContent, "\u2705 SR (0h)"); + assert.equal(findClass(h.cell("name"), "opportunities-extension-crm-sr-badge").textContent, "0h"); h.app.productsContentState.opptyProductsByNumber.set("TEST-1", { items: [{ RampMonths_c: 3 }] }); h.app.opportunitiesTable.renderOpportunitiesTable(); const actions = h.cell("name").children[0].children[1]; - assert.deepEqual(actions.children.map(child => child.textContent), ["1", "RM 3", "\u2705 SR (0h)", "Act ?"]); + assert.deepEqual(actions.children.map(child => child.textContent), ["1", "3", "0h", "?"]); findClass(h.cell("name"), "opportunities-extension-products-count").click(); assert.ok(findClass(h.rows()[1], "opportunities-extension-products-table")); }); diff --git a/tests/productActivities.test.cjs b/tests/productActivities.test.cjs index 209b566..f3e9f6d 100644 --- a/tests/productActivities.test.cjs +++ b/tests/productActivities.test.cjs @@ -48,7 +48,8 @@ test("Last update ignores superseded cycles and settles failures without changin assert.equal(h.app.productsContentState.productsLastCachedAt, 100); current.reject(new Error("Synthetic failure")); await flush(); - assert.equal(h.app.productsContentState.productsLastCachedAt, 300); + assert.equal(h.app.productsContentState.productsLastCachedAt, 100); + assert.equal(h.calls.includes("empty products"), false, "SR failure blocks Actions"); }); test("Last update waits for cache restoration and ignores a superseded Reference", async () => { @@ -111,7 +112,7 @@ test("follow-up calls wait for completion, deduplicate terminal messages and ref h.progress(first, { state: "complete" }); h.progress(first, { state: "complete" }); await flush(); - assert.deepEqual(h.calls, ["reset SR", "123", "SR token"]); + assert.deepEqual(h.calls, ["SR token", "123"]); const second = h.start("new-token"); h.progress(first, { state: "complete", optyNumber: "B", items: [{ RevnId: "old" }] }); h.progress(second, { state: "running", optyNumber: "A", items: [{ RevnId: "123" }] }); @@ -152,13 +153,13 @@ test("cached products restore activities without network; mixed cycles fetch onl h.progress(cached, { optyNumber: "A", items: [{ RevnId: "cached" }], fromCache: true }); h.progress(cached, { state: "complete" }); await flush(); - assert.deepEqual(h.calls, ["reset SR"]); + assert.deepEqual(h.calls, []); const mixed = h.start(); h.progress(mixed, { optyNumber: "A", items: [{ RevnId: "cached" }], fromCache: true }); h.progress(mixed, { optyNumber: "B", items: [{ RevnId: "fresh" }], fromCache: false }); h.progress(mixed, { state: "complete" }); await flush(); - assert.deepEqual(h.calls, ["reset SR", "reset SR", "fresh", "SR token"]); + assert.deepEqual(h.calls, ["SR token", "fresh"]); }); test("reopening an existing modal does not reload products or reset/query activities", async () => { diff --git a/tests/workloadActionForm.test.cjs b/tests/workloadActionForm.test.cjs new file mode 100644 index 0000000..89d22c0 --- /dev/null +++ b/tests/workloadActionForm.test.cjs @@ -0,0 +1,115 @@ +const assert = require("node:assert/strict"); +const { test } = require("node:test"); +const { loadApplication } = require("./support/application.cjs"); + +function setup() { + let document; + class Element { + constructor(tag) { this.tag = tag; this.children = []; this.attributes = {}; this.listeners = {}; this.isConnected = true; this.text = ""; } + set textContent(value) { this.text = value; this.children = []; } + get textContent() { return this.text + this.children.map(child => child.textContent).join(""); } + append(...nodes) { for (const node of nodes) { node.parent = this; this.children.push(node); } } + setAttribute(key, value) { this.attributes[key] = value; } + addEventListener(key, fn) { this.listeners[key] = fn; } + focus() { document.activeElement = this; } + remove() { this.parent.children = this.parent.children.filter(child => child !== this); this.isConnected = false; } + click() { this.listeners.click?.({ target: this, preventDefault() {}, stopPropagation() {} }); } + } + const host = new Element("host"); + document = { createElement: tag => new Element(tag), createElementNS: (_, tag) => new Element(tag), + getElementById: id => id === "opportunities-extension-modal" ? host : null, + listeners: {}, addEventListener(key, fn) { this.listeners[key] = fn; } }; + const app = loadApplication("content", { document, window: {} }); + app.currentUser.allowsCrmActivities = () => true; + app.authSessionState.principal = "synthetic@example.invalid"; + app.productsContentState.opptyProductsByNumber.set("A", { items: [] }); + app.productsContentState.opptyProductsByNumber.set("B", { items: [] }); + app.platformContentMessages.sendRuntimeMessage = () => assert.fail("Form must not send requests"); + const walk = node => [node, ...node.children.flatMap(walk)]; + const nodes = () => walk(host); + const form = () => nodes().find(node => node.tag === "form"); + return { app, host, document, nodes, form }; +} + +test("only plus on the missing Action badge opens a form with six fields and no save operation", () => { + const h = setup(); + const badge = h.app.opportunityWorkloadActions.createBadge("A"); + assert.equal(badge.textContent, "0+"); + badge.click(); + assert.equal(h.host.children.length, 0); + const plus = badge.children.find(node => node.tag === "button"); + assert.equal(plus.textContent, "+"); + assert.equal(plus.attributes["aria-haspopup"], "dialog"); + plus.click(); + assert.equal(h.host.children.length, 1); + assert.equal(h.host.children[0].attributes.role, "dialog"); + assert.deepEqual(h.nodes().filter(node => node.name).map(node => node.name), ["team", "startDate", "endDate", "status", "complexity", "notes"]); + assert.equal(h.nodes().find(node => node.name === "notes").tag, "textarea"); + assert.equal(h.nodes().find(node => node.name === "startDate").type, "date"); + assert.equal(h.document.activeElement.name, "team"); + assert.equal(h.nodes().find(node => node.textContent === "Save").disabled, true); + let prevented = false; + h.form().listeners.submit({ preventDefault() { prevented = true; } }); + assert.equal(prevented, true); + h.nodes().find(node => node.textContent === "Cancel").click(); + assert.equal(h.host.children.length, 0); + assert.equal(h.document.activeElement, plus); +}); + +test("form traps focus, handles Escape, replaces rather than duplicates, and resets its fields", () => { + const h = setup(); + h.app.contentModal.ensureEscapeKeyHandler(); + const first = h.app.opportunityWorkloadActions.createBadge("A").children.find(node => node.tag === "button"); + first.click(); + h.nodes().find(node => node.name === "notes").value = "Draft"; + const second = h.app.opportunityWorkloadActions.createBadge("B").children.find(node => node.tag === "button"); + second.click(); + assert.equal(h.host.children.length, 1); + assert.equal(h.nodes().find(node => node.name === "notes").value, undefined); + const cancel = h.nodes().find(node => node.textContent === "Cancel"); + cancel.focus(); + let prevented = false; + h.host.children[0].listeners.keydown({ key: "Tab", preventDefault() { prevented = true; } }); + assert.equal(prevented, true); + assert.equal(h.document.activeElement.title, "Close"); + h.document.listeners.keydown({ key: "Escape", preventDefault() {} }); + assert.equal(h.host.children.length, 0); + assert.equal(h.document.activeElement, second); +}); + +test("SALES_REP, loading/unknown Actions and stale triggers cannot open the modal", () => { + const h = setup(); + const plus = h.app.opportunityWorkloadActions.createBadge("A").children.find(node => node.tag === "button"); + h.app.currentUser.allowsCrmActivities = () => false; + plus.click(); + assert.equal(h.host.children.length, 0); + assert.equal(h.app.opportunityWorkloadActions.createBadge("A"), null); + h.app.currentUser.allowsCrmActivities = () => true; + h.app.productsContentState.opptyProductsByNumber.set("A", { items: [{ RevnId: "pending" }] }); + plus.click(); + assert.equal(h.host.children.length, 0); + assert.equal(h.app.opportunityWorkloadActions.createBadge("A").children.some(node => node.tag === "button"), false); + h.app.authSessionState.principal = ""; + assert.equal(h.app.opportunityWorkloadActions.createBadge("B").children.some(node => node.tag === "button"), false); +}); + +test("resetting Actions closes an open form without leaving an old opportunity context", () => { + const h = setup(); + h.app.opportunityWorkloadActions.createBadge("A").children.find(node => node.tag === "button").click(); + h.app.opportunityWorkloadActions.reset(); + assert.equal(h.host.children.length, 0); +}); + +test("Action header shows the selected opportunity customer, name and formatted close date safely", () => { + const h = setup(); + h.app.opportunitiesTableState.opportunitiesTableState.items = [ + { OptyNumber: "A", Name: "", CustomerAccount: { PartyUniqueName: "Customer A" }, EffectiveDate: "2026-11-30" }, + { OptyNumber: "B", Name: "Opportunity B", CustomerAccount: { PartyUniqueName: "Customer B" }, EffectiveDate: null } + ]; + h.app.opportunityWorkloadActions.createBadge("A").children.find(node => node.tag === "button").click(); + assert.deepEqual(h.nodes().filter(node => node.tag === "dt").map(node => node.textContent), ["Customer", "Name", "Close Date"]); + assert.deepEqual(h.nodes().filter(node => node.tag === "dd").map(node => node.textContent), ["Customer A", "", "30/11/2026"]); + assert.equal(h.nodes().some(node => node.tag === "script"), false); + h.app.opportunityWorkloadActions.createBadge("B").children.find(node => node.tag === "button").click(); + assert.deepEqual(h.nodes().filter(node => node.tag === "dd").map(node => node.textContent), ["Customer B", "Opportunity B", "-"]); +}); diff --git a/tests/workloadActions.test.cjs b/tests/workloadActions.test.cjs index 4ef3e07..bace36e 100644 --- a/tests/workloadActions.test.cjs +++ b/tests/workloadActions.test.cjs @@ -52,7 +52,9 @@ test("workload actions reject missing credentials, invalid ids, HTTP/network/JSO }); function contentFixture(send) { - const app = loadApplication("content", { document: { createElement: () => ({ attributes: {}, setAttribute(k, v) { this.attributes[k] = v; } }) } }); + const document = { createElement: () => ({ attributes: {}, append() {}, addEventListener() {}, setAttribute(k, v) { this.attributes[k] = v; } }) }; + document.createElementNS = (_, tag) => document.createElement(tag); + const app = loadApplication("content", { document }); app.currentUser.allowsCrmActivities = () => true; app.authContentSession.requestConsumerTokenServiceOnce = async () => ({ workloadActions: { value: "synthetic-wwb" } }); app.authSessionState.principal = "test@example.invalid"; @@ -74,12 +76,14 @@ test("Actions completion includes queued calls, shared pending records, failures const shared = app.opportunityWorkloadActions.loadProducts(products).then(() => { sharedComplete = true; }); await flush(); assert.equal(pending.length, 4); - pending.slice(0, 4).forEach(resolve => resolve({ ok: false, error: "Synthetic" })); - await flush(); - assert.equal(pending.length, 5); + for (let attempt = 0; attempt < 5; attempt += 1) { + pending.slice(attempt * 4, attempt * 4 + 4).forEach(resolve => resolve({ ok: false, error: "Synthetic" })); + await flush(); + } + assert.equal(pending.length, 21); assert.equal(complete, false); assert.equal(sharedComplete, false); - pending[4]({ ok: true, actions: [], hasNext: false }); + pending[20]({ ok: true, actions: [], hasNext: false }); await flush(); assert.equal(complete, false, "cache write still pending"); finishWrite(); @@ -109,18 +113,18 @@ test("actions aggregate all products, share RevnId queries across Reference chan const products = { items: [{ RevnId: "1" }, { RevnId: 2 }, { RevnId: "1" }] }; app.productsContentState.opptyProductsByNumber.set("A", products); app.opportunityWorkloadActions.loadProducts(products); - assert.equal(app.opportunityWorkloadActions.createBadge("A").textContent, "Act ..."); + assert.equal(app.opportunityWorkloadActions.createBadge("A").textContent, "..."); await flush(); assert.equal(calls.length, 2); assert.equal(calls[0].authorization.value, "synthetic-wwb"); const badge = app.opportunityWorkloadActions.createBadge("A"); - assert.equal(badge.textContent, "\u2705 Act"); + assert.equal(badge.textContent, "1"); assert.match(badge.title, /