NeonRyan commited on
Commit
5807365
·
unverified ·
1 Parent(s): 3b978bc

Add User Guide (#53)

Browse files

* Draft 1- Enhance UI with User Guide and Sidebar Improvements

- Added UserGuide component to App for global help access.
- Updated Sidebar component to replace icons and improve button styles.
- Introduced new chat button with updated design and functionality.
- Enhanced ChatPage with a help button to open the user guide.
- Improved CSS styles for better layout and user experience.

* Enhance User Guide with Advisor Information

- Updated UserGuide component to include advisor data from app configuration.
- Modified user guide content to dynamically display the number of advisors and their descriptions.
- Replaced static advisor list with a generated list based on available advisors.

* Fixed Help Circle error

phd-advisor-frontend/src/App.js CHANGED
@@ -5,6 +5,7 @@ import HomePage from './pages/HomePage';
5
  import ChatPage from './pages/ChatPage';
6
  import AuthPage from './pages/AuthPage';
7
  import CanvasPage from './pages/CanvasPage';
 
8
  import './styles/components.css';
9
 
10
  function App() {
@@ -97,6 +98,8 @@ function App() {
97
  onSignOut={handleSignOut}
98
  />
99
  )}
 
 
100
  </div>
101
  </ThemeProvider>
102
  </AppConfigProvider>
 
5
  import ChatPage from './pages/ChatPage';
6
  import AuthPage from './pages/AuthPage';
7
  import CanvasPage from './pages/CanvasPage';
8
+ import UserGuide from './components/UserGuide';
9
  import './styles/components.css';
10
 
11
  function App() {
 
98
  onSignOut={handleSignOut}
99
  />
100
  )}
101
+ {/* Global help center — listens for the 'open-user-guide' event */}
102
+ <UserGuide />
103
  </div>
104
  </ThemeProvider>
105
  </AppConfigProvider>
