mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 15:02:20 +02:00
static/style.css was 47,530 lines. It is now nine files under static/css/: tokens.css holds the :root custom properties, light theme and density classes, and style-part-01..08 carry the rest in their original order. Nothing was rewritten; every line moved verbatim and the <link> order in index.html reproduces the original file byte for byte. Cut points are brace-depth zero and outside block comments, so no rule or comment is split. All 47,531 source lines are accounted for across the fragments. The computed-style baseline recorded before the split is reproduced exactly, which is the evidence that the cascade is unchanged rather than an argument that it should be. Three things the split broke and this fixes: - The harness self-test swapped two conflicting .attach-strip blocks inside style.css to prove the digest is order-sensitive. It rewrote one hardcoded URL, so with the file gone it silently measured an unmodified page. It now searches every stylesheet, rewrites whichever holds the pair, and fails loudly if none does. - Four tests asserted the cache-bust token by matching /static/style.css?v=. They check the real invariant now, that every app stylesheet shares one token with app.js, through stylesheet_cache_version(). - The three panel stylesheets carried their own tokens, so a browser could hold half an old cascade and half a new one. All app stylesheets now bust together.
6012 lines
183 KiB
CSS
6012 lines
183 KiB
CSS
/* Fragment 3/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 <link> 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.
|
||
*/
|
||
.loading-dot:nth-child(1) {
|
||
animation: loading-bounce 1.4s infinite ease-in-out both;
|
||
}
|
||
.loading-dot:nth-child(2) {
|
||
animation: loading-bounce 1.4s infinite ease-in-out both;
|
||
animation-delay: -0.32s;
|
||
}
|
||
.loading-dot:nth-child(3) {
|
||
animation: loading-bounce 1.4s infinite ease-in-out both;
|
||
animation-delay: -0.64s;
|
||
}
|
||
.session-loading-state {
|
||
min-height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: flex-start;
|
||
gap: 12px;
|
||
color: var(--fg);
|
||
font-size: 12px;
|
||
pointer-events: none;
|
||
position: relative;
|
||
padding: 16px 14px 24px;
|
||
box-sizing: border-box;
|
||
overflow: hidden;
|
||
}
|
||
.session-loading-state::before { content: none; }
|
||
.session-skeleton-bubble {
|
||
width: min(78%, 680px);
|
||
border: 1px solid color-mix(in srgb, var(--border) 74%, transparent);
|
||
border-radius: 10px;
|
||
background: color-mix(in srgb, var(--panel, var(--bg)) 72%, transparent);
|
||
padding: 10px 12px 12px;
|
||
box-shadow: 0 8px 22px rgba(0, 0, 0, 0.14);
|
||
}
|
||
.session-skeleton-bubble.is-user {
|
||
align-self: flex-end;
|
||
width: min(64%, 520px);
|
||
}
|
||
.session-skeleton-bubble.is-ai {
|
||
align-self: flex-start;
|
||
}
|
||
.session-skeleton-line {
|
||
position: relative;
|
||
overflow: hidden;
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent);
|
||
border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
|
||
border-radius: 999px;
|
||
}
|
||
.session-skeleton-line {
|
||
height: 10px;
|
||
margin-top: 8px;
|
||
opacity: 0.62;
|
||
}
|
||
.session-skeleton-line::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: -1px;
|
||
transform: translateX(-120%);
|
||
background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--fg) 14%, transparent), transparent);
|
||
animation: session-skeleton-shimmer 1.25s ease-in-out infinite;
|
||
}
|
||
.session-skeleton-bubble:nth-child(2) .session-skeleton-line::after { animation-delay: 0.12s; }
|
||
.session-skeleton-bubble:nth-child(3) .session-skeleton-line::after { animation-delay: 0.24s; }
|
||
.session-skeleton-bubble:nth-child(4) .session-skeleton-line::after { animation-delay: 0.36s; }
|
||
@keyframes session-skeleton-shimmer {
|
||
100% { transform: translateX(120%); }
|
||
}
|
||
@media (max-width: 768px) {
|
||
.session-loading-state { padding: 12px 10px 18px; gap: 10px; }
|
||
.session-skeleton-bubble { width: 86%; padding: 9px 10px 11px; border-radius: 9px; }
|
||
.session-skeleton-bubble.is-user { width: 72%; }
|
||
.session-skeleton-line { height: 9px; margin-top: 7px; }
|
||
}
|
||
@keyframes loading-bounce {
|
||
0%, 80%, 100% {
|
||
transform: scale(0);
|
||
}
|
||
40% {
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
/* Modal styling */
|
||
.modal {
|
||
position:fixed;
|
||
top:0; left:0; width:100%; height:100%;
|
||
background:none;
|
||
display:flex; align-items:center; justify-content:center;
|
||
z-index:250;
|
||
backdrop-filter:none;
|
||
pointer-events:none;
|
||
}
|
||
/* Cookbook always sits above Gallery so the "Serve a model in
|
||
Cookbook…" flow (and any other "open Cookbook from inside another
|
||
modal") is visible no matter which modal was opened first. */
|
||
#cookbook-modal { z-index: 260; }
|
||
.modal.hidden { display:none; }
|
||
|
||
/* Tool windows open centered in the CHAT AREA (the space right of the
|
||
sidebar + icon rail), rather than the full viewport.
|
||
We narrow the overlay to the chat area so its flex-centering lands the
|
||
window there; fullscreen / docked states use position:fixed so they
|
||
escape this narrowed overlay and still fill the screen. The
|
||
--sidebar-w / --icon-rail-w vars track collapse state live, so when a
|
||
window (e.g. Cookbook) hides the sidebar this naturally re-centers.
|
||
Desktop only — on mobile these are full-screen sheets. */
|
||
@media (min-width: 769px) {
|
||
#calendar-modal,
|
||
#gallery-modal,
|
||
#tasks-modal,
|
||
#memory-modal,
|
||
#doclib-modal,
|
||
#compare-model-overlay,
|
||
#research-overlay,
|
||
#theme-modal,
|
||
#settings-modal,
|
||
#email-lib-modal {
|
||
left: calc(var(--icon-rail-w, 48px) + var(--sidebar-w, 0px));
|
||
width: calc(100% - (var(--icon-rail-w, 48px) + var(--sidebar-w, 0px)));
|
||
box-sizing: border-box;
|
||
/* Slide in sync with the sidebar's 0.25s collapse/expand so the
|
||
centered window glides instead of jumping when the nav toggles. */
|
||
transition: left 0.25s ease, width 0.25s ease;
|
||
}
|
||
}
|
||
.modal-content {
|
||
background:var(--panel);
|
||
border:1px solid var(--border);
|
||
width:min(520px, 92vw); max-height:85vh; padding:10px;
|
||
box-sizing:border-box; font-size:14px;
|
||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
letter-spacing: -0.015em;
|
||
display:flex; flex-direction:column;
|
||
position:relative;
|
||
overflow-y:auto;
|
||
border-radius:10px;
|
||
box-shadow:0 8px 32px rgba(0,0,0,0.45);
|
||
pointer-events:auto;
|
||
animation: modal-enter 0.25s ease-out both;
|
||
}
|
||
.memory-modal-content,
|
||
.tasks-modal-content,
|
||
.preset-modal-content,
|
||
#cookbook-modal .modal-content,
|
||
#theme-popup,
|
||
.doclib-modal-content,
|
||
.gallery-modal-content {
|
||
container-type: inline-size;
|
||
}
|
||
.modal-header {
|
||
display:flex; justify-content:space-between; align-items:center; margin-bottom:6px;
|
||
cursor:grab; user-select:none;
|
||
/* Pin the header (with its close button) to the top of the
|
||
scrollable modal-content so users can always dismiss the modal
|
||
even after scrolling far down — especially important on mobile
|
||
where the modal can be taller than the viewport. */
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 5;
|
||
/* Inherit the modal-content's background so the header matches the
|
||
panel body. Many tool modals set their content to var(--bg) inline
|
||
while this header was hard-coded to var(--panel) — making the title
|
||
strip a different shade in every theme. `inherit` tracks whatever
|
||
the content uses (var(--bg) or the default var(--panel)) and stays
|
||
opaque, so the sticky header still masks scrolled content. */
|
||
background-color: inherit;
|
||
}
|
||
.modal-header:active { cursor:grabbing; }
|
||
/* Edge/corner window resize (windowResize.js). While a resize is in
|
||
progress, suppress text selection and force the active resize cursor
|
||
across the whole document so it does not flicker as the pointer passes
|
||
over child elements mid-drag. */
|
||
body.window-resizing-active { user-select:none !important; }
|
||
body.window-resizing-active * { cursor:inherit !important; }
|
||
/* Suppress only TRANSITIONS while resizing so the edge tracks the cursor
|
||
crisply. We deliberately do NOT toggle `animation` here: toggling
|
||
animation off→on re-triggers the modal open-animation (a scale-in) on
|
||
mouseup, which both mis-measures the final size and visibly "pops" the
|
||
window. windowResize.js instead kills the one-shot open animation inline
|
||
once, in begin(). */
|
||
.window-resizing {
|
||
transition:none !important;
|
||
}
|
||
/* Cookbook opts out of the sticky header on mobile; the title bar scrolls
|
||
away with the content instead of following. Background is inherited from
|
||
the shared .modal-header rule so frosted/glass themes stay consistent. */
|
||
#cookbook-modal .modal-header {
|
||
position: static;
|
||
top: auto;
|
||
}
|
||
.modal-header h4 {
|
||
margin:0;
|
||
/* Push every header control (opacity slider, minimize, close) into one
|
||
group on the right — works whether or not optional controls like the
|
||
opacity slider are present, so the minimize button never floats to
|
||
the centre when a sibling is hidden. */
|
||
margin-right:auto;
|
||
font-size:1rem;
|
||
font-weight:600;
|
||
letter-spacing:-0.03em;
|
||
color:var(--red);
|
||
}
|
||
/* Headers with an optional Peek control already have the title's
|
||
auto-margin grouping all right-side controls. A second auto-margin on
|
||
the injected minimize button splits the group and makes it look
|
||
different from the other modal headers. */
|
||
.modal-header .theme-opacity-wrap + .modal-minimize-btn {
|
||
margin-left: 0 !important;
|
||
}
|
||
.close-btn,
|
||
.modal-close {
|
||
background:transparent;
|
||
color:color-mix(in srgb, var(--fg) 58%, transparent);
|
||
border:1px solid transparent;
|
||
font-size:0;
|
||
width:24px;
|
||
height:24px;
|
||
padding:0;
|
||
display:inline-flex;
|
||
align-items:center;
|
||
justify-content:center;
|
||
line-height:1;
|
||
text-indent:0;
|
||
cursor:pointer;
|
||
border-radius:999px;
|
||
line-height:1;
|
||
flex-shrink:0;
|
||
position:relative;
|
||
}
|
||
.close-btn > svg,
|
||
.modal-close > svg {
|
||
display:none;
|
||
}
|
||
.close-btn::before,
|
||
.modal-close::before {
|
||
content:"";
|
||
width:10px;
|
||
height:10px;
|
||
display:block;
|
||
background:currentColor;
|
||
-webkit-mask:
|
||
url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2 2L8 8M8 2L2 8' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E")
|
||
center / contain no-repeat;
|
||
mask:
|
||
url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2 2L8 8M8 2L2 8' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E")
|
||
center / contain no-repeat;
|
||
}
|
||
.close-btn:hover,
|
||
.modal-close:hover {
|
||
background:color-mix(in srgb, var(--fg) 10%, transparent);
|
||
border-color:color-mix(in srgb, var(--fg) 12%, transparent);
|
||
color:var(--fg);
|
||
}
|
||
/* Minimize button — sits beside the close button on every modal */
|
||
.minimize-btn {
|
||
background:transparent;
|
||
color:color-mix(in srgb, var(--fg) 58%, transparent);
|
||
border:1px solid transparent;
|
||
font-size:0;
|
||
font-weight:700;
|
||
width:24px;
|
||
height:24px;
|
||
padding:0;
|
||
display:inline-flex;
|
||
align-items:center;
|
||
justify-content:center;
|
||
line-height:1;
|
||
cursor:pointer;
|
||
border-radius:999px;
|
||
flex-shrink:0;
|
||
margin-left:auto; /* push to the right so it docks next to .close-btn */
|
||
margin-right:4px;
|
||
}
|
||
.minimize-btn::before {
|
||
content:"";
|
||
width:9px;
|
||
height:2px;
|
||
border-radius:999px;
|
||
background:currentColor;
|
||
display:block;
|
||
transform:translateY(2px);
|
||
}
|
||
.modal-minimize-btn.minimize-btn::before {
|
||
content:none;
|
||
display:none;
|
||
}
|
||
.minimize-btn:hover {
|
||
background:color-mix(in srgb, var(--fg) 10%, transparent);
|
||
border-color:color-mix(in srgb, var(--fg) 12%, transparent);
|
||
color:var(--fg);
|
||
}
|
||
@media (max-width: 768px) {
|
||
.minimize-btn { display: none !important; }
|
||
#modal-dock { display: none !important; }
|
||
}
|
||
/* Minimized modals are hidden but stay in the DOM with their state intact */
|
||
.modal.minimized { display:none !important; }
|
||
/* Bottom dock for minimized modals */
|
||
#modal-dock {
|
||
position:fixed;
|
||
bottom:var(--composer-clearance, 0px);
|
||
left:0;
|
||
right:0;
|
||
display:flex;
|
||
flex-wrap:wrap;
|
||
gap:4px;
|
||
padding:4px 8px;
|
||
z-index:240;
|
||
pointer-events:none;
|
||
justify-content:flex-start;
|
||
}
|
||
#modal-dock:empty { display:none; }
|
||
.modal-dock-item {
|
||
background:var(--panel);
|
||
border:1px solid var(--border);
|
||
border-bottom:none;
|
||
border-radius:6px 6px 0 0;
|
||
padding:4px 4px 4px 10px;
|
||
display:inline-flex;
|
||
align-items:center;
|
||
gap:6px;
|
||
cursor:pointer;
|
||
pointer-events:auto;
|
||
font-size:12px;
|
||
color:var(--fg);
|
||
max-width:220px;
|
||
box-shadow:0 -2px 8px rgba(0,0,0,0.25);
|
||
transition:background 0.15s;
|
||
}
|
||
.modal-dock-item:hover { background:var(--bg); }
|
||
.modal-dock-label {
|
||
white-space:nowrap;
|
||
overflow:hidden;
|
||
text-overflow:ellipsis;
|
||
max-width:180px;
|
||
}
|
||
.modal-dock-close {
|
||
background:transparent;
|
||
border:none;
|
||
color:var(--fg);
|
||
cursor:pointer;
|
||
font-size:14px;
|
||
padding:0 4px;
|
||
line-height:1;
|
||
opacity:0.6;
|
||
}
|
||
.modal-dock-close:hover { color:var(--red); opacity:1; }
|
||
.modal-body { flex:1; overflow-y:auto; }
|
||
.modal-body button { margin-top:6px; }
|
||
/* Styled confirm dialog — keeps backdrop */
|
||
#styled-confirm-overlay {
|
||
background:rgba(0,0,0,0.5);
|
||
backdrop-filter:blur(4px);
|
||
pointer-events:auto !important;
|
||
z-index: 99999 !important;
|
||
position: fixed !important;
|
||
top: 0 !important;
|
||
left: 0 !important;
|
||
width: 100% !important;
|
||
height: 100% !important;
|
||
top: 0; left: 0; width: 100%; height: 100%;
|
||
}
|
||
#styled-confirm-overlay .modal-content {
|
||
position: relative;
|
||
z-index: 10001;
|
||
}
|
||
.email-attachment-warning-modal {
|
||
z-index: 99999 !important;
|
||
}
|
||
.email-attachment-warning-modal .modal-content {
|
||
position: relative;
|
||
z-index: 100001;
|
||
}
|
||
.styled-confirm-box {
|
||
width:360px; max-width:90vw;
|
||
max-height:none; /* override modal-content's 85vh */
|
||
padding:14px 18px;
|
||
}
|
||
.styled-confirm-box .modal-header { margin-bottom:4px; }
|
||
.styled-confirm-box .modal-body p {
|
||
margin:8px 0 12px; color:var(--fg); font-size:0.92rem; line-height:1.45;
|
||
white-space:pre-line;
|
||
}
|
||
.styled-confirm-box .modal-footer {
|
||
display:flex; justify-content:flex-end; gap:8px; padding-top:6px;
|
||
border-top:1px solid var(--border); margin-top:4px;
|
||
}
|
||
@media (max-width:768px) {
|
||
.styled-confirm-box {
|
||
width: 85vw;
|
||
padding: 12px 16px;
|
||
font-size: 0.88rem;
|
||
border-radius: 12px;
|
||
}
|
||
.styled-confirm-box .modal-header h4 { font-size: 0.9rem; }
|
||
.styled-confirm-box .modal-body p { font-size: 0.85rem; margin: 6px 0 10px; }
|
||
.styled-confirm-box .modal-footer { gap: 10px; }
|
||
.styled-confirm-box .confirm-btn {
|
||
flex: 1;
|
||
/* More bottom than top padding nudges the label up ~2px so it isn't
|
||
sitting low in the taller mobile buttons. */
|
||
padding: 8px 12px 12px;
|
||
font-size: 0.85rem;
|
||
border-radius: 8px;
|
||
text-align: center;
|
||
}
|
||
}
|
||
.confirm-btn {
|
||
/* Asymmetric padding nudges the label UP ~2px from where it was (more
|
||
bottom than top padding), so the confirm-dialog text isn't sitting low. */
|
||
padding:3px 16px 5px; border-radius:4px; font-size:0.85rem;
|
||
cursor:pointer; border:1px solid var(--border);
|
||
font-family:inherit;
|
||
}
|
||
@media (max-width: 820px) {
|
||
/* Mobile: flip the asymmetry to shift the text 1 px UP from
|
||
centre instead (the bigger touch targets on mobile read better
|
||
with the label sitting slightly high). */
|
||
.confirm-btn { padding:2px 16px 4px; }
|
||
}
|
||
.confirm-btn-secondary { background:var(--bg); color:var(--fg); }
|
||
.confirm-btn-secondary:hover { background:var(--border); }
|
||
#styled-confirm-cancel .styled-confirm-cancel-label {
|
||
position:relative;
|
||
top:2px;
|
||
}
|
||
.confirm-btn-primary { background:var(--accent-primary, var(--red, #4a9eff)); color:#fff; border-color:transparent; }
|
||
.confirm-btn-primary:hover { filter:brightness(1.15); }
|
||
.confirm-btn-danger { background:var(--color-danger); color:#fff; border-color:transparent; }
|
||
.confirm-btn-danger:hover { background:var(--color-error); }
|
||
.cookbook-gguf-delete-box {
|
||
width:560px;
|
||
max-width:92vw;
|
||
}
|
||
.cookbook-gguf-delete-list {
|
||
display:flex;
|
||
flex-direction:column;
|
||
gap:6px;
|
||
max-height:42vh;
|
||
overflow:auto;
|
||
padding:2px 2px 4px;
|
||
}
|
||
.cookbook-gguf-delete-row {
|
||
display:grid;
|
||
grid-template-columns:18px minmax(0,1fr);
|
||
gap:7px 8px;
|
||
align-items:start;
|
||
padding:7px 8px;
|
||
border:1px solid var(--border);
|
||
border-radius:7px;
|
||
background:color-mix(in srgb, var(--panel, var(--bg)) 92%, var(--fg) 8%);
|
||
cursor:pointer;
|
||
}
|
||
.cookbook-gguf-delete-row:hover {
|
||
border-color:color-mix(in srgb, var(--accent-primary, var(--fg)) 45%, var(--border));
|
||
}
|
||
.cookbook-gguf-delete-cb {
|
||
-webkit-appearance:none;
|
||
appearance:none;
|
||
width:8px !important;
|
||
height:8px !important;
|
||
min-width:8px;
|
||
min-height:8px;
|
||
padding:0;
|
||
margin:4px 0 0;
|
||
border:1px solid var(--border);
|
||
border-radius:50%;
|
||
background:transparent;
|
||
box-sizing:content-box;
|
||
cursor:pointer;
|
||
transition:background 0.15s, border-color 0.15s, transform 0.12s;
|
||
}
|
||
.cookbook-gguf-delete-cb:hover {
|
||
border-color:var(--accent, var(--red));
|
||
transform:scale(1.12);
|
||
}
|
||
.cookbook-gguf-delete-cb:checked {
|
||
background:var(--accent, var(--red));
|
||
border-color:var(--accent, var(--red));
|
||
}
|
||
.cookbook-gguf-delete-main,
|
||
.cookbook-gguf-delete-path {
|
||
min-width:0;
|
||
overflow:hidden;
|
||
text-overflow:ellipsis;
|
||
white-space:nowrap;
|
||
}
|
||
.cookbook-gguf-delete-main {
|
||
font-size:0.86rem;
|
||
color:var(--fg);
|
||
}
|
||
.cookbook-gguf-delete-path {
|
||
grid-column:2;
|
||
margin-top:-2px;
|
||
font-size:0.74rem;
|
||
opacity:0.58;
|
||
}
|
||
/* Styled prompt — text-input dialog (used in place of window.prompt) */
|
||
#styled-prompt-overlay {
|
||
background:rgba(0,0,0,0.5);
|
||
backdrop-filter:blur(4px);
|
||
pointer-events:auto !important;
|
||
z-index: 99999 !important;
|
||
position: fixed !important;
|
||
top: 0 !important;
|
||
left: 0 !important;
|
||
width: 100% !important;
|
||
height: 100% !important;
|
||
}
|
||
#styled-prompt-overlay .modal-content {
|
||
position: relative;
|
||
z-index: 10001;
|
||
}
|
||
.styled-prompt-box { width: min(400px, 92vw); max-width: 100%; box-sizing: border-box; }
|
||
.styled-prompt-box .modal-body { padding-top: 4px; }
|
||
.styled-prompt-input {
|
||
width:100%;
|
||
box-sizing:border-box;
|
||
margin-top:8px;
|
||
padding:9px 12px;
|
||
border:1px solid var(--border);
|
||
border-radius:6px;
|
||
background:var(--bg);
|
||
color:var(--fg);
|
||
font:inherit;
|
||
font-size:0.95rem;
|
||
outline:none;
|
||
transition: border-color 0.15s, box-shadow 0.15s;
|
||
}
|
||
.styled-prompt-input:focus {
|
||
border-color: var(--accent-primary, var(--red, #4a9eff));
|
||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-primary, var(--red, #4a9eff)) 25%, transparent);
|
||
}
|
||
@media (max-width:768px) {
|
||
.styled-prompt-box { width: 85vw; }
|
||
.styled-prompt-input { font-size: 0.9rem; padding: 10px 12px; }
|
||
}
|
||
/* Scroll navigation buttons */
|
||
.scroll-nav-btn {
|
||
position:fixed;
|
||
background:var(--panel);
|
||
color: var(--accent);
|
||
border:none;
|
||
border-radius:10px;
|
||
width:38px; height:38px;
|
||
padding:0;
|
||
display:flex; align-items:center; justify-content:center;
|
||
font-size:14px;
|
||
line-height:1;
|
||
font-family:inherit;
|
||
cursor:pointer;
|
||
opacity:0;
|
||
pointer-events:none;
|
||
transition: opacity .2s, transform .3s cubic-bezier(0.25, 1, 0.5, 1), background .15s;
|
||
z-index:100;
|
||
transform: translateY(0);
|
||
}
|
||
.scroll-nav-btn::before {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
border-radius: 10px;
|
||
padding: 1px;
|
||
background: linear-gradient(to bottom, var(--border), color-mix(in srgb, var(--border) 30%, transparent));
|
||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||
-webkit-mask-composite: xor;
|
||
mask-composite: exclude;
|
||
pointer-events: none;
|
||
}
|
||
.scroll-nav-btn.agent-working::after,
|
||
body.chat-agent-working #scroll-bottom-btn.show::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 0;
|
||
border-radius: 10px;
|
||
padding: 1px;
|
||
background: conic-gradient(
|
||
from 0deg,
|
||
transparent 0deg,
|
||
transparent 245deg,
|
||
color-mix(in srgb, var(--accent, var(--red)) 78%, transparent) 315deg,
|
||
transparent 360deg
|
||
);
|
||
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
|
||
-webkit-mask-composite: xor;
|
||
mask-composite: exclude;
|
||
opacity: 0.65;
|
||
pointer-events: none;
|
||
animation: scrollAgentWorkingRing 1.05s linear infinite;
|
||
}
|
||
@keyframes scrollAgentWorkingRing {
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
#scroll-bottom-btn.show { opacity:1; pointer-events:auto; }
|
||
.scroll-nav-caret {
|
||
display: inline-block;
|
||
font-family: Arial, Helvetica, sans-serif;
|
||
font-size: 16px;
|
||
line-height: 1;
|
||
transform: translateY(-1px);
|
||
pointer-events: none;
|
||
}
|
||
@media (hover: hover) and (pointer: fine) {
|
||
#scroll-bottom-btn.show:hover {
|
||
border-color: color-mix(in srgb, var(--fg) 25%, transparent);
|
||
}
|
||
}
|
||
#scroll-bottom-btn.slide-out {
|
||
transform: translateY(20px);
|
||
opacity: 0 !important;
|
||
pointer-events: none;
|
||
}
|
||
/* Focus outline for accessibility */
|
||
:focus-visible {
|
||
outline: 2px solid var(--red);
|
||
outline-offset: 2px;
|
||
}
|
||
/* Hamburger menu button */
|
||
.hamburger {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 32px;
|
||
height: 32px;
|
||
background: none;
|
||
border: 1px solid transparent;
|
||
border-radius: 6px;
|
||
padding: 0;
|
||
cursor: pointer;
|
||
transition: background 0.15s, border-color 0.15s;
|
||
}
|
||
.hamburger:hover {
|
||
background: color-mix(in srgb, var(--fg) 7%, transparent);
|
||
border-color: var(--border);
|
||
}
|
||
.hamburger span {
|
||
display: block;
|
||
width: 16px;
|
||
height: 2px;
|
||
background: var(--fg);
|
||
border-radius: 1px;
|
||
transition: transform 0.2s, opacity 0.2s;
|
||
}
|
||
.hamburger span + span { margin-top: 3px; }
|
||
/* Agent indicator */
|
||
#agent-indicator {
|
||
position: fixed;
|
||
top: 20px;
|
||
right: 20px;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
border: 1px solid var(--border);
|
||
padding: 6px 12px;
|
||
border-radius: 6px;
|
||
font-size: 12px;
|
||
display: none;
|
||
z-index: 100;
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
}
|
||
#agent-indicator.active {
|
||
display: block;
|
||
border-color: var(--color-agent-active);
|
||
box-shadow: 0 0 10px rgba(0, 255, 0, 0.3);
|
||
}
|
||
#agent-indicator:hover {
|
||
border-color: var(--color-agent-active);
|
||
background: var(--panel);
|
||
}
|
||
#research-toggle-btn:disabled {
|
||
opacity: 0.6;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
/* ── Drag & Drop ── */
|
||
|
||
/* ---------- Color palette (dark / light) ---------- */
|
||
|
||
/* Drag and drop styling */
|
||
.section[dnd-active="true"] {
|
||
background: color-mix(in srgb, var(--red) 10%, transparent) !important;
|
||
border-color: var(--red) !important;
|
||
}
|
||
|
||
.section[dnd-over="true"] {
|
||
background: color-mix(in srgb, var(--red) 20%, transparent) !important;
|
||
border-color: var(--red) !important;
|
||
transform: scale(1.02);
|
||
}
|
||
|
||
.drag-handle {
|
||
cursor: grab;
|
||
opacity: 0.5;
|
||
padding: 0 6px;
|
||
user-select: none;
|
||
}
|
||
|
||
.drag-handle:hover {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.drag-handle:active {
|
||
cursor: grabbing;
|
||
}
|
||
|
||
/* ── UI Controls (Radio, Presets, Toolbar, Settings) ── */
|
||
|
||
|
||
/* Custom radio button styling */
|
||
.radio-option {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 8px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.radio-option:hover {
|
||
background: color-mix(in srgb, var(--fg) 9%, transparent);
|
||
border-color: var(--fg);
|
||
}
|
||
|
||
.radio-option input[type="radio"] {
|
||
appearance: none;
|
||
-webkit-appearance: none;
|
||
width: 18px;
|
||
height: 18px;
|
||
border: 2px solid var(--border);
|
||
border-radius: 50%;
|
||
outline: none;
|
||
margin: 0;
|
||
background: var(--bg);
|
||
transition: all 0.2s ease;
|
||
position: relative;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.radio-option input[type="radio"]:checked {
|
||
border-color: var(--red);
|
||
background: var(--red);
|
||
}
|
||
|
||
.radio-option input[type="radio"]:focus {
|
||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--red) 30%, transparent);
|
||
}
|
||
|
||
.radio-label {
|
||
color: var(--fg);
|
||
font-size: 14px;
|
||
user-select: none;
|
||
}
|
||
|
||
/* Preset buttons */
|
||
.preset-btn {
|
||
height: 27.2px; /* 15% smaller than 32px */
|
||
padding: 0 8.5px; /* 15% smaller than 10px */
|
||
margin-left: 4px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 4px;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
font-family: 'Fira Code', monospace;
|
||
font-size: 10.2px; /* 15% smaller than 12px */
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.preset-btn:hover {
|
||
background: var(--panel);
|
||
border-color: var(--fg);
|
||
}
|
||
|
||
.preset-btn.active {
|
||
background: var(--panel);
|
||
border-color: var(--fg);
|
||
box-shadow: 0 0 0 1px var(--fg), 0 0 8px color-mix(in srgb, var(--fg) 16%, transparent);
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* All preset buttons use the same blue color */
|
||
.preset-btn {
|
||
border-color: var(--red); /* Blue color */
|
||
}
|
||
|
||
.preset-btn.active {
|
||
border-color: var(--red); /* Blue color when active */
|
||
box-shadow: 0 0 0 1px var(--red), 0 0 8px color-mix(in srgb, var(--red) 30%, transparent);
|
||
}
|
||
|
||
/* Custom preset modal: the base .preset-modal-content sets overflow:hidden
|
||
(for desktop rounded-corner clipping), which on the mobile sheet clipped
|
||
the footer (Start/Cancel) off the bottom with no way to reach it. Let the
|
||
whole sheet scroll — same as every other mobile modal (.modal-content is
|
||
overflow-y:auto on mobile) — so the footer is always reachable. No flex
|
||
changes, so the body can't collapse. */
|
||
#custom-preset-modal .preset-modal-content {
|
||
overflow-y: auto !important;
|
||
}
|
||
#custom-preset-modal .modal-body label {
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
color: var(--fg);
|
||
margin-top: 8px;
|
||
margin-bottom: 4px;
|
||
display: block;
|
||
}
|
||
|
||
#custom-preset-modal .modal-body input,
|
||
#custom-preset-modal .modal-body textarea {
|
||
width: 100%;
|
||
margin-bottom: 8px;
|
||
box-sizing: border-box;
|
||
}
|
||
#custom-preset-modal .modal-body textarea,
|
||
#custom-preset-modal .modal-body input[type="text"] {
|
||
background: var(--panel);
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
color: var(--fg);
|
||
padding: 8px 10px;
|
||
font-size: 13px;
|
||
font-family: inherit;
|
||
transition: border-color 0.15s;
|
||
}
|
||
#custom-preset-modal .modal-body textarea {
|
||
resize: vertical;
|
||
}
|
||
#custom-preset-modal .modal-body textarea:focus,
|
||
#custom-preset-modal .modal-body input[type="text"]:focus {
|
||
outline: none;
|
||
border-color: var(--red);
|
||
}
|
||
|
||
#custom-preset-modal .modal-footer {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
gap: 8px;
|
||
margin-top: 12px;
|
||
padding-top: 10px;
|
||
border-top: 1px solid var(--border);
|
||
}
|
||
|
||
#custom-preset-modal .modal-footer button {
|
||
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;
|
||
}
|
||
#custom-preset-modal .modal-footer button:hover {
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
}
|
||
|
||
#custom-preset-modal .modal-footer button#save-custom-preset {
|
||
/* The theme's accent is stored in --red (theme.js sets --red = accentHex)
|
||
and --accent is undefined, so the canonical accent expression is
|
||
var(--accent, var(--red)). The old bare var(--accent) resolved to nothing
|
||
which, with color:var(--bg), made the button invisible. */
|
||
background: var(--accent, var(--red));
|
||
color: var(--bg);
|
||
border-color: var(--accent, var(--red));
|
||
}
|
||
#custom-preset-modal .modal-footer button#save-custom-preset:hover {
|
||
opacity: 0.85;
|
||
}
|
||
/* Toolbar visibility tab */
|
||
.toolbar-hint {
|
||
font-size: 12px;
|
||
color: color-mix(in srgb, var(--fg) 55%, transparent);
|
||
margin-bottom: 12px;
|
||
}
|
||
/* ── Appearance visibility toggles ── */
|
||
.vis-toggles {
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.vis-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
cursor: pointer;
|
||
padding: 5px 6px;
|
||
border-radius: 4px;
|
||
transition: background 0.12s;
|
||
}
|
||
.vis-row:hover {
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
}
|
||
.vis-row input[type="checkbox"] {
|
||
display: none;
|
||
}
|
||
.vis-icon {
|
||
width: 20px;
|
||
height: 20px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
color: color-mix(in srgb, var(--fg) 40%, transparent);
|
||
}
|
||
.vis-icon-text {
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
font-family: inherit;
|
||
letter-spacing: -0.5px;
|
||
}
|
||
.vis-label {
|
||
flex: 1;
|
||
font-size: 12px;
|
||
color: var(--fg);
|
||
user-select: none;
|
||
}
|
||
.vis-switch {
|
||
position: relative;
|
||
width: 30px;
|
||
height: 16px;
|
||
background: color-mix(in srgb, var(--fg) 15%, transparent);
|
||
border-radius: 8px;
|
||
transition: background 0.2s;
|
||
flex-shrink: 0;
|
||
}
|
||
.vis-switch::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 2px;
|
||
left: 2px;
|
||
width: 12px;
|
||
height: 12px;
|
||
background: var(--panel);
|
||
border-radius: 50%;
|
||
transition: transform 0.2s;
|
||
box-shadow: 0 1px 2px rgba(0,0,0,0.25);
|
||
}
|
||
.vis-row input:checked + .vis-switch {
|
||
background: var(--red);
|
||
}
|
||
.vis-row input:checked + .vis-switch::after {
|
||
transform: translateX(14px);
|
||
}
|
||
.vis-row input:checked ~ .vis-icon,
|
||
.vis-row:has(input:checked) .vis-icon {
|
||
color: var(--fg);
|
||
}
|
||
.persona-display-name-row .vis-label {
|
||
position: relative;
|
||
top: -4px;
|
||
}
|
||
.persona-display-name-row .vis-switch {
|
||
position: relative;
|
||
left: 4px;
|
||
}
|
||
.md-attach-paperclip-icon {
|
||
position: relative;
|
||
top: 1px;
|
||
}
|
||
/* Compare model selector — match the calendar modal's clean header
|
||
(no border underline). */
|
||
#compare-model-overlay .modal-header h4 {
|
||
pointer-events: none;
|
||
}
|
||
/* Compare model selector: keep manually-resized/tiny windows contained.
|
||
Picker dropdowns are appended to document.body, so the card itself can
|
||
clip and scroll without cropping the dropdown list. */
|
||
#compare-model-overlay .modal-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
max-height: min(720px, calc(100dvh - 48px));
|
||
overflow: hidden;
|
||
min-height: 180px;
|
||
}
|
||
#compare-model-overlay .modal-body {
|
||
overflow: auto;
|
||
flex: 1 1 auto;
|
||
min-height: 0;
|
||
}
|
||
.vis-hint {
|
||
font-size: 10px;
|
||
color: color-mix(in srgb, var(--fg) 30%, transparent);
|
||
font-weight: 400;
|
||
margin-left: 2px;
|
||
}
|
||
/* Settings toggle — admin-only lock indicator */
|
||
.ui-vis-lock {
|
||
display: none;
|
||
}
|
||
/* (legacy toolbar-toggle styles removed — now using .vis-* classes) */
|
||
|
||
/* Demo highlight pulse */
|
||
.odysseus-highlight {
|
||
outline: 2px solid var(--accent, var(--red)) !important;
|
||
outline-offset: 1px;
|
||
box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent, var(--red)) 18%, transparent);
|
||
animation: ody-pulse 1.5s ease-in-out infinite;
|
||
z-index: 100;
|
||
position: relative;
|
||
}
|
||
@keyframes ody-pulse {
|
||
0%, 100% { outline-color: var(--accent, var(--red)); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent, var(--red)) 18%, transparent); }
|
||
50% { outline-color: color-mix(in srgb, var(--accent, var(--red)) 40%, transparent); box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent, var(--red)) 8%, transparent); }
|
||
}
|
||
/* Floating breathing halo. Rendered as a body-level div positioned over
|
||
the target, so we don't fight the target's own outline / box-shadow /
|
||
overflow chain. JS keeps it in sync with the target's bounding rect. */
|
||
.tour-halo {
|
||
position: fixed;
|
||
pointer-events: none;
|
||
border: 3px solid var(--accent, var(--red));
|
||
border-radius: 10px;
|
||
z-index: 10000;
|
||
animation: ody-breathe 1.4s ease-in-out infinite;
|
||
opacity: 0;
|
||
transform: scale(0.94);
|
||
transition: opacity 0.35s ease-out, transform 0.35s ease-out;
|
||
}
|
||
.tour-halo.tour-fade-in {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
@keyframes ody-breathe {
|
||
0%, 100% {
|
||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, var(--red)) 55%, transparent),
|
||
0 0 22px 4px color-mix(in srgb, var(--accent, var(--red)) 40%, transparent);
|
||
border-color: var(--accent, var(--red));
|
||
}
|
||
50% {
|
||
box-shadow: 0 0 0 6px color-mix(in srgb, var(--accent, var(--red)) 30%, transparent),
|
||
0 0 40px 14px color-mix(in srgb, var(--accent, var(--red)) 70%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 80%, transparent);
|
||
}
|
||
}
|
||
/* While the tour is active, lift overflow:hidden on common clipping
|
||
ancestors so the halo around a highlighted child isn't cropped. */
|
||
body.tour-active .sidebar,
|
||
body.tour-active .sidebar-inner,
|
||
body.tour-active .chat-input-bar,
|
||
body.tour-active .chat-input-top,
|
||
body.tour-active .chat-input-wrap,
|
||
body.tour-active .chat-input-right,
|
||
body.tour-active .mode-toggle,
|
||
body.tour-active .model-picker-wrap {
|
||
overflow: visible !important;
|
||
}
|
||
|
||
/* ── Secret tour hint (drag-to-snap on first modal open) ── */
|
||
.tour-hint {
|
||
position: fixed;
|
||
z-index: 10002;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
padding: 12px 14px 10px;
|
||
width: 240px;
|
||
font-size: 0.78rem;
|
||
line-height: 1.5;
|
||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.32);
|
||
opacity: 0;
|
||
transform: translateY(-4px);
|
||
transition: opacity 0.28s ease-out, transform 0.28s ease-out;
|
||
pointer-events: auto;
|
||
}
|
||
.tour-hint.tour-hint-in { opacity: 1; transform: translateY(0); }
|
||
.tour-hint.tour-hint-out { opacity: 0; transform: translateY(-4px); }
|
||
.tour-hint-visual {
|
||
display: flex;
|
||
justify-content: center;
|
||
margin-bottom: 8px;
|
||
color: var(--accent, var(--red));
|
||
}
|
||
.tour-hint-visual svg { display: block; }
|
||
.tour-hint-text { margin-bottom: 10px; opacity: 0.92; }
|
||
.tour-hint-text b { color: var(--accent, var(--red)); font-weight: 600; }
|
||
.tour-hint-dismiss {
|
||
display: block;
|
||
margin: 0 0 0 auto;
|
||
background: none;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
border-radius: 6px;
|
||
padding: 3px 12px;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
font-size: 0.72rem;
|
||
opacity: 0.85;
|
||
transition: opacity 0.15s, background 0.15s;
|
||
}
|
||
.tour-hint-dismiss:hover { opacity: 1; background: color-mix(in srgb, var(--fg) 8%, transparent); }
|
||
|
||
/* SVG dance: cursor approaches title bar, drags right, modal snaps to a
|
||
right-half zone, holds, returns. 3.2s loop. */
|
||
.th-cursor { animation: th-cursor 3.2s ease-in-out infinite; transform-origin: 0 0; }
|
||
.th-modal-group { animation: th-modal-slide 3.2s ease-in-out infinite; transform-origin: 39px 31px; }
|
||
.th-zone { animation: th-zone-flash 3.2s ease-in-out infinite; }
|
||
@keyframes th-cursor {
|
||
0%, 5% { transform: translate(35px, 32px); }
|
||
18% { transform: translate(35px, 22px); }
|
||
48% { transform: translate(80px, 22px); }
|
||
72% { transform: translate(80px, 22px); }
|
||
90%, 100% { transform: translate(35px, 32px); }
|
||
}
|
||
@keyframes th-modal-slide {
|
||
0%, 18% { transform: translate(0, 0) scale(1, 1); }
|
||
48% { transform: translate(45px, 0) scale(1, 1); }
|
||
58% { transform: translate(30px, -19px) scale(1.4, 2.4); }
|
||
72% { transform: translate(30px, -19px) scale(1.4, 2.4); }
|
||
90%, 100% { transform: translate(0, 0) scale(1, 1); }
|
||
}
|
||
@keyframes th-zone-flash {
|
||
0%, 38% { opacity: 0; }
|
||
48% { opacity: 0.22; }
|
||
58%, 72% { opacity: 0; }
|
||
100% { opacity: 0; }
|
||
}
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.th-cursor, .th-modal-group, .th-zone { animation: none !important; }
|
||
}
|
||
.odysseus-hl-label {
|
||
position: absolute;
|
||
top: -22px;
|
||
left: 8px;
|
||
background: var(--red);
|
||
color: var(--bg);
|
||
font-size: 0.7rem;
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
white-space: nowrap;
|
||
z-index: 101;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* Generated images inside chat bubbles */
|
||
.msg.generated-image-wrap .body { text-align: center; }
|
||
.generated-image {
|
||
max-width: 100%;
|
||
max-height: 512px;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
transition: transform 0.2s;
|
||
display: inline-block;
|
||
margin: 0 auto;
|
||
}
|
||
.generated-image:hover { transform: scale(1.02); }
|
||
.generated-image-caption {
|
||
font-size: 0.8rem;
|
||
opacity: 0.5;
|
||
margin-top: 6px;
|
||
font-style: italic;
|
||
text-align: center;
|
||
}
|
||
|
||
/* Setup wizard */
|
||
.setup-wizard { padding: 16px; max-width: 500px; }
|
||
.setup-wizard .setup-title { font-size: 1.1rem; font-weight: 600; margin-bottom: 12px; color: var(--fg); }
|
||
.setup-wizard .setup-label { font-size: 0.85rem; color: var(--fg); opacity: 0.7; margin-bottom: 8px; }
|
||
.setup-wizard .setup-presets { display: flex; flex-wrap: wrap; gap: 8px; }
|
||
.setup-wizard .setup-preset-btn {
|
||
padding: 8px 14px; border: 1px solid var(--border); border-radius: 6px;
|
||
background: var(--panel); color: var(--fg); cursor: pointer;
|
||
font-size: 0.85rem; transition: all 0.2s;
|
||
}
|
||
.setup-wizard .setup-preset-btn:hover { border-color: var(--red); background: color-mix(in srgb, var(--red) 11%, transparent); }
|
||
.setup-wizard .setup-input {
|
||
display: block; width: 100%; padding: 8px 12px; margin-bottom: 8px;
|
||
background: var(--panel); border: 1px solid var(--border);
|
||
border-radius: 6px; color: var(--fg); font-size: 0.85rem; box-sizing: border-box;
|
||
}
|
||
.setup-wizard .setup-input:focus { border-color: var(--red); outline: none; }
|
||
.setup-wizard .setup-connect-btn {
|
||
padding: 8px 20px; background: var(--red); color: var(--bg);
|
||
border: none; border-radius: 6px; cursor: pointer; font-weight: 600; margin-top: 4px;
|
||
}
|
||
.setup-wizard .setup-connect-btn:hover { opacity: 0.9; }
|
||
.setup-wizard .setup-status { font-size: 0.8rem; margin-top: 8px; color: var(--fg); opacity: 0.7; }
|
||
.setup-wizard .setup-model-list { display: flex; flex-wrap: wrap; gap: 8px; }
|
||
.setup-wizard .setup-model-btn {
|
||
padding: 8px 14px; border: 1px solid var(--border); border-radius: 6px;
|
||
background: var(--panel); color: var(--fg); cursor: pointer;
|
||
font-size: 0.85rem; transition: all 0.2s;
|
||
}
|
||
.setup-wizard .setup-model-btn:hover { border-color: var(--red); background: color-mix(in srgb, var(--red) 11%, transparent); }
|
||
.setup-wizard .setup-step.hidden { display: none; }
|
||
|
||
/* Dropdown menu styles */
|
||
.dropdown {
|
||
position: absolute;
|
||
top: calc(100% + 6px);
|
||
right: 0;
|
||
background: var(--panel);
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3), 0 0 0 1px color-mix(in srgb, var(--fg) 5%, transparent);
|
||
z-index: 1000;
|
||
display: none;
|
||
min-width: 220px;
|
||
padding: 6px;
|
||
backdrop-filter: blur(12px);
|
||
}
|
||
|
||
.dropdown.show {
|
||
display: block;
|
||
animation: dropdown-in 0.15s ease-out;
|
||
}
|
||
@keyframes dropdown-in {
|
||
from { opacity:0; transform:translateY(-6px) scale(0.97); }
|
||
to { opacity:1; transform:translateY(0) scale(1); }
|
||
}
|
||
|
||
.dropdown-item {
|
||
padding: 8px 10px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
transition: background 0.12s ease;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
border-bottom: 1px solid color-mix(in srgb, var(--border) 40%, transparent);
|
||
}
|
||
|
||
.dropdown-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.dropdown-item .menu-icon {
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: 6px;
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 14px;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.dropdown-item .menu-text h4 {
|
||
margin: 0;
|
||
font-size: 12.5px;
|
||
font-weight: 500;
|
||
color: var(--fg);
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.dropdown-item .menu-text p {
|
||
margin: 0;
|
||
font-size: 10.5px;
|
||
color: var(--color-subheader);
|
||
line-height: 1.3;
|
||
}
|
||
|
||
.dropdown-item:hover {
|
||
background: color-mix(in srgb, var(--red) 10%, transparent);
|
||
}
|
||
.dropdown-item:hover .menu-icon {
|
||
background: color-mix(in srgb, var(--red) 15%, transparent);
|
||
}
|
||
|
||
/* Compact dropdown items (session/model context menus) */
|
||
.dropdown-item-compact {
|
||
cursor: pointer;
|
||
padding: 6px 8px;
|
||
font-size: 11px;
|
||
border-radius: 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
color: var(--fg);
|
||
transition: background 0.1s;
|
||
}
|
||
.dropdown-item-compact:hover {
|
||
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
||
}
|
||
.dropdown-item-compact .dropdown-icon {
|
||
width: 14px;
|
||
height: 14px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
opacity: 0.5;
|
||
}
|
||
.dropdown-item-compact .dropdown-icon svg {
|
||
width: 14px;
|
||
height: 14px;
|
||
}
|
||
.dropdown-item-compact .dropdown-shortcut {
|
||
margin-left: auto;
|
||
font-size: 9.5px;
|
||
opacity: 0.35;
|
||
font-weight: 400;
|
||
}
|
||
/* Keyboard shortcut hints (⌘+Alt+D etc.) are meaningless on touch —
|
||
hide them in the per-chat actions menu on mobile. */
|
||
@media (max-width: 768px) {
|
||
.session-dropdown .dropdown-shortcut { display: none; }
|
||
}
|
||
.dropdown-item-danger {
|
||
color: var(--red) !important;
|
||
}
|
||
.dropdown-item-danger .dropdown-icon {
|
||
opacity: 0.7;
|
||
}
|
||
|
||
/* Inline rename input for sessions */
|
||
.session-rename-input {
|
||
width: 100%;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
border: 1px solid var(--accent, var(--accent-primary));
|
||
border-radius: 4px;
|
||
padding: 2px 6px;
|
||
font-family: inherit;
|
||
font-size: 12px;
|
||
line-height: 1.3;
|
||
outline: none;
|
||
}
|
||
|
||
/* Session dropdown container */
|
||
.session-dropdown-menu {
|
||
position: fixed;
|
||
z-index: 1000;
|
||
display: none;
|
||
min-width: auto;
|
||
width: max-content;
|
||
padding: 4px;
|
||
animation: dropdown-in 0.15s ease-out;
|
||
}
|
||
|
||
/* Folder move submenu */
|
||
.session-folder-submenu {
|
||
position: fixed;
|
||
z-index: 1001;
|
||
display: none;
|
||
min-width: auto;
|
||
width: max-content;
|
||
padding: 4px;
|
||
}
|
||
|
||
.dropdown-divider {
|
||
height: 1px;
|
||
background: var(--border);
|
||
margin: 4px 8px;
|
||
}
|
||
|
||
/* Search toggle styles */
|
||
.search-toggle {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 6px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.search-provider-label {
|
||
font-size: 14px;
|
||
color: var(--fg);
|
||
}
|
||
|
||
/* ── Voice, Search, Themes, Comparison, Censor, Print ── */
|
||
|
||
/* Voice recording styles */
|
||
#mic-btn {
|
||
color: var(--fg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 4px;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
#mic-btn:hover {
|
||
background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
border-color: var(--fg);
|
||
}
|
||
|
||
#mic-btn.recording {
|
||
background: var(--color-recording);
|
||
border-color: var(--color-recording);
|
||
animation: pulse 1.5s infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0% { opacity: 1; }
|
||
50% { opacity: 0.7; }
|
||
100% { opacity: 1; }
|
||
}
|
||
|
||
#recording-indicator {
|
||
position: fixed;
|
||
top: 10px;
|
||
left: 0;
|
||
right: 0;
|
||
background: rgba(0, 0, 0, 0.8);
|
||
backdrop-filter: blur(10px);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 12px;
|
||
margin: 10px;
|
||
z-index: 1000;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
#recording-indicator.hidden {
|
||
display: none !important;
|
||
}
|
||
|
||
.recording-content {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
color: white;
|
||
}
|
||
|
||
.recording-icon {
|
||
color: var(--color-recording);
|
||
font-size: 20px;
|
||
animation: pulse 1.5s infinite;
|
||
}
|
||
|
||
.recording-text {
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
#stop-recording {
|
||
background: var(--color-recording);
|
||
color: white;
|
||
border: none;
|
||
border-radius: 6px;
|
||
padding: 6px 12px;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: background 0.2s ease;
|
||
}
|
||
|
||
#stop-recording:hover {
|
||
background: var(--color-recording-hover);
|
||
}
|
||
|
||
/* Error state for recording */
|
||
#recording-indicator.error {
|
||
background: rgba(173, 26, 26, 0.9);
|
||
}
|
||
|
||
.recording-error {
|
||
color: var(--color-recording);
|
||
font-size: 14px;
|
||
margin-top: 4px;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
#recording-indicator {
|
||
margin: 8px;
|
||
padding: 10px;
|
||
}
|
||
|
||
.recording-text {
|
||
font-size: 14px;
|
||
}
|
||
|
||
#stop-recording {
|
||
padding: 6px 10px;
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
/* SYNTAX HIGHLIGHTING — uses theme vars from style.css, no hardcoded overrides */
|
||
.hljs { color: var(--hl-fg, #9cdef2); background: none !important; }
|
||
pre { background: var(--code-bg, var(--hl-bg, #282c34)) !important; }
|
||
|
||
/* ---------- Search overlay (Ctrl+K command palette) ---------- */
|
||
.search-overlay {
|
||
position: fixed;
|
||
top: 0; left: 0; width: 100%; height: 100%;
|
||
background: rgba(0, 0, 0, 0.6);
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: center;
|
||
padding-top: var(--search-overlay-top, 15vh);
|
||
z-index: 300;
|
||
backdrop-filter: blur(6px);
|
||
}
|
||
.search-overlay.hidden { display: none; }
|
||
.search-popup {
|
||
width: 520px;
|
||
max-width: 90vw;
|
||
background: var(--bg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 12px;
|
||
box-shadow: 0 16px 48px rgba(0, 0, 0, 0.5), 0 0 0 1px color-mix(in srgb, var(--fg) 6%, transparent);
|
||
overflow: hidden;
|
||
display: flex;
|
||
flex-direction: column;
|
||
max-height: 60vh;
|
||
}
|
||
.search-popup input#search-input {
|
||
width: 100%;
|
||
background: transparent;
|
||
border: none;
|
||
border-bottom: 1px solid var(--border);
|
||
outline: none;
|
||
color: var(--fg);
|
||
font-size: 16px;
|
||
font-family: 'Fira Code', monospace;
|
||
padding: 14px 16px;
|
||
box-sizing: border-box;
|
||
}
|
||
.search-popup input#search-input::placeholder {
|
||
color: color-mix(in srgb, var(--fg) 30%, transparent);
|
||
}
|
||
.search-results {
|
||
overflow-y: auto;
|
||
flex: 1;
|
||
padding: 4px;
|
||
}
|
||
.search-results:empty {
|
||
display: none;
|
||
}
|
||
.search-group-header {
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
color: var(--color-subheader);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.5px;
|
||
padding: 10px 12px 4px;
|
||
}
|
||
.search-result-item {
|
||
display: flex;
|
||
align-items: baseline;
|
||
gap: 8px;
|
||
padding: 8px 12px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
transition: background 0.1s;
|
||
}
|
||
.search-result-item:hover,
|
||
.search-result-item.selected {
|
||
background: color-mix(in srgb, var(--red) 10%, transparent);
|
||
}
|
||
.search-result-role {
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
color: var(--color-subheader);
|
||
flex-shrink: 0;
|
||
min-width: 24px;
|
||
}
|
||
.search-result-snippet {
|
||
flex: 1;
|
||
font-size: 12px;
|
||
color: var(--fg);
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.search-result-time {
|
||
font-size: 10px;
|
||
color: color-mix(in srgb, var(--fg) 35%, transparent);
|
||
flex-shrink: 0;
|
||
white-space: nowrap;
|
||
}
|
||
mark.search-highlight {
|
||
/* Was orange-on-orange (0.35 alpha bg + orange text) — too low-contrast
|
||
to read. Solid accent fill with bg-colored text reads clearly. */
|
||
background: var(--accent, #e8a830);
|
||
color: var(--bg, #1a1a1a);
|
||
border-radius: 2px;
|
||
padding: 0 2px;
|
||
font-weight: 600;
|
||
}
|
||
.search-empty {
|
||
text-align: center;
|
||
color: color-mix(in srgb, var(--fg) 35%, transparent);
|
||
padding: 24px;
|
||
font-size: 13px;
|
||
}
|
||
|
||
/* ---------- Theme popup (uses .modal > .modal-content frame) ---------- */
|
||
#theme-modal { z-index: 260; }
|
||
#theme-popup .theme-popup-sub { color: color-mix(in srgb, var(--fg) 50%, transparent); font-size: 11px; margin-bottom: 10px; }
|
||
/* `max-height` instead of a fixed height so the popup shrinks to fit its
|
||
content (avoids the leftover whitespace after the time-based switching
|
||
card was removed). The inner .theme-tab-panel keeps overflow:auto, so
|
||
any taller content still scrolls inside. */
|
||
#theme-popup { overflow-y: hidden; max-height: min(85vh, 600px); }
|
||
#theme-popup .modal-header { flex-shrink: 0; }
|
||
#theme-popup .admin-tabs { margin: 0 -10px 8px; padding: 0 10px; flex-shrink: 0; }
|
||
.theme-tab-panel { overflow-y: auto; min-height: 0; flex: 1; padding-bottom: 10px; }
|
||
|
||
.theme-grid {
|
||
display: grid; grid-template-columns: repeat(auto-fill, minmax(66px, 1fr));
|
||
gap: 6px; margin-bottom: 12px;
|
||
}
|
||
.theme-swatch {
|
||
border: 2px solid var(--border); border-radius: 8px; cursor: pointer;
|
||
padding: 5px; text-align: center; font-size: 0.65rem; color: var(--fg);
|
||
transition: border-color 0.15s, transform 0.15s;
|
||
}
|
||
.theme-swatch:hover { transform: scale(1.06); }
|
||
.theme-swatch.active { border-color: var(--red); box-shadow: 0 0 0 2px color-mix(in srgb, var(--red) 33%, transparent); }
|
||
.theme-swatch-colors {
|
||
display: flex; justify-content: center; margin-bottom: 3px;
|
||
}
|
||
.theme-swatch-colors span {
|
||
width: 15px; height: 15px; border-radius: 50%;
|
||
margin-left: -5px;
|
||
border: 1.5px solid color-mix(in srgb, var(--fg) 12%, transparent);
|
||
}
|
||
.theme-swatch-colors span:first-child { margin-left: 0; }
|
||
.theme-custom-label { font-size: 11px; font-weight: 600; color: color-mix(in srgb, var(--fg) 50%, transparent); text-transform: uppercase; letter-spacing: 0.06em; margin: 10px 0 6px; }
|
||
.theme-custom { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 12px; }
|
||
.color-row { display: flex; align-items: center; gap: 4px; position: relative; }
|
||
.color-row label { font-size: 13px; font-weight: 500; color: var(--fg); opacity: 0.7; flex: 1; }
|
||
.color-row input[type="color"],
|
||
.color-row input.cp-swatch-input {
|
||
width: 24px; height: 24px; border: 1px solid var(--border); border-radius: 50%;
|
||
background: none; cursor: pointer; padding: 0; flex-shrink: 0;
|
||
overflow: hidden;
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
}
|
||
.color-row input[type="color"]::-webkit-color-swatch-wrapper { padding: 0; }
|
||
.color-row input[type="color"]::-webkit-color-swatch { border: none; border-radius: 50%; }
|
||
.color-row input[type="color"]::-moz-color-swatch { border: none; border-radius: 50%; }
|
||
#theme-bg-effect-color { position: relative; top: 2px; }
|
||
.color-row input.cp-swatch-input {
|
||
color: transparent;
|
||
text-shadow: none;
|
||
caret-color: transparent;
|
||
font-size: 0;
|
||
user-select: none;
|
||
}
|
||
.color-row input.cp-swatch-input::selection { background: transparent; }
|
||
.color-row input.cp-swatch-input:focus { outline: 1px solid var(--red); outline-offset: 1px; }
|
||
.color-reset-btn {
|
||
width: 24px; height: 24px; border: none; background: none; cursor: pointer;
|
||
color: var(--fg); opacity: 0; font-size: 1.15rem; padding: 0; line-height: 1;
|
||
transition: opacity 0.15s, color 0.15s; flex-shrink: 0; pointer-events: none;
|
||
position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
|
||
}
|
||
.color-row input[type="color"],
|
||
.color-row input.cp-swatch-input { margin-left: auto; }
|
||
/* Keep the harmony hex readout on the left, with the swatch dot anchored
|
||
to the right like the other color controls. */
|
||
#theme-harmony-card #harmony-accent-hex {
|
||
order: -1;
|
||
margin-right: auto;
|
||
}
|
||
.color-row:has(.color-reset-btn.changed) input[type="color"],
|
||
.color-row:has(.color-reset-btn.changed) input.cp-swatch-input { margin-right: 28px; }
|
||
.color-reset-btn.changed { opacity: 0.4; pointer-events: auto; }
|
||
.color-reset-btn.changed:hover { opacity: 1; color: var(--red); }
|
||
.theme-custom-divider {
|
||
grid-column: 1 / -1; font-size: 11px; color: var(--fg); opacity: 0.5;
|
||
text-transform: uppercase; letter-spacing: 0.04em; margin: 6px 0 2px;
|
||
border-top: 1px solid var(--border); padding-top: 6px;
|
||
}
|
||
.theme-swatch[data-custom] { position: relative; overflow: visible; }
|
||
/* Accent-coloured circular X — always visible (mobile-friendly), sits
|
||
INSIDE the swatch's top-right corner so it never crops into a
|
||
neighbouring swatch. */
|
||
.theme-delete-btn {
|
||
position: absolute;
|
||
top: -2px;
|
||
right: -2px;
|
||
width: 20px;
|
||
height: 20px;
|
||
padding: 0;
|
||
border: none;
|
||
border-radius: 50%;
|
||
background: var(--accent, var(--red, #d92534));
|
||
color: #fff;
|
||
cursor: pointer;
|
||
z-index: 2;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
|
||
transition: transform 0.12s, background 0.12s;
|
||
}
|
||
.theme-delete-btn:hover {
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 80%, white);
|
||
transform: scale(1.12);
|
||
}
|
||
.theme-delete-btn:active { transform: scale(0.95); }
|
||
.theme-delete-btn svg {
|
||
display: block;
|
||
/* Optical nudge — the X reads off-center inside the circle without it. */
|
||
position: relative;
|
||
left: 1px;
|
||
top: -1px;
|
||
}
|
||
.theme-save-row {
|
||
display: flex; gap: 6px; margin-top: 8px;
|
||
}
|
||
.theme-save-row input {
|
||
flex: 1; padding: 5px 8px; border: 1px solid var(--border); border-radius: 6px;
|
||
background: var(--bg); color: var(--fg); font-size: 12px; font-family: inherit;
|
||
}
|
||
.theme-save-row input:focus { outline: none; border-color: var(--red); }
|
||
.theme-save-row input::placeholder { color: color-mix(in srgb, var(--fg) 35%, transparent); }
|
||
.theme-save-row button {
|
||
padding: 6px 12px; border: 1px solid var(--red); border-radius: 6px;
|
||
background: transparent; color: var(--red); cursor: pointer;
|
||
font-size: 12px; font-family: inherit; white-space: nowrap; transition: all 0.15s;
|
||
}
|
||
.theme-save-row button:hover { background: color-mix(in srgb, var(--red) 11%, transparent); }
|
||
.theme-save-error {
|
||
font-size: 11px; color: var(--red); margin-top: 2px; display: none;
|
||
}
|
||
/* Import/Export */
|
||
.theme-io-row { display: flex; gap: 6px; margin-top: 6px; }
|
||
.theme-io-btn {
|
||
flex: 1; padding: 5px 10px; border: 1px solid var(--border); border-radius: 6px;
|
||
background: transparent; color: var(--fg); cursor: pointer;
|
||
font-size: 12px; opacity: 0.7; transition: all 0.15s; font-family: inherit;
|
||
}
|
||
.theme-io-btn:hover { opacity: 1; border-color: var(--fg); background: color-mix(in srgb, var(--fg) 5%, transparent); }
|
||
|
||
#memory-import-btn svg,
|
||
#memory-export-btn svg {
|
||
color: var(--accent, var(--red));
|
||
}
|
||
.theme-import-area {
|
||
width: 100%; margin-top: 6px; padding: 6px 8px;
|
||
border: 1px solid var(--border); border-radius: 6px;
|
||
background: var(--bg); color: var(--fg); font-size: 0.7rem;
|
||
font-family: inherit; resize: vertical; min-height: 48px;
|
||
}
|
||
.theme-import-area:focus { outline: none; border-color: var(--red); }
|
||
.theme-import-area.hidden { display: none; }
|
||
.theme-import-actions { display: flex; gap: 6px; margin-top: 4px; }
|
||
.theme-import-actions.hidden { display: none; }
|
||
/* Font & Density */
|
||
.theme-fd-row { display: flex; gap: 8px; margin-bottom: 8px; }
|
||
.theme-fd-group { flex: 1; display: flex; flex-direction: column; gap: 3px; }
|
||
.theme-fd-label { font-size: 12px; font-weight: 500; color: var(--fg); opacity: 0.6; }
|
||
.theme-fd-select {
|
||
padding: 5px 8px; border: 1px solid var(--border); border-radius: 6px;
|
||
background: var(--bg); color: var(--fg); font-size: 12px;
|
||
font-family: inherit; cursor: pointer;
|
||
}
|
||
.theme-fd-select:focus { outline: none; border-color: var(--red); }
|
||
@media (max-width: 768px) {
|
||
/* The switch is too cramped beside the Font and Density selects on
|
||
narrow screens; give Frosted a dedicated row instead. */
|
||
.theme-fd-row:first-of-type {
|
||
flex-wrap: wrap;
|
||
}
|
||
.theme-fd-row:first-of-type #theme-frosted-group {
|
||
flex: 1 1 100%;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
min-width: 0;
|
||
}
|
||
}
|
||
.theme-fd-range {
|
||
width: 100%;
|
||
max-width: 100%;
|
||
box-sizing: border-box;
|
||
margin: 0;
|
||
padding: 0;
|
||
height: 24px;
|
||
background: transparent;
|
||
cursor: pointer;
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
accent-color: var(--red);
|
||
}
|
||
.theme-fd-range::-webkit-slider-runnable-track {
|
||
height: 4px; background: var(--border); border-radius: 2px;
|
||
}
|
||
.theme-fd-range::-moz-range-track {
|
||
height: 4px; background: var(--border); border-radius: 2px;
|
||
}
|
||
.theme-fd-range::-webkit-slider-thumb {
|
||
-webkit-appearance: none; appearance: none;
|
||
width: 14px; height: 14px; border-radius: 50%;
|
||
background: var(--red); border: none; margin-top: -5px; cursor: pointer;
|
||
}
|
||
.theme-fd-range::-moz-range-thumb {
|
||
width: 14px; height: 14px; border-radius: 50%;
|
||
background: var(--red); border: none; cursor: pointer;
|
||
}
|
||
.theme-fd-range:focus { outline: none; }
|
||
/* Color Harmony Generator */
|
||
.theme-harmony-row { display: flex; gap: 8px; align-items: flex-end; }
|
||
.harmony-generate-btn {
|
||
padding: 5px 14px; border: 1px solid var(--red); border-radius: 6px;
|
||
background: transparent; color: var(--red); cursor: pointer;
|
||
font-size: 12px; white-space: nowrap; transition: all 0.15s;
|
||
font-family: inherit; width: 100%;
|
||
}
|
||
.harmony-generate-btn:hover { background: color-mix(in srgb, var(--red) 11%, transparent); }
|
||
.harmony-preview {
|
||
display: flex; height: 20px; border-radius: 6px; overflow: hidden;
|
||
margin-top: 8px; border: 1px solid var(--border);
|
||
}
|
||
.harmony-preview:empty { display: none; border: none; }
|
||
.harmony-preview span { flex: 1; }
|
||
#theme-reset-btn {
|
||
margin-top: 6px; width: 100%; padding: 6px; border: 1px solid var(--border);
|
||
border-radius: 6px; background: var(--bg); color: var(--fg); cursor: pointer;
|
||
font-size: 12px; font-family: inherit; opacity: 0.7; transition: opacity 0.15s;
|
||
}
|
||
#theme-reset-btn:hover { opacity: 1; }
|
||
.theme-adv-toggle {
|
||
margin-top: 10px; margin-bottom: 10px;
|
||
padding: 6px 8px; cursor: pointer;
|
||
font-size: 11px; color: var(--red); opacity: 0.8;
|
||
border: 1px solid var(--border); border-radius: 6px;
|
||
transition: opacity 0.15s, background 0.15s;
|
||
user-select: none;
|
||
}
|
||
.theme-adv-toggle:hover { opacity: 1; background: color-mix(in srgb, var(--fg) 4%, transparent); }
|
||
.theme-adv-toggle .theme-adv-arrow {
|
||
display: inline-block; transition: transform 0.2s; font-size: 10px;
|
||
margin-right: 4px;
|
||
}
|
||
.theme-adv-toggle.open .theme-adv-arrow { transform: rotate(90deg); }
|
||
.theme-adv-section { margin-top: 8px; margin-bottom: 10px; }
|
||
.theme-adv-section.hidden { display: none; }
|
||
.theme-adv-group { margin-bottom: 8px; }
|
||
.theme-adv-group-label {
|
||
font-size: 10px; color: var(--fg); opacity: 0.5;
|
||
text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 4px;
|
||
}
|
||
.theme-adv-clear-btn {
|
||
margin-top: 6px; width: 100%; padding: 5px; border: 1px solid var(--border);
|
||
border-radius: 6px; background: transparent; color: var(--fg); opacity: 0.5;
|
||
cursor: pointer; font-size: 12px; font-family: inherit; transition: opacity 0.15s;
|
||
}
|
||
.theme-adv-clear-btn:hover { opacity: 1; }
|
||
|
||
/* Customization is an editor, so keep its sections visually related while
|
||
preserving the existing controls and their order. */
|
||
#theme-tab-customize {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 10px;
|
||
}
|
||
#theme-tab-customize > .admin-card,
|
||
#theme-tab-customize > .theme-adv-toggle,
|
||
#theme-tab-customize > .theme-adv-section {
|
||
margin-top: 0;
|
||
margin-bottom: 0;
|
||
}
|
||
#theme-tab-customize > .admin-card {
|
||
padding: 12px;
|
||
}
|
||
#theme-tab-customize > .admin-card > h2 {
|
||
display: flex;
|
||
align-items: center;
|
||
min-height: 20px;
|
||
margin: 0 0 10px;
|
||
padding-bottom: 7px;
|
||
border-bottom: 1px solid color-mix(in srgb, var(--border) 65%, transparent);
|
||
font-size: 13px;
|
||
}
|
||
#theme-tab-customize .theme-custom {
|
||
gap: 6px 14px;
|
||
}
|
||
#theme-tab-customize .color-row {
|
||
min-height: 30px;
|
||
padding: 3px 6px;
|
||
box-sizing: border-box;
|
||
border: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
|
||
background: color-mix(in srgb, var(--fg) 2%, transparent);
|
||
}
|
||
#theme-tab-customize .color-row label {
|
||
font-size: 12px;
|
||
}
|
||
#theme-tab-customize .theme-adv-toggle {
|
||
flex-shrink: 0;
|
||
margin: 0;
|
||
background: color-mix(in srgb, var(--fg) 2%, transparent);
|
||
}
|
||
#theme-tab-customize .theme-adv-section {
|
||
padding: 10px 12px 2px;
|
||
border: 1px solid color-mix(in srgb, var(--border) 75%, transparent);
|
||
border-radius: 7px;
|
||
background: color-mix(in srgb, var(--panel) 55%, transparent);
|
||
}
|
||
#theme-tab-customize .theme-adv-group {
|
||
margin: 0;
|
||
padding: 0 0 9px;
|
||
border-bottom: 1px solid color-mix(in srgb, var(--border) 48%, transparent);
|
||
}
|
||
#theme-tab-customize .theme-adv-group + .theme-adv-group {
|
||
padding-top: 9px;
|
||
}
|
||
#theme-tab-customize .theme-adv-group:last-of-type {
|
||
border-bottom: 0;
|
||
}
|
||
#theme-tab-customize .theme-adv-group-label {
|
||
margin-bottom: 6px;
|
||
color: var(--red);
|
||
opacity: 0.8;
|
||
font-weight: 600;
|
||
}
|
||
#theme-tab-customize .theme-fd-row,
|
||
#theme-tab-customize .theme-harmony-row {
|
||
gap: 12px;
|
||
margin-bottom: 10px;
|
||
}
|
||
#theme-tab-customize .theme-fd-row:last-child,
|
||
#theme-tab-customize .theme-harmony-row:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
#theme-tab-customize .theme-fd-group {
|
||
min-width: 0;
|
||
}
|
||
#theme-tab-customize .theme-fd-select {
|
||
min-height: 30px;
|
||
}
|
||
#theme-tab-customize #theme-harmony-card .theme-fd-label {
|
||
font-size: 11px;
|
||
}
|
||
#theme-tab-customize .theme-save-row,
|
||
#theme-tab-customize .theme-io-row {
|
||
gap: 8px;
|
||
}
|
||
#theme-tab-customize #theme-reset-btn {
|
||
margin-top: 8px;
|
||
}
|
||
@media (max-width: 560px) {
|
||
#theme-tab-customize .theme-custom {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
#theme-tab-customize .theme-fd-row,
|
||
#theme-tab-customize .theme-harmony-row {
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
}
|
||
#theme-tab-customize .theme-fd-group,
|
||
#theme-tab-customize .theme-harmony-row .theme-fd-group {
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
|
||
/* Mobile: bottom sheet modals — slide up from bottom */
|
||
@media (max-width: 768px) {
|
||
.modal {
|
||
align-items: flex-end;
|
||
background: rgba(0,0,0,0.4);
|
||
pointer-events: auto;
|
||
/* Anchor the bottom sheet to the DYNAMIC viewport. The base overlay is
|
||
position:fixed; height:100% = the layout viewport, whose bottom sits
|
||
UNDER Firefox Android's bottom URL bar — so flex-end parked the sheet
|
||
(and its footer / Start button) beneath the bar. dvh excludes the bar
|
||
so the footer lands above it. Extra safe-area pad for iOS home bar. */
|
||
height: 100dvh;
|
||
padding-bottom: env(safe-area-inset-bottom, 0px);
|
||
}
|
||
/* Confirm dialog stays centered, not a bottom sheet */
|
||
#styled-confirm-overlay {
|
||
align-items: center;
|
||
}
|
||
.styled-confirm-box {
|
||
border-radius: 12px !important;
|
||
border: 1px solid var(--border) !important;
|
||
animation: modal-enter 0.25s ease-out both !important;
|
||
max-height: none !important;
|
||
}
|
||
.styled-confirm-box.modal-closing {
|
||
animation: modal-exit 0.18s ease-in both !important;
|
||
}
|
||
.styled-confirm-box::before {
|
||
display: none !important;
|
||
}
|
||
.styled-confirm-box .close-btn {
|
||
display: none !important;
|
||
}
|
||
#theme-popup {
|
||
width: 100% !important;
|
||
height: 65vh !important;
|
||
max-height: 65vh !important;
|
||
top: auto !important; left: 0 !important; right: 0 !important; bottom: 0 !important;
|
||
position: fixed !important;
|
||
border-radius: 14px 14px 0 0;
|
||
border: none;
|
||
border-top: 1px solid var(--border);
|
||
padding: 6px 12px 12px;
|
||
animation: sheet-enter 0.2s ease-out forwards;
|
||
overflow-y: hidden !important;
|
||
}
|
||
#theme-popup .theme-tab-panel {
|
||
touch-action: pan-y;
|
||
overscroll-behavior: contain;
|
||
-webkit-overflow-scrolling: touch;
|
||
}
|
||
#theme-popup.sheet-ready {
|
||
animation: none;
|
||
}
|
||
#theme-popup.modal-closing {
|
||
animation: sheet-exit 0.15s ease-in both !important;
|
||
}
|
||
.modal-content,
|
||
.memory-modal-content,
|
||
.settings-modal-content,
|
||
#compare-model-overlay .modal-content {
|
||
width: 100% !important;
|
||
/* 85dvh leaves comfortable headroom above the sheet so the user can
|
||
still see the chat behind it and the drag handle has breathing
|
||
room. Was 65vh (too short, content clipped) → 90vh (too tall, top
|
||
hugged the status bar). */
|
||
max-height: 85dvh !important;
|
||
max-height: 85vh !important; /* fallback for browsers without dvh */
|
||
height: auto !important;
|
||
border-radius: 14px 14px 0 0;
|
||
border: none;
|
||
border-top: 1px solid var(--border);
|
||
padding-top: 6px !important;
|
||
/* Clip children to the rounded top corners — otherwise the sticky
|
||
modal-header's var(--panel) background paints a darker
|
||
rectangle past the radius and the corners look square again. */
|
||
overflow: hidden;
|
||
animation: sheet-enter 0.2s ease-out forwards;
|
||
}
|
||
/* Keep the tall tool drawers on a shared mobile height ceiling. The
|
||
final mobile drawer rule below makes this content-sized so shorter
|
||
tools remain compact while tall ones leave a visible top gap. */
|
||
#cookbook-modal .modal-content,
|
||
#tasks-modal .modal-content,
|
||
#calendar-modal .modal-content,
|
||
#memory-modal .memory-modal-content,
|
||
#settings-modal .settings-modal-content,
|
||
#email-lib-modal .modal-content,
|
||
#doclib-modal .doclib-modal-content {
|
||
max-height: 90vh !important;
|
||
max-height: 90dvh !important;
|
||
height: auto !important;
|
||
/* Reserve the iOS home-indicator / bottom-bar strip so an expanded
|
||
skill card's footer (Delete / Edit / Run) isn't hidden under it.
|
||
dvh already excludes the URL bar; this handles the safe area. */
|
||
padding-bottom: env(safe-area-inset-bottom, 0px) !important;
|
||
}
|
||
/* Grab handle pill on the non-standard content classes too. Memory's
|
||
desktop rule defines a radial-glow ::before later in the file —
|
||
these body-prefixed selectors win the specificity battle on mobile. */
|
||
body .memory-modal-content::before,
|
||
body .settings-modal-content::before {
|
||
content: '';
|
||
display: block;
|
||
position: static;
|
||
inset: auto;
|
||
width: 36px; height: 4px;
|
||
background: var(--fg);
|
||
opacity: 0.25;
|
||
border-radius: 2px;
|
||
margin: 0 auto 4px;
|
||
flex-shrink: 0;
|
||
padding: 0;
|
||
border-top: 10px solid transparent;
|
||
border-bottom: 6px solid transparent;
|
||
background-clip: padding-box;
|
||
animation: none;
|
||
}
|
||
.memory-modal-content .close-btn,
|
||
.memory-modal-content .modal-close,
|
||
.settings-modal-content .close-btn,
|
||
.settings-modal-content .modal-close {
|
||
display: none !important;
|
||
}
|
||
.memory-modal-content,
|
||
.settings-modal-content {
|
||
touch-action: pan-y;
|
||
overscroll-behavior: contain;
|
||
}
|
||
/* Library modals use the same bottom-sheet sizing as the other tools.
|
||
The shared mobile drawer rule below provides the top breathing room. */
|
||
#cookbook-modal .modal-content,
|
||
#calendar-modal .modal-content,
|
||
#email-lib-modal .modal-content,
|
||
#doclib-modal .modal-content,
|
||
#gallery-modal .modal-content,
|
||
#tasks-modal .modal-content {
|
||
/* vh-first as fallback for very old browsers, then dvh wins so
|
||
the modal shrinks/grows with the mobile URL bar. Wrong order
|
||
previously made the expanded chat preview extend below the
|
||
visible viewport on Chrome/Safari mobile (URL bar covered the
|
||
action buttons row). */
|
||
max-height: 90vh !important;
|
||
max-height: 90dvh !important;
|
||
height: auto !important;
|
||
}
|
||
/* Anchor those modals to the top so the full height is usable */
|
||
#cookbook-modal,
|
||
#calendar-modal,
|
||
#email-lib-modal,
|
||
#doclib-modal,
|
||
#gallery-modal,
|
||
#tasks-modal {
|
||
padding-top: 0 !important;
|
||
align-items: stretch !important;
|
||
}
|
||
/* Deep Research already gets the swipe grab-handle pill from the
|
||
shared `.modal-content::before` rule (the pane carries that class).
|
||
The previous header-level pill was redundant and rendered as a
|
||
SECOND pill stacked above the real one — removed. */
|
||
/* The inner body must flex to fill the new full height, and the
|
||
tasks list inside it must scroll independently — otherwise the
|
||
list crops at whatever pre-mobile height the desktop layout had. */
|
||
#tasks-modal .modal-content {
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
}
|
||
#tasks-modal .modal-body {
|
||
flex: 1 1 auto !important;
|
||
min-height: 0 !important;
|
||
}
|
||
/* Memory/Skills: the body lacks flex:1, so on the fixed-height mobile
|
||
sheet (overflow:hidden) it grew past the viewport and clipped the
|
||
bottom of the skills list + its row action buttons with no way to
|
||
scroll there. Bound the body so the inner list scrolls internally. */
|
||
#memory-modal .memory-modal-content {
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
}
|
||
/* flex-basis MUST be 0 (not auto) — matches the working #doclib-modal
|
||
.modal-body. With basis:auto, Firefox (incl. mobile) sizes the body
|
||
to its content (~half height) instead of filling, while Chromium
|
||
fills it regardless — which is exactly why the skill expand worked
|
||
on desktop/Chromium but stuck at ~50% on Firefox mobile. */
|
||
#memory-modal .memory-modal-body {
|
||
flex: 1 1 0 !important;
|
||
min-height: 0 !important;
|
||
overflow: hidden !important;
|
||
}
|
||
/* Same basis:0 fix down the rest of the skills chain so every layer
|
||
fills instead of sizing to content under Firefox. */
|
||
#memory-modal .memory-tab-panel[data-memory-panel="skills"] {
|
||
flex: 1 1 0 !important;
|
||
min-height: 0 !important;
|
||
}
|
||
#memory-modal .memory-tab-panel[data-memory-panel="skills"] > .admin-card {
|
||
flex: 1 1 0 !important;
|
||
min-height: 0 !important;
|
||
}
|
||
/* The skills modal carries an extra toolbar row (search/sort/select +
|
||
bulk bar) the doc/email libraries don't, so the shared 82dvh preview
|
||
min-height overflowed here and pushed the expanded footer (Delete /
|
||
Edit / Run) off the bottom of the screen. Let flexbox size it from
|
||
the resolved card height instead, so the footer always pins inside
|
||
the visible area. */
|
||
#memory-modal .doclib-card.doclib-card-expanded .doclib-card-preview {
|
||
min-height: 0 !important;
|
||
}
|
||
/* Once enter animation finishes, clear it so inline transform works for dragging */
|
||
.modal-content.sheet-ready {
|
||
animation: none;
|
||
}
|
||
.modal-content.modal-closing {
|
||
animation: sheet-exit 0.15s ease-in both !important;
|
||
}
|
||
/* Grab handle — large touch target, visible pill */
|
||
#theme-popup::before,
|
||
.modal-content::before {
|
||
content: '';
|
||
display: block;
|
||
width: 36px; height: 4px;
|
||
background: var(--fg); opacity: 0.25;
|
||
border-radius: 2px;
|
||
margin: 0 auto 4px;
|
||
flex-shrink: 0;
|
||
padding: 0;
|
||
/* Expand touch target without changing visual size */
|
||
border-top: 10px solid transparent;
|
||
border-bottom: 6px solid transparent;
|
||
background-clip: padding-box;
|
||
}
|
||
/* Hide close X on mobile — swipe down to dismiss */
|
||
.modal-content .close-btn,
|
||
.modal-content .modal-close,
|
||
#theme-popup .close-btn {
|
||
display: none !important;
|
||
}
|
||
/* Hide the auto-injected minimize (_) button on mobile — the dock
|
||
chip already represents the minimized state, and the swipe-down
|
||
gesture is the canonical minimize action. */
|
||
.modal-minimize-btn,
|
||
.minimize-btn,
|
||
[data-minimize] {
|
||
display: none !important;
|
||
}
|
||
/* Lock modals to vertical touch only, prevent horizontal dragging */
|
||
.modal-content {
|
||
touch-action: pan-y;
|
||
overscroll-behavior: contain;
|
||
}
|
||
.modal-content .cookbook-body,
|
||
.modal-content .modal-body {
|
||
touch-action: pan-y;
|
||
overscroll-behavior: contain;
|
||
}
|
||
.modal-header {
|
||
cursor: default;
|
||
touch-action: none;
|
||
}
|
||
@keyframes sheet-enter {
|
||
from { transform: translateY(100%); }
|
||
to { transform: translateY(0); }
|
||
}
|
||
@keyframes sheet-exit {
|
||
from { transform: translateY(0); }
|
||
to { transform: translateY(100%); }
|
||
}
|
||
}
|
||
|
||
/* ── Model A/B Comparison ── */
|
||
|
||
/* -- Extracted inline-style classes -- */
|
||
.cmp-header-action-btn {
|
||
background: none; border: 1px solid var(--border); color: var(--fg);
|
||
cursor: pointer; padding: 3px 10px; font-size: 11px; font-weight: 600;
|
||
opacity: 0.7; transition: all 0.15s; line-height: 1; border-radius: 4px;
|
||
display: inline-flex; align-items: center; font-family: inherit;
|
||
}
|
||
.cmp-form-control {
|
||
padding: 8px; background: var(--bg); color: var(--fg);
|
||
border: 1px solid var(--border); border-radius: 6px; font-size: 0.85em;
|
||
}
|
||
.cmp-btn-secondary {
|
||
background: transparent; color: var(--fg); border: 1px solid var(--border);
|
||
border-radius: 6px; cursor: pointer;
|
||
}
|
||
.cmp-btn-primary {
|
||
background: var(--fg); color: var(--bg); border: none;
|
||
border-radius: 6px; cursor: pointer; font-weight: 600;
|
||
transition: filter 0.12s, background 0.12s, color 0.12s;
|
||
}
|
||
/* Override global button:hover (which switches bg to var(--panel) =
|
||
very dark) — keep the bright primary look and just brighten slightly. */
|
||
.cmp-btn-primary:hover:not(:disabled) {
|
||
background: var(--fg); color: var(--bg);
|
||
filter: brightness(1.1);
|
||
}
|
||
.cmp-btn-primary:active:not(:disabled) { filter: brightness(0.95); }
|
||
.cmp-btn-secondary:hover:not(:disabled) {
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
border-color: var(--fg); color: var(--fg);
|
||
}
|
||
.cmp-model-row {
|
||
display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
|
||
flex-wrap: wrap;
|
||
padding: 2px 0;
|
||
transition: margin-left 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.15s, border-color 0.15s;
|
||
}
|
||
.cmp-model-row-duplicate {
|
||
margin-left: -4px;
|
||
margin-right: -4px;
|
||
padding: 4px;
|
||
border-radius: 6px;
|
||
background: color-mix(in srgb, var(--color-error) 8%, transparent);
|
||
border: 1px solid color-mix(in srgb, var(--color-error) 20%, transparent);
|
||
}
|
||
.cmp-model-row-swap-target {
|
||
margin-left: -4px;
|
||
margin-right: -4px;
|
||
padding: 4px;
|
||
border-radius: 6px;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 8%, transparent);
|
||
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent, var(--red)) 42%, transparent);
|
||
}
|
||
.cmp-model-row-swap-target .cmp-row-label {
|
||
color: var(--accent, var(--red));
|
||
opacity: 1;
|
||
}
|
||
.cmp-row-label {
|
||
color: var(--fg); font-size: 0.82em; font-weight: 600; min-width: 20px;
|
||
opacity: 0.4; text-align: center; flex-shrink: 0;
|
||
}
|
||
.cmp-model-meta {
|
||
order: 3;
|
||
flex: 1 0 calc(100% - 28px);
|
||
margin-left: 28px;
|
||
margin-top: -4px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
min-width: 0;
|
||
font-size: 10px;
|
||
line-height: 1.2;
|
||
}
|
||
.cmp-model-meta-chip,
|
||
.cmp-model-meta-warning,
|
||
.cmp-model-meta-muted {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
max-width: 100%;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
border-radius: 999px;
|
||
padding: 1px 6px;
|
||
letter-spacing: 0;
|
||
}
|
||
.cmp-model-meta-chip {
|
||
color: color-mix(in srgb, var(--fg) 60%, transparent);
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
border: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
|
||
}
|
||
.cmp-model-meta-warning {
|
||
color: var(--color-error);
|
||
background: color-mix(in srgb, var(--color-error) 10%, transparent);
|
||
border: 1px solid color-mix(in srgb, var(--color-error) 24%, transparent);
|
||
font-weight: 600;
|
||
}
|
||
.cmp-model-meta-muted {
|
||
color: color-mix(in srgb, var(--fg) 36%, transparent);
|
||
}
|
||
.cmp-rm-btn {
|
||
background: none; border: none; color: var(--accent, var(--red)); cursor: pointer;
|
||
min-width: 20px; font-size: 16px; font-weight: 600; opacity: 0.3;
|
||
transition: all 0.15s; padding: 0; line-height: 1; text-align: center;
|
||
position: relative; top: -2px;
|
||
order: 2;
|
||
margin-left: auto;
|
||
align-self: center;
|
||
}
|
||
.cmp-prov-select {
|
||
flex: 0 0 auto; width: 120px; font-size: 0.8em;
|
||
}
|
||
/* Eval-prompts picker — only shown during compare; absolute top-right
|
||
inside .chat-input-top, matching .model-picker-wrap's slot. */
|
||
.chat-input-top > .cmp-eval-wrap {
|
||
position: relative;
|
||
grid-column: 2;
|
||
grid-row: 1;
|
||
top: -2px; right: 0;
|
||
z-index: 2;
|
||
}
|
||
.cmp-eval-btn {
|
||
display: inline-flex; align-items: center; gap: 4px;
|
||
padding: 4px 8px;
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
color: var(--fg);
|
||
font-size: 11px; font-weight: 500;
|
||
font-family: inherit;
|
||
cursor: pointer; opacity: 0.75;
|
||
transition: opacity 0.15s, border-color 0.15s;
|
||
}
|
||
.cmp-eval-btn:hover { opacity: 1; border-color: var(--fg); }
|
||
.cmp-eval-clear {
|
||
display: inline-flex; align-items: center; gap: 4px; margin-left: 4px;
|
||
border: 0; background: transparent; color: var(--fg); opacity: .55;
|
||
padding: 3px 5px; font: inherit; font-size: 10px; cursor: pointer;
|
||
}
|
||
.cmp-eval-clear:hover { opacity: 1; }
|
||
.cmp-eval-caret { opacity: 0.7; transform: rotate(180deg); }
|
||
.cmp-eval-menu {
|
||
position: absolute; bottom: calc(100% + 4px); right: 0;
|
||
min-width: 220px; max-width: 280px;
|
||
max-height: 360px; overflow-y: auto;
|
||
background: var(--panel);
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
box-shadow: 0 -4px 16px rgba(0,0,0,0.3);
|
||
padding: 4px;
|
||
z-index: 1000;
|
||
}
|
||
.cmp-eval-menu.hidden { display: none; }
|
||
.cmp-eval-group-label {
|
||
font-size: 9px; text-transform: uppercase; letter-spacing: 0.5px;
|
||
opacity: 0.45; font-weight: 600;
|
||
padding: 6px 8px 2px;
|
||
}
|
||
.cmp-eval-item {
|
||
display: block; width: 100%;
|
||
text-align: left;
|
||
padding: 5px 8px;
|
||
background: none; border: none;
|
||
color: var(--fg); font-size: 11px;
|
||
font-family: inherit;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
}
|
||
.cmp-eval-item:hover {
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
}
|
||
.cmp-eval-empty {
|
||
padding: 10px; text-align: center;
|
||
font-size: 11px; opacity: 0.5;
|
||
}
|
||
/* Tick on items that ship a known expected answer */
|
||
.cmp-eval-item-tick {
|
||
float: right;
|
||
margin-left: 6px;
|
||
font-size: 10px;
|
||
color: var(--color-success, #4caf50);
|
||
opacity: 0.8;
|
||
}
|
||
/* Expected-answer panel — floats as its own little window above the
|
||
chat-input-bar. Distinct surface, padded, drop-shadow, slightly
|
||
lifted so it reads as a separate UI element, not part of the input. */
|
||
.chat-input-bar:has(.cmp-eval-expected) { position: relative; }
|
||
.cmp-eval-expected {
|
||
position: absolute;
|
||
bottom: calc(100% + 8px);
|
||
right: 0;
|
||
display: inline-flex; align-items: center; gap: 8px;
|
||
padding: 8px 12px;
|
||
font-size: 11px;
|
||
background: var(--panel);
|
||
border: 1px solid color-mix(in srgb, var(--color-success, #4caf50) 50%, transparent);
|
||
border-radius: 8px;
|
||
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4), 0 1px 2px rgba(0, 0, 0, 0.2);
|
||
color: var(--fg);
|
||
width: fit-content;
|
||
z-index: 5;
|
||
pointer-events: auto;
|
||
}
|
||
.cmp-eval-expected.hidden { display: none; }
|
||
.cmp-eval-expected-label {
|
||
opacity: 0.6;
|
||
text-transform: uppercase;
|
||
font-size: 9px;
|
||
letter-spacing: 0.5px;
|
||
font-weight: 600;
|
||
}
|
||
.cmp-eval-expected-value {
|
||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||
font-size: 11px;
|
||
}
|
||
.cmp-eval-expected-close {
|
||
background: none; border: none; color: var(--fg);
|
||
font-size: 14px; line-height: 1; padding: 0 0 0 4px;
|
||
opacity: 0.5; cursor: pointer; font-family: inherit;
|
||
}
|
||
.cmp-eval-expected-close:hover { opacity: 1; }
|
||
/* Auto-grade badge — stamped on a pane after stream completes when an
|
||
eval prompt with a known expected answer was used. */
|
||
.pane-grade-badge {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
width: 18px; height: 18px;
|
||
margin: 0 4px;
|
||
font-size: 12px; font-weight: 700;
|
||
border-radius: 50%;
|
||
border: 1px solid currentColor;
|
||
flex-shrink: 0;
|
||
}
|
||
.pane-grade-badge.pass {
|
||
color: var(--color-success, #4caf50);
|
||
background: color-mix(in srgb, var(--color-success, #4caf50) 12%, transparent);
|
||
}
|
||
.pane-grade-badge.fail {
|
||
color: var(--color-error, #e55);
|
||
background: color-mix(in srgb, var(--color-error, #e55) 12%, transparent);
|
||
}
|
||
|
||
/* Compare probe overlay */
|
||
.compare-probe-overlay {
|
||
position: fixed; inset: 0; z-index: 300;
|
||
background: rgba(0,0,0,0.5); display: flex;
|
||
align-items: center; justify-content: center;
|
||
padding: 12px;
|
||
box-sizing: border-box;
|
||
}
|
||
.compare-probe-card {
|
||
width: min(460px, calc(100% - 16px));
|
||
max-height: min(620px, calc(100dvh - 24px));
|
||
box-sizing: border-box;
|
||
background: var(--bg); border: 1px solid var(--border); border-radius: 8px; padding: 14px;
|
||
display: flex; flex-direction: column; align-items: stretch; gap: 10px;
|
||
min-width: 280px; box-shadow: 0 8px 28px rgba(0,0,0,0.28);
|
||
overflow: hidden;
|
||
font-family: inherit;
|
||
}
|
||
.compare-probe-title {
|
||
font-size: 13px; font-weight: 400; color: var(--fg);
|
||
}
|
||
.compare-probe-title-label { font-weight: 600; }
|
||
.compare-probe-title-status { font-weight: 400; }
|
||
.compare-probe-list {
|
||
display: grid; grid-template-columns: 1fr 1fr; gap: 6px; min-width: 0; width: 100%;
|
||
overflow-y: auto;
|
||
}
|
||
.compare-probe-row {
|
||
display: flex; align-items: center; gap: 6px; padding: 6px 10px;
|
||
border-radius: 6px; background: color-mix(in srgb, var(--fg) 4%, transparent);
|
||
font-size: 12px; transition: background 0.2s; overflow: hidden;
|
||
}
|
||
.compare-probe-row.fail {
|
||
background: color-mix(in srgb, var(--color-error, #f44) 8%, transparent);
|
||
}
|
||
.compare-probe-spinner {
|
||
width: 24px; text-align: center; font-size: 10px; flex-shrink: 0;
|
||
letter-spacing: -1px; opacity: 0.6;
|
||
}
|
||
.compare-probe-spinner.ok { color: var(--color-success); animation: none; }
|
||
.compare-probe-spinner.fail { color: var(--color-error, #f44); animation: none; }
|
||
.compare-probe-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.compare-probe-status { font-size: 11px; opacity: 0.5; flex-shrink: 0; max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.compare-probe-status.ok { color: var(--color-success); opacity: 1; }
|
||
.compare-probe-status.fail { color: var(--color-error, #f44); opacity: 1; }
|
||
.compare-probe-action-btn {
|
||
display: inline-flex; align-items: center; gap: 5px;
|
||
min-height: 25px; padding: 3px 8px; background: transparent; color: var(--fg); border: 1px solid var(--border);
|
||
border-radius: 5px; cursor: pointer; font-size: 10px; font-family: inherit;
|
||
opacity: 0.78; transition: opacity 0.15s, border-color 0.15s, background 0.15s; white-space: nowrap; flex-shrink: 0;
|
||
}
|
||
.compare-probe-action-btn svg,
|
||
.compare-probe-footer-btn svg { width: 12px; height: 12px; flex: 0 0 auto; color: var(--accent, var(--red)); }
|
||
.compare-probe-action-btn:hover { opacity: 1; border-color: var(--accent, var(--red)); background: color-mix(in srgb, var(--fg) 5%, transparent); }
|
||
.compare-probe-feedback { display: flex; flex-direction: column; gap: 5px; }
|
||
.compare-probe-feedback:empty { display: none; }
|
||
.compare-probe-detail {
|
||
display: flex; align-items: center; gap: 6px; min-width: 0;
|
||
padding: 6px 8px; font-size: 10px;
|
||
background: color-mix(in srgb, var(--color-error, #f44) 6%, transparent);
|
||
border-left: 2px solid color-mix(in srgb, var(--color-error, #f44) 72%, transparent);
|
||
border-radius: 4px;
|
||
}
|
||
.compare-probe-detail-icon {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex: 0 0 14px;
|
||
width: 14px;
|
||
height: 14px;
|
||
color: var(--accent, var(--red));
|
||
font-family: inherit;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
line-height: 1;
|
||
}
|
||
.compare-probe-detail-message { flex: 1 1 auto; min-width: 0; line-height: 1.35; color: color-mix(in srgb, var(--fg) 72%, transparent); overflow-wrap: anywhere; }
|
||
.compare-probe-footer { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%; margin-top: 2px; }
|
||
.compare-probe-footer-btn {
|
||
display: inline-flex; align-items: center; gap: 6px; min-height: 30px; padding: 5px 10px;
|
||
font-family: inherit; font-size: 11px; font-weight: 600; line-height: 1;
|
||
}
|
||
.compare-probe-start-anyway,
|
||
.compare-probe-start-anyway:hover:not(:disabled) {
|
||
background: var(--accent, var(--red));
|
||
border: 1px solid var(--accent, var(--red));
|
||
color: var(--bg);
|
||
}
|
||
.compare-probe-start-anyway svg { color: currentColor; }
|
||
.compare-probe-start-anyway span { font-weight: 700; }
|
||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||
@keyframes pane-shake {
|
||
0%, 100% { transform: translateX(0); }
|
||
15% { transform: translateX(-3px) rotate(-0.5deg); }
|
||
30% { transform: translateX(3px) rotate(0.5deg); }
|
||
45% { transform: translateX(-2px); }
|
||
60% { transform: translateX(2px); }
|
||
75% { transform: translateX(-1px); }
|
||
}
|
||
|
||
.chat-container.compare-active {
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding: 0;
|
||
overflow: hidden;
|
||
animation: compare-enter 0.3s ease-out;
|
||
}
|
||
@keyframes compare-enter {
|
||
from { opacity: 0; transform: translateY(8px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
.chat-container.compare-active .chat-input-bar {
|
||
margin-bottom: 0;
|
||
}
|
||
.chat-container.compare-active #model-picker-wrap {
|
||
display: none !important;
|
||
}
|
||
.compare-grid {
|
||
display: grid;
|
||
gap: 4px;
|
||
flex: 1 1 0;
|
||
min-height: 0;
|
||
overflow: hidden;
|
||
position: relative;
|
||
}
|
||
.compare-mobile-tabs { display: none; }
|
||
.compare-grid[data-cols="2"] { grid-template-columns: 1fr 1fr; }
|
||
.compare-grid[data-cols="3"] { grid-template-columns: 1fr 1fr 1fr; }
|
||
.compare-grid[data-cols="4"] { grid-template-columns: repeat(4, 1fr); }
|
||
.compare-grid[data-cols="5"] { grid-template-columns: repeat(4, 1fr); }
|
||
.compare-grid[data-cols="6"] { grid-template-columns: repeat(4, 1fr); }
|
||
.compare-grid[data-cols="7"] { grid-template-columns: repeat(4, 1fr); }
|
||
.compare-grid[data-cols="8"] { grid-template-columns: repeat(4, 1fr); }
|
||
.compare-grid { grid-auto-rows: 1fr; }
|
||
.compare-shuffle-notice {
|
||
position: absolute;
|
||
left: 50%;
|
||
top: 50%;
|
||
transform: translate(-50%, -50%) scale(0.94);
|
||
z-index: 30;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 10px 14px;
|
||
border: 1px solid color-mix(in srgb, var(--red) 28%, var(--border));
|
||
border-radius: 8px;
|
||
background: color-mix(in srgb, var(--panel, var(--bg)) 92%, transparent);
|
||
color: var(--fg);
|
||
box-shadow: 0 10px 30px color-mix(in srgb, #000 24%, transparent);
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
line-height: 1;
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity 0.14s ease, transform 0.14s ease;
|
||
}
|
||
.compare-shuffle-notice.show {
|
||
opacity: 1;
|
||
transform: translate(-50%, -50%) scale(1);
|
||
}
|
||
.compare-shuffle-notice-icon {
|
||
display: inline-flex;
|
||
color: var(--red);
|
||
animation: compare-shuffle-dice 0.56s ease both;
|
||
}
|
||
.compare-shuffle-notice-icon svg {
|
||
display: block;
|
||
width: 18px;
|
||
height: 18px;
|
||
}
|
||
@keyframes compare-shuffle-dice {
|
||
0% { transform: rotate(-18deg) scale(0.9); }
|
||
55% { transform: rotate(380deg) scale(1.08); }
|
||
100% { transform: rotate(360deg) scale(1); }
|
||
}
|
||
/* Sequential waterfall layout — stacked rows, staggered left, flush right */
|
||
.compare-grid.sequential-layout {
|
||
display: flex !important;
|
||
flex-direction: column !important;
|
||
grid-template-columns: none !important;
|
||
gap: 4px;
|
||
overflow-y: auto;
|
||
}
|
||
.compare-grid.sequential-layout .compare-pane {
|
||
flex-shrink: 0;
|
||
min-height: 200px;
|
||
transition: margin-left 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease;
|
||
}
|
||
/* Herringbone diagonal cut on left side of sequential pane headers */
|
||
.compare-grid.sequential-layout .compare-pane .pane-header {
|
||
clip-path: polygon(20px 0, 100% 0, 100% 100%, 0 100%);
|
||
padding-left: 26px;
|
||
}
|
||
.compare-pane {
|
||
display: flex;
|
||
flex-direction: column;
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
overflow: hidden;
|
||
min-height: 0;
|
||
min-width: 0;
|
||
position: relative;
|
||
transition: border-color 0.18s ease, box-shadow 0.18s ease, opacity 0.18s ease;
|
||
}
|
||
.compare-pane::before {
|
||
content: "";
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
height: 2px;
|
||
z-index: 2;
|
||
pointer-events: none;
|
||
background: transparent;
|
||
transform-origin: left center;
|
||
}
|
||
.compare-pane.is-streaming {
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 34%, var(--border));
|
||
box-shadow: inset 0 1px 0 color-mix(in srgb, var(--accent, var(--red)) 12%, transparent);
|
||
}
|
||
.compare-pane.is-streaming::before {
|
||
background: linear-gradient(90deg, transparent 0%, var(--accent, var(--red)) 35%, var(--red) 50%, var(--accent, var(--red)) 65%, transparent 100%);
|
||
animation: compare-pane-progress 1.25s linear infinite;
|
||
}
|
||
.compare-pane.is-awaiting-input {
|
||
border-color: color-mix(in srgb, var(--red) 42%, var(--border));
|
||
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--red) 12%, transparent);
|
||
}
|
||
.compare-pane.is-awaiting-input::before {
|
||
background: var(--red);
|
||
animation: none;
|
||
}
|
||
.compare-pane.is-done {
|
||
border-color: color-mix(in srgb, var(--green, #50fa7b) 20%, var(--border));
|
||
}
|
||
.compare-pane.is-failed {
|
||
border-color: color-mix(in srgb, var(--color-error) 42%, var(--border));
|
||
}
|
||
.compare-pane.is-failed::before {
|
||
background: var(--color-error);
|
||
}
|
||
@keyframes compare-pane-progress {
|
||
from { transform: translateX(-100%); }
|
||
to { transform: translateX(100%); }
|
||
}
|
||
.compare-pane .pane-header {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: stretch;
|
||
gap: 4px;
|
||
padding: 4px 10px;
|
||
background: color-mix(in srgb, var(--fg) 4%, transparent);
|
||
border-bottom: 1px solid var(--border);
|
||
font-size: 0.82em;
|
||
font-weight: 600;
|
||
color: var(--fg);
|
||
transition: background 0.4s;
|
||
flex-shrink: 0;
|
||
overflow: visible;
|
||
min-width: 0;
|
||
flex-wrap: nowrap;
|
||
}
|
||
.pane-header-row { display: flex; align-items: center; width: 100%; min-width: 0; }
|
||
.pane-header-primary { min-height: 24px; }
|
||
.pane-header-secondary { min-height: 20px; }
|
||
.pane-primary-actions, .pane-stats { display: flex; align-items: center; gap: 4px; min-width: 0; }
|
||
.pane-primary-actions { margin-left: auto; flex: 0 0 auto; }
|
||
.pane-stats { flex: 1 1 auto; overflow: hidden; }
|
||
.compare-header-bar button:hover,
|
||
.compare-header-bar button:focus-visible {
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 14%, transparent) !important;
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 55%, var(--border)) !important;
|
||
color: var(--fg) !important;
|
||
opacity: 1 !important;
|
||
outline: none;
|
||
}
|
||
.compare-header-bar button:active {
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 24%, transparent) !important;
|
||
transform: scale(0.96);
|
||
}
|
||
.compare-more-wrap { position: relative; display: inline-flex; }
|
||
.compare-more-btn {
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
width: 28px; height: 24px; padding: 0 !important;
|
||
border: 1px solid transparent; border-radius: 5px;
|
||
background: none; color: var(--fg); cursor: pointer;
|
||
opacity: 0.5; transition: opacity .15s, background .15s;
|
||
}
|
||
.compare-header-bar .compare-close-btn {
|
||
width: 24px; height: 24px; min-width: 24px; padding: 0;
|
||
border-radius: 999px; font-size: 0; display: inline-flex;
|
||
align-items: center; justify-content: center;
|
||
}
|
||
.compare-header-bar .compare-close-btn:hover,
|
||
.compare-header-bar .compare-close-btn:focus-visible {
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent) !important;
|
||
border-color: transparent !important;
|
||
color: var(--fg) !important;
|
||
opacity: 1 !important;
|
||
outline: none;
|
||
}
|
||
.compare-header-bar .compare-more-btn:hover,
|
||
.compare-header-bar .compare-more-btn:focus-visible,
|
||
.compare-header-bar .compare-more-btn[aria-expanded="true"] {
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent) !important;
|
||
border-color: transparent !important;
|
||
color: var(--fg) !important;
|
||
opacity: 1 !important;
|
||
outline: none;
|
||
}
|
||
.compare-more-menu {
|
||
position: absolute; top: calc(100% + 5px); right: 0; z-index: 10002;
|
||
display: none; flex-direction: column; gap: 3px; min-width: 132px;
|
||
padding: 5px; border: 1px solid var(--border); border-radius: 8px;
|
||
background: var(--panel, var(--bg)); box-shadow: 0 8px 24px rgba(0,0,0,.3);
|
||
}
|
||
.compare-more-menu.is-open { display: flex; }
|
||
.compare-more-menu > .compare-export-wrap,
|
||
.compare-more-menu > button {
|
||
width: 100%; display: flex; align-items: center;
|
||
}
|
||
.compare-more-menu #compare-export-btn,
|
||
.compare-more-menu #compare-shuffle-btn,
|
||
.compare-more-menu #compare-check-btn,
|
||
.compare-more-menu #compare-add-menu-btn {
|
||
width: 100%; min-height: 32px; height: 32px;
|
||
box-sizing: border-box; justify-content: flex-start; gap: 7px;
|
||
padding: 7px 9px !important;
|
||
border: 1px solid transparent !important; border-radius: 6px;
|
||
background: transparent !important; color: var(--fg) !important;
|
||
font-size: 11px; font-weight: 500; opacity: .72;
|
||
transition: background .12s ease, opacity .12s ease, color .12s ease;
|
||
}
|
||
.compare-more-menu #compare-export-btn:hover,
|
||
.compare-more-menu #compare-shuffle-btn:hover,
|
||
.compare-more-menu #compare-check-btn:hover,
|
||
.compare-more-menu #compare-add-menu-btn:hover,
|
||
.compare-more-menu #compare-export-btn:focus-visible,
|
||
.compare-more-menu #compare-shuffle-btn:focus-visible,
|
||
.compare-more-menu #compare-check-btn:focus-visible,
|
||
.compare-more-menu #compare-add-menu-btn:focus-visible {
|
||
opacity: 1; background: color-mix(in srgb, var(--red) 10%, transparent) !important;
|
||
border-color: transparent !important; color: var(--fg) !important; outline: none;
|
||
}
|
||
.compare-more-menu #compare-export-btn svg,
|
||
.compare-more-menu #compare-shuffle-btn svg,
|
||
.compare-more-menu #compare-check-btn svg,
|
||
.compare-more-menu #compare-add-menu-btn svg { flex: 0 0 auto; opacity: .65; }
|
||
.compare-more-menu #compare-export-btn span,
|
||
.compare-more-menu #compare-shuffle-btn span,
|
||
.compare-more-menu #compare-check-btn span,
|
||
.compare-more-menu #compare-add-menu-btn span {
|
||
font-size: 11px !important; margin-left: 0 !important;
|
||
color: var(--fg) !important; opacity: 1 !important; font-weight: 500 !important;
|
||
}
|
||
.compare-more-menu #compare-export-btn,
|
||
.compare-more-menu #compare-shuffle-btn,
|
||
.compare-more-menu #compare-check-btn,
|
||
.compare-more-menu #compare-add-menu-btn {
|
||
color: var(--fg) !important; opacity: 1 !important; font-weight: 500 !important;
|
||
}
|
||
.compare-more-menu #compare-export-btn svg,
|
||
.compare-more-menu #compare-shuffle-btn svg,
|
||
.compare-more-menu #compare-check-btn svg,
|
||
.compare-more-menu #compare-add-menu-btn svg { color: var(--fg) !important; opacity: .65 !important; }
|
||
.compare-export-item:hover,
|
||
.compare-export-item:focus-visible {
|
||
background: color-mix(in srgb, var(--red) 10%, transparent) !important;
|
||
border-color: transparent !important; outline: none;
|
||
}
|
||
.compare-export-item { display: flex; align-items: center; gap: 8px; }
|
||
.compare-export-item > svg { flex: 0 0 auto; opacity: .65; }
|
||
.compare-export-menu .compare-export-item,
|
||
.compare-export-menu .compare-export-item > span {
|
||
color: var(--fg) !important;
|
||
opacity: 1 !important;
|
||
}
|
||
.compare-add-flap {
|
||
position: absolute; z-index: 20; right: -8px; top: 50%;
|
||
width: 34px; min-width: 34px; height: 30px; box-sizing: border-box;
|
||
padding: 0 !important;
|
||
display: inline-flex; flex-direction: row; align-items: center; justify-content: center;
|
||
gap: 0; border: 1px solid var(--border);
|
||
border-radius: 0 7px 7px 0; background: var(--panel, var(--bg));
|
||
color: var(--fg); cursor: pointer; opacity: .7;
|
||
box-shadow: 3px 2px 9px color-mix(in srgb, var(--fg) 12%, transparent);
|
||
transform: translate(0, -50%); transition: width .18s ease, opacity .15s, background .15s, box-shadow .15s;
|
||
}
|
||
.compare-add-flap:hover, .compare-add-flap:focus-visible {
|
||
width: 70px; opacity: 1; background: color-mix(in srgb, var(--fg) 8%, var(--panel));
|
||
box-shadow: 4px 3px 12px color-mix(in srgb, var(--fg) 18%, transparent);
|
||
outline: none;
|
||
}
|
||
.compare-add-flap span {
|
||
max-width: 0; overflow: hidden; white-space: nowrap; margin-left: 0 !important;
|
||
font-size: 10px; opacity: 0; transition: max-width .18s ease, margin-left .18s ease, opacity .12s;
|
||
}
|
||
.compare-add-flap:hover span, .compare-add-flap:focus-visible span {
|
||
max-width: 32px; margin-left: 3px !important; opacity: 1;
|
||
}
|
||
.compare-add-flap svg { flex-shrink: 0; position: relative; left: -3px; }
|
||
@media (max-width: 768px) {
|
||
.compare-add-flap {
|
||
top: 8px; right: 8px; width: auto; min-width: 32px; height: 32px;
|
||
padding: 5px 8px !important; flex-direction: row; transform: none;
|
||
border-right: 1px solid var(--border); border-radius: 6px;
|
||
}
|
||
.compare-add-flap span { opacity: 1; }
|
||
}
|
||
.pane-actions {
|
||
display: flex; gap: 4px; align-items: center; margin-left: auto; flex-shrink: 0;
|
||
}
|
||
.compare-pane-footer {
|
||
font-size: 0.72em; opacity: 0.4; padding: 4px 10px;
|
||
border-top: 1px solid color-mix(in srgb, var(--border) 40%, transparent);
|
||
text-align: center; flex-shrink: 0;
|
||
}
|
||
/* Per-pane vote button. Sits at the bottom of each compare pane so
|
||
the action lives right under the response it judges. */
|
||
.pane-vote-footer {
|
||
padding: 6px 8px;
|
||
border-top: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
|
||
background: color-mix(in srgb, var(--fg) 3%, transparent);
|
||
flex-shrink: 0;
|
||
}
|
||
.pane-vote-btn {
|
||
width: 100%;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 4px;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
padding: 6px 10px;
|
||
font-family: inherit;
|
||
font-size: 12px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: background 0.15s, border-color 0.15s, opacity 0.15s;
|
||
}
|
||
.pane-vote-btn:hover:not(:disabled) {
|
||
background: color-mix(in srgb, var(--accent, var(--fg)) 12%, var(--bg));
|
||
border-color: var(--accent, var(--fg));
|
||
}
|
||
.pane-vote-btn:disabled { cursor: not-allowed; }
|
||
.pane-vote-label {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
min-width: 0;
|
||
}
|
||
.pane-action-btn {
|
||
background: none; border: none; color: var(--fg); cursor: pointer;
|
||
opacity: 0.3; padding: 2px; border-radius: 4px;
|
||
display: flex; align-items: center; transition: all 0.15s;
|
||
}
|
||
.pane-action-btn:hover { opacity: 0.8; background: color-mix(in srgb, var(--fg) 6%, transparent); }
|
||
/* Pane title as clickable model-swap button */
|
||
.pane-title-btn {
|
||
background: none; border: none; cursor: pointer;
|
||
font-size: 10px; font-weight: 400; font-family: inherit;
|
||
color: var(--fg); padding: 0;
|
||
text-align: left; display: flex; align-items: center; gap: 4px;
|
||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||
transition: opacity 0.15s;
|
||
min-width: 0; flex: 1 1 0;
|
||
}
|
||
.pane-title-btn:hover { opacity: 0.7; }
|
||
.pane-title-caret { font-size: 0.6em; opacity: 0.35; flex-shrink: 0; position: relative; top: 2px; }
|
||
.pane-title-btn:hover .pane-title-caret { opacity: 0.7; }
|
||
.pane-mode-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
flex: 0 0 auto;
|
||
height: 18px;
|
||
padding: 0 6px;
|
||
border: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
|
||
border-radius: 999px;
|
||
background: color-mix(in srgb, var(--fg) 3%, var(--bg));
|
||
color: color-mix(in srgb, var(--fg) 76%, transparent);
|
||
font-size: 9px;
|
||
font-weight: 600;
|
||
line-height: 1;
|
||
letter-spacing: 0;
|
||
white-space: nowrap;
|
||
}
|
||
.pane-mode-dot {
|
||
width: 5px;
|
||
height: 5px;
|
||
border-radius: 50%;
|
||
background: currentColor;
|
||
opacity: 0.75;
|
||
flex: 0 0 auto;
|
||
}
|
||
.pane-mode-detail {
|
||
opacity: 0.52;
|
||
font-weight: 500;
|
||
}
|
||
.pane-mode-badge.pane-mode-icon-only {
|
||
width: 20px;
|
||
padding: 0;
|
||
justify-content: center;
|
||
}
|
||
.pane-mode-settings {
|
||
opacity: 0.65;
|
||
cursor: pointer;
|
||
}
|
||
.pane-settings-btn { width: 20px; height: 20px; justify-content: center; }
|
||
.pane-settings-btn[aria-expanded="true"] { opacity: 1; background: color-mix(in srgb, var(--fg) 9%, transparent); }
|
||
.response-metrics[data-action="settings"] { cursor: pointer; }
|
||
.response-thinking-state { color: color-mix(in srgb, var(--fg) 55%, transparent); }
|
||
.pane-mode-settings:hover,
|
||
.pane-mode-settings:focus-visible,
|
||
.pane-mode-settings[aria-expanded="true"] {
|
||
opacity: 1;
|
||
color: var(--fg);
|
||
background: color-mix(in srgb, var(--fg) 9%, var(--bg));
|
||
border-color: color-mix(in srgb, var(--accent, var(--fg)) 45%, var(--border));
|
||
outline: none;
|
||
}
|
||
.pane-mode-icon,
|
||
.pane-mode-icon svg {
|
||
display: block;
|
||
width: 12px;
|
||
height: 12px;
|
||
}
|
||
.pane-mode-agent {
|
||
color: color-mix(in srgb, var(--fg) 76%, transparent);
|
||
background: color-mix(in srgb, var(--fg) 3%, var(--bg));
|
||
border-color: color-mix(in srgb, var(--border) 70%, transparent);
|
||
}
|
||
.pane-mode-search {
|
||
color: color-mix(in srgb, var(--accent, var(--red)) 82%, var(--fg));
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 10%, var(--bg));
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 28%, var(--border));
|
||
}
|
||
.pane-mode-research {
|
||
color: color-mix(in srgb, #36c48f 82%, var(--fg));
|
||
background: color-mix(in srgb, #36c48f 10%, var(--bg));
|
||
border-color: color-mix(in srgb, #36c48f 28%, var(--border));
|
||
}
|
||
.compare-check-label {
|
||
position: relative;
|
||
top: -2px;
|
||
font-size: 11px;
|
||
margin-left: 3px;
|
||
}
|
||
.compare-check-icon {
|
||
position: relative;
|
||
top: 1px;
|
||
}
|
||
#compare-check-btn > .spinner-whirlpool {
|
||
position: relative;
|
||
top: -2px;
|
||
transform: none;
|
||
}
|
||
.compare-pane .pane-close-btn { opacity: 0.3; }
|
||
.compare-pane .pane-close-btn:hover { opacity: 1; color: var(--color-error); }
|
||
/* Model swap dropdown under pane title */
|
||
.pane-model-dropdown {
|
||
position: absolute;
|
||
z-index: 1000;
|
||
min-width: 220px;
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
background: var(--bg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
box-shadow: 0 4px 16px rgba(0,0,0,0.3);
|
||
padding: 4px;
|
||
}
|
||
.pane-model-item {
|
||
display: block; width: 100%;
|
||
box-sizing: border-box;
|
||
padding: 8px 10px; font-size: 11px; line-height: 1.3;
|
||
text-align: left; background: none; border: none; border-radius: 6px;
|
||
color: var(--fg); cursor: pointer; transition: background 0.12s ease;
|
||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||
}
|
||
.pane-model-item:hover,
|
||
.pane-model-item:focus-visible { background: color-mix(in srgb, var(--red) 10%, transparent); outline: none; }
|
||
.pane-model-item.current { color: var(--red); font-weight: 600; }
|
||
.pane-timer {
|
||
font-size: 10px; font-weight: 400; opacity: 0.45; font-variant-numeric: tabular-nums;
|
||
white-space: nowrap; padding-right: 4px;
|
||
}
|
||
.pane-summary {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
position: relative;
|
||
top: 1px;
|
||
min-height: 16px;
|
||
max-width: 150px;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
padding: 0 5px;
|
||
border-radius: 999px;
|
||
background: color-mix(in srgb, var(--fg) 4%, transparent);
|
||
color: color-mix(in srgb, var(--fg) 58%, transparent);
|
||
font-size: 9px;
|
||
font-weight: 500;
|
||
line-height: 1;
|
||
font-variant-numeric: tabular-nums;
|
||
cursor: pointer;
|
||
transition: max-width .15s ease, white-space .15s ease;
|
||
}
|
||
.pane-summary:empty { display: none; }
|
||
.pane-stats-popup {
|
||
position: fixed; z-index: 10040; width: 210px; padding: 6px;
|
||
background: var(--panel, var(--bg)); color: var(--fg);
|
||
border: 1px solid var(--border); border-radius: 7px;
|
||
box-shadow: 0 8px 24px rgba(0,0,0,.3); font-size: 11px;
|
||
}
|
||
.pane-stats-popup-title { padding: 4px 6px 7px; font-weight: 600; border-bottom: 1px solid var(--border); }
|
||
.pane-stats-popup-row { display: flex; justify-content: space-between; gap: 12px; padding: 6px; }
|
||
.pane-stats-popup-row span { color: color-mix(in srgb, var(--fg) 55%, transparent); }
|
||
.pane-stats-popup-row strong { font-weight: 500; font-variant-numeric: tabular-nums; text-align: right; }
|
||
/* Metrics stay on the lower row even in dense comparisons. */
|
||
.compare-grid[data-cols="4"] .pane-timer,
|
||
.compare-grid[data-cols="5"] .pane-timer,
|
||
.compare-grid[data-cols="6"] .pane-timer {
|
||
width: auto; order: initial; margin-top: 0; padding-bottom: 0; padding-left: 0;
|
||
}
|
||
.pane-finish-badge {
|
||
font-weight: 600; color: var(--green, #50fa7b);
|
||
position: relative;
|
||
top: 2px;
|
||
}
|
||
.compare-pane.winner .pane-header {
|
||
background: color-mix(in srgb, var(--green, #50fa7b) 12%, transparent);
|
||
border-bottom-color: color-mix(in srgb, var(--green, #50fa7b) 30%, var(--border));
|
||
}
|
||
.compare-pane.winner .pane-title {
|
||
color: var(--green, #50fa7b);
|
||
}
|
||
.compare-pane.loser .pane-header {
|
||
opacity: 0.5;
|
||
}
|
||
.confetti-piece {
|
||
position: fixed;
|
||
pointer-events: none;
|
||
z-index: 1000000;
|
||
}
|
||
.compare-pane.expanded { grid-column: 1 / -1; }
|
||
.compare-pane .chat-history {
|
||
flex: 1 1 0;
|
||
min-height: 0;
|
||
overflow-y: auto !important;
|
||
overflow-x: hidden;
|
||
padding: 8px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.compare-pane .chat-history .msg {
|
||
flex-shrink: 0;
|
||
}
|
||
.compare-gen-image {
|
||
max-width: 100%;
|
||
max-height: 100%;
|
||
object-fit: contain;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
}
|
||
.compare-section {
|
||
margin-bottom: 14px;
|
||
}
|
||
.compare-section:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
.compare-section-label {
|
||
font-size: 9px;
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.6px;
|
||
opacity: 0.5;
|
||
margin-bottom: 5px;
|
||
font-weight: 600;
|
||
}
|
||
/* Active-type/mode readout next to "Type:"/"Mode:" — only needed on mobile
|
||
(where the tab/toggle text labels are hidden); hidden on desktop. */
|
||
.compare-type-current,
|
||
.compare-mode-current { display: none; }
|
||
/* Contextual one-liner under the mode toggles describing what you just
|
||
changed — empty until the first toggle, then a subtle hint. */
|
||
.compare-mode-hint {
|
||
font-size: 11px;
|
||
opacity: 0.55;
|
||
margin-top: 6px;
|
||
min-height: 0;
|
||
line-height: 1.3;
|
||
}
|
||
.compare-mode-hint:empty { display: none; }
|
||
.compare-type-tabs .compare-mode-tab > svg,
|
||
.compare-type-current > svg {
|
||
color: var(--accent, var(--red));
|
||
}
|
||
|
||
.compare-mode-tabs {
|
||
display: flex;
|
||
gap: 4px;
|
||
flex-wrap: wrap;
|
||
min-width: 0;
|
||
}
|
||
/* Type tabs match Mode toggles 1:1 (same flex column layout, same metrics) */
|
||
.compare-mode-tab {
|
||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||
width: 56px; height: 38px; flex: 1 1 0;
|
||
padding: 5px 4px 4px; border: 1px solid var(--border); border-radius: 6px;
|
||
cursor: pointer; user-select: none; transition: all 0.15s;
|
||
background: none; color: var(--fg); opacity: 0.35;
|
||
flex-shrink: 0; gap: 0;
|
||
font-family: inherit;
|
||
}
|
||
.compare-mode-tab > svg {
|
||
width: 13px; height: 13px; flex: 0 0 13px;
|
||
}
|
||
.compare-mode-tab:hover {
|
||
opacity: 0.7; background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
}
|
||
.compare-mode-tab.active {
|
||
opacity: 1; border-color: var(--fg);
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent);
|
||
}
|
||
.compare-sources-box {
|
||
display: flex; align-items: center; gap: 6px;
|
||
padding: 6px 10px; margin-bottom: 8px;
|
||
border-radius: 6px; font-size: 0.78em;
|
||
background: color-mix(in srgb, var(--red) 8%, transparent);
|
||
border: 1px solid color-mix(in srgb, var(--red) 20%, transparent);
|
||
color: color-mix(in srgb, var(--fg) 70%, transparent);
|
||
cursor: default;
|
||
}
|
||
.compare-sources-box .sources-label { font-weight: 600; }
|
||
/* Compact tool blocks inside compare panes */
|
||
.compare-pane .agent-thread-node {
|
||
margin: 4px 0; font-size: 0.85em;
|
||
}
|
||
.compare-pane .agent-thread-cmd {
|
||
max-height: 80px; overflow-y: auto;
|
||
}
|
||
.compare-pane .agent-tool-output pre {
|
||
max-height: 120px; overflow-y: auto;
|
||
}
|
||
.compare-vote-bar {
|
||
display: flex; justify-content: center; gap: 8px;
|
||
padding: 8px; border-top: 1px solid var(--border);
|
||
flex-shrink: 0; flex-wrap: wrap;
|
||
}
|
||
.compare-vote-bar.hidden { display: none; }
|
||
.compare-vote-btn {
|
||
padding: 6px 13px; border: 1px solid var(--border); border-radius: 6px;
|
||
background: var(--panel); color: var(--fg); cursor: pointer; font-size: 0.8em;
|
||
transition: all 0.15s; white-space: nowrap;
|
||
}
|
||
.compare-score-label {
|
||
position: relative;
|
||
top: -2px;
|
||
display: inline-block;
|
||
}
|
||
.compare-vote-btn:hover { border-color: var(--red); background: color-mix(in srgb, var(--red) 11%, transparent); }
|
||
.compare-vote-tie { opacity: 0.7; }
|
||
.compare-rematch-btn {
|
||
display: flex; align-items: center; gap: 6px; margin-left: 8px;
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 60%, var(--border));
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 14%, transparent);
|
||
color: var(--fg); opacity: 1; font-weight: 600;
|
||
}
|
||
.compare-rematch-btn:hover { border-color: var(--accent, var(--red)); background: color-mix(in srgb, var(--accent, var(--red)) 24%, transparent); }
|
||
/* Preview button accent in pane header */
|
||
.pane-preview-btn.active { color: var(--red); }
|
||
/* Full-pane iframe for HTML preview */
|
||
.compare-pane-iframe {
|
||
flex: 1;
|
||
width: 100%;
|
||
border: none;
|
||
border-radius: 0 0 8px 8px;
|
||
background: #fff;
|
||
}
|
||
/* ---- Add-pane "+" button in pane header (last pane only) ---- */
|
||
.pane-add-btn { display: none !important; font-size: 16px; font-weight: 600; }
|
||
.compare-pane:last-child .pane-add-btn { display: flex !important; }
|
||
/* Dropdown for adding a pane */
|
||
.add-pane-dropdown {
|
||
position: absolute;
|
||
right: 0;
|
||
z-index: 100;
|
||
background: var(--panel, var(--bg));
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
min-width: 220px;
|
||
box-shadow: 0 8px 24px rgba(0,0,0,0.3), 0 0 0 1px color-mix(in srgb, var(--fg) 5%, transparent);
|
||
padding: 6px;
|
||
backdrop-filter: blur(12px);
|
||
animation: dropdown-in 0.15s ease-out;
|
||
}
|
||
.add-pane-search {
|
||
width: 100%;
|
||
padding: 6px 8px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 4px;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
font-size: 0.85em;
|
||
box-sizing: border-box;
|
||
margin-bottom: 4px;
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 1;
|
||
}
|
||
/* Compare toggle buttons — icon + label stacked */
|
||
.compare-toggle-label {
|
||
display: block;
|
||
font-size: 9px;
|
||
line-height: 1;
|
||
margin-top: 2px;
|
||
font-weight: 500;
|
||
}
|
||
.compare-blind-toggle,
|
||
.compare-save-toggle,
|
||
.compare-dice-toggle,
|
||
.compare-parallel-toggle,
|
||
.compare-reset-toggle {
|
||
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
||
width: 56px; height: auto; flex: 1 1 0;
|
||
padding: 5px 4px 4px; border: 1px solid var(--border); border-radius: 6px;
|
||
cursor: pointer; user-select: none; transition: all 0.15s;
|
||
background: none; color: var(--fg); opacity: 0.35;
|
||
flex-shrink: 0; gap: 0;
|
||
}
|
||
.compare-blind-toggle:hover,
|
||
.compare-save-toggle:hover,
|
||
.compare-dice-toggle:hover,
|
||
.compare-parallel-toggle:hover,
|
||
.compare-reset-toggle:hover {
|
||
opacity: 0.7; background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
}
|
||
.compare-blind-toggle.active {
|
||
opacity: 1; color: var(--accent, var(--red)); border-color: var(--accent, var(--red));
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 10%, transparent);
|
||
}
|
||
.compare-blind-toggle.active > svg {
|
||
color: var(--accent, var(--red));
|
||
}
|
||
.compare-save-toggle.active {
|
||
opacity: 1; color: var(--color-save-green); border-color: var(--color-save-green);
|
||
background: color-mix(in srgb, var(--red) 10%, transparent);
|
||
}
|
||
.compare-dice-toggle.active {
|
||
opacity: 1; color: var(--red); border-color: var(--red);
|
||
background: color-mix(in srgb, var(--red) 10%, transparent);
|
||
}
|
||
.compare-parallel-toggle {
|
||
opacity: 1; color: #e0a050; border-color: #e0a050;
|
||
background: rgba(224, 160, 80, 0.1);
|
||
}
|
||
.compare-parallel-toggle.active {
|
||
color: var(--accent, var(--red)); border-color: var(--accent, var(--red));
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 10%, transparent);
|
||
}
|
||
@media (max-width: 520px) {
|
||
.compare-toggle-label { display: none; }
|
||
/* Tab text labels are hidden on mobile, so spell out the active type next
|
||
to "Type:" with its icon. */
|
||
.compare-type-current {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
margin-left: 5px;
|
||
font-weight: 600;
|
||
vertical-align: -3px;
|
||
}
|
||
.compare-type-current svg { width: 14px; height: 14px; }
|
||
/* Mode list — comma-separated, each name already coloured inline. */
|
||
.compare-mode-current {
|
||
display: inline;
|
||
margin-left: 5px;
|
||
font-weight: 600;
|
||
}
|
||
.compare-blind-toggle,
|
||
.compare-save-toggle,
|
||
.compare-dice-toggle,
|
||
.compare-parallel-toggle,
|
||
.compare-reset-toggle {
|
||
width: 32px; height: 32px; min-width: 32px; padding: 0;
|
||
}
|
||
/* The Group tab's seq/parallel toggle is a single full-width button (not
|
||
a row of compact icons like the Compare header), so keep its label and
|
||
make it a comfortable touch target with the text beside the icon. */
|
||
#group-mode-btn {
|
||
flex-direction: row !important;
|
||
width: auto !important;
|
||
height: auto !important;
|
||
min-height: 44px;
|
||
padding: 8px 14px !important;
|
||
gap: 8px !important;
|
||
font-size: 13px;
|
||
}
|
||
#group-mode-btn .compare-toggle-label {
|
||
display: inline !important;
|
||
font-size: 13px;
|
||
margin-top: 0;
|
||
}
|
||
#group-mode-btn svg { width: 18px; height: 18px; }
|
||
/* Compare header: hide labels + close button, show icons only */
|
||
#compare-shuffle-btn span {
|
||
display: none;
|
||
}
|
||
#compare-shuffle-btn,
|
||
#compare-check-btn,
|
||
#compare-add-btn {
|
||
padding: 3px 6px;
|
||
}
|
||
/* Save space so the header buttons fit on one row: tighter padding +
|
||
smaller labels (icons kept full size). (Score now lives in the vote bar.) */
|
||
.compare-header-bar button { padding: 3px 5px !important; }
|
||
.compare-header-bar #compare-check-btn > span,
|
||
.compare-header-bar #compare-add-btn > span {
|
||
font-size: 10px; margin-left: 2px;
|
||
}
|
||
/* Compare mobile: keep the close X visible — it's the only way out
|
||
now that the hamburger is hidden during compare mode. */
|
||
.compare-header-bar {
|
||
padding: 14px 8px 10px 8px !important;
|
||
min-height: 44px;
|
||
}
|
||
.compare-pane .pane-header {
|
||
align-items: stretch;
|
||
row-gap: 3px;
|
||
}
|
||
.compare-pane .pane-title-btn {
|
||
flex: 1 1 auto;
|
||
width: auto;
|
||
padding-right: 2px;
|
||
}
|
||
/* Compare is already visibly in chat mode; the Chat speech-bubble
|
||
badge adds a redundant second row on narrow screens. */
|
||
.compare-pane .pane-mode-chat { display: none; }
|
||
.compare-pane .pane-timer,
|
||
.compare-pane .pane-summary,
|
||
.compare-pane .pane-finish-badge,
|
||
.compare-pane .pane-mode-badge,
|
||
.compare-pane .pane-actions {
|
||
order: 1;
|
||
align-self: center;
|
||
}
|
||
.compare-pane .pane-finish-badge { top: 0; }
|
||
.compare-pane .pane-summary {
|
||
max-width: 110px;
|
||
}
|
||
.compare-pane .pane-mode-detail {
|
||
display: none;
|
||
}
|
||
.compare-grid[data-cols="4"] .compare-pane .pane-timer,
|
||
.compare-grid[data-cols="5"] .compare-pane .pane-timer,
|
||
.compare-grid[data-cols="6"] .compare-pane .pane-timer {
|
||
width: auto;
|
||
order: 1;
|
||
margin-top: 0;
|
||
padding-bottom: 0;
|
||
padding-left: 0;
|
||
}
|
||
.compare-pane .pane-actions {
|
||
margin-left: auto;
|
||
}
|
||
/* Mode tabs: icons only, centered */
|
||
.compare-mode-tab span { display: none; }
|
||
.compare-mode-tabs { justify-content: center; }
|
||
/* Header action buttons: hide text labels on Export / Shuffle /
|
||
Model on mobile so the close X fits on the right. Score keeps
|
||
its "Score" label because its icon (4-square grid) reads too
|
||
similar to Shuffle's icon without text. */
|
||
.compare-header-bar #compare-export-btn > span,
|
||
.compare-header-bar #compare-shuffle-btn > span {
|
||
display: none;
|
||
}
|
||
/* Override the desktop override: on mobile the model picker overlay
|
||
MUST cap its height to the viewport so the dropdown doesn't run
|
||
past the bottom of the screen. */
|
||
#compare-model-overlay .modal-content {
|
||
max-height: 85dvh !important;
|
||
max-height: 85vh !important;
|
||
overflow: hidden !important;
|
||
}
|
||
#compare-model-overlay .modal-body {
|
||
overflow: auto !important;
|
||
flex: 1 1 auto !important;
|
||
min-height: 0 !important;
|
||
}
|
||
}
|
||
/* Hide number input spinners */
|
||
input[type="number"]::-webkit-inner-spin-button,
|
||
input[type="number"]::-webkit-outer-spin-button {
|
||
-webkit-appearance: none; margin: 0;
|
||
}
|
||
|
||
/* ── Sensitive info censor ── */
|
||
.censored-item {
|
||
filter: blur(5px);
|
||
cursor: pointer;
|
||
transition: filter 0.2s;
|
||
border-radius: 2px;
|
||
padding: 0 2px;
|
||
background: rgba(255,100,100,0.08);
|
||
user-select: none;
|
||
}
|
||
.censored-item:hover { filter: blur(3px); background: rgba(255,100,100,0.15); }
|
||
.censored-item.revealed {
|
||
filter: none;
|
||
background: rgba(100,255,100,0.08);
|
||
user-select: auto;
|
||
cursor: text;
|
||
}
|
||
|
||
#settings-menu-list .list-item.active {
|
||
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
||
border-color: var(--accent);
|
||
}
|
||
|
||
/* ── Print / PDF Export ── */
|
||
@media print {
|
||
body { background: #fff !important; color: #000 !important; }
|
||
#sidebar, .sidebar, #icon-rail, .hamburger-btn, #sidebar-backdrop, .chat-input-bar, .input-bar-wrapper,
|
||
#welcome-screen, .chat-top-bar, .chat-meta-overlay, .msg-footer,
|
||
.modal, .toast, .overflow-wrapper, .mode-toggle, .incognito-btn,
|
||
button, .dropdown, .session-dropdown,
|
||
.agent-tool-spinner, .agent-thread-node.running { display: none !important; }
|
||
main.chat-container { width: 100% !important; margin: 0 !important; padding: 0 !important; max-height: none !important; overflow: visible !important; }
|
||
#chat-history { max-height: none !important; overflow: visible !important; height: auto !important; padding: 0 !important; }
|
||
.msg { break-inside: avoid; page-break-inside: avoid; border: none !important; box-shadow: none !important; }
|
||
.msg-ai { background: #f5f5f5 !important; color: #000 !important; }
|
||
.msg-user { background: #e8e8e8 !important; color: #000 !important; }
|
||
.msg .role { color: #333 !important; font-weight: bold; }
|
||
.msg .body { color: #000 !important; }
|
||
pre, code { background: #f0f0f0 !important; color: #000 !important; border: 1px solid #ccc !important; }
|
||
details { display: block !important; }
|
||
details[open] summary ~ * { display: block !important; }
|
||
details > summary { list-style: none; }
|
||
details > summary::before { content: "" !important; }
|
||
#chat-history::before { content: attr(data-print-title); display: block; font-size: 1.3em; font-weight: bold; margin-bottom: 1em; color: #000; }
|
||
a { color: #000 !important; text-decoration: underline; }
|
||
}
|
||
|
||
|
||
/* ── Components (from style.css) ── */
|
||
|
||
/* Self-hosted Fira Code font */
|
||
@font-face { font-family: 'Fira Code'; font-weight: 300; font-style: normal; font-display: swap; src: url('/static/fonts/FiraCode-Light.woff2') format('woff2'); }
|
||
@font-face { font-family: 'Fira Code'; font-weight: 400; font-style: normal; font-display: swap; src: url('/static/fonts/FiraCode-Regular.woff2') format('woff2'); }
|
||
@font-face { font-family: 'Fira Code'; font-weight: 600; font-style: normal; font-display: swap; src: url('/static/fonts/FiraCode-SemiBold.woff2') format('woff2'); }
|
||
|
||
/* Scrollbar styling */
|
||
|
||
/* Code block styling */
|
||
pre, code, .hljs {
|
||
font-size: 11px;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
/* WebKit (Chrome, Edge, Safari) */
|
||
/* Utility class for red text */
|
||
.red-text {
|
||
color: var(--red);
|
||
}
|
||
|
||
/* Internal chat links (search results, session references) */
|
||
a.chat-link {
|
||
color: var(--hl-function);
|
||
text-decoration: none;
|
||
border-bottom: 1px dotted var(--hl-function);
|
||
cursor: pointer;
|
||
}
|
||
a.chat-link:hover {
|
||
opacity: 0.8;
|
||
border-bottom-style: solid;
|
||
}
|
||
|
||
a.chat-link[href^="#email-"] {
|
||
display: inline;
|
||
padding: 1px 5px;
|
||
border: 1px solid color-mix(in srgb, var(--accent, var(--red)) 34%, transparent);
|
||
border-radius: 5px;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 8%, transparent);
|
||
color: var(--fg);
|
||
font-weight: 600;
|
||
border-bottom-style: solid;
|
||
}
|
||
a.chat-link[href^="#email-"]:hover {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 14%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 55%, transparent);
|
||
}
|
||
|
||
a.chat-link[href^="#notes-more-"],
|
||
a.chat-link[href^="#skills-more-"],
|
||
a.chat-link[href^="#memories-more-"],
|
||
a.chat-link[href^="#events-more-"],
|
||
a.chat-link[href^="#sessions-more-"] {
|
||
color: var(--muted);
|
||
border-bottom: 1px dotted color-mix(in srgb, var(--muted) 55%, transparent);
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
}
|
||
a.chat-link[href^="#notes-more-"]:hover,
|
||
a.chat-link[href^="#skills-more-"]:hover,
|
||
a.chat-link[href^="#memories-more-"]:hover,
|
||
a.chat-link[href^="#events-more-"]:hover,
|
||
a.chat-link[href^="#sessions-more-"]:hover {
|
||
color: var(--fg);
|
||
opacity: 1;
|
||
border-bottom-style: solid;
|
||
}
|
||
.more-list-expanded {
|
||
display: block;
|
||
max-height: 0;
|
||
overflow: hidden;
|
||
opacity: 0;
|
||
color: inherit;
|
||
font: inherit;
|
||
line-height: inherit;
|
||
transition: max-height 220ms ease, opacity 160ms ease;
|
||
}
|
||
.more-list-expanded.is-open {
|
||
opacity: 1;
|
||
}
|
||
.more-list-expanded-content {
|
||
color: inherit;
|
||
font: inherit;
|
||
line-height: inherit;
|
||
}
|
||
|
||
/* Session items */
|
||
.session-item { position: relative; }
|
||
.text-ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.session-menu-btn { padding: 0 2px !important; min-width: 20px; height: 20px; display: inline-flex !important; align-items: center; justify-content: center; background: none !important; border-color: transparent !important; }
|
||
.session-menu-btn:hover { background: none !important; border-color: transparent !important; }
|
||
@media (max-width: 768px) {
|
||
.session-menu-btn { display: none !important; }
|
||
.item-drag-handle { display: none !important; }
|
||
}
|
||
.session-menu-btn svg { transition: transform 0.2s ease; }
|
||
|
||
/* First-time swipe hint */
|
||
.swipe-hint {
|
||
position: absolute;
|
||
right: 8px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
font-size: 0.7rem;
|
||
color: var(--color-error, #f44);
|
||
opacity: 0.8;
|
||
transition: opacity 0.5s ease;
|
||
pointer-events: none;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
z-index: 2;
|
||
}
|
||
.swipe-hint-arrow {
|
||
animation: swipe-nudge 1s ease-in-out infinite;
|
||
}
|
||
@keyframes swipe-nudge {
|
||
0%, 100% { transform: translateX(0); }
|
||
50% { transform: translateX(-6px); }
|
||
}
|
||
|
||
/* Utility classes */
|
||
.muted { opacity: 0.5; }
|
||
.muted-sm { opacity: 0.35; font-size: 0.8em; }
|
||
.accent-link { color: var(--accent-primary, var(--color-accent)); cursor: pointer; font-size: 0.85em; }
|
||
.models-empty-state { text-align: center; padding: 12px 8px; line-height: 1.6; }
|
||
|
||
/* Provider logo inside favorite dot */
|
||
.provider-logo {
|
||
border: none !important;
|
||
background: none !important;
|
||
width: 14px !important; height: 14px !important;
|
||
display: inline-flex; align-items: center; justify-content: center;
|
||
transition: opacity 0.15s;
|
||
}
|
||
.provider-logo svg { width: 14px; height: 14px; display: block; }
|
||
.provider-logo:hover { opacity: 1 !important; transform: scale(1.2); }
|
||
|
||
/* Hide session menu button until hover — use width:0 so it doesn't steal space from text */
|
||
.list-item .hamburger { opacity: 0; width: 0; min-width: 0; overflow: hidden; padding: 0 !important; transition: opacity 0.15s, width 0.15s, padding 0.15s; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
|
||
.list-item:hover .hamburger { opacity: 1; width: 24px; min-width: 24px; padding: 0 4px !important; }
|
||
@media (max-width: 768px) {
|
||
.list-item .hamburger { opacity: 0.5; width: 28px; min-width: 28px; padding: 0 4px !important; }
|
||
.list-item .hamburger:active { opacity: 1; }
|
||
}
|
||
|
||
/* Hamburger menu button styling (overrides default button appearance) */
|
||
button.hamburger {
|
||
background: none;
|
||
border: none;
|
||
padding: 0;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* ============================================ */
|
||
/* HEADER SIZING FOR CHAT MESSAGES */
|
||
/* ============================================ */
|
||
/* Markdown in chat messages — colorful, scannable */
|
||
.msg h1, .msg h2, .msg h3, .msg h4, .msg h5, .msg h6 {
|
||
margin: 0.6em 0 0.3em 0;
|
||
line-height: 1.3;
|
||
border-bottom: none;
|
||
padding-bottom: 0;
|
||
}
|
||
|
||
.msg h1 {
|
||
font-size: 1.15em;
|
||
font-weight: 700;
|
||
color: var(--hl-keyword, #c678dd);
|
||
}
|
||
|
||
.msg h2 {
|
||
font-size: 1.1em;
|
||
font-weight: 600;
|
||
color: var(--hl-function, #5b8def);
|
||
}
|
||
|
||
.msg h3 {
|
||
font-size: 1.05em;
|
||
font-weight: 600;
|
||
color: var(--hl-string, #98c379);
|
||
}
|
||
|
||
.msg h4 {
|
||
font-size: 1.02em;
|
||
font-weight: 600;
|
||
color: var(--hl-builtin, #e5c07b);
|
||
}
|
||
|
||
.msg h5 {
|
||
font-size: 1em;
|
||
font-weight: 600;
|
||
color: var(--hl-variable, #61afef);
|
||
}
|
||
|
||
.msg h6 {
|
||
font-size: 0.95em;
|
||
font-weight: 600;
|
||
color: var(--hl-number, #d19a66);
|
||
}
|
||
|
||
/* Bold text — subtle accent color */
|
||
.msg strong, .msg b {
|
||
color: var(--hl-builtin, #e5c07b);
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* Italic — softer highlight */
|
||
.msg em, .msg i {
|
||
color: var(--hl-params, #abb2bf);
|
||
font-style: italic;
|
||
}
|
||
|
||
/* Bold + italic */
|
||
.msg strong em, .msg em strong,
|
||
.msg b i, .msg i b,
|
||
.msg b em, .msg em b,
|
||
.msg strong i, .msg i strong {
|
||
color: var(--hl-keyword, #c678dd);
|
||
}
|
||
|
||
/* Strikethrough */
|
||
.msg del {
|
||
color: color-mix(in srgb, var(--fg) 45%, transparent);
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
/* Inline code */
|
||
.msg code:not(pre code) {
|
||
color: var(--hl-string, #98c379);
|
||
background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
padding: 1px 5px;
|
||
border-radius: 4px;
|
||
font-size: 0.9em;
|
||
}
|
||
|
||
/* Blockquotes */
|
||
.msg blockquote {
|
||
border-left: 3px solid var(--hl-function, #5b8def);
|
||
padding: 4px 12px;
|
||
margin: 0.5em 0;
|
||
color: color-mix(in srgb, var(--fg) 75%, transparent);
|
||
background: var(--bg);
|
||
border-radius: 0 6px 6px 0;
|
||
}
|
||
.msg blockquote p { margin: 0.3em 0; }
|
||
|
||
/* Horizontal rules */
|
||
.msg hr {
|
||
border: none;
|
||
height: 1px;
|
||
background: linear-gradient(90deg, transparent, var(--border), transparent);
|
||
margin: 0.8em 0;
|
||
}
|
||
|
||
/* Lists */
|
||
.msg ul, .msg ol {
|
||
margin: 0.3em 0 0.3em 1.2em;
|
||
padding: 0;
|
||
}
|
||
.msg li {
|
||
margin: 0.15em 0;
|
||
}
|
||
.msg li::marker {
|
||
color: var(--hl-function, #5b8def);
|
||
}
|
||
|
||
/* Links */
|
||
.msg a {
|
||
color: var(--hl-function, #5b8def);
|
||
text-decoration: none;
|
||
border-bottom: 1px solid rgba(91, 141, 239, 0.3);
|
||
transition: border-color 0.15s;
|
||
}
|
||
.msg a:hover {
|
||
border-bottom-color: var(--hl-function, #5b8def);
|
||
}
|
||
.msg a.is-loading {
|
||
opacity: 0.65;
|
||
border-bottom-color: var(--accent, #bd93f9);
|
||
cursor: progress;
|
||
}
|
||
|
||
/* Tables */
|
||
.msg table {
|
||
border-collapse: collapse;
|
||
margin: 0.5em 0;
|
||
font-size: 0.9em;
|
||
display: block;
|
||
width: max-content;
|
||
min-width: 100%;
|
||
max-width: 100%;
|
||
overflow-x: auto;
|
||
-webkit-overflow-scrolling: touch;
|
||
table-layout: auto;
|
||
}
|
||
.msg th {
|
||
background: color-mix(in srgb, var(--fg) 7%, transparent);
|
||
color: var(--hl-keyword, #c678dd);
|
||
font-weight: 600;
|
||
padding: 6px 12px;
|
||
border: 1px solid var(--border);
|
||
text-align: left;
|
||
min-width: 9ch;
|
||
word-break: normal;
|
||
overflow-wrap: break-word;
|
||
}
|
||
.msg td {
|
||
padding: 5px 12px;
|
||
border: 1px solid var(--border);
|
||
min-width: 9ch;
|
||
word-break: normal;
|
||
overflow-wrap: break-word;
|
||
}
|
||
|
||
/* Agent UI Styling */
|
||
.agent-controls {
|
||
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||
border: 1px solid #dee2e6;
|
||
border-radius: 8px;
|
||
padding: 12px;
|
||
margin-bottom: 12px;
|
||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.agent-toggle label {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
cursor: pointer;
|
||
font-weight: 500;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
#workflow-selector {
|
||
margin-top: 8px;
|
||
}
|
||
|
||
#workflow-type {
|
||
width: 100%;
|
||
padding: 6px 12px;
|
||
border: 1px solid #ced4da;
|
||
border-radius: 4px;
|
||
background: white;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.agent-progress {
|
||
background: #ffebee;
|
||
border: 1px solid #ef9a9a;
|
||
border-radius: 6px;
|
||
padding: 12px;
|
||
margin: 8px 0;
|
||
text-align: center;
|
||
}
|
||
|
||
.agent-working {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 8px;
|
||
font-style: italic;
|
||
color: var(--red);
|
||
}
|
||
|
||
.loading-dots::after {
|
||
content: '...';
|
||
animation: dots 1.5s infinite;
|
||
}
|
||
|
||
@keyframes dots {
|
||
0%, 20% { opacity: 0; }
|
||
40% { opacity: 0.5; }
|
||
60%, 100% { opacity: 1; }
|
||
}
|
||
|
||
.workflow-info {
|
||
background: #f8f9fa;
|
||
border: 1px solid var(--red);
|
||
border-radius: 6px;
|
||
padding: 8px 12px;
|
||
margin: 4px 0;
|
||
font-size: 0.9em;
|
||
color: var(--red);
|
||
text-align: center;
|
||
}
|
||
|
||
/* Scrollbar uses --red from :root (set at top of file) */
|
||
|
||
/* Loading spinner */
|
||
@keyframes spin {
|
||
to { transform: rotate(360deg); }
|
||
}
|
||
.spinner {
|
||
width: 24px;
|
||
height: 24px;
|
||
margin: 8px auto;
|
||
border: 3px solid var(--border);
|
||
border-top-color: var(--red);
|
||
border-radius: 50%;
|
||
animation: spin 0.9s linear infinite;
|
||
}
|
||
|
||
/* Inline spinner for buttons */
|
||
.btn-spinner {
|
||
display: inline-block;
|
||
width: 12px;
|
||
height: 12px;
|
||
border: 2px solid transparent;
|
||
border-top-color: currentColor;
|
||
border-radius: 50%;
|
||
animation: spin 1s linear infinite;
|
||
margin-right: 6px;
|
||
}
|
||
|
||
/* Loading indicator for messages */
|
||
.loading-indicator {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 10px;
|
||
}
|
||
.loading-dots {
|
||
display: flex;
|
||
gap: 4px;
|
||
}
|
||
.loading-dot {
|
||
width: 6px;
|
||
height: 6px;
|
||
background-color: var(--fg);
|
||
border-radius: 50%;
|
||
opacity: 0.6;
|
||
}
|
||
.loading-dot:nth-child(1) {
|
||
animation: loading-bounce 1.4s infinite ease-in-out both;
|
||
}
|
||
.loading-dot:nth-child(2) {
|
||
animation: loading-bounce 1.4s infinite ease-in-out both;
|
||
animation-delay: -0.32s;
|
||
}
|
||
.loading-dot:nth-child(3) {
|
||
animation: loading-bounce 1.4s infinite ease-in-out both;
|
||
animation-delay: -0.64s;
|
||
}
|
||
@keyframes loading-bounce {
|
||
0%, 80%, 100% {
|
||
transform: scale(0);
|
||
}
|
||
40% {
|
||
transform: scale(1);
|
||
}
|
||
}
|
||
|
||
/* Hamburger menu button */
|
||
.hamburger {
|
||
display: inline-flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
width: 24px;
|
||
height: 18px !important;
|
||
background: none;
|
||
border: none;
|
||
padding: 0;
|
||
cursor: pointer;
|
||
}
|
||
.hamburger span {
|
||
display: block;
|
||
width: 100%;
|
||
height: 3px;
|
||
background: var(--fg);
|
||
border-radius: 2px;
|
||
}
|
||
|
||
/* Agent indicator */
|
||
#agent-indicator {
|
||
position: fixed;
|
||
top: 20px;
|
||
right: 20px;
|
||
background: var(--sidebar-bg, var(--panel));
|
||
color: var(--fg);
|
||
border: 1px solid var(--border);
|
||
padding: 6px 12px;
|
||
border-radius: 6px;
|
||
font-size: 12px;
|
||
display: none;
|
||
z-index: 100;
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
}
|
||
#agent-indicator.active {
|
||
display: block;
|
||
border-color: var(--color-agent-active);
|
||
box-shadow: 0 0 10px rgba(0, 255, 0, 0.3);
|
||
}
|
||
#agent-indicator:hover {
|
||
border-color: var(--color-agent-active);
|
||
background: var(--panel);
|
||
}
|
||
|
||
/* Preset buttons */
|
||
.preset-btn {
|
||
height: 27.2px;
|
||
padding: 0 8.5px;
|
||
margin-left: 4px;
|
||
border: 1px solid var(--red);
|
||
border-radius: 4px;
|
||
background: var(--sidebar-bg, var(--panel));
|
||
color: var(--fg);
|
||
font-family: inherit;
|
||
font-size: 10.2px;
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.preset-btn:hover {
|
||
background: var(--panel);
|
||
border-color: var(--fg);
|
||
}
|
||
|
||
.preset-btn.active {
|
||
background: var(--panel);
|
||
border-color: var(--red);
|
||
box-shadow: 0 0 0 1px var(--red), 0 0 8px color-mix(in srgb, var(--red) 30%, transparent);
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* Custom preset modal — inherits from .modal base class */
|
||
|
||
/* Unified chat input area */
|
||
.chat-input-area {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
background: var(--panel);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 12px;
|
||
margin-top: 12px;
|
||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.chat-controls-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.chat-controls-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.chat-controls-right {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
|
||
.control-group {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
}
|
||
|
||
.control-label {
|
||
font-size: 11px;
|
||
color: var(--fg);
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.toggle-switch {
|
||
position: relative;
|
||
display: inline-block;
|
||
width: 30px;
|
||
height: 16px;
|
||
}
|
||
|
||
.toggle-switch input {
|
||
opacity: 0;
|
||
width: 0;
|
||
height: 0;
|
||
}
|
||
|
||
.toggle-slider {
|
||
position: absolute;
|
||
cursor: pointer;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: color-mix(in srgb, var(--fg) 15%, transparent);
|
||
border-radius: 8px;
|
||
transition: background 0.08s;
|
||
}
|
||
|
||
.toggle-slider:before {
|
||
position: absolute;
|
||
content: "";
|
||
height: 12px;
|
||
width: 12px;
|
||
left: 4px;
|
||
top: 2px;
|
||
background-color: var(--panel);
|
||
border-radius: 50%;
|
||
transition: transform 0.08s;
|
||
box-shadow: 0 1px 2px rgba(0,0,0,0.25);
|
||
}
|
||
|
||
.toggle-switch input:checked + .toggle-slider {
|
||
background-color: var(--toggle-active, var(--red));
|
||
}
|
||
|
||
.toggle-switch input:checked + .toggle-slider:before {
|
||
transform: translateX(14px);
|
||
}
|
||
|
||
.preset-buttons-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.chat-input-form {
|
||
display: flex;
|
||
gap: 8px;
|
||
align-items: flex-end;
|
||
}
|
||
|
||
#message {
|
||
flex: 1;
|
||
min-height: 34px;
|
||
max-height: 120px;
|
||
resize: none;
|
||
font-size: 13px !important;
|
||
overflow-y: auto !important;
|
||
line-height: 1.4 !important;
|
||
font-family: inherit !important;
|
||
}
|
||
|
||
.action-button {
|
||
width: 34px;
|
||
height: 34px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0;
|
||
margin: 0;
|
||
background: none;
|
||
border: 1px solid var(--border);
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
color: var(--fg);
|
||
transition: all 0.2s ease;
|
||
}
|
||
|
||
.action-button:hover {
|
||
background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
border-color: var(--fg);
|
||
}
|
||
|
||
.action-button:disabled {
|
||
opacity: 0.5;
|
||
cursor: not-allowed;
|
||
}
|
||
|
||
.action-button.recording {
|
||
background: var(--color-recording);
|
||
border-color: var(--color-recording);
|
||
animation: pulse 1.5s infinite;
|
||
}
|
||
|
||
@keyframes pulse {
|
||
0% { opacity: 1; }
|
||
50% { opacity: 0.7; }
|
||
100% { opacity: 1; }
|
||
}
|
||
|
||
#stop-icon {
|
||
display: none;
|
||
width: 14px;
|
||
height: 14px;
|
||
background: var(--color-recording);
|
||
border-radius: 2px;
|
||
}
|
||
|
||
/* Attachment strip — centered + max-width to match the chat-input-bar below,
|
||
otherwise the chip floats flush-left while the input is centered (visible on
|
||
desktop where the chat area is wider than 800px). */
|
||
.attach-strip {
|
||
display: flex;
|
||
gap: 6px;
|
||
flex-wrap: wrap;
|
||
padding: 2px 8px;
|
||
max-width: 800px;
|
||
width: 100%;
|
||
margin-left: auto;
|
||
margin-right: auto;
|
||
box-sizing: border-box;
|
||
}
|
||
.attach-strip:empty { display: none; }
|
||
|
||
/* Upload-in-progress feedback: the message bubble shows immediately, so while
|
||
the files are still uploading we put a whirlpool ON each attachment chip and
|
||
dim the chip's content — making it obvious that file is being sent, not stuck. */
|
||
.attach-strip.attach-uploading .thumb {
|
||
position: relative;
|
||
pointer-events: none;
|
||
}
|
||
.attach-strip.attach-uploading .thumb > :not(.thumb-upload-spinner) {
|
||
opacity: 0.4;
|
||
}
|
||
.thumb-upload-spinner {
|
||
position: absolute;
|
||
inset: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
pointer-events: none;
|
||
z-index: 3;
|
||
}
|
||
|
||
.thumb {
|
||
border: 1px solid var(--border);
|
||
background: color-mix(in srgb, var(--fg) 11%, transparent);
|
||
padding: 3px 6px;
|
||
font-size: 12px;
|
||
display: flex;
|
||
gap: 6px;
|
||
align-items: center;
|
||
border-radius: 4px;
|
||
transition: all 0.2s ease;
|
||
max-width: 180px;
|
||
}
|
||
.thumb-img {
|
||
max-width: 60px;
|
||
max-height: 40px;
|
||
border-radius: 3px;
|
||
object-fit: cover;
|
||
}
|
||
.attach-image-preview {
|
||
margin: 4px 0;
|
||
}
|
||
.attach-image-preview img {
|
||
box-shadow: 0 1px 4px rgba(0,0,0,0.2);
|
||
/* Same border as the chat bubbles. */
|
||
border: 1px solid var(--bubble-border, var(--border));
|
||
}
|
||
/* Image chips: image fills the chip, X overlays as a corner accent badge.
|
||
Same on desktop and mobile — doc/text chips keep the beside-X layout. */
|
||
.thumb.thumb-image {
|
||
position: relative;
|
||
padding: 0;
|
||
}
|
||
.thumb.thumb-image .thumb-img {
|
||
max-height: 56px;
|
||
display: block;
|
||
}
|
||
@media (max-width: 768px) {
|
||
.thumb.thumb-image .thumb-img {
|
||
cursor: pointer;
|
||
touch-action: manipulation;
|
||
}
|
||
}
|
||
.thumb.thumb-image button {
|
||
position: absolute;
|
||
/* Sit on the top-right corner edge as an accent badge. */
|
||
top: -7px;
|
||
right: -7px;
|
||
width: 24px;
|
||
height: 24px;
|
||
min-width: 0;
|
||
padding: 0;
|
||
border: 2px solid var(--bg);
|
||
border-radius: 50%;
|
||
background: var(--accent-primary, var(--red));
|
||
color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 15px;
|
||
line-height: 1;
|
||
z-index: 3;
|
||
transition: transform 0.12s ease, filter 0.12s ease, box-shadow 0.12s ease;
|
||
}
|
||
.thumb.thumb-image button:hover {
|
||
transform: scale(1.12);
|
||
filter: brightness(1.12);
|
||
box-shadow: 0 2px 8px rgba(0,0,0,0.25);
|
||
}
|
||
.thumb.thumb-image button:active {
|
||
transform: scale(0.96);
|
||
}
|
||
|
||
.attach-crop-overlay {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: var(--attach-crop-z, 100001);
|
||
background: rgba(0, 0, 0, 0.72);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 14px;
|
||
box-sizing: border-box;
|
||
}
|
||
.attach-crop-panel {
|
||
width: min(94vw, 520px);
|
||
max-height: min(86vh, 720px);
|
||
background: var(--panel, #111);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
box-shadow: 0 18px 50px rgba(0,0,0,0.45);
|
||
overflow: hidden;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
.attach-crop-stage {
|
||
position: relative;
|
||
min-height: 280px;
|
||
height: min(66vh, 560px);
|
||
background: #050505;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
touch-action: none;
|
||
}
|
||
.attach-crop-img {
|
||
max-width: 100%;
|
||
max-height: 100%;
|
||
object-fit: contain;
|
||
user-select: none;
|
||
pointer-events: none;
|
||
}
|
||
.attach-crop-box {
|
||
position: absolute;
|
||
border: 2px solid var(--accent, var(--red));
|
||
box-shadow: 0 0 0 9999px rgba(0,0,0,0.42);
|
||
cursor: move;
|
||
touch-action: none;
|
||
box-sizing: border-box;
|
||
}
|
||
.attach-crop-box::before,
|
||
.attach-crop-box::after {
|
||
content: '';
|
||
position: absolute;
|
||
inset: 33.333% 0 auto;
|
||
border-top: 1px solid rgba(255,255,255,0.38);
|
||
}
|
||
.attach-crop-box::after {
|
||
inset: 66.666% 0 auto;
|
||
}
|
||
.attach-crop-handle {
|
||
position: absolute;
|
||
right: -9px;
|
||
bottom: -9px;
|
||
width: 20px;
|
||
height: 20px;
|
||
border-radius: 50%;
|
||
background: var(--accent, var(--red));
|
||
border: 2px solid var(--bg);
|
||
box-sizing: border-box;
|
||
cursor: nwse-resize;
|
||
}
|
||
.attach-crop-actions {
|
||
display: flex;
|
||
gap: 8px;
|
||
padding: 10px;
|
||
background: color-mix(in srgb, var(--bg) 78%, transparent);
|
||
}
|
||
.attach-crop-btn {
|
||
flex: 1;
|
||
height: 34px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 5px;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
font: inherit;
|
||
font-size: 12px;
|
||
}
|
||
.attach-crop-primary {
|
||
background: var(--accent, var(--red));
|
||
color: #fff;
|
||
border-color: var(--accent, var(--red));
|
||
}
|
||
@media (max-width: 768px) {
|
||
/* Collapsed "N files" badge: use the same corner-X accent badge as image thumbs. */
|
||
.thumb-collapsed { position: relative; }
|
||
.thumb-collapsed .thumb-collapsed-x {
|
||
position: absolute;
|
||
top: -7px;
|
||
right: -7px;
|
||
width: 24px;
|
||
height: 24px;
|
||
min-width: 0;
|
||
padding: 0;
|
||
border: 2px solid var(--bg);
|
||
border-radius: 50%;
|
||
background: var(--accent-primary, var(--red));
|
||
color: #fff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 15px;
|
||
line-height: 1;
|
||
z-index: 3;
|
||
opacity: 1;
|
||
}
|
||
/* Bigger remove-X tap target for non-image (doc/text) chips on mobile too. */
|
||
.thumb button {
|
||
height: 28px;
|
||
min-width: 28px;
|
||
font-size: 15px;
|
||
}
|
||
}
|
||
.thumb span {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.thumb:hover {
|
||
background: color-mix(in srgb, var(--fg) 16%, transparent);
|
||
border-color: var(--fg);
|
||
}
|
||
|
||
.thumb button {
|
||
height: 24px;
|
||
padding: 0 5px;
|
||
font-size: 0.95em;
|
||
border-radius: 4px;
|
||
color: var(--accent-primary, var(--red));
|
||
}
|
||
|
||
.thumb-collapsed {
|
||
cursor: pointer;
|
||
color: var(--red);
|
||
border-color: var(--red);
|
||
background: color-mix(in srgb, var(--red) 10%, transparent);
|
||
font-weight: 600;
|
||
gap: 8px;
|
||
border-radius: 999px; /* pill — rounder than the square file chips */
|
||
padding-left: 12px;
|
||
}
|
||
.thumb-collapsed:hover {
|
||
background: color-mix(in srgb, var(--red) 20%, transparent);
|
||
}
|
||
.thumb-collapsed-label { white-space: nowrap; }
|
||
.thumb-collapsed-x {
|
||
height: 24px; padding: 0 7px; font-size: 13px; border-radius: 4px;
|
||
color: var(--accent-primary, var(--red));
|
||
background: none; border: none; cursor: pointer; opacity: 0.6;
|
||
}
|
||
.thumb-collapsed-x:hover { opacity: 1; }
|
||
|
||
/* Recording indicator */
|
||
#recording-indicator {
|
||
position: fixed;
|
||
top: 10px;
|
||
left: 0;
|
||
right: 0;
|
||
background: rgba(0, 0, 0, 0.8);
|
||
backdrop-filter: blur(10px);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 12px;
|
||
margin: 10px;
|
||
z-index: 1000;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
||
}
|
||
|
||
#recording-indicator.hidden {
|
||
display: none !important;
|
||
}
|
||
|
||
.recording-content {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12px;
|
||
color: white;
|
||
}
|
||
|
||
.recording-icon {
|
||
color: var(--color-recording);
|
||
font-size: 20px;
|
||
animation: pulse 1.5s infinite;
|
||
}
|
||
|
||
.recording-text {
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.stop-recording-btn {
|
||
background: var(--color-recording);
|
||
color: white;
|
||
border: none;
|
||
border-radius: 6px;
|
||
padding: 6px 12px;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: background 0.2s ease;
|
||
}
|
||
|
||
.stop-recording-btn:hover {
|
||
background: var(--color-recording-hover);
|
||
}
|
||
|
||
#recording-indicator.error {
|
||
background: rgba(173, 26, 26, 0.9);
|
||
}
|
||
|
||
.recording-error {
|
||
color: var(--color-recording);
|
||
font-size: 14px;
|
||
margin-top: 4px;
|
||
}
|
||
|
||
/* Mermaid diagram containers */
|
||
.mermaid-container {
|
||
margin: 12px 0;
|
||
padding: 16px;
|
||
background: color-mix(in srgb, var(--bg) 95%, var(--fg));
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
overflow-x: auto;
|
||
text-align: center;
|
||
}
|
||
.mermaid-container svg { max-width: 100%; height: auto; }
|
||
|
||
/* KaTeX math overrides */
|
||
.katex-display { margin: 0.8em 0; overflow-x: auto; overflow-y: hidden; }
|
||
.katex { font-size: 1.1em; }
|
||
|
||
/* Hide thinking sections globally via settings toggle */
|
||
body.hide-thinking .thinking-section { display: none !important; }
|
||
|
||
/* Widen chat area via settings toggle */
|
||
body.fullwidth-chat .chat-history {
|
||
padding-left: 0 !important;
|
||
padding-right: 12px !important;
|
||
}
|
||
|
||
/* Thinking process styles — colors follow theme accent */
|
||
.msg .body .stream-content {
|
||
width: 100%;
|
||
}
|
||
.thinking-section {
|
||
margin: 12px 0;
|
||
width: 100%;
|
||
max-width: 100%;
|
||
box-sizing: border-box;
|
||
border: 1px solid color-mix(in srgb, var(--red) 30%, transparent);
|
||
border-radius: 8px;
|
||
background: color-mix(in srgb, var(--red) 5%, transparent);
|
||
overflow: hidden;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
.thinking-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 12px;
|
||
padding: 6px 12px;
|
||
cursor: pointer;
|
||
user-select: none;
|
||
background: color-mix(in srgb, var(--red) 8%, transparent);
|
||
border-bottom: 1px solid color-mix(in srgb, var(--red) 20%, transparent);
|
||
transition: background 0.2s ease;
|
||
}
|
||
|
||
.thinking-header > .token-new {
|
||
display: none;
|
||
}
|
||
|
||
.thinking-header > div:last-child {
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.thinking-header:hover {
|
||
background: color-mix(in srgb, var(--red) 12%, transparent);
|
||
}
|
||
|
||
.thinking-header-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
font-size: 0.9em;
|
||
color: var(--red);
|
||
font-weight: 500;
|
||
overflow: hidden;
|
||
min-width: 0;
|
||
}
|
||
.thinking-header-left span {
|
||
display: block;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
transition: opacity 0.2s ease;
|
||
}
|
||
|
||
.thinking-icon {
|
||
font-size: 1.1em;
|
||
}
|
||
|
||
.thinking-toggle {
|
||
font-size: 0.9em;
|
||
color: var(--red);
|
||
transition: transform 0.3s ease;
|
||
}
|
||
.thinking-toggle::after {
|
||
content: '\25BC'; /* ▼ */
|
||
}
|
||
|
||
.thinking-toggle.expanded {
|
||
transform: rotate(180deg);
|
||
}
|
||
|
||
.thinking-content {
|
||
max-height: 0;
|
||
overflow: hidden;
|
||
transition: max-height 0.3s ease, padding 0.3s ease;
|
||
padding: 0 12px;
|
||
}
|
||
|
||
.thinking-content.expanded {
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
padding: 12px;
|
||
}
|
||
|
||
.thinking-content-inner {
|
||
font-size: 0.85em;
|
||
color: var(--fg);
|
||
opacity: 0.9;
|
||
line-height: 1.5;
|
||
}
|
||
.live-reply-content {
|
||
animation: fadeSlideIn 0.3s ease-out;
|
||
}
|
||
@keyframes fadeSlideIn {
|
||
from { opacity: 0; transform: translateY(4px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
|
||
/* Thinking indicator animation */
|
||
.thinking-indicator {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
color: var(--red);
|
||
font-style: italic;
|
||
padding: 8px 0;
|
||
}
|
||
|
||
.thinking-dots::after {
|
||
content: '...';
|
||
animation: thinking-dots 1.5s infinite;
|
||
display: inline-block;
|
||
width: 20px;
|
||
text-align: left;
|
||
}
|
||
|
||
@keyframes thinking-dots {
|
||
0%, 20% { content: '.'; }
|
||
40% { content: '..'; }
|
||
60%, 100% { content: '...'; }
|
||
}
|
||
|
||
.thinking-complete {
|
||
color: var(--red);
|
||
font-size: 0.9em;
|
||
padding: 4px 0;
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.research-context-continue-hint {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
margin: 5px 2px 0;
|
||
color: var(--fg-muted, var(--fg));
|
||
font-size: 10px;
|
||
opacity: 0.55;
|
||
}
|
||
.research-context-continue-hint svg {
|
||
flex: 0 0 auto;
|
||
opacity: 0.8;
|
||
}
|
||
|
||
/* ── Sources section — collapsible source citations ── */
|
||
.sources-section {
|
||
margin: 8px 0 12px;
|
||
border: 1px solid color-mix(in srgb, var(--red) 30%, transparent);
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
transition: all 0.3s ease;
|
||
}
|
||
.sources-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 8px 12px;
|
||
cursor: pointer;
|
||
background: color-mix(in srgb, var(--red) 8%, transparent);
|
||
border-bottom: 1px solid color-mix(in srgb, var(--red) 20%, transparent);
|
||
transition: background 0.2s ease;
|
||
user-select: none;
|
||
}
|
||
.sources-header:hover {
|
||
background: color-mix(in srgb, var(--red) 12%, transparent);
|
||
}
|
||
.sources-header-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
font-size: 0.85em;
|
||
font-weight: 500;
|
||
color: var(--red);
|
||
}
|
||
.sources-header-left svg {
|
||
width: 14px;
|
||
height: 14px;
|
||
flex-shrink: 0;
|
||
opacity: 0.7;
|
||
}
|
||
.sources-toggle {
|
||
font-size: 0.8em;
|
||
color: var(--red);
|
||
opacity: 0.7;
|
||
transition: none;
|
||
}
|
||
.sources-toggle::after {
|
||
content: '\25B6'; /* ▶ right arrow */
|
||
}
|
||
.sources-toggle[data-arrow="down"]::after {
|
||
content: '\25BC'; /* ▼ down arrow */
|
||
}
|
||
.sources-content {
|
||
max-height: 0;
|
||
overflow: hidden;
|
||
transition: max-height 0.3s ease, padding 0.3s ease;
|
||
padding: 0 10px;
|
||
}
|
||
.sources-content.expanded {
|
||
max-height: 3000px;
|
||
padding: 8px 10px;
|
||
}
|
||
.sources-content-inner {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
.source-link {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 5px 8px;
|
||
border-radius: 6px;
|
||
background: color-mix(in srgb, var(--fg) 4%, transparent);
|
||
text-decoration: none;
|
||
color: var(--fg);
|
||
transition: background 0.15s ease;
|
||
}
|
||
.source-link:hover {
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent);
|
||
}
|
||
.source-num {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 20px;
|
||
height: 20px;
|
||
border-radius: 50%;
|
||
background: color-mix(in srgb, var(--fg) 15%, transparent);
|
||
color: var(--fg);
|
||
font-size: 0.7em;
|
||
font-weight: 600;
|
||
flex-shrink: 0;
|
||
}
|
||
.source-title {
|
||
flex: 1;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
font-size: 0.82em;
|
||
}
|
||
.source-domain {
|
||
font-size: 0.72em;
|
||
opacity: 0.45;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.ai-spinner {
|
||
color: var(--red);
|
||
}
|
||
/* Nudge the Tidy button 2px left. */
|
||
#memory-tidy-btn { position: relative; left: -2px; }
|
||
/* Tidy button's whirlpool nudge — sits 1px lower so it visually centers on
|
||
the Tidy label baseline. */
|
||
#memory-tidy-btn .ai-spinner-whirlpool,
|
||
#memory-tidy-btn .spinner-whirlpool {
|
||
position: relative;
|
||
top: 1px;
|
||
}
|
||
.list-item.stream-complete {
|
||
animation: none;
|
||
}
|
||
.session-run-state {
|
||
flex: 0 0 auto;
|
||
margin-left: 5px;
|
||
font-size: 10px;
|
||
line-height: 1;
|
||
color: var(--fg-dim, #888);
|
||
opacity: 0.9;
|
||
}
|
||
.session-run-state.is-working {
|
||
color: var(--accent, var(--red));
|
||
}
|
||
.session-run-state .session-run-whirlpool {
|
||
width: 12px !important;
|
||
height: 12px !important;
|
||
margin: 0 !important;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
}
|
||
.session-run-state .session-run-whirlpool .ai-spinner-whirlpool {
|
||
display: inline-flex;
|
||
width: 12px;
|
||
height: 12px;
|
||
}
|
||
.session-run-state.is-done {
|
||
color: var(--color-success, #4caf50);
|
||
font-weight: 600;
|
||
}
|
||
.cookbook-notif-active svg { opacity: 1 !important; }
|
||
|
||
/* Rail notification dot — pulsing indicator on icon-rail buttons */
|
||
.icon-rail-btn.rail-notify {
|
||
opacity: 1 !important;
|
||
position: relative;
|
||
}
|
||
.icon-rail-btn.rail-notify::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 5px;
|
||
right: 4px;
|
||
width: 6px;
|
||
height: 6px;
|
||
border-radius: 50%;
|
||
background: var(--accent, var(--red));
|
||
animation: rail-notif-pulse 2s ease-in-out infinite;
|
||
z-index: 1;
|
||
}
|
||
.icon-rail-btn.rail-notify.rail-notify-success::before {
|
||
background: var(--color-success, #4caf50);
|
||
}
|
||
@keyframes rail-notif-pulse {
|
||
0%, 100% { opacity: 1; transform: scale(1); }
|
||
50% { opacity: 0.4; transform: scale(0.8); }
|
||
}
|
||
@keyframes stream-complete-pulse {
|
||
0%, 100% { box-shadow: none; }
|
||
50% { box-shadow: inset 0 0 0 1.5px var(--accent); }
|
||
}
|
||
|
||
/* ===== SLASH COMMAND RESPONSES ===== */
|
||
.msg.msg-system {
|
||
padding: 6px 12px; margin: 4px auto 4px 8px;
|
||
max-width: 85%; background: none; border-left: 2px solid var(--border);
|
||
}
|
||
.msg.msg-system .body { padding: 0; }
|
||
.msg.msg-system pre { margin: 4px 0; white-space: pre-wrap; font-size: 0.85em; }
|
||
.dropdown-divider {
|
||
height: 1px;
|
||
margin: 3px 6px;
|
||
background: color-mix(in srgb, var(--border) 60%, transparent);
|
||
}
|
||
.msg.stream-done-toast {
|
||
cursor: pointer;
|
||
border-left-color: var(--accent, var(--border));
|
||
border-radius: 6px;
|
||
background: color-mix(in srgb, var(--accent) 6%, transparent);
|
||
transition: background 0.15s;
|
||
}
|
||
.msg.stream-done-toast:hover {
|
||
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
||
}
|
||
.msg.stream-done-toast .body {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.stream-done-indicator {
|
||
font-family: monospace;
|
||
font-size: 1.1em;
|
||
line-height: 1;
|
||
color: var(--accent);
|
||
flex-shrink: 0;
|
||
animation: bar-pulse 1.2s ease-in-out infinite;
|
||
}
|
||
@keyframes bar-pulse {
|
||
0%, 100% { opacity: 0.4; }
|
||
50% { opacity: 1; }
|
||
}
|
||
|
||
/* ===== AGENT MULTI-BUBBLE ===== */
|
||
.msg.msg-tool {
|
||
display: none; /* legacy — hidden, replaced by agent-thread */
|
||
}
|
||
.msg.msg-continuation {
|
||
margin-top: 2px;
|
||
}
|
||
|
||
/* ===== AGENT THREAD TIMELINE ===== */
|
||
.agent-thread {
|
||
position: relative;
|
||
margin: 2px 0 2px 28px;
|
||
padding: 4px 0 4px 22px;
|
||
max-width: calc(85% - 20px);
|
||
box-sizing: border-box;
|
||
}
|
||
.agent-thread::before {
|
||
content: '';
|
||
position: absolute;
|
||
left: 5px;
|
||
top: 14px;
|
||
bottom: 14px;
|
||
width: 2px;
|
||
background: color-mix(in srgb, var(--red) 18%, transparent);
|
||
border-radius: 1px;
|
||
}
|
||
/* Extend line to connect to chat bubble above/below */
|
||
.agent-thread.has-top::before {
|
||
top: -6.5px;
|
||
}
|
||
.agent-thread.has-bottom::before {
|
||
bottom: -5px;
|
||
}
|
||
.agent-thread.has-ask-user-bottom::before {
|
||
bottom: -12px;
|
||
}
|
||
/* Terminating dot at bottom when no bubble below and last node is expanded */
|
||
.agent-thread:not(.has-bottom) .agent-thread-node.open:last-child::after {
|
||
content: '';
|
||
position: absolute;
|
||
/* Centre the 6px dot on the rail: the rail sits at left:5px + 2px wide,
|
||
so its centre is 6px from the thread's left edge and the dot's left
|
||
edge belongs at 3px — i.e. 3px - padding-left. Keep this in step with
|
||
.agent-thread-dot and with the mobile padding override below. */
|
||
left: -19px;
|
||
bottom: 5px;
|
||
width: 6px;
|
||
height: 6px;
|
||
border-radius: 50%;
|
||
background: var(--red);
|
||
box-shadow: 0 0 4px 1px color-mix(in srgb, var(--red) 55%, transparent),
|
||
0 0 0 3px color-mix(in srgb, var(--red) 18%, transparent);
|
||
}
|
||
|
||
/* Synapse pulse — a bright dot traveling down the line */
|
||
.agent-thread::after {
|
||
content: '';
|
||
position: absolute;
|
||
left: 4px;
|
||
width: 4px;
|
||
height: 4px;
|
||
border-radius: 50%;
|
||
background: var(--red);
|
||
box-shadow: 0 0 3px 1px color-mix(in srgb, var(--red) 50%, transparent);
|
||
pointer-events: none;
|
||
top: 0%;
|
||
opacity: 0;
|
||
}
|
||
.agent-thread.streaming::after {
|
||
animation: synapse-capped-short 0.8s ease-in-out infinite;
|
||
}
|
||
.agent-thread.streaming.has-top::after {
|
||
animation: synapse-capped 0.8s ease-in-out infinite;
|
||
}
|
||
.agent-thread.streaming.has-bottom::after {
|
||
animation: synapse-travel-short 0.8s ease-in-out infinite;
|
||
}
|
||
.agent-thread.streaming.has-top.has-bottom::after {
|
||
animation: synapse-travel 0.8s ease-in-out infinite;
|
||
}
|
||
@keyframes synapse-travel {
|
||
0% { top: 0%; opacity: 0; }
|
||
5% { opacity: 0.5; }
|
||
85% { opacity: 0.35; }
|
||
100% { top: 100%; opacity: 0; }
|
||
}
|
||
@keyframes synapse-capped {
|
||
0% { top: 0%; opacity: 0; }
|
||
5% { opacity: 0.5; }
|
||
70% { opacity: 0.35; top: calc(100% - 20px); }
|
||
100% { opacity: 0; top: calc(100% - 20px); }
|
||
}
|
||
@keyframes synapse-travel-short {
|
||
0% { top: 14px; opacity: 0; }
|
||
5% { opacity: 0.5; }
|
||
85% { opacity: 0.35; }
|
||
100% { top: 100%; opacity: 0; }
|
||
}
|
||
@keyframes synapse-capped-short {
|
||
0% { top: 14px; opacity: 0; }
|
||
5% { opacity: 0.5; }
|
||
70% { opacity: 0.35; top: calc(100% - 20px); }
|
||
100% { opacity: 0; top: calc(100% - 20px); }
|
||
}
|
||
.agent-thread-node {
|
||
position: relative;
|
||
padding: 5px 0;
|
||
}
|
||
.agent-thread-node + .agent-thread-node {
|
||
margin-top: 2px;
|
||
}
|
||
/* Supervisor ladder cards — same chrome as tool cards but tinted so the
|
||
user can tell at a glance "this is the agent recovering" vs "this is
|
||
the agent doing work". Stop rung gets the red accent. */
|
||
.agent-thread-node.supervisor-step .agent-thread-tool {
|
||
color: color-mix(in srgb, var(--accent, #c08a3e) 80%, var(--fg));
|
||
font-style: italic;
|
||
}
|
||
.agent-thread-node.supervisor-step .agent-thread-dot {
|
||
background: color-mix(in srgb, var(--accent, #c08a3e) 60%, transparent);
|
||
}
|
||
.agent-thread-node.supervisor-step[data-rung="stop"] .agent-thread-tool {
|
||
color: var(--red, #d65a5a);
|
||
}
|
||
.agent-thread-node.supervisor-step[data-rung="stop"] .agent-thread-dot {
|
||
background: color-mix(in srgb, var(--red, #d65a5a) 60%, transparent);
|
||
}
|
||
.agent-thread-dot {
|
||
position: absolute;
|
||
left: -20px;
|
||
top: 10px;
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
background: var(--red);
|
||
border: 2px solid var(--bg);
|
||
z-index: 1;
|
||
}
|
||
.agent-thread-node.running .agent-thread-dot {
|
||
background: var(--red);
|
||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--red) 25%, transparent);
|
||
animation: thread-pulse 1.5s ease-in-out infinite;
|
||
top: 10px;
|
||
}
|
||
@keyframes thread-pulse {
|
||
0%, 100% { box-shadow: 0 0 0 2px color-mix(in srgb, var(--red) 20%, transparent); }
|
||
50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--red) 10%, transparent); }
|
||
}
|
||
.agent-thread-node.error .agent-thread-dot {
|
||
background: var(--color-error);
|
||
}
|
||
.agent-thread-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
cursor: pointer;
|
||
font-size: 0.85em;
|
||
color: color-mix(in srgb, var(--fg) 70%, transparent);
|
||
user-select: none;
|
||
padding: 2px 0;
|
||
}
|
||
.agent-thread-header:hover {
|
||
color: var(--fg);
|
||
}
|
||
.agent-thread-icon {
|
||
font-size: 0.9em;
|
||
color: var(--red);
|
||
}
|
||
.agent-thread-tool-icon {
|
||
width: 14px;
|
||
height: 14px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex: 0 0 14px;
|
||
color: color-mix(in srgb, var(--fg) 64%, transparent);
|
||
opacity: 0.85;
|
||
}
|
||
.agent-thread-tool-icon svg {
|
||
display: block;
|
||
width: 12px;
|
||
height: 12px;
|
||
}
|
||
.agent-thread-tool-icon-link {
|
||
color: inherit;
|
||
text-decoration: none;
|
||
cursor: pointer;
|
||
}
|
||
.agent-thread-tool-icon-link:hover {
|
||
color: var(--red);
|
||
opacity: 1;
|
||
}
|
||
.agent-thread-node.error .agent-thread-icon {
|
||
color: var(--color-error);
|
||
}
|
||
.agent-thread-tool {
|
||
font-weight: 600;
|
||
color: var(--red);
|
||
text-transform: uppercase;
|
||
letter-spacing: 0.3px;
|
||
font-size: 0.9em;
|
||
}
|
||
.agent-thread-header-link {
|
||
width: 17px;
|
||
height: 17px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex: 0 0 17px;
|
||
margin-left: -3px;
|
||
color: var(--red);
|
||
opacity: 0.72;
|
||
text-decoration: none;
|
||
border: 0;
|
||
background: transparent;
|
||
}
|
||
.agent-thread-header-link:hover {
|
||
opacity: 1;
|
||
color: var(--red);
|
||
}
|
||
.agent-thread-header-link svg {
|
||
display: block;
|
||
}
|
||
.agent-thread-header-link-calendar {
|
||
transform: translateY(-2px);
|
||
}
|
||
.msg-ai .body a[href^="#event-"],
|
||
.msg-ai .body a[href^="#email-"],
|
||
.msg-ai .body a[href^="#document-"],
|
||
.msg-ai .body a[href^="#note-"],
|
||
.msg-ai .body a[href^="#task-"],
|
||
.msg-ai .body a[href^="#skill-"],
|
||
.msg-ai .body a[href^="#memory-"],
|
||
.msg-ai .body a[href^="#session-"] {
|
||
display: inline-flex;
|
||
align-items: baseline;
|
||
max-width: 100%;
|
||
padding: 1px 5px;
|
||
border-radius: 5px;
|
||
background: color-mix(in srgb, var(--red) 12%, transparent);
|
||
color: var(--red);
|
||
font-weight: 600;
|
||
text-decoration: none;
|
||
box-decoration-break: clone;
|
||
-webkit-box-decoration-break: clone;
|
||
}
|
||
.msg-ai .body a[href^="#event-"],
|
||
.msg-ai .body a[href^="#note-"],
|
||
.msg-ai .body a[href^="#skill-"],
|
||
.msg-ai .body a[href^="#memory-"],
|
||
.msg-ai .body a[href^="#session-"] {
|
||
font-size: 11px;
|
||
line-height: 1.35;
|
||
}
|
||
.msg-ai .body p:has(> .emoji:first-child):has(> a.chat-link[href^="#note-"]) {
|
||
margin-top: 0.15em;
|
||
margin-bottom: 0.15em;
|
||
line-height: 1.35;
|
||
}
|
||
.msg-ai .body a[href^="#event-"]:hover,
|
||
.msg-ai .body a[href^="#email-"]:hover,
|
||
.msg-ai .body a[href^="#document-"]:hover,
|
||
.msg-ai .body a[href^="#note-"]:hover,
|
||
.msg-ai .body a[href^="#task-"]:hover,
|
||
.msg-ai .body a[href^="#skill-"]:hover,
|
||
.msg-ai .body a[href^="#memory-"]:hover,
|
||
.msg-ai .body a[href^="#session-"]:hover {
|
||
background: color-mix(in srgb, var(--red) 18%, transparent);
|
||
text-decoration: underline;
|
||
}
|
||
.agent-thread-status {
|
||
font-size: 0.85em;
|
||
opacity: 0.5;
|
||
}
|
||
.agent-thread-chevron {
|
||
width: 12px;
|
||
height: 12px;
|
||
flex: 0 0 12px;
|
||
display: inline-grid;
|
||
place-items: center;
|
||
opacity: 0.4;
|
||
}
|
||
.agent-thread-chevron::before {
|
||
content: "";
|
||
width: 0;
|
||
height: 0;
|
||
border-top: 4px solid transparent;
|
||
border-bottom: 4px solid transparent;
|
||
border-left: 6px solid currentColor;
|
||
transform-origin: 50% 50%;
|
||
transition: transform 0.2s ease;
|
||
}
|
||
.agent-thread-node.open .agent-thread-chevron::before {
|
||
transform: rotate(90deg);
|
||
}
|
||
.agent-thread-node.browser-preview-node .agent-thread-chevron {
|
||
display: none;
|
||
}
|
||
.agent-thread-wave {
|
||
font-family: monospace;
|
||
font-size: 0.85em;
|
||
color: var(--red);
|
||
letter-spacing: -1px;
|
||
}
|
||
/* Live "cooking" timer on a running tool — prominent (accent, tabular) so a
|
||
long-running command always reads as alive, not frozen. */
|
||
.agent-thread-elapsed {
|
||
margin: 0 6px 0 4px;
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
font-variant-numeric: tabular-nums;
|
||
color: var(--accent, var(--red));
|
||
}
|
||
/* Stall watchdog banner — shown when the stream has been silent for ~1min. */
|
||
.stall-banner {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin: 8px auto;
|
||
padding: 8px 12px;
|
||
max-width: 90%;
|
||
font-size: 12px;
|
||
border-radius: 8px;
|
||
background: color-mix(in srgb, var(--color-warning, #f0ad4e) 12%, var(--bg));
|
||
border: 1px solid color-mix(in srgb, var(--color-warning, #f0ad4e) 40%, transparent);
|
||
}
|
||
.stall-banner-txt { flex: 1; opacity: 0.85; }
|
||
.stall-banner-btn {
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
padding: 4px 10px;
|
||
border-radius: 6px;
|
||
border: none;
|
||
background: var(--accent, var(--red));
|
||
color: #fff;
|
||
cursor: pointer;
|
||
flex-shrink: 0;
|
||
}
|
||
.stall-banner-stop {
|
||
background: none;
|
||
color: var(--fg);
|
||
border: 1px solid var(--border);
|
||
}
|
||
.agent-thread-content {
|
||
display: none;
|
||
padding: 4px 0 2px 0;
|
||
overflow-x: auto;
|
||
overflow-y: hidden;
|
||
}
|
||
.agent-thread-node.open .agent-thread-content {
|
||
display: block;
|
||
}
|
||
.agent-thread-cmd {
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
padding: 8px 12px;
|
||
margin: 4px 0;
|
||
color: var(--fg);
|
||
font-size: 0.85em;
|
||
white-space: pre-wrap;
|
||
word-break: break-word;
|
||
line-height: 1.4;
|
||
overflow-x: auto;
|
||
}
|
||
.agent-thread-summary {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
max-width: 100%;
|
||
margin: 4px 0;
|
||
padding: 4px 8px;
|
||
border: 1px solid color-mix(in srgb, var(--accent, var(--red)) 26%, var(--border));
|
||
border-radius: 6px;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 8%, transparent);
|
||
color: color-mix(in srgb, var(--fg) 84%, var(--accent, var(--red)));
|
||
font-size: 12px;
|
||
font-variant-numeric: tabular-nums;
|
||
line-height: 1.35;
|
||
}
|
||
.agent-thread-summary-link {
|
||
cursor: pointer;
|
||
text-decoration: none;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.agent-thread-summary-link:hover {
|
||
color: var(--accent, var(--red));
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 42%, var(--border));
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 12%, transparent);
|
||
}
|
||
|
||
.agent-image-progress {
|
||
margin: 6px 0 0;
|
||
}
|
||
.agent-image-progress-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 10px;
|
||
font-size: 11px;
|
||
line-height: 1.2;
|
||
color: color-mix(in srgb, var(--fg) 72%, transparent);
|
||
}
|
||
.agent-image-progress-label {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.agent-image-progress-value {
|
||
flex-shrink: 0;
|
||
font-variant-numeric: tabular-nums;
|
||
color: color-mix(in srgb, var(--accent, var(--red)) 75%, var(--fg));
|
||
}
|
||
.agent-image-progress-track {
|
||
display: none !important;
|
||
}
|
||
|
||
.private-browser-preview {
|
||
width: 100%;
|
||
max-height: min(300px, 36vh);
|
||
margin: 6px 0 2px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
overflow: hidden;
|
||
border: 1px solid color-mix(in srgb, var(--red) 20%, transparent);
|
||
border-radius: 8px;
|
||
background: color-mix(in srgb, var(--red) 5%, transparent);
|
||
color: var(--fg);
|
||
box-shadow: none;
|
||
}
|
||
.private-browser-preview-header {
|
||
height: 32px;
|
||
min-height: 32px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding: 0 6px 0 10px;
|
||
border-bottom: 1px solid color-mix(in srgb, var(--red) 15%, transparent);
|
||
background: color-mix(in srgb, var(--red) 10%, transparent);
|
||
font-size: 0.85em;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
}
|
||
.private-browser-preview-title {
|
||
flex-shrink: 0;
|
||
color: var(--red);
|
||
font-size: inherit;
|
||
font-weight: inherit;
|
||
line-height: 1;
|
||
letter-spacing: 0;
|
||
}
|
||
.private-browser-preview-status {
|
||
min-width: 0;
|
||
flex: 1;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
color: color-mix(in srgb, var(--fg) 68%, transparent);
|
||
font-size: inherit;
|
||
line-height: 1;
|
||
}
|
||
.private-browser-preview-fold {
|
||
width: 18px;
|
||
height: 18px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
left: 2px;
|
||
flex-shrink: 0;
|
||
padding: 0;
|
||
border: 0;
|
||
border-radius: 0;
|
||
background: transparent;
|
||
color: var(--red);
|
||
cursor: pointer;
|
||
font-size: 0.95em;
|
||
font-family: inherit;
|
||
font-weight: 500;
|
||
line-height: 1;
|
||
text-shadow: none;
|
||
-webkit-text-stroke: 0;
|
||
}
|
||
.private-browser-preview-fold:hover {
|
||
background: transparent;
|
||
color: var(--red);
|
||
}
|
||
.private-browser-preview-frame {
|
||
position: relative;
|
||
min-height: 130px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
background: color-mix(in srgb, #000 72%, var(--bg));
|
||
box-shadow:
|
||
inset 0 1px 0 color-mix(in srgb, #fff 8%, transparent),
|
||
inset 0 0 0 1px color-mix(in srgb, #000 35%, transparent),
|
||
0 8px 18px color-mix(in srgb, #000 18%, transparent);
|
||
}
|
||
.private-browser-preview[data-browser-url] .private-browser-preview-frame {
|
||
cursor: zoom-in;
|
||
}
|
||
.private-browser-preview[data-browser-url] .private-browser-preview-frame::after {
|
||
content: "";
|
||
position: absolute;
|
||
inset: 0;
|
||
pointer-events: none;
|
||
opacity: 0.55;
|
||
transition: opacity 150ms ease;
|
||
background:
|
||
radial-gradient(circle at center, transparent 42%, color-mix(in srgb, #000 30%, transparent) 100%),
|
||
color-mix(in srgb, var(--bg) 10%, transparent);
|
||
}
|
||
.private-browser-preview[data-browser-url] .private-browser-preview-frame:hover::after {
|
||
opacity: 0.9;
|
||
}
|
||
.private-browser-preview.folded .private-browser-preview-frame {
|
||
display: none;
|
||
}
|
||
.private-browser-preview.folded .private-browser-preview-header {
|
||
border-bottom: 0;
|
||
}
|
||
.private-browser-preview-frame img {
|
||
width: 100%;
|
||
height: auto;
|
||
max-height: calc(min(300px, 36vh) - 32px);
|
||
display: block;
|
||
object-fit: contain;
|
||
transform: scale(1.1);
|
||
transform-origin: center center;
|
||
animation: private-browser-image-in 180ms ease-out both;
|
||
}
|
||
.private-browser-preview-frame img:not([src]),
|
||
.private-browser-preview-frame img[src=""] {
|
||
display: none;
|
||
}
|
||
.private-browser-preview-empty {
|
||
padding: 22px 14px;
|
||
width: auto;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 7px;
|
||
color: color-mix(in srgb, var(--fg) 48%, transparent);
|
||
font-size: 11px;
|
||
line-height: 1.35;
|
||
}
|
||
.private-browser-preview-spinner {
|
||
width: 13px;
|
||
height: 13px;
|
||
flex: 0 0 13px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.private-browser-preview-spinner .spinner-whirlpool,
|
||
.private-browser-preview-spinner .ai-spinner-whirlpool {
|
||
margin: 0 !important;
|
||
}
|
||
@keyframes private-browser-image-in {
|
||
from { opacity: 0; transform: scale(1.08); }
|
||
to { opacity: 1; transform: scale(1.1); }
|
||
}
|
||
|
||
@media (max-width: 700px) {
|
||
.private-browser-preview-frame img {
|
||
max-height: calc(36vh - 32px);
|
||
}
|
||
}
|
||
|
||
/* Mobile: constrain thread content */
|
||
@media (max-width: 768px) {
|
||
.agent-thread {
|
||
margin-left: 16px;
|
||
padding-left: 18px;
|
||
max-width: calc(90% - 16px);
|
||
}
|
||
.agent-thread-cmd {
|
||
font-size: 0.78em;
|
||
padding: 6px 8px;
|
||
max-width: 100%;
|
||
overflow-x: auto;
|
||
}
|
||
.agent-thread-content {
|
||
max-width: calc(100vw - 90px);
|
||
}
|
||
.agent-tool-output pre {
|
||
font-size: 0.8em;
|
||
max-width: 100%;
|
||
overflow-x: auto;
|
||
}
|
||
.agent-thread-header {
|
||
font-size: 0.8em;
|
||
}
|
||
.agent-thread-dot {
|
||
left: -16px;
|
||
top: 10px;
|
||
}
|
||
/* padding-left drops to 18px here, so the terminating dot needs its own
|
||
offset (3px - 18px) to stay centred on the rail. */
|
||
.agent-thread:not(.has-bottom) .agent-thread-node.open:last-child::after {
|
||
left: -15px;
|
||
}
|
||
}
|
||
|
||
/* ===== AGENT TOOL OUTPUT (inside thread nodes) ===== */
|
||
.agent-tool-output {
|
||
margin-top: 8px;
|
||
background: color-mix(in srgb, var(--red) 5%, transparent);
|
||
border: 1px solid color-mix(in srgb, var(--red) 20%, transparent);
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
}
|
||
.agent-tool-output summary {
|
||
color: var(--red);
|
||
background: color-mix(in srgb, var(--red) 10%, transparent);
|
||
border-bottom: 1px solid color-mix(in srgb, var(--red) 15%, transparent);
|
||
cursor: pointer;
|
||
font-size: 0.85em;
|
||
user-select: none;
|
||
padding: 6px 10px;
|
||
font-weight: 500;
|
||
/* Chevron on the right (like the thinking section) instead of the default
|
||
left-side disclosure triangle. */
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
list-style: none;
|
||
}
|
||
.agent-tool-output summary::-webkit-details-marker { display: none; }
|
||
/* File-write diff — neutral chrome (not the red error tint) + colored lines */
|
||
.agent-tool-diff {
|
||
background: color-mix(in srgb, var(--fg) 4%, transparent);
|
||
border-color: color-mix(in srgb, var(--fg) 18%, transparent);
|
||
}
|
||
.agent-tool-diff summary {
|
||
color: var(--fg);
|
||
background: color-mix(in srgb, var(--fg) 7%, transparent);
|
||
border-bottom-color: color-mix(in srgb, var(--fg) 12%, transparent);
|
||
}
|
||
.agent-tool-diff .diff-stat {
|
||
font-weight: 600;
|
||
opacity: 0.7;
|
||
font-family: var(--mono, monospace);
|
||
}
|
||
/* Collapsed diff summary: filename + +adds/−dels (theme green/red). */
|
||
.agent-tool-diff summary {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.agent-tool-diff .diff-file {
|
||
font-family: var(--mono, monospace);
|
||
font-weight: 600;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.agent-tool-diff .diff-summary-stats {
|
||
margin-left: auto;
|
||
font-family: var(--mono, monospace);
|
||
font-weight: 600;
|
||
flex-shrink: 0;
|
||
}
|
||
.agent-tool-diff .diff-summary-stats .diff-stat-add { color: var(--green, #2ecc71); }
|
||
.agent-tool-diff .diff-summary-stats .diff-stat-del { color: var(--red, #e74c3c); }
|
||
.agent-tool-diff .diff-summary-stats .diff-stat-new { color: var(--accent, var(--red)); opacity: 0.85; }
|
||
.diff-pre {
|
||
margin: 0;
|
||
padding: 8px 10px;
|
||
overflow-x: auto;
|
||
font-family: var(--mono, monospace);
|
||
font-size: 0.82em;
|
||
line-height: 1.45;
|
||
}
|
||
.diff-pre span { display: block; white-space: pre; }
|
||
.diff-pre .diff-add { background: color-mix(in srgb, #2ecc71 22%, transparent); }
|
||
.diff-pre .diff-del { background: color-mix(in srgb, #e74c3c 22%, transparent); }
|
||
.diff-pre .diff-hunk { color: var(--accent); opacity: 0.85; }
|
||
.diff-pre .diff-meta { opacity: 0.55; }
|
||
.diff-pre .diff-ctx { opacity: 0.8; }
|
||
/* Suppress the global `summary::before { content: '▶' }` left arrow — this
|
||
section uses a right-side chevron instead. */
|
||
.agent-tool-output summary::before { content: none; }
|
||
.agent-tool-output summary::after {
|
||
content: '\25BC'; /* ▼ */
|
||
color: var(--red);
|
||
font-size: 0.9em;
|
||
transition: transform 0.3s ease;
|
||
}
|
||
.agent-tool-output[open] > summary::after {
|
||
transform: rotate(180deg);
|
||
}
|
||
.agent-tool-output summary:hover {
|
||
background: color-mix(in srgb, var(--red) 15%, transparent);
|
||
}
|
||
.agent-thinking-dots .ai-spinner {
|
||
font-size: 12px;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
|
||
.agent-tool-output[open] {
|
||
background: color-mix(in srgb, var(--red) 6%, transparent);
|
||
}
|
||
.agent-tool-output[open] > :not(summary) {
|
||
animation: detail-reveal 0.25s ease-out both;
|
||
}
|
||
@keyframes detail-reveal {
|
||
from { opacity: 0; transform: translateY(-4px); }
|
||
to { opacity: 1; transform: translateY(0); }
|
||
}
|
||
.agent-tool-output pre {
|
||
background: transparent;
|
||
border: none;
|
||
border-radius: 0;
|
||
padding: 10px 14px;
|
||
margin-top: 0;
|
||
max-height: 300px;
|
||
overflow-y: auto;
|
||
font-size: 0.95em;
|
||
color: var(--fg);
|
||
opacity: 0.85;
|
||
white-space: pre-wrap;
|
||
word-break: break-all;
|
||
line-height: 1.5;
|
||
}
|
||
|
||
/* Mobile responsive styles */
|
||
@media (max-width: 768px) {
|
||
#recording-indicator {
|
||
margin: 8px;
|
||
padding: 10px;
|
||
}
|
||
|
||
.recording-text {
|
||
font-size: 14px;
|
||
}
|
||
|
||
.stop-recording-btn {
|
||
padding: 6px 10px;
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
/* ===== PANE STYLES (shared by compare) ===== */
|
||
|
||
.pane-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 6px 0 4px;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.close-split-btn,
|
||
.pane-close-btn {
|
||
background: none;
|
||
border: none;
|
||
color: var(--color-error);
|
||
font-size: 18px;
|
||
cursor: pointer;
|
||
padding: 0 4px;
|
||
line-height: 1;
|
||
opacity: 0;
|
||
transition: opacity 0.15s;
|
||
}
|
||
.pane-header:hover .close-split-btn,
|
||
.pane-header:hover .pane-close-btn {
|
||
opacity: 1;
|
||
}
|
||
.close-split-btn:hover,
|
||
.pane-close-btn:hover {
|
||
color: var(--color-error-light);
|
||
}
|
||
|
||
/* Compare pane close controls use the same shared circular close treatment
|
||
as modal/title close buttons. */
|
||
.compare-pane .pane-close-btn.close-btn {
|
||
width: 24px;
|
||
height: 24px;
|
||
min-width: 24px;
|
||
padding: 0;
|
||
border: 1px solid transparent;
|
||
border-radius: 999px;
|
||
background: transparent;
|
||
color: color-mix(in srgb, var(--fg) 58%, transparent);
|
||
font-size: 0;
|
||
opacity: 0.5;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: background 0.15s, color 0.15s, opacity 0.15s;
|
||
}
|
||
.compare-pane .pane-close-btn.close-btn:hover,
|
||
.compare-pane .pane-close-btn.close-btn:focus-visible {
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent);
|
||
border-color: color-mix(in srgb, var(--fg) 12%, transparent);
|
||
color: var(--fg);
|
||
opacity: 1;
|
||
outline: none;
|
||
}
|
||
.compare-pane .pane-action-btn[data-action="expand"] {
|
||
width: 24px;
|
||
height: 24px;
|
||
min-width: 24px;
|
||
padding: 0;
|
||
border: 1px solid transparent;
|
||
border-radius: 999px;
|
||
justify-content: center;
|
||
transition: background 0.15s, color 0.15s, opacity 0.15s;
|
||
}
|
||
.compare-pane .pane-action-btn[data-action="expand"]:hover,
|
||
.compare-pane .pane-action-btn[data-action="expand"]:focus-visible {
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent);
|
||
border-color: color-mix(in srgb, var(--fg) 12%, transparent);
|
||
color: var(--fg);
|
||
opacity: 1;
|
||
outline: none;
|
||
}
|
||
|
||
|
||
/* ============================================ */
|
||
/* RESEARCH DETAILS EXPANDABLE SECTION - UPDATED */
|
||
/* ============================================ */
|
||
|
||
/* Style the details element */
|
||
details {
|
||
background: color-mix(in srgb, var(--hl-string) 5%, transparent);
|
||
border: 1px solid color-mix(in srgb, var(--hl-string) 30%, transparent);
|
||
border-radius: 8px;
|
||
margin: 12px 0;
|
||
padding: 0;
|
||
overflow: hidden;
|
||
transition: all 0.3s ease;
|
||
}
|
||
|
||
details[open] {
|
||
background: color-mix(in srgb, var(--hl-string) 8%, transparent);
|
||
}
|
||
details[open] > :not(summary) {
|
||
animation: detail-reveal 0.25s ease-out both;
|
||
}
|
||
|
||
/* Style the summary (clickable header) - NO CURSIVE, NORMAL SIZE */
|
||
summary {
|
||
cursor: pointer;
|
||
padding: 10px 14px;
|
||
background: color-mix(in srgb, var(--hl-string) 10%, transparent);
|
||
border-bottom: 1px solid color-mix(in srgb, var(--hl-string) 20%, transparent);
|
||
font-weight: 500;
|
||
font-size: 0.95em;
|
||
font-style: normal;
|
||
font-family: inherit;
|
||
color: var(--hl-string);
|
||
user-select: none;
|
||
list-style: none;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
transition: background 0.2s ease;
|
||
}
|
||
|
||
summary:hover {
|
||
background: color-mix(in srgb, var(--hl-string) 15%, transparent);
|
||
}
|
||
|
||
/* Add custom arrow */
|
||
summary::before {
|
||
content: '▶';
|
||
display: inline-block;
|
||
transition: transform 0.3s ease;
|
||
font-size: 0.75em; /* Smaller arrow */
|
||
}
|
||
|
||
details[open] summary::before {
|
||
transform: rotate(90deg);
|
||
}
|
||
|
||
/* Hide default marker in webkit browsers */
|
||
summary::-webkit-details-marker {
|
||
display: none;
|
||
}
|
||
|
||
/* Style the content inside details - SMALLER, MORE COMPACT */
|
||
details > div,
|
||
details > p,
|
||
details > ul,
|
||
details > ol {
|
||
padding: 12px 14px; /* Less padding */
|
||
animation: fadeIn 0.3s ease;
|
||
font-size: 0.9em; /* Smaller text */
|
||
line-height: 1.5;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(-10px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
/* Style research findings inside details - SMALLER HEADINGS */
|
||
details h3 {
|
||
margin-top: 12px;
|
||
margin-bottom: 6px;
|
||
color: var(--hl-string);
|
||
font-size: 0.95em;
|
||
font-weight: 500;
|
||
}
|
||
|
||
details h4 {
|
||
margin-top: 10px;
|
||
margin-bottom: 5px;
|
||
color: var(--hl-string);
|
||
font-size: 0.9em;
|
||
font-weight: 500;
|
||
}
|
||
|
||
details ul {
|
||
margin-left: 18px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
details li {
|
||
margin-bottom: 5px;
|
||
line-height: 1.4;
|
||
font-size: 0.85em; /* Smaller list items */
|
||
}
|
||
|
||
details strong {
|
||
color: var(--hl-string);
|
||
font-weight: 500;
|
||
}
|
||
|
||
details a {
|
||
color: var(--accent);
|
||
text-decoration: none;
|
||
transition: color 0.2s ease;
|
||
}
|
||
|
||
details a:hover {
|
||
color: var(--color-link-hover);
|
||
text-decoration: underline;
|
||
}
|
||
|
||
/* Research metadata - SMALLER */
|
||
details .research-meta {
|
||
font-size: 0.8em;
|
||
color: var(--fg);
|
||
opacity: 0.8;
|
||
margin-top: 4px;
|
||
}
|
||
|
||
/* Source links - SMALLER */
|
||
details .source-link {
|
||
display: inline-block;
|
||
margin-top: 3px;
|
||
padding: 2px 5px;
|
||
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
||
border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
|
||
border-radius: 4px;
|
||
font-size: 0.68em;
|
||
color: var(--accent);
|
||
}
|
||
|
||
details .source-link:hover {
|
||
background: color-mix(in srgb, var(--accent) 20%, transparent);
|
||
border-color: var(--accent);
|
||
}
|
||
|
||
/* Research report links - clean and subtle */
|
||
details a {
|
||
color: var(--accent);
|
||
text-decoration: none;
|
||
font-weight: normal; /* Remove bold */
|
||
font-size: 0.85em;
|
||
opacity: 0.9;
|
||
transition: all 0.2s ease;
|
||
word-break: break-all; /* Break long URLs nicely */
|
||
}
|
||
|
||
details a:hover {
|
||
color: var(--color-link-hover);
|
||
text-decoration: underline;
|
||
opacity: 1;
|
||
}
|
||
|
||
/* ============================================ */
|
||
/* CUSTOM SYNTAX HIGHLIGHTING - Theme-Reactive */
|
||
/* ============================================ */
|
||
.hljs {
|
||
background: var(--code-bg, var(--hl-bg, var(--panel)));
|
||
color: var(--code-fg, var(--hl-fg, var(--fg)));
|
||
padding: 8px;
|
||
border-radius: 4px;
|
||
}
|
||
|
||
/* Keywords & control flow — purple/magenta */
|
||
.hljs-keyword,
|
||
.hljs-selector-tag { color: var(--hl-keyword); }
|
||
|
||
/* Strings & regex — warm yellow/orange */
|
||
.hljs-string,
|
||
.hljs-regexp,
|
||
.hljs-addition { color: var(--hl-string); }
|
||
|
||
/* Comments & docs — muted. font-style intentionally omitted: italics shift
|
||
glyph widths in the highlight overlay relative to the transparent textarea
|
||
above it, which makes the caret drift away from the visible character. */
|
||
.hljs-comment,
|
||
.hljs-quote,
|
||
.hljs-meta { color: var(--hl-comment); }
|
||
|
||
/* Functions & method names — blue */
|
||
.hljs-function,
|
||
.hljs-title,
|
||
.hljs-title.function_,
|
||
.hljs-section { color: var(--hl-function); }
|
||
|
||
/* Numbers & constants — distinct from strings */
|
||
.hljs-number,
|
||
.hljs-literal { color: var(--hl-number, var(--hl-string)); }
|
||
|
||
/* Built-ins & types — teal/cyan tint */
|
||
.hljs-built_in,
|
||
.hljs-type,
|
||
.hljs-class,
|
||
.hljs-title.class_ { color: var(--hl-builtin, var(--hl-function)); }
|
||
|
||
/* Variables & identifiers — fg with slight distinction */
|
||
.hljs-variable,
|
||
.hljs-template-variable,
|
||
.hljs-attr { color: var(--hl-variable, var(--hl-fg, var(--fg))); }
|
||
|
||
/* Operators & punctuation — slightly dimmed fg */
|
||
.hljs-operator,
|
||
.hljs-punctuation { color: var(--hl-fg, var(--fg)); opacity: 0.8; }
|
||
|
||
/* Parameters */
|
||
.hljs-params { color: var(--hl-params, var(--hl-fg, var(--fg))); }
|
||
|
||
/* Property access, attributes in HTML/XML */
|
||
.hljs-property,
|
||
.hljs-selector-class,
|
||
.hljs-selector-id { color: var(--hl-variable, var(--hl-function)); }
|
||
|
||
/* Tags (HTML) */
|
||
.hljs-tag { color: var(--hl-keyword); }
|
||
.hljs-name { color: var(--hl-keyword); }
|
||
|
||
/* Deletion/diff */
|
||
.hljs-deletion { color: var(--red); }
|
||
|
||
/* Symbol, special */
|
||
.hljs-symbol { color: var(--hl-string); }
|
||
.hljs-link { color: var(--hl-function); text-decoration: underline; }
|
||
|
||
/* Emphasis — applied globally (chat messages, rendered markdown in docs
|
||
preview, etc.) but explicitly NEUTRALIZED in the doc editor's overlay so
|
||
the textarea-and-overlay caret alignment stays bit-perfect. Bold / italic
|
||
shift glyph widths and that drifts the click-to-row mapping. */
|
||
.hljs-emphasis { font-style: italic; }
|
||
.hljs-strong { font-weight: bold; }
|
||
.doc-editor-highlight .hljs-emphasis,
|
||
.doc-editor-highlight .hljs-strong {
|
||
font-style: normal !important;
|
||
font-weight: inherit !important;
|
||
}
|