@iprep/server 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,30 +1,58 @@
1
- # @iprep/server
2
-
3
- Express.js backend API for iPrep.
4
-
5
- ## Development
6
-
7
- ```bash
8
- pnpm run dev
9
- ```
10
-
11
- Server runs on `http://localhost:3000`
12
-
13
- ## API Endpoints
14
-
15
- - `GET /health` - Health check
16
- - `GET /api/tutors` - List available tutors
17
- - `POST /api/chat` - Send message to tutor
18
- - `GET /api/conversations` - Get conversations
19
- - `POST /api/documents/upload` - Upload documents
20
-
21
- ## Services
22
-
23
- - **ChatService** - Handles message orchestration
24
- - **TutorService** - Manages tutor configurations
25
- - **DocumentService** - Manages uploaded documents
26
- - **SessionService** - Manages user sessions
27
-
28
- ## Adapters
29
-
30
- - **ClaudeAdapter** - Spawns Claude CLI process
1
+ # @iprep/server
2
+
3
+ Express.js backend API for iPrep. Connects the React frontend to Claude Code CLI and the SQLite database.
4
+
5
+ ## Development
6
+
7
+ ```bash
8
+ pnpm run dev
9
+ ```
10
+
11
+ Server runs on `http://localhost:3000`
12
+
13
+ ## API Endpoints
14
+
15
+ ### Health
16
+ | Method | Endpoint | Description |
17
+ | ------ | ---------- | ------------------ |
18
+ | `GET` | `/health` | Server health check |
19
+
20
+ ### Tutors
21
+ | Method | Endpoint | Description |
22
+ | ------ | ------------------ | ---------------------------- |
23
+ | `GET` | `/api/tutors` | List all available tutors |
24
+ | `GET` | `/api/tutors/:id` | Get a single tutor config |
25
+
26
+ ### Chat
27
+ | Method | Endpoint | Description |
28
+ | ------ | ------------ | ------------------------------------ |
29
+ | `POST` | `/api/chat` | Send a message → Claude → response |
30
+
31
+ ### Conversations
32
+ | Method | Endpoint | Description |
33
+ | ------ | ------------------------------------- | ------------------------------ |
34
+ | `GET` | `/api/conversations?userId=&tutorId=` | List conversations |
35
+ | `GET` | `/api/conversations/:id` | Get conversation details |
36
+ | `GET` | `/api/conversations/:id/messages` | Get messages in a conversation |
37
+
38
+ ### Documents
39
+ | Method | Endpoint | Description |
40
+ | -------- | ------------------------------------- | -------------------------------- |
41
+ | `GET` | `/api/documents/:tutorId` | List documents for a tutor |
42
+ | `POST` | `/api/documents/:tutorId/upload` | Upload a document (.md or .txt) |
43
+ | `DELETE` | `/api/documents/:tutorId/:documentId` | Delete a document |
44
+
45
+ ## Services
46
+
47
+ | Service | Description |
48
+ | -------------------- | -------------------------------------------------- |
49
+ | **ChatService** | Orchestrates message flow (user → Claude → DB → UI)|
50
+ | **TutorService** | Loads tutor configs from `~/.iprep/aitutors/` |
51
+ | **DocumentService** | Manages document uploads and storage per tutor |
52
+ | **SessionService** | Creates and tracks user–tutor sessions |
53
+
54
+ ## Notes
55
+
56
+ - Tutor configs are loaded from `~/.iprep/aitutors/{tutorId}/` (markdown files)
57
+ - Uploaded documents are stored at `~/.iprep/aitutors/{tutorId}/docs/`
58
+ - Only `.md` and `.txt` files are accepted for upload (max 10 MB)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iprep/server",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "Express backend API for iPrep",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -8,19 +8,13 @@
8
8
  "src/",
9
9
  "public/"
10
10
  ],
11
- "scripts": {
12
- "start": "node src/index.js",
13
- "dev": "cross-env NODE_ENV=development node --watch src/index.js",
14
- "build": "pnpm --filter @iprep/web run build",
15
- "prepublishOnly": "pnpm --filter @iprep/web run build"
16
- },
17
11
  "publishConfig": {
18
12
  "access": "public"
19
13
  },
