Your IP : 216.73.217.81
{"version":3,"sources":["nf-ai-chat.scss","nf-ai-chat.css","home/runner/work/ninja-forms/ninja-forms/assets/scss/shared/_nf-ai-model-picker.scss"],"names":[],"mappings":"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","file":"nf-ai-chat.css","sourcesContent":["@use \"../shared/nf-ai-model-picker\" as ai-model;\n\n/**\n * AI assistant styles: builder header button + drawer chat.\n *\n * Compiles to assets/css/nf-ai-chat.css (enqueued by NF_AJAX_REST_AIChat).\n */\n\n/*\n * Header button: identical markup and styling treatment to the public-link\n * icon (span.dashicons inside the anchor, same float/spacing/size), with a\n * blue resting state so it stands out.\n */\n#nf-header .nf-ai-assistant {\n float: right;\n margin-right: 30px;\n padding: 8px 0;\n color: #1EA9EA;\n}\n\n/*\n * Custom AI sparkle glyph: no icon set we ship carries the modern sparkle\n * convention, so it's a masked SVG painted with currentColor — it inherits\n * and transitions color exactly like a font icon.\n */\n.nf-ai-sparkle {\n display: inline-block;\n width: 1em;\n height: 1em;\n vertical-align: -0.125em;\n background-color: currentColor;\n -webkit-mask: url(../img/nf-ai-sparkle.svg) no-repeat center;\n -webkit-mask-size: contain;\n mask: url(../img/nf-ai-sparkle.svg) no-repeat center;\n mask-size: contain;\n}\n\n/* Sized so the sparkle optically matches the 30px public-link dashicon. */\n#nf-header .nf-ai-assistant .nf-ai-sparkle {\n width: 30px;\n height: 30px;\n vertical-align: middle;\n -webkit-mask-size: 26px;\n mask-size: 26px;\n}\n\n#nf-header .nf-ai-assistant:hover {\n color: #1590c9;\n}\n\n/*\n * While the AI drawer is open, hide the dev-mode footer so the panel reads\n * as a chat session, not a settings pane. No layout overrides: the chat is\n * normal-flow drawer content, exactly like the other drawers.\n */\n#nf-drawer.nf-ai-drawer-active .nf-drawer-dev-mode-note {\n display: none;\n}\n\n.nf-ai-chat-title {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n font-size: 16px;\n font-weight: 600;\n color: #23282d;\n padding: 4px 2px 8px;\n border-bottom: 1px solid #e2e4e7;\n}\n\n.nf-ai-chat-title .nf-ai-sparkle {\n color: #1EA9EA;\n margin-right: 6px;\n font-size: 16px;\n}\n\n/*\n * One row above the composer: conversation control on the left, model control\n * on the right. Start new chat used to live inside the model popup, where it\n * existed only while that popup was open and two reviewers failed to find it.\n */\n.nf-ai-chat-controls {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 5px 2px 0;\n border-top: 1px solid #e2e4e7;\n}\n\n.nf-ai-model-control {\n // min-width lets the trigger truncate a long model name in a narrow\n // drawer instead of pushing Start new chat out of the row.\n flex: 0 1 auto;\n min-width: 0;\n position: relative;\n display: flex;\n justify-content: flex-end;\n}\n\n#nf-drawer {\n @include ai-model.model-picker(6px 7px, 12px, 11px, 11px);\n}\n\n#nf-drawer .nf-ai-model-trigger {\n width: auto;\n max-width: 100%;\n min-height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: flex-end;\n gap: 3px;\n margin: 0;\n padding: 1px 0;\n border: 0;\n border-radius: 2px;\n background: transparent;\n box-shadow: none;\n color: #646970;\n font-size: 11px;\n text-align: right;\n cursor: pointer;\n}\n\n#nf-drawer .nf-ai-model-trigger:hover {\n background: transparent;\n color: #2271b1;\n}\n\n#nf-drawer .nf-ai-model-trigger:focus {\n outline: none;\n background: transparent;\n box-shadow: 0 0 0 1px #2271b1;\n color: #135e96;\n}\n\n.nf-ai-model-current {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n#nf-drawer .nf-ai-model-trigger .dashicons {\n flex: 0 0 auto;\n width: 16px;\n height: 16px;\n font-size: 16px;\n line-height: 16px;\n transition: transform .15s ease;\n}\n\n.nf-ai-model-control.is-open .nf-ai-model-trigger .dashicons {\n transform: rotate(180deg);\n}\n\n.nf-ai-model-menu {\n @include ai-model.model-menu-chrome(300px, 9px, .16);\n\n // The composer sits at the foot of the drawer, so this list opens upward.\n z-index: 30;\n bottom: calc(100% - 2px);\n}\n\n.nf-ai-model-control:not(.is-open) .nf-ai-model-menu {\n display: none;\n}\n\n#nf-drawer .nf-ai-model-search {\n height: 32px;\n margin: 0 0 8px;\n}\n\n.nf-ai-model-group {\n padding: 6px 0;\n}\n\n#nf-drawer .nf-ai-model-option,\n#nf-drawer .nf-ai-model-show-all {\n min-height: 0;\n margin: 0;\n}\n\n#nf-drawer .nf-ai-start-new-chat {\n flex: 0 0 auto;\n width: auto;\n min-height: 0;\n margin: 0;\n padding: 6px 7px;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: #646970;\n font-size: 12px;\n text-align: left;\n white-space: nowrap;\n cursor: pointer;\n}\n\n#nf-drawer .nf-ai-start-new-chat:hover,\n#nf-drawer .nf-ai-start-new-chat:focus {\n background: #f0f0f1;\n color: #2c3338;\n}\n\n#nf-drawer .nf-ai-start-new-chat:disabled {\n opacity: .6;\n cursor: wait;\n}\n\n.nf-ai-spin {\n animation: nf-ai-spin-anim 1s linear infinite;\n}\n\n@keyframes nf-ai-spin-anim {\n from { transform: rotate(0deg); }\n to { transform: rotate(360deg); }\n}\n\n\n/*\n * Chat column: messages anchor just above the input, growing upward.\n * Sized with a viewport-based height in normal flow — no absolute\n * positioning, so the drawer's own layout is untouched.\n */\n.nf-ai-chat {\n display: flex;\n flex-direction: column;\n height: calc(100vh - 136px);\n min-height: 320px;\n}\n\n.nf-ai-chat-log {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n padding: 4px 2px 10px;\n}\n\n/* Push the conversation to the bottom of the log, chatbot-style. */\n.nf-ai-chat-log > :first-child {\n margin-top: auto;\n}\n\n/* A message row: sender line (avatar + name) above the bubble. */\n.nf-ai-row {\n margin-top: 12px;\n display: flex;\n flex-direction: column;\n}\n\n.nf-ai-row.is-user {\n align-items: flex-end;\n}\n\n.nf-ai-row.is-assistant,\n.nf-ai-row.is-error {\n align-items: flex-start;\n}\n\n.nf-ai-sender {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 4px;\n font-size: 12px;\n color: #72777c;\n}\n\n.nf-ai-sender img {\n width: 22px;\n height: 22px;\n border-radius: 50%;\n display: block;\n}\n\n.nf-ai-sender .nf-ai-time {\n color: #a0a5aa;\n font-size: 11px;\n}\n\n.nf-ai-sender .nf-ai-time::before {\n content: '·';\n margin-right: 6px;\n}\n\n.nf-ai-msg {\n padding: 9px 13px;\n border-radius: 14px;\n line-height: 1.45;\n max-width: 85%;\n white-space: pre-wrap;\n word-wrap: break-word;\n font-size: 14px;\n}\n\n/* Bare messages (no sender row), e.g. the busy indicator. */\n.nf-ai-chat-log > .nf-ai-msg {\n margin-top: 12px;\n}\n\n.nf-ai-msg.is-user {\n background: #1EA9EA;\n color: #fff;\n border-bottom-right-radius: 4px;\n}\n\n.nf-ai-msg.is-assistant {\n background: #fff;\n color: #23282d;\n border: 1px solid #e2e4e7;\n border-bottom-left-radius: 4px;\n}\n\n/*\n * A full border rather than a left accent bar, matching the assistant bubble's\n * treatment. #b32d2e reaches 5.67:1 on this background where #d63638 reached\n * only 4.25:1, short of AA for text this size.\n */\n.nf-ai-msg.is-error {\n background: #fcf0f1;\n color: #b32d2e;\n border: 1px solid #f0b3b4;\n border-radius: 4px;\n}\n\n/* Compact chat input pinned at the bottom. */\n.nf-ai-chat-input {\n display: flex;\n gap: 8px;\n align-items: flex-end;\n padding: 8px 0 4px;\n}\n\n/* ID-scoped: the builder's stylesheet sets a fixed height on drawer textareas. */\n#nf-drawer .nf-ai-chat-input textarea {\n flex: 1;\n resize: none;\n height: 38px;\n min-height: 38px;\n border: 1px solid #ccd0d4;\n border-radius: 18px;\n padding: 8px 14px;\n font-size: 14px;\n line-height: 1.4;\n background: #fff;\n max-height: 120px;\n overflow-y: auto;\n box-sizing: border-box;\n margin: 0;\n}\n\n.nf-ai-chat-send {\n flex: 0 0 auto;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 50%;\n background: #1EA9EA;\n color: #fff;\n cursor: pointer;\n margin-bottom: 1px;\n padding: 0;\n}\n\n.nf-ai-chat-send .dashicons {\n line-height: 36px;\n width: 36px;\n height: 36px;\n font-size: 22px;\n}\n\n.nf-ai-chat-send:hover {\n background: #1590c9;\n}\n\n.nf-ai-chat-send:disabled,\n.nf-ai-chat-input textarea:disabled,\n.nf-ai-provider-select:disabled,\n#nf-drawer .nf-ai-model-trigger:disabled {\n opacity: 0.6;\n cursor: wait;\n}\n\n.nf-ai-chat-reload {\n display: block;\n margin-top: 8px;\n}\n\n.nf-ai-undo-row {\n margin: 2px 0 6px 30px;\n}\n\n.nf-ai-undo {\n background: #fff;\n border: 1px solid #d0d5d9;\n border-radius: 999px;\n padding: 3px 14px;\n font-size: 12px;\n line-height: 1.5;\n color: #3c434a;\n cursor: pointer;\n transition: border-color 0.15s ease, color 0.15s ease;\n}\n\n.nf-ai-undo:hover {\n border-color: #1EA9EA;\n color: #1EA9EA;\n}\n\n/*\n * The connect panel the drawer shows in place of a composer when no provider\n * is connected, rather than offering an empty model list and no way forward.\n */\n.nf-ai-connect {\n padding: 4px 2px;\n color: #50575e;\n font-size: 13px;\n line-height: 1.6;\n}\n\n.nf-ai-connect p {\n margin: 0 0 10px;\n}\n\n.nf-ai-connect-title {\n color: #23282d;\n font-size: 14px;\n font-weight: 600;\n}\n\n/* The save-first modal: why the form must be saved, and what to call it. */\n.nf-ai-save-first p {\n margin: 0 0 12px;\n color: #50575e;\n line-height: 1.6;\n}\n\n.nf-ai-save-first label {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 600;\n}\n\n.nf-ai-save-first .nf-ai-save-first-title {\n width: 100%;\n margin-bottom: 12px;\n}\n\n.nf-ai-save-first #nf-ai-save-first-error {\n margin-bottom: 10px;\n color: #b32d2e;\n font-size: 13px;\n}\n\n/*\n * The chat controls and composer set display, which out-specifies the browser's\n * [hidden] rule, so hiding them needs a class that wins on its own terms.\n */\n.nf-ai-chat .nf-ai-hidden {\n display: none;\n}\n","@charset \"UTF-8\";\n/**\n * AI assistant styles: builder header button + drawer chat.\n *\n * Compiles to assets/css/nf-ai-chat.css (enqueued by NF_AJAX_REST_AIChat).\n */\n/*\n * Header button: identical markup and styling treatment to the public-link\n * icon (span.dashicons inside the anchor, same float/spacing/size), with a\n * blue resting state so it stands out.\n */\n#nf-header .nf-ai-assistant {\n float: right;\n margin-right: 30px;\n padding: 8px 0;\n color: #1EA9EA;\n}\n\n/*\n * Custom AI sparkle glyph: no icon set we ship carries the modern sparkle\n * convention, so it's a masked SVG painted with currentColor — it inherits\n * and transitions color exactly like a font icon.\n */\n.nf-ai-sparkle {\n display: inline-block;\n width: 1em;\n height: 1em;\n vertical-align: -0.125em;\n background-color: currentColor;\n -webkit-mask: url(../img/nf-ai-sparkle.svg) no-repeat center;\n -webkit-mask-size: contain;\n mask: url(../img/nf-ai-sparkle.svg) no-repeat center;\n mask-size: contain;\n}\n\n/* Sized so the sparkle optically matches the 30px public-link dashicon. */\n#nf-header .nf-ai-assistant .nf-ai-sparkle {\n width: 30px;\n height: 30px;\n vertical-align: middle;\n -webkit-mask-size: 26px;\n mask-size: 26px;\n}\n\n#nf-header .nf-ai-assistant:hover {\n color: #1590c9;\n}\n\n/*\n * While the AI drawer is open, hide the dev-mode footer so the panel reads\n * as a chat session, not a settings pane. No layout overrides: the chat is\n * normal-flow drawer content, exactly like the other drawers.\n */\n#nf-drawer.nf-ai-drawer-active .nf-drawer-dev-mode-note {\n display: none;\n}\n\n.nf-ai-chat-title {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n font-size: 16px;\n font-weight: 600;\n color: #23282d;\n padding: 4px 2px 8px;\n border-bottom: 1px solid #e2e4e7;\n}\n\n.nf-ai-chat-title .nf-ai-sparkle {\n color: #1EA9EA;\n margin-right: 6px;\n font-size: 16px;\n}\n\n/*\n * One row above the composer: conversation control on the left, model control\n * on the right. Start new chat used to live inside the model popup, where it\n * existed only while that popup was open and two reviewers failed to find it.\n */\n.nf-ai-chat-controls {\n flex: 0 0 auto;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 5px 2px 0;\n border-top: 1px solid #e2e4e7;\n}\n\n.nf-ai-model-control {\n flex: 0 1 auto;\n min-width: 0;\n position: relative;\n display: flex;\n justify-content: flex-end;\n}\n\n#nf-drawer .nf-ai-model-menu {\n overscroll-behavior: contain;\n}\n#nf-drawer .nf-ai-model-search {\n width: 100%;\n box-sizing: border-box;\n}\n#nf-drawer .nf-ai-model-group {\n border-top: 1px solid #f0f0f1;\n}\n#nf-drawer .nf-ai-model-group strong {\n display: block;\n padding: 2px 7px 5px;\n color: #646970;\n font-size: 11px;\n}\n#nf-drawer .nf-ai-model-option,\n#nf-drawer .nf-ai-model-show-all {\n display: block;\n width: 100%;\n padding: 6px 7px;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: #2c3338;\n font-size: 12px;\n text-align: left;\n cursor: pointer;\n}\n#nf-drawer .nf-ai-model-option:hover,\n#nf-drawer .nf-ai-model-option:focus,\n#nf-drawer .nf-ai-model-option.is-active,\n#nf-drawer .nf-ai-model-option.is-selected {\n background: #f0f6fc;\n color: #135e96;\n}\n#nf-drawer .nf-ai-model-option.is-active {\n outline: 2px solid #2271b1;\n outline-offset: -2px;\n}\n#nf-drawer .nf-ai-model-option.is-extra,\n#nf-drawer .nf-ai-model-menu.is-searching .nf-ai-model-show-all,\n#nf-drawer .nf-ai-model-group.show-all .nf-ai-model-show-all {\n display: none;\n}\n#nf-drawer .nf-ai-model-group.show-all .nf-ai-model-option.is-extra,\n#nf-drawer .nf-ai-model-menu.is-searching .nf-ai-model-option.is-extra {\n display: block;\n}\n#nf-drawer .nf-ai-model-option.is-filtered-out {\n display: none;\n}\n#nf-drawer .nf-ai-model-show-all {\n color: #2271b1;\n font-size: 11px;\n}\n\n#nf-drawer .nf-ai-model-trigger {\n width: auto;\n max-width: 100%;\n min-height: 24px;\n display: inline-flex;\n align-items: center;\n justify-content: flex-end;\n gap: 3px;\n margin: 0;\n padding: 1px 0;\n border: 0;\n border-radius: 2px;\n background: transparent;\n box-shadow: none;\n color: #646970;\n font-size: 11px;\n text-align: right;\n cursor: pointer;\n}\n\n#nf-drawer .nf-ai-model-trigger:hover {\n background: transparent;\n color: #2271b1;\n}\n\n#nf-drawer .nf-ai-model-trigger:focus {\n outline: none;\n background: transparent;\n box-shadow: 0 0 0 1px #2271b1;\n color: #135e96;\n}\n\n.nf-ai-model-current {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n#nf-drawer .nf-ai-model-trigger .dashicons {\n flex: 0 0 auto;\n width: 16px;\n height: 16px;\n font-size: 16px;\n line-height: 16px;\n transition: transform 0.15s ease;\n}\n\n.nf-ai-model-control.is-open .nf-ai-model-trigger .dashicons {\n transform: rotate(180deg);\n}\n\n.nf-ai-model-menu {\n position: absolute;\n right: 0;\n left: 0;\n max-height: 300px;\n overflow-y: auto;\n padding: 9px;\n border: 1px solid #c3c4c7;\n border-radius: 6px;\n background: #fff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);\n z-index: 30;\n bottom: calc(100% - 2px);\n}\n\n.nf-ai-model-control:not(.is-open) .nf-ai-model-menu {\n display: none;\n}\n\n#nf-drawer .nf-ai-model-search {\n height: 32px;\n margin: 0 0 8px;\n}\n\n.nf-ai-model-group {\n padding: 6px 0;\n}\n\n#nf-drawer .nf-ai-model-option,\n#nf-drawer .nf-ai-model-show-all {\n min-height: 0;\n margin: 0;\n}\n\n#nf-drawer .nf-ai-start-new-chat {\n flex: 0 0 auto;\n width: auto;\n min-height: 0;\n margin: 0;\n padding: 6px 7px;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: #646970;\n font-size: 12px;\n text-align: left;\n white-space: nowrap;\n cursor: pointer;\n}\n\n#nf-drawer .nf-ai-start-new-chat:hover,\n#nf-drawer .nf-ai-start-new-chat:focus {\n background: #f0f0f1;\n color: #2c3338;\n}\n\n#nf-drawer .nf-ai-start-new-chat:disabled {\n opacity: 0.6;\n cursor: wait;\n}\n\n.nf-ai-spin {\n animation: nf-ai-spin-anim 1s linear infinite;\n}\n\n@keyframes nf-ai-spin-anim {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n/*\n * Chat column: messages anchor just above the input, growing upward.\n * Sized with a viewport-based height in normal flow — no absolute\n * positioning, so the drawer's own layout is untouched.\n */\n.nf-ai-chat {\n display: flex;\n flex-direction: column;\n height: calc(100vh - 136px);\n min-height: 320px;\n}\n\n.nf-ai-chat-log {\n flex: 1;\n overflow-y: auto;\n display: flex;\n flex-direction: column;\n padding: 4px 2px 10px;\n}\n\n/* Push the conversation to the bottom of the log, chatbot-style. */\n.nf-ai-chat-log > :first-child {\n margin-top: auto;\n}\n\n/* A message row: sender line (avatar + name) above the bubble. */\n.nf-ai-row {\n margin-top: 12px;\n display: flex;\n flex-direction: column;\n}\n\n.nf-ai-row.is-user {\n align-items: flex-end;\n}\n\n.nf-ai-row.is-assistant,\n.nf-ai-row.is-error {\n align-items: flex-start;\n}\n\n.nf-ai-sender {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 4px;\n font-size: 12px;\n color: #72777c;\n}\n\n.nf-ai-sender img {\n width: 22px;\n height: 22px;\n border-radius: 50%;\n display: block;\n}\n\n.nf-ai-sender .nf-ai-time {\n color: #a0a5aa;\n font-size: 11px;\n}\n\n.nf-ai-sender .nf-ai-time::before {\n content: \"·\";\n margin-right: 6px;\n}\n\n.nf-ai-msg {\n padding: 9px 13px;\n border-radius: 14px;\n line-height: 1.45;\n max-width: 85%;\n white-space: pre-wrap;\n word-wrap: break-word;\n font-size: 14px;\n}\n\n/* Bare messages (no sender row), e.g. the busy indicator. */\n.nf-ai-chat-log > .nf-ai-msg {\n margin-top: 12px;\n}\n\n.nf-ai-msg.is-user {\n background: #1EA9EA;\n color: #fff;\n border-bottom-right-radius: 4px;\n}\n\n.nf-ai-msg.is-assistant {\n background: #fff;\n color: #23282d;\n border: 1px solid #e2e4e7;\n border-bottom-left-radius: 4px;\n}\n\n/*\n * A full border rather than a left accent bar, matching the assistant bubble's\n * treatment. #b32d2e reaches 5.67:1 on this background where #d63638 reached\n * only 4.25:1, short of AA for text this size.\n */\n.nf-ai-msg.is-error {\n background: #fcf0f1;\n color: #b32d2e;\n border: 1px solid #f0b3b4;\n border-radius: 4px;\n}\n\n/* Compact chat input pinned at the bottom. */\n.nf-ai-chat-input {\n display: flex;\n gap: 8px;\n align-items: flex-end;\n padding: 8px 0 4px;\n}\n\n/* ID-scoped: the builder's stylesheet sets a fixed height on drawer textareas. */\n#nf-drawer .nf-ai-chat-input textarea {\n flex: 1;\n resize: none;\n height: 38px;\n min-height: 38px;\n border: 1px solid #ccd0d4;\n border-radius: 18px;\n padding: 8px 14px;\n font-size: 14px;\n line-height: 1.4;\n background: #fff;\n max-height: 120px;\n overflow-y: auto;\n box-sizing: border-box;\n margin: 0;\n}\n\n.nf-ai-chat-send {\n flex: 0 0 auto;\n width: 36px;\n height: 36px;\n border: none;\n border-radius: 50%;\n background: #1EA9EA;\n color: #fff;\n cursor: pointer;\n margin-bottom: 1px;\n padding: 0;\n}\n\n.nf-ai-chat-send .dashicons {\n line-height: 36px;\n width: 36px;\n height: 36px;\n font-size: 22px;\n}\n\n.nf-ai-chat-send:hover {\n background: #1590c9;\n}\n\n.nf-ai-chat-send:disabled,\n.nf-ai-chat-input textarea:disabled,\n.nf-ai-provider-select:disabled,\n#nf-drawer .nf-ai-model-trigger:disabled {\n opacity: 0.6;\n cursor: wait;\n}\n\n.nf-ai-chat-reload {\n display: block;\n margin-top: 8px;\n}\n\n.nf-ai-undo-row {\n margin: 2px 0 6px 30px;\n}\n\n.nf-ai-undo {\n background: #fff;\n border: 1px solid #d0d5d9;\n border-radius: 999px;\n padding: 3px 14px;\n font-size: 12px;\n line-height: 1.5;\n color: #3c434a;\n cursor: pointer;\n transition: border-color 0.15s ease, color 0.15s ease;\n}\n\n.nf-ai-undo:hover {\n border-color: #1EA9EA;\n color: #1EA9EA;\n}\n\n/*\n * The connect panel the drawer shows in place of a composer when no provider\n * is connected, rather than offering an empty model list and no way forward.\n */\n.nf-ai-connect {\n padding: 4px 2px;\n color: #50575e;\n font-size: 13px;\n line-height: 1.6;\n}\n\n.nf-ai-connect p {\n margin: 0 0 10px;\n}\n\n.nf-ai-connect-title {\n color: #23282d;\n font-size: 14px;\n font-weight: 600;\n}\n\n/* The save-first modal: why the form must be saved, and what to call it. */\n.nf-ai-save-first p {\n margin: 0 0 12px;\n color: #50575e;\n line-height: 1.6;\n}\n\n.nf-ai-save-first label {\n display: block;\n margin-bottom: 6px;\n font-size: 13px;\n font-weight: 600;\n}\n\n.nf-ai-save-first .nf-ai-save-first-title {\n width: 100%;\n margin-bottom: 12px;\n}\n\n.nf-ai-save-first #nf-ai-save-first-error {\n margin-bottom: 10px;\n color: #b32d2e;\n font-size: 13px;\n}\n\n/*\n * The chat controls and composer set display, which out-specifies the browser's\n * [hidden] rule, so hiding them needs a class that wins on its own terms.\n */\n.nf-ai-chat .nf-ai-hidden {\n display: none;\n}","// The drop-down panel both pickers open is the same piece of chrome: a bordered\n// white card that stretches the width of its trigger and scrolls its own list.\n// Only the arbitrary sizing differs between the two hosts, so it is passed in;\n// where the panel is anchored and how it stacks are genuinely per-surface and\n// stay at the call site with the rest of that surface's positioning.\n@mixin model-menu-chrome($max-height, $padding, $shadow-alpha) {\n position: absolute;\n right: 0;\n left: 0;\n max-height: $max-height;\n overflow-y: auto;\n padding: $padding;\n border: 1px solid #c3c4c7;\n border-radius: 6px;\n background: #fff;\n box-shadow: 0 8px 24px rgba(0, 0, 0, $shadow-alpha);\n}\n\n@mixin model-picker($option-padding, $option-size, $heading-size, $show-all-size) {\n // The menu owns its wheel events, so it also has to stop the scroll from\n // continuing into whatever is behind it once the list reaches an end.\n .nf-ai-model-menu {\n overscroll-behavior: contain;\n }\n\n .nf-ai-model-search {\n width: 100%;\n box-sizing: border-box;\n }\n\n .nf-ai-model-group {\n border-top: 1px solid #f0f0f1;\n }\n\n .nf-ai-model-group strong {\n display: block;\n padding: 2px 7px 5px;\n color: #646970;\n font-size: $heading-size;\n }\n\n .nf-ai-model-option,\n .nf-ai-model-show-all {\n display: block;\n width: 100%;\n padding: $option-padding;\n border: 0;\n border-radius: 3px;\n background: transparent;\n color: #2c3338;\n font-size: $option-size;\n text-align: left;\n cursor: pointer;\n }\n\n .nf-ai-model-option:hover,\n .nf-ai-model-option:focus,\n .nf-ai-model-option.is-active,\n .nf-ai-model-option.is-selected {\n background: #f0f6fc;\n color: #135e96;\n }\n\n // Arrow keys move a cursor through the list while focus stays in the search\n // field, so the option under that cursor needs a mark of its own.\n .nf-ai-model-option.is-active {\n outline: 2px solid #2271b1;\n outline-offset: -2px;\n }\n\n .nf-ai-model-option.is-extra,\n .nf-ai-model-menu.is-searching .nf-ai-model-show-all,\n .nf-ai-model-group.show-all .nf-ai-model-show-all {\n display: none;\n }\n\n .nf-ai-model-group.show-all .nf-ai-model-option.is-extra,\n .nf-ai-model-menu.is-searching .nf-ai-model-option.is-extra {\n display: block;\n }\n\n // Search filtering owns visibility here so the keyboard cursor and the\n // stylesheet cannot disagree about which options are on offer. It follows\n // the rules above so a filtered-out option stays hidden either way.\n .nf-ai-model-option.is-filtered-out {\n display: none;\n }\n\n .nf-ai-model-show-all {\n color: #2271b1;\n font-size: $show-all-size;\n }\n}\n"]}