Files
odysseus/static/css/cookbook-research-memory-settings.css
T
Léo 3807cb22e7 refactor(css): move cookbook, research, memory and settings styles to their own file
Last step of splitting static/style.css by panel. This moves the cookbook,
deep research, memory and settings rules that can move into
static/css/cookbook-research-memory-settings.css.

After the three steps style.css still holds the shell and every rule whose
move would change the cascade, which on this branch is most of the file.
Eager ordered links, verbatim moves, no rendering change.
2026-09-23 16:12:53 +02:00

1424 lines
47 KiB
CSS

/* Cookbook (including What Fits?), deep research, memory, settings and admin.
*
* Split out of style.css for maintainability, not for performance: this file
* is loaded eagerly from index.html immediately after style.css, so the rules
* land in the cascade in exactly the order they had inside the single file.
* Nothing here is lazy-loaded.
*
* LOAD ORDER IS PART OF THE CONTRACT. The <link> tags in static/index.html and
* the PRECACHE list in static/sw.js must both list the stylesheets in this
* order:
* 1. static/style.css
* 2. static/css/documents-gallery-editor.css
* 3. static/css/email-calendar-notes-tasks.css
* 4. static/css/cookbook-research-memory-settings.css
*
* Rules were moved verbatim. A rule stays in style.css when its selector group
* covers more than one panel, when the class is shared design language used by
* modules outside this panel, or when moving it would change which of two
* equally specific rules wins.
*/
/* Cookbook already shows its own running/served-status dot
(#cookbook-notif-dot, toggled with .cookbook-notif-active on the
button). Don't stack the tabbed-down pulse on top of it — the two
dots overlap. Suppress the minimized dot while the status dot is up. */
.list-item.rail-minimized.cookbook-notif-active::after { display: none; }
@keyframes research-done-pulse {
0%, 100% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.5); opacity: 0.7; }
}
@keyframes research-pulse {
0%, 100% { background: color-mix(in srgb, var(--red) 12%, transparent); }
50% { background: color-mix(in srgb, var(--red) 22%, transparent); }
}
#cookbook-gguf-delete-overlay {
background:rgba(0,0,0,0.5);
backdrop-filter:blur(4px);
pointer-events:auto !important;
z-index:99999 !important;
position:fixed !important;
inset:0 !important;
}
.cookbook-gguf-delete-actions {
flex-wrap:wrap;
}
/* ── Processing pulse animation (reused by session-star) ── */
@keyframes research-pulse {
0%, 100% { opacity: 0.3; transform: scale(0.8); }
50% { opacity: 1; transform: scale(1.2); }
}
@keyframes memory-synapse-pulse {
0%, 100% { opacity: 0.35; transform: scale(1); }
50% { opacity: 0.65; transform: scale(1.02); }
}
.memory-add-input::placeholder {
color: color-mix(in srgb, var(--fg) 40%, transparent);
}
.memory-toolbar-toggle:has(input:not(:checked)) > span {
text-decoration: line-through;
text-decoration-color: color-mix(in srgb, var(--fg) 30%, transparent);
}
.memory-sort-label { white-space: nowrap; }
.memory-sort-btn[aria-expanded="true"] .memory-sort-caret { transform: rotate(180deg); }
@keyframes memory-synapse-sweep {
/* Sweep traverses left → right in the first ~12% of the cycle (≈0.7s of
a 6.2s loop), then waits offscreen. */
0% { --sweep: -20%; }
12% { --sweep: 120%; }
13%, 100% { --sweep: 120%; }
}
.memory-item-edit-input:focus {
outline: none;
}
.memory-edit-cat-select:focus {
outline: none;
}
.memory-add-row .memory-edit-cat-select:focus {
border-color: var(--red);
}
.memory-item-source::before,
.memory-item-time::before {
content: '\00b7 ';
}
.adm-check-dot::after {
content: '';
position: absolute;
left: 50%;
top: 45%;
width: 5px;
height: 2.5px;
border-left: 1.5px solid #fff;
border-bottom: 1.5px solid #fff;
transform: translate(-50%, -50%) rotate(-45deg) scale(0);
transform-origin: center;
transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.adm-model-row:active .adm-check-dot {
transform: scale(0.9);
}
.adm-cb-hidden:checked + .adm-check-dot::after {
transform: translate(-50%, -50%) rotate(-45deg) scale(1);
}
.adm-cb-hidden:checked + .adm-endpoint-select-dot::after {
display: none;
}
/* Most recently added endpoint — brief accent glow so the user can
spot the new row immediately after Adding / Find. Fades out cleanly. */
@keyframes adm-ep-just-added-glow {
0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent, var(--red)) 55%, transparent); background: color-mix(in srgb, var(--accent, var(--red)) 18%, transparent); }
60% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent, var(--red)) 0%, transparent); background: color-mix(in srgb, var(--accent, var(--red)) 8%, transparent); }
100% { box-shadow: 0 0 0 0 transparent; background: transparent; }
}
.adm-section-toggle:focus-visible { outline: 1px solid var(--red); outline-offset: 1px; }
/* Collapsed: hide the form body and point the caret right. */
.adm-add-section.collapsed .admin-model-form { display: none; }
.adm-add-section.collapsed .adm-section-caret { transform: rotate(-90deg); }
.adm-quickstart-section {
margin-top: 7px;
}
.adm-quickstart-section:not(.collapsed) .adm-quickstart-toggle {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.adm-quickstart-section.collapsed .adm-quickstart-body { display: none; }
.adm-quickstart-section.collapsed .adm-section-caret { transform: rotate(-90deg); }
.adm-provider-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@keyframes admin-spin {
to { transform: rotate(360deg); }
}
.admin-rag-item .admin-btn-delete { font-size: 10px; padding: 2px 6px; }
/* Cookbook's cached-model list: NO inner-scroll cap. Two nested scroll
surfaces (this + the outer .admin-card) trapped the wheel so an expanded
serve panel couldn't be reached on tall content. Let the outer
.admin-card (overflow-y:auto) be the single scroll surface. */
.hwfit-cached-list {
max-height: none !important;
overflow-y: visible !important;
}
/* The Servers list reuses .memory-toolbar for layout but must grow with every
added server — the 120px cap above was clipping manually-added servers. */
.memory-toolbar.cookbook-servers-toolbar {
max-height: none;
overflow: visible;
}
#hwfit-cached-list {
position: relative;
top: -6px;
}
#hwfit-server-select,
#hwfit-search {
position: relative;
top: -2px !important;
}
#hwfit-search {
height: 30px;
min-height: 30px;
font-family: inherit;
font-size: 11px;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23e06c75' stroke-opacity='0.85' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='8'/><line x1='21' y1='21' x2='16.65' y2='16.65'/></svg>");
background-repeat: no-repeat;
background-position: 9px center;
padding-left: 28px;
}
.cookbook-body::-webkit-scrollbar {
width: 4px;
}
.cookbook-body::-webkit-scrollbar-thumb {
background: color-mix(in srgb, var(--fg) 15%, transparent);
border-radius: 4px;
}
.cookbook-body::-webkit-scrollbar-track {
background: transparent;
padding: 4px 0;
}
#hwfit-dl-server.cookbook-server-select-colored,
#hwfit-server-select.cookbook-server-select-colored,
#hwfit-cache-server.cookbook-server-select-colored,
#hwfit-deps-server.cookbook-server-select-colored {
color: var(--cookbook-server-color, var(--fg));
border-color: color-mix(in srgb, var(--cookbook-server-color) 55%, var(--border));
background-color: color-mix(in srgb, var(--cookbook-server-color) 12%, var(--bg));
}
.cookbook-output-wrap:hover .cookbook-output-kill { opacity: 0.7; }
.cookbook-tab-error-dot { --notif-glow: var(--color-error, #f44); }
/* Brief highlight on the matched task card when jumping from the
running pill, so the user can spot it among a long list. */
.cookbook-task-flash {
animation: cookbook-task-flash-anim 1.6s ease-out;
}
@keyframes cookbook-task-flash-anim {
0% { box-shadow: 0 0 0 2px var(--accent, var(--red)); }
100% { box-shadow: 0 0 0 2px transparent; }
}
/* Cookbook header "downloading" status label sits 2px too far left
against the rest of the cookbook chrome — nudge it right. */
#cookbook-bg-status {
left: 2px;
}
/* Keep both GPU action labels on one line — they wrapped to two rows on
mobile, which looked broken. */
.cookbook-gpu-probe, .cookbook-gpu-clear { white-space: nowrap; }
#cookbook-hf-latest-list .cookbook-hf-link:hover {
opacity: 1;
}
#cookbook-hf-latest-list {
min-height: 0;
max-height: min(52vh, 480px);
overflow-y: auto;
overflow-x: hidden;
overscroll-behavior: contain;
scrollbar-width: thin;
}
.cookbook-section-header .cookbook-section-title {
flex: 1;
}
.cookbook-section-header:hover .cookbook-section-chevron { opacity: 1; }
.cookbook-slot-wrap:hover .cookbook-slot-del { opacity: 1; }
/* Keep dependency pills visually centered against the package description.
The row itself stays stable; only the controls move down slightly. */
.cookbook-dep-row > .cookbook-dep-tag {
transform: translateY(2px);
}
/* Conditional line under the Download h2: only when the section is folded
(collapsed). When expanded, the body content provides separation; the
underline reads as clutter. */
#cookbook-dl-tab-fold { border-bottom: none !important; padding-bottom: 0 !important; }
#cookbook-dl-tab-fold.is-folded {
border-bottom: 1px solid color-mix(in srgb, var(--border) 40%, transparent) !important;
padding-bottom: 6px !important;
}
/* Smooth open/close for the Direct Download body — replaces the
instant display:none toggle with a max-height + opacity slide so
auto-fold and auto-expand don't feel jarring. 1200px is a safe
upper bound for the body height; the slide only fires up to the
actual content height because content stops there. */
#cookbook-dl-tab-fold-body {
overflow: hidden;
max-height: 1200px;
opacity: 1;
transition: max-height 0.28s ease, opacity 0.18s ease, margin 0.28s ease;
}
#cookbook-dl-tab-fold-body.is-folded {
max-height: 0;
opacity: 0;
margin-top: 0;
margin-bottom: 0;
pointer-events: none;
}
.cookbook-dep-installed-btn .cookbook-dep-installed-label { padding: 0 8px; }
.cookbook-dep-installed-btn:hover { filter: brightness(1.15); }
.hwfit-serve-topline .hwfit-serve-runtime-note {
flex: 1 1 auto;
min-width: 0;
}
/* Expanded serve panel — make sure it can be scrolled past when it
grows taller than the visible viewport. Caps panel height to viewport
minus chrome and gives it its own internal scroll, so the surrounding
cached-list scroll isn't the only escape route. */
.hwfit-cached-item .hwfit-serve-panel {
max-height: calc(100vh - 180px);
overflow-y: auto;
overscroll-behavior: contain;
}
@media (max-width: 768px) {
.hwfit-cached-item .hwfit-serve-panel {
max-height: calc(100svh - 120px);
}
.hwfit-serve-preset-row {
justify-content: flex-end;
margin: -2px 0 0;
}
.hwfit-serve-topline {
flex-wrap: wrap;
}
.hwfit-serve-topline .hwfit-serve-runtime-note {
flex-basis: 100%;
}
.hwfit-serve-topline .hwfit-serve-runtime-text {
white-space: normal;
}
}
.hwfit-serve-row label select,
.hwfit-serve-row label input {
display: block;
margin-top: 2px;
}
.hwfit-extra-env-label {
grid-column: 1 / -1;
}
.hwfit-serve-panel[data-backend-active="vllm"] .hwfit-extra-env-label {
grid-column: 2 / -1;
}
.hwfit-sf.hwfit-sf-full { grid-column: 1 / -1; }
.hwfit-spec-tokens-bare::-webkit-outer-spin-button,
.hwfit-spec-tokens-bare::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
display: none;
}
.hwfit-numstep .hwfit-spec-tokens::-webkit-outer-spin-button,
.hwfit-numstep .hwfit-spec-tokens::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.hwfit-numstep-btn:focus { outline: none; }
.hwfit-spec-group:has(input[type="checkbox"]:not(:checked)) .hwfit-spec-method,
.hwfit-spec-group:has(input[type="checkbox"]:not(:checked)) .hwfit-spec-tokens,
.hwfit-spec-group:has(input[type="checkbox"]:not(:checked)) .hwfit-numstep {
opacity: 0.45;
pointer-events: none;
}
.hwfit-serve-extra {
margin-bottom: 6px;
}
.hwfit-serve-cmd-details {
margin: 4px 0 0;
}
.hwfit-serve-cmd-summary::-webkit-details-marker {
display: none;
}
.hwfit-serve-cmd-summary::after {
content: '';
margin-left: auto;
width: 0;
height: 0;
border-left: 4px solid currentColor;
border-top: 3px solid transparent;
border-bottom: 3px solid transparent;
opacity: 0.6;
transform: rotate(0deg);
transition: transform 0.18s ease;
}
.hwfit-serve-cmd-details[open] > .hwfit-serve-cmd-summary::after {
transform: rotate(90deg);
}
.hwfit-serve-cmd-details[open] > .hwfit-serve-cmd-summary {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
/* Same z-index treatment as .cookbook-task-dropdown — cookbook modal's
auto-stack climbs past low values; popups append to body and need to
sit above the modal regardless. */
:where(.hwfit-cached-dropdown,
.cookbook-gpu-split-menu,
.cookbook-launch-actions-menu,
.cookbook-saved-menu,
.cookbook-dep-menu) {
z-index: 10000;
}
.hwfit-serve-cmd-wrap .hwfit-serve-cmd {
/* Just enough breathing room so a cursor at line-end doesn't actually
touch the Copy icon — text otherwise uses the full width of the box. */
padding-right: 32px;
}
.hwfit-serve-cmd-details[open] .hwfit-serve-cmd {
border-color: color-mix(in srgb, var(--accent, var(--red)) 48%, var(--border));
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent, var(--red)) 16%, transparent),
0 0 12px color-mix(in srgb, var(--accent, var(--red)) 13%, transparent);
}
.cookbook-gpu-split .cookbook-gpu-split-main {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
}
.cookbook-gpu-split .cookbook-gpu-split-arrow {
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
border-left-width: 0 !important;
padding: 0 6px !important;
min-width: 24px;
}
.cookbook-task[data-type="download"][data-status="running"] .cookbook-task-type[data-type="download"] {
background: color-mix(in srgb, var(--color-accent, #00aaff) 18%, transparent);
color: var(--color-accent, #00aaff);
}
@keyframes cookbook-wave-pulse {
0%, 100% { opacity: 0.45; }
50% { opacity: 1; }
}
.cookbook-task[data-status="done"] .cookbook-task-check-ico { display: inline; }
.cookbook-task[data-status="done"] .cookbook-task-clear-ico { display: none; }
.cookbook-task-header {
cursor: pointer;
}
.cookbook-env-row > .cookbook-field-label {
flex: 1 1 140px;
min-width: 120px;
}
.cookbook-extra-label { grid-column: 1 / -1; }
.cookbook-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--fg);
border: 2px solid var(--panel);
box-shadow: 0 1px 4px rgba(0,0,0,0.3);
cursor: pointer;
transition: transform 0.1s, box-shadow 0.1s;
}
.cookbook-slider:hover::-webkit-slider-thumb {
transform: scale(1.15);
box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent, var(--red)) 20%, transparent);
}
.cookbook-slider:active::-webkit-slider-thumb {
transform: scale(1.25);
box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent, var(--red)) 25%, transparent);
}
.cookbook-slider::-moz-range-thumb {
width: 14px;
height: 14px;
border-radius: 50%;
background: var(--fg);
border: 2px solid var(--panel);
box-shadow: 0 1px 4px rgba(0,0,0,0.3);
cursor: pointer;
}
.cookbook-slider::-moz-range-progress {
background: var(--accent, var(--red));
height: 6px;
border-radius: 4px;
}
.cookbook-slider::-webkit-slider-runnable-track {
height: 6px;
border-radius: 4px;
}
.cookbook-slider::-moz-range-track {
height: 6px;
border-radius: 4px;
background: color-mix(in srgb, var(--fg) 12%, transparent);
}
.cookbook-checkbox:checked::after {
transform: translateX(14px);
}
/* Sliders span full row for alignment */
.cookbook-field-slider {
grid-column: 1 / -1;
}
.cookbook-diag-body {
margin-top: 7px;
}
/* Add Server collapsible */
.cookbook-server-details {
margin: 4px 0 6px;
}
.cookbook-server-toggle::-webkit-details-marker { display: none; }
.cookbook-srv-status:hover { transform: scale(1.3); }
@keyframes cookbook-srv-pulse {
0%, 100% { opacity: 0.45; }
50% { opacity: 1; }
}
.cookbook-server-entry::after {
content: '';
position: absolute;
inset: 0;
z-index: 2;
border-radius: inherit;
padding: 1px;
pointer-events: none;
background: linear-gradient(
to right,
transparent 0%,
transparent calc(var(--sweep, -20%) - 8%),
color-mix(in srgb, var(--cookbook-server-color, var(--red)) 85%, transparent) var(--sweep, -20%),
transparent calc(var(--sweep, -20%) + 8%),
transparent 100%
);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
animation: memory-synapse-sweep 6.2s linear infinite;
animation-delay: 0.4s;
}
#cookbook-servers-list .cookbook-server-entry:nth-child(2n)::after { animation-duration: 7.4s; animation-delay: 1.6s; }
#cookbook-servers-list .cookbook-server-entry:nth-child(3n)::after { animation-duration: 8.8s; animation-delay: 3.2s; }
#cookbook-servers-list .cookbook-server-entry:nth-child(5n)::after { animation-duration: 9.3s; animation-delay: 4.7s; }
#cookbook-servers-list .cookbook-server-entry:nth-child(7n)::after { animation-duration: 5.5s; animation-delay: 2.3s; }
.cookbook-server-entry:hover::after { animation: none; opacity: 0; }
@media (prefers-reduced-motion: reduce) {
.cookbook-server-entry::after { animation: none; opacity: 0; }
}
/* Keep the row inside the card on narrow screens — the fixed-width host/path
inputs would otherwise overflow the card's background to the right. */
@media (max-width: 768px) {
.cookbook-server-row .cookbook-srv-host,
.cookbook-server-row .cookbook-srv-path { flex: 1 1 100% !important; width: auto !important; min-width: 0 !important; }
}
.cookbook-server-row .cookbook-srv-name { width: 60px; flex-shrink: 0; flex-grow: 0; }
.cookbook-server-row select.cookbook-srv-color {
display: none !important;
}
.cookbook-server-row .cookbook-srv-color-btn:focus-visible {
outline: 2px solid color-mix(in srgb, var(--cookbook-server-color, var(--accent, var(--red))) 70%, transparent);
outline-offset: 2px;
}
.cookbook-server-row .cookbook-srv-host { flex: 1; min-width: 100px; }
.cookbook-server-row .cookbook-srv-host[readonly] { opacity: 0.4; cursor: default; }
.cookbook-server-row .cookbook-srv-port { width: 40px; flex-shrink: 0; flex-grow: 0; }
.cookbook-server-row .cookbook-srv-env { width: 65px; flex-shrink: 0; flex-grow: 0; }
.cookbook-server-row .cookbook-srv-path { flex: 1; min-width: 80px; }
.cookbook-server-row .cookbook-srv-status { width: 8px; height: 8px; align-self: center; }
/* Brief highlight on the serve command box when a saved config is loaded, so
the click clearly registers (loading is otherwise silent). */
.cookbook-cmd-flash {
animation: cookbookCmdFlash 0.6s ease;
}
.hwfit-toolbar:has(.hwfit-hw-manual-btn) {
gap: 8px;
}
.hwfit-toolbar .hwfit-server-select { min-width: 70px; flex-shrink: 0; }
.hwfit-toolbar .hwfit-usecase { min-width: 70px; flex-shrink: 0; }
.hwfit-toolbar .hwfit-engine { min-width: 0; width: 86px; flex-shrink: 0; font-size: 10px; }
.hwfit-toolbar .hwfit-search { flex: 1; min-width: 80px; }
.hwfit-advanced-panel .hwfit-engine-menu {
min-width: 132px;
}
/* Lower-opacity "Search models..." placeholder so it reads as a hint, not
a label — matches the muted form-field feel of the inline filters. */
.hwfit-search::placeholder { opacity: 0.5; }
.hwfit-search::-webkit-input-placeholder { opacity: 0.5; }
.hwfit-search::-moz-placeholder { opacity: 0.5; }
.hwfit-quant-wrap .hwfit-quant,
.hwfit-engine-wrap .hwfit-engine {
/* Make room for the ? on the right edge, in addition to the native chevron. */
padding-right: 32px;
}
.hwfit-toolbar .hwfit-host { width: 110px; flex-shrink: 0; }
.hwfit-env-row .hwfit-envtype { width: auto; min-width: 70px; flex-shrink: 0; }
.hwfit-env-row .hwfit-envpath { flex: 1; min-width: 100px; }
.hwfit-env-row .hwfit-gpus { width: 90px; flex-shrink: 0; }
.hwfit-hw-chip-dismiss { cursor: pointer; }
.hwfit-hw-chip-row[data-hw-chip="gpu"] .hwfit-hw-chip-x {
transform: translateY(-3px);
}
.hwfit-manual-panel .hwfit-hw-manual-save,
.hwfit-manual-panel .hwfit-hw-manual-clear {
/* -3 (was -2) — 1px more up to optically align with the labeled
inputs to their left. */
transform: translateY(-3px);
}
.cookbook-model-list-fade {
animation: cookbook-model-list-fade-in 180ms ease-out both;
}
@keyframes cookbook-model-list-fade-in {
from { opacity: 0; transform: translateY(3px); }
to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
.cookbook-model-list-fade,
.hwfit-list.cookbook-hwfit-models-just-loaded > .hwfit-row:not(.hwfit-header) { animation: none; }
}
.hwfit-row:has(.hwfit-dl-dot):hover { opacity: 0.9; }
.hwfit-row:has(.hwfit-dl-dot) .hwfit-dl-dot { opacity: 1; }
.hwfit-header .hwfit-name { font-size: 9px; }
.hwfit-sortable { cursor: pointer; user-select: none; }
.hwfit-c-params { width: 42px; }
.hwfit-c-quant { width: 52px; }
.hwfit-c-vram { width: 42px; }
.hwfit-c-ctx { width: 32px; }
.hwfit-c-speed { width: 44px; }
.hwfit-c-mode { width: 72px; }
@keyframes hwfit-panel-in {
from { opacity: 0; transform: translateY(-4px); }
to { opacity: 1; transform: translateY(0); }
}
.hwfit-cb { cursor: pointer; }
.settings-appearance-panel {
flex-direction: column;
}
@keyframes cookbook-modal-enter {
0% {
opacity: 0;
transform: translateY(12px) scale(0.94);
filter: saturate(0.85);
}
65% {
opacity: 1;
transform: translateY(-2px) scale(1.012);
filter: saturate(1.05);
}
100% {
opacity: 1;
transform: translateY(0) scale(1);
filter: none;
}
}
@keyframes cookbook-modal-enter-mobile {
0% { opacity: 0; transform: translateY(100%); }
100% { opacity: 1; transform: translateY(0); }
}
/* Cookbook Serve Advanced fold — wraps the rarely-touched tuning rows
(KV/Attention/Swap/Env for vLLM, llama.cpp batch/cache/split, VRAM
monitor, speculative, extra args). Matches the existing .hwfit-panel-
advanced look: muted-gray label, no caps, no letter-spacing, no
warning-y opacity. Content flows into the parent's existing scroll
surface (no inner max-height) and inner rows reset their margin so
stacking gaps don't double when the fold opens. */
/* Styled to match the Add Models page collapsible sections
(.adm-section-toggle) — same border/background/caret pattern, so the
two folds across the app read consistently. */
details.hwfit-serve-advanced {
margin-top: 8px;
overflow: visible;
}
details.hwfit-serve-advanced > summary.hwfit-serve-advanced-summary {
cursor: pointer;
user-select: none;
list-style: none;
display: flex;
align-items: center;
gap: 6px;
font-size: 11px;
color: var(--fg);
opacity: 0.8;
border: 1px solid var(--border);
border-radius: 6px;
padding: 6px 9px;
background: color-mix(in srgb, var(--fg) 4%, transparent);
transition: border-color 0.12s, background 0.12s, opacity 0.12s, border-radius 0s;
}
details.hwfit-serve-advanced > summary.hwfit-serve-advanced-summary::-webkit-details-marker {
display: none;
}
details.hwfit-serve-advanced > summary.hwfit-serve-advanced-summary:hover {
opacity: 1;
border-color: var(--red);
background: color-mix(in srgb, var(--red) 8%, transparent);
}
/* Caret on the right, rotates open/closed. SVG-style rectangles via
borders keep this glyph-free + crisp at small sizes. */
details.hwfit-serve-advanced > summary.hwfit-serve-advanced-summary::after {
content: '';
margin-left: auto;
width: 0;
height: 0;
border-left: 4px solid currentColor;
border-top: 3px solid transparent;
border-bottom: 3px solid transparent;
opacity: 0.6;
transform: rotate(90deg);
transition: transform 0.18s ease;
}
details.hwfit-serve-advanced:not([open]) > summary.hwfit-serve-advanced-summary::after {
transform: rotate(0deg);
}
/* Body rows below the header — tight rhythm so the fold doesn't
feel airy. The cookbook modal's existing .cookbook-body is the
scroll surface; nothing inside the fold should add its own scroll. */
details.hwfit-serve-advanced[open] > summary.hwfit-serve-advanced-summary {
margin-bottom: 6px;
}
details.hwfit-serve-advanced > .hwfit-serve-row.hwfit-vram-monitor .hwfit-vram-readout {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
}
details.hwfit-serve-advanced > .hwfit-serve-row label select,
details.hwfit-serve-advanced > .hwfit-serve-row label input {
margin-top: 1px;
}
details.hwfit-serve-advanced label:has(.hwfit-sf[data-field="vllm_attn_backend"]) {
position: relative;
left: -63px;
}
details.hwfit-serve-advanced label:has(.hwfit-sf[data-field="vllm_block_size"]) {
position: relative;
left: -75px;
}
details.hwfit-serve-advanced label:has(.hwfit-sf[data-field="swap"]) {
position: relative;
left: -73px;
}
details.hwfit-serve-advanced label:has(.hwfit-sf[data-field="vllm_kv_cache_dtype"]) {
position: relative;
left: 2px;
}
@media (max-width: 768px) {
details.hwfit-serve-advanced label:has(.hwfit-sf[data-field="vllm_block_size"]) {
left: 1px;
}
details.hwfit-serve-advanced label:has(.hwfit-sf[data-field="swap"]) {
left: -3px;
}
details.hwfit-serve-advanced > .hwfit-serve-checks .hwfit-sf-cb {
flex: 1 1 100%;
}
}
/* Hide the native number-input spinner arrows (e.g. SMTP/IMAP Port) — they
render unstyled and ugly. Field still accepts only numbers. */
.settings-input[type="number"]::-webkit-outer-spin-button,
.settings-input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.settings-input[type="number"] {
-moz-appearance: textfield;
appearance: textfield;
}
.cookbook-output-wrap:hover .cookbook-output-copy {
opacity: 0.5;
}
.cookbook-output-wrap .cookbook-output-copy:hover {
opacity: 1;
}
#cookbook-dl-btn-search {
position: relative;
top: -4px;
padding-top: 0;
padding-bottom: 0;
height: 28px;
}
#cookbook-dl-btn {
position: relative;
top: -4px;
}
.research-synapse-compact .rs-stage { height: 288px; }
@keyframes rs-live {
0%, 100% { opacity: 0.45; }
50% { opacity: 1; }
}
.research-synapse .rs-guide ellipse {
fill: none;
stroke: color-mix(in srgb, var(--fg) 7%, transparent);
stroke-width: 1;
stroke-dasharray: 2 7;
}
.research-synapse .rs-edge-tone-1 { stroke: color-mix(in srgb, var(--gold, #d4a72c) 45%, var(--border)); }
.research-synapse .rs-edge-tone-2 { stroke: color-mix(in srgb, #5aa7c7 42%, var(--border)); }
.research-synapse .rs-edge.rs-edge-firing {
stroke: var(--accent, var(--red));
stroke-width: 2;
opacity: 1;
filter: drop-shadow(0 0 4px var(--accent, var(--red)));
animation: rs-fire 1.1s ease-out;
}
@keyframes rs-fire {
0% { stroke-dasharray: 4 200; stroke-dashoffset: 200; opacity: 0; }
20% { opacity: 1; }
100% { stroke-dasharray: 200 4; stroke-dashoffset: -200; opacity: 0.55; }
}
.research-synapse .rs-node-root {
fill: var(--accent, var(--red));
stroke: var(--accent, var(--red));
filter: drop-shadow(0 0 5px color-mix(in srgb, var(--accent, var(--red)) 65%, transparent));
}
.research-synapse .rs-root-halo {
fill: none;
stroke: color-mix(in srgb, var(--accent, var(--red)) 28%, transparent);
stroke-width: 1;
}
/* Sub & leaf nodes stay inside the accent palette so the whole graph
reads as one organism. Leaves are softer/lower-contrast dots that
float around their sub — not green-on-stem (which read as palm fronds). */
.research-synapse .rs-node-sub {
fill: color-mix(in srgb, var(--accent, var(--red)) 10%, var(--bg));
stroke: color-mix(in srgb, var(--accent, var(--red)) 70%, var(--fg));
}
.research-synapse .rs-node-sub.rs-node-tone-1 {
fill: color-mix(in srgb, var(--gold, #d4a72c) 11%, var(--bg));
stroke: color-mix(in srgb, var(--gold, #d4a72c) 76%, var(--fg));
}
.research-synapse .rs-node-sub.rs-node-tone-2 {
fill: color-mix(in srgb, #5aa7c7 11%, var(--bg));
stroke: color-mix(in srgb, #5aa7c7 72%, var(--fg));
}
.research-synapse .rs-node-leaf {
stroke: color-mix(in srgb, var(--accent, var(--red)) 55%, transparent);
fill: color-mix(in srgb, var(--accent, var(--red)) 42%, var(--bg));
}
.research-synapse .rs-node-leaf.rs-node-tone-1 { fill: color-mix(in srgb, var(--gold, #d4a72c) 48%, var(--bg)); }
.research-synapse .rs-node-leaf.rs-node-tone-2 { fill: color-mix(in srgb, #5aa7c7 48%, var(--bg)); }
.research-synapse .rs-source-node { cursor: help; }
@keyframes rs-hub-expand {
0% { filter: drop-shadow(0 0 0 transparent); }
35% { filter: drop-shadow(0 0 7px var(--accent, var(--red))); }
100% { filter: drop-shadow(0 0 0 transparent); }
}
@keyframes rs-pop {
0% { transform: scale(0); opacity: 0; }
60% { transform: scale(1.25); opacity: 1; }
100% { opacity: 1; }
}
@keyframes rs-pulse {
0% { transform: scale(1); opacity: 0.65; }
100% { transform: scale(5); opacity: 0; }
}
.research-synapse .rs-meta .rs-sep { display: none; }
.research-synapse.rs-complete .rs-pulse { animation: none; opacity: 0; }
.research-synapse.rs-complete .rs-node-root {
fill: var(--color-success, #4caf50);
stroke: var(--color-success, #4caf50);
}
@media (max-width: 480px) {
.research-synapse .rs-meta { grid-template-columns: 1fr auto auto; row-gap: 6px; }
.research-synapse .rs-meta .rs-status { display: none; }
}
.hwfit-cached-menu-btn svg { fill: currentColor; }
.settings-email-preferences-card > h2 {
display: none;
}
[data-settings-panel="email"] > .settings-email-preferences-card {
padding-top: 0;
}
.cookbook-task-menu-btn {
top: 0 !important;
transform: translateY(2px) scale(1.15) !important;
}
/* Settings "+ Add server" matches the model-dir "+ Add" path button (22px). */
#cookbook-server-add.cal-add-btn-text {
height: 28px;
min-width: 62px;
border-radius: 14px;
padding: 0 12px 0 8px;
position: relative;
top: 1px;
font-size: 12px;
}
@keyframes research-pane-enter {
from { opacity: 0; }
to { opacity: 1; }
}
.research-pane-header:active { cursor:grabbing; }
.research-pane-header h4 {
margin: 0;
font-size: 1rem;
font-weight: 600;
color: var(--red);
display: inline-flex;
align-items: center;
gap: 6px;
}
.research-tab-panel.hidden,
.research-tab-panel[hidden] { display: none; }
.research-tab-heading h2 {
margin: 0;
font-size: 14px;
font-weight: 600;
line-height: 1;
}
.research-tab-panel:not([data-research-panel="research"]) .research-jobs-list {
flex: 1 1 auto;
min-height: 0;
overflow-y: auto;
}
/* Hide the in-body "Research" subtitle on mobile to save vertical space —
the toolbar/header carries enough context already. */
/* Match the .admin-card h2 styling used in Documents/Library so the
"Research" sub-title reads the same as those modals' titles. */
.research-new-job h2 {
font-size: 14px;
font-weight: 600;
letter-spacing: 0;
}
.research-new-job > .research-new-job-desc {
margin: 6px 0 0;
display: flex;
align-items: center;
gap: 6px;
flex-wrap: wrap;
}
@media (max-width: 600px) {
/* Keep the "Research" title visible on mobile (matches the Cookbook tab
titles, which show on mobile). It used to be hidden here. */
.research-new-job h2 {
font-size: 14px;
}
}
.research-setting:has(#research-model) .research-setting-label {
position: relative;
top: 1px;
}
.research-setting:has(#research-rounds) select,
.research-setting:has(#research-category) select {
position: relative;
top: -4px;
}
.research-setting:has(#research-rounds) .research-setting-label,
.research-setting:has(#research-category) .research-setting-label {
position: relative;
top: 4px;
}
.research-setting select {
font-size: 11px; padding: 4px 6px;
background: var(--bg);
color: var(--fg);
border: 1px solid var(--border); border-radius: 4px;
}
.research-picker-btn:focus-visible,
.research-picker-option:focus-visible {
outline: 2px solid color-mix(in srgb, var(--accent, var(--red)) 65%, transparent);
outline-offset: 1px;
}
.research-picker-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.research-picker.open .research-picker-btn > svg { transform: rotate(180deg); }
.research-picker-menu[hidden] { display: none; }
.research-picker-option > span:nth-child(2):not(.research-picker-check),
.research-picker-option > span:first-child:not(.research-picker-icon) {
overflow: hidden; text-overflow: ellipsis;
}
.research-picker-option.active .research-picker-check { opacity: 1; }
.research-run-mode-popover.rrm-up { transform-origin: bottom right; }
.research-run-mode-popover .research-run-mode-row:hover {
background: color-mix(in srgb, var(--accent-primary, var(--red)) 14%, transparent);
}
.research-job-card.done { cursor:pointer; }
/* Past (library) research used to be dimmed to 0.65 which read as "greyed out".
They now look the same as the rest — folding them under "Past research"
handles the de-clutter instead. */
.research-job-card.done.from-library { opacity:1; }
.research-job-thumb-frame[role="button"] { cursor: pointer; }
.research-job-thumb-frame[role="button"]:hover {
outline: 1px solid color-mix(in srgb, var(--accent, var(--red)) 65%, transparent);
outline-offset: 1px;
}
.research-job-report-body h1, .research-job-report-body h2, .research-job-report-body h3 {
color: var(--cat-color, var(--accent, var(--fg)));
}
.research-hero::after {
content: ''; position: absolute; right: -40px; top: -40px;
width: 160px; height: 160px; border-radius: 50%;
background: radial-gradient(circle, color-mix(in srgb, var(--cat-color, var(--accent)) 15%, transparent) 0%, transparent 60%);
pointer-events: none;
}
.research-hero-icon svg { width: 100%; height: 100%; }
/* Product: callout-style bullets */
.research-body-product ul { list-style: none; padding-left: 0; }
.research-body-product ul li {
padding: 6px 10px 6px 28px; margin: 4px 0;
border-left: 2px solid color-mix(in srgb, #5b8abf 40%, transparent);
background: color-mix(in srgb, #5b8abf 4%, transparent);
border-radius: 0 4px 4px 0; position: relative;
}
.research-body-product ul li::before {
content: '▸'; position: absolute; left: 10px;
color: #5b8abf; font-weight: bold;
}
/* Comparison: styled table */
.research-body-comparison table {
width: 100%; border-collapse: collapse; margin: 12px 0;
border: 1px solid color-mix(in srgb, #e5a33a 25%, transparent);
border-radius: 6px; overflow: hidden;
}
.research-body-comparison th {
background: color-mix(in srgb, #e5a33a 18%, transparent);
color: #e5a33a; font-weight: 700;
padding: 8px 12px; text-align: left;
border-bottom: 2px solid color-mix(in srgb, #e5a33a 40%, transparent);
}
.research-body-comparison td {
padding: 8px 12px;
border-bottom: 1px solid color-mix(in srgb, #e5a33a 12%, transparent);
}
.research-body-comparison tr:nth-child(even) td {
background: color-mix(in srgb, #e5a33a 3%, transparent);
}
/* How-to: big numbered steps */
.research-body-howto ol { counter-reset: howto-step; list-style: none; padding-left: 0; }
.research-body-howto ol > li {
counter-increment: howto-step; position: relative;
padding: 10px 12px 10px 52px; margin: 8px 0;
background: color-mix(in srgb, #82c882 5%, transparent);
border-radius: 8px; border-left: 2px solid #82c882;
}
.research-body-howto ol > li::before {
content: counter(howto-step);
position: absolute; left: 10px; top: 14px;
width: 30px; height: 30px; border-radius: 50%;
background: #82c882; color: white;
font-weight: 700; font-size: 13px;
display: flex; align-items: center; justify-content: center;
box-shadow: 0 2px 6px color-mix(in srgb, #82c882 40%, transparent);
}
/* Landscape: section banners */
.research-body-landscape h3 {
padding: 8px 14px;
background: linear-gradient(90deg, color-mix(in srgb, #a07ae0 15%, transparent), transparent);
border-left: 3px solid #a07ae0;
border-radius: 0 6px 6px 0;
margin: 14px 0 8px;
}
/* Fact-check: verdict emphasis */
.research-body-factcheck blockquote {
border-left: 3px solid var(--red);
background: color-mix(in srgb, var(--red) 6%, transparent);
padding: 10px 14px; margin: 10px 0;
border-radius: 0 6px 6px 0;
}
.research-body-factcheck strong {
color: var(--red);
padding: 1px 6px; border-radius: 4px;
background: color-mix(in srgb, var(--red) 12%, transparent);
}
.research-job-cancel:hover,
.research-job-remove:hover,
.research-job-report-link:hover { opacity:1; }
.research-synapse-toggle:hover,
.research-synapse-toggle.active { opacity:1; }
.research-job-synapse-host.synapse-collapsed { display:none; }
.research-job-summary .research-job-thumb-frame {
transform: translateY(-4px);
}
.research-job-summary .research-job-failnote {
margin: 2px 0 0;
}
.research-job-thumb-frame::after {
content: "";
position: absolute;
inset: 0;
pointer-events: none;
background: radial-gradient(ellipse at center,
transparent 42%,
color-mix(in srgb, var(--accent, var(--red)) 28%, transparent) 100%);
opacity: 0.75;
}
/* Push the first dim (dismiss/delete) button — and everything after it — to
the right edge of the actions row. `:first-of-type` would match the very
first <button> in the row regardless of class; this immediate-sibling
combinator targets only a dim button that follows a non-dim one. */
.research-job-actions .research-job-action:not(.research-job-action-dim)
+ .research-job-action-dim { margin-left: auto; }
/* Edge case: all buttons in the row are dim — push first dim right. */
.research-job-actions > .research-job-action-dim:first-child { margin-left: auto; }
.research-job-action-dim:hover { opacity: 1; }
.research-job-overflow.open .research-job-more {
color: var(--fg);
border-color: color-mix(in srgb, var(--cat-color) 45%, var(--border));
background: color-mix(in srgb, var(--cat-color) 8%, transparent);
}
.research-job-menu[hidden] { display: none; }
.research-section-divider::before,
.research-section-divider::after {
content:''; flex:1; height:1px;
background:var(--border);
}
.research-section.collapsed .research-section-body { display: none; }
.research-section:not(.collapsed) > .research-section-header { border-bottom: 1px solid var(--border); }
.research-section-header:has(.research-library-hint) { padding-bottom: 8px; }
.research-section.collapsed .research-section-chevron { transform: rotate(-90deg); }
/* Active section dot: pulsing accent glow (work in progress). */
.research-section-dot.pulsing { animation: research-dot-pulse 1.5s ease-in-out infinite; }
@keyframes research-dot-pulse {
0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent, var(--red)) 55%, transparent); }
70% { box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent, var(--red)) 0%, transparent); }
}
.research-source-link:hover { text-decoration:underline; }
.research-navigation-trace-live {
margin:7px 0 0;
max-height:92px;
overflow:hidden;
}
.research-nav-target {
overflow:hidden;
text-overflow:ellipsis;
white-space:nowrap;
}
.research-nav-status {
opacity:0.85;
}
.research-action-row .research-nav-target {
opacity:0.9;
}
.research-action-skipped {
opacity:0.62;
}
.research-nav-meta {
grid-column:2 / -1;
opacity:0.68;
}
.research-job-report-body h1,
.research-job-report-body h2,
.research-job-report-body h3 { font-size:13px; margin:12px 0 4px; }
.research-job-report-body p { margin:4px 0; }
.research-job-report-body pre { font-size:11px; }
.research-library-toggle:hover { opacity:1; }
.research-library-list {
max-height:300px; overflow-y:auto;
}
.research-lib-open:hover { opacity:1; }
@keyframes research-badge-breathe {
0%, 100% {
transform: scale(1);
opacity: 0.85;
box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-primary, var(--red)) 55%, transparent);
}
50% {
transform: scale(1.35);
opacity: 1;
box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent-primary, var(--red)) 0%, transparent);
}
}
@media (prefers-reduced-motion: reduce) {
.research-badge { animation: none; }
}
@media (prefers-reduced-motion: reduce) {
.research-sb-dot { animation: none; }
}
/* Nudge the X icon in the "Clear all" button down 2px. */
#research-clear-all svg { position: relative; top: 2px; }
@media (min-width: 769px) {
#research-pane.research-results-view {
height: 78vh;
}
}
.research-section-clear svg { width: 11px; height: 11px; }
.research-job-action.research-job-action-report:hover {
color: var(--cat-color, var(--accent, var(--red)));
border-color: var(--cat-color, var(--accent, var(--red)));
background: color-mix(in srgb, var(--cat-color, var(--accent, var(--red))) 10%, transparent);
}
.research-start-btn svg { color: inherit; }
.research-library-link:hover { opacity: 0.8; }
/* Nudge the Delete button 4px left. */
.research-job-action[data-action="delete"] { position: relative; right: 2px; }
.research-job-card.research-standard:hover {
background: color-mix(in srgb, var(--research-accent) 7%, var(--bg));
border-color: color-mix(in srgb, var(--research-accent) 42%, var(--border));
}
.research-job-card.research-standard .research-progress-fill {
background: var(--research-accent);
}
.research-job-card.research-standard-v0,
.research-hero.research-hero-v0 { --research-accent: #db8576; }
.research-job-card.research-standard-v1,
.research-hero.research-hero-v1 { --research-accent: #d2a45f; }
.research-job-card.research-standard-v2,
.research-hero.research-hero-v2 { --research-accent: #72ad8d; }
.research-job-card.research-standard-v3,
.research-hero.research-hero-v3 { --research-accent: #72a5cf; }
.research-job-card.research-standard-v4,
.research-hero.research-hero-v4 { --research-accent: #aa86c7; }
.adm-copilot-copy { margin-left: auto; }
.adm-chatgpt-usage-host {
margin: 4px 0 6px 0;
}
.hwfit-serve-launch-group .hwfit-serve-launch {
border-top-right-radius: 0 !important;
border-bottom-right-radius: 0 !important;
margin-right: 0 !important;
}
.hwfit-schedule-title-text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hwfit-schedule-field input[type="time"] {
font: inherit;
min-width: 90px;
}
/* Days field inline with From / Until — push it + the action buttons to
the right end of the row so the row reads: From | Until | …gap… | Days | Cancel | Save. */
.hwfit-schedule-days-field {
margin-left: auto;
}
.hwfit-schedule-mirror-label { white-space: nowrap; }
.hwfit-schedule-mirror-switch { transform: scale(0.85); transform-origin: left center; }
.hwfit-sched-err.is-visible { display: block; }
/* Real-time Diagnostics Log Terminal UI Styles */
.settings-system-logs-svg {
vertical-align: -2px;
margin-right: 5px;
opacity: 0.6;
}
.settings-system-logs-toggle-sub {
margin-bottom: 12px;
}
.settings-system-logs-tab:hover,
.settings-system-logs-tab.active {
opacity: 1;
}
.settings-system-logs-refresh-svg {
pointer-events: none;
}
/* ── Settings navigation / finder ────────────────────────────── */
.settings-sidebar-content {
display: flex;
min-width: 0;
flex: 1;
flex-direction: column;
gap: 2px;
overflow-y: auto;
overflow-x: hidden;
}
.settings-nav-search-wrap {
position: relative;
margin: 0 0 8px;
}
.settings-nav-search {
box-sizing: border-box;
width: 100%;
min-width: 0;
height: 32px;
padding: 5px 9px 5px 29px;
border: 1px solid var(--border);
border-radius: 6px;
outline: none;
background: var(--bg);
color: var(--fg);
font: inherit;
font-size: 11px;
}
.settings-nav-search:focus {
border-color: var(--accent, var(--red));
}
.settings-nav-search::placeholder {
color: var(--fg);
opacity: 0.45;
}
.settings-nav-search-icon {
position: absolute;
z-index: 2;
top: 9px;
left: 9px;
pointer-events: none;
opacity: 0.5;
}
.settings-nav-search-results {
position: absolute;
z-index: 30;
top: calc(100% + 4px);
left: 0;
right: 0;
min-width: 100%;
max-height: 300px;
overflow-y: auto;
overflow-x: hidden;
padding: 4px;
border: 1px solid var(--border);
border-radius: 7px;
background: var(--panel);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.28);
}
.settings-search-result {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
width: 100%;
align-items: center;
gap: 10px;
padding: 8px 9px;
border: 0;
border-radius: 5px;
background: transparent;
color: var(--fg);
font: inherit;
text-align: left;
cursor: pointer;
}
.settings-search-result:hover,
.settings-search-result.active {
background: color-mix(in srgb, var(--fg) 8%, transparent);
}
.settings-search-result-label {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 11px;
}
.settings-search-result-group {
flex: 0 0 auto;
max-width: 92px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 9px;
opacity: 0.5;
}
.settings-search-empty {
padding: 8px;
color: var(--fg);
font-size: 10px;
text-align: center;
opacity: 0.55;
}
.settings-sidebar-resize-handle {
position: absolute;
z-index: 20;
top: 0;
right: -3px;
width: 6px;
height: 100%;
cursor: col-resize;
background: transparent;
touch-action: none;
}
.settings-sidebar-resize-handle:hover,
.settings-sidebar-resizing .settings-sidebar-resize-handle {
background: var(--accent, var(--red));
opacity: 0.45;
}
.settings-sidebar-resizing {
transition: none;
user-select: none;
}
body.settings-sidebar-resize-active {
cursor: col-resize;
user-select: none;
}
.settings-sidebar-toggle {
position: absolute;
z-index: 25;
top: 9px;
right: -13px;
display: flex;
width: 24px;
height: 24px;
align-items: center;
justify-content: center;
padding: 0;
border: 1px solid var(--border);
border-radius: 50%;
background: var(--panel);
color: var(--fg);
cursor: pointer;
opacity: 0;
transition: opacity 0.12s ease, border-color 0.12s ease;
}
.settings-sidebar:hover .settings-sidebar-toggle,
.settings-sidebar-toggle:focus-visible,
.settings-sidebar.settings-sidebar-collapsed .settings-sidebar-toggle {
opacity: 1;
}
.settings-sidebar-toggle:hover,
.settings-sidebar-toggle:focus-visible {
border-color: var(--accent, var(--red));
color: var(--accent, var(--red));
}
.settings-sidebar-toggle-expand {
display: none;
}
.settings-sidebar.settings-sidebar-collapsed {
width: 34px;
flex-basis: 34px;
padding: 0;
}
.settings-sidebar.settings-sidebar-collapsed .settings-sidebar-content {
display: none;
}
.settings-sidebar.settings-sidebar-collapsed .settings-sidebar-resize-handle {
display: none;
}
.settings-sidebar.settings-sidebar-collapsed .settings-sidebar-toggle {
top: 10px;
right: 5px;
}
.settings-sidebar.settings-sidebar-collapsed .settings-sidebar-toggle-collapse {
display: none;
}
.settings-sidebar.settings-sidebar-collapsed .settings-sidebar-toggle-expand {
display: block;
}
/* The existing narrow/snapped layout is a horizontal tab rail. Sidebar
resizing/collapse applies only to the vertical desktop layout. */
@container settings-modal (max-width: 620px) {
.settings-sidebar {
width: auto;
flex: 0 0 auto;
transition: none;
}
.settings-sidebar-content {
flex-direction: row;
overflow-x: auto;
overflow-y: hidden;
}
.settings-nav-search-wrap,
.settings-sidebar-resize-handle,
.settings-sidebar-toggle {
display: none;
}
.settings-sidebar.settings-sidebar-collapsed {
width: auto;
flex-basis: auto;
padding: 6px;
}
.settings-sidebar.settings-sidebar-collapsed .settings-sidebar-content {
display: flex;
}
}
@media (max-width: 600px) {
.settings-sidebar {
width: auto;
flex: 0 0 auto;
}
.settings-sidebar-content {
flex-direction: row;
overflow-x: auto;
overflow-y: hidden;
}
.settings-nav-search-wrap,
.settings-sidebar-resize-handle,
.settings-sidebar-toggle {
display: none;
}
}
.cookbook-chat-target {
animation: cookbook-chat-target-pulse 1.8s ease-out;
}
@keyframes cookbook-chat-target-pulse {
0%, 35% { outline: 2px solid var(--accent, #d46a6a); outline-offset: 2px; }
100% { outline: 2px solid transparent; outline-offset: 5px; }
}
#research-pane .research-history-clear-btn {
margin-left: auto;
height: 22px;
padding-top: 0;
padding-bottom: 0;
}
#research-pane .research-history-desc {
flex: 0 0 auto;
position: relative;
top: -8px;
margin: 6px 0 0;
font-size: 11px;
}
#research-pane .research-history-search-wrap {
position: relative;
top: 2px;
display: flex;
align-items: center;
width: 100%;
min-width: 0;
margin-top: 0;
}