- ` : this._messages.map(m => renderMsg(this, m))}
+ ${this._messages.length === 0 ? this._renderEmptyState() : this._messages.map(m => renderMsg(this, m))}
${this._waiting ? html`
diff --git a/web/components/shared/settings-page.js b/web/components/shared/settings-page.js
new file mode 100644
index 0000000..b4a2fc2
--- /dev/null
+++ b/web/components/shared/settings-page.js
@@ -0,0 +1,126 @@
+import { html, nothing } from 'lit';
+import { LightElement } from '../../lib/base.js';
+import { t, LOCALES, getLocale, setLocale, I18nMixin } from '../../lib/i18n.js';
+
+// Stable per-user avatar color: same user, same hue, everywhere (topbar twin).
+function avatarColor(name) {
+ let h = 0;
+ for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) >>> 0;
+ return `hsl(${h % 360}, 55%, 52%)`;
+}
+
+/**
+ * Mobile settings page: account card, theme + language preferences and logout.
+ * The theme chain mirrors the desktop topbar (localStorage `theme` wins over
+ * the OS preference, applied on `data-bs-theme`); the language goes through
+ * the shared `setLocale(..., { persist: true })`, which also saves it to the
+ * user profile server-side.
+ */
+export class SettingsPage extends I18nMixin(LightElement) {
+ static properties = {
+ visible: { type: Boolean },
+ _me: { state: true },
+ _theme: { state: true },
+ };
+
+ constructor() {
+ super();
+ this.visible = false;
+ this._me = null;
+ this._theme = document.documentElement.getAttribute('data-bs-theme') ?? 'light';
+ }
+
+ updated(changed) {
+ if (changed.has('visible') && this.visible) this._loadMe();
+ }
+
+ async _loadMe() {
+ try {
+ const res = await fetch('/api/auth/me');
+ if (res.ok) this._me = await res.json();
+ } catch { /* keep whatever we have */ }
+ }
+
+ _setTheme(theme) {
+ this._theme = theme;
+ document.documentElement.setAttribute('data-bs-theme', theme);
+ localStorage.setItem('theme', theme);
+ }
+
+ _setLocale(e) {
+ setLocale(e.target.value, { persist: true });
+ }
+
+ _logout() {
+ fetch('/api/auth/logout', { method: 'POST' }).then(() => window.location.reload());
+ }
+
+ render() {
+ if (!this.visible) return nothing;
+
+ const name = this._me?.display_name || this._me?.username || '';
+ const initial = name ? name.charAt(0).toUpperCase() : '?';
+ const color = this._me?.username ? avatarColor(this._me.username) : 'var(--accent)';
+ const current = getLocale();
+
+ return html`
+
+ `;
+ }
+}
+
+customElements.define('settings-page', SettingsPage);
diff --git a/web/css/mobile.css b/web/css/mobile.css
index 8dd143b..9a2a381 100644
--- a/web/css/mobile.css
+++ b/web/css/mobile.css
@@ -1,47 +1,47 @@
+/* ── Mobile theme — warm "paper" palette, aligned with the desktop ───────────
+ Consumes the shared design tokens from variables.css (loaded first):
+ --accent*, --radius-*, --card-*, --sidebar-*, --msg-*, --placeholder-color
+ and the --bs-* overrides all flip with [data-bs-theme]. Only mobile-specific
+ derivations are declared here. */
+
:root {
- --mobile-nav-height: 60px;
- --mobile-chat-size: 56px;
+ --mobile-nav-height: 64px;
+ --mobile-chat-size: 58px;
- --mobile-bg: #ffffff;
- --mobile-nav-bg: #ffffff;
- --mobile-nav-border: #dee2e6;
- --mobile-nav-color: #6c757d;
- --mobile-nav-active: #0d6efd;
- --mobile-chat-bg: #0d6efd;
+ --mobile-bg: var(--bs-body-bg);
+ --mobile-text: var(--sidebar-brand-color);
+ --mobile-text-soft: var(--sidebar-text);
+ --mobile-nav-color: var(--placeholder-color);
+ --mobile-nav-active: var(--accent);
- /* Grouped-list surfaces: a faintly recessed list "well" with raised cards
- on top, so a card reads as elevated even where it shares the page colour. */
- --mobile-list-bg: #f4f4f7;
- --mobile-card-bg: #ffffff;
- --mobile-card-border: #ececf1;
- --mobile-card-shadow: 0 1px 2px rgba(16, 24, 40, 0.06), 0 6px 16px rgba(16, 24, 40, 0.05);
+ /* Raised surfaces (nav bar, section headers) — the warm cream the desktop
+ uses for its sidebar. */
+ --mobile-chrome-bg: var(--sidebar-bg);
+ --mobile-chrome-border: var(--sidebar-divider);
- /* Raised neutral surface for the chat composer + assistant bubbles, kept
- grey/neutral on purpose so the mobile chat doesn't inherit the desktop's
- indigo-tinted --msg-assistant-bg (which reads as purple in dark mode). */
- --mobile-surface: #f2f2f7;
- --mobile-surface-text: #1c1c1e;
+ /* Grouped-list well + cards. */
+ --mobile-list-bg: var(--bs-body-bg);
+ --mobile-card-bg: var(--card-bg);
+ --mobile-card-border: var(--card-border);
+ --mobile-card-shadow: var(--card-shadow);
+
+ /* Chat surfaces. */
+ --mobile-bubble-bg: var(--msg-assistant-bg);
+ --mobile-bubble-text: var(--msg-assistant-text);
+
+ /* Semantic actions. */
+ --mobile-ok: #3d9a63;
+ --mobile-danger: #c94a3c;
}
[data-bs-theme="dark"] {
- --mobile-bg: #1c1c1e;
- --mobile-nav-bg: #1c1c1e;
- --mobile-nav-border: #3a3a3c;
- --mobile-nav-color: #8e8e93;
- --mobile-nav-active: #6ea8fe;
- --mobile-chat-bg: #0d6efd;
- --mobile-surface: #2c2c2e;
- --mobile-surface-text: #e5e5ea;
-
- /* Dark: recess the list below the page colour, raise cards above it. */
- --mobile-list-bg: #161618;
- --mobile-card-bg: #2c2c2e;
- --mobile-card-border: #3a3a3c;
- --mobile-card-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 14px rgba(0, 0, 0, 0.3);
+ --mobile-ok: #4db87a;
+ --mobile-danger: #e8836f;
}
body {
background: var(--mobile-bg);
+ color: var(--mobile-text);
color-scheme: light dark;
}
@@ -56,120 +56,6 @@ body {
mobile-app[data-native] #mobile-root { padding-top: 0; }
mobile-app[data-native] .chat-page-input-area { padding-bottom: 10px; }
-/* ── Section header ─────────────────────────────────── */
-
-.mobile-section-header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 14px 16px;
- border-bottom: 1px solid var(--mobile-nav-border);
- flex-shrink: 0;
-}
-
-.mobile-section-title {
- font-size: 1.05rem;
- font-weight: 700;
- color: var(--bs-body-color, #212529);
- display: flex;
- align-items: center;
- gap: 8px;
-}
-
-.mobile-alert-error {
- margin: 12px 16px;
- padding: 10px 14px;
- background: #f8d7da;
- color: #842029;
- border-radius: 8px;
- font-size: 0.85rem;
-}
-
-/* Refresh button in section headers (agent-inbox.css isn't loaded on mobile). */
-.inbox-refresh-btn {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: 34px;
- height: 34px;
- padding: 0;
- border: 1px solid var(--mobile-nav-border);
- border-radius: 8px;
- background: transparent;
- color: var(--mobile-nav-color);
- font-size: 1rem;
- cursor: pointer;
- -webkit-tap-highlight-color: transparent;
-}
-
-.inbox-refresh-btn:active { transform: scale(0.94); }
-
-/* ── Inbox ──────────────────────────────────────────── */
-
-.mobile-inbox {
- display: flex;
- flex-direction: column;
- height: 100%;
-}
-
-.mobile-inbox-list {
- flex: 1;
- overflow-y: auto;
- -webkit-overflow-scrolling: touch;
- padding: 12px 16px;
- display: flex;
- flex-direction: column;
- gap: 12px;
-}
-
-.inbox-section-label {
- font-size: 0.8rem;
- font-weight: 700;
- text-transform: uppercase;
- letter-spacing: 0.5px;
- color: var(--mobile-nav-color);
- display: flex;
- align-items: center;
- gap: 8px;
- margin-top: 4px;
-}
-
-/* ── Footer buttons ──────────────────────────────────── */
-
-.inbox-btn {
- flex: 1;
- display: inline-flex;
- align-items: center;
- justify-content: center;
- gap: 6px;
- padding: 12px;
- font-size: 0.9rem;
- font-weight: 600;
- border-radius: 10px;
- border: none;
- cursor: pointer;
- -webkit-tap-highlight-color: transparent;
-}
-
-.inbox-btn-approve {
- background: #198754;
- color: #fff;
-}
-
-.inbox-btn-reject {
- background: transparent;
- color: #dc3545;
- border: 1.5px solid #dc3545;
-}
-
-/* ── Empty state override (full-height inside mobile-inbox) ── */
-
-.mobile-inbox .inbox-empty {
- flex: 1;
- height: auto;
- padding: 40px 20px;
-}
-
#mobile-root {
display: flex;
flex-direction: column;
@@ -185,37 +71,258 @@ mobile-app[data-native] .chat-page-input-area { padding-bottom: 10px; }
flex-direction: column;
}
-/* ── Coming soon ────────────────────────────────────── */
+/* ── Section header ───────────────────────────────────────────────────────── */
+
+.mobile-section-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 10px;
+ padding: 13px 16px;
+ background: var(--mobile-chrome-bg);
+ border-bottom: 1px solid var(--mobile-chrome-border);
+ flex-shrink: 0;
+}
+
+.mobile-section-title {
+ font-size: 1.12rem;
+ font-weight: 700;
+ letter-spacing: -0.01em;
+ color: var(--mobile-text);
+ display: flex;
+ align-items: center;
+ gap: 9px;
+ min-width: 0;
+}
+
+.mobile-section-title > i {
+ color: var(--accent);
+ font-size: 1.05rem;
+}
+
+.mobile-alert-error {
+ margin: 12px 16px;
+ padding: 10px 14px;
+ background: rgba(var(--accent-rgb), 0.1);
+ color: var(--mobile-danger);
+ border: 1px solid rgba(var(--accent-rgb), 0.25);
+ border-radius: var(--radius-md);
+ font-size: 0.85rem;
+}
+
+/* Round ghost button in section headers (refresh, back, actions). */
+.inbox-refresh-btn,
+.chat-page-back {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 36px;
+ height: 36px;
+ padding: 0;
+ border: 1px solid var(--mobile-card-border);
+ border-radius: 50%;
+ background: var(--mobile-card-bg);
+ color: var(--mobile-text-soft);
+ font-size: 1rem;
+ cursor: pointer;
+ box-shadow: var(--mobile-card-shadow);
+ -webkit-tap-highlight-color: transparent;
+ transition: transform 0.12s, color 0.12s, border-color 0.12s;
+}
+
+.inbox-refresh-btn:active,
+.chat-page-back:active {
+ transform: scale(0.92);
+ color: var(--accent);
+ border-color: var(--accent);
+}
+
+.chat-page-back { font-size: 1.1rem; }
+
+/* ── Empty states ─────────────────────────────────────────────────────────── */
+
+.mobile-inbox .inbox-empty,
+.mobile-projects .inbox-empty {
+ flex: 1;
+ height: auto;
+ padding: 40px 20px;
+ background: transparent;
+ color: var(--mobile-text-soft);
+}
+
+.inbox-empty i {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 72px;
+ height: 72px;
+ border-radius: 22px;
+ background: var(--accent-soft);
+ color: var(--accent);
+ font-size: 1.9rem;
+ opacity: 1;
+ margin-bottom: 14px;
+}
+
+.inbox-empty p {
+ font-size: 0.92rem;
+ font-weight: 500;
+}
+
+/* ── Inbox ────────────────────────────────────────────────────────────────── */
+
+.mobile-inbox {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+}
+
+.mobile-inbox-list {
+ flex: 1;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+ padding: 14px 16px calc(14px + env(safe-area-inset-bottom));
+ background: var(--mobile-list-bg);
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.inbox-section-label {
+ font-size: 0.74rem;
+ font-weight: 700;
+ text-transform: uppercase;
+ letter-spacing: 0.07em;
+ color: var(--mobile-nav-color);
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ margin-top: 6px;
+}
+
+/* Warm badges inside the mobile inbox (Bootstrap defaults are too cold). */
+.mobile-inbox .badge.bg-warning {
+ background: rgba(217, 158, 46, 0.16) !important;
+ color: #a5720f;
+}
+.mobile-inbox .badge.bg-info {
+ background: rgba(var(--accent-rgb), 0.12) !important;
+ color: var(--accent);
+}
+.mobile-inbox .badge.bg-danger {
+ background: var(--accent) !important;
+}
+[data-bs-theme="dark"] .mobile-inbox .badge.bg-warning {
+ background: rgba(234, 179, 8, 0.18) !important;
+ color: #e8b93e;
+}
+
+/* Inbox cards on mobile: radius from the shared scale, warm surface. */
+.mobile-inbox .inbox-card {
+ border-radius: var(--radius-lg);
+ background: var(--mobile-card-bg);
+ border-color: var(--mobile-card-border);
+ box-shadow: var(--mobile-card-shadow);
+}
+
+.mobile-inbox .inbox-card-header,
+.mobile-inbox .inbox-card-footer {
+ background: var(--bs-tertiary-bg);
+}
+
+.mobile-inbox .approval-card { border-left: 4px solid #d99e2e; }
+.mobile-inbox .clarification-card { border-left: 4px solid var(--accent); }
+
+/* ── Inbox footer buttons ─────────────────────────────────────────────────── */
+
+.inbox-btn {
+ flex: 1;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 6px;
+ padding: 12px;
+ font-size: 0.92rem;
+ font-weight: 600;
+ border-radius: var(--radius-md);
+ border: none;
+ cursor: pointer;
+ -webkit-tap-highlight-color: transparent;
+ transition: transform 0.12s, filter 0.12s;
+}
+
+.inbox-btn:active { transform: scale(0.97); }
+
+.inbox-btn-approve {
+ background: var(--mobile-ok);
+ color: #fff;
+}
+
+.inbox-btn-reject {
+ background: transparent;
+ color: var(--mobile-danger);
+ border: 1.5px solid var(--mobile-danger);
+}
+
+/* Clarification answer send button + chips: warm accent instead of cold cyan. */
+.mobile-inbox .inbox-answer-send {
+ background: var(--accent);
+ color: #fff;
+ border-radius: var(--radius-md);
+}
+
+.mobile-inbox .inbox-chip:hover,
+.mobile-inbox .inbox-chip:active {
+ background: var(--accent);
+ border-color: var(--accent);
+ color: #fff;
+}
+
+.mobile-inbox .inbox-answer-input:focus {
+ border-color: var(--accent);
+ box-shadow: 0 0 0 3px var(--accent-ring);
+}
+
+/* ── Coming soon ──────────────────────────────────────────────────────────── */
.mobile-coming-soon {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
- gap: 12px;
+ gap: 14px;
height: 100%;
- color: var(--mobile-nav-color);
+ color: var(--mobile-text-soft);
}
-.mobile-coming-soon i { font-size: 2.5rem; opacity: 0.35; }
+.mobile-coming-soon i {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 72px;
+ height: 72px;
+ border-radius: 22px;
+ background: var(--accent-soft);
+ color: var(--accent);
+ font-size: 1.9rem;
+}
.mobile-coming-soon p {
margin: 0;
font-size: 0.95rem;
font-weight: 500;
- opacity: 0.6;
}
-/* ── Bottom nav ─────────────────────────────────────── */
+/* ── Bottom nav ───────────────────────────────────────────────────────────── */
.mobile-nav {
display: flex;
- align-items: center;
+ align-items: stretch;
justify-content: space-around;
- height: var(--mobile-nav-height);
- background: var(--mobile-nav-bg);
- border-top: 1px solid var(--mobile-nav-border);
- padding-bottom: env(safe-area-inset-bottom);
+ height: calc(var(--mobile-nav-height) + env(safe-area-inset-bottom));
+ background: var(--mobile-chrome-bg);
+ border-top: 1px solid var(--mobile-chrome-border);
+ padding: 6px 8px calc(6px + env(safe-area-inset-bottom));
position: relative;
z-index: 100;
}
@@ -225,62 +332,88 @@ mobile-app[data-native] .chat-page-input-area { padding-bottom: 10px; }
flex-direction: column;
align-items: center;
justify-content: center;
- gap: 2px;
+ gap: 3px;
flex: 1;
- height: 100%;
cursor: pointer;
color: var(--mobile-nav-color);
font-size: 0.62rem;
+ font-weight: 600;
+ letter-spacing: 0.01em;
user-select: none;
-webkit-tap-highlight-color: transparent;
transition: color 0.15s;
}
+.mobile-nav-item .nav-icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 46px;
+ height: 28px;
+ border-radius: 999px;
+ transition: background 0.18s, color 0.18s;
+}
+
+.mobile-nav-item i {
+ font-size: 1.25rem;
+ line-height: 1;
+}
+
.mobile-nav-item.active {
color: var(--mobile-nav-active);
}
-.mobile-nav-item i {
- font-size: 1.3rem;
- line-height: 1;
+.mobile-nav-item.active .nav-icon {
+ background: var(--accent-soft);
}
-/* ── Center chat FAB ────────────────────────────────── */
+/* ── Center chat FAB ──────────────────────────────────────────────────────── */
.mobile-nav-item.chat-btn {
position: relative;
- top: -14px;
- flex: 1.2;
+ top: -18px;
+ flex: 1.15;
}
.chat-fab {
width: var(--mobile-chat-size);
height: var(--mobile-chat-size);
border-radius: 50%;
- background: var(--mobile-chat-bg);
+ background: linear-gradient(135deg, var(--accent), var(--accent-hover));
display: flex;
align-items: center;
justify-content: center;
- box-shadow: 0 3px 10px rgba(0, 0, 0, 0.25);
+ border: 3px solid var(--mobile-bg);
+ box-shadow: 0 4px 14px rgba(var(--accent-rgb), 0.4);
transition: transform 0.15s, box-shadow 0.15s;
}
.chat-fab i {
- font-size: 1.5rem;
+ font-size: 1.45rem;
color: #fff !important;
}
+.mobile-nav-item.chat-btn .nav-icon {
+ width: auto;
+ height: auto;
+ background: none !important;
+}
+
.mobile-nav-item.chat-btn.active .chat-fab {
- box-shadow: 0 4px 14px rgba(13, 110, 253, 0.45);
- transform: scale(1.06);
+ transform: scale(1.07);
+ box-shadow: 0 6px 18px rgba(var(--accent-rgb), 0.55);
}
.mobile-nav-item.chat-btn span {
- margin-top: 6px;
- font-size: 0.6rem;
+ margin-top: 4px;
+ color: var(--mobile-nav-color);
}
-/* ── Chat page ──────────────────────────────────────── */
+.mobile-nav-item.chat-btn.active span {
+ color: var(--mobile-nav-active);
+}
+
+/* ── Chat page ────────────────────────────────────────────────────────────── */
.chat-page {
display: flex;
@@ -288,23 +421,7 @@ mobile-app[data-native] .chat-page-input-area { padding-bottom: 10px; }
flex: 1;
min-height: 0;
overflow: hidden;
-}
-
-/* Wider bubbles on narrow screens */
-.chat-page .copilot-msg {
- max-width: 96%;
- /* Allow the bubble to shrink below its content's intrinsic width so inner
- scroll containers (code/diff/table) collapse and scroll internally instead
- of widening the bubble past the viewport. */
- min-width: 0;
- font-size: 0.92rem;
-}
-
-/* Assistant bubbles use a neutral surface instead of the desktop's indigo-tinted
- --msg-assistant-bg, which clashed with the mobile neutral palette. */
-.chat-page .copilot-msg.assistant {
- background: var(--mobile-surface);
- color: var(--mobile-surface-text);
+ background: var(--mobile-bg);
}
.chat-page-header-actions {
@@ -313,6 +430,29 @@ mobile-app[data-native] .chat-page-input-area { padding-bottom: 10px; }
gap: 8px;
}
+/* Warm ghost style for the header action buttons (new session). */
+.chat-page-header-actions .btn-outline-secondary,
+.chat-page-attach-btn.btn-outline-secondary {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 36px;
+ height: 36px;
+ padding: 0;
+ border: 1px solid var(--mobile-card-border);
+ border-radius: 50%;
+ background: var(--mobile-card-bg);
+ color: var(--mobile-text-soft);
+ box-shadow: var(--mobile-card-shadow);
+}
+
+.chat-page-header-actions .btn-outline-secondary:active,
+.chat-page-attach-btn.btn-outline-secondary:active {
+ color: var(--accent);
+ border-color: var(--accent);
+ transform: scale(0.92);
+}
+
.chat-page-messages {
flex: 1;
min-height: 0;
@@ -322,56 +462,136 @@ mobile-app[data-native] .chat-page-input-area { padding-bottom: 10px; }
this, `overflow-y: auto` makes the unset x-axis compute to `auto` too. */
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
- padding: 12px 14px;
+ padding: 14px 14px;
display: flex;
flex-direction: column;
gap: 8px;
}
-.chat-page-empty {
+/* Wider bubbles on narrow screens */
+.chat-page .copilot-msg {
+ max-width: 88%;
+ /* Allow the bubble to shrink below its content's intrinsic width so inner
+ scroll containers (code/diff/table) collapse and scroll internally instead
+ of widening the bubble past the viewport. */
+ min-width: 0;
+ font-size: 0.95rem;
+ border-radius: 1.15rem;
+}
+
+.chat-page .copilot-msg.assistant {
+ background: var(--mobile-bubble-bg);
+ color: var(--mobile-bubble-text);
+ border-bottom-left-radius: 0.25rem;
+}
+
+.chat-page .copilot-msg.user {
+ border-bottom-right-radius: 0.25rem;
+}
+
+/* ── Chat hero (empty state) ──────────────────────────────────────────────── */
+
+.chat-page-hero {
+ margin: auto;
+ width: 100%;
+ max-width: 420px;
+ padding: 2rem 0.75rem;
display: flex;
flex-direction: column;
align-items: center;
- justify-content: center;
- gap: 10px;
- height: 100%;
+ text-align: center;
+}
+
+.chat-page-hero-logo {
+ width: 84px;
+ height: 84px;
+ border-radius: 24px;
+ box-shadow: var(--mobile-card-shadow);
+}
+
+.chat-page-hero-title {
+ font-size: 1.45rem;
+ font-weight: 700;
+ letter-spacing: -0.01em;
+ color: var(--mobile-text);
+ margin: 1rem 0 0.25rem;
+}
+
+.chat-page-hero-sub {
color: var(--mobile-nav-color);
+ font-size: 0.95rem;
+ margin: 0 0 1.5rem;
}
-.chat-page-empty i {
- font-size: 2rem;
- opacity: 0.4;
+.chat-page-suggestions {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+ width: 100%;
+ text-align: left;
}
-.chat-page-empty p {
- margin: 0;
- font-size: 0.9rem;
- opacity: 0.6;
+.chat-page-suggestion {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ width: 100%;
+ border: 1px solid var(--mobile-card-border);
+ background: var(--mobile-card-bg);
+ color: var(--mobile-text);
+ border-radius: var(--radius-lg);
+ padding: 12px 14px;
+ font-size: 0.92rem;
+ font-weight: 500;
+ cursor: pointer;
+ box-shadow: var(--mobile-card-shadow);
+ -webkit-tap-highlight-color: transparent;
+ transition: border-color 0.15s, transform 0.12s;
}
+.chat-page-suggestion i {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 34px;
+ height: 34px;
+ border-radius: 10px;
+ background: var(--accent-soft);
+ color: var(--accent);
+ font-size: 0.95rem;
+ flex-shrink: 0;
+}
+
+.chat-page-suggestion:active {
+ border-color: var(--accent);
+ transform: scale(0.98);
+}
+
+/* ── Composer ─────────────────────────────────────────────────────────────── */
+
.chat-page-input-area {
padding: 10px 12px;
padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px));
- border-top: 1px solid var(--mobile-nav-border);
- background: var(--mobile-bg);
+ border-top: 1px solid var(--mobile-chrome-border);
+ background: var(--mobile-chrome-bg);
flex-shrink: 0;
}
-/* Unified composer: a single bordered box wrapping the textarea and the
- toolbar below it, mirroring the desktop copilot (.copilot-composer). Uses
- the neutral mobile surface so it matches the assistant bubbles. */
+/* Unified composer: a single card wrapping the textarea and the toolbar below
+ it, mirroring the desktop copilot (.copilot-composer). */
.chat-page-composer {
display: flex;
flex-direction: column;
- border: 1px solid var(--mobile-nav-border);
- border-radius: 0.75rem;
- background: var(--mobile-surface);
+ border: 1px solid var(--mobile-card-border);
+ border-radius: var(--radius-lg);
+ background: var(--mobile-card-bg);
+ box-shadow: var(--mobile-card-shadow);
transition: border-color 0.15s, box-shadow 0.15s;
}
.chat-page-composer:focus-within {
border-color: var(--accent);
- box-shadow: 0 0 0 3px rgba(var(--accent-rgb), 0.12);
+ box-shadow: 0 0 0 3px var(--accent-ring);
}
.chat-page-textarea {
@@ -382,16 +602,20 @@ mobile-app[data-native] .chat-page-input-area { padding-bottom: 10px; }
border: none;
outline: none;
background: transparent;
- color: inherit;
- font-size: 0.95rem;
- line-height: 1.4;
- padding: 12px 14px 6px;
- min-height: 44px;
+ color: var(--mobile-text);
+ font-size: 1rem;
+ line-height: 1.45;
+ padding: 13px 14px 6px;
+ min-height: 46px;
max-height: 120px;
overflow-y: auto;
}
-/* ── Composer toolbar (below the textarea) ─────────────────────────────────── */
+.chat-page-textarea::placeholder {
+ color: var(--placeholder-color);
+}
+
+/* ── Composer toolbar (below the textarea) ────────────────────────────────── */
.chat-page-toolbar {
display: flex;
@@ -408,30 +632,31 @@ mobile-app[data-native] .chat-page-input-area { padding-bottom: 10px; }
gap: 6px;
}
-/* Model selector — a native