/* ── PlainSQL — Pro AI Dark Theme ──────────────────────── */ /* Inspired by ChatGPT / Claude / Cursor */ /* Monochromatic indigo accent · No gradients on UI chrome */ *, *::before, *::after { box-sizing: border-box; } :root { --bg: #0a0a0a; --surface-1: #111111; --surface-2: #171717; --surface-3: #1e1e1e; --surface-4: #282828; --line: rgba(255, 255, 255, 0.08); --line-strong: rgba(255, 255, 255, 0.14); --text: #ececec; --muted: #a1a1a1; --subtle: #737373; --faint: #525252; --accent: #6366f1; --accent-hover: #818cf8; --accent-muted: rgba(99, 102, 241, 0.15); --accent-subtle: rgba(99, 102, 241, 0.08); --danger: #ef4444; --success: #22c55e; --warning: #eab308; --shadow: 0 1px 3px rgba(0, 0, 0, 0.3); --shadow-lg: 0 8px 32px rgba(0, 0, 0, 0.4); --font: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; --mono: "JetBrains Mono", Consolas, monospace; --sidebar-w: 280px; --radius: 10px; --radius-sm: 6px; } html, body { height: 100%; } body { margin: 0; overflow: hidden; background: var(--bg); color: var(--text); font-family: var(--font); font-size: 14px; letter-spacing: -0.01em; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } button, input, textarea, select { font: inherit; } button { color: inherit; cursor: pointer; } a { color: var(--accent); text-decoration: none; } /* ── Layout Shell ────────────────────────────────────────── */ .app-shell { display: grid; grid-template-columns: var(--sidebar-w) minmax(0, 1fr); height: 100vh; } /* ── Sidebar ─────────────────────────────────────────────── */ .sidebar { border-right: 1px solid var(--line); background: var(--surface-1); display: flex; flex-direction: column; min-height: 0; z-index: 20; } .sidebar-head { padding: 16px; border-bottom: 1px solid var(--line); } .brand { display: flex; align-items: center; gap: 10px; } .brand-mark { width: 36px; height: 36px; display: grid; place-items: center; border-radius: 8px; background: var(--accent); color: #fff; font-weight: 800; font-size: 0.7rem; letter-spacing: 0.03em; flex-shrink: 0; } .brand-copy strong { display: block; font-size: 0.92rem; font-weight: 700; color: var(--text); } .brand-copy span { display: block; margin-top: 2px; color: var(--subtle); font-size: 0.72rem; } .new-chat { width: 100%; margin-top: 14px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: transparent; color: var(--text); min-height: 38px; padding: 0 12px; font-weight: 600; font-size: 0.82rem; transition: background 150ms ease, border-color 150ms ease; } .new-chat:hover { background: var(--surface-3); border-color: var(--accent); } .sidebar-scroll { flex: 1; overflow-y: auto; padding: 12px 10px; } /* Scrollbar styling */ .sidebar-scroll::-webkit-scrollbar, .chat-scroll::-webkit-scrollbar, .table-wrap::-webkit-scrollbar { width: 6px; height: 6px; } .sidebar-scroll::-webkit-scrollbar-thumb, .chat-scroll::-webkit-scrollbar-thumb, .table-wrap::-webkit-scrollbar-thumb { background: var(--surface-4); border-radius: 6px; } .section { margin-bottom: 16px; } .section-title { display: flex; align-items: center; justify-content: space-between; padding: 0 8px 8px; color: var(--subtle); font-size: 0.68rem; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; } .history-list, .saved-list { display: grid; gap: 2px; } .side-item { width: 100%; min-height: 36px; border: 1px solid transparent; border-radius: var(--radius-sm); background: transparent; color: var(--muted); text-align: left; padding: 8px 10px; cursor: pointer; display: flex; gap: 8px; align-items: center; transition: background 120ms ease, color 120ms ease; } .side-item:hover, .side-item.active { background: var(--surface-3); color: var(--text); } .side-item.active { background: var(--accent-subtle); color: var(--accent-hover); } .side-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.8rem; } .side-item small { color: var(--faint); font-size: 0.7rem; margin-left: auto; flex-shrink: 0; } /* Schema panel */ .schema-panel { display: grid; gap: 8px; padding: 10px; background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--radius-sm); } .field-label { color: var(--subtle); font-size: 0.72rem; font-weight: 600; } .select { width: 100%; height: 36px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface-1); color: var(--text); padding: 0 10px; outline: none; font-size: 0.8rem; } .schema-meta { display: flex; align-items: center; justify-content: space-between; color: var(--subtle); font-size: 0.7rem; } .sidebar-foot { padding: 12px 14px; border-top: 1px solid var(--line); } .system-pill { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 10px; border: 1px solid rgba(34, 197, 94, 0.2); border-radius: var(--radius-sm); background: rgba(34, 197, 94, 0.06); color: var(--success); font-size: 0.72rem; font-weight: 700; } .status-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--success); flex-shrink: 0; } .system-pill.warning { border-color: rgba(234, 179, 8, 0.25); background: rgba(234, 179, 8, 0.06); color: var(--warning); } .system-pill.warning .status-dot { background: var(--warning); } /* ── Workspace / Main Area ───────────────────────────────── */ .workspace { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; min-width: 0; min-height: 0; position: relative; background: var(--bg); } .topbar { height: 52px; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 0 24px; border-bottom: 1px solid var(--line); background: var(--bg); z-index: 12; } .mobile-menu { display: none; border: 1px solid var(--line); background: var(--surface-2); border-radius: var(--radius-sm); width: 36px; height: 36px; font-size: 0.75rem; } .conversation-title { min-width: 0; } .conversation-title h1 { margin: 0; font-size: 0.88rem; font-weight: 600; color: var(--text); } .conversation-title p { margin: 2px 0 0; color: var(--subtle); font-size: 0.74rem; } .top-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; } .chip { height: 28px; display: inline-flex; align-items: center; gap: 5px; padding: 0 10px; border: 1px solid var(--line); border-radius: 999px; background: var(--surface-2); color: var(--muted); font-size: 0.7rem; font-weight: 600; white-space: nowrap; } .ghost-action { height: 30px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: transparent; color: var(--muted); padding: 0 12px; font-size: 0.74rem; font-weight: 600; cursor: pointer; transition: color 120ms ease, border-color 120ms ease; } .ghost-action:hover { color: var(--text); border-color: var(--accent); } /* ── Chat Area ───────────────────────────────────────────── */ .chat-scroll { overflow-y: auto; padding: 32px 28px 180px; min-height: 0; scroll-behavior: smooth; } .chat-inner { max-width: 820px; margin: 0 auto; display: grid; gap: 24px; } /* ── Welcome Screen ──────────────────────────────────────── */ .welcome { min-height: calc(100vh - 280px); display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: 16px; padding: 48px 20px; } .welcome-badge { display: inline-flex; align-items: center; gap: 6px; border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--muted); border-radius: 999px; padding: 6px 14px; font-size: 0.72rem; font-weight: 600; } .welcome h2 { max-width: 520px; margin: 0; font-size: 1.6rem; line-height: 1.3; font-weight: 700; color: var(--text); } .welcome h2 span { color: var(--accent); } .welcome p { max-width: 460px; margin: 0; color: var(--subtle); font-size: 0.88rem; line-height: 1.6; } .prompt-grid { width: min(640px, 100%); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin-top: 8px; } .prompt-card { min-height: 80px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-1); color: var(--text); padding: 14px; text-align: left; cursor: pointer; display: flex; flex-direction: column; gap: 6px; transition: border-color 150ms ease, background 150ms ease; } .prompt-card:hover { border-color: var(--accent); background: var(--accent-subtle); } .prompt-card strong { font-size: 0.82rem; font-weight: 600; } .prompt-card span { color: var(--subtle); font-size: 0.74rem; line-height: 1.4; } /* ── Messages ────────────────────────────────────────────── */ .message { display: grid; grid-template-columns: 30px minmax(0, 1fr); gap: 12px; align-items: start; animation: rise 200ms ease both; } .message.user { grid-template-columns: minmax(0, 1fr) 30px; } @keyframes rise { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } } .avatar { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: var(--surface-3); color: var(--subtle); font-weight: 700; font-size: 0.62rem; border: 1px solid var(--line); flex-shrink: 0; } .avatar.ai { background: var(--accent-muted); border-color: rgba(99, 102, 241, 0.25); color: var(--accent-hover); } .bubble { min-width: 0; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-1); padding: 14px 16px; line-height: 1.65; color: var(--text); font-size: 0.88rem; } .user .bubble { justify-self: end; max-width: min(640px, 92%); background: var(--accent-muted); border-color: rgba(99, 102, 241, 0.2); } .ai .bubble { width: 100%; background: transparent; border-color: var(--line); } .bubble-stream { color: var(--text); white-space: pre-wrap; min-height: 20px; } .typing-caret::after { content: ""; display: inline-block; width: 2px; height: 1em; margin-left: 3px; vertical-align: -0.12em; background: var(--accent); animation: blink 800ms steps(2, start) infinite; } @keyframes blink { 50% { opacity: 0; } } /* ── Loading State ───────────────────────────────────────── */ .loading-row { display: grid; gap: 10px; } .loading-copy { color: var(--subtle); font-size: 0.8rem; font-weight: 500; } .skeleton { height: 10px; border-radius: 4px; background: linear-gradient(90deg, var(--surface-3), var(--surface-4), var(--surface-3)); background-size: 200% 100%; animation: shimmer 1.4s ease infinite; } .skeleton:nth-child(2) { width: 75%; } .skeleton:nth-child(3) { width: 50%; } @keyframes shimmer { from { background-position: 100% 0; } to { background-position: -100% 0; } } .loading-stage { display: flex; align-items: center; gap: 8px; color: var(--accent); font-size: 0.78rem; font-weight: 600; } .loading-stage .spinner { width: 14px; height: 14px; border: 2px solid var(--surface-4); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* ── Meta Row ────────────────────────────────────────────── */ .meta-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; } .meta { border: 1px solid var(--line); border-radius: 999px; background: var(--surface-2); padding: 4px 10px; color: var(--subtle); font-size: 0.68rem; font-weight: 600; } .meta b { color: var(--text); font-family: var(--mono); font-weight: 600; } /* ── SQL / Result / Chart / Insight Blocks ────────────────── */ .sql-block, .result-block, .chart-block, .insight-block, .explanation-block, .error-box { margin-top: 12px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-1); overflow: hidden; } .block-head { min-height: 38px; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 12px; border-bottom: 1px solid var(--line); background: var(--surface-2); } .block-title { color: var(--subtle); font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; } .block-actions { display: flex; gap: 6px; flex-wrap: wrap; } .icon-button, .small-button { min-height: 28px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface-3); color: var(--muted); padding: 0 10px; cursor: pointer; font-size: 0.7rem; font-weight: 600; transition: color 120ms ease, border-color 120ms ease; } .icon-button:hover, .small-button:hover { color: var(--text); border-color: var(--accent); } .small-button.active, .chart-toggle.active { color: #fff; border-color: var(--accent); background: var(--accent); } /* SQL code */ pre { margin: 0; padding: 14px 16px; overflow: auto; color: #d4d4d8; font-family: var(--mono); font-size: 0.8rem; line-height: 1.7; white-space: pre-wrap; overflow-wrap: anywhere; } .kw { color: var(--accent-hover); font-weight: 600; } .num { color: #fbbf24; } .str { color: #34d399; } /* Result tables */ .table-wrap { overflow: auto; max-height: 360px; } table { width: 100%; border-collapse: collapse; min-width: 560px; } th, td { padding: 10px 14px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: top; } th { position: sticky; top: 0; z-index: 1; background: var(--surface-2); color: var(--subtle); font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; } td { color: var(--muted); font-family: var(--mono); font-size: 0.76rem; } tr:hover td { background: var(--accent-subtle); } /* Charts */ .chart-body { height: 320px; padding: 14px; background: var(--surface-1); } /* Insights */ .insight-block { padding: 12px 16px; background: var(--accent-subtle); border-color: rgba(99, 102, 241, 0.15); } .insight-title { margin: 0 0 8px; color: var(--accent); font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; } .insight-list { margin: 0; padding-left: 16px; color: var(--muted); font-size: 0.84rem; line-height: 1.6; } .insight-list li+li { margin-top: 5px; } /* Explanation */ .explanation-block { padding: 12px 16px; background: rgba(234, 179, 8, 0.05); border-color: rgba(234, 179, 8, 0.12); } .explanation-block p { margin: 0; color: var(--muted); line-height: 1.65; font-size: 0.84rem; } /* Errors */ .error-box { padding: 12px 16px; color: #fca5a5; background: rgba(239, 68, 68, 0.06); border-color: rgba(239, 68, 68, 0.2); font-size: 0.84rem; line-height: 1.5; } .empty-result { padding: 20px 16px; color: var(--muted); background: var(--surface-2); border-color: var(--line); text-align: center; font-size: 0.84rem; } /* Message actions (regenerate, copy) */ .message-actions { display: flex; gap: 6px; margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); } .message-actions .small-button { font-size: 0.72rem; min-height: 26px; padding: 0 10px; } .feedback-group { display: flex; gap: 4px; margin-left: auto; } .feedback-btn { font-size: 0.85rem !important; padding: 0 6px !important; min-width: 30px; transition: all 0.2s ease; opacity: 0.55; } .feedback-btn:hover { opacity: 1; transform: scale(1.15); } .feedback-btn.active { opacity: 1; background: rgba(99, 102, 241, 0.25) !important; border-color: var(--accent) !important; } /* Delete chat button in sidebar */ .side-item { position: relative; } .side-item .delete-chat { display: none; position: absolute; right: 4px; top: 50%; transform: translateY(-50%); width: 22px; height: 22px; border: none; border-radius: 4px; background: rgba(239, 68, 68, 0.15); color: var(--danger); font-size: 0.65rem; cursor: pointer; place-items: center; } .side-item:hover .delete-chat { display: grid; } .side-item .delete-chat:hover { background: rgba(239, 68, 68, 0.3); } /* Keyboard shortcut badge */ .kbd { display: inline-flex; align-items: center; gap: 2px; padding: 1px 5px; border: 1px solid var(--line-strong); border-radius: 4px; background: var(--surface-3); color: var(--faint); font-family: var(--mono); font-size: 0.62rem; font-weight: 600; } /* Summary strip */ .summary-strip { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; margin-top: 12px; } .summary-strip div { min-height: 64px; display: flex; flex-direction: column; justify-content: space-between; gap: 8px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); padding: 10px; } .summary-strip span { color: var(--subtle); font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; } .summary-strip strong { min-width: 0; color: var(--text); font-family: var(--mono); font-size: 0.86rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* ── Composer ────────────────────────────────────────────── */ .composer { position: absolute; left: 0; right: 0; bottom: 0; padding: 16px 28px 20px; background: linear-gradient(0deg, var(--bg) 78%, transparent); z-index: 10; } .composer-inner { max-width: 820px; margin: 0 auto; display: grid; gap: 8px; } .suggestions { display: flex; gap: 6px; overflow-x: auto; padding-bottom: 2px; scrollbar-width: none; } .suggestions::-webkit-scrollbar { display: none; } .suggestion { flex-shrink: 0; border: 1px solid var(--line); border-radius: 999px; background: var(--surface-2); color: var(--muted); min-height: 30px; padding: 0 12px; cursor: pointer; font-size: 0.74rem; font-weight: 600; transition: border-color 120ms ease, color 120ms ease; } .suggestion:hover { color: var(--text); border-color: var(--accent); } .composer-form { border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface-1); padding: 8px 10px; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: end; transition: border-color 200ms ease; } .composer-form:focus-within { border-color: var(--accent); } textarea { width: 100%; min-height: 42px; max-height: 150px; resize: none; border: 0; outline: 0; background: transparent; color: var(--text); padding: 10px 8px 8px; line-height: 1.5; font-size: 0.88rem; } textarea::placeholder { color: var(--faint); } .send-button { width: 36px; height: 36px; border: 0; border-radius: var(--radius-sm); background: var(--accent); color: #fff; font-weight: 700; font-size: 0.85rem; cursor: pointer; display: grid; place-items: center; transition: background 120ms ease; } .send-button:hover { background: var(--accent-hover); } .send-button:disabled { background: var(--surface-4); color: var(--faint); cursor: not-allowed; } .composer-hint { display: flex; justify-content: space-between; gap: 12px; color: var(--faint); font-size: 0.68rem; padding: 0 4px; } /* ── Toasts ──────────────────────────────────────────────── */ .toasts { position: fixed; right: 16px; bottom: 16px; display: grid; gap: 8px; z-index: 100; max-width: min(340px, calc(100vw - 32px)); } .toast { border: 1px solid var(--line-strong); border-radius: var(--radius-sm); background: var(--surface-2); color: var(--text); padding: 10px 14px; font-size: 0.8rem; animation: rise 160ms ease both; } .toast.success { border-color: rgba(34, 197, 94, 0.3); } .toast.error { border-color: rgba(239, 68, 68, 0.35); } /* ── Scrim (mobile sidebar backdrop) ─────────────────────── */ .scrim { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.6); display: none; z-index: 15; } /* ── Workspace Metrics (sidebar) — kept minimal ──────────── */ .workspace-card { display: grid; gap: 10px; padding: 10px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); } .metric-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; } .metric-grid div { min-height: 56px; display: grid; align-content: center; gap: 4px; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-1); padding: 8px; } .metric-grid strong { font-family: var(--mono); font-size: 0.96rem; color: var(--text); } .metric-grid span { color: var(--subtle); font-size: 0.66rem; font-weight: 700; text-transform: uppercase; } .pipeline { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 4px; } .pipeline span { min-height: 24px; display: grid; place-items: center; border-radius: var(--radius-sm); background: var(--surface-3); color: var(--faint); font-size: 0.6rem; font-weight: 700; } .pipeline span.active { background: var(--accent-muted); color: var(--accent); } /* ── Command Strip (welcome) ─────────────────────────────── */ .command-strip { width: min(640px, 100%); display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; } .command-strip span { min-height: 36px; display: grid; place-items: center; border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface-2); color: var(--muted); font-size: 0.72rem; font-weight: 600; } /* ── Responsive ──────────────────────────────────────────── */ @media (max-width: 1100px) { .top-actions .chip:nth-child(n+3) { display: none; } } @media (max-width: 920px) { .app-shell { grid-template-columns: 1fr; } .sidebar { position: fixed; inset: 0 auto 0 0; width: min(84vw, 300px); transform: translateX(-102%); transition: transform 180ms ease; } body.sidebar-open .sidebar { transform: translateX(0); } body.sidebar-open .scrim { display: block; } .mobile-menu { display: grid; place-items: center; } .topbar { padding: 0 16px; } .top-actions .chip:nth-child(n+2) { display: none; } .chat-scroll { padding: 20px 16px 180px; } .composer { padding: 14px 16px; } .prompt-grid { grid-template-columns: 1fr; } .welcome { min-height: calc(100vh - 300px); } .welcome h2 { font-size: 1.35rem; } .summary-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); } } @media (max-width: 560px) { .conversation-title p { display: none; } .top-actions { display: none; } .message, .message.user { grid-template-columns: 1fr; } .avatar { display: none; } .user .bubble { max-width: 100%; } .composer-hint { display: none; } .welcome h2 { font-size: 1.2rem; } .chat-scroll { padding-bottom: 190px; } .command-strip, .summary-strip { grid-template-columns: 1fr; } .prompt-card { min-height: 68px; } table { min-width: 480px; } }