style(ui): rework light/dark theme to make it visually consistent

Rework the color system around warm neutrals and route hardcoded
surfaces through theme tokens for consistency.

- Theme tokens (index.css, ThemeContext): warm cream light mode and
  neutral charcoal dark mode, replacing the pure-white/blue-tinted
  palette; update PWA theme-color meta
- Code blocks: soft grey background in light mode via
  oneLight/oneDark, and drop the Tailwind Typography <pre> shell that
  framed the highlighter in a dark box
- Dropdowns/panels: convert CommandMenu, Quick Settings, and the JSON
  response block from hardcoded gray/slate to popover/muted/border
  tokens
- Git panel: Publish button purple -> primary blue
- Composer: drop top padding so the input sits flush with the thread
This commit is contained in:
Haileyesus
2026-06-29 23:45:00 +03:00
parent e71f3bf3f6
commit 032258b260
14 changed files with 98 additions and 82 deletions

View File

@@ -197,7 +197,7 @@ export default function ChatComposer({
const hasPendingPermissions = pendingPermissionRequests.length > 0;
return (
<div className="chat-composer-shell flex-shrink-0 p-2 pb-2 sm:p-4 sm:pb-4 md:p-4 md:pb-6">
<div className="chat-composer-shell flex-shrink-0 px-2 pb-2 pt-0 sm:px-4 sm:pb-4 md:px-4 md:pb-6">
{!hasPendingPermissions && (
<ActivityIndicator activity={activity} onAbort={onAbortSession} />
)}

View File

@@ -226,7 +226,7 @@ export default function CommandMenu({
return renderInPortal(
<div
ref={menuRef}
className="command-menu command-menu-empty border border-gray-200 bg-white/95 text-sm text-gray-500 dark:border-gray-700/80 dark:bg-gray-900/95 dark:text-gray-400"
className="command-menu command-menu-empty border border-border bg-popover/95 text-sm text-muted-foreground"
style={{
...menuBaseStyle,
...menuPosition,
@@ -247,15 +247,15 @@ export default function CommandMenu({
ref={menuRef}
role="listbox"
aria-label="Available commands"
className="command-menu border border-gray-200/90 bg-white/95 text-gray-900 dark:border-slate-700/80 dark:bg-slate-950/95 dark:text-slate-100"
className="command-menu border border-border bg-popover/95 text-popover-foreground"
style={{ ...menuBaseStyle, ...menuPosition, opacity: 1, transform: 'translateY(0)' }}
>
{orderedNamespaces.map((namespace) => (
<div key={namespace} className="command-group">
{orderedNamespaces.length > 1 && (
<div className="flex items-center justify-between px-2 pb-1.5 pt-2 text-[10px] font-semibold uppercase tracking-wide text-gray-500 dark:text-slate-400">
<div className="flex items-center justify-between px-2 pb-1.5 pt-2 text-[10px] font-semibold uppercase tracking-wide text-muted-foreground">
<span>{namespaceLabels[namespace] || namespace}</span>
<span className="rounded border border-gray-200 bg-gray-50 px-1.5 py-0.5 text-[10px] text-gray-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400">
<span className="rounded border border-border bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground">
{(groupedCommands[namespace] || []).length}
</span>
</div>
@@ -273,15 +273,15 @@ export default function CommandMenu({
aria-selected={isSelected}
className={`command-item group relative mb-1 flex cursor-pointer items-start gap-2 rounded-md border px-2.5 py-2 transition-all ${
isSelected
? 'border-sky-200 bg-sky-50 shadow-sm dark:border-cyan-400/30 dark:bg-cyan-400/10'
: 'border-transparent bg-transparent hover:border-gray-200 hover:bg-gray-50/90 dark:hover:border-slate-700 dark:hover:bg-slate-900/80'
? 'border-primary/30 bg-primary/10 shadow-sm'
: 'border-transparent bg-transparent hover:border-border hover:bg-accent'
}`}
onMouseEnter={() => onSelect && commandIndex >= 0 && onSelect(command, commandIndex, true)}
onClick={() => onSelect && commandIndex >= 0 && onSelect(command, commandIndex, false)}
onMouseDown={(event) => event.preventDefault()}
>
{isSelected && (
<span className="absolute bottom-1.5 left-1.5 top-1.5 w-0.5 rounded-full bg-sky-500 dark:bg-cyan-300" />
<span className="absolute bottom-1.5 left-1.5 top-1.5 w-0.5 rounded-full bg-primary" />
)}
<span className={`mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-md border ${accentClass}`}>
<NamespaceIcon aria-hidden="true" size={14} strokeWidth={2.2} />
@@ -289,20 +289,20 @@ export default function CommandMenu({
<div className="min-w-0 flex-1 pr-1">
<div className={`flex min-w-0 items-center gap-2 ${command.description ? 'mb-1' : 'mb-0'}`}>
<span
className="min-w-0 truncate font-mono text-[13px] font-semibold text-gray-950 dark:text-slate-50"
className="min-w-0 truncate font-mono text-[13px] font-semibold text-foreground"
title={command.name}
>
{command.name}
</span>
{command.metadata?.type && (
<span className="command-metadata-badge shrink-0 rounded border border-gray-200 bg-white px-1.5 py-0.5 text-[10px] font-medium text-gray-500 shadow-sm dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300">
<span className="command-metadata-badge shrink-0 rounded border border-border bg-muted px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground shadow-sm">
{command.metadata.type}
</span>
)}
</div>
{command.description && (
<div
className="truncate whitespace-nowrap text-[12px] leading-4 text-gray-500 dark:text-slate-400"
className="truncate whitespace-nowrap text-[12px] leading-4 text-muted-foreground"
title={command.description}
>
{command.description}
@@ -310,7 +310,7 @@ export default function CommandMenu({
)}
</div>
{isSelected && (
<span className="mt-1 flex h-6 w-6 shrink-0 items-center justify-center rounded border border-sky-200 bg-white text-sky-600 shadow-sm dark:border-cyan-400/30 dark:bg-slate-950 dark:text-cyan-200">
<span className="mt-1 flex h-6 w-6 shrink-0 items-center justify-center rounded border border-primary/30 bg-card text-primary shadow-sm">
<CornerDownLeft aria-hidden="true" size={13} strokeWidth={2.2} />
</span>
)}

View File

@@ -4,11 +4,12 @@ import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { oneDark, oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { useTranslation } from 'react-i18next';
import { normalizeInlineCodeFences } from '../../utils/chatFormatting';
import { copyTextToClipboard } from '../../../../utils/clipboard';
import { usePaletteOps } from '../../../../contexts/PaletteOpsContext';
import { useTheme } from '../../../../contexts/ThemeContext';
type MarkdownProps = {
children: React.ReactNode;
@@ -59,6 +60,7 @@ type CodeBlockProps = {
const CodeBlock = ({ node, inline, className, children, ...props }: CodeBlockProps) => {
const { t } = useTranslation('chat');
const { isDarkMode } = useTheme();
const [copied, setCopied] = useState(false);
const raw = Array.isArray(children) ? children.join('') : String(children ?? '');
const looksMultiline = /[\r\n]/.test(raw);
@@ -96,7 +98,7 @@ const CodeBlock = ({ node, inline, className, children, ...props }: CodeBlockPro
}
})
}
className="absolute right-2 top-2 z-10 rounded-md border border-gray-600 bg-gray-700/80 px-2 py-1 text-xs text-white opacity-0 transition-opacity hover:bg-gray-700 focus:opacity-100 active:opacity-100 group-hover:opacity-100"
className="absolute right-2 top-2 z-10 rounded-md border border-border bg-card/90 px-2 py-1 text-xs text-foreground/80 opacity-0 transition-opacity hover:bg-muted focus:opacity-100 active:opacity-100 group-hover:opacity-100"
title={copied ? t('codeBlock.copied') : t('codeBlock.copyCode')}
aria-label={copied ? t('codeBlock.copied') : t('codeBlock.copyCode')}
>
@@ -132,17 +134,20 @@ const CodeBlock = ({ node, inline, className, children, ...props }: CodeBlockPro
<SyntaxHighlighter
language={language}
style={oneDark}
style={isDarkMode ? oneDark : oneLight}
customStyle={{
margin: 0,
borderRadius: '0.5rem',
borderRadius: '0.75rem',
fontSize: '0.875rem',
padding: language && language !== 'text' ? '2rem 1rem 1rem 1rem' : '1rem',
// ChatGPT-style soft grey block in light mode; keep oneDark's own bg in dark.
...(isDarkMode ? {} : { background: 'hsl(var(--muted))' }),
}}
codeTagProps={{
style: {
fontFamily:
'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
...(isDarkMode ? {} : { background: 'transparent' }),
},
}}
>
@@ -154,6 +159,10 @@ const CodeBlock = ({ node, inline, className, children, ...props }: CodeBlockPro
const markdownComponents = {
code: CodeBlock,
// CodeBlock renders its own syntax-highlighted <pre>; this passthrough stops
// react-markdown (and Tailwind Typography) from wrapping it in a second,
// dark-themed <pre> shell that would frame the block.
pre: ({ children }: { children?: React.ReactNode }) => <>{children}</>,
blockquote: ({ children }: { children?: React.ReactNode }) => (
<blockquote className="my-2 border-l-4 border-gray-300 pl-4 italic text-gray-600 dark:border-gray-600 dark:text-gray-400">
{children}

View File

@@ -377,15 +377,15 @@ const MessageComponent = memo(({ message, prevMessage, createDiff, onFileOpen, a
return (
<div className="my-2">
<div className="mb-2 flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400">
<div className="mb-2 flex items-center gap-2 text-sm text-muted-foreground">
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
<span className="font-medium">{t('json.response')}</span>
</div>
<div className="overflow-hidden rounded-lg border border-gray-600/30 bg-gray-800 dark:border-gray-700 dark:bg-gray-900">
<div className="overflow-hidden rounded-lg border border-border bg-muted">
<pre className="overflow-x-auto p-4">
<code className="block whitespace-pre font-mono text-sm text-gray-100 dark:text-gray-200">
<code className="block whitespace-pre font-mono text-sm text-foreground">
{formatted}
</code>
</pre>

View File

@@ -1,8 +1,9 @@
import { useState } from 'react';
import type { ComponentProps } from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark as prismOneDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { oneDark as prismOneDark, oneLight as prismOneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
import { copyTextToClipboard } from '../../../../../utils/clipboard';
import { useTheme } from '../../../../../contexts/ThemeContext';
type MarkdownCodeBlockProps = {
inline?: boolean;
@@ -16,6 +17,7 @@ export default function MarkdownCodeBlock({
node: _node,
...props
}: MarkdownCodeBlockProps) {
const { isDarkMode } = useTheme();
const [copied, setCopied] = useState(false);
const rawContent = Array.isArray(children) ? children.join('') : String(children ?? '');
const looksMultiline = /[\r\n]/.test(rawContent);
@@ -50,20 +52,22 @@ export default function MarkdownCodeBlock({
setTimeout(() => setCopied(false), 2000);
}
})}
className="absolute right-2 top-2 z-10 rounded-md border border-gray-600 bg-gray-700/80 px-2 py-1 text-xs text-white opacity-0 transition-opacity hover:bg-gray-700 group-hover:opacity-100"
className="absolute right-2 top-2 z-10 rounded-md border border-border bg-card/90 px-2 py-1 text-xs text-foreground/80 opacity-0 transition-opacity hover:bg-muted group-hover:opacity-100"
>
{copied ? 'Copied!' : 'Copy'}
</button>
<SyntaxHighlighter
language={language}
style={prismOneDark}
style={isDarkMode ? prismOneDark : prismOneLight}
customStyle={{
margin: 0,
borderRadius: '0.5rem',
borderRadius: '0.75rem',
fontSize: '0.875rem',
padding: language !== 'text' ? '2rem 1rem 1rem 1rem' : '1rem',
...(isDarkMode ? {} : { background: 'hsl(var(--muted))' }),
}}
codeTagProps={{ style: isDarkMode ? {} : { background: 'transparent' } }}
>
{rawContent}
</SyntaxHighlighter>

View File

@@ -12,6 +12,9 @@ type MarkdownPreviewProps = {
const markdownPreviewComponents: Components = {
code: MarkdownCodeBlock,
// MarkdownCodeBlock renders its own highlighted <pre>; passthrough prevents a
// second Typography-styled <pre> shell from framing it.
pre: ({ children }) => <>{children}</>,
blockquote: ({ children }) => (
<blockquote className="my-2 border-l-4 border-gray-300 pl-4 italic text-gray-600 dark:border-gray-600 dark:text-gray-400">
{children}

View File

@@ -189,7 +189,7 @@ export default function GitPanelHeader({
<button
onClick={requestPublishConfirmation}
disabled={anyPending}
className="flex items-center gap-1 rounded-lg bg-purple-600 px-2.5 py-1 text-sm text-white transition-colors hover:bg-purple-700 disabled:opacity-50"
className="flex items-center gap-1 rounded-lg bg-primary px-2.5 py-1 text-sm text-primary-foreground transition-colors hover:bg-primary/90 disabled:opacity-50"
title={`Publish "${currentBranch}" to ${remoteName}`}
>
<Upload className={`h-3 w-3 ${isPublishing ? 'animate-pulse' : ''}`} />

View File

@@ -16,7 +16,7 @@ export const HANDLE_POSITION_MAX = 90;
export const DRAG_THRESHOLD_PX = 5;
export const SETTING_ROW_CLASS =
'flex items-center justify-between p-3 rounded-lg bg-gray-50 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors border border-transparent hover:border-gray-300 dark:hover:border-gray-600';
'flex items-center justify-between p-3 rounded-lg bg-muted/60 hover:bg-accent transition-colors border border-transparent hover:border-border';
export const TOGGLE_ROW_CLASS = `${SETTING_ROW_CLASS} cursor-pointer`;

View File

@@ -49,11 +49,11 @@ export default function QuickSettingsContent({
<div className="flex-1 space-y-6 overflow-y-auto overflow-x-hidden bg-background p-4">
<QuickSettingsSection title={t('quickSettings.sections.appearance')}>
<div className={SETTING_ROW_CLASS}>
<span className="flex items-center gap-2 text-sm text-gray-900 dark:text-white">
<span className="flex items-center gap-2 text-sm text-foreground">
{isDarkMode ? (
<Moon className="h-4 w-4 text-gray-600 dark:text-gray-400" />
<Moon className="h-4 w-4 text-muted-foreground" />
) : (
<Sun className="h-4 w-4 text-gray-600 dark:text-gray-400" />
<Sun className="h-4 w-4 text-muted-foreground" />
)}
{t('quickSettings.darkMode')}
</span>
@@ -68,7 +68,7 @@ export default function QuickSettingsContent({
<QuickSettingsSection title={t('quickSettings.sections.inputSettings')}>
{renderToggleRows(inputSettingToggles)}
<p className="ml-3 text-xs text-gray-500 dark:text-gray-400">
<p className="ml-3 text-xs text-muted-foreground">
{t('quickSettings.sendByCtrlEnterDescription')}
</p>
</QuickSettingsSection>

View File

@@ -5,9 +5,9 @@ export default function QuickSettingsPanelHeader() {
const { t } = useTranslation('settings');
return (
<div className="border-b border-gray-200 bg-gray-50 p-4 dark:border-gray-700 dark:bg-gray-900">
<h3 className="flex items-center gap-2 text-lg font-semibold text-gray-900 dark:text-white">
<Settings2 className="h-5 w-5 text-gray-600 dark:text-gray-400" />
<div className="border-b border-border bg-muted/40 p-4">
<h3 className="flex items-center gap-2 text-lg font-semibold text-foreground">
<Settings2 className="h-5 w-5 text-muted-foreground" />
{t('quickSettings.title')}
</h3>
</div>

View File

@@ -13,7 +13,7 @@ export default function QuickSettingsSection({
}: QuickSettingsSectionProps) {
return (
<div className={`space-y-2 ${className}`}>
<h4 className="mb-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
<h4 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
{title}
</h4>
{children}

View File

@@ -17,8 +17,8 @@ function QuickSettingsToggleRow({
}: QuickSettingsToggleRowProps) {
return (
<label className={TOGGLE_ROW_CLASS}>
<span className="flex items-center gap-2 text-sm text-gray-900 dark:text-white">
<Icon className="h-4 w-4 text-gray-600 dark:text-gray-400" />
<span className="flex items-center gap-2 text-sm text-foreground">
<Icon className="h-4 w-4 text-muted-foreground" />
{label}
</span>
<input

View File

@@ -41,7 +41,7 @@ export const ThemeProvider = ({ children }) => {
const themeColorMeta = document.querySelector('meta[name="theme-color"]');
if (themeColorMeta) {
themeColorMeta.setAttribute('content', '#0c1117'); // Dark background color (hsl(222.2 84% 4.9%))
themeColorMeta.setAttribute('content', '#141414'); // Dark background color (hsl(0 0% 8%))
}
} else {
document.documentElement.classList.remove('dark');
@@ -55,7 +55,7 @@ export const ThemeProvider = ({ children }) => {
const themeColorMeta = document.querySelector('meta[name="theme-color"]');
if (themeColorMeta) {
themeColorMeta.setAttribute('content', '#ffffff'); // Light background color
themeColorMeta.setAttribute('content', '#f6f4ef'); // Light background color (warm cream)
}
}
}, [isDarkMode]);

View File

@@ -23,37 +23,37 @@
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--background: 44 22% 96%;
--foreground: 36 25% 4%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--card-foreground: 36 25% 4%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--popover-foreground: 36 25% 4%;
--primary: 221.2 83.2% 53.3%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--secondary: 44 15% 91%;
--secondary-foreground: 36 15% 18%;
--muted: 44 15% 91%;
--muted-foreground: 40 5% 44%;
--accent: 44 15% 91%;
--accent-foreground: 36 15% 18%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--border: 44 14% 87%;
--input: 44 14% 87%;
--ring: 221.2 83.2% 53.3%;
--radius: 0.5rem;
/* Nav design tokens */
--nav-glass-bg: 0 0% 100% / 0.7;
--nav-glass-bg: 44 22% 96% / 0.7;
--nav-glass-blur: 20px;
--nav-glass-saturate: 1.8;
--nav-tab-glow: 221.2 83.2% 53.3% / 0.18;
--nav-tab-ring: 221.2 83.2% 53.3% / 0.10;
--nav-float-shadow: 0 0% 0% / 0.06;
--nav-float-ring: 214.3 31.8% 91.4% / 0.5;
--nav-divider-color: 214.3 31.8% 91.4% / 0.5;
--nav-input-bg: 210 40% 96.1% / 0.5;
--nav-float-ring: 44 14% 87% / 0.5;
--nav-divider-color: 44 14% 87% / 0.5;
--nav-input-bg: 44 15% 91% / 0.5;
--nav-input-focus-ring: 221.2 83.2% 53.3% / 0.22;
/* Safe area CSS variables */
@@ -85,36 +85,36 @@
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 217.2 91.2% 8%;
--card-foreground: 210 40% 98%;
--popover: 217.2 91.2% 8%;
--popover-foreground: 210 40% 98%;
--background: 0 0% 8%;
--foreground: 40 8% 93%;
--card: 0 0% 12%;
--card-foreground: 40 8% 93%;
--popover: 0 0% 12%;
--popover-foreground: 40 8% 93%;
--primary: 217.2 91.2% 59.8%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--primary-foreground: 0 0% 8%;
--secondary: 0 0% 17%;
--secondary-foreground: 40 8% 93%;
--muted: 0 0% 17%;
--muted-foreground: 0 0% 60%;
--accent: 0 0% 17%;
--accent-foreground: 40 8% 93%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 220 13% 46%;
--destructive-foreground: 40 8% 93%;
--border: 0 0% 17%;
--input: 0 0% 23%;
--ring: 217.2 91.2% 59.8%;
/* Nav design tokens — dark overrides */
--nav-glass-bg: 217.2 91.2% 8% / 0.55;
--nav-glass-bg: 0 0% 12% / 0.55;
--nav-glass-blur: 24px;
--nav-glass-saturate: 1.6;
--nav-tab-glow: 217.2 91.2% 59.8% / 0.25;
--nav-tab-ring: 217.2 91.2% 59.8% / 0.15;
--nav-float-shadow: 0 0% 0% / 0.35;
--nav-float-ring: 217.2 32.6% 17.5% / 0.3;
--nav-divider-color: 217.2 32.6% 17.5% / 0.5;
--nav-input-bg: 217.2 32.6% 17.5% / 0.5;
--nav-float-ring: 0 0% 17% / 0.3;
--nav-divider-color: 0 0% 17% / 0.5;
--nav-input-bg: 0 0% 17% / 0.5;
--nav-input-focus-ring: 217.2 91.2% 59.8% / 0.25;
}
}
@@ -350,7 +350,7 @@
}
.dark .scrollbar-thin::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.3);
background: rgba(38, 38, 38, 0.3);
}
.dark .scrollbar-thin::-webkit-scrollbar-thumb {
@@ -369,7 +369,7 @@
}
.dark::-webkit-scrollbar-track {
background: rgba(31, 41, 55, 0.5);
background: rgba(38, 38, 38, 0.5);
}
.dark::-webkit-scrollbar-thumb {
@@ -384,7 +384,7 @@
/* Firefox scrollbar styles */
.dark {
scrollbar-width: thin;
scrollbar-color: rgba(107, 114, 128, 0.5) rgba(31, 41, 55, 0.5);
scrollbar-color: rgba(115, 115, 115, 0.5) rgba(38, 38, 38, 0.5);
}
/* Ensure checkbox styling is preserved */
@@ -475,7 +475,7 @@
/* Fix focus-within container issues in dark mode */
.dark .focus-within\:ring-2:focus-within {
background-color: rgb(31 41 55) !important; /* gray-800 */
background-color: rgb(20 20 20) !important;
}
/* Ensure textarea remains transparent with visible text */
@@ -873,12 +873,12 @@
/* Fix focus ring offset color in dark mode */
.dark [class*="ring-offset"] {
--tw-ring-offset-color: rgb(31 41 55); /* gray-800 */
--tw-ring-offset-color: rgb(20 20 20);
}
/* Ensure buttons don't show white backgrounds in dark mode */
.dark button:focus {
--tw-ring-offset-color: rgb(31 41 55); /* gray-800 */
--tw-ring-offset-color: rgb(20 20 20);
}
/* Fix mobile select dropdown styling */
@@ -921,8 +921,8 @@
}
.dark select option {
background-color: rgb(31 41 55) !important;
color: rgb(243 244 246) !important;
background-color: rgb(31 31 31) !important;
color: rgb(237 235 230) !important;
}
/* Tool details chevron animation */