20
14
  "dependencies": {
21
- "@iprep/adapter-utils": "^1.1.0",
22
- "@iprep/db": "^1.1.0",
23
- "@iprep/shared": "^1.1.0",
15
+ "@iprep/adapter-utils": "^1.1.4",
16
+ "@iprep/db": "^1.1.4",
17
+ "@iprep/shared": "^1.1.4",
24
18
  "body-parser": "^1.20.2",
25
19
  "cors": "^2.8.5",
26
20
  "dotenv": "^16.3.1",
@@ -31,5 +25,10 @@
31
25
  "devDependencies": {
32
26
  "nodemon": "^3.0.2"
33
27
  },
34
- "author": "kundalik.dev"
35
- }
28
+ "author": "kundalik.dev",
29
+ "scripts": {
30
+ "start": "node src/index.js",
31
+ "dev": "cross-env NODE_ENV=development node --watch src/index.js",
32
+ "build": "pnpm --filter @iprep/web run build"
33
+ }
34
+ }
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap";*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body,#root{height:100%;overflow:hidden}body{font-family:var(--font-sans);background:var(--bg-app);color:var(--text-primary);font-size:14px;line-height:1.6;-webkit-font-smoothing:antialiased;transition:var(--transition-theme)}.sidebar,.main-content,.chat-header,.right-drawer,.mode-switcher-bar,.drawer-header,.drawer-tabs{transition:var(--transition-theme)}::-webkit-scrollbar{width:5px}::-webkit-scrollbar-track{background:transparent}::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:3px}::-webkit-scrollbar-thumb:hover{background:#fff3}:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px;border-radius:var(--radius-sm)}button{cursor:pointer;border:none;background:none;font-family:inherit}input,textarea{font-family:inherit}a{color:var(--text-accent);text-decoration:none}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.app-shell{display:flex;height:100vh;width:100vw;overflow:hidden}:root{--color-primary: #7C6FFF;--color-primary-hover: #6B5EF0;--color-primary-light: rgba(124, 111, 255, .12);--color-accent: #00D4C8;--color-accent-hover: #00BEB3;--color-success: #22C55E;--color-success-hover: #16A34A;--color-warning: #F59E0B;--color-error: #EF4444;--color-info: #3B82F6;--radius-sm: 6px;--radius-md: 12px;--radius-lg: 18px;--radius-xl: 24px;--radius-full: 9999px;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-8: 32px;--space-10: 40px;--sidebar-w: 68px;--drawer-w: 380px;--call-btn-size: 48px;--header-row-h: 70px;--toolbar-row-h: 52px;--font-sans: "Inter", "Segoe UI", system-ui, sans-serif;--font-mono: "JetBrains Mono", "Fira Code", monospace;--transition-fast: all .15s ease;--transition-base: all .25s ease;--transition-slow: all .4s ease;--transition-theme: background .3s ease, color .3s ease, border-color .3s ease, box-shadow .3s ease}:root[data-theme=dark]{--bg-app: #0D0D14;--bg-surface: #14141F;--bg-sidebar: #0D0D14;--bg-card: #1C1C2C;--bg-input: #1A1A28;--bg-hover: rgba(255,255,255,.05);--bg-active: rgba(124,111,255,.15);--text-primary: #F0F0FF;--text-secondary: #9090B8;--text-muted: #5A5A80;--text-accent: #7C6FFF;--text-on-primary: #FFFFFF;--border-color: rgba(255,255,255,.06);--border-active: rgba(124,111,255,.5);--bubble-user-bg: #7C6FFF;--bubble-user-text: #FFFFFF;--bubble-ai-bg: #1C1C2C;--bubble-ai-text: #E8E8F8;--shadow-sm: 0 1px 3px rgba(0,0,0,.4);--shadow-md: 0 4px 12px rgba(0,0,0,.5);--shadow-lg: 0 8px 32px rgba(0,0,0,.6);--shadow-glow: 0 0 24px rgba(124,111,255,.25);--drawer-bg: #111122;--drawer-border: rgba(255, 255, 255, .06);--drawer-tab-bg: rgba(255, 255, 255, .04);--drawer-tab-active: var(--color-primary);--call-bar-bg: rgba(0, 0, 0, .6);--call-bar-border: rgba(255, 255, 255, .08);--call-end-bg: #EF4444;--call-end-hover: #DC2626}:root[data-theme=light]{--bg-app: #F8F9FA;--bg-surface: #FFFFFF;--bg-sidebar: #F1F3F5;--bg-card: #FFFFFF;--bg-input: #F1F3F5;--bg-hover: rgba(0,0,0,.04);--bg-active: rgba(124,111,255,.1);--text-primary: #1A1A1A;--text-secondary: #4A4A4A;--text-muted: #717171;--text-accent: #7C6FFF;--text-on-primary: #FFFFFF;--border-color: rgba(0,0,0,.08);--border-active: rgba(124,111,255,.5);--bubble-user-bg: #7C6FFF;--bubble-user-text: #FFFFFF;--bubble-ai-bg: #E9ECEF;--bubble-ai-text: #1A1A1A;--shadow-sm: 0 1px 2px rgba(0,0,0,.05);--shadow-md: 0 4px 6px rgba(0,0,0,.07);--shadow-lg: 0 10px 15px rgba(0,0,0,.1);--shadow-glow: 0 0 20px rgba(124,111,255,.15);--drawer-bg: #FFFFFF;--drawer-border: rgba(0,0,0,.08);--drawer-tab-bg: rgba(0,0,0,.03);--drawer-tab-active: var(--color-primary);--call-bar-bg: rgba(255, 255, 255, .85);--call-bar-border: rgba(0, 0, 0, .08);--call-end-bg: #EF4444;--call-end-hover: #DC2626}:root:not([data-theme]){--bg-app: #F8F9FA;--bg-surface: #FFFFFF;--bg-sidebar: #F1F3F5;--bg-card: #FFFFFF;--bg-input: #F1F3F5;--bg-hover: rgba(0,0,0,.04);--bg-active: rgba(124,111,255,.1);--text-primary: #1A1A1A;--text-secondary: #4A4A4A;--text-muted: #717171;--text-accent: #7C6FFF;--text-on-primary: #FFFFFF;--border-color: rgba(0,0,0,.08);--border-active: rgba(124,111,255,.5);--bubble-user-bg: #7C6FFF;--bubble-user-text: #FFFFFF;--bubble-ai-bg: #E9ECEF;--bubble-ai-text: #1A1A1A;--shadow-sm: 0 1px 2px rgba(0,0,0,.05);--shadow-md: 0 4px 6px rgba(0,0,0,.07);--shadow-lg: 0 10px 15px rgba(0,0,0,.1);--shadow-glow: 0 0 20px rgba(124,111,255,.15);--drawer-bg: #FFFFFF;--drawer-border: rgba(0,0,0,.08);--drawer-tab-bg: rgba(0,0,0,.03);--drawer-tab-active: var(--color-primary);--call-bar-bg: rgba(255, 255, 255, .85);--call-bar-border: rgba(0, 0, 0, .08);--call-end-bg: #EF4444;--call-end-hover: #DC2626}.sidebar{width:var(--sidebar-w);min-width:var(--sidebar-w);background:var(--bg-sidebar);border-right:1px solid var(--border-color);display:flex;flex-direction:column;align-items:center;padding:var(--space-4) 0;gap:var(--space-2);z-index:10}.sidebar__logo{width:40px;height:40px;background:var(--color-primary);border-radius:var(--radius-md);display:flex;align-items:center;justify-content:center;font-weight:700;font-size:16px;color:#fff;margin-bottom:var(--space-4);box-shadow:var(--shadow-glow);flex-shrink:0}.sidebar__nav{display:flex;flex-direction:column;align-items:center;gap:var(--space-2);flex:1;width:100%;padding:0 var(--space-2)}.sidebar__bottom{display:flex;flex-direction:column;align-items:center;gap:var(--space-2);padding:0 var(--space-2)}.tutor-icon-btn{position:relative;width:48px;height:48px;border-radius:var(--radius-md);background:var(--bg-card);border:2px solid transparent;display:flex;align-items:center;justify-content:center;font-size:20px;transition:var(--transition-base);overflow:visible}.tutor-icon-btn:hover{background:var(--bg-hover);border-color:var(--border-active);transform:scale(1.05)}.tutor-icon-btn.active{background:var(--bg-active);border-color:var(--color-primary);box-shadow:var(--shadow-glow)}.tutor-icon-btn .badge{position:absolute;top:-4px;right:-4px;min-width:16px;height:16px;background:var(--color-primary);color:#fff;font-size:10px;font-weight:600;border-radius:var(--radius-full);display:flex;align-items:center;justify-content:center;padding:0 4px;border:2px solid var(--bg-sidebar)}.tutor-icon-btn .tooltip{position:absolute;left:calc(100% + 10px);top:50%;transform:translateY(-50%);background:var(--bg-card);border:1px solid var(--border-color);color:var(--text-primary);font-size:12px;font-weight:500;padding:6px 10px;border-radius:var(--radius-sm);white-space:nowrap;pointer-events:none;opacity:0;transition:var(--transition-fast);box-shadow:var(--shadow-md);z-index:100}.tutor-icon-btn:hover .tooltip{opacity:1}.sidebar__add-btn{width:48px;height:48px;border-radius:var(--radius-md);background:var(--bg-card);border:2px dashed var(--text-muted);display:flex;align-items:center;justify-content:center;font-size:20px;color:var(--text-muted);transition:var(--transition-base)}.sidebar__add-btn:hover{border-color:var(--color-primary);color:var(--color-primary);background:var(--color-primary-light)}.theme-switcher{width:40px;height:40px;border-radius:var(--radius-md);background:var(--bg-card);border:1px solid var(--border-color);display:flex;align-items:center;justify-content:center;color:var(--text-secondary);cursor:pointer;transition:var(--transition-base);margin-top:var(--space-2)}.theme-switcher:hover{background:var(--bg-hover);border-color:var(--border-active);color:var(--text-primary);transform:scale(1.05)}.theme-switcher svg{transition:transform .5s ease}.theme-switcher:hover svg{transform:rotate(15deg)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;background:var(--bg-surface);min-width:0}.chat-header{display:flex;align-items:center;gap:var(--space-3);padding:0 var(--space-6);height:var(--header-row-h);border-bottom:1px solid var(--border-color);background:var(--bg-surface);flex-shrink:0}.chat-header__avatar{width:38px;height:38px;border-radius:var(--radius-md);background:var(--color-primary-light);border:2px solid var(--color-primary);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0}.chat-header__info{flex:1}.chat-header__name{font-size:15px;font-weight:600;color:var(--text-primary)}.chat-header__status{font-size:12px;color:var(--color-success);display:flex;align-items:center;gap:5px}.chat-header__status:before{content:"";width:6px;height:6px;background:var(--color-success);border-radius:50%;display:inline-block}.chat-header__actions{display:flex;align-items:center;gap:var(--space-2)}.session-timer{display:flex;align-items:center;gap:5px;padding:5px 10px;background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-full);flex-shrink:0;-webkit-user-select:none;user-select:none}.session-timer--running .session-timer__icon{animation:timer-pulse 2s ease-in-out infinite}@keyframes timer-pulse{0%,to{opacity:1}50%{opacity:.5}}.session-timer__icon{font-size:13px;line-height:1}.session-timer__time{font-size:13px;font-weight:500;font-family:Courier New,Courier,monospace;color:var(--text-secondary);min-width:34px;text-align:right}.header-icon-btn{width:34px;height:34px;border-radius:var(--radius-md);background:var(--bg-card);border:1px solid var(--border-color);color:var(--text-secondary);font-size:15px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:var(--transition-fast);flex-shrink:0}.header-icon-btn:hover{background:var(--bg-hover);border-color:var(--border-active);color:var(--text-primary);transform:scale(1.05)}.header-icon-btn--danger:hover{border-color:var(--color-error);color:var(--color-error);background:var(--bg-hover)}.drawer-toggle-btn{width:34px;height:34px;border-radius:var(--radius-md);background:var(--bg-card);border:1px solid var(--border-color);color:var(--text-secondary);font-size:15px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:var(--transition-fast);flex-shrink:0}.drawer-toggle-btn:hover{background:var(--bg-hover);border-color:var(--border-active);color:var(--text-primary);transform:scale(1.05)}.drawer-toggle-btn.active{background:var(--color-primary-light);border-color:var(--color-primary);color:var(--color-primary)}.mode-switcher-bar{display:flex;align-items:center;justify-content:center;padding:0 var(--space-6);height:var(--toolbar-row-h);background:var(--bg-surface);border-bottom:1px solid var(--border-color);flex-shrink:0}.mode-switcher{display:flex;gap:4px;background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-full);padding:4px}.mode-tab{display:flex;align-items:center;gap:6px;padding:6px 18px;border-radius:var(--radius-full);border:none;background:transparent;color:var(--text-secondary);font-size:13px;font-weight:500;cursor:pointer;transition:background .18s ease,color .18s ease;white-space:nowrap}.mode-tab:hover:not(.active){background:var(--bg-hover);color:var(--text-primary)}.mode-tab.active{background:var(--color-primary);color:var(--text-on-primary);box-shadow:0 2px 8px #7c6fff59}.mode-tab__icon{font-size:14px}.mode-panel{display:flex;flex-direction:column;flex:1;overflow:hidden;min-height:0;animation:modeFadeIn .2s ease}@keyframes modeFadeIn{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}@media (max-width: 600px){.sidebar{width:56px;min-width:56px}.tutor-icon-btn{width:40px;height:40px;font-size:17px}.mode-tab{padding:6px 12px;font-size:12px}.mode-tab__label{display:none}}.chat-window{flex:1;overflow-y:auto;padding:var(--space-6);display:flex;flex-direction:column;gap:var(--space-4);scroll-behavior:smooth}.chat-empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-4);text-align:center;padding:var(--space-8)}.chat-empty__icon{font-size:56px;line-height:1;filter:drop-shadow(0 0 20px rgba(124,111,255,.4))}.chat-empty__title{font-size:20px;font-weight:600;color:var(--text-primary)}.chat-empty__sub{font-size:14px;color:var(--text-secondary);max-width:340px;line-height:1.7}.chat-empty__suggestions{display:flex;flex-wrap:wrap;gap:var(--space-2);justify-content:center;margin-top:var(--space-2)}.suggestion-chip{padding:8px 14px;background:var(--color-primary-light);border:1px solid var(--border-active);border-radius:var(--radius-full);color:var(--text-accent);font-size:13px;cursor:pointer;transition:var(--transition-fast);font-weight:500}.suggestion-chip:hover{background:var(--color-primary);color:#fff;transform:translateY(-2px);box-shadow:0 4px 12px #7c6fff66}.message-group{display:flex;gap:var(--space-3);align-items:flex-end;animation:fadeSlideUp .25s ease both}.message-group.user{flex-direction:row-reverse}@keyframes fadeSlideUp{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.msg-avatar{width:32px;height:32px;border-radius:var(--radius-md);background:var(--color-primary-light);border:2px solid var(--color-primary);display:flex;align-items:center;justify-content:center;font-size:15px;flex-shrink:0}.message-group.user .msg-avatar{background:var(--bg-card);border-color:var(--border-color)}.message-bubble{max-width:75%;padding:10px 16px;border-radius:var(--radius-lg);line-height:1.65;font-size:14px;position:relative;word-break:break-word}.message-bubble.ai{background:var(--bubble-ai-bg);color:var(--bubble-ai-text);border-bottom-left-radius:var(--radius-sm);border:1px solid var(--border-color)}.message-bubble.user{background:var(--bubble-user-bg);color:var(--bubble-user-text);border-bottom-right-radius:var(--radius-sm)}.message-bubble__time{font-size:11px;color:var(--text-muted);margin-top:4px;display:block}.message-group.user .message-bubble__time{text-align:right}.typing-indicator{display:flex;align-items:center;gap:var(--space-3);animation:fadeSlideUp .2s ease both}.typing-dots{background:var(--bubble-ai-bg);border:1px solid var(--border-color);border-radius:var(--radius-lg);border-bottom-left-radius:var(--radius-sm);padding:12px 18px;display:flex;gap:5px;align-items:center}.typing-dots span{width:7px;height:7px;background:var(--text-muted);border-radius:50%;display:inline-block;animation:blink 1.2s infinite ease-in-out}.typing-dots span:nth-child(2){animation-delay:.2s}.typing-dots span:nth-child(3){animation-delay:.4s}@keyframes blink{0%,80%,to{transform:scale(.8);opacity:.5}40%{transform:scale(1.1);opacity:1}}.input-area{padding:var(--space-4) var(--space-6);border-top:1px solid var(--border-color);background:var(--bg-surface);flex-shrink:0;display:flex;flex-direction:column;align-items:center}.input-wrapper{display:flex;align-items:flex-end;gap:var(--space-3);background:var(--bg-input);border:1.5px solid var(--border-color);border-radius:var(--radius-xl);padding:10px 12px 10px 18px;transition:var(--transition-base);width:100%;max-width:720px}.input-wrapper:focus-within{border-color:var(--color-primary);box-shadow:0 0 0 3px #7c6fff1f}.input-wrapper textarea{flex:1;background:none;border:none;outline:none;color:var(--text-primary);font-size:14px;line-height:1.6;resize:none;max-height:160px;min-height:24px;overflow-y:auto}.input-wrapper textarea::placeholder{color:var(--text-muted)}.input-send-btn{width:38px;height:38px;border-radius:var(--radius-full);background:var(--color-primary);color:#fff;display:flex;align-items:center;justify-content:center;transition:var(--transition-fast);flex-shrink:0;font-size:16px}.input-send-btn:hover:not(:disabled){background:var(--color-primary-hover);transform:scale(1.08);box-shadow:var(--shadow-glow)}.input-send-btn:disabled{opacity:.4;cursor:not-allowed}.input-hint{font-size:11px;color:var(--text-muted);margin-top:6px;text-align:center;padding-left:4px}.message-bubble p{margin-bottom:8px}.message-bubble p:last-child{margin-bottom:0}.message-bubble code{background:#0000004d;padding:2px 6px;border-radius:4px;font-family:var(--font-mono);font-size:13px}.message-bubble pre{background:#0006;padding:12px;border-radius:var(--radius-sm);overflow-x:auto;margin:8px 0}.message-bubble ul,.message-bubble ol{padding-left:18px;margin:6px 0}@media (max-width: 600px){.message-bubble{max-width:90%}.chat-window,.input-area{padding:var(--space-3)}}.right-drawer{position:fixed;top:0;right:0;bottom:0;width:var(--drawer-w);background:var(--drawer-bg);border-left:1px solid var(--drawer-border);display:flex;flex-direction:column;z-index:50;transform:translate(100%);transition:transform .3s cubic-bezier(.4,0,.2,1);overflow:hidden}.right-drawer.open{transform:translate(0)}.drawer-resize-handle{position:absolute;left:0;top:0;bottom:0;width:12px;cursor:ew-resize;z-index:10;display:flex;align-items:center;justify-content:center}.drawer-resize-handle:before{content:"";position:absolute;left:5px;top:0;bottom:0;width:1px;background:var(--drawer-border);transition:background .15s ease,width .15s ease}.drawer-resize-handle__grip{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:grid;grid-template-columns:3px 3px;grid-template-rows:repeat(3,3px);gap:3px;padding:7px 4px;border-radius:5px;background:var(--bg-card);border:1px solid var(--drawer-border);transition:background .15s ease,border-color .15s ease,box-shadow .15s ease,transform .15s ease;z-index:1}.drawer-resize-handle__grip span{display:block;width:3px;height:3px;border-radius:50%;background:var(--text-muted);transition:background .15s ease}.drawer-handle-reset{position:absolute;top:calc(50% + 30px);left:50%;transform:translate(-50%);width:20px;height:20px;border-radius:50%;background:var(--bg-card);border:1px solid var(--border-color);color:var(--text-muted);font-size:10px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:2;transition:background .15s ease,border-color .15s ease,color .15s ease,box-shadow .15s ease;pointer-events:auto}.drawer-handle-reset:hover{background:var(--color-error, #EF4444);border-color:var(--color-error, #EF4444);color:#fff;box-shadow:0 0 0 3px #ef44442e}.drawer-resize-handle:hover:before{background:var(--color-primary);width:2px}.drawer-resize-handle:hover .drawer-resize-handle__grip{border-color:var(--color-primary);box-shadow:0 0 0 3px #7c6fff1f;background:var(--bg-surface, var(--bg-card))}.drawer-resize-handle:hover .drawer-resize-handle__grip span{background:var(--color-primary)}.drawer-resize-handle.dragging:before{background:var(--color-primary);width:2px}.drawer-resize-handle.dragging .drawer-resize-handle__grip{border-color:var(--color-primary);box-shadow:0 0 0 4px #7c6fff33;transform:translate(-50%,-50%) scaleY(1.08)}.drawer-resize-handle.dragging .drawer-resize-handle__grip span{background:var(--color-primary)}.right-drawer.resizing{transition:none!important}@media (max-width: 767px){.drawer-resize-handle{display:none}}.drawer-backdrop{display:none;position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:49;opacity:0;transition:opacity .3s ease}.drawer-header{display:flex;align-items:center;justify-content:space-between;padding:0 var(--space-4) 0 var(--space-5);height:var(--header-row-h);border-bottom:1px solid var(--drawer-border);flex-shrink:0;gap:var(--space-2)}.drawer-header__title{font-size:14px;font-weight:600;color:var(--text-secondary);text-transform:uppercase;letter-spacing:.08em}.drawer-close-btn{width:28px;height:28px;border-radius:var(--radius-sm);background:transparent;border:1px solid transparent;color:var(--text-muted);font-size:14px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:var(--transition-fast)}.drawer-close-btn:hover{background:var(--bg-hover);border-color:var(--border-color);color:var(--text-primary)}@media (min-width: 768px){.drawer-close-btn{display:none}}.drawer-tabs-wrapper{display:flex;flex-direction:column;flex:1;overflow:hidden}.drawer-tabs{display:flex;align-items:center;gap:var(--space-1);padding:0 var(--space-4);height:var(--toolbar-row-h);background:var(--drawer-tab-bg);border-bottom:1px solid var(--drawer-border);flex-shrink:0}.drawer-tab{flex:1;display:flex;align-items:center;justify-content:center;gap:5px;padding:7px var(--space-2);border-radius:var(--radius-full);border:none;background:transparent;color:var(--text-secondary);font-size:12px;font-weight:500;cursor:pointer;transition:var(--transition-fast);white-space:nowrap}.drawer-tab:hover{background:var(--bg-hover);color:var(--text-primary)}.drawer-tab.active{background:var(--drawer-tab-active);color:var(--text-on-primary)}.drawer-tab__icon{font-size:13px}.drawer-tab__label{font-size:12px}.drawer-tab-content{flex:1;overflow-y:auto;overscroll-behavior:contain}.drawer-tab-content::-webkit-scrollbar{width:4px}.drawer-tab-content::-webkit-scrollbar-track{background:transparent}.drawer-tab-content::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:2px}.drawer-tab-panel{padding:var(--space-5);animation:drawerFadeIn .2s ease}.drawer-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:var(--space-10) var(--space-6);gap:var(--space-3)}.drawer-placeholder__icon{font-size:40px;opacity:.5}.drawer-placeholder__title{font-size:16px;font-weight:600;color:var(--text-primary);margin:0}.drawer-placeholder__body{font-size:13px;color:var(--text-secondary);line-height:1.6;max-width:260px;margin:0}@keyframes drawerFadeIn{0%{opacity:0;transform:translateY(4px)}to{opacity:1;transform:translateY(0)}}@media (max-width: 1199px){.right-drawer{position:fixed}.drawer-backdrop.visible{display:block;opacity:1}}@media (max-width: 767px){.right-drawer{width:100%;z-index:100}.drawer-close-btn{display:flex}.drawer-backdrop.visible{display:block;opacity:1}}.ai-cap__header{margin-bottom:var(--space-4)}.ai-cap__title{font-size:15px;font-weight:700;color:var(--text-primary);margin:0 0 var(--space-1)}.ai-cap__subtitle{font-size:12px;color:var(--text-muted);margin:0}.ai-cap__list{display:flex;flex-direction:column;gap:var(--space-3);margin-bottom:var(--space-4)}.ai-cap__state{display:flex;flex-direction:column;align-items:center;gap:var(--space-3);padding:var(--space-8) 0;color:var(--text-secondary);font-size:13px;text-align:center}.ai-cap__state--error{color:var(--color-error)}.ai-cap__spinner{width:20px;height:20px;border:2px solid var(--border-color);border-top-color:var(--color-primary);border-radius:50%;animation:spin .7s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.ai-file-card{background:var(--bg-card);border:1px solid var(--border-color);border-left:4px solid var(--accent, var(--color-primary));border-radius:var(--radius-md);padding:var(--space-4);transition:var(--transition-fast)}.ai-file-card:hover{border-color:var(--accent, var(--color-primary));box-shadow:0 0 0 1px var(--accent, var(--color-primary)),var(--shadow-sm)}.ai-file-card__header{display:flex;align-items:flex-start;gap:var(--space-3);margin-bottom:var(--space-2)}.ai-file-card__icon{font-size:20px;line-height:1;flex-shrink:0}.ai-file-card__titles{display:flex;flex-direction:column;gap:2px;min-width:0}.ai-file-card__name{font-size:14px;font-weight:600;color:var(--text-primary)}.ai-file-card__filename{font-size:11px;color:var(--text-muted);font-family:var(--font-mono)}.ai-file-card__desc{font-size:12px;color:var(--text-secondary);line-height:1.5;margin:0 0 var(--space-3)}.ai-file-card__footer{display:flex;align-items:center;justify-content:space-between;gap:var(--space-2)}.ai-file-card__meta{font-size:11px;color:var(--text-muted)}.ai-file-card__view-btn{font-size:12px;font-weight:500;color:var(--color-primary);background:var(--color-primary-light);border:1px solid transparent;border-radius:var(--radius-full);padding:4px 10px;cursor:pointer;transition:var(--transition-fast);white-space:nowrap}.ai-file-card__view-btn:hover{background:var(--color-primary);color:var(--text-on-primary)}.ai-tip-card{display:flex;gap:var(--space-3);align-items:flex-start;background:#7c6fff0f;border:1px solid rgba(124,111,255,.15);border-radius:var(--radius-md);padding:var(--space-3) var(--space-4);margin-top:var(--space-4)}.ai-tip-card__icon{font-size:16px;flex-shrink:0}.ai-tip-card__text{font-size:12px;color:var(--text-secondary);line-height:1.5;margin:0}.ai-tip-card__text code{font-family:var(--font-mono);font-size:11px;background:#ffffff0f;padding:1px 4px;border-radius:3px;color:var(--color-accent)}.md-viewer-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000b3;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:200;display:flex;align-items:center;justify-content:center;padding:var(--space-6);animation:overlayFadeIn .2s ease}@keyframes overlayFadeIn{0%{opacity:0}to{opacity:1}}.md-viewer{background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-lg);width:100%;max-width:700px;max-height:80vh;display:flex;flex-direction:column;box-shadow:var(--shadow-lg);animation:modalSlideIn .2s ease}@keyframes modalSlideIn{0%{opacity:0;transform:scale(.95) translateY(8px)}to{opacity:1;transform:scale(1) translateY(0)}}.md-viewer__header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--border-color);flex-shrink:0;gap:var(--space-3)}.md-viewer__title{font-size:14px;font-weight:600;color:var(--text-primary);font-family:var(--font-mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.md-viewer__close{width:28px;height:28px;border-radius:var(--radius-sm);background:transparent;border:1px solid transparent;color:var(--text-muted);font-size:14px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;transition:var(--transition-fast)}.md-viewer__close:hover{background:var(--bg-hover);border-color:var(--border-color);color:var(--text-primary)}.md-viewer__body{flex:1;overflow-y:auto;padding:var(--space-5) var(--space-6);font-size:14px;line-height:1.7;color:var(--bubble-ai-text)}.md-viewer__body::-webkit-scrollbar{width:4px}.md-viewer__body::-webkit-scrollbar-track{background:transparent}.md-viewer__body::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:2px}.md-viewer__body h1,.md-viewer__body h2,.md-viewer__body h3,.md-viewer__body h4,.md-viewer__body h5,.md-viewer__body h6{color:var(--text-primary);font-weight:700;margin:var(--space-5) 0 var(--space-2);line-height:1.3}.md-viewer__body h1{font-size:20px;border-bottom:1px solid var(--border-color);padding-bottom:var(--space-2)}.md-viewer__body h2{font-size:17px}.md-viewer__body h3{font-size:15px}.md-viewer__body h4,.md-viewer__body h5,.md-viewer__body h6{font-size:13px}.md-viewer__body p{margin:0 0 var(--space-3)}.md-viewer__body strong{color:var(--text-primary);font-weight:600}.md-viewer__body em{color:var(--text-secondary);font-style:italic}.md-viewer__body a{color:var(--color-primary);text-decoration:underline}.md-viewer__body a:hover{color:var(--color-primary-hover)}.md-viewer__body code{font-family:var(--font-mono);font-size:12px;background:var(--bg-app);border:1px solid var(--border-color);border-radius:3px;padding:1px 5px;color:var(--color-accent)}.md-viewer__body pre{background:var(--bg-app);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:var(--space-4);overflow-x:auto;margin:var(--space-3) 0}.md-viewer__body pre code{background:transparent;border:none;padding:0;font-size:13px;color:var(--text-primary)}.md-viewer__body ul,.md-viewer__body ol{padding-left:var(--space-5);margin:0 0 var(--space-3)}.md-viewer__body li{margin-bottom:var(--space-1)}.md-viewer__body blockquote{border-left:3px solid var(--color-primary);padding-left:var(--space-4);margin:var(--space-3) 0;color:var(--text-secondary);font-style:italic}.md-viewer__body hr{border:none;border-top:1px solid var(--border-color);margin:var(--space-5) 0}.settings-group{margin-bottom:var(--space-5);border-bottom:1px solid var(--drawer-border);padding-bottom:var(--space-4)}.settings-group:last-of-type{border-bottom:none}.settings-group__title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--text-muted);margin:0 0 var(--space-4)}.settings-item{display:flex;flex-direction:column;gap:var(--space-2);margin-bottom:var(--space-4)}.settings-item__meta{display:flex;flex-direction:column;gap:2px}.settings-item__label{font-size:13px;font-weight:500;color:var(--text-primary)}.settings-item__hint{font-size:11px;color:var(--text-muted);line-height:1.4}.settings-item__control{width:100%}.settings-select{width:100%;background:var(--bg-app);border:1px solid var(--border-color);border-radius:var(--radius-md);color:var(--text-primary);font-size:13px;padding:8px 32px 8px 12px;cursor:pointer;transition:border-color .15s ease;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%239090B8' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 12px center}.settings-select:focus{outline:none;border-color:var(--color-primary);box-shadow:0 0 0 3px #7c6fff1f}.settings-select:disabled{opacity:.45;cursor:not-allowed}.settings-radio-group{display:flex;gap:4px;background:var(--bg-app);border:1px solid var(--border-color);border-radius:var(--radius-full);padding:3px}.settings-radio{flex:1;padding:6px var(--space-2);border-radius:var(--radius-full);border:none;background:transparent;color:var(--text-secondary);font-size:12px;font-weight:500;cursor:pointer;transition:background .15s ease,color .15s ease;text-align:center;white-space:nowrap}.settings-radio:hover:not(.active){background:var(--bg-hover);color:var(--text-primary)}.settings-radio.active{background:var(--color-primary);color:var(--text-on-primary);box-shadow:0 1px 6px #7c6fff59}.settings-slider-row{display:flex;align-items:center;gap:var(--space-3)}.settings-slider{flex:1;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:4px;background:var(--bg-hover);border-radius:2px;outline:none;cursor:pointer}.settings-slider::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;border-radius:50%;background:var(--color-primary);box-shadow:0 0 6px #7c6fff80;cursor:pointer;transition:box-shadow .15s ease}.settings-slider::-webkit-slider-thumb:hover{box-shadow:0 0 10px #7c6fffb3}.settings-slider::-moz-range-thumb{width:16px;height:16px;border-radius:50%;background:var(--color-primary);border:none;box-shadow:0 0 6px #7c6fff80;cursor:pointer}.settings-slider__value{font-size:12px;font-weight:600;color:var(--text-primary);font-family:var(--font-mono);min-width:36px;text-align:right}.settings-toggle{position:relative;width:42px;height:24px;border-radius:var(--radius-full);border:none;background:var(--bg-hover);cursor:pointer;transition:background .2s ease;padding:0;flex-shrink:0}.settings-toggle.on{background:var(--color-primary);box-shadow:0 0 8px #7c6fff66}.settings-toggle__thumb{position:absolute;top:3px;left:3px;width:18px;height:18px;border-radius:50%;background:var(--text-on-primary);box-shadow:0 1px 4px #0000004d;transition:transform .2s ease;pointer-events:none}.settings-toggle.on .settings-toggle__thumb{transform:translate(18px)}.settings-reset-row{display:flex;justify-content:center;padding-top:var(--space-3);margin-top:var(--space-2)}.settings-reset-btn{font-size:12px;font-weight:500;color:var(--text-secondary);background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-full);padding:7px 18px;cursor:pointer;transition:var(--transition-fast)}.settings-reset-btn:hover{border-color:var(--color-error);color:var(--color-error)}.doc-tab__header{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--space-4)}.doc-tab__title{font-size:15px;font-weight:700;color:var(--text-primary);margin:0}.doc-tab__upload-btn{font-size:12px;font-weight:600;color:var(--text-on-primary);background:var(--color-primary);border:none;border-radius:var(--radius-full);padding:5px 12px;cursor:pointer;transition:var(--transition-fast);white-space:nowrap}.doc-tab__upload-btn:hover:not(:disabled){background:var(--color-primary-hover)}.doc-tab__upload-btn:disabled{opacity:.45;cursor:not-allowed}.doc-tab__error{background:#ef44441a;border:1px solid rgba(239,68,68,.3);border-radius:var(--radius-md);color:var(--color-error);font-size:12px;padding:var(--space-3) var(--space-4);margin-bottom:var(--space-3)}.doc-list{display:flex;flex-direction:column;gap:var(--space-3);margin-bottom:var(--space-4)}.doc-card{background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-md);padding:var(--space-3) var(--space-4);transition:var(--transition-fast)}.doc-card:hover{border-color:var(--border-active);box-shadow:0 0 0 1px #7c6fff26,var(--shadow-sm);transform:translateY(-1px)}.doc-card__top{display:flex;align-items:center;gap:var(--space-3);margin-bottom:var(--space-2)}.doc-card__icon{font-size:22px;flex-shrink:0;line-height:1}.doc-card__info{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1}.doc-card__name{font-size:13px;font-weight:600;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.doc-card__meta{font-size:11px;color:var(--text-muted)}.doc-card__status{font-size:11px;font-weight:600;border-radius:var(--radius-full);padding:3px 8px;white-space:nowrap;flex-shrink:0}.doc-card__status--success{background:#22c55e1f;color:var(--color-success)}.doc-card__status--failed{background:#ef44441f;color:var(--color-error)}.doc-card__status--pending{background:#f59e0b1f;color:var(--color-warning);animation:pulse 1.6s ease-in-out infinite}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}.doc-card__actions{display:flex;justify-content:flex-end}.doc-card__btn{font-size:11px;font-weight:500;color:var(--text-muted);background:transparent;border:1px solid transparent;border-radius:var(--radius-full);padding:3px 10px;cursor:pointer;transition:var(--transition-fast)}.doc-card__btn:hover{background:#7c6fff1a;border-color:#7c6fff4d;color:var(--color-accent, #7C6FFF)}.doc-card__btn--view:hover{background:#3b82f61a;border-color:#3b82f64d;color:#3b82f6}.doc-card__btn--edit:hover{background:#f59e0b1a;border-color:#f59e0b4d;color:var(--color-warning, #F59E0B)}.doc-card__btn--delete:hover{background:#ef44441a;border-color:#ef44444d;color:var(--color-error)}.doc-upload-zone{display:flex;flex-direction:column;align-items:center;gap:var(--space-2);padding:var(--space-5) var(--space-4);border:2px dashed var(--border-color);border-radius:var(--radius-md);margin-top:var(--space-4);cursor:pointer;transition:border-color .2s ease,background .2s ease;text-align:center}.doc-upload-zone:hover,.doc-upload-zone:focus{border-color:var(--color-primary);background:var(--color-primary-light);outline:none}.doc-upload-zone.active{border-color:var(--color-primary);background:var(--color-primary-light);box-shadow:0 0 0 3px #7c6fff26}.doc-upload-zone__icon{font-size:28px;opacity:.6}.doc-upload-zone__text{font-size:13px;color:var(--text-secondary)}.doc-upload-zone__text u{color:var(--color-primary);text-decoration-color:var(--color-primary)}.doc-upload-zone__hint{font-size:11px;color:var(--text-muted)}.doc-upload-progress{margin-top:var(--space-3)}.doc-upload-progress__label{font-size:12px;color:var(--text-secondary);margin-bottom:var(--space-1)}.doc-upload-progress__bar{height:4px;background:var(--bg-hover);border-radius:2px;overflow:hidden}.doc-upload-progress__fill{height:100%;background:var(--color-primary);border-radius:2px;transition:width .15s ease}.doc-empty{display:flex;flex-direction:column;align-items:center;text-align:center;padding:var(--space-8) var(--space-4);gap:var(--space-2)}.doc-empty__icon{font-size:40px;opacity:.4}.doc-empty__title{font-size:15px;font-weight:600;color:var(--text-primary);margin:0}.doc-empty__body{font-size:13px;color:var(--text-secondary);margin:0}.doc-empty__btn{margin-top:var(--space-3);font-size:13px;font-weight:600;color:var(--text-on-primary);background:var(--color-primary);border:none;border-radius:var(--radius-full);padding:8px 18px;cursor:pointer;transition:var(--transition-fast)}.doc-empty__btn:hover:not(:disabled){background:var(--color-primary-hover)}.doc-empty__btn:disabled{opacity:.45;cursor:not-allowed}.ai-cap__header-row{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--space-3)}.ai-cap__new-btn{font-size:12px;font-weight:600;color:var(--text-on-primary);background:var(--color-primary);border:none;border-radius:var(--radius-full);padding:5px 12px;cursor:pointer;transition:var(--transition-fast);white-space:nowrap;flex-shrink:0}.ai-cap__new-btn:hover:not(:disabled){background:var(--color-primary-hover)}.ai-cap__new-btn:disabled{opacity:.45;cursor:not-allowed}.ai-file-card__actions{display:flex;gap:var(--space-2);align-items:center}.ai-file-card__edit-btn{font-size:12px;font-weight:500;color:var(--text-secondary);background:var(--bg-app);border:1px solid var(--border-color);border-radius:var(--radius-full);padding:4px 10px;cursor:pointer;transition:var(--transition-fast);white-space:nowrap}.ai-file-card__edit-btn:hover{background:var(--color-primary-light);border-color:var(--color-primary);color:var(--color-primary)}.user-files-section{margin-top:var(--space-4)}.user-files-section__divider{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:var(--text-muted);padding:var(--space-2) 0;border-top:1px solid var(--border-color);margin-bottom:var(--space-2)}.user-file-row{display:flex;align-items:center;gap:var(--space-2);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);border:1px solid var(--border-color);background:var(--bg-card);margin-bottom:var(--space-2);transition:var(--transition-fast)}.user-file-row:hover{border-color:var(--border-active)}.user-file-row__icon{font-size:16px;flex-shrink:0}.user-file-row__name{font-size:13px;font-family:var(--font-mono);color:var(--text-primary);flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.user-file-row__actions{display:flex;gap:var(--space-2);flex-shrink:0}.user-file-row__btn{font-size:12px;font-weight:500;color:var(--text-secondary);background:transparent;border:1px solid transparent;border-radius:var(--radius-full);padding:3px 9px;cursor:pointer;transition:var(--transition-fast);white-space:nowrap}.user-file-row__btn:hover{background:var(--color-primary-light);border-color:var(--color-primary);color:var(--color-primary)}.user-file-row__btn--delete:hover{background:#ef44441a;border-color:#ef44444d;color:var(--color-error)}.ai-editor-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000bf;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:300;display:flex;align-items:stretch;justify-content:center;padding:var(--space-6);animation:overlayFadeIn .15s ease}.ai-editor{background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-lg);width:100%;max-width:860px;display:flex;flex-direction:column;box-shadow:var(--shadow-lg);animation:modalSlideIn .2s ease;overflow:hidden}.ai-editor__header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--border-color);flex-shrink:0;gap:var(--space-3)}.ai-editor__title{font-size:14px;font-weight:600;color:var(--text-primary);font-family:var(--font-mono);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}.ai-editor__header-actions{display:flex;align-items:center;gap:var(--space-2);flex-shrink:0}.ai-editor__save-btn{font-size:13px;font-weight:600;color:var(--text-on-primary);background:var(--color-primary);border:none;border-radius:var(--radius-full);padding:6px 16px;cursor:pointer;transition:var(--transition-fast);opacity:.45}.ai-editor__save-btn.active,.ai-editor__save-btn:not(:disabled):hover{opacity:1;background:var(--color-primary-hover)}.ai-editor__save-btn:disabled{cursor:not-allowed}.ai-editor__cancel-btn{font-size:13px;font-weight:500;color:var(--text-secondary);background:transparent;border:1px solid var(--border-color);border-radius:var(--radius-full);padding:5px 14px;cursor:pointer;transition:var(--transition-fast)}.ai-editor__cancel-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.ai-editor__close-btn{width:28px;height:28px;border-radius:var(--radius-sm);background:transparent;border:1px solid transparent;color:var(--text-muted);font-size:14px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:var(--transition-fast);flex-shrink:0}.ai-editor__close-btn:hover{background:var(--bg-hover);border-color:var(--border-color);color:var(--text-primary)}.ai-editor__tab-bar{display:flex;align-items:center;gap:var(--space-1);padding:var(--space-2) var(--space-4);border-bottom:1px solid var(--border-color);background:var(--drawer-tab-bg);flex-shrink:0}.ai-editor__tab{font-size:12px;font-weight:500;color:var(--text-secondary);background:transparent;border:none;border-radius:var(--radius-full);padding:5px 12px;cursor:pointer;transition:var(--transition-fast)}.ai-editor__tab:hover{background:var(--bg-hover);color:var(--text-primary)}.ai-editor__tab.active{background:var(--drawer-tab-active);color:var(--text-on-primary)}.ai-editor__dirty-badge{font-size:11px;color:var(--color-warning);margin-left:auto;opacity:.9}.ai-editor__body{flex:1;overflow:hidden;display:flex;flex-direction:column;min-height:0}.ai-editor__textarea{flex:1;width:100%;height:100%;padding:var(--space-5) var(--space-6);background:var(--bg-app);border:none;outline:none;color:var(--text-primary);font-family:var(--font-mono);font-size:13px;line-height:1.7;resize:none;box-sizing:border-box}.ai-editor__textarea::placeholder{color:var(--text-muted)}.ai-editor__preview{flex:1;overflow-y:auto;padding:var(--space-5) var(--space-6)}.ai-editor__preview::-webkit-scrollbar{width:4px}.ai-editor__preview::-webkit-scrollbar-track{background:transparent}.ai-editor__preview::-webkit-scrollbar-thumb{background:#ffffff1a;border-radius:2px}.ai-editor__error{padding:var(--space-3) var(--space-5);background:#ef44441a;border-top:1px solid rgba(239,68,68,.3);color:var(--color-error);font-size:12px;flex-shrink:0}.ai-editor-confirm-overlay{position:fixed;top:0;right:0;bottom:0;left:0;z-index:400;display:flex;align-items:center;justify-content:center;background:#00000080;animation:overlayFadeIn .15s ease}.ai-editor-confirm{background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-lg);padding:var(--space-6);max-width:360px;width:100%;box-shadow:var(--shadow-lg)}.ai-editor-confirm__msg{font-size:14px;color:var(--text-primary);margin:0 0 var(--space-5);line-height:1.5}.ai-editor-confirm__actions{display:flex;gap:var(--space-3);justify-content:flex-end}.ai-editor-confirm__discard{font-size:13px;font-weight:500;color:var(--text-on-primary);background:var(--color-error);border:none;border-radius:var(--radius-full);padding:7px 16px;cursor:pointer;transition:var(--transition-fast)}.ai-editor-confirm__discard:hover{filter:brightness(1.1)}.ai-editor-confirm__keep{font-size:13px;font-weight:500;color:var(--text-secondary);background:transparent;border:1px solid var(--border-color);border-radius:var(--radius-full);padding:6px 16px;cursor:pointer;transition:var(--transition-fast)}.ai-editor-confirm__keep:hover{background:var(--bg-hover);color:var(--text-primary)}.create-file-overlay{position:fixed;top:0;right:0;bottom:0;left:0;background:#000000a6;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);z-index:300;display:flex;align-items:center;justify-content:center;padding:var(--space-6);animation:overlayFadeIn .15s ease}.create-file-modal{background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-lg);width:100%;max-width:420px;box-shadow:var(--shadow-lg);animation:modalSlideIn .2s ease;overflow:hidden}.create-file-modal__header{display:flex;align-items:center;justify-content:space-between;padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--border-color)}.create-file-modal__title{font-size:14px;font-weight:600;color:var(--text-primary)}.create-file-modal__field{padding:var(--space-4) var(--space-5) 0}.create-file-modal__label{display:block;font-size:12px;font-weight:600;color:var(--text-secondary);margin-bottom:var(--space-2);text-transform:uppercase;letter-spacing:.05em}.create-file-modal__filename-row{display:flex;align-items:center;gap:var(--space-2)}.create-file-modal__input{flex:1;background:var(--bg-app);border:1px solid var(--border-color);border-radius:var(--radius-md);color:var(--text-primary);font-family:var(--font-mono);font-size:13px;padding:8px 12px;outline:none;transition:border-color .15s ease}.create-file-modal__input:focus{border-color:var(--color-primary);box-shadow:0 0 0 3px #7c6fff1f}.create-file-modal__input.invalid{border-color:var(--color-error)}.create-file-modal__suffix{font-size:13px;font-family:var(--font-mono);color:var(--text-muted);flex-shrink:0}.create-file-modal__error{display:block;font-size:11px;color:var(--color-error);margin-top:var(--space-1)}.create-file-modal__select{margin-top:0}.create-file-modal__footer{display:flex;justify-content:flex-end;gap:var(--space-3);padding:var(--space-5)}.create-file-modal__cancel-btn{font-size:13px;font-weight:500;color:var(--text-secondary);background:transparent;border:1px solid var(--border-color);border-radius:var(--radius-full);padding:6px 14px;cursor:pointer;transition:var(--transition-fast)}.create-file-modal__cancel-btn:hover{background:var(--bg-hover);color:var(--text-primary)}.create-file-modal__create-btn{font-size:13px;font-weight:600;color:var(--text-on-primary);background:var(--color-primary);border:none;border-radius:var(--radius-full);padding:7px 18px;cursor:pointer;transition:var(--transition-fast)}.create-file-modal__create-btn:hover:not(:disabled){background:var(--color-primary-hover)}.create-file-modal__create-btn:disabled{opacity:.45;cursor:not-allowed}@media (min-width: 1200px){.app-shell.drawer-open .main-content{margin-right:var(--drawer-w);transition:margin-right .3s cubic-bezier(.4,0,.2,1)}.app-shell .main-content{transition:margin-right .3s cubic-bezier(.4,0,.2,1)}}.call-stage{position:relative;flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;background:var(--bg-app);overflow:hidden;min-height:0}.call-stage:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:radial-gradient(ellipse 60% 55% at 50% 45%,rgba(124,111,255,.06) 0%,transparent 70%);pointer-events:none}.call-avatar-wrapper{display:flex;flex-direction:column;align-items:center;gap:var(--space-5);z-index:1}.call-avatar{position:relative;display:flex;align-items:center;justify-content:center}.avatar-glow{position:absolute;top:-24px;right:-24px;bottom:-24px;left:-24px;display:flex;align-items:center;justify-content:center;pointer-events:none}.avatar-glow__ring{position:absolute;border-radius:50%;border:1px solid rgba(124,111,255,.15);transition:opacity .4s ease}.avatar-glow__ring--outer{top:0;right:0;bottom:0;left:0;box-shadow:0 0 32px #7c6fff1a}.avatar-glow__ring--inner{top:12px;right:12px;bottom:12px;left:12px;border-color:#7c6fff33;box-shadow:0 0 20px #7c6fff26}.avatar-glow.speaking .avatar-glow__ring--outer{animation:glowRingPulseOuter 1.5s ease-in-out infinite}.avatar-glow.speaking .avatar-glow__ring--inner{animation:glowRingPulseInner 1.5s ease-in-out infinite .15s}@keyframes glowRingPulseOuter{0%,to{box-shadow:0 0 20px #7c6fff26;border-color:#7c6fff33}50%{box-shadow:0 0 60px #7c6fff73,0 0 100px #7c6fff26;border-color:#7c6fff80}}@keyframes glowRingPulseInner{0%,to{box-shadow:0 0 12px #7c6fff33;border-color:#7c6fff40}50%{box-shadow:0 0 36px #7c6fff8c;border-color:#7c6fff99}}.call-avatar__circle{position:relative;width:180px;height:180px;border-radius:50%;background:var(--bg-card);border:3px solid rgba(124,111,255,.3);display:flex;align-items:center;justify-content:center;overflow:hidden;box-shadow:0 0 24px #7c6fff33,var(--shadow-lg);transition:border-color .4s ease,box-shadow .4s ease;z-index:1}.call-avatar.speaking .call-avatar__circle{animation:speakingGlow 1.5s ease-in-out infinite;border-color:#7c6fff99}@keyframes speakingGlow{0%,to{box-shadow:0 0 20px #7c6fff4d}50%{box-shadow:0 0 40px #7c6fff99,0 0 80px #7c6fff33}}.call-avatar__emoji{font-size:80px;line-height:1;-webkit-user-select:none;user-select:none}.tutor-avatar{position:relative;display:flex;align-items:center;justify-content:center;flex-shrink:0}.tutor-avatar__img{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;object-fit:cover;border-radius:50%;opacity:0;transition:opacity .25s ease}.tutor-avatar__img.loaded{opacity:1}.tutor-avatar__emoji{line-height:1;-webkit-user-select:none;user-select:none}.tutor-avatar--fill{width:100%;height:100%}.tutor-avatar--fill .tutor-avatar__emoji{font-size:80px;line-height:1}@media (max-width: 767px){.tutor-avatar--fill .tutor-avatar__emoji{font-size:58px}}.tutor-icon__avatar{border-radius:50%;overflow:hidden}.tutor-icon__avatar .tutor-avatar__img{border-radius:50%}.call-avatar__info{text-align:center;display:flex;flex-direction:column;gap:var(--space-1)}.call-avatar__name{font-size:22px;font-weight:700;color:var(--text-primary);margin:0;letter-spacing:-.01em}.call-avatar__role{font-size:14px;color:var(--text-secondary);margin:0;max-width:300px;line-height:1.4}@media (max-width: 767px){.call-avatar__circle{width:130px;height:130px}.call-avatar__emoji{font-size:58px}.call-avatar__name{font-size:18px}.call-avatar__role{font-size:13px}}.call-bar{position:absolute;bottom:32px;left:50%;transform:translate(-50%);display:flex;align-items:center;gap:0;background:var(--call-bar-bg);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1px solid var(--call-bar-border);border-radius:var(--radius-full);padding:10px 16px;z-index:10;box-shadow:var(--shadow-lg);white-space:nowrap}.call-bar__zone{display:flex;align-items:center;gap:var(--space-2);padding:0 var(--space-2)}.call-bar__divider{width:1px;height:32px;background:#ffffff0f;flex-shrink:0}.call-btn{width:var(--call-btn-size);height:var(--call-btn-size);border-radius:50%;border:1px solid transparent;background:transparent;color:var(--text-primary);font-size:20px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .15s ease,border-color .15s ease,transform .15s ease;flex-shrink:0}.call-btn:hover:not(:disabled){background:#ffffff1a}.call-btn:active:not(:disabled){transform:scale(.95)}.call-btn.active{background:var(--color-primary-light);border-color:var(--color-primary);color:var(--color-primary)}.call-btn.danger,.call-btn--end{background:var(--call-end-bg);color:var(--text-on-primary);font-size:18px;transform:rotate(135deg);width:56px;height:56px}.call-btn.danger:hover:not(:disabled),.call-btn--end:hover:not(:disabled){background:var(--call-end-hover);box-shadow:0 4px 16px #ef444466}.call-btn.danger:active:not(:disabled),.call-btn--end:active:not(:disabled){transform:rotate(135deg) scale(.95)}.call-btn:disabled{opacity:.35;cursor:not-allowed}.call-btn.mic-muted{border-color:var(--color-error);color:var(--color-error)}.mic-zone{display:flex;align-items:center;gap:var(--space-2)}.voice-dots{display:flex;align-items:flex-end;gap:3px;height:20px;padding-bottom:2px}.voice-dot{width:3px;background:var(--text-primary);border-radius:2px;height:6px;animation:voiceLevel .6s ease-in-out infinite;transition:background .2s ease}.voice-dot.paused{animation:none;height:4px;background:var(--text-muted)}.voice-dot:nth-child(1){animation-delay:0s;animation-duration:.55s}.voice-dot:nth-child(2){animation-delay:.1s;animation-duration:.65s}.voice-dot:nth-child(3){animation-delay:.2s;animation-duration:.5s}.voice-dot:nth-child(4){animation-delay:.3s;animation-duration:.7s}@keyframes voiceLevel{0%,to{height:4px}50%{height:18px}}.call-join-screen{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--space-5);background:var(--bg-app);position:relative;overflow:hidden}.call-join-screen:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;background:radial-gradient(ellipse 60% 55% at 50% 45%,rgba(124,111,255,.06) 0%,transparent 70%);pointer-events:none}.call-join__avatar-wrap{display:flex;flex-direction:column;align-items:center;gap:var(--space-5);z-index:1}.call-join__status{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--text-secondary);background:var(--bg-card);border:1px solid var(--border-color);border-radius:var(--radius-full);padding:6px 14px;z-index:1}.call-join__status-dot{width:8px;height:8px;border-radius:50%;background:var(--color-success);animation:statusPulse 2s ease-in-out infinite;flex-shrink:0}@keyframes statusPulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(.85)}}.call-join__btn{display:flex;align-items:center;gap:10px;padding:14px 36px;background:var(--color-success);color:var(--text-on-primary);border:none;border-radius:var(--radius-full);font-size:16px;font-weight:600;cursor:pointer;z-index:1;transition:transform .15s ease,box-shadow .15s ease,background .15s ease;box-shadow:0 4px 20px #22c55e59}.call-join__btn:hover{transform:scale(1.04);box-shadow:0 6px 28px #22c55e80;background:var(--color-success-hover)}.call-join__btn:active{transform:scale(.98)}.call-join__btn-icon{font-size:18px;line-height:1}.call-join__hint{font-size:12px;color:var(--text-muted);margin:0;z-index:1}@media (max-width: 767px){.call-bar{bottom:20px;padding:8px 12px}.call-bar__zone{padding:0 var(--space-1)}.call-btn{width:40px;height:40px;font-size:17px}.call-btn--end,.call-btn.danger{width:46px;height:46px;font-size:16px}.voice-dots{display:none}}