{"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"]}