@import 'tailwindcss'; @plugin '@tailwindcss/typography'; @import 'tw-shimmer'; @import 'katex/dist/katex.min.css'; @import '@vscode/codicons/dist/codicon.css'; @custom-variant dark (&:is(.dark *)); @font-face { font-family: 'Collapse'; font-style: normal; font-weight: 700; font-display: swap; src: url('../../../node_modules/@nous-research/ui/dist/fonts/Collapse-Bold.woff2') format('woff2'); } @theme inline { --color-background: var(--dt-background); --color-foreground: var(--dt-foreground); --color-card: var(--dt-card); --color-card-foreground: var(--dt-card-foreground); --color-muted: var(--dt-muted); --color-muted-foreground: var(--dt-muted-foreground); --color-popover: var(--dt-popover); --color-popover-foreground: var(--dt-popover-foreground); --color-primary: var(--dt-primary); --color-primary-foreground: var(--dt-primary-foreground); --color-secondary: var(--dt-secondary); --color-secondary-foreground: var(--dt-secondary-foreground); --color-accent: var(--dt-accent); --color-accent-foreground: var(--dt-accent-foreground); --color-border: var(--dt-border); --color-input: var(--dt-input); --color-ring: var(--dt-ring); --color-destructive: var(--dt-destructive); --color-destructive-foreground: var(--dt-destructive-foreground); --color-midground: var(--dt-midground); --color-midground-foreground: var(--dt-midground-foreground); --font-sans: var(--dt-font-sans); --font-mono: var(--dt-font-mono); --spacing-mul: var(--dt-spacing-mul, 1); --radius-xs: calc(var(--radius-scalar) * 0.125rem); --radius-sm: calc(var(--radius-scalar) * 0.5rem); --radius-md: calc(var(--radius-scalar) * 0.625rem); --radius-lg: calc(var(--radius-scalar) * 0.75rem); --radius-xl: calc(var(--radius-scalar) * 1rem); --radius-2xl: calc(var(--radius-scalar) * 1.5rem); --radius-3xl: calc(var(--radius-scalar) * 2rem); --radius-4xl: calc(var(--radius-scalar) * 2.5rem); --color-sidebar-ring: var(--sidebar-ring); --color-sidebar-border: var(--sidebar-border); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-accent: var(--sidebar-accent); --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); --color-sidebar-primary: var(--sidebar-primary); --color-sidebar-foreground: var(--sidebar-foreground); --color-sidebar: var(--sidebar); --shadow-xs: 0 0.0625rem 0.125rem color-mix(in srgb, #000 5%, transparent); --shadow-sm: 0 0 0 0.0625rem color-mix(in srgb, var(--dt-foreground) 6%, transparent), 0 0.125rem 0.5rem color-mix(in srgb, #000 4%, transparent); --shadow-md: 0 0 0 0.0625rem color-mix(in srgb, var(--dt-foreground) 8%, transparent), 0 0.25rem 1rem color-mix(in srgb, #000 8%, transparent), 0 1rem 2rem -1.5rem color-mix(in srgb, #000 18%, transparent); /* Soft floating shadow for borderless modals/overlays. Single top light source: every layer is centered (x=0) and cast downward, with negative spread that grows with the blur so each layer is pulled horizontally inward — the shadow pools below the panel instead of bleeding out every side. Layered (contact → ambient) for a smooth, natural falloff. */ --shadow-nous: 0 0.125rem 0.25rem -0.125rem color-mix(in srgb, #000 7%, transparent), 0 0.5rem 0.75rem -0.375rem color-mix(in srgb, #000 6%, transparent), 0 1.25rem 1.75rem -0.875rem color-mix(in srgb, #000 6%, transparent), 0 2.25rem 3rem -1.75rem color-mix(in srgb, #000 0%, transparent); /* Hairline border paired with --shadow-nous on borderless overlays. currentColor resolves per-element, so it adapts to text color/theme. */ --stroke-nous: color-mix(in srgb, currentColor 3%, transparent); --shadow-lg: inset 0 0.0625rem 0 color-mix(in srgb, #fff 28%, transparent), 0 0 0 0.0625rem color-mix(in srgb, var(--dt-foreground) 8%, transparent), 0 0.75rem 2rem color-mix(in srgb, #000 12%, transparent); --shadow-composer: 0 0.0625rem 0.125rem color-mix(in srgb, #000 5%, transparent); } @layer base { :root { color-scheme: light; --theme-foreground: #17171a; --theme-primary: #0053fd; --theme-secondary: color-mix(in srgb, #0053fd 7%, #ffffff); --theme-accent-soft: color-mix(in srgb, #0053fd 10%, #ffffff); --theme-midground: #0053fd; --theme-warm: #cf806d; --theme-background-seed: #f8faff; --theme-sidebar-seed: #f3f7ff; --theme-card-seed: #ffffff; --theme-elevated-seed: #ffffff; --theme-bubble-seed: color-mix(in srgb, #0053fd 6%, #ffffff); --theme-neutral-chrome: #f3f3f3; --theme-neutral-sidebar: #f3f3f3; --theme-neutral-card: #fcfcfc; --theme-mix-chrome: 92%; --theme-mix-sidebar: 100%; --theme-mix-card: 22%; --theme-mix-elevated: 28%; --theme-mix-bubble: 0%; --theme-fill-primary-accent-mix: 16%; --theme-fill-secondary-accent-mix: 11%; --theme-fill-tertiary-accent-mix: 8%; --theme-fill-quaternary-accent-mix: 5%; --theme-fill-quinary-accent-mix: 3%; --theme-stroke-primary-accent-mix: 24%; --theme-stroke-secondary-accent-mix: 16%; --theme-stroke-tertiary-accent-mix: 10%; --theme-stroke-quaternary-accent-mix: 6%; --theme-row-hover-accent-mix: 4%; --theme-row-active-accent-mix: 8%; --theme-control-hover-accent-mix: 6%; --theme-control-active-accent-mix: 8%; --ui-base: var(--theme-foreground); --ui-accent: var(--theme-midground); --ui-accent-secondary: var(--theme-primary); --ui-warm: var(--theme-warm); --ui-red: #cf2d56; --ui-orange: #db704b; --ui-yellow: #c08532; --ui-green: #1f8a65; --ui-cyan: #4c7f8c; --ui-blue: #0053fd; --ui-purple: #9e94d5; --ui-bg-chrome: color-mix( in srgb, var(--theme-background-seed) var(--theme-mix-chrome), var(--theme-neutral-chrome) ); --ui-bg-sidebar: color-mix( in srgb, var(--theme-sidebar-seed) var(--theme-mix-sidebar), var(--theme-neutral-sidebar) ); --ui-bg-editor: color-mix(in srgb, var(--theme-card-seed) var(--theme-mix-card), var(--theme-neutral-card)); --ui-bg-elevated: color-mix( in srgb, var(--theme-elevated-seed) var(--theme-mix-elevated), var(--theme-neutral-card) ); --ui-bg-card: color-mix(in srgb, var(--ui-accent) 4%, color-mix(in srgb, var(--ui-base) 4%, transparent)); --ui-bg-input: #fcfcfc; --ui-bg-primary: color-mix( in srgb, var(--ui-accent) var(--theme-fill-primary-accent-mix), color-mix(in srgb, var(--ui-base) 10%, transparent) ); --ui-bg-secondary: color-mix( in srgb, var(--ui-accent) var(--theme-fill-secondary-accent-mix), color-mix(in srgb, var(--ui-base) 7%, transparent) ); --ui-bg-tertiary: color-mix( in srgb, var(--ui-accent) var(--theme-fill-tertiary-accent-mix), color-mix(in srgb, var(--ui-base) 5%, transparent) ); --ui-bg-quaternary: color-mix( in srgb, var(--ui-accent) var(--theme-fill-quaternary-accent-mix), color-mix(in srgb, var(--ui-base) 4%, transparent) ); --ui-bg-quinary: color-mix( in srgb, var(--ui-accent) var(--theme-fill-quinary-accent-mix), color-mix(in srgb, var(--ui-base) 3%, transparent) ); --ui-row-hover-background: color-mix( in srgb, var(--ui-accent) var(--theme-row-hover-accent-mix), color-mix(in srgb, var(--ui-base) 3%, transparent) ); --ui-row-active-background: color-mix( in srgb, var(--ui-accent) var(--theme-row-active-accent-mix), color-mix(in srgb, var(--ui-base) 5%, transparent) ); --ui-control-hover-background: color-mix( in srgb, var(--ui-accent) var(--theme-control-hover-accent-mix), color-mix(in srgb, var(--ui-base) 4%, transparent) ); --ui-control-active-background: color-mix( in srgb, var(--ui-accent) var(--theme-control-active-accent-mix), color-mix(in srgb, var(--ui-base) 5%, transparent) ); --ui-text-primary: color-mix(in srgb, var(--ui-base) 94%, transparent); --ui-text-secondary: color-mix(in srgb, var(--ui-base) 74%, transparent); --ui-text-tertiary: color-mix(in srgb, var(--ui-base) 54%, transparent); --ui-text-quaternary: color-mix(in srgb, var(--ui-base) 36%, transparent); --ui-stroke-primary: color-mix( in srgb, var(--ui-accent) var(--theme-stroke-primary-accent-mix), color-mix(in srgb, var(--ui-base) 10%, transparent) ); --ui-stroke-secondary: color-mix( in srgb, var(--ui-accent) var(--theme-stroke-secondary-accent-mix), color-mix(in srgb, var(--ui-base) 7%, transparent) ); --ui-stroke-tertiary: color-mix( in srgb, var(--ui-accent) var(--theme-stroke-tertiary-accent-mix), color-mix(in srgb, var(--ui-base) 5%, transparent) ); --ui-stroke-quaternary: color-mix( in srgb, var(--ui-accent) var(--theme-stroke-quaternary-accent-mix), color-mix(in srgb, var(--ui-base) 3%, transparent) ); --ui-sash-hover-border: color-mix(in srgb, var(--ui-accent) 18%, var(--ui-stroke-tertiary)); --ui-sash-hover-background: color-mix(in srgb, var(--ui-accent) 6%, transparent); --ui-surface-background: var(--ui-bg-editor); --ui-sidebar-surface-background: var(--ui-bg-sidebar); --ui-chat-surface-background: var(--ui-bg-chrome); --ui-editor-surface-background: var(--ui-bg-chrome); --ui-chat-bubble-background: color-mix( in srgb, var(--theme-bubble-seed) var(--theme-mix-bubble), var(--theme-neutral-card) ); --ui-chat-bubble-opaque-background: var(--ui-bg-editor); --ui-inline-code-background: color-mix(in srgb, #141414 5%, transparent); --ui-inline-code-border: color-mix(in srgb, #141414 8%, transparent); --ui-inline-code-foreground: color-mix(in srgb, #141414 88%, transparent); --ui-selection-background: color-mix(in srgb, #ffd24a 55%, transparent); --dt-background: var(--ui-bg-chrome); --dt-foreground: var(--ui-text-primary); --dt-card: var(--ui-bg-editor); --dt-card-foreground: var(--ui-text-primary); --dt-muted: var(--ui-bg-tertiary); --dt-muted-foreground: var(--ui-text-tertiary); --dt-popover: color-mix(in srgb, var(--ui-bg-elevated) 96%, transparent); --dt-popover-foreground: var(--ui-text-primary); --dt-primary: var(--theme-primary); --dt-primary-foreground: #fcfcfc; --dt-secondary: var(--theme-secondary); --dt-secondary-foreground: var(--ui-text-secondary); --dt-accent: var(--theme-accent-soft); --dt-accent-foreground: var(--ui-text-primary); --dt-border: var(--ui-stroke-secondary); --dt-input: var(--ui-stroke-primary); --dt-ring: var(--ui-stroke-primary); --dt-midground: var(--theme-midground); --dt-composer-ring: var(--ui-base); --dt-destructive: #cf2d56; --dt-destructive-foreground: #ffffff; --dt-sidebar-bg: var(--ui-bg-sidebar); --dt-sidebar-border: var(--ui-stroke-secondary); --dt-user-bubble: var(--ui-chat-bubble-background); --dt-user-bubble-border: var(--ui-stroke-tertiary); --dt-font-sans: 'Segoe WPC', 'Segoe UI', -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji', emoji; --dt-font-mono: 'Cascadia Code', 'JetBrains Mono', 'SF Mono', ui-monospace, Menlo, Consolas, monospace, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji', emoji; --dt-base-size: 1rem; --dt-line-height: 1.5; --dt-letter-spacing: 0; --dt-spacing-mul: 1; --radius: 0.75rem; --radius-scalar: 0.6; /* Space under last message vs overlay composer — driven by the measured composer height (see composer/index.tsx). */ --thread-last-message-clearance: calc(var(--composer-measured-height) + 2rem); --composer-shell-pad-block-end: 0.625rem; --message-text-indent: 0.75rem; --conversation-text-font-size: 0.8125rem; --conversation-tool-font-size: 0.6875rem; --conversation-caption-font-size: 0.75rem; --conversation-line-height: 1.125rem; --conversation-caption-line-height: 1rem; --conversation-turn-gap: 0.375rem; /* Gap between top-level turn blocks (prose ↔ tools ↔ thinking) — enough air that scaffolding reads as separate from the reply, not crammed into it. */ --turn-block-gap: 0.75rem; /* Tight gap between tool rows inside a single action group, so a back-to-back run still reads as one cohesive sequence. */ --tool-row-gap: 0.375rem; /* Paragraph spacing — vertical gap between prose paragraphs, both inside a markdown block and between consecutive prose parts. Single knob; tweak freely. */ --paragraph-gap: 0.45rem; --sticky-human-top: 0.23rem; --file-tree-row-height: 1.375rem; --composer-width: 48.75rem; --composer-control-size: 1.75rem; --composer-control-primary-size: 1.875rem; --composer-control-gap: 0.25rem; --composer-row-gap: 0.25rem; --composer-ring-strength: 1; --composer-surface-pad-x: 0.5rem; --composer-surface-pad-y: 0.3125rem; --composer-input-min-height: 1.625rem; --composer-input-max-height: 9.375rem; --composer-input-inline-min-width: 8rem; --composer-fallback-height: 2.75rem; --composer-measured-height: calc(0.5rem + var(--composer-shell-pad-block-end) + var(--composer-fallback-height)); --composer-surface-measured-height: var(--composer-fallback-height); --thread-viewport-height: max( 0rem, calc(100% - var(--composer-measured-height) + var(--composer-surface-measured-height)) ); --vsq: min(0.5vh, 0.5vw); --image-preview-max-width: 34rem; --image-preview-height: clamp(16.25rem, calc(var(--vsq) * 100), 26.25rem); --sidebar-width: 14.8125rem; --chat-min-width: 28rem; --titlebar-control-size: 1.25rem; --titlebar-control-height: 1.375rem; --sidebar-content-inline-padding: 1rem; --sidebar: var(--dt-sidebar-bg); --sidebar-foreground: var(--dt-foreground); --sidebar-primary: var(--dt-primary); --sidebar-primary-foreground: var(--dt-primary-foreground); --sidebar-accent: var(--ui-control-active-background); --sidebar-accent-foreground: var(--dt-accent-foreground); --sidebar-border: var(--dt-sidebar-border); --sidebar-ring: var(--dt-ring); --sidebar-edge-border: color-mix(in srgb, var(--ui-base) 7.5%, transparent); --chrome-action-hover: var(--ui-control-hover-background); --midground: var(--dt-midground); --background: var(--dt-background); --foreground: var(--dt-foreground); --warm-glow: color-mix(in srgb, var(--ui-warm) 32%, color-mix(in srgb, var(--ui-accent) 6%, transparent)); /* `--noise-opacity-mul` is set per-mode by `applyTheme()`. */ --noise-opacity-mul: 1; --backdrop-invert-mul: 1; } :root.dark { /* Per-mode mix knobs — overridden inline by `applyTheme()` per skin. */ --theme-mix-chrome: 74%; --theme-mix-card: 38%; --theme-mix-elevated: 46%; --theme-mix-bubble: 46%; --theme-neutral-chrome: #0d0d0e; --theme-neutral-sidebar: #0a0a0b; --theme-neutral-card: #161618; /* Dark-only accent palette overrides. */ --ui-red: #e75e78; --ui-green: #55a583; --ui-cyan: #6f9ba6; --sidebar-edge-border: color-mix(in srgb, var(--ui-base) 12%, transparent); --composer-ring-strength: 1.3; --backdrop-invert-mul: 0; --ui-inline-code-background: color-mix(in srgb, #ffffff 7%, transparent); --ui-inline-code-border: color-mix(in srgb, #ffffff 10%, transparent); --ui-inline-code-foreground: color-mix(in srgb, #ffffff 88%, transparent); --ui-selection-background: color-mix(in srgb, #ffd24a 38%, transparent); } * { box-sizing: border-box; border-color: var(--dt-border); } html, body, #root { height: 100%; } html { font-size: var(--dt-base-size, 0.875rem); } body { margin: 0; background: var(--ui-chat-surface-background); color: var(--dt-foreground); font-family: var(--dt-font-sans); font-size: 0.8125rem; line-height: var(--dt-line-height, 1.55); letter-spacing: var(--dt-letter-spacing, 0); overflow: hidden; -webkit-user-select: none; user-select: none; -webkit-font-smoothing: antialiased; } button, textarea { font: inherit; } :where( a, .underline, [class~='hover:underline'], [class~='focus:underline'], [class~='focus-visible:underline'], [class~='group-hover:underline'], [class~='peer-hover:underline'] ) { text-decoration-color: color-mix(in srgb, currentColor 20%, transparent); text-underline-offset: 0.25rem; } *::selection { background: var(--ui-selection-background); color: inherit; } } .dither { background: repeating-conic-gradient(currentColor 0% 25%, transparent 0% 50%) 0 0 / 0.125rem 0.125rem; } :root:not([style*='--theme-asset-bg:']) .theme-default-filler { display: block; } :root[style*='--theme-asset-bg:'] .theme-default-filler { display: none; } /* Primitive-level pointer cursor for every interactive control (buttons, selects, menu items, switches, tabs, summaries). Keeps individual components from having to hardcode `cursor-pointer`; explicit cursor utilities (cursor-grab, cursor-default, disabled:cursor-*) still win since they live in the utilities layer. */ @layer base { button:not(:disabled):not([aria-disabled='true']), summary, [role='button']:not([aria-disabled='true']), [role='menuitem']:not([aria-disabled='true']), [role='menuitemradio']:not([aria-disabled='true']), [role='menuitemcheckbox']:not([aria-disabled='true']), [role='option']:not([aria-disabled='true']), [role='switch']:not([aria-disabled='true']), [role='tab']:not([aria-disabled='true']) { cursor: pointer; } } @layer utilities { [class*='rounded-full'], [class*=':rounded-full'] { border-radius: calc(var(--radius-scalar) * 9999rem); } } @keyframes arc-border { 0% { background-position: 15% 15%; } 100% { background-position: 75% 75%; } } .arc-border { --arc-c0: color-mix(in srgb, var(--dt-foreground) 0%, transparent); --arc-c1: var(--dt-midground); --arc-c2: var(--dt-background); --arc-angle: 160deg; --arc-width: 0.078125rem; --arc-inset: -0.125rem; --arc-duration: 2.23s; pointer-events: none; position: absolute; overflow: hidden; border-radius: inherit; inset: var(--arc-inset); padding: var(--arc-width); mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; } :root.dark .arc-border { --arc-c1: var(--dt-foreground); } /* Quest-style "needs you" pulse for a clarify-blocked session's dot — a soft amber glow that breathes so the row draws the eye without a toast. */ @keyframes quest-glow { 0%, 100% { transform: scale(1); box-shadow: 0 0 0.1875rem color-mix(in srgb, var(--color-amber-500, #f59e0b) 70%, transparent), 0 0 0.5rem color-mix(in srgb, var(--color-amber-500, #f59e0b) 45%, transparent); } 50% { transform: scale(1.18); box-shadow: 0 0 0.3125rem color-mix(in srgb, var(--color-amber-500, #f59e0b) 90%, transparent), 0 0 0.875rem color-mix(in srgb, var(--color-amber-500, #f59e0b) 65%, transparent); } } .quest-glow { animation: quest-glow 1.8s ease-in-out infinite; } @media (prefers-reduced-motion: reduce) { .quest-glow { animation: none; box-shadow: 0 0 0.25rem color-mix(in srgb, var(--color-amber-500, #f59e0b) 80%, transparent), 0 0 0.625rem color-mix(in srgb, var(--color-amber-500, #f59e0b) 55%, transparent); } } /* Command-palette deep-link: briefly flash the targeted settings row. */ @keyframes setting-field-flash { 0% { background-color: color-mix(in srgb, var(--dt-primary, #f59e0b) 22%, transparent); } 100% { background-color: transparent; } } .setting-field-highlight { animation: setting-field-flash 1.6s ease-out; } @media (prefers-reduced-motion: reduce) { .setting-field-highlight { animation: none; } } .arc-border::before { content: ''; position: absolute; inset: 0; border-radius: inherit; background: linear-gradient( var(--arc-angle), transparent 0%, var(--arc-c0) 15%, var(--arc-c1) 20%, var(--arc-c2) 25%, transparent 35%, transparent 40%, var(--arc-c0) 55%, var(--arc-c1) 60%, var(--arc-c2) 65%, transparent 75%, transparent 80%, var(--arc-c0) 95%, var(--arc-c1) 100% ); background-size: 300% 300%; animation: arc-border var(--arc-duration) linear infinite; } /* Flip the arc's travel direction (e.g. the Nous Portal hero row). */ .arc-border.arc-reverse::before { animation-direction: reverse; } /* Nous Portal hero: slower, blue → orange arc. */ .arc-border.arc-nous, :root.dark .arc-border.arc-nous { --arc-c1: #4f8cff; --arc-c2: #ff8c42; --arc-duration: 3.27s; } @media (prefers-reduced-motion: reduce) { .arc-border::before { animation: none; } } /* No focus rings, anywhere. Kills the native outline plus Tailwind's `focus-visible:ring-*` (a box-shadow driven by --tw-ring-*). Unlayered so it beats the utilities layer without !important on the outline. The composer / .desktop-input-chrome focus glow is untouched — those set `box-shadow` directly rather than through the ring vars. */ *:focus, *:focus-visible { outline: none; } *:focus-visible { --tw-ring-shadow: 0 0 #0000 !important; --tw-ring-offset-shadow: 0 0 #0000 !important; } button { -webkit-app-region: no-drag; } /* Button variant styling lives entirely in the cva in components/ui/button.tsx (the single source of truth). Don't re-add [data-slot='button'] rules here — attribute selectors out-specify the Tailwind utilities and silently override the variants. */ [data-slot='dropdown-menu-content'], [data-slot='select-content'], [data-slot='dialog-content'] { border-color: var(--ui-stroke-secondary); background: color-mix(in srgb, var(--ui-bg-elevated) 96%, transparent); box-shadow: var(--shadow-md); backdrop-filter: blur(0.75rem) saturate(1.08); -webkit-backdrop-filter: blur(0.75rem) saturate(1.08); } [data-slot='dropdown-menu-item']:focus, [data-slot='dropdown-menu-checkbox-item']:focus, [data-slot='dropdown-menu-radio-item']:focus { background: var(--ui-bg-tertiary); color: var(--ui-text-primary); } input, textarea, [contenteditable]:not([contenteditable='false']), [data-slot='aui_user-message-root'], [data-slot='aui_assistant-message-content'], [data-selectable-text='true'], [data-selectable-text='true'] * { -webkit-user-select: text; user-select: text; } button, [role='button'] { -webkit-user-select: none; user-select: none; } img, picture, video, canvas, svg { -webkit-user-select: none; user-select: none; } img, video, canvas { -webkit-user-drag: none; } /* Shared input chrome — mirrors composer hover/focus FX. Unlayered to beat Tailwind utilities. */ .desktop-input-chrome { --ring-pct: 18%; --ring-fall: var(--dt-input); background: color-mix(in srgb, var(--dt-card) 68%, transparent); border-color: color-mix( in srgb, var(--dt-composer-ring) calc(var(--ring-pct) * var(--composer-ring-strength)), var(--ring-fall) ); box-shadow: none; transition: background-color 200ms ease-out, border-color 200ms ease-out; } .desktop-input-chrome:hover { --ring-pct: 30%; background: color-mix(in srgb, var(--dt-card) 86%, transparent); } .desktop-input-chrome:focus { --ring-pct: 45%; --ring-fall: transparent; background: var(--dt-card); box-shadow: none; outline: none; } .desktop-input-chrome[aria-invalid='true'] { border-color: var(--dt-destructive); } @layer components { .scrollbar-dt, .scrollbar-dt * { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--dt-midground) 18%, transparent) transparent; } .scrollbar-dt::-webkit-scrollbar, .scrollbar-dt *::-webkit-scrollbar { width: 0.5rem; height: 0.5rem; } .scrollbar-dt::-webkit-scrollbar-track, .scrollbar-dt::-webkit-scrollbar-corner, .scrollbar-dt *::-webkit-scrollbar-track, .scrollbar-dt *::-webkit-scrollbar-corner { background: transparent; } .scrollbar-dt::-webkit-scrollbar-thumb, .scrollbar-dt *::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--dt-midground) 18%, transparent); border-radius: 9999rem; border: 0.125rem solid transparent; background-clip: padding-box; } .scrollbar-dt::-webkit-scrollbar-thumb:hover, .scrollbar-dt *::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--dt-midground) 40%, transparent); background-clip: padding-box; } .scrollbar-dt::-webkit-scrollbar-button, .scrollbar-dt *::-webkit-scrollbar-button { display: none; } /* Variant for portaled overlays (Radix DropdownMenu, Popover, etc.) that render under document.body, outside the `.scrollbar-dt` scope on #root. Same visual treatment, applied directly to the overlay container so its (and only its) internal scrollbar is themed. */ .dt-portal-scrollbar { scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--dt-midground) 28%, transparent) transparent; } .dt-portal-scrollbar::-webkit-scrollbar { width: 0.375rem; height: 0.375rem; } .dt-portal-scrollbar::-webkit-scrollbar-track, .dt-portal-scrollbar::-webkit-scrollbar-corner { background: transparent; } .dt-portal-scrollbar::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--dt-midground) 28%, transparent); border-radius: 9999rem; border: 0.0625rem solid transparent; background-clip: padding-box; } .dt-portal-scrollbar::-webkit-scrollbar-thumb:hover { background: color-mix(in srgb, var(--dt-midground) 50%, transparent); background-clip: padding-box; } .dt-portal-scrollbar::-webkit-scrollbar-button { display: none; } } /* Bottom clearance lives on [data-slot='aui_composer-clearance'] — virtualized items unmount, so :nth-last-child can't fire reliably. */ [data-slot='aui_assistant-message-content'] { padding-left: var(--message-text-indent); font-size: var(--conversation-text-font-size); line-height: 1.5; } [data-slot='aui_assistant-message-root'] { width: 100%; } [data-slot='aui_assistant-message-content'] .aui-md, [data-slot='aui_assistant-message-content'] .aui-md :where(p, li, blockquote, table, pre) { font-size: inherit; } /* Tailwind Typography sets `.prose :where(p) { margin: 1.25em }` (~16px). That selector ties our `my-*` utility on specificity and wins on source order, so paragraph spacing must be reclaimed here at higher specificity. One tight top-margin (bottom zeroed to avoid doubling), first child reset to flush. */ [data-slot='aui_assistant-message-content'] .aui-md :where(p) { margin-block: var(--paragraph-gap) 0; } /* First rendered element of a prose block is flush — the block-level gap above (tool / paragraph) already provides the separation. Reach one level deep too: Streamdown wraps blocks in a `div.space-y-*`, so the real first line is the first child's first child. */ [data-slot='aui_assistant-message-content'] .aui-md > :first-child, [data-slot='aui_assistant-message-content'] .aui-md > :first-child > :first-child { margin-top: 0; } /* Prose, tools, todos, and thinking all share one left edge (the message content's --message-text-indent). No extra prose indent — a single gutter reads cleaner than a ragged tool-vs-reply column. */ [data-slot='aui_user-message-root'] { top: var(--sticky-human-top); } [data-slot='aui_user-message-root'], [data-slot='aui_edit-composer-root'] { font-size: var(--conversation-text-font-size); } /* Sticky human bubbles clamp to ~2 lines with a soft bottom fade so a long prompt doesn't dominate the viewport. The clamp lifts on focus only (clicking opens the edit composer, which shows the full text) — not on hover, so the bubble doesn't jump as the pointer passes over it. --human-msg-full is the measured content height (set in UserMessage) so it animates to the real height instead of overshooting the cap. */ .sticky-human-clamp { cursor: pointer; max-height: calc(2 * var(--dt-line-height) * var(--conversation-text-font-size) + 0.15rem); overflow: hidden; transition: max-height 0.08s cubic-bezier(0.4, 0, 0.2, 1); } .sticky-human-clamp[data-clamped='true'] { -webkit-mask-image: linear-gradient(to bottom, #000 55%, transparent); mask-image: linear-gradient(to bottom, #000 55%, transparent); } .composer-human-message:focus-within .sticky-human-clamp { max-height: min(var(--human-msg-full, 24rem), 24rem); overflow-y: auto; -webkit-mask-image: none; mask-image: none; } /* The thread renders items in natural document flow (padding spacers, not transforms) and @tanstack/react-virtual already adjusts scrollTop itself when an off-screen turn is measured and its real height differs from the 220px estimate. The browser's native scroll anchoring (overflow-anchor: auto) would adjust scrollTop for that SAME size delta, so the two double-correct and the view lurches — most visibly on Windows mouse wheels, whose coarse notches mount/measure several under-estimated turns per tick. Opt out of native anchoring so only the virtualizer compensates. */ [data-slot='aui_thread-viewport'] { overflow-anchor: none; } [data-slot='aui_thread-content'] { max-width: var(--composer-width); padding-inline: 1.5rem; } [data-slot='aui_intro'] { align-items: center; justify-content: center; padding-bottom: var(--composer-measured-height); text-align: center; } [data-slot='aui_intro'] > div { max-width: min(var(--composer-width), 82vw); } [data-slot='aui_intro'] p:last-child { max-width: 34rem; margin-inline: auto; color: var(--ui-text-tertiary); font-size: 0.875rem; line-height: 1.45; } .fit-text { display: flex; font-size: var(--fit-text-min, 1rem); container-type: inline-size; --captured-length: initial; --support-sentinel: var(--captured-length, 9999px); } .fit-text > [aria-hidden='true'] { visibility: hidden; } .fit-text > :not([aria-hidden='true']) { flex-grow: 1; container-type: inline-size; --captured-length: 100cqi; --available-space: var(--captured-length); } .fit-text > :not([aria-hidden='true']) > * { display: block; inline-size: var(--available-space); line-height: var(--fit-text-line-height, 1); --support-sentinel: inherit; --captured-length: 100cqi; --ratio: tan(atan2(var(--available-space), var(--available-space) - var(--captured-length))); --font-size: clamp( var(--fit-text-min, 1em), 1em * var(--ratio), var(--fit-text-max, infinity * 1px) - var(--support-sentinel) ); font-size: var(--font-size); } @container (inline-size > 0) { .fit-text > :not([aria-hidden='true']) > * { white-space: nowrap; } } @property --captured-length { syntax: ''; initial-value: 0px; inherits: true; } @property --captured-length2 { syntax: ''; initial-value: 0px; inherits: true; } [data-slot='composer-root'] { width: min(var(--composer-width), calc(100% - 2rem)); padding-bottom: var(--composer-shell-pad-block-end); } [data-slot='composer-root'] > .pointer-events-none { background: linear-gradient( to bottom, transparent, color-mix(in srgb, var(--ui-chat-surface-background) 88%, transparent) ) !important; } [data-slot='composer-surface'] { border-color: var(--ui-stroke-secondary) !important; } [data-slot='composer-fade'] { min-height: 2.375rem; } [data-slot='composer-rich-input'] { color: var(--ui-text-primary); font-size: 0.8125rem; } [data-slot='composer-rich-input']:empty::before { color: var(--ui-text-tertiary) !important; } [data-slot='composer-root']:focus-within [data-slot='composer-surface'] > [aria-hidden='true'] { background: var(--ui-chat-bubble-background) !important; } /* Tool/thinking blocks now live at message-text alignment (no leading chevron column to escape into), so their headers and bodies share a common left edge with the model's text. */ [data-slot='aui_assistant-message-content'] > [data-slot='tool-block'], [data-slot='aui_assistant-message-content'] > [data-slot='aui_thinking-disclosure'] { width: 100%; max-width: 100%; } [data-slot='aui_assistant-message-content'] .aui-md [data-streamdown='code-block'] code { max-width: none; font-family: inherit; font-size: inherit; padding: 0; border-radius: 0; background: transparent; color: inherit; overflow-x: visible; overflow-wrap: inherit; vertical-align: baseline; word-break: inherit; white-space: inherit; } /* Streamdown's adapter wraps code fences in a `data-streamdown="code-block"` container with its own card chrome. We render our own , so this strips the upstream chrome down to a layout-only passthrough. */ [data-slot='aui_assistant-message-content'] .aui-md [data-streamdown='code-block'] { contain: none; overflow: visible; margin-block: var(--paragraph-gap) 0 !important; padding: 0 !important; gap: 0 !important; border: 0 !important; border-radius: 0 !important; background: transparent !important; color: inherit; } [data-slot='aui_assistant-message-content'] .aui-md [data-streamdown='code-block']:has(.aui-prose-fence) { margin-block: 0 !important; } [data-slot='aui_assistant-message-content'] .aui-md [data-slot='code-card'] { /* Streamdown nests blocks, so the container's child-combinator rhythm can't reach the card. Carry the paragraph gap on the card itself (top-owned); collapses cleanly with the wrapper's margin when one is present, and the first-child reset still flushes a leading code block. */ margin-block: var(--paragraph-gap) 0; position: relative; transition: border-color 180ms ease-out, box-shadow 180ms ease-out, background-color 180ms ease-out; } [data-slot='aui_assistant-message-content'] .aui-md [data-slot='code-card'][data-streaming='true'] { animation: code-card-stream-enter 180ms cubic-bezier(0.16, 1, 0.3, 1) both, code-card-stream-glow 1.8s ease-in-out 180ms infinite alternate; border-color: color-mix(in srgb, var(--dt-ring) 24%, var(--ui-stroke-tertiary)); box-shadow: 0 0 0 0.0625rem color-mix(in srgb, var(--dt-ring) 10%, transparent), 0 0.625rem 1.75rem color-mix(in srgb, var(--dt-ring) 8%, transparent); } [data-slot='aui_assistant-message-content'] .aui-md [data-slot='code-card'][data-streaming='true'] [data-slot='code-card-body'] { -webkit-mask-image: linear-gradient(to bottom, black 0%, black calc(100% - 1.5rem), rgb(0 0 0 / 64%) 100%); mask-image: linear-gradient(to bottom, black 0%, black calc(100% - 1.5rem), rgb(0 0 0 / 64%) 100%); } [data-slot='aui_assistant-message-content'] .aui-md :not(pre) > code { border: 0.0625rem solid var(--ui-inline-code-border); background: var(--ui-inline-code-background); color: var(--ui-inline-code-foreground); } [data-slot='aui_assistant-message-content'] .aui-md :where(.aui-shiki, .aui-shiki > pre) { margin: 0 !important; } [data-slot='aui_assistant-message-content'] .aui-md .aui-md-table { border-spacing: 0; } [data-slot='aui_assistant-message-content'] .aui-md .aui-md-table > table, [data-slot='aui_assistant-message-content'] .aui-md .aui-md-table thead, [data-slot='aui_assistant-message-content'] .aui-md .aui-md-table tbody, [data-slot='aui_assistant-message-content'] .aui-md .aui-md-table tr, [data-slot='aui_assistant-message-content'] .aui-md .aui-md-table th, [data-slot='aui_assistant-message-content'] .aui-md .aui-md-table td { margin: 0 !important; margin-block-start: 0 !important; margin-block-end: 0 !important; } /* Tool / thinking blocks are scaffolding around the model's reply, so we keep them transparent and fade them slightly. The reading column (prose) stays at full strength; scaffolding lifts back to full opacity on hover/focus so it stays legible when the user actually wants to read it. */ [data-slot='tool-block'], [data-slot='aui_thinking-disclosure'] { background: transparent !important; } [data-slot='aui_assistant-message-content'] > :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure']) { opacity: 0.67; transition: opacity 120ms ease-out; } [data-slot='aui_assistant-message-content'] > :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure']):is(:hover, :focus-within) { opacity: 1; } /* Conversation block rhythm. assistant-ui renders each range as a direct child of the message content with no per-part wrapper, so adjacency rules cover every pairing — first block needs no reset, nested tool rows are untouched. Two tiers: scaffolding (tool / thinking) gets a roomy block gap so it reads as separate from the reply; consecutive prose collapses to a tight paragraph rhythm so split-out text parts don't look like a big gap. */ /* Scaffolding adjacent to anything → roomy block gap. */ [data-slot='aui_assistant-message-content'] > :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure']) + :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure'], .aui-md), [data-slot='aui_assistant-message-content'] > .aui-md + :is([data-slot='tool-block'], [data-slot='aui_thinking-disclosure']) { margin-top: var(--turn-block-gap); } /* Prose ↔ prose → tight paragraph rhythm, matching in-block paragraph spacing. */ [data-slot='aui_assistant-message-content'] > .aui-md + .aui-md { margin-top: var(--paragraph-gap); } /* Message action bars — flat icon hits with default dim; only the hovered/focused control is full-strength. */ [data-slot='aui_msg-actions'] button { border: 0; border-radius: 0; background: transparent; box-shadow: none; padding: 0; gap: 0; height: auto; width: auto; min-height: 0; min-width: 0; flex-shrink: 0; cursor: pointer; color: var(--color-muted-foreground); opacity: 0.5; } [data-slot='aui_msg-actions'] button:disabled { cursor: default; } [data-slot='aui_msg-actions'] button:hover { background: transparent; color: var(--color-foreground); opacity: 1; } [data-slot='aui_msg-actions'] button:active { background: transparent; } [data-slot='aui_msg-actions'] button:focus-visible { opacity: 1; } [data-slot='aui_msg-actions'] button svg { width: 0.875rem; height: 0.875rem; } /* Live thinking preview window. Pairs with the ResizeObserver in ThinkingDisclosure that pins scrollTop to the bottom — older lines fade into the top mask while the latest tokens settle in below. */ .thinking-preview { -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 28%, black 100%); mask-image: linear-gradient(to bottom, transparent 0%, black 28%, black 100%); } @keyframes code-card-stream-enter { from { opacity: 0.74; transform: translateY(0.375rem); } to { opacity: 1; transform: translateY(0); } } @keyframes code-card-stream-glow { from { border-color: color-mix(in srgb, var(--dt-ring) 18%, var(--ui-stroke-tertiary)); box-shadow: 0 0 0 0.0625rem color-mix(in srgb, var(--dt-ring) 6%, transparent), 0 0.5rem 1.5rem color-mix(in srgb, var(--dt-ring) 5%, transparent); } to { border-color: color-mix(in srgb, var(--dt-ring) 32%, var(--ui-stroke-tertiary)); box-shadow: 0 0 0 0.0625rem color-mix(in srgb, var(--dt-ring) 12%, transparent), 0 0.75rem 2rem color-mix(in srgb, var(--dt-ring) 10%, transparent); } } @media (prefers-reduced-motion: reduce) { [data-slot='aui_assistant-message-content'] .aui-md [data-slot='code-card'][data-streaming='true'] { animation: none; } } /* ── Keybind panel / edit overlay: small key chips ────────────────────────── A quiet `kbd`-style chip shared by the shortcuts panel and the on-screen editor so both read as the same control. No animation, no glow. */ .kbd-cap { display: inline-grid; place-items: center; min-width: 1.5rem; height: 1.4rem; padding: 0 0.4rem; border-radius: 0.375rem; font-family: var(--dt-font-mono, ui-monospace, monospace); font-size: 0.72rem; font-weight: 500; line-height: 1; color: color-mix(in srgb, var(--dt-foreground) 82%, transparent); background: color-mix(in srgb, var(--ui-bg-elevated) 70%, transparent); border: 1px solid var(--ui-stroke-secondary); box-shadow: inset 0 -1px 0 color-mix(in srgb, var(--ui-stroke-tertiary) 50%, transparent); } /* Unbound slot: a hollow dashed chip inviting a binding. */ .kbd-cap--ghost { color: color-mix(in srgb, var(--dt-foreground) 42%, transparent); background: none; border-style: dashed; border-color: var(--ui-stroke-tertiary); box-shadow: none; font-style: italic; } /* Waiting for a keypress: solid accent, no motion. */ .kbd-capturing { color: var(--theme-primary); border-color: color-mix(in srgb, var(--theme-primary) 55%, var(--ui-stroke-secondary)) !important; border-style: solid; background: color-mix(in srgb, var(--theme-primary) 9%, var(--ui-bg-elevated)); box-shadow: none; }