phd-advisor-frontend/src/components/UserGuide.js ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from 'react';
2
+ import ReactDOM from 'react-dom';
3
+ import ReactMarkdown from 'react-markdown';
4
+ import remarkGfm from 'remark-gfm';
5
+ import * as LucideIcons from 'lucide-react';
6
+ import { X, Search, ChevronRight, BookOpen } from 'lucide-react';
7
+ import { useAppConfig } from '../contexts/AppConfigContext';
8
+ import { userGuideTopics } from '../data/userGuide';
9
+ import '../styles/UserGuide.css';
10
+
11
+ const UserGuide = () => {
12
+ const { config, advisors } = useAppConfig();
13
+ const [isOpen, setIsOpen] = useState(false);
14
+ const [activeId, setActiveId] = useState(userGuideTopics[0].id);
15
+ const [search, setSearch] = useState('');
16
+
17
+ useEffect(() => {
18
+ const open = () => setIsOpen(true);
19
+ window.addEventListener('open-user-guide', open);
20
+ return () => window.removeEventListener('open-user-guide', open);
21
+ }, []);
22
+
23
+ useEffect(() => {
24
+ if (!isOpen) return;
25
+ const onKey = (e) => e.key === 'Escape' && setIsOpen(false);
26
+ window.addEventListener('keydown', onKey);
27
+ return () => window.removeEventListener('keydown', onKey);
28
+ }, [isOpen]);
29
+
30
+ const appName = config?.app?.title || 'the app';
31
+ const advisorEntries = Object.values(advisors || {});
32
+ const advisorCount = advisorEntries.length;
33
+ const advisorList = advisorEntries
34
+ .map((a) => `- **${a.name}:** ${a.description || a.role || ''}`.trimEnd())
35
+ .join('\n');
36
+ const q = search.toLowerCase().trim();
37
+ const filteredTopics = q
38
+ ? userGuideTopics.filter(t =>
39
+ t.title.toLowerCase().includes(q) || t.content.toLowerCase().includes(q))
40
+ : userGuideTopics;
41
+ const activeTopic = userGuideTopics.find(t => t.id === activeId) || userGuideTopics[0];
42
+
43
+ if (!isOpen) return null;
44
+
45
+ return ReactDOM.createPortal(
46
+ <div className="ug-overlay" onClick={(e) => e.target === e.currentTarget && setIsOpen(false)}>
47
+ <div className="ug-modal" role="dialog" aria-label="User Guide">
48
+ {/* Header */}
49
+ <div className="ug-header">
50
+ <div className="ug-title">
51
+ <span className="ug-title-icon">
52
+ <BookOpen size={18} />
53
+ </span>
54
+ <span>User Guide</span>
55
+ </div>
56
+ <button className="ug-close" onClick={() => setIsOpen(false)} aria-label="Close">
57
+ <X size={20} />
58
+ </button>
59
+ </div>
60
+
61
+ <div className="ug-body">
62
+ {/* Sidebar / TOC */}
63
+ <aside className="ug-sidebar">
64
+ <div className="ug-search">
65
+ <Search size={14} />
66
+ <input
67
+ type="text"
68
+ placeholder="Search the guide…"
69
+ value={search}
70
+ onChange={(e) => setSearch(e.target.value)}
71
+ />
72
+ </div>
73
+ <nav className="ug-toc">
74
+ {filteredTopics.length === 0 && (
75
+ <div className="ug-empty">No matches</div>
76
+ )}
77
+ {filteredTopics.map((t) => {
78
+ const TopicIcon = LucideIcons[t.icon] || BookOpen;
79
+ return (
80
+ <button
81
+ key={t.id}
82
+ className={`ug-toc-item ${t.id === activeId ? 'active' : ''}`}
83
+ onClick={() => setActiveId(t.id)}
84
+ >
85
+ <TopicIcon size={16} />
86
+ <span>{t.title}</span>
87
+ <ChevronRight size={14} className="ug-toc-arrow" />
88
+ </button>
89
+ );
90
+ })}
91
+ </nav>
92
+ </aside>
93
+
94
+ {/* Content */}
95
+ <main className="ug-content" key={activeTopic.id}>
96
+ <ReactMarkdown remarkPlugins={[remarkGfm]}>
97
+ {activeTopic.content
98
+ .replace(/\{\{appName\}\}/g, appName)
99
+ .replace(/\{\{advisorCount\}\}/g, String(advisorCount))
100
+ .replace(/\{\{advisorList\}\}/g, advisorList)}
101
+ </ReactMarkdown>
102
+ </main>
103
+ </div>
104
+ </div>
105
+ </div>,
106
+ document.body
107
+ );
108
+ };
109
+
110
+ export default UserGuide;
phd-advisor-frontend/src/data/userGuide.js ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // User Guide content. Content can be overridden per-application by replacing
2
+ // these strings with values pulled from the backend config in the future.
3
+ // Use {{appName}} as a placeholder. It gets replaced at render time.
4
+
5
+ export const userGuideTopics = [
6
+ {
7
+ id: 'getting-started',
8
+ title: 'Getting Started',
9
+ icon: 'Sparkles',
10
+ content: `# Welcome to {{appName}}
11
+
12
+ {{appName}} is your AI-powered academic guidance system. A panel of specialized AI advisors gives you diverse perspectives on your research, writing, methodology, and more.
13
+
14
+ ## Your first steps
15
+ 1. **Start a new chat** using the pencil icon next to the search bar
16
+ 2. **Type a question.** Anything about your research, methodology, or PhD journey
17
+ 3. **Read multiple advisor responses.** Each persona brings a different lens
18
+ 4. **Reply to a specific advisor** to dig deeper into their perspective
19
+
20
+ ## Need help?
21
+ You can return to this guide anytime by clicking the **?** icon in the header.`,
22
+ },
23
+ {
24
+ id: 'advisors',
25
+ title: 'Your Advisors',
26
+ icon: 'GraduationCap',
27
+ content: `# Your Advisors
28
+
29
+ {{appName}} comes with {{advisorCount}} specialized advisor personas. Each one is tuned with a different perspective and area of expertise.
30
+
31
+ ## Available advisors
32
+ {{advisorList}}
33
+
34
+ ## Seeing who's available
35
+ Click the **"X Advisors"** dropdown in the top right of the chat to see all of your advisors and their current status.`,
36
+ },
37
+ {
38
+ id: 'conversations',
39
+ title: 'Conversations & Replies',
40
+ icon: 'MessageCircle',
41
+ content: `# Conversations & Replies
42
+
43
+ ## Asking a question
44
+ Type into the chat box at the bottom. All advisors will respond with their unique perspective.
45
+
46
+ ## Replying to a specific advisor
47
+ Click on any advisor's response to **reply directly to them**. This continues the conversation with just that persona, letting you go deeper on their specific angle.
48
+
49
+ ## Expanding a response
50
+ Some responses include an **"Expand"** action to ask the advisor to elaborate further with more detail.
51
+
52
+ ## Tips
53
+ - Be specific. The more context, the better the advice
54
+ - Ask follow-up questions to refine the response
55
+ - Different advisors will sometimes disagree, and that's a feature, not a bug`,
56
+ },
57
+ {
58
+ id: 'documents',
59
+ title: 'Uploading Documents',
60
+ icon: 'Paperclip',
61
+ content: `# Uploading Documents
62
+
63
+ You can attach **PDFs, Word documents, and text files** to give your advisors context.
64
+
65
+ ## How it works
66
+ 1. Click the paperclip icon in the chat input
67
+ 2. Select your file
68
+ 3. Wait for it to process
69
+ 4. Ask a question, and your advisors will reference the document
70
+
71
+ ## What can it handle?
72
+ - Research papers (PDF)
73
+ - Drafts and chapters (DOCX, TXT)
74
+ - Notes and outlines
75
+
76
+ ## Behind the scenes
77
+ Documents are processed using **RAG (retrieval-augmented generation)**. The system finds the most relevant chunks of your document for each question, so even long documents work well.`,
78
+ },
79
+ {
80
+ id: 'sessions',
81
+ title: 'Sessions & History',
82
+ icon: 'MessagesSquare',
83
+ content: `# Sessions & History
84
+
85
+ Every conversation is automatically saved as a session.
86
+
87
+ ## Finding past chats
88
+ Use the **search bar** in the sidebar to filter your past sessions by title.
89
+
90
+ ## Switching between sessions
91
+ Click any session in the sidebar to return to it. Your full context is preserved.
92
+
93
+ ## Starting a new chat
94
+ Click the pencil/edit icon next to the search bar to start a fresh conversation.
95
+
96
+ ## Renaming or deleting
97
+ Hover any session to reveal the **menu**. From there you can rename or delete.`,
98
+ },
99
+ {
100
+ id: 'canvas',
101
+ title: 'Progress Canvas',
102
+ icon: 'BarChart3',
103
+ content: `# {{appName}} Canvas
104
+
105
+ The Canvas is a **structured dashboard view** of your PhD journey. It pulls insights from your conversations and organizes them into 10 sections:
106
+
107
+ - Research Progress
108
+ - Methodology
109
+ - Theoretical Framework
110
+ - Challenges & Obstacles
111
+ - Next Steps
112
+ - Writing & Communication
113
+ - Career Development
114
+ - Literature Review
115
+ - Data Analysis
116
+ - Motivation & Mindset
117
+
118
+ ## Accessing the Canvas
119
+ Click the **{{appName}} Canvas** button in the sidebar.
120
+
121
+ ## Exporting
122
+ You can print or download the Canvas as a snapshot of your progress.`,
123
+ },
124
+ {
125
+ id: 'tips',
126
+ title: 'Tips & Shortcuts',
127
+ icon: 'Sparkles',
128
+ content: `# Tips & Shortcuts
129
+
130
+ ## Get better answers
131
+ - **Provide context.** Mention your field, your stage, your specific concern.
132
+ - **Quote your work.** Paste a paragraph from your draft for targeted feedback.
133
+ - **Use multiple advisors.** Ask one for theory, another for practical next steps.
134
+
135
+ ## Useful workflows
136
+ - **Stuck on methodology?** Ask the Methodologist + Theorist together.
137
+ - **Feeling burnt out?** The Motivational Coach + Empathetic Listener help reframe.
138
+ - **Need to be challenged?** Talk to the Constructive Critic and Socratic Mentor.
139
+
140
+ ## Theme
141
+ Switch between light and dark mode using the toggle in the top right.`,
142
+ },
143
+ ];
phd-advisor-frontend/src/pages/ChatPage.js CHANGED
@@ -1,5 +1,7 @@
1
  import React, { useState, useEffect, useRef, useMemo } from 'react';
