| /* Composer — outer container, controls, pickers, tool buttons, send/workspace/branch/streaming. Composer block merged in from tool-output.css (was misplaced there) — issue #546 PR3. Runtime interaction prompt styles live in interaction-prompts.css. */ |
| .composer { |
| flex: 0 0 auto; |
| display: flex; |
| flex-direction: column; |
| align-items: center; |
| padding: var(--space-2) var(--space-6) var(--space-2); |
| /* PR-GRAY-CARD-LIFT-5 (WAWQAQ msg `d4277aba` round 3): the composer |
| outer used to paint a vertical white-fade over `--background`, |
| designed for the older parchment shell where the page bg was |
| warm-white. Now that `--background` itself is pure white and the |
| shell is a visibly gray `--surface-canvas`, the composer outer |
| painted itself white-on-white, defeating the gray-plate / white- |
| card lift. Switch to transparent so the gray plate shows around |
| the composer card. */ |
| background: transparent; |
| } |
| |
| .maka-composer-astryx { |
| width: min(var(--maka-chat-measure), 100%); |
| max-width: var(--maka-chat-measure); |
| } |
| |
| /* Row-flow, not the old stacked column: image thumbnails and file/quote |
| chips share one wrapping row. `width: 100%` is what makes the wrap real: |
| as a flex item of Astryx's drawer content this group would otherwise size |
| to max-content, run past the drawer edge, and get clipped by the drawer |
| root's overflow:hidden — the drawer must grow DOWN, never rightward. */ |
| .maka-composer-context-drawer { |
| display: flex; |
| width: 100%; |
| min-width: 0; |
| flex-wrap: wrap; |
| align-items: center; |
| gap: var(--space-1-5); |
| flex-direction: row; |
| padding: var(--space-1) var(--space-3) var(--space-2); |
| } |
| |
| /* Astryx ChatComposerDrawer wraps its content in a display:grid whose single |
| implicit column sizes to the content's max-content contribution — with a |
| long chip row that resolves WIDER than the grid (measured: 896px column in |
| a 648px grid), so the row wrapped against a phantom width and everything |
| past the drawer's right edge was clipped. Pin the column to the grid's own |
| width; the group above then wraps against the real edge. The content region |
| is the child carrying the disclosure id (aria-controls target). */ |
| .maka-composer-astryx .astryx-chat-composer-drawer > div[id] { |
| grid-template-columns: minmax(0, 1fr); |
| } |
| |
| /* The collapse toggle is a full-width 20px band whose only visible affordance |
| is a 20×2px pill — its aria-label («收起附加内容» / «展开附加内容») was |
| unreadable for sighted users, and a native `title` needs a ~1s motionless |
| hover that a thin band rarely gets. Surface the label as an instant CSS |
| tooltip instead: `attr(aria-label)` tracks the live attribute, so the text |
| flips with the collapse state and stays localized with no JS. |
| |
| Placement is the hard constraint: the drawer root clips its own box |
| (overflow:hidden for the collapse animation), so the bubble can't rise |
| above the band, and the input card paints ABOVE the drawer (body z-index 2 |
| vs drawer 1 — that overlap is the card's design), so anything hanging |
| below the collapsed band gets covered. The one strip clear of both is the |
| band's own height — within it the bubble tracks the pointer horizontally |
| (--maka-drawer-tooltip-x, set by the drawer's onPointerMove in |
| composer.tsx), falling back to beside the pill for keyboard focus. */ |
| .maka-composer-astryx .astryx-chat-composer-drawer > [role='button'][aria-controls] { |
| position: relative; |
| } |
| |
| .maka-composer-astryx .astryx-chat-composer-drawer > [role='button'][aria-controls]::after { |
| /* local: --maka-drawer-tooltip-x — bubble x within the band, written by |
| the drawer's onPointerMove in composer.tsx (cleared on pointer leave); |
| the fallback beside the pill serves keyboard focus. */ |
| content: attr(aria-label); |
| position: absolute; |
| top: 50%; |
| left: var(--maka-drawer-tooltip-x, calc(50% + 20px)); |
| transform: translateY(-50%); |
| padding: 3px 8px; |
| border-radius: var(--radius-control); |
| /* Astryx's fixed tooltip pair (same as Thumbnail's remove scrim): legible |
| in both themes without borrowing surface tokens for text. 11px matches |
| Astryx's own tooltip type — a lockstep exception, not the product scale. */ |
| background-color: var(--color-overlay); |
| color: var(--color-on-dark); |
| font-size: 11px; |
| line-height: 1.4; |
| white-space: nowrap; |
| pointer-events: none; |
| opacity: 0; |
| visibility: hidden; |
| transition: opacity var(--duration-quick) var(--ease-out-strong); |
| z-index: var(--z-tooltip); |
| } |
| |
| .maka-composer-astryx .astryx-chat-composer-drawer > [role='button'][aria-controls]:hover::after, |
| .maka-composer-astryx .astryx-chat-composer-drawer > [role='button'][aria-controls]:focus-visible::after { |
| opacity: 1; |
| visibility: visible; |
| } |
| |
| /* Staged attachments share the quote chips' Token rhythm (maintainer |
| decision on the #2367 follow-up); the drawer stays a flat chip row. Cap |
| the chip and let Astryx Token's own ellipsis truncate, so a full |
| z-library book title cannot span the drawer — the full name rides the |
| chip's hover Tooltip instead. */ |
| .maka-composer-context-drawer .maka-composer-attachment-token { |
| max-width: min(280px, 100%); |
| } |
| |
| .maka-composer-input { |
| position: relative; |
| display: flex; |
| flex-direction: column; |
| gap: var(--space-1-5); |
| min-width: 0; |
| } |
| |
| .maka-composer-left-controls, |
| .maka-composer-right-controls { |
| display: flex; |
| align-items: center; |
| /* PR-REFERENCE-PIXEL-8 (WAWQAQ msg `f79de85f` round 8): reference implementation's |
| bundle uses gap values centered on 4-8px (extracted from |
| `globals-UfMzAdiO.css` — 4px is the most common gap, 12px never |
| appears as a toolbar gap). Maka's 12px composer toolbar gap |
| read as too loose vs reference implementation's tighter density. 8px keeps |
| individual controls separable while pulling them into one |
| coherent toolbar group. */ |
| gap: var(--space-1-5); |
| flex-wrap: wrap; |
| } |
| |
| /* Shrinkable so the `flex-wrap: wrap` above can actually engage. At |
| `flex: 0 0 auto` this box sizes to max-content, which means it never has a |
| width to wrap inside — it just overflows, and the overflow runs under the |
| send button and past the card's right edge. That stayed invisible while the |
| row held four controls; the project picker adds to it and a 480px window has |
| nowhere to put the overflow. `min-width: 0` because the default |
| `auto` floor would keep the same overflow for a long model name. */ |
| .maka-composer-left-controls { |
| flex: 1 1 auto; |
| min-width: 0; |
| } |
| |
| .maka-composer-right-controls { |
| flex: 0 0 auto; |
| justify-content: flex-end; |
| } |
| |
| /* Quiet footer: + and permission are both ghost icon buttons. */ |
| .maka-composer-left-controls .permissionModeIcon, |
| .maka-composer-left-controls .maka-composer-plus-menu { |
| display: inline-flex; |
| align-items: center; |
| } |
| |
| /* Cursor: product-wide native-cursor.css (maka.legacy) owns default vs pointer. */ |
| |
| /* Astryx sm list density: DropdownMenuItem + Selector options use |
| padding-block: var(--spacing-1) (4px) when size=sm. RadioItem only sizes its |
| radio glyph from menuSize and never applies itemSizeStyles, so it stays on |
| Item balanced (8px) and permission rows look taller than + / model. Quiet |
| menus force the sm block pad so all three composer popouts share one ladder. |
| Use product --space-1 (same 4px step as Astryx --spacing-1). Upstream |
| should wire itemSizeStyles into RadioItem; drop this when it does. */ |
| .maka-composer-quiet-menu [role="menuitemradio"] { |
| padding-block: var(--space-1); |
| } |
| |
| /* Astryx sizes the popover to its widest row (min-width:anchor-size, no max). |
| The model menu lost the 260px/56vw option-label cap with the Selector, so |
| the menu itself needs the ceiling: a long model name (BYOK catalogs love |
| `vendor/a-very-long-model-name`) must wrap inside the panel, never push it |
| off the window. Rows already wrap (Item has no nowrap) and the panel has |
| overflow-y:auto for the tall direction. */ |
| .maka-composer-quiet-menu { |
| max-width: min(320px, 92vw); |
| } |
| |
| /* Model chip (static fallback) still owns its own quiet geometry. */ |
| .maka-composer-model-chip { |
| font: var(--maka-text-label); |
| /* #1879: was a bare 26px. It is NOT an Astryx component — `ModelChipStatic` |
| puts this class only on its inert `<span>` branch; the `onOpenSettings` |
| branch renders a `Button size="sm"` that carries no class at all |
| (chat-model-switcher.tsx). So nothing sizes this box but this rule, and |
| unpinning it measured 22px (the label role's 20px line box plus two |
| hairlines) against the 28px Selector beside it. `--h-control-md` resolves |
| to `--size-element-sm`, which is the token that Selector's own `size="sm"` |
| reads — so the two agree by deriving from one token rather than by two |
| product rules agreeing on a literal. */ |
| height: var(--h-control-md); |
| display: inline-flex; |
| align-items: center; |
| justify-content: center; |
| gap: var(--space-1); |
| padding: 0 var(--space-2); |
| border: var(--border-width-hairline) solid transparent; |
| border-radius: var(--radius-pill); |
| background: transparent; |
| color: var(--foreground-secondary); |
| white-space: nowrap; |
| max-width: min(180px, 28vw); |
| transition: |
| background-color var(--duration-base) var(--ease-out-strong), |
| color var(--duration-base) var(--ease-out-strong); |
| } |
| .maka-composer-model-chip:hover { |
| background: var(--state-hover-bg); |
| color: var(--foreground); |
| border-color: transparent; |
| } |
| |
| /* Mode ON marks sit at the tail of the footer's left controls (#1897) — |
| session state, not context staged for the next send, so they no longer live |
| in the drawer. |
| |
| Maka blue is the single product accent (DESIGN.md), and an active mode is |
| exactly what it is for; which mode a mark is comes from its icon, not a hue, |
| so all three share the one accent. The wash derives from currentColor so a |
| disabled mark dims both layers together. |
| |
| `background-color`, never the `background` shorthand: the shorthand would |
| suppress the ghost button's hover and active overlays and leave the one way |
| out of a mode with no pointer feedback. |
| `flex: 0 0 auto` keeps a long model name from compressing the mark away. */ |
| .maka-composer-mode-button { |
| flex: 0 0 auto; |
| color: var(--accent); |
| background-color: color-mix(in srgb, currentColor 10%, transparent); |
| } |
| /* Model + thinking pair lives in left-controls (after permission), not send. */ |
| .maka-composer-left-controls .maka-model-selection-controls { |
| min-width: 0; |
| max-width: min(420px, 52vw); |
| } |
| .maka-composer-left-controls .maka-model-switcher-trigger, |
| .maka-composer-left-controls .maka-new-chat-model-selector { |
| min-width: 100px; |
| max-width: min(220px, 28vw); |
| } |
| |
| .maka-composer-model-chip-text { |
| min-width: 0; |
| overflow: hidden; |
| text-overflow: ellipsis; |
| white-space: nowrap; |
| } |
| |
| .maka-composer-model-status { |
| width: 6px; |
| height: 6px; |
| border-radius: var(--radius-pill); |
| background: var(--destructive); |
| flex: 0 0 auto; |
| } |
| |
| /* The active transcript and docked card meet at one boundary. Keeping the |
| outer composer's default top padding here exposes an extra strip of panel |
| background after the transcript viewport has already ended. */ |
| .mainColumn:not([data-home-surface="true"]) .composer { |
| padding-top: 0; |
| } |
| |
| /* U3 no-model dead-end hint. Sits ABOVE the composer form (outside its box, so |
| it never touches the #740 constant footprint). Edged, not pill; quiet caption |
| text + one link-button into Settings · 模型. Theme-aware via tokens. Centered to the chat measure, matching the revision-notice layout. */ |
| .maka-composer-no-model-hint { |
| font: var(--maka-text-supporting); |
| display: flex; |
| align-items: center; |
| gap: var(--space-2); |
| width: min( |
| var(--maka-chat-measure), |
| calc(100% - (2 * var(--space-6)) - (2 * var(--space-3))) |
| ); |
| max-width: var(--maka-chat-measure); |
| margin: 0 auto var(--space-1-5); |
| padding: var(--space-1) var(--space-2-5); |
| border: var(--border-width-hairline) solid var(--warning); |
| border-radius: var(--radius-control); |
| color: var(--foreground-secondary); |
| } |
| |
| .maka-composer-no-model-hint-action { |
| font: var(--maka-text-supporting); |
| flex-shrink: 0; |
| color: var(--link); |
| text-decoration: none; |
| border-radius: var(--radius-control); |
| } |
| |
| .maka-composer-no-model-hint-action:hover { |
| text-decoration: underline; |
| } |
| |
| .maka-composer-no-model-hint-action:focus-visible { |
| outline: var(--focus-ring-width) solid var(--focus-ring); |
| outline-offset: var(--focus-ring-offset); |
| } |
| |
| /* Edit-and-resend notice. A single quiet inline pill above the composer form, |
| matching the composer toolbar chip family (not a heavy info card). */ |
| .maka-composer-revision-notice { |
| font: var(--maka-text-supporting); |
| display: flex; |
| align-items: center; |
| gap: var(--space-1-5); |
| width: min( |
| var(--maka-chat-measure), |
| calc(100% - (2 * var(--space-6)) - (2 * var(--space-3))) |
| ); |
| max-width: var(--maka-chat-measure); |
| margin: 0 auto var(--space-1); |
| padding: 0 var(--space-1-5); |
| box-sizing: border-box; |
| /* #1879: was `height: 26px`, an off-ruler literal. The floor is arithmetic |
| under `border-box`: a 20px supporting line box plus two hairline borders |
| needs 22px, so `--h-control-sm` (24px) is the smallest tier that holds it |
| without clipping. Loses 2px. */ |
| height: var(--h-control-sm); |
| border: var(--border-width-hairline) solid var(--border); |
| border-radius: var(--radius-pill); |
| background: var(--background-elevated); |
| color: var(--foreground-secondary); |
| } |
| |
| .maka-composer-revision-notice > svg { |
| flex: 0 0 auto; |
| color: var(--muted-foreground); |
| } |
| |
| .maka-composer-revision-notice-text { |
| min-width: 0; |
| flex: 1 1 auto; |
| display: flex; |
| align-items: baseline; |
| gap: var(--space-1); |
| overflow: hidden; |
| white-space: nowrap; |
| } |
| |
| .maka-composer-revision-notice-detail { |
| color: var(--muted-foreground); |
| overflow: hidden; |
| text-overflow: ellipsis; |
| } |
| |
| /* #1879: the one site in this family where the old height was not merely |
| off-ruler but smaller than the line box it renders — measured, an 18px box |
| around a 20px line box, and `display: block` so the text was not centred |
| either. Nothing clipped (the 2px excess is half-leading, and there is no |
| `overflow: hidden` here), but a box shorter than its own line box has no |
| defensible height. `--h-control-xs` (20px) is that line box. Gains 2px. */ |
| .maka-composer-revision-notice-cancel { |
| font: var(--maka-text-supporting); |
| appearance: none; |
| flex: 0 0 auto; |
| height: var(--h-control-xs); |
| display: inline-flex; |
| align-items: center; |
| padding: 0 var(--space-1-5); |
| border: none; |
| border-radius: var(--radius-pill); |
| background: transparent; |
| color: var(--muted-foreground); |
| white-space: nowrap; |
| transition: background-color var(--duration-base) var(--ease-out-strong), color var(--duration-base) var(--ease-out-strong); |
| } |
| |
| .maka-composer-revision-notice-cancel:hover:not(:disabled) { |
| background: var(--state-hover-bg); |
| color: var(--foreground); |
| } |
| |
| .maka-composer-revision-notice-cancel:focus-visible { |
| outline: var(--focus-ring-width) solid var(--focus-ring); |
| outline-offset: var(--focus-ring-offset); |
| } |
| |
| .maka-composer-revision-notice-cancel:disabled { |
| opacity: var(--opacity-disabled); |
| } |
| |
| /* The project picker, last in the composer footer's send-context group. It is |
| rendered only while no session owns the composer — the project is a |
| session-creation parameter. See packages/ui/src/workspace-picker.tsx. */ |
| .maka-composer-workspace { |
| display: flex; |
| align-items: center; |
| min-width: 0; |
| } |
| |
| /* Cap the open menu at the window. Astryx gives the popover |
| `min-width: anchor-size(width)` and no ceiling, and the item labels are not |
| truncated, so one long project name grows the shrink-to-fit popover past the |
| right edge of a narrow window — where the actions go with it and there is no |
| way to scroll them back. Same cap the model menus carry |
| (`.maka-composer-quiet-menu`), expressed in the workspace's own tokens. |
| |
| The panel itself must not scroll: the catalogue scrolls inside its own |
| region below, and the actions after it must stay put. Astryx caps the menu |
| at 300px with `overflow-y: auto`, which scrolls the actions too and chains |
| overscroll to the page behind the popover — lift both so the only scroller |
| in this menu is the catalogue region. */ |
| .maka-composer-workspace [role="menu"] { |
| max-width: min(320px, calc(100vw - var(--space-6))); |
| max-height: none; |
| overflow: visible; |
| } |
| |
| /* The catalogue's own scroll region — the ONLY thing that scrolls in this |
| menu. `max-height` is the budget the whole popover used to share (224px of |
| catalogue + two action rows ≈ the old 300px ceiling); `overscroll-behavior: |
| contain` stops the wheel from chaining past the catalogue's ends into the |
| page behind the popover, which is what dragged the sticky-pinned actions |
| along before. `scrollbar-gutter: stable` keeps the row width constant when |
| the scrollbar appears. */ |
| .maka-workspace-picker-scroll { |
| max-height: 224px; |
| overflow-y: auto; |
| overscroll-behavior: contain; |
| scrollbar-gutter: stable; |
| /* Ink tint, not a border — see --foreground-alpha-16 (same alpha, right family). */ |
| scrollbar-color: var(--foreground-alpha-16) transparent; |
| scrollbar-width: thin; |
| } |
| |
| /* The rule between catalogue and actions, drawn by the group's own top border. |
| `:not(:first-child)` covers first run — no projects yet — where the group |
| would open the menu with a rule dividing nothing. Nothing scrolls under the |
| group, so it needs no background of its own: the menu surface shows through |
| and Astryx keeps painting its hover and keyboard-highlight tints on the |
| rows. */ |
| .maka-composer-workspace [role="menu"] > [role="group"]:not(:first-child) { |
| border-top: 1px solid var(--border); |
| } |
| |
| .maka-workspace-picker-status { |
| font: var(--maka-text-supporting); |
| margin-left: auto; |
| color: var(--muted-foreground); |
| } |