/* Fragment 4/9 of the former static/style.css. * * This is a mechanical, order-preserving slice: rules were moved verbatim * and this file's position in the order of static/index.html is what * keeps the cascade identical. Reordering the links, or moving a rule between * fragments, can change which of two competing declarations wins. * * static/index.html and the PRECACHE list in static/sw.js must list every * fragment in the same order. tests/test_static_stylesheet_manifest.py and * tests/test_css_computed_style_snapshot.py both fail if that drifts. */ /* ===== Markdown highlighting — document editor ===== IMPORTANT: this is an overlay layered behind a transparent textarea, so every styled token must occupy the EXACT same width as the corresponding characters in the textarea. Anything that changes glyph metrics (font-weight/style, padding, border, letter-spacing) makes the caret drift away from the rendered glyph underneath. Color / background / text- decoration are safe — they don't change layout width. */ .doc-editor-highlight .language-markdown .hljs-section { color: var(--hl-keyword, #c678dd); } .doc-editor-highlight .language-markdown .hljs-strong { color: var(--hl-number, #d19a66); } .doc-editor-highlight .language-markdown .hljs-emphasis { color: var(--hl-string, #e5c07b); } .doc-editor-highlight .language-markdown .hljs-bullet { color: var(--hl-builtin, #56b6c2); } .doc-editor-highlight .language-markdown .hljs-code { color: var(--hl-builtin, #56b6c2); background: color-mix(in srgb, var(--hl-builtin, #56b6c2) 10%, transparent); border-radius: 2px; } .doc-editor-highlight .language-markdown .hljs-link { color: var(--hl-function, #61afef); text-decoration: underline; } .doc-editor-highlight .language-markdown .hljs-quote { color: var(--hl-comment, #828997); } .doc-editor-highlight .language-markdown .hljs-symbol { color: var(--red); } /* Standalone [bracketed text] — scene directions, annotations */ .doc-editor-highlight .language-markdown .md-bracket { color: var(--hl-builtin, #56b6c2); opacity: 0.85; } /* Heading # markers — dimmer than the heading text */ .doc-editor-highlight .language-markdown .md-heading-marker { color: var(--hl-comment, #828997); font-weight: 400; } /* ===== CUSTOM PRESET MODAL ===== */ .preset-modal-content { width: min(460px, 90vw); border-radius: 12px; overflow: hidden; } .preset-modal-body { display: flex; flex-direction: column; overflow-x: hidden; } /* Footer Start/Cancel buttons get a leading icon. Done via ::before + a masked SVG (not an inline child) because the labels are set with .textContent, which would wipe a child element on every tab switch. background:currentColor makes the icon follow the button's text color. */ #save-custom-preset, #cancel-custom-preset { display: inline-flex; align-items: center; gap: 6px; } #save-custom-preset::before, #cancel-custom-preset::before { content: ""; width: 13px; height: 13px; flex-shrink: 0; background-color: currentColor; -webkit-mask: var(--_btn-ic) center / contain no-repeat; mask: var(--_btn-ic) center / contain no-repeat; } #save-custom-preset::before { --_btn-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolygon points='5 3 19 12 5 21 5 3'/%3E%3C/svg%3E"); } #cancel-custom-preset::before { --_btn-ic: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3C/svg%3E"); } .preset-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin: 0 -10px 12px; padding: 0 10px; margin: 0 -16px; padding: 0 16px; margin-bottom: 12px; } .preset-tab { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 10px; background: none; border: none; border-bottom: 2px solid transparent; color: var(--color-muted); font-family: inherit; font-size: 13px; font-weight: 500; cursor: pointer; transition: all 0.15s; } .preset-tab-icon { flex-shrink: 0; } /* On narrow widths the icon + label can crowd 4 tabs — drop the labels to icon-only so the row stays clean. */ @media (max-width: 460px) { .preset-tab span { display: none; } } .preset-tab:hover { color: var(--fg); background: color-mix(in srgb, var(--fg) 4%, transparent); } .preset-tab.active { color: var(--red); border-bottom-color: var(--red); } .preset-tab-content { overflow: hidden; } .preset-tab-content.hidden { display: none; } .preset-templates-hint { font-size: 11px; color: var(--color-muted); margin: 0 0 8px; } .prompt-templates-list { display: flex; flex-direction: column; gap: 6px; max-height: 300px; overflow-y: auto; } .prompt-template-card { padding: 10px 12px; border: 1px solid var(--border); border-radius: 6px; background: color-mix(in srgb, var(--fg) 3%, transparent); cursor: pointer; transition: all 0.15s; } .prompt-template-card:hover { background: color-mix(in srgb, var(--accent) 8%, transparent); border-color: color-mix(in srgb, var(--accent) 30%, transparent); } .prompt-template-card.selected { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); } .prompt-template-name { font-size: 12px; font-weight: 600; color: var(--fg); margin-bottom: 4px; } .prompt-template-preview { font-size: 11px; color: var(--color-muted); line-height: 1.4; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .preset-slider-row { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; margin-bottom: 6px; } .preset-slider-row label { font-size: 13px; color: var(--fg); font-weight: 500; margin: 0; } .preset-slider-value { font-size: 12px; color: var(--fg); font-weight: 600; min-width: 40px; text-align: right; } .preset-range { -webkit-appearance: none; appearance: none; width: 100%; height: 6px; background: var(--border); border-radius: 4px; outline: none; margin-bottom: 4px; box-sizing: border-box; display: block; padding: 0; margin-left: 0; margin-right: 0; } .preset-range::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 18px; height: 18px; border-radius: 50%; background: var(--red, var(--fg)); cursor: pointer; border: 2px solid var(--panel); box-shadow: 0 1px 4px rgba(0,0,0,0.2); } .preset-range::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: var(--red, var(--fg)); cursor: pointer; border: 2px solid var(--panel); box-shadow: 0 1px 4px rgba(0,0,0,0.2); } .preset-range::-webkit-slider-runnable-track { height: 6px; border-radius: 4px; } .preset-range::-moz-range-track { height: 6px; background: var(--border); border-radius: 4px; } .preset-temp-hints { display: flex; font-size: 10px; color: var(--color-muted); margin-top: -4px; margin-bottom: 10px; padding: 0 2px; opacity: 0.7; } .preset-temp-hints span { flex: 1; } .preset-temp-hints span:nth-child(2) { text-align: center; } .preset-temp-hints span:last-child { text-align: right; } .preset-clear-btn { padding: 7px 14px; background: none; border: 1px solid var(--border); color: var(--color-muted); border-radius: 6px; cursor: pointer; font-size: 12px; font-weight: 500; transition: all 0.15s; } .preset-clear-btn:hover { color: var(--color-error); border-color: var(--color-error); } .preset-hint-icon { display: inline-flex; align-items: center; justify-content: center; width: 15px; height: 15px; border-radius: 50%; border: 1px solid var(--border); font-size: 10px; font-weight: 600; color: var(--color-muted); cursor: help; vertical-align: middle; margin-left: 4px; transition: all 0.15s; } .preset-hint-icon:hover { color: var(--fg); border-color: var(--fg); } .preset-section-header { font-size: 11px; font-weight: 600; color: var(--color-muted); text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 6px; padding: 0 2px; } .user-template-card { position: relative; } .user-template-delete { background: none; border: none; color: var(--color-muted); font-size: 13px; cursor: pointer; padding: 0 2px; line-height: 1; opacity: 0; transition: opacity 0.15s, color 0.15s; } .user-template-card:hover .user-template-delete { opacity: 1; } .user-template-delete:hover { color: var(--color-error); } .preset-save-template-btn { padding: 7px 14px; border-radius: 6px; font-size: 12px; font-weight: 500; border: 1px solid var(--border); background: none; color: var(--fg); cursor: pointer; transition: all 0.15s; } .preset-save-template-btn:hover { border-color: var(--accent, var(--red)); color: var(--accent, var(--red)); } .char-prompt-wrap { position: relative; } .char-prompt-wrap textarea { padding-bottom: 28px; } .char-expand-btn { position: absolute; bottom: 14px; right: 6px; background: var(--panel); border: 1px solid var(--border); border-radius: 4px; color: var(--color-muted); font-size: 11px; padding: 2px 8px; cursor: pointer; transition: all 0.15s; margin: 0; z-index: 1; } .char-expand-btn:hover { color: var(--red); border-color: var(--red); } .char-expand-btn.expanding { opacity: 0.5; pointer-events: none; } /* Memory scope bar (My Memories / Characters) */ .memory-scope-bar { display: flex; gap: 0; margin: 0 0 8px 0 !important; padding: 0 !important; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; } .memory-scope-btn { flex: 1; padding: 8px 12px !important; margin: 0 !important; font-size: 11px !important; font-weight: 600; background: none; border: none; color: var(--fg); opacity: 0.5; cursor: pointer; transition: all 0.15s; } .memory-scope-btn + .memory-scope-btn { border-left: 1px solid var(--border); } .memory-scope-btn.active { background: color-mix(in srgb, var(--red) 12%, transparent); color: var(--red); opacity: 1; } .memory-scope-btn:hover:not(.active) { background: color-mix(in srgb, var(--fg) 5%, transparent); } .memory-char-list { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 8px; } .memory-char-chip { padding: 4px 10px; font-size: 11px; font-weight: 500; border: 1px solid var(--border); border-radius: 12px; background: none; color: var(--fg); cursor: pointer; transition: all 0.15s; margin: 0; } .memory-char-chip.active { background: color-mix(in srgb, var(--red) 12%, transparent); border-color: var(--red); color: var(--red); } .memory-char-chip:hover:not(.active) { background: color-mix(in srgb, var(--fg) 6%, transparent); } /* Disabled state dims the form */ #char-fields-wrap.disabled { opacity: 0.35; pointer-events: none; filter: grayscale(0.5); transition: opacity 0.2s, filter 0.2s; } #char-fields-wrap { transition: opacity 0.2s, filter 0.2s; } /* Name combo: input + delete btn */ .char-name-combo { display: flex; gap: 4px; align-items: center; margin-bottom: 8px; } .char-name-combo input, .char-name-combo select { flex: 1; } .char-template-select { background: var(--panel); border: 1px solid var(--border); border-radius: 6px; color: var(--fg); padding: 6px 8px; font-size: 13px; font-family: inherit; cursor: pointer; } .char-template-select:focus { outline: none; border-color: var(--red); } .char-action-btn { background: none; border: 1px solid var(--border); border-radius: 6px; color: var(--color-muted); font-size: 11px; padding: 4px 8px; cursor: pointer; transition: all 0.15s; flex-shrink: 0; margin: 0 !important; white-space: nowrap; /* Uniform width so the trailing button column matches between the select row (+ New) and the name row (Reset) — that keeps the select and the name input the same width, since both fields flex:1 into the leftover. */ min-width: 64px; text-align: center; } .char-action-btn:hover { color: var(--fg); border-color: var(--fg); } #char-delete-template-btn:hover { color: var(--color-error); border-color: var(--color-error); } /* Character toggle row in preset modal */ .preset-toggle-row { display: flex; align-items: center; gap: 6px; margin-top: 12px; font-size: 13px; color: var(--fg); } .preset-sub-option { display: flex; align-items: center; gap: 6px; margin-top: 6px; padding: 8px 10px; font-size: 12px; color: var(--color-muted); background: var(--panel); border: 1px solid var(--border); border-radius: 6px; } .preset-mem-choice { flex: 1; padding: 6px 10px; font-size: 12px; font-weight: 500; border: 1px solid var(--border); border-radius: 6px; background: none; color: var(--fg); cursor: pointer; transition: all 0.15s; margin: 0; } .preset-mem-choice.active { background: color-mix(in srgb, var(--red) 12%, transparent); border-color: var(--red); color: var(--red); } .preset-mem-choice:hover:not(.active) { background: color-mix(in srgb, var(--fg) 6%, transparent); } /* ===== MEMORY MODAL ===== */ .memory-modal-content { width: min(560px, 90vw); max-height: 78vh; font-size: 12px; overflow: hidden; /* clip both axes; the inner .memory-modal-body owns scrolling. (overflow-x alone promotes overflow-y to `auto` → a stray vertical scrollbar) */ /* Subtle synapse-pulse — a soft radial glow that breathes in/out. Layered over the existing modal bg so it shows through without overpowering content. */ position: relative; isolation: isolate; } .memory-modal-content::before { content: none; } @media (prefers-reduced-motion: reduce) { .memory-modal-content::before { animation: none; opacity: 0.4; } } .memory-modal-content .modal-header h4 { font-size: 1rem; } .memory-modal-body { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; overflow-x: hidden; /* Stop synapse-pulse pseudo-elements from triggering a sideways scrollbar */ overscroll-behavior: contain; min-height: 0; /* Fill the modal-content's height so the flex chain (tab-panel → admin-card → list → expanded card) is bounded. Without this the chain grows to content, so an expanded skill card pushed its footer off-screen; capping the preview then left it floating too high. Bounding here lets the preview flex to fill and the footer pin to the bottom naturally. */ flex: 1 1 auto; } .memory-tabs { display: flex; gap: 0; border-bottom: 1px solid var(--border); margin: -4px -4px 0; padding: 0 4px; flex-shrink: 0; } #memory-modal [data-memory-scope].hidden { display: none !important; } .memory-tab { background: none; border: none; color: var(--fg); opacity: 0.5; font-size: 12px; font-family: inherit; padding: 8px 14px; cursor: pointer; border-bottom: 2px solid transparent; transition: opacity 0.15s, border-color 0.15s, color 0.15s, background 0.15s; } .memory-tab:hover { opacity: 0.8; background: color-mix(in srgb, var(--fg) 5%, transparent); } .memory-tab.active { opacity: 1; color: var(--red); border-bottom-color: var(--red); } .memory-tab-panel { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; /* overflow-y:auto makes the browser compute overflow-x to `auto` too, which produced a stray horizontal scrollbar whenever a child was slightly too wide (long unbroken memory text, or the skills two-column row). Clip X explicitly — inner code blocks keep their own overflow-x:auto. */ overflow-x: hidden; flex: 1; min-width: 0; min-height: 0; } .memory-tab-panel.hidden { display: none; } /* Browse: bounded flex column so #memory-list gets remaining height (not 0px). height:min(78vh,max-content) gives a definite cap when long, natural height when short. flex-basis:auto (not 0) on the list avoids collapse in auto-sized parents. Toolbar siblings are flex-shrink:0; only #memory-list grows. */ #memory-modal .memory-modal-content:has( .memory-tab-panel[data-memory-panel="browse"]:not(.hidden) ) { display: flex; flex-direction: column; max-height: 78vh; height: 78vh; overflow: hidden; } #memory-modal .memory-modal-content:has( .memory-tab-panel[data-memory-panel="browse"]:not(.hidden) ) .modal-header, #memory-modal .memory-modal-content:has( .memory-tab-panel[data-memory-panel="browse"]:not(.hidden) ) .memory-tabs { flex: 0 0 auto; } #memory-modal .memory-modal-content:has( .memory-tab-panel[data-memory-panel="browse"]:not(.hidden) ) .memory-modal-body { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow: hidden; } #memory-modal .memory-tab-panel[data-memory-panel="browse"] { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow: hidden; } #memory-modal .memory-tab-panel[data-memory-panel="browse"] > .admin-card { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow: hidden; } #memory-modal .memory-tab-panel[data-memory-panel="browse"] > .admin-card > *:not(#memory-list):not(#memory-suggestions-body) { flex: 0 0 auto; } #memory-modal .memory-tab-panel[data-memory-panel="browse"] #memory-list:not(.hidden), #memory-modal .memory-tab-panel[data-memory-panel="browse"] #memory-suggestions-body:not(.hidden) { flex: 1 1 auto; min-height: 0; overflow-y: auto; } #memory-modal .memory-tab-panel[data-memory-panel="browse"] #memory-suggestions-body:not(.hidden) .memory-suggestions-header { flex-shrink: 0; position: sticky; top: 0; z-index: 1; background: var(--bg); } #memory-modal .memory-tab-panel[data-memory-panel].hidden { display: none; } /* Settings cards dim + mute when their toggle is OFF (matches the .memory-toolbar-toggle "off" treatment elsewhere). */ #memory-modal .memory-tab-panel[data-memory-panel="settings"] .admin-card { transition: opacity 0.15s, border-color 0.15s, background 0.15s; } #memory-modal .memory-tab-panel[data-memory-panel="settings"] .admin-card:has(.admin-switch input:not(:checked)) { opacity: 0.55; border-color: color-mix(in srgb, var(--fg) 8%, transparent); background: color-mix(in srgb, var(--fg) 2%, transparent); } /* Skills tab — two-column layout: skills list (left, wider) + Add Skill form (right, narrower). Collapses to a single column on narrow screens. */ .memory-tab-panel[data-memory-panel="skills"] { flex-direction: row; align-items: stretch; gap: 10px; } .memory-tab-panel[data-memory-panel="skills"] > .admin-card:first-of-type { flex: 2 1 0; min-width: 0; } /* The shared chip-scroll frame is a flex-growing row by default. In the vertical Skills card it must stay content-sized so #skills-list keeps the remaining height for the skill cards. */ .memory-tab-panel[data-memory-panel="skills"] > .admin-card > .doclib-chip-scroll-frame { flex: 0 0 auto; min-height: 25px; } .memory-tab-panel[data-memory-panel="skills"] > .admin-card:nth-of-type(2) { flex: 1 1 0; margin-top: 0 !important; min-width: 220px; } @media (max-width: 640px) { .memory-tab-panel[data-memory-panel="skills"] { flex-direction: column; } .memory-tab-panel[data-memory-panel="skills"] > .admin-card:nth-of-type(2) { margin-top: 12px !important; } } .memory-desc { margin: 0; font-size: 11px; line-height: 1.5; /* 65% keeps this description text above WCAG AA 4.5:1 (50% was ~3.9:1). */ color: color-mix(in srgb, var(--fg) 65%, transparent); } .memory-add-row { display: flex; gap: 6px; align-items: center; height: 32px; } /* Skill Import beside URL field — match input height; cancel modal-body button margin. */ .memory-add-row .theme-io-btn { flex: none; height: 28px; box-sizing: border-box; margin-top: 0; padding: 5px 10px; } .memory-add-input { flex: 1; height: 28px; padding: 0 10px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg); color: var(--fg); font-family: inherit; font-size: 12px; box-sizing: border-box; } /* Textareas need explicit vertical padding — inputs vertically center text via line-height/height; textareas would otherwise pin text to the top. */ textarea.memory-add-input { height: auto; padding: 6px 10px; line-height: 1.4; } .memory-add-input:focus { outline: none; border-color: var(--red); } .memory-add-btn { width: 28px; height: 28px; border-radius: 6px; border: 1px solid var(--border); background: var(--bg); color: var(--fg); font-size: 16px; box-sizing: border-box; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s; flex-shrink: 0; } .memory-add-btn:hover { background: var(--panel); border-color: var(--red); color: var(--red); } .memory-toolbar { display: flex; flex-direction: column; gap: 6px; padding: 4px 0 8px; } .memory-toolbar-row { display: flex; align-items: center; gap: 8px; } .memory-toolbar-btn { background: none; border: 1px solid var(--border); color: color-mix(in srgb, var(--fg) 60%, transparent); font-size: 11px; height: 24px; padding: 0 8px; border-radius: 6px; cursor: pointer; font-family: inherit; transition: all 0.15s; white-space: nowrap; } .memory-toolbar-btn:hover { border-color: var(--fg); color: var(--fg); } .memory-toolbar-btn.active { background: color-mix(in srgb, var(--red) 15%, transparent); border-color: color-mix(in srgb, var(--red) 40%, transparent); color: var(--red); } .email-note-actions .memory-toolbar-btn.active:hover { color: var(--fg); } .memory-toolbar-btn.danger { color: var(--color-error); border-color: var(--color-error); } .memory-toolbar-btn.danger:hover { background: color-mix(in srgb, var(--color-error) 10%, transparent); } .memory-toolbar-btn:disabled { opacity: 0.35; cursor: default; outline: none; } .memory-toolbar-btn.spinning { border-color: transparent; background: none; } .memory-toolbar-toggle { display: flex; align-items: center; gap: 5px; font-size: 11px; height: 24px; color: color-mix(in srgb, var(--fg) 60%, transparent); cursor: pointer; padding: 0 4px; user-select: none; transition: all 0.15s; } .memory-toolbar-toggle:hover { color: var(--fg); } .memory-toolbar-toggle .admin-switch { vertical-align: middle; } .memory-toolbar-toggle:has(input:not(:checked)) { opacity: 0.7; } /* Bulk action bar */ .memory-bulk-bar { display: flex; align-items: center; gap: 8px; padding: 6px 2px; margin-bottom: 2px; border: 1px solid color-mix(in srgb, var(--red) 30%, transparent); border-radius: 8px; background: color-mix(in srgb, var(--red) 5%, transparent); font-size: 11px; } .memory-bulk-bar.hidden { display: none; } /* Custom Memory sort picker — replaces the native

. */ .a11y-visually-hidden { position: absolute !important; width: 1px !important; height: 1px !important; padding: 0 !important; margin: -1px !important; overflow: hidden !important; clip: rect(0, 0, 0, 0) !important; white-space: nowrap !important; border: 0 !important; } /* ── Custom language type picker (replaces visible chrome of native */ .adm-provider-picker { position: relative; margin-bottom: 6px; } .adm-provider-combo { display: flex; align-items: stretch; } .adm-provider-combo input { flex: 1; min-width: 0; border-top-right-radius: 0; border-bottom-right-radius: 0; } .adm-provider-btn { width: 100%; display: flex; align-items: center; gap: 8px; background: var(--bg); color: var(--fg); border: 1px solid var(--border); border-radius: 6px; padding: 5px 8px; font-family: inherit; font-size: 12px; cursor: pointer; text-align: left; } .adm-provider-combo .adm-provider-btn { width: 128px; flex-shrink: 0; border-left: 0; border-top-left-radius: 0; border-bottom-left-radius: 0; justify-content: space-between; } .adm-provider-btn:hover { border-color: color-mix(in srgb, var(--fg) 30%, var(--border)); } .adm-provider-current { flex: 1; display: flex; align-items: center; gap: 8px; min-width: 0; } .adm-provider-logo { width: 14px; height: 14px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--fg); opacity: 0.85; } .adm-provider-logo svg { width: 14px; height: 14px; } /* Pull the settings-select 4px closer to its logo chip so the row reads as logo+select instead of having an extra gap. */ .adm-model-logo + .settings-select { margin-left: -4px; } /* Fallback rows: stretch the model select so the trash button on the right aligns with the right edge of the Endpoint and Model dropdowns above the fallback list. Without flex:1 the model select shrinks to its content and the trash button rides up tight to it. */ .settings-fallback-row > .settings-select { flex: 1 1 0; min-width: 0; } /* Constrain logo SVGs in settings dropdown chips. Many provider icons in providers.js declare only viewBox (no width/height), so without this rule the browser falls back to 300x150 and blows up the row. */ .settings-fallback-row > span[style*="width:18px"] svg:not([width]), .settings-row > span[style*="width:18px"] svg:not([width]), span[id$="-logo"] svg:not([width]) { width: 100%; height: 100%; display: block; } .adm-provider-logo:empty { background: color-mix(in srgb, var(--fg) 12%, transparent); border-radius: 50%; } .adm-provider-caret { flex-shrink: 0; transition: transform 0.15s; } .adm-provider-picker:has(.adm-provider-menu:not(.hidden)) .adm-provider-caret { transform: rotate(180deg); } .adm-provider-menu { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 100; max-height: 280px; overflow-y: auto; background: var(--panel); border: 1px solid var(--border); border-radius: 6px; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); padding: 4px; } .adm-provider-menu.hidden { display: none; } .adm-provider-item { display: flex; align-items: center; gap: 8px; padding: 5px 8px; border-radius: 4px; font-size: 12px; cursor: pointer; } .adm-provider-item:hover { background: color-mix(in srgb, var(--fg) 8%, transparent); } .adm-provider-item.active { background: color-mix(in srgb, var(--accent, var(--red)) 14%, transparent); } /* When the Appearance tab is open, the #settings-modal-opacity slider (in the header) fades the modal so the user can see the rest of the UI react as toggles flip. The fade is applied as a background color-mix in JS (settings.js) rather than element opacity, so the controls/text stay crisp — mirroring the Theme customizer's opacity slider. */ /* Search provider fallback chain — chips + drag-reorder */ .search-fallback-chain { flex: 1; display: flex; align-items: center; flex-wrap: wrap; gap: 6px; min-height: 28px; } .search-fb-chip { display: inline-flex; align-items: center; gap: 4px; padding: 3px 4px 3px 6px; background: color-mix(in srgb, var(--fg) 6%, transparent); border: 1px solid var(--border); border-radius: 10px; font-size: 11px; cursor: grab; user-select: none; } .search-fb-chip.dragging { opacity: 0.4; } .search-fb-grip { opacity: 0.35; font-size: 10px; line-height: 1; cursor: grab; } .search-fb-logo { width: 12px; height: 12px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; opacity: 0.85; } .search-fb-logo svg { width: 12px; height: 12px; } .search-fb-remove { background: none; border: none; color: var(--fg); opacity: 0.45; cursor: pointer; font-size: 14px; line-height: 1; padding: 0 2px; transition: opacity 0.15s, color 0.15s; } .search-fb-remove:hover { opacity: 1; color: var(--red); } .search-fb-add { background: var(--bg); color: var(--fg); border: 1px dashed var(--border); border-radius: 10px; padding: 2px 6px; font-family: inherit; font-size: 11px; outline: none; cursor: pointer; } .search-fb-add:focus, .search-fb-add:hover { border-color: var(--accent, var(--red)); border-style: solid; } .mcp-tools-search { width: 100%; box-sizing: border-box; margin-bottom: 6px; padding: 5px 8px; font-size: 11px; font-family: inherit; background: color-mix(in srgb, var(--fg) 4%, transparent); border: 1px solid var(--border); border-radius: 4px; color: var(--fg); outline: none; } .mcp-tools-search:focus { border-color: color-mix(in srgb, var(--accent) 60%, var(--border)); } .mcp-tools-count { font-size: 11px; font-weight: 600; opacity: 0.7; } /* Badges */ .admin-badge { font-size: 10px; padding: 2px 6px; border-radius: 4px; background: color-mix(in srgb, var(--red) 20%, transparent); color: var(--red); font-weight: 600; } .admin-badge-off { background: color-mix(in srgb, var(--color-error) 20%, transparent); color: var(--color-error); } /* Buttons */ .admin-btn-delete { background: none; border: 1px solid color-mix(in srgb, var(--color-error) 27%, transparent); color: var(--color-error); padding: 4px 10px; border-radius: 6px; cursor: pointer; font-size: 11px; font-family: inherit; transition: all 0.15s; } .admin-btn-delete:hover { background: var(--color-error); border-color: var(--color-error); color: #fff; } .admin-btn-add { padding: 4px 10px; border: 1px solid var(--accent, var(--red)); border-radius: 6px; background: var(--accent, var(--red)); color: var(--bg); cursor: pointer; font-weight: 600; font-size: 11px; font-family: inherit; box-sizing: border-box; transition: opacity 0.15s, background 0.15s, border-color 0.15s; } .admin-btn-add:hover { background: var(--accent, var(--red)); border-color: var(--accent, var(--red)); opacity: 0.9; } .admin-btn-add:disabled { opacity: 0.5; cursor: not-allowed; } .admin-btn-sm { padding: 3px 8px; border: 1px solid var(--border); border-radius: 6px; background: var(--panel); color: var(--fg); cursor: pointer; font-size: 11px; } .admin-btn-sm:hover { background: var(--border); border-color: var(--red); } .admin-spinner { display: inline-block; width: 12px; height: 12px; border: 2px solid var(--border); border-top-color: var(--red); border-radius: 50%; animation: admin-spin 0.6s linear infinite; vertical-align: -2px; margin-right: 2px; } /* Forms */ .admin-add-form { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; } .admin-add-form input { flex: 1; min-width: 120px; padding: 5px 8px; height: 32px; box-sizing: border-box; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; color: var(--fg); font-family: inherit; font-size: 12px; } .admin-add-form input:focus { outline: none; border-color: var(--red); } .admin-switch-inline { display: flex; align-items: center; gap: 6px; font-size: 11px; color: color-mix(in srgb, var(--fg) 60%, transparent); cursor: default; } .admin-model-form { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; } .admin-model-form input, .admin-model-form select { padding: 5px 8px; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; color: var(--fg); font-size: 12px; } .admin-model-form input:focus { outline: none; border-color: var(--red); } .admin-model-form-row { display: flex; gap: 6px; flex-wrap: wrap; /* let buttons drop to a new row on narrow widths instead of overflowing the modal */ align-items: center; } .admin-model-form-row input { flex: 1 1 180px; /* api-key input takes the long axis but allows dropping below the buttons at small widths */ min-width: 0; /* don't refuse to shrink past content width */ } .admin-model-form-row select { flex: 0 0 auto; } .admin-model-form-row button { flex: 0 0 auto; white-space: nowrap; } /* On narrow screens, give buttons their own row + push the Add button to the right so it remains the obvious primary action. */ @media (max-width: 540px) { .admin-model-form-row input { flex-basis: 100%; } .admin-model-form-row .admin-btn-add { margin-left: auto; } } .adm-ep-inline-msg { min-height: 16px; margin-top: 5px; font-size: 11px; } /* Endpoint items */ .admin-ep-item { display: flex; align-items: center; gap: 6px; padding: 6px 8px; background: var(--bg); border-radius: 6px; margin-bottom: 4px; font-size: 12px; } .admin-ep-info { flex: 1; overflow: hidden; } .admin-ep-name { color: var(--fg); font-weight: 500; } .admin-ep-detail { color: color-mix(in srgb, var(--fg) 40%, transparent); font-size: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: -4px; } /* Settings panel — tint each card's h2 title icon with the user's accent colour. Direct-child selector (`> h2 > svg`) so SVGs nested inside header buttons (Test, kebab, etc.) are untouched. Each title icon uses stroke="currentColor", so setting color propagates; existing inline opacity:0.6 stays so the tint reads soft. */ /* Selected integration card — class beats inline borderColor reset */ .intg-card.intg-card-active { border-color: var(--accent, var(--red)) !important; } /* Edge-dock resize handle: invisible at rest, accent stripe animates in on hover. Inline background:transparent + transition come from modalSnap.js; this rule paints the accent gradient on hover, beating the inline style with !important. */ .edge-dock-resize-handle-left:hover { background: linear-gradient(to right, transparent 0 3px, color-mix(in srgb, var(--accent, var(--red)) 35%, transparent) 3px 7px, transparent 7px 10px) !important; } .edge-dock-resize-handle-right:hover { background: linear-gradient(to left, transparent 0 3px, color-mix(in srgb, var(--accent, var(--red)) 35%, transparent) 3px 7px, transparent 7px 10px) !important; } [data-settings-panel] .admin-card > h2 > svg, #theme-popup .admin-card > h2 > svg, [data-settings-panel="added-models"] .adm-ep-section-head > svg { color: var(--accent, var(--red)); }