Files
openclaw/ui/src/styles/chat/layout.css
Peter Steinberger e279076010 fix(ui): carapace follow-ups — embed font stacks, data-theme-resolved, undefined status tokens (#113724)
* feat(ui): publish carapace embed font stacks to MCP apps

Adopt the carapace embed contract's sandbox-safe font stacks: publish
--font-sans for the first time and switch --font-mono from the host's
JetBrains-led token to the embed mono stack. Both are static, system-
resolvable values byte-identical to carapace candidate/embed.css, since
the sandbox font-src policy silently drops brand faces.

* feat(ui): emit data-theme-resolved alongside theme attributes

Carapace CSS selects on [data-theme-resolved]; keep it in lockstep with
data-theme-mode at boot (index.html IIFE) and on every runtime theme
change (bootstrap publish path). Rename applyStartupPresentation to
applyThemePresentation: it runs on every theme change, not just startup.

* fix(ui): resolve undefined --success/--warning tokens and drop dead hex fallbacks

--success and --warning were never defined (real tokens: --ok/--warn),
so sites with literal fallbacks rendered off-palette one-off colors and
sites without them silently dropped declarations (invalid color-mix in
the chat sidebar warn banner). Map all uses to the semantic tokens
across board, chat sidebar/layout, layout, and components styles, and
strip the stale dead var() hex fallbacks in these global stylesheets.
Code-syntax palette hexes in the file view are documented as deliberate.
2026-07-25 09:32:56 -07:00

4910 lines
102 KiB
CSS

/* =============================================
CHAT CARD LAYOUT - Flex container with sticky compose
============================================= */
/* Main chat card - flex column layout, transparent background */
openclaw-chat-page {
display: flex;
flex: 1 1 0;
min-width: 0;
min-height: 0;
}
.chat {
--chat-thread-max-width: 48rem;
position: relative;
display: flex;
flex-direction: column;
flex: 1 1 0;
height: 100%;
width: 100%;
min-height: 0;
/* Allow flex shrinking */
padding: 0 !important;
overflow: hidden;
background: transparent !important;
border: none !important;
box-shadow: none !important;
}
/* Chat pane error alert. The pane strips its own padding, so the alert
carries its own inset as a centered card instead of stretching into a
full-bleed bar; visual language mirrors the connection pill (status dot
on an elevated surface) with a danger accent. */
.chat-error {
display: flex;
align-items: flex-start;
gap: 10px;
align-self: center;
max-width: min(36rem, calc(100% - 32px));
margin: 12px 16px 4px;
padding: 10px 14px;
border: 1px solid color-mix(in srgb, var(--danger) 32%, var(--border));
border-radius: var(--radius-lg);
background: color-mix(in srgb, var(--danger) 9%, var(--bg-elevated));
box-shadow: var(--shadow-lg);
color: var(--text-strong);
font-size: 13px;
line-height: 1.5;
animation: chat-error-enter 0.25s var(--ease-out);
}
@keyframes chat-error-enter {
from {
opacity: 0;
transform: translateY(-4px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@media (prefers-reduced-motion: reduce) {
.chat-error {
animation: none;
}
}
.chat-error__dot {
flex-shrink: 0;
width: 7px;
height: 7px;
/* Optically centers the dot on the first text line when the message wraps. */
margin-top: 6px;
border-radius: var(--radius-full);
background: var(--danger);
box-shadow: 0 0 8px color-mix(in srgb, var(--danger) 55%, transparent);
}
.chat-error__content {
min-width: 0;
overflow-wrap: anywhere;
}
.chat-error__dismiss {
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
width: 26px;
height: 26px;
/* Pulls the hit target into the card's padding so the text stays the
tallest run and the card keeps its compact height. */
margin: -4px -6px -4px 2px;
border: 0;
border-radius: var(--radius-sm);
background: transparent;
color: var(--muted);
transition: background var(--duration-fast) var(--ease-out);
}
.chat-error__dismiss:hover {
background: color-mix(in srgb, currentColor 12%, transparent);
color: var(--text-strong);
}
.chat-error__dismiss:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.chat-error__dismiss svg {
display: block;
width: 15px;
height: 15px;
fill: none;
stroke: currentColor;
stroke-width: 1.8;
stroke-linecap: round;
stroke-linejoin: round;
}
.chat::after {
content: "";
position: absolute;
inset: 0;
z-index: 90;
pointer-events: none;
background: var(--accent);
opacity: 0;
transition: opacity 140ms cubic-bezier(0.23, 1, 0.32, 1);
}
.chat[data-attachment-drop-active]::after {
opacity: 0.1;
}
.chat > * {
transition: opacity 140ms cubic-bezier(0.23, 1, 0.32, 1);
}
.chat[data-attachment-drop-active] > * {
opacity: 0.5;
}
.chat-workspace-conflict-notice {
flex: 0 0 auto;
margin: 12px 16px 0;
color: var(--text);
}
.chat-workspace-conflict-notice__content {
display: grid;
gap: 8px;
}
.chat-workspace-conflict-notice__content p,
.chat-workspace-conflict-event p {
margin: 0;
color: var(--muted);
}
.chat-workspace-conflict-notice__title,
.chat-workspace-conflict-event__header {
display: flex;
align-items: center;
gap: 8px;
color: color-mix(in srgb, var(--warn) 82%, var(--text-strong));
}
.chat-workspace-conflict-notice__title svg,
.chat-workspace-conflict-event__header svg {
width: 17px;
height: 17px;
flex: 0 0 auto;
}
.chat-workspace-conflict-paths {
display: grid;
gap: 3px;
margin: 0;
padding-left: 22px;
}
.chat-workspace-conflict-paths code,
.chat-workspace-conflict-ref code,
.chat-workspace-conflict-commands code {
overflow-wrap: anywhere;
}
.chat-workspace-conflict-more {
color: var(--muted);
font-size: 12px;
}
.chat-workspace-conflict-command-help {
margin: 0;
color: var(--muted);
font-size: 12px;
}
.chat-workspace-conflict-ref,
.chat-workspace-conflict-commands > div {
display: grid;
grid-template-columns: max-content minmax(0, 1fr) max-content;
align-items: center;
gap: 8px;
}
.chat-workspace-conflict-ref > span,
.chat-workspace-conflict-commands span {
color: var(--muted);
font-size: 12px;
}
.chat-workspace-conflict-ref code,
.chat-workspace-conflict-commands code {
min-width: 0;
padding: 4px 7px;
border-radius: var(--radius-sm);
background: color-mix(in srgb, var(--bg) 72%, transparent);
font-size: 11px;
}
.chat-workspace-conflict-commands {
display: grid;
gap: 5px;
}
@media (max-width: 640px) {
.chat-workspace-conflict-ref,
.chat-workspace-conflict-commands > div {
grid-template-columns: minmax(0, 1fr) max-content;
}
.chat-workspace-conflict-ref > span,
.chat-workspace-conflict-commands span {
grid-column: 1 / -1;
}
}
@media (prefers-reduced-motion: reduce) {
.chat::after,
.chat > * {
transition-duration: 0ms;
}
}
.chat-workbench__main {
/* Positioning context for the floating rail openers so they pin to the
thread column instead of overlapping an open right-docked rail. */
position: relative;
grid-column: 1;
grid-row: 1;
display: flex;
flex-direction: column;
flex: 1 1 0;
width: 100%;
min-width: 0;
min-height: 0;
}
/* Chat header - fixed at top, transparent */
.chat-header {
display: flex;
justify-content: space-between;
align-items: flex-end;
gap: 16px;
flex-wrap: wrap;
flex-shrink: 0;
padding-bottom: 0;
margin-bottom: 0;
background: transparent;
}
.chat-header__left {
display: flex;
align-items: flex-end;
gap: 12px;
flex-wrap: wrap;
min-width: 0;
}
.chat-header__right {
display: flex;
align-items: center;
gap: 8px;
}
.chat-session {
min-width: 240px;
}
/* Chat thread - scrollable middle section, transparent */
.chat-thread {
flex: 1 1 0;
/* Grow, shrink, and use 0 base for proper scrolling */
overflow-y: auto;
overflow-x: hidden;
overflow-anchor: none;
/* The transcript is document content, unlike the surrounding app chrome. */
user-select: text;
scrollbar-gutter: stable both-edges;
scrollbar-color: var(--muted-strong) transparent;
/* The pane header owns the titlebar and native drag surface. No horizontal
padding: macOS overlay scrollbars render inside the
scroll container's padding, which floats the thumb away from the pane
edge (visible next to the sidebar divider). The side inset lives on
.chat-thread-inner instead so the scrollbar hugs the edge. */
padding: clamp(20px, 3vh, 28px) 0 6px;
margin: 0 0 0 0;
min-height: 0;
/* Allow shrinking for flex scroll behavior */
border-radius: var(--radius-md);
background: transparent;
}
:root .chat-thread::-webkit-scrollbar-thumb {
background: var(--muted-strong);
}
:root .chat-thread::-webkit-scrollbar-thumb:hover {
background: var(--text);
}
.chat-thread-inner > :first-child {
margin-top: 0 !important;
}
.chat-thread-inner {
box-sizing: border-box;
/* 36px shared gutter plus the responsive side inset that used to be
.chat-thread's horizontal padding (moved off the scroll container so
overlay scrollbars sit flush at the pane edge). */
width: calc(100% - 36px - 2 * clamp(6px, 1vw, 12px));
max-width: var(--chat-thread-max-width);
margin-inline: auto;
}
.chat-inline-approval {
box-sizing: border-box;
flex: 0 0 auto;
width: calc(100% - 36px - 2 * clamp(6px, 1vw, 12px));
max-width: var(--chat-thread-max-width);
margin: 8px auto;
}
.chat-run-error {
box-sizing: border-box;
display: flex;
align-items: flex-start;
gap: 8px;
width: calc(100% - 36px);
max-width: 48rem;
margin: 8px auto 0;
padding: 9px 11px;
border: 1px solid color-mix(in srgb, var(--danger) 38%, var(--border));
border-radius: 8px;
background: color-mix(in srgb, var(--danger) 8%, var(--panel));
color: var(--text);
font-size: 13px;
line-height: 1.4;
}
.chat-run-error__icon {
display: inline-flex;
width: 16px;
height: 16px;
flex: 0 0 16px;
margin-top: 1px;
color: var(--danger);
}
.chat-run-error__icon svg {
width: 100%;
height: 100%;
}
.chat-run-error__summary {
min-width: 0;
overflow-wrap: anywhere;
}
.chat-virtual-sizer {
position: relative;
width: 100%;
}
.chat-virtual-row {
position: absolute;
top: 0;
left: 0;
display: flow-root;
width: 100%;
}
.chat-virtual-row--first > :first-child {
margin-top: 0 !important;
}
.chat-history-sentinel {
display: flex;
min-height: 28px;
align-items: center;
justify-content: center;
}
.chat-virtual-sizer > .chat-history-sentinel {
position: absolute;
z-index: 1;
top: 0;
right: 0;
left: 0;
min-height: 1px;
pointer-events: none;
}
.chat-history-loading {
display: inline-flex;
align-items: center;
gap: 8px;
color: var(--muted);
font-size: 12px;
}
/* The zero-height anchor keeps the affordance out of the flex flow so showing
it never shrinks the transcript or moves the composer. */
.chat-scroll-to-bottom-wrap {
position: relative;
align-self: stretch;
height: 0;
flex: 0 0 0;
z-index: 10;
}
.chat-scroll-to-bottom {
position: absolute;
bottom: 12px;
left: 50%;
display: inline-flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
padding: 0;
line-height: 1;
color: var(--text);
background: var(--panel-strong);
border: 1px solid var(--border);
border-radius: var(--radius-full);
box-shadow: var(--shadow-sm);
cursor: pointer;
pointer-events: auto;
transform: translateX(-50%);
}
.chat-scroll-to-bottom:focus-visible {
outline: 2px solid color-mix(in srgb, var(--text) 28%, transparent);
outline-offset: 2px;
}
.chat-scroll-to-bottom svg {
width: 16px;
height: 16px;
stroke: currentColor;
fill: none;
stroke-width: 1.5px;
stroke-linecap: round;
stroke-linejoin: round;
flex-shrink: 0;
}
/* Context usage instrument - compact dial with an on-demand session readout. */
.context-usage {
position: relative;
display: inline-flex;
align-items: center;
gap: 5px;
flex-shrink: 0;
color: var(--ctx-color, var(--muted));
}
.context-usage details {
display: inline-flex;
}
.context-ring {
display: inline-flex;
align-items: center;
gap: 5px;
height: 24px;
padding: 0 7px;
border-radius: var(--radius-full);
color: currentColor;
font-size: 11px;
line-height: 1;
list-style: none;
user-select: none;
animation: fade-in 0.2s var(--ease-out);
transition:
color 150ms ease-out,
background 150ms ease-out;
}
.context-ring::-webkit-details-marker {
display: none;
}
.context-ring:hover,
.context-usage details[open] .context-ring {
background: var(--ctx-bg, color-mix(in srgb, var(--muted) 8%, transparent));
}
.context-ring--warning {
background: var(--ctx-bg, transparent);
}
.context-ring__dial {
flex-shrink: 0;
transform: rotate(-90deg);
}
.context-ring__track,
.context-ring__fill {
fill: none;
stroke-width: 2.5px;
}
.context-ring__track {
stroke: color-mix(in srgb, currentColor 22%, transparent);
}
.context-ring__fill {
stroke: currentColor;
stroke-linecap: round;
}
.context-ring__pct {
font-variant-numeric: tabular-nums;
letter-spacing: 0.01em;
}
.context-usage__popover {
position: absolute;
right: 0;
bottom: calc(100% + 10px);
z-index: 70;
width: min(340px, calc(100vw - 42px));
padding: 16px;
border: 1px solid color-mix(in srgb, var(--border) 78%, transparent);
border-radius: var(--radius-lg);
background: color-mix(in srgb, var(--popover) 96%, var(--card));
color: var(--popover-foreground);
box-shadow: var(--shadow-lg);
animation: fade-in 150ms var(--ease-out);
}
.context-usage__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.context-usage__title,
.context-usage__section-label {
color: var(--muted);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.context-usage__context-value {
font-size: 13px;
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
.context-usage__bar {
height: 5px;
margin: 12px 0 15px;
overflow: hidden;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--muted) 22%, transparent);
}
.context-usage__bar span {
display: block;
height: 100%;
border-radius: inherit;
background: var(--ctx-color, var(--accent));
box-shadow: 0 0 12px color-mix(in srgb, var(--ctx-color, var(--accent)) 46%, transparent);
}
.context-usage__section-label {
padding-top: 14px;
border-top: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
}
.context-usage__plan-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-top: 14px;
}
.context-usage__plan-link {
display: inline-flex;
align-items: center;
gap: 6px;
color: var(--muted);
text-decoration: none;
transition: color 150ms ease-out;
}
.context-usage__plan-link:hover {
color: var(--text);
}
.context-usage__plan-link svg {
width: 12px;
height: 12px;
}
.context-usage__plan-badge {
color: var(--text);
font-size: 11px;
font-weight: 650;
letter-spacing: 0.02em;
text-transform: none;
}
.context-usage__account {
overflow: hidden;
margin-top: 4px;
color: var(--muted);
font-size: 12px;
text-overflow: ellipsis;
white-space: nowrap;
}
.context-usage__limits {
display: flex;
flex-direction: column;
gap: 11px;
margin-top: 12px;
}
.context-usage__limit-head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 12px;
}
.context-usage__limit-label {
overflow: hidden;
color: var(--text);
font-size: 12px;
font-weight: 550;
text-overflow: ellipsis;
white-space: nowrap;
}
.context-usage__limit-meta {
display: inline-flex;
align-items: baseline;
gap: 8px;
color: var(--muted);
font-size: 11px;
white-space: nowrap;
}
.context-usage__limit-meta strong {
color: var(--text);
font-size: 12px;
font-weight: 650;
font-variant-numeric: tabular-nums;
}
.context-usage__limit-bar {
height: 4px;
margin-top: 6px;
overflow: hidden;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--muted) 20%, transparent);
}
.context-usage__limit-bar span {
display: block;
height: 100%;
border-radius: inherit;
background: var(--accent);
}
.context-usage__limit-bar span.context-usage__limit-fill--warn {
background: var(--warn);
}
.context-usage__limit-bar span.context-usage__limit-fill--danger {
background: var(--danger);
}
.context-usage__stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
gap: 8px;
margin: 10px 0 0;
}
.context-usage__stats--cost {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.context-usage__stats div {
min-width: 0;
padding: 9px 10px;
border: 1px solid color-mix(in srgb, var(--border) 68%, transparent);
border-radius: var(--radius-sm);
background: color-mix(in srgb, var(--card) 72%, transparent);
}
.context-usage__stats dt {
color: var(--muted);
font-size: 10px;
font-weight: 650;
letter-spacing: 0.05em;
text-transform: uppercase;
}
.context-usage__stats dd {
margin: 4px 0 0;
overflow: hidden;
color: var(--text);
font-size: 14px;
font-weight: 700;
font-variant-numeric: tabular-nums;
text-overflow: ellipsis;
}
.context-usage__model {
display: block;
margin-top: 12px;
overflow: hidden;
color: var(--muted);
font-size: 11px;
text-overflow: ellipsis;
white-space: nowrap;
}
.context-usage__model + .context-usage__model {
margin-top: 6px;
}
.context-usage__model strong {
color: var(--text);
font-weight: 650;
}
.context-ring__action {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 5px;
height: 20px;
padding: 0 8px;
border-radius: var(--radius-full);
border: 1px solid color-mix(in srgb, currentColor 38%, transparent);
background: color-mix(in srgb, currentColor 12%, transparent);
color: currentColor;
font: inherit;
font-size: 11px;
line-height: 1;
transition:
background 150ms ease-out,
border-color 150ms ease-out,
opacity 150ms ease-out;
}
.context-ring__action:hover:not(:disabled) {
background: color-mix(in srgb, currentColor 18%, transparent);
border-color: color-mix(in srgb, currentColor 55%, transparent);
}
.context-ring__action:disabled {
cursor: not-allowed;
opacity: 0.65;
}
.context-ring__action svg {
width: 12px;
height: 12px;
flex-shrink: 0;
stroke: currentColor;
fill: none;
stroke-width: 1.7px;
stroke-linecap: round;
stroke-linejoin: round;
}
.context-ring__action--busy svg {
animation: compaction-spin 1s linear infinite;
}
.agent-chat__goal {
align-self: center;
display: flex;
flex-direction: column;
max-width: calc(100% - 20px);
min-width: 0;
margin: 0 auto 8px;
padding: 5px 8px 5px 12px;
color: color-mix(in srgb, var(--text) 82%, var(--muted));
background: color-mix(in srgb, var(--bg-elevated) 84%, transparent);
border: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
border-radius: var(--radius-lg);
font-size: 12px;
line-height: 1.25;
}
.agent-chat__goal-row {
display: flex;
align-items: center;
min-width: 0;
gap: 8px;
}
.agent-chat__goal-icon {
display: inline-flex;
flex-shrink: 0;
}
.agent-chat__goal-icon svg {
width: 14px;
height: 14px;
stroke: currentColor;
fill: none;
stroke-width: 1.7px;
stroke-linecap: round;
stroke-linejoin: round;
}
.agent-chat__goal-label,
.agent-chat__goal-objective {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.agent-chat__goal-label {
flex: 0 0 auto;
font-weight: 700;
}
.agent-chat__goal-objective {
flex: 1 1 auto;
color: var(--muted);
}
.agent-chat__goal-elapsed {
flex-shrink: 0;
color: var(--muted);
font-variant-numeric: tabular-nums;
}
.agent-chat__goal-actions {
display: flex;
align-items: center;
flex-shrink: 0;
gap: 2px;
}
.agent-chat__goal-action {
display: inline-flex;
align-items: center;
justify-content: center;
width: 22px;
height: 22px;
padding: 0;
color: var(--muted);
background: none;
border: none;
border-radius: var(--radius-sm);
}
.agent-chat__goal-action:hover {
color: var(--text);
background: color-mix(in srgb, var(--text) 10%, transparent);
}
.agent-chat__goal-action svg {
width: 13px;
height: 13px;
stroke: currentColor;
fill: none;
stroke-width: 1.7px;
stroke-linecap: round;
stroke-linejoin: round;
}
.agent-chat__goal-detail {
display: flex;
flex-direction: column;
gap: 4px;
margin-top: 6px;
padding: 6px 2px 3px;
border-top: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
color: var(--text);
}
.agent-chat__goal-detail-objective {
white-space: pre-wrap;
overflow-wrap: anywhere;
}
.agent-chat__goal-detail-note,
.agent-chat__goal-detail-meta {
color: var(--muted);
overflow-wrap: anywhere;
}
.agent-chat__goal--active {
color: var(--ok);
background: color-mix(in srgb, var(--ok) 9%, var(--card));
border-color: color-mix(in srgb, var(--ok) 28%, var(--border));
}
.agent-chat__goal--blocked,
.agent-chat__goal--budget_limited,
.agent-chat__goal--usage_limited {
color: var(--warn);
background: color-mix(in srgb, var(--warn) 10%, var(--card));
border-color: color-mix(in srgb, var(--warn) 30%, var(--border));
}
.agent-chat__goal--complete {
color: color-mix(in srgb, var(--ok) 72%, var(--text));
}
/* Image attachments preview */
.chat-attachments {
display: inline-flex;
flex-wrap: wrap;
gap: 8px;
padding: 8px;
background: var(--panel);
border-radius: var(--radius-md);
border: 1px solid var(--border);
width: fit-content;
max-width: 100%;
align-self: flex-start;
/* Don't stretch in flex column parent */
}
.chat-attachment {
position: relative;
width: 80px;
height: 80px;
border-radius: var(--radius-sm);
overflow: hidden;
border: 1px solid var(--border);
background: var(--bg);
}
.chat-attachment__img {
width: 100%;
height: 100%;
object-fit: contain;
}
.chat-attachment__remove {
position: absolute;
top: 4px;
right: 4px;
width: 24px;
height: 24px;
border-radius: 50%;
border: none;
background: rgba(0, 0, 0, 0.7);
color: #fff;
font-size: 12px;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity 150ms ease-out;
}
.chat-attachment:hover .chat-attachment__remove {
opacity: 1;
}
.chat-attachment__remove:hover {
background: color-mix(in srgb, var(--danger) 90%, black);
}
.chat-attachment__remove svg {
width: 12px;
height: 12px;
stroke: currentColor;
fill: none;
stroke-width: 2px;
}
/* Light theme attachment overrides */
:root[data-theme-mode="light"] .chat-attachments {
background: #f8fafc;
border-color: rgba(16, 24, 40, 0.1);
}
:root[data-theme-mode="light"] .chat-attachment {
border-color: rgba(16, 24, 40, 0.15);
background: #fff;
}
:root[data-theme-mode="light"] .chat-attachment__remove {
background: rgba(0, 0, 0, 0.6);
}
/* Message images (sent images displayed in chat) */
.chat-message-images {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 8px;
}
.chat-message-image-button {
display: inline-flex;
max-width: 100%;
padding: 0;
border: 0;
border-radius: var(--radius-md);
background: transparent;
cursor: zoom-in;
}
.chat-message-image-button:focus-visible {
outline: 2px solid var(--focus-ring);
outline-offset: 3px;
}
.chat-message-image {
width: auto;
max-width: min(100%, 300px);
height: auto;
max-height: 200px;
border-radius: var(--radius-md);
object-fit: contain;
transition: transform 150ms ease-out;
}
.chat-message-image-button:hover .chat-message-image {
transform: scale(1.02);
}
/* User message images align right */
.chat-group.user .chat-message-images {
justify-content: flex-end;
}
.chat-group.user.chat-group--peer .chat-message-images {
justify-content: flex-start;
}
.chat-assistant-attachments {
display: flex;
flex-direction: column;
gap: 10px;
margin-bottom: 8px;
}
.chat-assistant-attachments img.chat-message-image {
display: block;
}
.chat-assistant-attachment-card {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: color-mix(in srgb, var(--card) 82%, var(--bg));
}
.chat-assistant-attachment-card--audio,
.chat-assistant-attachment-card--video {
display: flex;
flex-direction: column;
align-items: stretch;
}
.chat-assistant-attachment-card--audio audio,
.chat-assistant-attachment-card--video video {
width: min(100%, 360px);
max-width: 100%;
}
.chat-assistant-attachment-card--video video {
border-radius: var(--radius-sm);
background: #000;
}
.chat-assistant-attachment-card__header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
margin-bottom: 8px;
}
.chat-assistant-attachment-card__title,
.chat-assistant-attachment-card__link {
color: var(--text);
font-size: 13px;
text-decoration: none;
word-break: break-word;
}
.chat-assistant-attachment-card__reason {
color: var(--muted);
font-size: 12px;
line-height: 1.4;
}
.chat-assistant-attachment-card__icon {
display: inline-flex;
width: 16px;
height: 16px;
color: var(--muted);
}
.chat-assistant-attachment-card__icon svg {
width: 16px;
height: 16px;
}
.chat-assistant-attachment-badge,
.chat-reply-pill {
display: inline-flex;
align-items: center;
gap: 6px;
width: fit-content;
max-width: 100%;
border-radius: 999px;
font-size: 12px;
}
.chat-assistant-attachment-badge {
padding: 3px 8px;
background: color-mix(in srgb, var(--accent) 14%, transparent);
color: var(--accent);
border: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
}
.chat-reply-pill {
margin-bottom: 8px;
padding: 5px 10px;
color: var(--muted);
border: 1px solid var(--border);
background: color-mix(in srgb, var(--bg) 70%, transparent);
}
.chat-reply-pill__icon {
display: inline-flex;
width: 14px;
height: 14px;
}
.chat-reply-pill__icon svg {
width: 14px;
height: 14px;
}
/* Reply preview bar above composer */
.chat-reply-preview {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 12px;
margin-bottom: 4px;
background: color-mix(in srgb, var(--accent) 8%, transparent);
border: 1px solid color-mix(in srgb, var(--accent) 20%, transparent);
border-radius: 8px;
font-size: 12px;
color: var(--muted);
}
.chat-reply-preview__icon {
display: inline-flex;
width: 16px;
height: 16px;
flex-shrink: 0;
}
.chat-reply-preview__icon svg {
width: 16px;
height: 16px;
}
.chat-reply-preview__label {
font-weight: 600;
flex-shrink: 0;
color: var(--accent);
}
.chat-reply-preview__text {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--text);
}
.chat-reply-preview__dismiss {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
padding: 0;
border: none;
background: none;
color: var(--muted);
border-radius: 4px;
flex-shrink: 0;
}
.chat-reply-preview__dismiss:hover {
color: var(--text);
background: color-mix(in srgb, var(--text) 10%, transparent);
}
.chat-reply-preview__dismiss svg {
width: 16px;
height: 16px;
stroke: currentColor;
fill: none;
stroke-width: 2px;
}
/* Right-click reply context menu */
.chat-reply-context-menu {
position: fixed;
z-index: 9999;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
padding: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
min-width: 160px;
}
.chat-reply-context-menu button {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
padding: 8px 12px;
border: none;
background: none;
color: var(--text);
border-radius: 6px;
text-align: left;
}
.chat-reply-context-menu button:hover,
.chat-reply-context-menu button:focus-visible {
background: color-mix(in srgb, var(--accent) 12%, transparent);
outline: none;
}
.chat-selection-popup {
position: fixed;
z-index: 9999;
display: flex;
gap: 2px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 8px;
padding: 3px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
animation: fade-in 0.12s var(--ease-out);
}
.chat-selection-popup button {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 10px;
border: none;
background: none;
color: var(--text);
border-radius: 6px;
font-size: 12px;
white-space: nowrap;
}
.chat-selection-popup button:hover,
.chat-selection-popup button:focus-visible {
background: color-mix(in srgb, var(--accent) 12%, transparent);
outline: none;
}
.chat-selection-popup button svg {
width: 14px;
height: 14px;
flex-shrink: 0;
color: var(--muted);
}
.agent-chat__composer-shell {
display: grid;
grid-template-columns: minmax(0, 1fr);
align-items: end;
gap: 6px;
width: calc(100% - 36px);
max-width: var(--chat-thread-max-width, 48rem);
margin: 8px auto 14px;
}
.task-suggestions {
display: grid;
gap: 8px;
max-height: min(40vh, 24rem);
overflow-y: auto;
overscroll-behavior: contain;
padding: 0 14px 10px;
}
.session-suggestions {
display: flex;
flex-direction: column;
gap: 6px;
padding: 0 16px 8px;
}
.session-suggestion {
display: grid;
grid-template-columns: auto minmax(0, 1fr) auto;
align-items: center;
gap: 10px;
min-height: 38px;
padding: 6px 8px;
border: 1px solid var(--border);
border-radius: 10px;
background: color-mix(in srgb, var(--panel-strong) 74%, transparent);
}
.session-suggestion__author,
.session-suggestion__state {
border-radius: 999px;
padding: 3px 8px;
font-size: 11px;
font-weight: 600;
white-space: nowrap;
}
.session-suggestion__author {
color: var(--text-strong);
background: var(--panel-hover);
}
.session-suggestion__state {
color: var(--muted);
}
.session-suggestion__text {
max-height: 12rem;
overflow: auto;
overflow-wrap: anywhere;
color: var(--text);
font-size: 13px;
white-space: pre-wrap;
}
.session-suggestion__actions {
display: flex;
align-items: center;
gap: 2px;
}
.session-suggestion__action {
width: 28px;
height: 28px;
}
.session-suggestion__action svg {
width: 15px;
height: 15px;
}
.agent-chat__typing-indicator {
padding: 0 4px 4px;
color: var(--muted);
font-size: 11px;
font-style: italic;
}
@media (max-width: 640px) {
.session-suggestion {
grid-template-columns: auto minmax(0, 1fr);
}
.session-suggestion__actions,
.session-suggestion__state {
grid-column: 1 / -1;
justify-self: end;
}
}
.task-suggestion {
display: flex;
align-items: flex-start;
gap: 12px;
padding: 12px;
border: 1px solid color-mix(in srgb, var(--accent) 32%, var(--border));
border-radius: 12px;
background: color-mix(in srgb, var(--accent) 7%, var(--panel));
}
.task-suggestion__icon {
display: grid;
width: 32px;
height: 32px;
flex: 0 0 32px;
place-items: center;
border-radius: 10px;
color: var(--accent);
background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.task-suggestion__icon svg,
.task-suggestion__start svg {
width: 16px;
height: 16px;
}
.task-suggestion__body {
min-width: 0;
flex: 1;
}
.task-suggestion__eyebrow {
color: var(--accent);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.task-suggestion__title {
margin-top: 2px;
color: var(--text);
font-weight: 650;
}
.task-suggestion__summary {
margin-top: 3px;
color: var(--muted);
font-size: 13px;
line-height: 1.35;
}
.task-suggestion__details {
display: grid;
gap: 7px;
margin-top: 10px;
}
.task-suggestion__detail {
display: grid;
grid-template-columns: 78px minmax(0, 1fr);
gap: 8px;
align-items: start;
color: var(--muted);
font-size: 11px;
}
.task-suggestion__detail > span {
padding-top: 3px;
font-weight: 650;
letter-spacing: 0.03em;
text-transform: uppercase;
}
.task-suggestion__detail code,
.task-suggestion__detail pre {
min-width: 0;
max-height: 9rem;
margin: 0;
padding: 5px 7px;
overflow: auto;
border: 1px solid var(--border);
border-radius: 6px;
background: color-mix(in srgb, var(--bg) 70%, transparent);
color: var(--text);
font: 11px/1.4 var(--font-mono);
white-space: pre-wrap;
overflow-wrap: anywhere;
}
.task-suggestion__actions {
display: flex;
align-items: center;
gap: 6px;
}
.task-suggestion__start {
display: inline-flex;
align-items: center;
gap: 6px;
white-space: nowrap;
}
@media (max-width: 640px) {
.task-suggestion {
align-items: flex-start;
flex-wrap: wrap;
}
.task-suggestion__actions {
width: 100%;
justify-content: flex-end;
padding-left: 44px;
}
.task-suggestion__detail {
grid-template-columns: minmax(0, 1fr);
gap: 3px;
}
}
.chat-swarm {
display: grid;
gap: 6px;
width: calc(100% - 36px);
max-width: var(--chat-thread-max-width, 48rem);
/* Completed phases stay visible while any child runs; bound large swarms so
their retained dots cannot displace the composer. */
max-height: clamp(160px, 32vh, 260px);
margin: 0 auto;
padding: 0 2px 8px 0;
overflow-y: auto;
overscroll-behavior: contain;
}
.chat-swarm__group {
display: grid;
gap: 6px;
padding: 8px 10px;
border: 1px solid color-mix(in srgb, var(--accent) 18%, var(--border));
border-radius: 10px;
background: color-mix(in srgb, var(--accent) 3%, var(--panel));
box-shadow: 0 6px 20px color-mix(in srgb, var(--accent) 5%, transparent);
}
.chat-swarm__header {
display: flex;
align-items: baseline;
gap: 8px;
min-width: 0;
}
.chat-swarm__header strong {
overflow: hidden;
color: var(--text);
font-size: 12px;
text-overflow: ellipsis;
white-space: nowrap;
}
.chat-swarm__header span,
.chat-swarm__narrator,
.chat-swarm__phase {
color: var(--muted);
font-size: 10px;
}
.chat-swarm__narrator {
overflow: hidden;
line-height: 1.35;
text-overflow: ellipsis;
white-space: nowrap;
}
.chat-swarm__phase-row {
display: grid;
grid-template-columns: minmax(56px, auto) 1fr;
align-items: center;
gap: 8px;
}
.chat-swarm__phase {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.chat-swarm__dots {
display: flex;
flex-wrap: wrap;
gap: 6px;
}
.chat-swarm__dot {
width: 9px;
height: 9px;
border-radius: 50%;
background: var(--muted);
}
.chat-swarm__dot--queued {
border: 1px solid var(--muted);
background: transparent;
}
.chat-swarm__dot--running {
animation: chat-swarm-pulse 1.25s ease-in-out infinite;
background: var(--accent);
}
.chat-swarm__dot--done {
background: var(--ok);
}
.chat-swarm__dot--failed {
border-radius: 3px;
background: var(--danger);
transform: rotate(45deg) scale(0.82);
}
.chat-swarm__more {
color: var(--muted);
font-size: 10px;
line-height: 9px;
}
@keyframes chat-swarm-pulse {
50% {
box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 25%, transparent);
opacity: 0.55;
}
}
@media (prefers-reduced-motion: reduce) {
.chat-swarm__dot--running {
animation: none;
}
}
.chat-prs {
display: grid;
gap: 6px;
/* Mirror .agent-chat__composer-shell sizing: the rows belong to the input
stack and must not read as a full-pane banner above a narrower composer. */
width: calc(100% - 36px);
max-width: var(--chat-thread-max-width, 48rem);
margin: 0 auto;
padding: 0 0 8px;
}
.chat-pr {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
padding: 7px 10px;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--panel);
font-size: 13px;
}
.chat-pr[data-state="merged"] {
border-color: color-mix(in srgb, #a78bfa 32%, var(--border));
background: color-mix(in srgb, #a78bfa 7%, var(--panel));
}
.chat-pr__link {
display: flex;
flex: 1;
align-items: center;
gap: 8px;
min-width: 0;
color: var(--text);
text-decoration: none;
}
.chat-pr__link:hover .chat-pr__number {
text-decoration: underline;
}
.chat-pr__icon {
display: grid;
flex: 0 0 auto;
place-items: center;
color: var(--ok);
}
.chat-pr[data-state="draft"] .chat-pr__icon {
color: var(--muted);
}
.chat-pr[data-state="closed"] .chat-pr__icon {
color: var(--danger);
}
.chat-pr[data-state="merged"] .chat-pr__icon {
color: #a78bfa;
}
:root[data-theme-mode="light"] .chat-pr[data-state="merged"] .chat-pr__icon {
color: #7c3aed;
}
.chat-pr[data-state="branch"] .chat-pr__icon {
color: var(--muted);
}
.chat-pr__link--static {
cursor: default;
}
.chat-pr__icon svg,
.chat-pr__warning svg {
width: 15px;
height: 15px;
}
.chat-pr__icon svg,
.chat-pr__warning svg,
.chat-pr__dismiss svg {
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.chat-pr__number {
flex: 0 0 auto;
font-weight: 650;
}
.chat-pr__repo {
flex: 0 0 auto;
color: var(--muted);
}
.chat-pr__branch {
min-width: 0;
overflow: hidden;
color: var(--muted);
font: 12px/1.4 var(--font-mono);
text-overflow: ellipsis;
white-space: nowrap;
}
.chat-pr__meta {
display: flex;
flex: 0 0 auto;
align-items: center;
gap: 8px;
}
.chat-pr__diff {
display: inline-flex;
gap: 5px;
font: 12px/1.4 var(--font-mono);
}
.chat-pr__additions {
color: var(--ok);
}
.chat-pr__deletions {
color: var(--danger);
}
.chat-pr__checks {
position: relative;
color: var(--muted);
}
.chat-pr__checks[data-checks="passing"] {
color: var(--ok);
}
.chat-pr__checks[data-checks="pending"] {
color: var(--warn);
}
.chat-pr__checks[data-checks="failing"] {
color: var(--danger);
}
.chat-pr__checks-pill {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 2px 8px;
border-radius: var(--radius-full);
background: color-mix(in srgb, currentColor 12%, transparent);
cursor: pointer;
font-size: 12px;
font-weight: 600;
list-style: none;
user-select: none;
}
.chat-pr__checks-pill::-webkit-details-marker {
display: none;
}
.chat-pr__checks-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: currentColor;
}
.chat-pr__checks-menu {
position: absolute;
z-index: 30;
right: 0;
bottom: calc(100% + 8px);
min-width: 200px;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 12px;
background: var(--panel);
box-shadow: var(--shadow-md, 0 8px 24px rgb(0 0 0 / 0.18));
color: var(--text);
font-size: 13px;
font-weight: 500;
}
.chat-pr__checks-menu-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 6px;
color: var(--muted);
font-size: 12px;
}
.chat-pr__checks-menu-header a {
display: grid;
place-items: center;
color: var(--muted);
}
.chat-pr__checks-menu-header a:hover {
color: var(--text);
}
.chat-pr__checks-menu-header svg {
width: 14px;
height: 14px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.chat-pr__checks-row {
display: flex;
align-items: center;
gap: 8px;
padding: 3px 0;
}
.chat-pr__checks-row-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: currentColor;
}
.chat-pr__checks-row--passed .chat-pr__checks-row-dot {
background: var(--ok);
}
.chat-pr__checks-row--failed .chat-pr__checks-row-dot {
background: var(--danger);
}
.chat-pr__checks-row--running .chat-pr__checks-row-dot {
background: var(--warn);
}
.chat-pr__checks-row--skipped .chat-pr__checks-row-dot {
background: var(--muted);
}
.chat-pr__checks-row-label {
flex: 1;
}
.chat-pr__checks-row-count {
color: var(--muted);
font-variant-numeric: tabular-nums;
}
.chat-pr__state {
color: var(--muted);
font-weight: 600;
}
.chat-pr[data-state="merged"] .chat-pr__state {
color: #a78bfa;
}
:root[data-theme-mode="light"] .chat-pr[data-state="merged"] .chat-pr__state {
color: #7c3aed;
}
.chat-pr__warning {
display: grid;
place-items: center;
color: var(--warn);
}
.chat-pr__create {
flex: 0 0 auto;
padding: 3px 10px;
border: 1px solid var(--border);
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--accent) 12%, transparent);
color: var(--text);
font-size: 12px;
font-weight: 600;
text-decoration: none;
white-space: nowrap;
}
.chat-pr__create:hover {
background: color-mix(in srgb, var(--accent) 22%, transparent);
}
.chat-pr__dismiss {
display: grid;
padding: 2px;
place-items: center;
border: none;
background: none;
color: var(--muted);
cursor: pointer;
}
.chat-pr__dismiss:hover {
color: var(--text);
}
.chat-pr__dismiss svg {
width: 14px;
height: 14px;
}
.chat-prs__more {
justify-self: start;
padding: 2px 10px;
border: none;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--muted) 14%, transparent);
color: var(--muted);
cursor: pointer;
font-size: 12px;
font-weight: 600;
}
.chat-prs__more:hover {
color: var(--text);
}
@media (max-width: 640px) {
.chat-pr__branch,
.chat-pr__repo {
display: none;
}
}
.agent-chat__input {
--chat-box-inset: 8px;
position: relative;
display: flex;
flex-direction: column;
min-width: 0;
margin: 0;
padding: 0;
background: var(--card);
border: 1px solid var(--border);
border-radius: var(--radius-md);
box-shadow: var(--shadow-sm);
flex-shrink: 0;
transition:
border-color var(--duration-fast) ease,
box-shadow var(--duration-fast) ease;
}
.agent-chat__input:focus-within {
border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
box-shadow: 0 0 0 3px var(--accent-subtle);
}
.agent-chat__input--offline,
.agent-chat__input--offline:focus-within {
border-color: color-mix(in srgb, var(--warn) 38%, var(--border));
box-shadow: 0 0 0 2px color-mix(in srgb, var(--warn) 10%, transparent);
}
.agent-chat__offline-hint {
padding: 5px var(--chat-box-inset);
border-bottom: 1px solid color-mix(in srgb, var(--warn) 22%, transparent);
background: color-mix(in srgb, var(--warn) 7%, transparent);
color: color-mix(in srgb, var(--warn) 72%, var(--text));
font-size: 11px;
line-height: 1.3;
}
@supports (backdrop-filter: blur(1px)) {
.agent-chat__input {
backdrop-filter: blur(12px) saturate(1.6);
-webkit-backdrop-filter: blur(12px) saturate(1.6);
}
}
.agent-chat__composer-combobox {
position: relative;
display: flex;
flex-direction: column;
flex: 1 1 auto;
min-width: 0;
}
.agent-chat__sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.agent-chat__composer-combobox > :is(textarea, input) {
width: 100%;
min-height: 36px;
max-height: calc(7em + 24px);
resize: none;
padding: var(--chat-box-inset);
padding-left: calc(var(--chat-box-inset) - 4px);
border: none;
background: transparent;
color: var(--text);
font-size: var(--control-ui-text-md);
font-family: inherit;
line-height: 1.4;
outline: none;
box-sizing: border-box;
}
.agent-chat__composer-combobox > :is(textarea, input):focus-visible {
box-shadow: none;
}
.agent-chat__composer-combobox > :is(textarea, input)::placeholder {
color: var(--muted);
}
/* One ellipsized line while empty: long agent names otherwise wrap the
placeholder, grow the box, and surface the overlay scrollbar as a stray
gray pill. On the control (not ::placeholder) so Firefox honors it too;
typing unsets :placeholder-shown, restoring normal wrapping. */
.agent-chat__composer-combobox > :is(textarea, input):placeholder-shown {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@media (hover: none) and (pointer: coarse) {
.agent-chat__composer-combobox > :is(textarea, input) {
font-size: var(--control-ui-input-text-size);
}
}
.agent-chat__composer-status-stack {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 6px;
padding: 8px 10px 0;
}
.agent-chat__composer-status-stack:not(
:has(.compaction-indicator, .fallback-indicator, .agent-chat__goal)
) {
display: none;
}
.agent-chat__composer-status-stack .compaction-indicator,
.agent-chat__composer-status-stack .fallback-indicator,
.agent-chat__composer-status-stack .agent-chat__goal {
margin: 0;
}
/* Keep settings, split view, and run status together while the model picker
uses the remaining footer space. */
.agent-chat__composer-controls {
display: flex;
position: relative;
align-items: center;
justify-content: flex-start;
gap: 6px;
flex: 1 1 auto;
width: auto;
min-width: 0;
margin-left: 0;
padding: 0;
}
.agent-chat__composer-run-status {
display: inline-flex;
order: 2;
flex: 0 0 auto;
align-items: center;
}
.agent-chat__composer-controls .chat-composer-model-control {
order: 3;
}
.agent-chat__composer-run-status .agent-chat__run-status {
max-width: min(240px, 30vw);
}
.agent-chat__composer-session {
min-width: 0;
flex: 1 1 260px;
}
.agent-chat__composer-controls .chat-controls {
display: flex;
justify-content: flex-end;
gap: 6px;
min-width: 0;
margin: 0;
}
.agent-chat__composer-controls .chat-controls__session-row {
min-width: 0;
}
.agent-chat__composer-controls .chat-controls__actions {
flex-wrap: wrap;
justify-content: flex-end;
}
.chat-view-menu-wrapper {
position: relative;
display: inline-flex;
align-items: center;
margin-left: 0;
min-width: 0;
order: 0;
}
.chat-composer-model-control {
display: inline-flex;
flex: 0 0 auto;
min-width: 0;
max-width: 70vw;
margin-left: auto;
order: 3;
}
.chat-composer-model-control .chat-controls__model {
width: 100%;
}
.chat-view-menu-trigger {
display: inline-flex;
align-items: center;
justify-content: center;
flex: 0 0 auto;
width: 36px;
min-width: 36px;
height: 36px;
padding: 0;
border: none;
border-radius: var(--radius-sm);
background: transparent;
color: var(--muted);
transition:
background var(--duration-fast) ease,
color var(--duration-fast) ease;
}
.chat-view-menu-trigger:hover,
.chat-view-menu-trigger--open {
background: color-mix(in srgb, var(--text) 7%, transparent);
color: var(--text);
}
.chat-view-menu-trigger svg {
width: 18px;
height: 18px;
stroke: currentColor;
fill: none;
stroke-width: 1.7px;
stroke-linecap: round;
stroke-linejoin: round;
}
.chat-view-menu {
display: inline-flex;
z-index: 60;
}
.chat-view-menu::part(menu) {
min-width: 200px;
padding: 6px;
border: 1px solid color-mix(in srgb, var(--border) 78%, transparent);
border-radius: var(--radius-md);
background: color-mix(in srgb, var(--bg-elevated) 94%, var(--card));
box-shadow: var(--shadow-lg);
}
.chat-view-menu__item {
color: var(--text);
font-size: 13px;
text-align: left;
}
.chat-view-menu__check {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
flex: 0 0 auto;
}
.chat-view-menu__check svg {
width: 14px;
height: 14px;
stroke: currentColor;
fill: none;
stroke-width: 2px;
}
.chat-view-menu__text {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.agent-chat__stt-interim {
padding: 10px 14px 0;
color: var(--muted);
font-size: var(--control-ui-text-sm);
line-height: 1.35;
overflow-wrap: anywhere;
}
.agent-chat__composer-input-row {
display: flex;
align-items: flex-end;
gap: 4px;
min-width: 0;
padding: var(--chat-box-inset);
}
.agent-chat__disabled-reason {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-3);
padding: 8px var(--chat-box-inset) 0;
color: var(--muted);
font-size: var(--control-ui-text-sm);
line-height: 1.4;
}
.agent-chat__disabled-banner {
width: 100%;
box-sizing: border-box;
}
.agent-chat__disabled-banner .btn {
flex: 0 0 auto;
}
.agent-chat__composer-footer {
display: flex;
align-items: center;
justify-content: flex-start;
flex-shrink: 0;
box-sizing: border-box;
gap: 8px;
min-height: 44px;
border-top: 1px solid color-mix(in srgb, var(--border) 64%, transparent);
/* Split the inset evenly so the settings chip sits centered between the
divider and the card edge instead of hugging the divider. */
padding: calc(var(--chat-box-inset) / 2) var(--chat-box-inset);
}
.agent-chat__composer-meta,
.agent-chat__toolbar-right {
display: flex;
align-items: center;
gap: 4px;
}
.agent-chat__composer-meta {
flex: 0 0 auto;
min-width: 0;
}
.agent-chat__composer-actions {
display: flex;
align-items: center;
gap: 4px;
flex: 0 0 auto;
}
.agent-chat__input-btn,
.agent-chat__toolbar-right .btn--ghost {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
min-width: 36px;
height: 36px;
border-radius: var(--radius-sm);
border: none;
background: transparent;
color: var(--muted);
flex-shrink: 0;
padding: 0 10px;
transition: all var(--duration-fast) ease;
}
.agent-chat__input-btn svg,
.agent-chat__toolbar-right .btn--ghost svg {
width: 18px;
height: 18px;
fill: none;
stroke: currentColor;
stroke-width: 1.5px;
stroke-linecap: round;
stroke-linejoin: round;
}
.agent-chat__control-label {
display: none;
}
.agent-chat__input-btn:hover:not(:disabled),
.agent-chat__toolbar-right .btn--ghost:hover:not(:disabled) {
color: var(--text);
background: var(--bg-hover);
}
.agent-chat__input-btn:disabled,
.agent-chat__toolbar-right .btn--ghost:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.agent-chat__attach-menu {
display: flex;
align-items: center;
position: relative;
flex: 0 0 auto;
}
.agent-chat__attach-menu > button:disabled {
opacity: 0.4;
cursor: not-allowed;
}
.agent-chat__attach-menu[open] > button {
color: var(--text);
background: var(--bg-hover);
}
.agent-chat__attach-menu::part(menu) {
width: 152px;
padding: 5px;
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--bg-elevated);
box-shadow: var(--shadow-lg);
}
.agent-chat__attach-menu-option {
color: var(--text);
font-size: 12px;
}
.agent-chat__attach-menu-option svg {
width: 16px;
height: 16px;
flex: 0 0 16px;
fill: none;
stroke: currentColor;
stroke-width: 1.5px;
stroke-linecap: round;
stroke-linejoin: round;
}
/* Selected/open states stay a quiet neutral wash; only live recording gets a
(soft) danger tint so "active" chrome never competes with the send button. */
.agent-chat__input-btn--active,
.agent-chat__input-btn--open {
color: var(--text);
background: color-mix(in srgb, var(--text) 7%, transparent);
}
.agent-chat__input-btn--talk {
color: var(--danger, #ef4444);
background: color-mix(in srgb, var(--danger, #ef4444) 9%, transparent);
}
.agent-chat__talk-status {
display: flex;
align-items: center;
gap: 8px;
color: var(--text);
}
.agent-chat__talk-status-text {
min-width: 0;
flex: 1;
}
/* Bars-only meter; the stop-voice pill button supplies the chrome around it. */
.agent-chat__voice-activity {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 3px;
height: 20px;
}
.agent-chat__voice-activity-bar {
position: relative;
width: 3px;
height: 18px;
flex: 0 0 3px;
border-radius: 999px;
background: color-mix(in srgb, var(--accent) 88%, var(--text));
box-shadow: 0 0 5px color-mix(in srgb, var(--accent) 30%, transparent);
opacity: 0.9;
transform: scaleY(var(--talk-bar-scale, 0.18));
transform-origin: center;
transition:
transform 90ms linear,
opacity var(--duration-fast) ease;
}
.agent-chat__voice-activity[data-status="connecting"] .agent-chat__voice-activity-bar {
animation: agent-chat-voice-connecting 1.05s ease-in-out infinite;
animation-delay: var(--talk-bar-delay);
}
.agent-chat__voice-activity[data-status="thinking"] .agent-chat__voice-activity-bar {
animation: agent-chat-voice-thinking 0.9s ease-in-out infinite;
animation-delay: var(--talk-bar-delay);
}
@keyframes agent-chat-voice-connecting {
0%,
100% {
opacity: 0.42;
transform: scaleY(0.2);
}
50% {
opacity: 0.9;
transform: scaleY(0.58);
}
}
@keyframes agent-chat-voice-thinking {
0%,
100% {
opacity: 0.4;
transform: scaleY(0.24);
}
45% {
opacity: 1;
transform: scaleY(0.92);
}
}
@media (prefers-reduced-motion: reduce) {
.agent-chat__voice-activity-bar {
animation: none !important;
opacity: 0.78;
transform: scaleY(0.38);
transition: none !important;
}
.agent-chat__voice-activity[data-status="connecting"] .agent-chat__voice-activity-bar {
opacity: 0.48;
transform: scaleY(0.18);
}
.agent-chat__voice-activity[data-status="connecting"]
.agent-chat__voice-activity-bar:nth-child(4) {
opacity: 0.9;
transform: scaleY(0.56);
}
.agent-chat__voice-activity[data-status="thinking"] .agent-chat__voice-activity-bar:nth-child(3),
.agent-chat__voice-activity[data-status="thinking"] .agent-chat__voice-activity-bar:nth-child(4),
.agent-chat__voice-activity[data-status="thinking"] .agent-chat__voice-activity-bar:nth-child(5) {
transform: scaleY(0.72);
}
.chat-send-btn--voice-live::after {
animation: none !important;
opacity: 0.45;
}
.chat-send-btn--voice-live .agent-chat__voice-activity,
.chat-send-btn__voice-stop-glyph {
transition: none !important;
}
}
.agent-chat__voice-turns {
display: flex;
flex-direction: column;
gap: 8px;
padding: 0 4px 8px;
background: transparent;
}
/* Flex row, not grid: WebKit (Mac/iOS WKWebView) never re-runs shrink-to-fit
intrinsic sizing for a grid flex-item while streamed transcript text grows,
freezing the turn at first-delta width and wrapping one character per line. */
.agent-chat__voice-turn {
display: flex;
gap: 8px;
align-items: baseline;
max-width: min(100%, 780px);
padding: 8px 10px;
border: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
border-radius: 8px;
background: color-mix(in srgb, var(--bg) 82%, transparent);
}
.agent-chat__voice-turn--user {
align-self: flex-end;
background: color-mix(in srgb, var(--accent) 10%, var(--bg));
}
.agent-chat__voice-turn--assistant {
align-self: flex-start;
}
.agent-chat__voice-turn-speaker {
flex: 0 0 auto;
min-width: 56px;
max-width: 200px;
overflow: hidden;
color: var(--muted);
font-size: 12px;
font-weight: 700;
text-overflow: ellipsis;
white-space: nowrap;
}
.agent-chat__voice-turn-text {
flex: 1 1 auto;
min-width: 0;
overflow-wrap: anywhere;
color: var(--text);
font-size: 13px;
line-height: 1.45;
white-space: pre-wrap;
}
.agent-chat__voice-turn-stream {
flex: 0 0 auto;
width: 6px;
height: 6px;
border-radius: 999px;
background: var(--accent);
opacity: 0.7;
}
.agent-chat__input-divider {
width: 1px;
height: 16px;
background: var(--border);
margin: 0 4px;
}
.agent-chat__token-row {
display: flex;
align-items: center;
justify-content: flex-end;
flex: 0 0 16px;
box-sizing: border-box;
min-height: 16px;
padding: 0 var(--chat-box-inset) 2px;
}
.agent-chat__token-count {
font-size: 0.7rem;
line-height: 1;
color: var(--muted);
white-space: nowrap;
font-variant-numeric: tabular-nums;
pointer-events: none;
}
.agent-chat__run-status {
display: inline-flex;
align-items: center;
gap: 6px;
height: 24px;
max-width: 132px;
padding: 0 2px;
color: var(--muted);
font-size: 0.72rem;
line-height: 1;
white-space: nowrap;
overflow: hidden;
flex-shrink: 0;
user-select: none;
}
.agent-chat__run-status svg {
width: 13px;
height: 13px;
stroke: currentColor;
fill: none;
stroke-width: 1.6px;
stroke-linecap: round;
stroke-linejoin: round;
flex-shrink: 0;
}
.agent-chat__run-status-label {
overflow: hidden;
text-overflow: ellipsis;
}
/* Interrupted is the only visible composer run status: killed runs leave no
transcript marker, so silence would read as "finished". Working/Done are
covered by the thread spark, content arriving, and Stop reverting. */
.agent-chat__run-status--interrupted {
color: var(--warn);
}
@keyframes chat-run-status-spin {
to {
transform: rotate(360deg);
}
}
/* Send is the primary action of the whole surface, so it gets the same solid
accent treatment as .btn.primary; variants (--stop, --voice*) override the
fill instead of reintroducing borders. */
.chat-send-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
min-width: 36px;
width: 36px;
height: 36px;
border-radius: var(--radius-full);
border: none;
background: var(--primary);
color: var(--primary-foreground);
box-shadow: 0 1px 3px var(--accent-subtle);
flex-shrink: 0;
transition:
background var(--duration-fast) ease,
color var(--duration-fast) ease,
box-shadow var(--duration-fast) ease,
opacity var(--duration-fast) ease;
padding: 0;
}
@media (max-width: 860px) {
.agent-chat__input-btn,
.agent-chat__toolbar-right .btn--ghost {
width: 36px;
min-width: 36px;
padding: 0;
}
.agent-chat__control-label {
display: none;
}
}
.chat-send-btn svg {
width: 18px;
height: 18px;
stroke: currentColor;
fill: none;
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
}
.chat-send-btn:hover:not(:disabled) {
background: var(--accent-hover);
box-shadow: 0 2px 12px var(--accent-glow);
}
:root[data-theme="dark"] .chat-send-btn:hover:not(:disabled) {
background: var(--primary-hover);
}
:root[data-theme="openknot"] .chat-send-btn:hover:not(:disabled) {
background: var(--primary-hover);
}
/* Outline (not box-shadow) so the hover rules' higher-specificity box-shadow
overrides can never swallow the keyboard focus indicator. */
.chat-send-btn:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
/* Muted fill (not a ghost outline) while there is nothing to send, so the
accent fill itself signals "ready". */
.chat-send-btn:disabled {
background: color-mix(in srgb, var(--muted) 16%, transparent);
color: var(--muted);
box-shadow: none;
opacity: 0.8;
cursor: not-allowed;
}
/* Idle voice fill stays muted so the idle -> hover -> recording progression
escalates (10% -> 18% -> live meter + breathing glow); a full-strength idle
fill makes recording state indistinguishable at a glance. */
.chat-send-btn--voice {
background: color-mix(in srgb, var(--accent) 10%, transparent);
color: var(--accent);
box-shadow: none;
}
.chat-send-btn--voice:hover:not(:disabled) {
background: color-mix(in srgb, var(--accent) 18%, transparent);
box-shadow: none;
}
.chat-talk-control {
display: inline-flex;
align-items: center;
flex: 0 0 auto;
}
.chat-talk-control > openclaw-tooltip {
display: inline-flex;
}
.chat-talk-control .chat-send-btn {
border-radius: var(--radius-full) 0 0 var(--radius-full);
}
/* Stretch instead of a fixed height so the picker always matches the voice
button, including the 44px mobile bump in layout.mobile.css. */
.chat-talk-input-picker {
display: inline-flex;
align-self: stretch;
}
.chat-talk-input-picker__trigger {
display: inline-flex;
align-items: center;
justify-content: center;
width: 20px;
min-width: 20px;
height: 100%;
padding: 0;
border: 0;
border-left: 1px solid color-mix(in srgb, var(--accent) 24%, transparent);
border-radius: 0 var(--radius-full) var(--radius-full) 0;
background: color-mix(in srgb, var(--accent) 10%, transparent);
color: var(--accent);
transition: background var(--duration-fast) ease;
}
.chat-talk-control--active .chat-talk-input-picker__trigger {
background: color-mix(in srgb, var(--accent) 14%, transparent);
}
.chat-talk-input-picker__trigger:hover,
.chat-talk-input-picker[open] .chat-talk-input-picker__trigger {
background: color-mix(in srgb, var(--accent) 20%, transparent);
}
.chat-talk-input-picker__trigger:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
.chat-talk-input-picker__trigger svg {
width: 12px;
height: 12px;
fill: none;
stroke: currentColor;
stroke-width: 2px;
}
.chat-talk-input-picker[open] .chat-talk-input-picker__trigger svg {
transform: rotate(180deg);
}
.chat-talk-input-picker::part(menu) {
width: min(300px, calc(100vw - 24px));
padding: 6px;
border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
border-radius: var(--radius-md);
background: color-mix(in srgb, var(--bg-elevated) 96%, var(--card));
box-shadow: var(--shadow-md);
}
.chat-talk-input-picker__heading {
padding: 6px 9px 5px;
color: var(--text-strong);
font-size: 12px;
font-weight: 700;
}
.chat-talk-input-picker__item {
color: var(--text);
font-size: 13px;
}
.chat-talk-input-picker__label {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.chat-talk-input-picker__check {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
color: var(--accent);
}
.chat-talk-input-picker__check svg {
width: 14px;
height: 14px;
fill: none;
stroke: currentColor;
stroke-width: 2px;
}
.chat-talk-input-picker__note,
.chat-talk-input-picker__warning,
.chat-talk-input-picker__hint {
padding: 5px 9px;
color: var(--muted);
font-size: 11px;
line-height: 1.35;
}
.chat-talk-input-picker__warning {
color: var(--warn);
}
.chat-talk-input-picker__hint {
margin-top: 3px;
border-top: 1px solid color-mix(in srgb, var(--border) 65%, transparent);
padding-top: 8px;
}
.chat-send-btn--hold-enabled {
touch-action: none;
-webkit-touch-callout: none;
user-select: none;
}
.chat-send-btn--dictating {
width: auto;
min-width: 76px;
gap: 8px;
padding: 0 12px;
border-radius: var(--radius-full);
color: var(--danger, #ef4444);
background: color-mix(in srgb, var(--danger, #ef4444) 14%, transparent);
box-shadow: 0 0 16px color-mix(in srgb, var(--danger, #ef4444) 24%, transparent);
touch-action: none;
-webkit-touch-callout: none;
user-select: none;
}
.chat-send-btn--dictating .agent-chat__voice-activity-bar {
background: color-mix(in srgb, var(--danger, #ef4444) 88%, var(--text));
box-shadow: 0 0 5px color-mix(in srgb, var(--danger, #ef4444) 30%, transparent);
}
.chat-send-btn__dictation-time {
min-width: 3ch;
font-size: 11px;
font-variant-numeric: tabular-nums;
}
.agent-chat__dictation-status {
display: flex;
min-width: 0;
align-items: center;
gap: 8px;
color: var(--danger, #ef4444);
font-size: 12px;
}
.agent-chat__dictation-status--finalizing {
color: var(--muted);
}
.agent-chat__dictation-label {
flex: 0 0 auto;
font-variant-numeric: tabular-nums;
}
.agent-chat__dictation-partial {
min-width: 0;
overflow: hidden;
color: var(--muted);
text-overflow: ellipsis;
white-space: nowrap;
}
.agent-chat__video-preview {
position: relative;
align-self: flex-end;
width: min(240px, 45vw);
margin: 4px 8px 0;
overflow: hidden;
border: 1px solid color-mix(in srgb, var(--border) 80%, transparent);
border-radius: var(--radius-lg);
background: #000;
box-shadow: var(--shadow-md);
}
.agent-chat__video-preview video {
display: block;
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}
.agent-chat__video-preview video.agent-chat__video-preview-mirrored {
transform: scaleX(-1);
}
.agent-chat__video-preview-switch-tooltip {
position: absolute;
top: 8px;
right: 8px;
}
.agent-chat__video-preview-switch {
display: grid;
width: 34px;
height: 34px;
padding: 7px;
border: 1px solid color-mix(in srgb, white 28%, transparent);
border-radius: var(--radius-full);
background: color-mix(in srgb, #000 68%, transparent);
color: white;
cursor: pointer;
place-items: center;
backdrop-filter: blur(8px);
}
.agent-chat__video-preview-switch:hover:not(:disabled) {
background: color-mix(in srgb, #000 82%, transparent);
}
.agent-chat__video-preview-switch:disabled {
cursor: wait;
opacity: 0.6;
}
.agent-chat__video-preview-switch svg {
width: 100%;
height: 100%;
}
/* Live voice input: the level meter itself is the control. Keeping it accent
(vs the danger stop square) is what disambiguates the two controls when a
run is abortable while recording; the stop glyph only crossfades in on
hover/focus so the resting state stays a pure waveform. */
.chat-send-btn--voice-live {
position: relative;
width: auto;
min-width: 64px;
padding: 0 14px;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--accent) 14%, transparent);
color: var(--accent);
box-shadow: none;
}
.chat-send-btn--voice-live::after {
content: "";
position: absolute;
inset: -1px;
border-radius: inherit;
box-shadow: 0 0 16px color-mix(in srgb, var(--accent) 30%, transparent);
opacity: 0.5;
animation: chat-voice-live-breathe 2.8s ease-in-out infinite;
pointer-events: none;
}
.chat-send-btn--voice-live:hover:not(:disabled) {
background: color-mix(in srgb, var(--accent) 20%, transparent);
box-shadow: none;
}
.chat-send-btn--voice-live .agent-chat__voice-activity {
transition: opacity var(--duration-fast) ease;
}
.chat-send-btn--voice-live:hover:not(:disabled) .agent-chat__voice-activity,
.chat-send-btn--voice-live:focus-visible .agent-chat__voice-activity {
opacity: 0.25;
}
.chat-send-btn__voice-stop-glyph {
position: absolute;
inset: 0;
display: inline-flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity var(--duration-fast) ease;
}
.chat-send-btn--voice-live .chat-send-btn__voice-stop-glyph svg {
width: 12px;
height: 12px;
fill: currentColor;
stroke: none;
}
.chat-send-btn--voice-live:hover:not(:disabled) .chat-send-btn__voice-stop-glyph,
.chat-send-btn--voice-live:focus-visible .chat-send-btn__voice-stop-glyph {
opacity: 1;
}
@keyframes chat-voice-live-breathe {
0%,
100% {
opacity: 0.35;
}
50% {
opacity: 0.8;
}
}
/* Errored Talk session: the meter is gone, so the stop glyph stays visible
and the glow calms down; the alert row above owns the error message. */
.chat-send-btn--voice-error .chat-send-btn__voice-stop-glyph {
opacity: 1;
}
.chat-send-btn--voice-error::after {
animation: none;
opacity: 0.25;
}
/* Soft danger fill so Stop generating reads as the one destructive control
next to the accent-filled send button. */
.chat-send-btn--stop {
background: color-mix(in srgb, var(--danger) 12%, transparent);
color: var(--danger);
box-shadow: none;
}
.chat-send-btn--stop svg {
width: 18px;
height: 18px;
fill: currentColor;
stroke: none;
}
.chat-send-btn--stop:hover:not(:disabled) {
background: color-mix(in srgb, var(--danger) 18%, transparent);
color: color-mix(in srgb, var(--danger) 82%, #fff);
box-shadow: none;
}
@media (min-width: 1600px) {
.agent-chat__composer-combobox > :is(textarea, input) {
max-height: calc(7em + 12px);
}
.agent-chat__composer-footer {
min-height: 28px;
}
.agent-chat__composer-footer .agent-chat__input-btn {
min-width: 28px;
height: 28px;
padding-inline: 6px;
}
.agent-chat__composer-input-row .agent-chat__input-btn {
min-width: 36px;
width: 36px;
height: 36px;
padding-inline: 0;
}
}
@media (max-width: 768px), (max-width: 932px) and (max-height: 500px) and (orientation: landscape) {
.agent-chat__input {
--chat-box-inset: 4px;
}
.agent-chat__composer-input-row {
gap: 0;
}
.agent-chat__composer-input-row .agent-chat__input-btn--attach {
width: 36px;
min-width: 36px;
height: 44px;
}
.agent-chat__composer-combobox {
align-self: stretch;
}
.agent-chat__composer-combobox > :is(textarea, input) {
flex: 1 1 auto;
min-height: 44px;
max-height: calc(7em + var(--chat-box-inset) + var(--chat-box-inset));
padding-top: 10px;
padding-bottom: 10px;
font-size: var(--control-ui-input-text-size);
}
.agent-chat__composer-actions {
flex-direction: column;
gap: 4px;
margin-left: var(--chat-box-inset);
}
.agent-chat__composer-controls {
order: 0;
display: grid;
/* Three columns: settings, the transient interrupted toast (absent in
the normal state, so its column collapses), and the model picker. */
grid-template-columns: 40px minmax(0, max-content) minmax(0, max-content);
flex: 1 1 0;
width: auto;
margin-left: 0;
gap: 0;
}
.agent-chat__composer-meta {
margin-left: 0;
}
.agent-chat__composer-controls .chat-controls__model,
.chat-composer-model-control {
width: fit-content;
min-width: 0;
max-width: min(70vw, 100%);
margin-left: 0;
}
/* The borderless trigger is 30px on desktop; keep a >=40px touch target
inside the mobile composer grid. */
.agent-chat__composer-controls .chat-controls__inline-select-trigger {
width: fit-content;
max-width: 100%;
height: 40px;
min-height: 40px;
gap: 4px;
padding: 0 2px 0 4px;
}
.agent-chat__input .chat-controls__inline-select-menu--combined {
position: fixed;
left: auto;
right: max(12px, var(--safe-area-right));
bottom: calc(96px + var(--safe-area-bottom));
width: min(392px, calc(100vw - 24px));
max-height: min(440px, calc(100vh - 116px - var(--safe-area-bottom)));
}
.chat-view-menu-wrapper {
width: 40px;
margin-left: 0;
justify-self: start;
}
.chat-view-menu-trigger {
width: 36px;
min-width: 36px;
max-width: 36px;
height: 44px;
min-height: 44px;
justify-content: center;
padding: 0;
}
.agent-chat__toolbar-right {
flex-direction: column;
gap: 8px;
margin-bottom: calc(var(--chat-box-inset, 4px) + 1px);
}
.agent-chat__composer-shell {
grid-template-columns: minmax(0, 1fr);
gap: 0;
}
}
@media (max-width: 932px) and (max-height: 500px) and (orientation: landscape) {
.chat-thread {
min-height: 40vh;
}
.agent-chat__input {
max-height: min(36vh, 164px);
overflow-x: hidden;
overflow-y: auto;
overscroll-behavior: contain;
}
.agent-chat__input:has(.chat-controls__inline-select[open]),
.agent-chat__input:has(wa-dropdown.chat-view-menu[open]),
.agent-chat__input:has(.agent-chat__attach-menu[open]) {
overflow: visible;
}
.agent-chat__input .chat-controls__inline-select-menu--combined {
max-height: calc(100vh - 148px);
}
.agent-chat__composer-footer {
position: sticky;
bottom: 0;
z-index: 3;
background: var(--card);
}
.agent-chat__composer-combobox > :is(textarea, input) {
min-height: 48px;
max-height: 56px;
overflow-y: auto;
}
.agent-chat__input > .slash-menu {
flex: 0 0 auto;
position: sticky;
top: 0;
bottom: auto;
max-height: min(28vh, 88px);
margin-bottom: 6px;
}
}
@media (max-width: 640px), (max-width: 932px) and (max-height: 500px) and (orientation: landscape) {
/* Backdrop-filter contains fixed descendants; lift it and the landscape scroll clip while open. */
.agent-chat__input:has(.chat-controls__inline-select[open]),
.agent-chat__input:has(wa-dropdown.chat-view-menu[open]),
.agent-chat__input:has(.context-usage details[open]),
.agent-chat__input:has(.agent-chat__attach-menu[open]) {
overflow: visible;
backdrop-filter: none;
-webkit-backdrop-filter: none;
}
.context-usage__popover {
position: fixed;
left: max(12px, var(--safe-area-left));
right: max(12px, var(--safe-area-right));
bottom: calc(96px + var(--safe-area-bottom));
width: auto;
max-height: calc(100vh - 116px - var(--safe-area-bottom));
overflow-y: auto;
}
}
.slash-menu {
position: absolute;
bottom: 100%;
left: 0;
right: 0;
max-height: 320px;
overflow-y: auto;
background: var(--popover);
border: 1px solid var(--border-strong);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-lg);
z-index: 30;
margin-bottom: 4px;
padding: 6px;
scrollbar-width: thin;
}
.slash-menu-group + .slash-menu-group {
margin-top: 4px;
padding-top: 4px;
border-top: 1px solid color-mix(in srgb, var(--border) 50%, transparent);
}
.slash-menu-group__label {
padding: 4px 10px 2px;
font-size: 0.68rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: var(--accent);
opacity: 0.7;
}
.slash-menu-item {
display: flex;
align-items: center;
gap: 8px;
padding: 7px 10px;
border-radius: var(--radius-sm);
transition:
background var(--duration-fast) ease,
color var(--duration-fast) ease;
}
.slash-menu-item:hover,
.slash-menu-item--active {
background: color-mix(in srgb, var(--accent) 10%, var(--bg-hover));
}
.slash-menu-icon {
display: flex;
align-items: center;
justify-content: center;
width: 20px;
height: 20px;
flex-shrink: 0;
color: var(--accent);
opacity: 0.7;
}
.slash-menu-icon svg {
width: 14px;
height: 14px;
stroke: currentColor;
fill: none;
stroke-width: 1.5px;
stroke-linecap: round;
stroke-linejoin: round;
}
.slash-menu-item--active .slash-menu-icon,
.slash-menu-item:hover .slash-menu-icon {
opacity: 1;
}
.slash-menu-name {
font-size: 0.82rem;
font-weight: 600;
font-family: var(--mono);
color: var(--accent);
white-space: nowrap;
}
.slash-menu-args {
font-size: 0.75rem;
color: var(--muted);
font-family: var(--mono);
opacity: 0.65;
}
.slash-menu-desc {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
text-align: right;
font-size: 0.75rem;
color: var(--muted);
}
.slash-menu-item--active .slash-menu-name {
color: var(--accent-hover);
}
.slash-menu-item--active .slash-menu-desc {
color: var(--text);
}
.slash-menu-badge {
font-size: 0.65rem;
font-weight: 600;
padding: 1px 6px;
border-radius: var(--radius-sm);
background: color-mix(in srgb, var(--accent) 12%, transparent);
color: var(--accent);
white-space: nowrap;
flex-shrink: 0;
}
.slash-menu-show-more {
display: flex;
align-items: center;
justify-content: center;
gap: 4px;
width: 100%;
padding: 8px 10px;
margin-top: 4px;
font-size: 0.75rem;
font-weight: 600;
color: var(--accent);
background: none;
border: none;
border-top: 1px solid color-mix(in srgb, var(--border) 50%, transparent);
transition:
background var(--duration-fast) ease,
color var(--duration-fast) ease;
}
.slash-menu-show-more:hover {
background: color-mix(in srgb, var(--accent) 8%, transparent);
color: var(--accent-hover);
}
.slash-menu-footer {
display: flex;
gap: 10px;
padding: 6px 10px 4px;
font-size: 0.68rem;
color: var(--muted);
border-top: 1px solid color-mix(in srgb, var(--border) 50%, transparent);
margin-top: 4px;
}
.slash-menu-footer kbd {
display: inline-block;
padding: 1px 4px;
font-size: 0.65rem;
font-family: var(--mono);
border: 1px solid var(--border);
border-radius: 3px;
background: var(--bg);
line-height: 1.3;
}
.chat-attachments-preview {
display: flex;
gap: 8px;
flex-wrap: wrap;
flex-shrink: 0;
margin-top: 4px;
padding-block-start: 10px;
padding-inline-start: 10px;
margin-bottom: 8px;
}
.chat-attachment-thumb {
position: relative;
width: 60px;
height: 60px;
border-radius: var(--radius-sm);
overflow: hidden;
border: 1px solid var(--border);
}
.chat-attachment-thumb--file {
width: 180px;
}
.chat-attachment-thumb--pasted-text {
width: min(220px, calc(100vw - 64px));
height: 60px;
border-radius: var(--radius-sm);
background: color-mix(in srgb, var(--panel) 72%, transparent);
}
.chat-attachment-thumb img {
width: 100%;
height: 100%;
object-fit: cover;
}
.chat-attachment-remove {
position: absolute;
top: 4px;
right: 4px;
z-index: 1;
width: 20px;
height: 20px;
padding: 0;
border-radius: 50%;
border: none;
background: var(--text);
color: var(--bg);
font-size: 12px;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
}
.chat-attachment-remove svg {
width: 13px;
height: 13px;
stroke: currentColor;
fill: none;
stroke-width: 2px;
stroke-linecap: round;
stroke-linejoin: round;
}
.chat-attachment-file {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
height: 100%;
padding: 8px 34px 8px 10px;
overflow: hidden;
font-size: 0.72rem;
color: var(--text);
background: var(--panel);
}
.chat-attachment-file--pasted-text {
gap: 8px;
padding: 10px 42px 10px 10px;
background: color-mix(in srgb, var(--panel) 62%, transparent);
}
.chat-attachment-file__icon {
display: inline-flex;
flex: 0 0 auto;
color: var(--muted);
}
.chat-attachment-file__icon svg {
width: 16px;
height: 16px;
stroke: currentColor;
fill: none;
stroke-width: 1.7px;
stroke-linecap: round;
stroke-linejoin: round;
}
.chat-attachment-file--pasted-text .chat-attachment-file__icon {
width: 28px;
height: 40px;
align-items: center;
justify-content: center;
}
.chat-attachment-file--pasted-text .chat-attachment-file__icon svg {
width: 18px;
height: 18px;
}
.chat-attachment-file__name {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.chat-attachment-file--pasted-text .chat-attachment-file__name {
font-size: 0.86rem;
line-height: 1.2;
}
.chat-attachment-file__body {
display: flex;
min-width: 0;
flex-direction: column;
gap: 4px;
}
.chat-attachment-file__meta {
color: var(--muted);
font-size: 0.68rem;
}
.chat-attachment-text-action {
display: inline-flex;
width: fit-content;
max-width: 100%;
align-items: center;
gap: 3px;
padding: 0;
border: none;
color: var(--muted);
background: transparent;
cursor: pointer;
font: inherit;
line-height: 1.15;
text-align: left;
text-decoration: underline;
text-underline-offset: 2px;
}
.chat-attachment-text-action:hover {
color: var(--text);
}
.chat-attachment-text-action svg {
width: 13px;
height: 13px;
stroke: currentColor;
fill: none;
stroke-width: 1.7px;
stroke-linecap: round;
stroke-linejoin: round;
}
.agent-chat__file-input,
.agent-chat__photo-input,
.agent-chat__camera-input {
display: none;
}
/* Chat controls - moved to content-header area, left aligned */
.chat-controls {
display: inline-flex;
align-items: center;
justify-content: flex-start;
gap: 8px;
flex-wrap: wrap;
min-height: 36px;
position: relative;
overflow: visible;
}
.chat-controls__session {
min-width: 0;
max-width: none;
}
.chat-controls__agent {
min-width: 0;
max-width: none;
}
.chat-controls__session-row {
display: grid;
grid-template-columns: minmax(116px, 5fr) minmax(132px, 7fr) minmax(180px, 8fr);
grid-template-areas: "agent session model";
align-items: center;
gap: 6px;
width: 100%;
min-height: 36px;
min-width: 0;
}
.chat-controls__session-row--single-agent {
grid-template-columns: minmax(132px, 7fr) minmax(180px, 8fr);
grid-template-areas: "session model";
}
.chat-controls__session-picker {
grid-area: session;
position: relative;
}
.chat-controls__session-trigger {
display: flex;
align-items: center;
justify-content: space-between;
gap: 6px;
width: 100%;
min-height: 36px;
padding: 8px 10px 8px 12px;
border: 1px solid var(--input);
border-radius: var(--radius-md);
background: var(--bg-elevated);
color: var(--text);
font: inherit;
font-size: 14px;
line-height: 1.2;
min-width: 0;
transition:
background var(--duration-fast) ease-out,
border-color var(--duration-fast) ease-out;
}
.chat-controls__session-trigger:hover:not(:disabled),
.chat-controls__session-trigger[aria-expanded="true"] {
border-color: color-mix(in srgb, var(--accent) 38%, var(--input));
background: color-mix(in srgb, var(--bg-elevated) 90%, var(--accent-subtle) 10%);
}
.chat-controls__session-trigger:disabled {
cursor: default;
opacity: 0.6;
}
.chat-controls__session-trigger-label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
min-width: 0;
}
.chat-controls__session-trigger-icon {
display: inline-flex;
width: 16px;
height: 16px;
flex: 0 0 auto;
color: var(--muted);
}
.chat-controls__session-trigger-icon svg {
width: 16px;
height: 16px;
stroke: currentColor;
fill: none;
stroke-width: 1.5px;
}
.chat-controls__agent {
grid-area: agent;
}
.chat-controls__session-row--flash .chat-controls__session-trigger {
animation: chat-session-switch-flash 0.2s ease-out;
}
.chat-controls__session-notice {
width: 100%;
min-height: 16px;
font-size: 12px;
line-height: 16px;
color: var(--muted);
}
@keyframes chat-session-switch-flash {
0% {
border-color: color-mix(in srgb, var(--accent) 72%, var(--border));
background: color-mix(in srgb, var(--accent-subtle) 62%, var(--card));
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
100% {
border-color: var(--border);
background: var(--card);
box-shadow: none;
}
}
@media (prefers-reduced-motion: reduce) {
.chat-controls__session-row--flash .chat-controls__session-trigger {
animation: none;
border-color: color-mix(in srgb, var(--accent) 70%, var(--border));
box-shadow: var(--focus-ring);
}
.agent-chat__talk-input-refresh:disabled svg,
.agent-chat__talk-input-spinner {
animation: none;
}
}
.chat-controls__model {
grid-area: model;
min-width: 0;
max-width: none;
}
.chat-controls__inline-select {
position: relative;
min-width: 0;
}
.chat-controls__inline-select summary {
list-style: none;
}
.chat-controls__inline-select summary::-webkit-details-marker {
display: none;
}
/* Composer controls are quiet text controls: no borders/fills at rest so the
composer frame stays the only chrome; hover/open get a soft wash. */
.chat-controls__inline-select-trigger {
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: flex-start;
gap: 6px;
width: 100%;
height: 30px;
min-height: 30px;
padding: 0 6px 0 8px;
border: none;
border-radius: var(--radius-sm);
background: transparent;
color: var(--text);
font-size: 13px;
line-height: 1.35;
overflow: hidden;
user-select: none;
}
.chat-controls__inline-select-trigger:hover,
.chat-controls__inline-select[open] > .chat-controls__inline-select-trigger {
background: color-mix(in srgb, var(--text) 7%, transparent);
color: var(--text-strong);
}
.chat-controls__inline-select-trigger:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.chat-controls__inline-select-trigger--disabled {
cursor: not-allowed;
opacity: 0.55;
}
.chat-controls__inline-select-label {
min-width: 0;
overflow: hidden;
line-height: 1.35;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Keep the chevron pinned right when the mobile trigger stretches. */
.chat-controls__inline-select-icon {
display: inline-flex;
width: 14px;
height: 14px;
margin-left: auto;
color: var(--muted);
flex: 0 0 auto;
}
.chat-controls__inline-select-icon svg,
.chat-controls__inline-select-check svg {
width: 100%;
height: 100%;
stroke: currentColor;
fill: none;
}
.chat-controls__inline-select[open] .chat-controls__inline-select-icon {
transform: rotate(180deg);
}
.chat-controls__inline-select-menu {
position: absolute;
left: 0;
bottom: calc(100% + 6px);
z-index: 80;
display: grid;
gap: 2px;
width: max(300%, min(300px, calc(100vw - 32px)));
max-height: min(280px, calc(100vh - 120px));
padding: 6px;
border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
border-radius: var(--radius-md);
background: color-mix(in srgb, var(--bg-elevated) 96%, var(--card));
box-shadow: var(--shadow-md);
overflow-y: auto;
}
.chat-controls__inline-select-option {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
width: 100%;
min-height: 34px;
padding: 7px 9px;
border: 1px solid transparent;
border-radius: var(--radius-sm);
background: transparent;
color: var(--text);
font: inherit;
font-size: 13px;
text-align: left;
}
.chat-controls__inline-select-option:hover,
.chat-controls__inline-select-option:focus-visible {
border-color: color-mix(in srgb, var(--border) 76%, transparent);
background: var(--bg-hover);
outline: none;
}
.chat-controls__inline-select-option--selected {
color: var(--text-strong);
background: color-mix(in srgb, var(--text) 6%, transparent);
}
/* The combined picker contains provider, model, and reasoning controls in one
bounded surface instead of opening a second flyout. */
.chat-controls__inline-select-menu--combined {
left: auto;
right: 0;
display: flex;
flex-direction: column;
gap: 0;
width: min(392px, calc(100vw - 24px));
max-height: min(440px, calc(100vh - 96px));
padding: 0;
overflow: hidden;
}
.chat-controls__model-browser {
display: grid;
grid-template-columns: 120px minmax(0, 1fr);
min-height: 132px;
max-height: 220px;
flex: 1 1 220px;
overflow: hidden;
}
.chat-controls__locked-model {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
padding: 8px 10px;
background: color-mix(in srgb, var(--card) 78%, transparent);
}
.chat-controls__locked-model-value {
overflow: hidden;
flex: 1 1 auto;
color: var(--text-strong);
font-size: 12px;
font-weight: 600;
text-overflow: ellipsis;
white-space: nowrap;
}
.chat-controls__locked-model-badge {
flex: 0 0 auto;
padding: 2px 6px;
border: 1px solid color-mix(in srgb, var(--border) 78%, transparent);
border-radius: var(--radius-full);
color: var(--muted);
font-size: 10px;
font-weight: 650;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.chat-controls__provider-list {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
padding: 8px 6px;
border-right: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
background: color-mix(in srgb, var(--card) 78%, transparent);
overflow-y: auto;
}
.chat-controls__provider-option {
display: flex;
align-items: center;
gap: 6px;
width: 100%;
min-height: 32px;
padding: 0 7px;
border: 1px solid transparent;
border-radius: var(--radius-sm);
background: transparent;
color: var(--muted);
font: inherit;
font-size: 12px;
font-weight: 550;
text-align: left;
}
/* Mask/brand-color rules live on .provider-brand-icon (components.css). */
.chat-controls__provider-icon {
width: 18px;
height: 18px;
flex: 0 0 18px;
}
.chat-controls__provider-icon.provider-brand-icon--fallback {
font-size: 9px;
}
.chat-controls__inline-select-trigger > .chat-controls__provider-icon {
width: 16px;
height: 16px;
flex-basis: 16px;
}
.chat-controls__provider-option:hover,
.chat-controls__provider-option:focus-visible {
background: var(--bg-hover);
color: var(--text);
outline: none;
}
.chat-controls__provider-option[aria-pressed="true"] {
border-color: color-mix(in srgb, var(--border) 74%, transparent);
background: color-mix(in srgb, var(--text) 7%, transparent);
color: var(--text-strong);
}
.chat-controls__provider-models {
min-width: 0;
padding: 8px;
overflow-y: auto;
}
.chat-controls__provider-model-group {
display: grid;
gap: 4px;
}
.chat-controls__provider-model-group[hidden] {
display: none;
}
.chat-controls__inline-select-section-label {
padding: 3px 6px 2px;
color: var(--muted);
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
.chat-controls__combined-model {
position: relative;
display: block;
}
.chat-controls__combined-model-option {
justify-content: flex-start;
gap: 8px;
min-height: 40px;
padding: 5px 8px;
}
.chat-controls__model-option-copy {
display: grid;
gap: 1px;
min-width: 0;
flex: 1 1 auto;
}
.chat-controls__model-option-title,
.chat-controls__model-option-provider {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.chat-controls__model-option-title {
display: flex;
align-items: center;
gap: 6px;
color: var(--text);
font-size: 12px;
font-weight: 600;
}
.chat-controls__model-option-name {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
}
.chat-controls__model-default-label {
display: inline-flex;
align-items: center;
gap: 4px;
flex: 0 0 auto;
color: color-mix(in srgb, var(--accent) 76%, var(--text));
font-size: 9px;
font-weight: 700;
letter-spacing: 0.08em;
line-height: 1;
text-transform: uppercase;
}
.chat-controls__model-default-label::before {
width: 4px;
height: 4px;
border-radius: 50%;
background: var(--accent);
content: "";
}
.chat-controls__model-option-provider {
color: var(--muted);
font-size: 11px;
font-weight: 450;
}
.chat-controls__reasoning-panel {
position: static;
display: grid;
gap: 4px;
flex: 0 0 auto;
width: auto;
max-height: none;
padding: 8px 10px 9px;
border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent);
background: color-mix(in srgb, var(--card) 78%, transparent);
overflow: visible;
}
.chat-controls__reasoning-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
min-width: 0;
}
/* Model provenance sits above the provider browser, outside the reasoning
panel; mirrors the reasoning head's anatomy with its own class family so
test selectors and semantics stay distinct. */
.chat-controls__model-provenance {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
min-width: 0;
padding: 8px 10px 6px;
border-bottom: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
}
.chat-controls__model-provenance-state {
display: inline-flex;
align-items: center;
gap: 4px;
min-width: 0;
padding-right: 6px;
}
.chat-controls__model-provenance-value {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 12px;
}
.chat-controls__model-provenance-value--inherit {
color: var(--muted);
}
.chat-controls__model-reset {
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
padding: 0;
border: none;
border-radius: 4px;
background: transparent;
color: var(--muted);
cursor: pointer;
}
.chat-controls__model-reset:hover:not(:disabled) {
background: color-mix(in srgb, var(--border) 45%, transparent);
color: var(--text);
}
.chat-controls__model-reset svg {
width: 12px;
height: 12px;
}
.chat-controls__reasoning-state {
display: inline-flex;
align-items: center;
gap: 4px;
min-width: 0;
padding-right: 6px;
}
.chat-controls__reasoning-value {
overflow: hidden;
color: var(--text-strong);
font-size: 12px;
font-weight: 600;
white-space: nowrap;
text-overflow: ellipsis;
}
/* Muted value = inherited model default; no reset shows because there is no
override to clear. */
.chat-controls__reasoning-value--inherit {
color: var(--muted);
font-weight: 500;
}
.chat-controls__reasoning-reset {
display: inline-flex;
align-items: center;
justify-content: center;
width: 18px;
height: 18px;
padding: 0;
border: none;
border-radius: var(--radius-full);
background: none;
color: var(--muted);
}
.chat-controls__reasoning-reset:hover:not(:disabled),
.chat-controls__reasoning-reset:focus-visible {
background: var(--bg-hover);
color: var(--text);
outline: none;
}
.chat-controls__reasoning-reset:disabled {
cursor: not-allowed;
opacity: 0.55;
}
.chat-controls__reasoning-reset svg {
width: 12px;
height: 12px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
}
/* Discrete effort slider: native range input for keyboard/a11y, decorative
stop dots layered underneath. */
.chat-controls__reasoning-slider {
position: relative;
display: flex;
align-items: center;
height: 22px;
margin: 0 6px;
}
.chat-controls__reasoning-dots {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 5px;
pointer-events: none;
}
.chat-controls__reasoning-dot {
width: 4px;
height: 4px;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--text) 28%, transparent);
}
.chat-controls__reasoning-dot--default {
background: color-mix(in srgb, var(--text) 55%, transparent);
}
.chat-controls__reasoning-range {
-webkit-appearance: none;
appearance: none;
position: relative;
z-index: 1;
width: 100%;
height: 22px;
margin: 0;
padding: 0;
background: transparent;
}
.chat-controls__reasoning-range:disabled {
cursor: not-allowed;
opacity: 0.5;
}
.chat-controls__reasoning-range:focus-visible {
outline: none;
}
.chat-controls__reasoning-range::-webkit-slider-runnable-track {
height: 3px;
border-radius: var(--radius-full);
background: linear-gradient(
90deg,
color-mix(in srgb, var(--text) 45%, transparent) var(--reasoning-fill, 0%),
color-mix(in srgb, var(--text) 14%, transparent) var(--reasoning-fill, 0%)
);
}
.chat-controls__reasoning-range::-webkit-slider-thumb {
-webkit-appearance: none;
width: 14px;
height: 14px;
margin-top: -5.5px;
border: none;
border-radius: var(--radius-full);
background: var(--text-strong);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
}
.chat-controls__reasoning-range:focus-visible::-webkit-slider-thumb {
box-shadow: var(--focus-ring);
}
.chat-controls__reasoning-range--inherit::-webkit-slider-thumb {
background: var(--muted);
}
.chat-controls__reasoning-range--unanchored::-webkit-slider-thumb {
opacity: 0.35;
}
.chat-controls__reasoning-range::-moz-range-track {
height: 3px;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--text) 14%, transparent);
}
.chat-controls__reasoning-range::-moz-range-progress {
height: 3px;
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--text) 45%, transparent);
}
.chat-controls__reasoning-range::-moz-range-thumb {
width: 14px;
height: 14px;
border: none;
border-radius: var(--radius-full);
background: var(--text-strong);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
}
.chat-controls__reasoning-range--inherit::-moz-range-thumb {
background: var(--muted);
}
.chat-controls__reasoning-range--unanchored::-moz-range-thumb {
opacity: 0.35;
}
/* Speed is a single fast-mode toggle: bolt icon plus the current state word.
Explicit off/auto overrides stay reachable through the /fast command. */
.chat-controls__speed-row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
min-width: 0;
}
.chat-controls__speed-toggle {
display: inline-flex;
align-items: center;
gap: 6px;
min-height: 28px;
padding: 4px 12px;
border: 1px solid color-mix(in srgb, var(--border) 92%, var(--text));
border-radius: var(--radius-full);
background: color-mix(in srgb, var(--text) 4%, var(--card));
color: var(--muted);
font: inherit;
font-size: 12px;
font-weight: 550;
line-height: 1;
}
.chat-controls__speed-toggle:hover:not(:disabled),
.chat-controls__speed-toggle:focus-visible {
border-color: color-mix(in srgb, var(--text) 20%, var(--border));
background: color-mix(in srgb, var(--text) 6%, var(--card));
color: var(--text);
outline: none;
}
.chat-controls__speed-toggle--active {
border-color: color-mix(in srgb, var(--accent) 76%, var(--border));
background: color-mix(in srgb, var(--accent) 12%, var(--card));
color: var(--text-strong);
}
.chat-controls__speed-toggle:disabled {
cursor: not-allowed;
opacity: 0.55;
}
.chat-controls__speed-toggle-icon {
display: inline-flex;
width: 13px;
height: 13px;
flex: 0 0 auto;
}
.chat-controls__speed-toggle-icon svg {
width: 100%;
height: 100%;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linejoin: round;
}
/* Filled bolt telegraphs the active fast tier without relying on color alone. */
.chat-controls__speed-toggle--active .chat-controls__speed-toggle-icon svg {
fill: currentColor;
}
.chat-controls__reasoning-option {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 5px;
min-width: 0;
min-height: 32px;
padding: 5px;
border: 1px solid color-mix(in srgb, var(--border) 74%, transparent);
border-radius: var(--radius-sm);
background: color-mix(in srgb, var(--card) 74%, transparent);
color: var(--muted);
font: inherit;
font-size: 12px;
line-height: 1;
}
.chat-controls__reasoning-option:hover:not(:disabled),
.chat-controls__reasoning-option:focus-visible {
border-color: color-mix(in srgb, var(--text) 20%, var(--border));
background: color-mix(in srgb, var(--text) 6%, var(--card));
color: var(--text);
outline: none;
}
.chat-controls__reasoning-option--selected {
border-color: color-mix(in srgb, var(--accent) 76%, var(--border));
background: color-mix(in srgb, var(--accent) 12%, var(--card));
color: var(--text-strong);
}
.chat-controls__reasoning-option:disabled {
cursor: not-allowed;
opacity: 0.55;
}
.chat-controls__inline-select-check {
display: inline-flex;
width: 14px;
height: 14px;
color: var(--accent);
flex: 0 0 auto;
}
.chat-controls__thinking {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
}
/* Controls separator: the visible divider is the background; any glyph content
is clipped by the 1px overflow-hidden box. */
.chat-controls__separator {
align-self: center;
flex: 0 0 1px;
width: 1px;
height: 22px;
margin: 0 3px;
overflow: hidden;
background: color-mix(in srgb, var(--border-strong) 72%, transparent);
color: var(--muted);
font-size: 12px;
line-height: 1;
font-weight: 300;
user-select: none;
}
.chat-controls .btn--icon {
width: 36px;
min-width: 36px;
height: 36px;
padding: 0;
border-radius: var(--radius-lg);
}
:root[data-theme-mode="light"] .chat-controls__separator {
background: rgba(16, 24, 40, 0.18);
}
.chat-controls__session select,
.chat-controls__agent select {
box-sizing: border-box;
height: 36px;
min-height: 36px;
padding: 0 34px 0 12px;
width: 100%;
max-width: none;
border-color: color-mix(in srgb, var(--input) 88%, transparent);
border-radius: var(--radius-lg);
background-color: color-mix(in srgb, var(--card) 92%, var(--bg-elevated) 8%);
font-size: 13px;
overflow: hidden;
text-overflow: ellipsis;
}
.chat-controls__thinking {
display: flex;
align-items: center;
gap: 4px;
font-size: 12px;
padding: 4px 10px;
background: rgba(255, 255, 255, 0.04);
border-radius: var(--radius-sm);
border: 1px solid var(--border);
}
.chat-controls__auto-expand {
padding: 8px;
}
/* Light theme thinking indicator override */
:root[data-theme-mode="light"] .chat-controls__thinking {
background: rgba(255, 255, 255, 0.9);
border-color: rgba(16, 24, 40, 0.15);
}
@media (max-width: 768px) {
.agent-chat__talk-options--settings .agent-chat__talk-options-primary,
.agent-chat__talk-options--settings .agent-chat__talk-options-grid {
grid-template-columns: minmax(0, 1fr);
}
.agent-chat__talk-input-setting {
order: -1;
}
.chat-controls__session {
min-width: 120px;
max-width: none;
}
.chat-controls__agent {
min-width: 120px;
max-width: none;
}
.chat-controls__model {
min-width: 140px;
max-width: none;
}
.chat-controls {
gap: 8px;
}
.agent-chat__input-btn,
.agent-chat__toolbar-right .btn--ghost,
.chat-send-btn {
width: 44px;
min-width: 44px;
height: 44px;
}
/* Keep the live voice pill wide enough for its 7-bar meter; the generic
44px square above would crush it at phone widths. */
.chat-send-btn--voice-live {
width: auto;
min-width: 64px;
}
.agent-chat__composer-shell {
width: calc(100% - 8px);
margin: 6px 4px calc(14px + var(--safe-area-bottom));
gap: 6px;
}
.chat-run-error {
width: calc(100% - 8px);
margin: 6px 4px 0;
}
.agent-chat__composer-shell:has(.agent-chat__composer-combobox > :is(textarea, input):focus) {
margin-bottom: 0;
}
.agent-chat__composer-footer {
flex-wrap: nowrap;
gap: 3px;
min-height: 44px;
}
.agent-chat__composer-controls .chat-controls__model {
min-width: 0;
}
}
@media (display-mode: standalone) and (max-width: 768px) {
.agent-chat__composer-shell {
margin-bottom: calc(14px + max(var(--safe-area-bottom), 34px));
}
.agent-chat__composer-shell:has(.agent-chat__composer-combobox > :is(textarea, input):focus) {
margin-bottom: 0;
}
}
@media (max-width: 900px) {
.chat-session {
min-width: 180px;
}
}
@media (max-width: 640px) {
.agent-chat__composer-controls {
align-items: center;
flex-direction: row;
}
.agent-chat__composer-controls .chat-controls {
justify-content: flex-start;
}
.chat-controls__model-browser {
grid-template-columns: 120px minmax(0, 1fr);
min-height: 180px;
}
.chat-controls__provider-option {
padding-inline: 8px;
font-size: 12px;
}
.chat-controls {
flex-wrap: wrap;
gap: 8px;
}
.chat-controls__session {
min-width: 120px;
}
.chat-controls__model {
min-width: 150px;
}
}
/* Chat loading skeleton */
.chat-loading-skeleton {
padding: 4px 0;
animation: fade-in 0.3s var(--ease-out);
}
.chat-loading-skeleton .chat-msg {
width: min(560px, 82%);
}
.chat-loading-skeleton .chat-line.user .chat-msg {
width: min(360px, 70%);
}
.chat-loading-skeleton .chat-bubble {
width: 100%;
box-sizing: border-box;
}
/* Welcome state (new session) */
.agent-chat__welcome {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
gap: 10px;
width: min(100%, 640px);
margin: auto;
padding: clamp(20px, 4vh, 40px) 24px;
flex: 1;
min-height: 0;
}
.agent-chat__welcome h2 {
font-size: 24px;
font-weight: 600;
margin: 0;
color: var(--text);
}
.agent-chat__welcome-avatar {
width: 96px;
height: 96px;
border-radius: 50%;
object-fit: cover;
}
/* The 120x120 Clawd canvas stays centered in the existing hero slot. */
.agent-chat__welcome-clawd {
width: 128px;
height: 112px;
margin-bottom: 2px;
display: grid;
place-items: center;
overflow: visible;
}
/* Phones (and short landscape): scale the welcome hero down so the composer
and recent chats fit the first screenful on the start screen and /new. */
@media (max-width: 768px), (max-width: 932px) and (max-height: 500px) and (orientation: landscape) {
.agent-chat__welcome {
gap: 8px;
padding: 16px 12px;
}
.agent-chat__welcome h2 {
font-size: 20px;
}
.agent-chat__welcome-avatar {
width: 64px;
height: 64px;
}
.agent-chat__welcome-clawd {
width: 88px;
height: 77px;
}
.agent-chat__welcome-clawd openclaw-mascot {
transform: scale(0.6875);
}
.agent-chat__welcome .agent-chat__avatar--text {
width: 64px;
height: 64px;
font-size: 22px;
}
}
.agent-chat__avatar--text {
width: 80px;
height: 80px;
border-radius: var(--radius-lg);
background: var(--secondary);
border: 1px solid var(--border);
color: var(--text);
display: grid;
place-items: center;
font-size: 28px;
font-weight: 700;
}
/* Recent user chats replace the canned suggestions once any exist. */
.agent-chat__recents {
display: flex;
flex-direction: column;
gap: 4px;
width: min(100%, 520px);
margin-top: 12px;
text-align: left;
}
.agent-chat__recents-title {
font-size: 12px;
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--muted);
margin: 0 0 2px 4px;
}
.agent-chat__recent {
display: flex;
align-items: center;
gap: 8px;
min-height: 40px;
padding: 8px 12px;
border-radius: var(--radius-md);
border: 1px solid transparent;
background: transparent;
color: var(--text);
font-size: 13px;
text-align: left;
transition:
background 0.15s,
border-color 0.15s;
}
.agent-chat__recent:hover {
background: var(--panel);
border-color: var(--border);
}
.agent-chat__recent-name {
font-weight: 500;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.agent-chat__recent-sub {
color: var(--muted);
font-size: 12px;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.agent-chat__recent-time {
margin-left: auto;
color: var(--muted);
font-size: 12px;
white-space: nowrap;
}
.agent-chat__hint {
font-size: 13px;
color: var(--muted);
margin: 0;
}
.agent-chat__hint kbd {
display: inline-block;
padding: 1px 6px;
font-size: 12px; /* was 11px */
font-family: var(--font-mono);
background: var(--panel-strong);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
}
.agent-chat__suggestions {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
width: min(100%, 480px);
margin-top: 8px;
}
.agent-chat__suggestion {
min-height: 40px;
font-size: 13px;
line-height: 1.4;
padding: 10px 16px;
border-radius: var(--radius-md);
border: 1px solid var(--border);
background: var(--panel);
color: var(--text);
/* Localized labels wrap to multiple lines; balance keeps the split even and
break-word stops long words from pushing past the chip border. */
text-wrap: balance;
overflow-wrap: break-word;
transition:
background 0.15s,
border-color 0.15s;
}
.agent-chat__suggestion:hover {
background: var(--panel-strong);
border-color: var(--accent);
}
/* Must stay after the base suggestion rules: equal specificity, so source
order is what lets the phone layout win over the two-column default. */
@media (max-width: 768px) {
.agent-chat__suggestions {
grid-template-columns: minmax(0, 1fr);
width: min(100%, 360px);
}
.agent-chat__suggestion {
min-height: 44px;
}
}
/* Mobile dropdown toggle — hidden on desktop */
/* Mobile gear toggle + dropdown are hidden by default in layout.css */