2
- import { Home, MessageCircle, Reply, X, Sparkles, Users, Settings2, FileText, Menu } from 'lucide-react';
 
 
3
  import EnhancedChatInput from '../components/EnhancedChatInput';
4
  import MessageBubble from '../components/MessageBubble';
5
  import ThinkingIndicator from '../components/ThinkingIndicator';
@@ -824,6 +826,15 @@ const handleNewChat = async (sessionId = null) => {
824
 
825
  {/* Theme Toggle */}
826
  <ThemeToggle />
 
 
 
 
 
 
 
 
 
827
  </div>
828
  </div>
829
  </div>
 
1
  import React, { useState, useEffect, useRef, useMemo } from 'react';
2
+
3
+ import { Home, MessageCircle, Reply, X, Sparkles, Users, Settings2, FileText, Menu, HelpCircle } from 'lucide-react';
4
+
5
  import EnhancedChatInput from '../components/EnhancedChatInput';
6
  import MessageBubble from '../components/MessageBubble';
7
  import ThinkingIndicator from '../components/ThinkingIndicator';
 
826
 
827
  {/* Theme Toggle */}
828
  <ThemeToggle />
829
+
830
+ {/* Help / User Guide */}
831
+ <button
832
+ className="header-help-btn"
833
+ onClick={() => window.dispatchEvent(new CustomEvent('open-user-guide'))}
834
+ title="Open user guide"
835
+ >
836
+ <HelpCircle />
837
+ </button>
838
  </div>
839
  </div>
840
  </div>
phd-advisor-frontend/src/styles/ChatPage.css CHANGED
@@ -730,6 +730,32 @@
730
  background: var(--bg-secondary-dark, #374151);
731
  }
732
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
733
  /* Loading session indicator */
734
  .loading-session {
735
  display: flex;
 
730
  background: var(--bg-secondary-dark, #374151);
731
  }
732
 
733
+ .header-help-btn {
734
+ display: flex;
735
+ align-items: center;
736
+ justify-content: center;
737
+ padding: 10px;
738
+ background: var(--bg-primary);
739
+ border: 1px solid var(--border-primary);
740
+ border-radius: 12px;
741
+ cursor: pointer;
742
+ color: var(--text-secondary);
743
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
744
+ transition: all 0.2s ease;
745
+ }
746
+
747
+ .header-help-btn svg {
748
+ width: 20px;
749
+ height: 20px;
750
+ display: block;
751
+ }
752
+
753
+ .header-help-btn:hover {
754
+ background: var(--bg-secondary);
755
+ border-color: #2663EB;
756
+ color: #2663EB;
757
+ }
758
+
759
  /* Loading session indicator */
760
  .loading-session {
761
  display: flex;
phd-advisor-frontend/src/styles/UserGuide.css ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* === User Guide modal ============================================== */
2
+ .ug-overlay {
3
+ position: fixed;
4
+ inset: 0;
5
+ background: rgba(0, 0, 0, 0.6);
6
+ backdrop-filter: blur(4px);
7
+ display: flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ z-index: 1000;
11
+ animation: ug-fade 0.18s ease;
12
+ }
13
+
14
+ @keyframes ug-fade {
15
+ from { opacity: 0; }
16
+ to { opacity: 1; }
17
+ }
18
+
19
+ .ug-modal {
20
+ width: 92vw;
21
+ max-width: 1000px;
22
+ height: 80vh;
23
+ max-height: 720px;
24
+ background: var(--bg-primary);
25
+ color: var(--text-primary);
26
+ border: 1px solid var(--border-primary);
27
+ border-radius: 18px;
28
+ box-shadow: 0 30px 80px -10px rgba(0, 0, 0, 0.5);
29
+ display: flex;
30
+ flex-direction: column;
31
+ overflow: hidden;
32
+ animation: ug-pop 0.22s cubic-bezier(0.4, 0, 0.2, 1);
33
+ }
34
+
35
+ @keyframes ug-pop {
36
+ from { opacity: 0; transform: scale(0.96); }
37
+ to { opacity: 1; transform: scale(1); }
38
+ }
39
+
40
+ /* Header bar */
41
+ .ug-header {
42
+ display: flex;
43
+ align-items: center;
44
+ justify-content: space-between;
45
+ padding: 18px 22px;
46
+ border-bottom: 1px solid var(--border-primary);
47
+ }
48
+
49
+ .ug-title {
50
+ display: flex;
51
+ align-items: center;
52
+ gap: 10px;
53
+ font-size: 16px;
54
+ font-weight: 700;
55
+ letter-spacing: -0.01em;
56
+ }
57
+
58
+ .ug-title-icon {
59
+ display: flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ width: 32px;
63
+ height: 32px;
64
+ border-radius: 8px;
65
+ background: #2663EB;
66
+ color: #fff;
67
+ flex-shrink: 0;
68
+ }
69
+
70
+ .ug-close {
71
+ display: flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ width: 32px;
75
+ height: 32px;
76
+ border: none;
77
+ background: transparent;
78
+ border-radius: 8px;
79
+ cursor: pointer;
80
+ color: var(--text-secondary);
81
+ transition: background 0.15s ease, color 0.15s ease;
82
+ }
83
+
84
+ .ug-close:hover {
85
+ background: var(--bg-secondary);
86
+ color: var(--text-primary);
87
+ }
88
+
89
+ /* Body layout: sidebar + content */
90
+ .ug-body {
91
+ flex: 1;
92
+ display: grid;
93
+ grid-template-columns: 240px 1fr;
94
+ min-height: 0;
95
+ }
96
+
97
+ /* Sidebar */
98
+ .ug-sidebar {
99
+ display: flex;
100
+ flex-direction: column;
101
+ border-right: 1px solid var(--border-primary);
102
+ background: var(--bg-secondary);
103
+ min-height: 0;
104
+ }
105
+
106
+ .ug-search {
107
+ display: flex;
108
+ align-items: center;
109
+ gap: 8px;
110
+ margin: 14px;
111
+ padding: 8px 12px;
112
+ background: var(--bg-primary);
113
+ border: 1px solid var(--border-primary);
114
+ border-radius: 10px;
115
+ color: var(--text-secondary);
116
+ }
117
+
118
+ .ug-search input {
119
+ flex: 1;
120
+ border: none;
121
+ outline: none;
122
+ background: transparent;
123
+ color: var(--text-primary);
124
+ font-size: 13.5px;
125
+ }
126
+
127
+ .ug-search input::placeholder {
128
+ color: var(--text-tertiary);
129
+ }
130
+
131
+ .ug-toc {
132
+ flex: 1;
133
+ overflow-y: auto;
134
+ padding: 4px 10px 14px;
135
+ display: flex;
136
+ flex-direction: column;
137
+ gap: 2px;
138
+ }
139
+
140
+ .ug-toc-item {
141
+ display: flex;
142
+ align-items: center;
143
+ gap: 10px;
144
+ padding: 10px 12px;
145
+ border: none;
146
+ background: transparent;
147
+ border-radius: 8px;
148
+ cursor: pointer;
149
+ color: var(--text-secondary);
150
+ font-size: 13.5px;
151
+ font-weight: 500;
152
+ text-align: left;
153
+ transition: background 0.15s ease, color 0.15s ease;
154
+ }
155
+
156
+ .ug-toc-item span {
157
+ flex: 1;
158
+ }
159
+
160
+ .ug-toc-arrow {
161
+ opacity: 0;
162
+ transition: opacity 0.15s ease, transform 0.15s ease;
163
+ }
164
+
165
+ .ug-toc-item:hover {
166
+ background: var(--bg-primary);
167
+ color: var(--text-primary);
168
+ }
169
+
170
+ .ug-toc-item:hover .ug-toc-arrow {
171
+ opacity: 0.6;
172
+ }
173
+
174
+ .ug-toc-item.active {
175
+ background: rgba(38, 99, 235, 0.1);
176
+ color: #2663EB;
177
+ }
178
+
179
+ .ug-toc-item.active .ug-toc-arrow {
180
+ opacity: 1;
181
+ transform: translateX(2px);
182
+ }
183
+
184
+ .ug-empty {
185
+ padding: 14px;
186
+ font-size: 13px;
187
+ color: var(--text-tertiary);
188
+ text-align: center;
189
+ }
190
+
191
+ /* Content area */
192
+ .ug-content {
193
+ overflow-y: auto;
194
+ padding: 28px 36px 40px;
195
+ font-size: 15px;
196
+ line-height: 1.65;
197
+ color: var(--text-primary);
198
+ animation: ug-slide 0.2s cubic-bezier(0.4, 0, 0.2, 1);
199
+ }
200
+
201
+ @keyframes ug-slide {
202
+ from { opacity: 0; transform: translateY(6px); }
203
+ to { opacity: 1; transform: translateY(0); }
204
+ }
205
+
206
+ .ug-content h1 {
207
+ margin: 0 0 16px;
208
+ font-size: 26px;
209
+ font-weight: 800;
210
+ letter-spacing: -0.02em;
211
+ color: var(--text-primary);
212
+ }
213
+
214
+ .ug-content h2 {
215
+ margin: 28px 0 10px;
216
+ font-size: 18px;
217
+ font-weight: 700;
218
+ color: var(--text-primary);
219
+ letter-spacing: -0.01em;
220
+ }
221
+
222
+ .ug-content h3 {
223
+ margin: 22px 0 6px;
224
+ font-size: 15px;
225
+ font-weight: 700;
226
+ color: var(--text-primary);
227
+ }
228
+
229
+ .ug-content p {
230
+ margin: 0 0 14px;
231
+ color: var(--text-secondary);
232
+ }
233
+
234
+ .ug-content ul, .ug-content ol {
235
+ margin: 0 0 16px;
236
+ padding-left: 22px;
237
+ color: var(--text-secondary);
238
+ }
239
+
240
+ .ug-content li {
241
+ margin-bottom: 6px;
242
+ }
243
+
244
+ .ug-content strong {
245
+ color: var(--text-primary);
246
+ font-weight: 600;
247
+ }
248
+
249
+ .ug-content code {
250
+ padding: 1px 6px;
251
+ border-radius: 4px;
252
+ background: var(--bg-secondary);
253
+ font-size: 0.9em;
254
+ color: #2663EB;
255
+ font-family: 'SF Mono', ui-monospace, monospace;
256
+ }
257
+
258
+ .ug-content a {
259
+ color: #2663EB;
260
+ text-decoration: none;
261
+ }
262
+
263
+ .ug-content a:hover {
264
+ text-decoration: underline;
265
+ }
266
+
267
+ /* Mobile */
268
+ @media (max-width: 720px) {
269
+ .ug-body {
270
+ grid-template-columns: 1fr;
271
+ grid-template-rows: auto 1fr;
272
+ }
273
+ .ug-sidebar {
274
+ border-right: none;
275
+ border-bottom: 1px solid var(--border-primary);
276
+ max-height: 200px;
277
+ }
278
+ .ug-content {
279
+ padding: 22px 22px 36px;
280
+ }
281
+ }