| /* ============================================================================ |
| Chat message body |
| ---------------------------------------------------------------------------- |
| The MessageBody surface: message row shell, assistant bubble shell, the |
| hover copy button, the streaming caret, and the user-turn meta row. The |
| Markdown prose element layer (.maka-prose + code-block chrome + hljs |
| palette) lives in prose.css (#618 item 3). |
| |
| Relocated from maka-tokens.css. Authored unlayered (the renderer styles/ |
| contract requires it) but pulled into @layer components by |
| `@import ... layer(components)` in styles.css, so the rules keep the exact |
| cascade precedence they had in tokens — Tailwind utilities still win, which |
| several selectors here depend on: .maka-message-row's margin loses to the |
| Message variant's ml-0/mr-auto, .maka-message-copy loses to the UiButton |
| size utilities. Zero visual change — issue #546 PR4. |
| ============================================================================ */ |
| |
| /* --- Message row (Message primitive base: cva("maka-message-row")) -------- */ |
| .maka-message-row { |
| max-width: var(--maka-chat-measure); |
| margin: 0 auto; |
| width: 100%; |
| opacity: 1; |
| } |
| |
| /* --- Assistant bubble shell ----------------------------------------------- */ |
| /* User message: a tinted, width-capped block anchored to the right — now |
| the `Bubble variant="user"` chat primitive (issue #332 PR1). It keeps the |
| neutral `--chat-user-bg` token path; the shell utilities live in |
| packages/ui/src/primitives/chat.tsx. */ |
| /* Assistant: no bubble — just text on background, like an editor. The |
| markdown typography (color, line-height, break-word, edge-margin trims) |
| lives on .maka-prose in prose.css — the assistant Bubble variant carries |
| both classes, so the shell keeps only container geometry (#618 item 2). |
| The reading measure (max-width) lives on .maka-message-row above, shared |
| with the composer, so the assistant block matches the composer width. */ |
| .maka-bubble-assistant { |
| padding: var(--space-0-5) 0 0; |
| } |
| /* The streaming ▎ caret + its trailing-<p> inline hack were retired by the |
| streaming UI rework: the "still writing" signal is now the per-word fade-in |
| (@keyframes maka-stream-fade-in, wrapped by markdown-body's rehype pass), so |
| the trailing paragraph keeps its normal block layout. */ |
| |
| /* --- Hover-revealed copy button on assistant messages -------------------- */ |
| /* The wrapper is position: relative so the button can anchor to the top-right |
| corner. The hover/focus-within guard keeps it out of the way until the user |
| deliberately mouses over the bubble or tabs into it. */ |
| .maka-bubble-with-actions { |
| position: relative; |
| } |
| .maka-message-copy { |
| position: absolute; |
| top: 2px; |
| right: -2px; |
| width: 24px; |
| height: 24px; |
| display: grid; |
| place-items: center; |
| border: 0; |
| border-radius: var(--radius-pill); |
| background: oklch(from var(--background) l c h / 0.88); |
| color: var(--muted-foreground); |
| opacity: 0; |
| /* PR-CHAT-COPY-BUTTON-POLISH-0 (WAWQAQ 10min loop): the copy |
| button used to fade in on hover but never moved — felt like |
| a label flickering on. Add a tiny entrance translate (4px |
| down → 0) + scale (0.94 → 1) on the rest state so the reveal |
| on hover reads as "this just slid in from above" rather than |
| a fade-only flash. transform stays GPU-accelerated; transition |
| list keeps both axes coherent. */ |
| transform: translateY(-3px) scale(var(--scale-press)); |
| transition: |
| opacity var(--duration-base) var(--ease-out-strong), |
| transform var(--duration-emphasized) var(--ease-out-strong), |
| color var(--duration-quick) var(--ease-out-strong), |
| background var(--duration-quick) var(--ease-out-strong), |
| box-shadow var(--duration-quick) var(--ease-out-strong); |
| } |
| |
| /* Labelled variant (e.g. "复制思考过程") — flows inline, doesn't absolute- |
| position, and always visible since it's already inside a collapsible |
| region the user has expanded. */ |
| .maka-message-copy[data-labelled="true"] { |
| position: static; |
| width: auto; |
| height: auto; |
| display: inline-flex; |
| align-items: center; |
| gap: var(--space-1-5); |
| padding: var(--space-0-5) var(--space-2); |
| font-size: var(--font-size-caption); |
| font-weight: var(--font-weight-semibold); |
| opacity: 1; |
| background: transparent; |
| } |
| /* (The user-turn meta-row copy renders via MessageCopyButton's |
| `footerStyle`, so it reuses the Marker `footer-action` shell |
| (`markerVariants('footer-action')`) directly and needs no bespoke |
| override here.) */ |
| .maka-bubble-with-actions:hover .maka-message-copy, |
| .maka-bubble-with-actions:focus-within .maka-message-copy, |
| .maka-message-copy:focus-visible { |
| opacity: 1; |
| /* Settle into the resting position when the parent bubble is |
| hovered or anything inside it gains focus. The entrance |
| translate / scale defined on .maka-message-copy resolves |
| here. */ |
| transform: translateY(0) scale(1); |
| } |
| .maka-message-copy:hover { |
| color: var(--foreground); |
| background: var(--state-hover-bg); |
| box-shadow: 0 1px 3px oklch(from var(--foreground) l c h / 0.08); |
| } |
| .maka-message-copy[data-copied="true"] { |
| color: var(--success-text); |
| background: oklch(from var(--success) l c h / 0.08); |
| opacity: 1; |
| } |
| .maka-message-copy[data-pending="true"] { |
| cursor: progress; |
| opacity: 1; |
| } |
| .maka-message-copy[data-copy-feedback="failed"] { |
| color: var(--destructive); |
| background: oklch(from var(--destructive) l c h / 0.08); |
| opacity: 1; |
| } |
| |
| /* --- User-turn meta row (relocated from tool-output.css) ----------------- */ |
| /* PR-CHAT-CHROME-FOLLOWUP-0 / PR5 CHAT-MESSAGE-TIME-0: the relative time is |
| always visible now (it was `opacity: 0` until hover, which hid it on |
| touch + from assistive tech). It stays quiet — caption tier (11px) at |
| normal weight, muted — and rides in the user turn's meta row beneath |
| the block. Aligned to the same tier the footer-action cva uses (text-xs). */ |
| .maka-message-time-inline { |
| display: inline-block; |
| color: var(--muted-foreground); |
| font-size: var(--font-size-caption); |
| font-weight: var(--font-weight-normal); |
| line-height: var(--leading-none); |
| font-variant-numeric: tabular-nums; |
| white-space: nowrap; |
| } |
| |
| /* User turn meta row: quiet time + a copy affordance, right-aligned |
| beneath the message block (the parent `Message role="user"` aligns its |
| items to flex-end, so this row shrink-wraps and hugs the right edge). */ |
| .maka-message-meta { |
| display: inline-flex; |
| align-items: center; |
| gap: var(--space-1-5); |
| } |
| |
| /* Turn summary / lineage rows / footer measure column folded into the |
| `@maka/ui` Marker chat primitive's own variants (issue #332 PR2 — |
| packages/ui/src/primitives/chat.tsx); the layout is now location- |
| independent instead of keyed on a `[data-role="assistant"]` descendant. */ |
| |
| [data-slot="message"] pre { |
| margin: 0; |
| font: inherit; |
| } |
| |
| /* System-note pill. Ties (0,2,1) with `.maka-prose .maka-code-block pre`, |
| which now sits later in the cascade (prose.css imports after this file) — |
| so a fenced code block inside a system note would render as a full code |
| block, not this pill. No system note carries a <pre> today (they're |
| plain-text labels from SYSTEM_NOTE_LABELS), so the pill only ever styles |
| bare <pre> without code-block chrome. */ |
| [data-slot="message"][data-role="system"] pre { |
| display: inline-flex; |
| border-radius: var(--radius-pill); |
| background: oklch(from var(--info) l c h / 0.08); |
| color: var(--info-text); |
| padding: var(--space-0-5) var(--space-1-5); |
| font-size: var(--font-size-caption); |
| } |