243 lines
8.7 KiB
CSS
243 lines
8.7 KiB
CSS
/**
|
|||
|
|
* SHARED chat-surface theme — the single place the widget's themed appearance is
|
||
|
|
* defined. Imported by BOTH the real widget (`WidgetBuilder.vue`) and the admin
|
||
|
|
* preview (`AgentChatPreviewPanel.vue`) so they can never drift.
|
||
|
|
*
|
||
|
|
* Every rule is scoped under `.chat-container.rp-surface` (both surfaces add the
|
||
|
|
* `rp-surface` marker class to their panel root). The extra class both contains the
|
||
|
|
* global import to the widget and gives these rules enough specificity to win over
|
||
|
|
* each component's own scoped `[data-v-*]` CSS. Every value comes from the `--rp-*`
|
||
|
|
* custom properties emitted by `themeCssVars()` in `widget-theme.ts` — no hard-coded
|
||
|
|
* per-theme values live here.
|
||
|
|
*
|
||
|
|
* Components keep only their own NON-themed, structural CSS (layout, animations,
|
||
|
|
* socket/streaming bits, admin-mock chrome) in their scoped <style> blocks.
|
||
|
|
*/
|
||
|
|
|
||
|
|
/* ===== Panel ===== */
|
||
|
|
.chat-container.rp-surface {
|
||
|
|
font-family: var(--rp-body-font);
|
||
|
|
color: var(--rp-text);
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .chat-panel {
|
||
|
|
background: var(--rp-card);
|
||
|
|
color: var(--rp-text);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ===== Header ===== */
|
||
|
|
.chat-container.rp-surface .chat-header {
|
||
|
|
padding: 14px 16px;
|
||
|
|
border-bottom: 1px solid var(--rp-hairline);
|
||
|
|
background: transparent;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .header-info h3 {
|
||
|
|
color: var(--rp-text);
|
||
|
|
font-family: var(--rp-body-font);
|
||
|
|
font-size: 14.5px;
|
||
|
|
font-weight: 600;
|
||
|
|
line-height: 1.15;
|
||
|
|
}
|
||
|
|
/* --rp-presence is the accent when it is readable on the card, otherwise the
|
||
|
|
contrast-derived muted colour (see themeCssVars). */
|
||
|
|
.chat-container.rp-surface .rp-presence,
|
||
|
|
.chat-container.rp-surface .status-text {
|
||
|
|
color: var(--rp-presence, var(--rp-accent));
|
||
|
|
font-size: 11.5px;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .status-indicator.online {
|
||
|
|
background: var(--rp-presence, var(--rp-accent));
|
||
|
|
box-shadow: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ===== Avatars — circle by default, rounded-square on mono (Terminal); no ring ===== */
|
||
|
|
.chat-container.rp-surface .header-orb,
|
||
|
|
.chat-container.rp-surface .header-avatar {
|
||
|
|
width: 34px;
|
||
|
|
height: 34px;
|
||
|
|
border-radius: var(--rp-avatar-radius);
|
||
|
|
border: none;
|
||
|
|
box-shadow: none;
|
||
|
|
object-fit: cover;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .rp-msg-avatar,
|
||
|
|
.chat-container.rp-surface .rp-msg-avatar-orb,
|
||
|
|
.chat-container.rp-surface .rp-msg-avatar-img,
|
||
|
|
.chat-container.rp-surface .rp-welcome-orb,
|
||
|
|
.chat-container.rp-surface .rp-welcome-avatar {
|
||
|
|
width: 28px;
|
||
|
|
height: 28px;
|
||
|
|
border-radius: var(--rp-avatar-radius);
|
||
|
|
border: none;
|
||
|
|
box-shadow: none;
|
||
|
|
flex-shrink: 0;
|
||
|
|
display: block;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .rp-msg-avatar-img,
|
||
|
|
.chat-container.rp-surface .rp-welcome-avatar { object-fit: cover; }
|
||
|
|
|
||
|
|
/* ===== Messages ===== */
|
||
|
|
.chat-container.rp-surface .message {
|
||
|
|
max-width: 100%;
|
||
|
|
gap: 9px;
|
||
|
|
align-items: flex-start;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .message-bubble {
|
||
|
|
padding: 10px 14px;
|
||
|
|
font-size: 14px;
|
||
|
|
line-height: 1.5;
|
||
|
|
box-shadow: none;
|
||
|
|
max-width: 84%;
|
||
|
|
}
|
||
|
|
/* Collapse markdown paragraph margins so a one-line reply is a compact bubble. */
|
||
|
|
.chat-container.rp-surface .message-bubble p { margin: 0; }
|
||
|
|
.chat-container.rp-surface .message-bubble p + p { margin-top: 0.5em; }
|
||
|
|
/* Markdown links inside messages: clearly a link and clickable (v-html content, so
|
||
|
|
this must be a global rule — scoped styles don't reach it). Inherits the bubble
|
||
|
|
colour so it's readable on both the agent surface and the accent user bubble. */
|
||
|
|
.chat-container.rp-surface .message-bubble a {
|
||
|
|
color: inherit;
|
||
|
|
text-decoration: underline;
|
||
|
|
text-underline-offset: 2px;
|
||
|
|
font-weight: 600;
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .message-bubble a:hover { opacity: 0.82; }
|
||
|
|
/* Markdown code & wide content (v-html, so global rules): scroll inside the
|
||
|
|
bubble instead of painting past it and forcing the chat to scroll sideways.
|
||
|
|
Backgrounds derive from currentColor so they read on light and dark bubbles. */
|
||
|
|
.chat-container.rp-surface .message-bubble pre {
|
||
|
|
max-width: 100%;
|
||
|
|
overflow-x: auto;
|
||
|
|
margin: 0.5em 0;
|
||
|
|
padding: var(--space-sm, 12px);
|
||
|
|
border-radius: 8px;
|
||
|
|
background: color-mix(in srgb, currentColor 8%, transparent);
|
||
|
|
-webkit-overflow-scrolling: touch;
|
||
|
|
scrollbar-width: thin;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .message-bubble pre code {
|
||
|
|
/* Code keeps its formatting; the <pre> scrollbar handles long lines. */
|
||
|
|
white-space: pre;
|
||
|
|
overflow-wrap: normal;
|
||
|
|
background: none;
|
||
|
|
padding: 0;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .message-bubble code {
|
||
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||
|
|
font-size: 0.9em;
|
||
|
|
background: color-mix(in srgb, currentColor 8%, transparent);
|
||
|
|
padding: 1px 5px;
|
||
|
|
border-radius: 6px;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .message-bubble table {
|
||
|
|
display: block;
|
||
|
|
max-width: 100%;
|
||
|
|
overflow-x: auto;
|
||
|
|
border-collapse: collapse;
|
||
|
|
margin: 0.5em 0;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .message-bubble th,
|
||
|
|
.chat-container.rp-surface .message-bubble td {
|
||
|
|
border: 1px solid color-mix(in srgb, currentColor 20%, transparent);
|
||
|
|
padding: 4px 8px;
|
||
|
|
}
|
||
|
|
/* Agent/bot bubble: agent surface + hairline, tail top-left. */
|
||
|
|
.chat-container.rp-surface .agent-message .message-bubble,
|
||
|
|
.chat-container.rp-surface .assistant-message .message-bubble {
|
||
|
|
background: var(--rp-agent-bg);
|
||
|
|
color: var(--rp-text);
|
||
|
|
border: 1px solid var(--rp-hairline);
|
||
|
|
border-radius: var(--rp-bubble-tail) var(--rp-bubble) var(--rp-bubble) var(--rp-bubble);
|
||
|
|
}
|
||
|
|
/* User bubble: accent fill, contrast text, tail bottom-right. */
|
||
|
|
.chat-container.rp-surface .user-message .message-bubble {
|
||
|
|
background: var(--rp-accent);
|
||
|
|
color: var(--rp-on-accent);
|
||
|
|
border: none;
|
||
|
|
border-radius: var(--rp-bubble) var(--rp-bubble) var(--rp-bubble-tail) var(--rp-bubble);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ===== Quick-action pills ===== */
|
||
|
|
.chat-container.rp-surface .rp-quick-action {
|
||
|
|
padding: 8px 14px;
|
||
|
|
border-radius: 999px;
|
||
|
|
border: 1px solid color-mix(in srgb, var(--rp-accent) 66%, transparent);
|
||
|
|
background: color-mix(in srgb, var(--rp-accent) 18%, transparent);
|
||
|
|
color: var(--rp-text);
|
||
|
|
font-family: var(--rp-body-font);
|
||
|
|
font-size: 12.5px;
|
||
|
|
font-weight: 600;
|
||
|
|
cursor: pointer;
|
||
|
|
transition: background .15s ease, color .15s ease, border-color .15s ease;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .rp-quick-action:hover:not(:disabled) {
|
||
|
|
background: var(--rp-accent);
|
||
|
|
color: var(--rp-on-accent);
|
||
|
|
border-color: var(--rp-accent);
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface.theme-terminal .rp-quick-action { border-radius: 6px; }
|
||
|
|
|
||
|
|
/* ===== Input bar + send (transparent bar — card shows through, no grey band) ===== */
|
||
|
|
.chat-container.rp-surface .chat-input {
|
||
|
|
background: transparent;
|
||
|
|
border-top: 1px solid var(--rp-hairline);
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .message-input input,
|
||
|
|
.chat-container.rp-surface .email-input input {
|
||
|
|
border-radius: var(--rp-field-radius);
|
||
|
|
border: 1px solid color-mix(in srgb, var(--rp-accent) 30%, var(--rp-hairline));
|
||
|
|
background: color-mix(in srgb, var(--rp-text) 6%, transparent);
|
||
|
|
color: var(--rp-text);
|
||
|
|
font-family: var(--rp-body-font);
|
||
|
|
font-size: 14px;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .message-input input::placeholder,
|
||
|
|
.chat-container.rp-surface .email-input input::placeholder {
|
||
|
|
color: var(--rp-muted);
|
||
|
|
opacity: 1;
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .message-input input:focus,
|
||
|
|
.chat-container.rp-surface .email-input input:focus {
|
||
|
|
border-color: var(--rp-accent);
|
||
|
|
box-shadow: 0 0 0 3px color-mix(in srgb, var(--rp-accent) 22%, transparent);
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .send-button {
|
||
|
|
width: 42px;
|
||
|
|
min-width: 42px;
|
||
|
|
height: 42px;
|
||
|
|
flex-shrink: 0;
|
||
|
|
border: none;
|
||
|
|
border-radius: var(--rp-field-radius);
|
||
|
|
background: var(--rp-accent);
|
||
|
|
color: var(--rp-on-accent);
|
||
|
|
cursor: pointer;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ===== Powered-by footer (transparent — card shows, no grey band) ===== */
|
||
|
|
.chat-container.rp-surface .powered-by,
|
||
|
|
.chat-container.rp-surface .powered-by-welcome {
|
||
|
|
background: transparent;
|
||
|
|
border-top: none;
|
||
|
|
color: var(--rp-muted);
|
||
|
|
font-family: var(--rp-body-font);
|
||
|
|
}
|
||
|
|
.chat-container.rp-surface .rp-powered-prefix { color: var(--rp-muted); opacity: 1; }
|
||
|
|
.chat-container.rp-surface .rp-brand { color: var(--rp-text); font-weight: 700; }
|
||
|
|
|
||
|
|
/* Mono (Terminal): monospace across the whole surface. */
|
||
|
|
.chat-container.rp-surface.theme-terminal,
|
||
|
|
.chat-container.rp-surface.theme-terminal .chat-panel,
|
||
|
|
.chat-container.rp-surface.theme-terminal .header-info h3,
|
||
|
|
.chat-container.rp-surface.theme-terminal .message-bubble,
|
||
|
|
.chat-container.rp-surface.theme-terminal .rp-quick-action,
|
||
|
|
.chat-container.rp-surface.theme-terminal .message-input input,
|
||
|
|
.chat-container.rp-surface.theme-terminal .powered-by {
|
||
|
|
font-family: var(--rp-body-font);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Glass: frosted panel. */
|
||
|
|
.chat-container.rp-surface.theme-glass .chat-panel {
|
||
|
|
backdrop-filter: blur(14px);
|
||
|
|
-webkit-backdrop-filter: blur(14px);
|
||
|
|
}
|