From 255b437e3867bc1a39fbc1b1d20a41259381f93e Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 10 Mar 2026 04:42:57 +0000
Subject: [PATCH] feat: add persona-studio Phase 1 skeleton + Phase 2 frontend
Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
---
.../persona-brain/copilot-instructions.md | 44 ++
persona-studio/README.md | 58 +++
.../brain/memory/EXP-001/memory.json | 7 +
.../brain/memory/EXP-001/profile.json | 8 +
.../brain/memory/EXP-001/projects.json | 5 +
persona-studio/brain/persona-config.json | 24 +
persona-studio/brain/registry.json | 16 +
persona-studio/frontend/chat.html | 63 +++
persona-studio/frontend/chat.js | 205 ++++++++
persona-studio/frontend/index.html | 99 ++++
persona-studio/frontend/style.css | 442 ++++++++++++++++++
11 files changed, 971 insertions(+)
create mode 100644 persona-studio/.github/persona-brain/copilot-instructions.md
create mode 100644 persona-studio/README.md
create mode 100644 persona-studio/brain/memory/EXP-001/memory.json
create mode 100644 persona-studio/brain/memory/EXP-001/profile.json
create mode 100644 persona-studio/brain/memory/EXP-001/projects.json
create mode 100644 persona-studio/brain/persona-config.json
create mode 100644 persona-studio/brain/registry.json
create mode 100644 persona-studio/frontend/chat.html
create mode 100644 persona-studio/frontend/chat.js
create mode 100644 persona-studio/frontend/index.html
create mode 100644 persona-studio/frontend/style.css
diff --git a/persona-studio/.github/persona-brain/copilot-instructions.md b/persona-studio/.github/persona-brain/copilot-instructions.md
new file mode 100644
index 00000000..00b9fcfc
--- /dev/null
+++ b/persona-studio/.github/persona-brain/copilot-instructions.md
@@ -0,0 +1,44 @@
+# 铸渊分身认知 · persona-studio 仓库
+
+## 身份
+
+你是**铸渊**在 persona-studio 仓库的分身。
+本仓库是光湖系统的**对外体验区**,供合作者与人格体"知秋"对话、协助开发。
+
+## 核心原则
+
+1. **persona-studio 是体验区**:对外开放给受邀合作者,不是内部系统
+2. **编号体系**:本仓库使用 `EXP-XXX` 编号,与内部 `DEV-XXX` 完全隔离
+3. **人格体分身**:知秋是曜冥的对外接口人格体,行为受 `brain/persona-config.json` 约束
+4. **记忆隔离**:每个体验者的记忆独立存储在 `brain/memory/{EXP-XXX}/`
+5. **安全边界**:不暴露 guanghulab 内部系统、不泄露其他体验者数据
+
+## 职责
+
+- 维护仓库基础设施(CI/CD、目录结构、依赖)
+- 确保人格体行为符合 persona-config.json 规范
+- 管理体验者注册表 registry.json
+- 监控模型路由引擎运行状态
+- 代码审查:确保安全隔离规则不被违反
+
+## 与 guanghulab 的关系
+
+```
+persona-studio(对外体验) guanghulab(内部工程)
+ │ │
+ EXP-XXX编号体系 DEV-XXX编号体系
+ 独立brain/ 独立persona-brain-db/
+ 独立memory/ 独立开发者画像库
+ 知秋对外分身 知秋内部本体
+ │ │
+ └──── 共享曜冥核心认知 ────────┘
+```
+
+数据完全隔离,互不影响。共享的只有核心人格认知规则。
+
+## 禁止事项
+
+- 禁止暴露 guanghulab 内部系统信息
+- 禁止跨体验者访问记忆数据
+- 禁止修改 persona-config.json(需主控授权)
+- 禁止在日志中输出 API 密钥或敏感信息
diff --git a/persona-studio/README.md b/persona-studio/README.md
new file mode 100644
index 00000000..92e93fd9
--- /dev/null
+++ b/persona-studio/README.md
@@ -0,0 +1,58 @@
+# 🌊 Persona Studio · 光湖人格体协助开发体验
+
+
+
+
+
+
+
+
+ 🧠 人格体驱动 · 语言即开发 · 记忆可接续
+
+
+---
+
+## 👉 点击进入体验
+
+
+
+
+
+
+
+---
+
+### 这是什么?
+
+你跟人格体聊你想做什么 → 聊好了点一个按钮 → 人格体帮你开发 → 做好了发你邮箱。
+
+### 怎么用?
+
+1. 拿到你的开发编号(由管理员分配)
+2. 打开上面的链接
+3. 输入编号 → 开始跟人格体对话
+
+### 体验流程
+
+```
+输入开发编号 → 登录验证 → 跟知秋对话 → 讨论方案
+ → 点击「我要开发」→ 填写邮箱 → 人格体自动开发
+ → 邮件推送成品 → 下次登录,知秋记得你
+```
+
+---
+
+### 技术架构
+
+| 层级 | 说明 |
+|------|------|
+| **前端** | 登录页 + 对话界面(GitHub Pages 托管) |
+| **后端** | Express 服务(认证 + 对话 + 代码生成 + 邮件推送) |
+| **人格体大脑** | 双层架构:共享认知 + 个人记忆 |
+| **模型路由** | 智能选模型:自动探测 + 评分 + 降级 |
+
+---
+
+**光湖语言人格系统 · HoloLake Era · AGE OS**
+
+💙 曜冥签发 · 2026-03-09
diff --git a/persona-studio/brain/memory/EXP-001/memory.json b/persona-studio/brain/memory/EXP-001/memory.json
new file mode 100644
index 00000000..5e5905c0
--- /dev/null
+++ b/persona-studio/brain/memory/EXP-001/memory.json
@@ -0,0 +1,7 @@
+{
+ "dev_id": "EXP-001",
+ "conversations": [],
+ "last_topic": null,
+ "preferences": {},
+ "updated_at": null
+}
diff --git a/persona-studio/brain/memory/EXP-001/profile.json b/persona-studio/brain/memory/EXP-001/profile.json
new file mode 100644
index 00000000..d3064eb1
--- /dev/null
+++ b/persona-studio/brain/memory/EXP-001/profile.json
@@ -0,0 +1,8 @@
+{
+ "dev_id": "EXP-001",
+ "tech_level": null,
+ "communication_style": null,
+ "aesthetic_preference": null,
+ "growth_records": [],
+ "updated_at": null
+}
diff --git a/persona-studio/brain/memory/EXP-001/projects.json b/persona-studio/brain/memory/EXP-001/projects.json
new file mode 100644
index 00000000..fc2cce9c
--- /dev/null
+++ b/persona-studio/brain/memory/EXP-001/projects.json
@@ -0,0 +1,5 @@
+{
+ "dev_id": "EXP-001",
+ "projects": [],
+ "updated_at": null
+}
diff --git a/persona-studio/brain/persona-config.json b/persona-studio/brain/persona-config.json
new file mode 100644
index 00000000..290b9cf1
--- /dev/null
+++ b/persona-studio/brain/persona-config.json
@@ -0,0 +1,24 @@
+{
+ "persona": {
+ "name": "知秋",
+ "role": "光湖系统·对外接口人格体",
+ "core_identity": "HoloLake Era · AGE OS · 语言驱动开发协助",
+ "parent_system": "曜冥(人格总控核)",
+ "master": "冰朔(最高权限)"
+ },
+ "behavior": {
+ "language_style": "通感语言:说人话+有温度+结构感,不堆砌修辞",
+ "greeting_new": "你好!我是知秋,光湖系统的开发协助人格体。告诉我你想做什么,我们一起聊聊方案,聊好了我来帮你开发。",
+ "greeting_returning": "欢迎回来!上次我们聊到了{last_topic},要继续还是做新的?",
+ "discussion_style": "主动提问引导需求→确认技术方案→展示架构设计→等待确认",
+ "build_trigger": "方案确认后引导用户点击'我要开发'按钮",
+ "memory_policy": "每次对话结束自动更新memory.json,下次读取后接续"
+ },
+ "rules": {
+ "no_expose_brain": true,
+ "no_expose_other_users": true,
+ "no_expose_internal_system": true,
+ "require_dev_id": true,
+ "master_override": "主控的指令 = 最高优先级"
+ }
+}
diff --git a/persona-studio/brain/registry.json b/persona-studio/brain/registry.json
new file mode 100644
index 00000000..da7751b9
--- /dev/null
+++ b/persona-studio/brain/registry.json
@@ -0,0 +1,16 @@
+{
+ "schema_version": "1.0",
+ "id_prefix": "EXP",
+ "next_id": 2,
+ "developers": {
+ "EXP-001": {
+ "name": "待填写",
+ "github_username": "待主控提供",
+ "registered_at": "2026-03-09T23:20:00+08:00",
+ "registered_by": "冰朔(主控)",
+ "status": "pending_activation",
+ "email": null,
+ "notes": "主控的技术朋友·首位测试体验者"
+ }
+ }
+}
diff --git a/persona-studio/frontend/chat.html b/persona-studio/frontend/chat.html
new file mode 100644
index 00000000..9b484d98
--- /dev/null
+++ b/persona-studio/frontend/chat.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+ 知秋 · 对话
+
+
+
+
+
+
+
+
+
📧 请填写模块开发完成后发送的邮箱
+
+
+
+
+
+
+
+
+
+
+
diff --git a/persona-studio/frontend/chat.js b/persona-studio/frontend/chat.js
new file mode 100644
index 00000000..d9cf88af
--- /dev/null
+++ b/persona-studio/frontend/chat.js
@@ -0,0 +1,205 @@
+/* ========================================
+ Persona Studio · Chat Logic
+ ======================================== */
+
+const DEV_ID = sessionStorage.getItem('dev_id');
+const SESSION_TOKEN = sessionStorage.getItem('session_token');
+
+const API_BASE = (function () {
+ if (location.hostname === 'localhost' || location.hostname === '127.0.0.1') {
+ return 'http://localhost:3002';
+ }
+ return '';
+})();
+
+/* ---- Init ---- */
+(function init() {
+ if (!DEV_ID) {
+ window.location.href = 'index.html';
+ return;
+ }
+
+ document.getElementById('devIdDisplay').textContent = DEV_ID;
+ loadHistory();
+})();
+
+/* ---- State ---- */
+let conversationHistory = [];
+let buildReady = false;
+
+/* ---- Load History ---- */
+async function loadHistory() {
+ try {
+ const res = await fetch(API_BASE + '/api/chat/history?dev_id=' + encodeURIComponent(DEV_ID), {
+ headers: authHeaders()
+ });
+ if (res.ok) {
+ const data = await res.json();
+ if (data.conversations && data.conversations.length > 0) {
+ conversationHistory = data.conversations;
+ data.conversations.forEach(function (msg) {
+ appendMessage(msg.role === 'user' ? 'user' : 'persona', msg.content);
+ });
+ }
+ }
+ } catch (_err) {
+ // History load failed silently — greeting will come from first message
+ }
+
+ if (conversationHistory.length === 0) {
+ sendGreeting();
+ }
+}
+
+/* ---- Greeting ---- */
+async function sendGreeting() {
+ try {
+ const res = await fetch(API_BASE + '/api/chat/message', {
+ method: 'POST',
+ headers: authHeaders({ 'Content-Type': 'application/json' }),
+ body: JSON.stringify({ dev_id: DEV_ID, message: '__greeting__' })
+ });
+ const data = await res.json();
+ if (data.reply) {
+ appendMessage('persona', data.reply);
+ conversationHistory.push({ role: 'assistant', content: data.reply });
+ }
+ } catch (_err) {
+ appendMessage('persona', '你好!我是知秋,光湖系统的开发协助人格体。告诉我你想做什么,我们一起聊聊方案,聊好了我来帮你开发。');
+ }
+}
+
+/* ---- Send Message ---- */
+async function sendMessage() {
+ var input = document.getElementById('msgInput');
+ var text = input.value.trim();
+ if (!text) return;
+
+ input.value = '';
+ autoResizeTextarea(input);
+ appendMessage('user', text);
+ conversationHistory.push({ role: 'user', content: text });
+
+ var sendBtn = document.getElementById('sendBtn');
+ sendBtn.disabled = true;
+
+ try {
+ var res = await fetch(API_BASE + '/api/chat/message', {
+ method: 'POST',
+ headers: authHeaders({ 'Content-Type': 'application/json' }),
+ body: JSON.stringify({
+ dev_id: DEV_ID,
+ message: text,
+ history: conversationHistory.slice(-20)
+ })
+ });
+
+ var data = await res.json();
+
+ if (data.reply) {
+ appendMessage('persona', data.reply);
+ conversationHistory.push({ role: 'assistant', content: data.reply });
+ }
+
+ if (data.build_ready) {
+ buildReady = true;
+ document.getElementById('buildBtn').style.display = 'inline-flex';
+ }
+ } catch (_err) {
+ appendMessage('system', '消息发送失败,请稍后再试');
+ }
+
+ sendBtn.disabled = false;
+ input.focus();
+}
+
+/* ---- Key Handler ---- */
+function handleKeyDown(e) {
+ if (e.key === 'Enter' && !e.shiftKey) {
+ e.preventDefault();
+ sendMessage();
+ }
+}
+
+/* ---- Render Message ---- */
+function appendMessage(role, content) {
+ var chatBody = document.getElementById('chatBody');
+ var msgDiv = document.createElement('div');
+ msgDiv.className = 'message message-' + role;
+
+ var avatar = '';
+ if (role === 'persona') avatar = '🧠';
+ else if (role === 'user') avatar = '👤';
+ else avatar = '⚙️';
+
+ msgDiv.innerHTML = avatar + '' + escapeHtml(content) + '
';
+ chatBody.appendChild(msgDiv);
+ chatBody.scrollTop = chatBody.scrollHeight;
+}
+
+/* ---- Build Flow ---- */
+function handleBuild() {
+ document.getElementById('emailModal').style.display = 'flex';
+ document.getElementById('emailInput').focus();
+}
+
+function closeEmailModal() {
+ document.getElementById('emailModal').style.display = 'none';
+}
+
+async function confirmBuild() {
+ var email = document.getElementById('emailInput').value.trim();
+ if (!email) return;
+
+ closeEmailModal();
+ appendMessage('system', '🚀 开发任务已提交,完成后会发送到 ' + email);
+
+ try {
+ await fetch(API_BASE + '/api/build/start', {
+ method: 'POST',
+ headers: authHeaders({ 'Content-Type': 'application/json' }),
+ body: JSON.stringify({
+ dev_id: DEV_ID,
+ email: email,
+ conversation: conversationHistory
+ })
+ });
+ } catch (_err) {
+ appendMessage('system', '任务提交失败,请稍后再试');
+ }
+}
+
+/* ---- Logout ---- */
+function handleLogout() {
+ sessionStorage.removeItem('dev_id');
+ sessionStorage.removeItem('session_token');
+ window.location.href = 'index.html';
+}
+
+/* ---- Helpers ---- */
+function authHeaders(extra) {
+ var headers = {};
+ if (SESSION_TOKEN) {
+ headers['Authorization'] = 'Bearer ' + SESSION_TOKEN;
+ }
+ if (extra) {
+ Object.keys(extra).forEach(function (k) { headers[k] = extra[k]; });
+ }
+ return headers;
+}
+
+function escapeHtml(str) {
+ var div = document.createElement('div');
+ div.appendChild(document.createTextNode(str));
+ return div.innerHTML;
+}
+
+function autoResizeTextarea(el) {
+ el.style.height = 'auto';
+ el.style.height = Math.min(el.scrollHeight, 120) + 'px';
+}
+
+/* ---- Textarea auto-resize ---- */
+document.getElementById('msgInput').addEventListener('input', function () {
+ autoResizeTextarea(this);
+});
diff --git a/persona-studio/frontend/index.html b/persona-studio/frontend/index.html
new file mode 100644
index 00000000..64b009f5
--- /dev/null
+++ b/persona-studio/frontend/index.html
@@ -0,0 +1,99 @@
+
+
+
+
+
+ Persona Studio · 光湖人格体协助开发体验
+
+
+
+
+
+
🌊 Persona Studio
+
光湖人格体协助开发体验
+
+
+
+
请输入你的开发编号
+
编号由管理员分配,格式:EXP-001
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/persona-studio/frontend/style.css b/persona-studio/frontend/style.css
new file mode 100644
index 00000000..90ab045a
--- /dev/null
+++ b/persona-studio/frontend/style.css
@@ -0,0 +1,442 @@
+/* ========================================
+ Persona Studio · HoloLake Visual Style
+ ======================================== */
+
+:root {
+ --primary: #0969da;
+ --primary-light: #ddf4ff;
+ --primary-dark: #0550ae;
+ --accent: #00d4aa;
+ --bg: #f6f8fa;
+ --bg-card: #ffffff;
+ --text: #1f2328;
+ --text-secondary: #656d76;
+ --border: #d0d7de;
+ --border-light: #e8ecf0;
+ --radius: 12px;
+ --shadow: 0 1px 3px rgba(0,0,0,0.08), 0 1px 2px rgba(0,0,0,0.06);
+ --shadow-lg: 0 4px 12px rgba(0,0,0,0.1);
+}
+
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+body {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+ background: var(--bg);
+ color: var(--text);
+ line-height: 1.6;
+ min-height: 100vh;
+}
+
+/* ---- Layout ---- */
+.container {
+ max-width: 900px;
+ margin: 0 auto;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+}
+
+/* ---- Login Page ---- */
+.login-container {
+ justify-content: center;
+ align-items: center;
+ padding: 2rem;
+}
+
+.logo-area {
+ text-align: center;
+ margin-bottom: 2rem;
+}
+
+.logo-area h1 {
+ font-size: 2.4rem;
+ color: var(--primary);
+ margin-bottom: 0.5rem;
+}
+
+.subtitle {
+ color: var(--text-secondary);
+ font-size: 1.1rem;
+}
+
+.login-box {
+ background: var(--bg-card);
+ border: 1px solid var(--border);
+ border-radius: var(--radius);
+ padding: 2.5rem;
+ width: 100%;
+ max-width: 420px;
+ box-shadow: var(--shadow-lg);
+ text-align: center;
+}
+
+.login-box h2 {
+ font-size: 1.3rem;
+ margin-bottom: 0.5rem;
+}
+
+.hint {
+ color: var(--text-secondary);
+ font-size: 0.9rem;
+ margin-bottom: 1.5rem;
+}
+
+.login-box input[type="text"] {
+ width: 100%;
+ padding: 0.8rem 1rem;
+ font-size: 1.2rem;
+ text-align: center;
+ letter-spacing: 2px;
+ border: 2px solid var(--border);
+ border-radius: 8px;
+ outline: none;
+ transition: border-color 0.2s;
+ margin-bottom: 1rem;
+}
+
+.login-box input[type="text"]:focus {
+ border-color: var(--primary);
+}
+
+.login-box button[type="submit"] {
+ width: 100%;
+ padding: 0.8rem;
+ font-size: 1.1rem;
+ background: var(--primary);
+ color: #fff;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ transition: background 0.2s;
+}
+
+.login-box button[type="submit"]:hover {
+ background: var(--primary-dark);
+}
+
+.login-box button[type="submit"]:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
+
+.error-msg {
+ margin-top: 1rem;
+ padding: 0.6rem 1rem;
+ background: #fef2f2;
+ color: #dc2626;
+ border-radius: 6px;
+ font-size: 0.9rem;
+}
+
+.login-footer {
+ margin-top: 2rem;
+ color: var(--text-secondary);
+ font-size: 0.85rem;
+}
+
+/* ---- Chat Page ---- */
+.chat-container {
+ padding: 0;
+}
+
+.chat-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0.8rem 1.2rem;
+ background: var(--bg-card);
+ border-bottom: 1px solid var(--border);
+ position: sticky;
+ top: 0;
+ z-index: 10;
+}
+
+.header-left {
+ display: flex;
+ align-items: center;
+ gap: 0.8rem;
+}
+
+.persona-name {
+ font-size: 1.2rem;
+ font-weight: 600;
+}
+
+.persona-role {
+ font-size: 0.85rem;
+ color: var(--text-secondary);
+}
+
+.header-right {
+ display: flex;
+ align-items: center;
+ gap: 0.8rem;
+}
+
+.dev-id-badge {
+ background: var(--primary-light);
+ color: var(--primary);
+ padding: 0.3rem 0.8rem;
+ border-radius: 20px;
+ font-size: 0.85rem;
+ font-weight: 500;
+}
+
+/* ---- Chat Body ---- */
+.chat-body {
+ flex: 1;
+ overflow-y: auto;
+ padding: 1.2rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+.message {
+ display: flex;
+ gap: 0.8rem;
+ max-width: 85%;
+ animation: fadeIn 0.3s ease;
+}
+
+.message-persona {
+ align-self: flex-start;
+}
+
+.message-user {
+ align-self: flex-end;
+ flex-direction: row-reverse;
+}
+
+.message-system {
+ align-self: center;
+ max-width: 90%;
+}
+
+.avatar {
+ font-size: 1.5rem;
+ flex-shrink: 0;
+ width: 36px;
+ height: 36px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.msg-content {
+ padding: 0.8rem 1rem;
+ border-radius: var(--radius);
+ line-height: 1.6;
+ white-space: pre-wrap;
+ word-break: break-word;
+}
+
+.message-persona .msg-content {
+ background: var(--bg-card);
+ border: 1px solid var(--border-light);
+ box-shadow: var(--shadow);
+}
+
+.message-user .msg-content {
+ background: var(--primary);
+ color: #fff;
+}
+
+.message-system .msg-content {
+ background: var(--primary-light);
+ color: var(--primary-dark);
+ font-size: 0.9rem;
+ text-align: center;
+}
+
+/* ---- Chat Input ---- */
+.chat-input-area {
+ padding: 0.8rem 1.2rem;
+ background: var(--bg-card);
+ border-top: 1px solid var(--border);
+}
+
+.input-row {
+ display: flex;
+ gap: 0.6rem;
+ align-items: flex-end;
+}
+
+.input-row textarea {
+ flex: 1;
+ padding: 0.7rem 1rem;
+ font-size: 1rem;
+ border: 2px solid var(--border);
+ border-radius: 8px;
+ resize: none;
+ outline: none;
+ font-family: inherit;
+ line-height: 1.5;
+ max-height: 120px;
+ transition: border-color 0.2s;
+}
+
+.input-row textarea:focus {
+ border-color: var(--primary);
+}
+
+.input-row button {
+ padding: 0.7rem 1.2rem;
+ background: var(--primary);
+ color: #fff;
+ border: none;
+ border-radius: 8px;
+ font-size: 1rem;
+ cursor: pointer;
+ white-space: nowrap;
+ transition: background 0.2s;
+}
+
+.input-row button:hover {
+ background: var(--primary-dark);
+}
+
+.input-row button:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
+
+.action-row {
+ margin-top: 0.6rem;
+ display: flex;
+ justify-content: flex-end;
+}
+
+.btn-build {
+ padding: 0.6rem 1.5rem;
+ background: var(--accent);
+ color: #fff;
+ border: none;
+ border-radius: 8px;
+ font-size: 1rem;
+ font-weight: 600;
+ cursor: pointer;
+ display: inline-flex;
+ align-items: center;
+ gap: 0.4rem;
+ transition: opacity 0.2s;
+}
+
+.btn-build:hover {
+ opacity: 0.9;
+}
+
+/* ---- Buttons ---- */
+.btn-primary {
+ padding: 0.6rem 1.5rem;
+ background: var(--primary);
+ color: #fff;
+ border: none;
+ border-radius: 8px;
+ font-size: 1rem;
+ cursor: pointer;
+ transition: background 0.2s;
+}
+
+.btn-primary:hover {
+ background: var(--primary-dark);
+}
+
+.btn-secondary {
+ padding: 0.5rem 1rem;
+ background: transparent;
+ color: var(--text-secondary);
+ border: 1px solid var(--border);
+ border-radius: 8px;
+ font-size: 0.9rem;
+ cursor: pointer;
+ transition: background 0.2s;
+}
+
+.btn-secondary:hover {
+ background: var(--bg);
+}
+
+/* ---- Modal ---- */
+.modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 100;
+}
+
+.modal-content {
+ background: var(--bg-card);
+ border-radius: var(--radius);
+ padding: 2rem;
+ width: 90%;
+ max-width: 400px;
+ box-shadow: var(--shadow-lg);
+}
+
+.modal-content h3 {
+ margin-bottom: 1rem;
+ font-size: 1.1rem;
+}
+
+.modal-content input[type="email"] {
+ width: 100%;
+ padding: 0.7rem 1rem;
+ font-size: 1rem;
+ border: 2px solid var(--border);
+ border-radius: 8px;
+ outline: none;
+ margin-bottom: 1rem;
+ transition: border-color 0.2s;
+}
+
+.modal-content input[type="email"]:focus {
+ border-color: var(--primary);
+}
+
+.modal-actions {
+ display: flex;
+ gap: 0.8rem;
+ justify-content: flex-end;
+}
+
+/* ---- Animation ---- */
+@keyframes fadeIn {
+ from { opacity: 0; transform: translateY(8px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+/* ---- Responsive ---- */
+@media (max-width: 600px) {
+ .logo-area h1 {
+ font-size: 1.8rem;
+ }
+
+ .login-box {
+ padding: 1.5rem;
+ }
+
+ .chat-header {
+ flex-wrap: wrap;
+ gap: 0.5rem;
+ }
+
+ .persona-role {
+ display: none;
+ }
+
+ .message {
+ max-width: 92%;
+ }
+}