2b362eb
commit 2b362eb
3 files changed
+3683 -0
Showing 3 changed files+3683-0
βΌdocs-site/index.html
+1769-0
| @@ -0,0 +1,1769 @@ | ||
1 | +<!DOCTYPE html> | |
2 | +<html lang="en"> | |
3 | +<head> | |
4 | + <meta charset="UTF-8"> | |
5 | + <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
6 | + <title>OpenGrammar Documentation</title> | |
7 | + <meta name="description" content="Complete documentation for OpenGrammar - Your privacy-first, open-source writing assistant"> | |
8 | + <link rel="preconnect" href="https://fonts.googleapis.com"> | |
9 | + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> | |
10 | + <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"> | |
11 | + <link rel="stylesheet" href="styles.css"> | |
12 | +</head> | |
13 | +<body> | |
14 | + <div class="paper-texture"></div> | |
15 | + | |
16 | + <!-- Sidebar Navigation --> | |
17 | + <aside class="sidebar"> | |
18 | + <div class="sidebar-header"> | |
19 | + <div class="logo"> | |
20 | + <svg class="logo-icon" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"> | |
21 | + <rect width="40" height="40" rx="8" fill="url(#logo-gradient)"/> | |
22 | + <path d="M12 20L18 26L28 14" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/> | |
23 | + <defs> | |
24 | + <linearGradient id="logo-gradient" x1="0" y1="0" x2="40" y2="40" gradientUnits="userSpaceOnUse"> | |
25 | + <stop stop-color="#3B82F6"/> | |
26 | + <stop offset="1" stop-color="#8B5CF6"/> | |
27 | + </linearGradient> | |
28 | + </defs> | |
29 | + </svg> | |
30 | + <span class="logo-text">OpenGrammar</span> | |
31 | + </div> | |
32 | + <span class="version-badge">v2.1.0</span> | |
33 | + </div> | |
34 | + | |
35 | + <nav class="sidebar-nav"> | |
36 | + <div class="nav-section"> | |
37 | + <div class="nav-section-title">Getting Started</div> | |
38 | + <a href="#quick-start" class="nav-link active" data-page="quick-start"> | |
39 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
40 | + <path d="M10.894 2.553a1 1 0 00-1.788 0l-7 14a1 1 0 001.169 1.409l5-1.429A1 1 0 009 15.571V11a1 1 0 112 0v4.571a1 1 0 00.725.962l5 1.428a1 1 0 001.17-1.408l-7-14z"/> | |
41 | + </svg> | |
42 | + Quick Start | |
43 | + </a> | |
44 | + <a href="#what-is-opengrammar" class="nav-link" data-page="what-is-opengrammar"> | |
45 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
46 | + <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"/> | |
47 | + </svg> | |
48 | + What is OpenGrammar? | |
49 | + </a> | |
50 | + </div> | |
51 | + | |
52 | + <div class="nav-section"> | |
53 | + <div class="nav-section-title">Installation</div> | |
54 | + <a href="#browser-setup" class="nav-link" data-page="browser-setup"> | |
55 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
56 | + <path fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h6a1 1 0 110 2H4a1 1 0 01-1-1z" clip-rule="evenodd"/> | |
57 | + </svg> | |
58 | + Browser Extension | |
59 | + </a> | |
60 | + <a href="#backend-deployment" class="nav-link" data-page="backend-deployment"> | |
61 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
62 | + <path fill-rule="evenodd" d="M2 5a2 2 0 012-2h12a2 2 0 012 2v10a2 2 0 01-2 2H4a2 2 0 01-2-2V5zm3.293 1.293a1 1 0 011.414 0l3 3a1 1 0 010 1.414l-3 3a1 1 0 01-1.414-1.414L7.586 10 5.293 7.707a1 1 0 010-1.414z" clip-rule="evenodd"/> | |
63 | + </svg> | |
64 | + Backend Deployment | |
65 | + </a> | |
66 | + <a href="#docker-self-hosting" class="nav-link" data-page="docker-self-hosting"> | |
67 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
68 | + <path d="M5 4a2 2 0 012-2h6a2 2 0 012 2v14l-5-2.5L5 18V4z"/> | |
69 | + </svg> | |
70 | + Docker Self-Hosting | |
71 | + </a> | |
72 | + </div> | |
73 | + | |
74 | + <div class="nav-section"> | |
75 | + <div class="nav-section-title">Configuration</div> | |
76 | + <a href="#ai-providers" class="nav-link" data-page="ai-providers"> | |
77 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
78 | + <path d="M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3zM6 8a2 2 0 11-4 0 2 2 0 014 0zM16 18v-3a5.972 5.972 0 00-.75-2.906A3.005 3.005 0 0119 15v3h-3zM4.75 12.094A5.973 5.973 0 004 15v3H1v-3a3 3 0 013.75-2.906z"/> | |
79 | + </svg> | |
80 | + AI Providers | |
81 | + </a> | |
82 | + <a href="#extension-settings" class="nav-link" data-page="extension-settings"> | |
83 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
84 | + <path fill-rule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clip-rule="evenodd"/> | |
85 | + </svg> | |
86 | + Extension Settings | |
87 | + </a> | |
88 | + </div> | |
89 | + | |
90 | + <div class="nav-section"> | |
91 | + <div class="nav-section-title">User Guide</div> | |
92 | + <a href="#using-opengrammar" class="nav-link" data-page="using-opengrammar"> | |
93 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
94 | + <path d="M9 4.804A7.968 7.968 0 005.5 4c-1.255 0-2.443.29-3.5.804v10A7.969 7.969 0 015.5 14c1.669 0 3.218.51 4.5 1.385A7.962 7.962 0 0114.5 14c1.255 0 2.443.29 3.5.804v-10A7.968 7.968 0 0014.5 4c-1.255 0-2.443.29-3.5.804V12a1 1 0 11-2 0V4.804z"/> | |
95 | + </svg> | |
96 | + Using OpenGrammar | |
97 | + </a> | |
98 | + <a href="#tone-rewriting" class="nav-link" data-page="tone-rewriting"> | |
99 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
100 | + <path fill-rule="evenodd" d="M4 2a2 2 0 00-2 2v11a3 3 0 106 0V4a2 2 0 00-2-2H4zm1 14a1 1 0 100-2 1 1 0 000 2zm5-1.757l4.9-4.9a2 2 0 000-2.828L13.485 5.1a2 2 0 00-2.828 0L10 5.757v8.486zM16 18H9.071l6-6H16a2 2 0 012 2v2a2 2 0 01-2 2z" clip-rule="evenodd"/> | |
101 | + </svg> | |
102 | + Tone Rewriting | |
103 | + </a> | |
104 | + <a href="#writing-statistics" class="nav-link" data-page="writing-statistics"> | |
105 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
106 | + <path d="M2 11a1 1 0 011-1h2a1 1 0 011 1v5a1 1 0 01-1 1H3a1 1 0 01-1-1v-5zM8 7a1 1 0 011-1h2a1 1 0 011 1v9a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM14 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1h-2a1 1 0 01-1-1V4z"/> | |
107 | + </svg> | |
108 | + Writing Statistics | |
109 | + </a> | |
110 | + <a href="#keyboard-shortcuts" class="nav-link" data-page="keyboard-shortcuts"> | |
111 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
112 | + <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clip-rule="evenodd"/> | |
113 | + </svg> | |
114 | + Keyboard Shortcuts | |
115 | + </a> | |
116 | + </div> | |
117 | + | |
118 | + <div class="nav-section"> | |
119 | + <div class="nav-section-title">Support</div> | |
120 | + <a href="#troubleshooting" class="nav-link" data-page="troubleshooting"> | |
121 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
122 | + <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-3a1 1 0 00-.867.5 1 1 0 11-1.731-1A3 3 0 0113 8a3.001 3.001 0 01-2 2.83V11a1 1 0 11-2 0v-1a1 1 0 011-1 1 1 0 100-2zm0 8a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/> | |
123 | + </svg> | |
124 | + Troubleshooting | |
125 | + </a> | |
126 | + <a href="#faq" class="nav-link" data-page="faq"> | |
127 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
128 | + <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-3a1 1 0 00-.867.5 1 1 0 11-1.731-1A3 3 0 0113 8a3.001 3.001 0 01-2 2.83V11a1 1 0 11-2 0v-1a1 1 0 011-1 1 1 0 100-2zm0 8a1 1 0 100-2 1 1 0 000 2z" clip-rule="evenodd"/> | |
129 | + </svg> | |
130 | + FAQ | |
131 | + </a> | |
132 | + <a href="#api-reference" class="nav-link" data-page="api-reference"> | |
133 | + <svg class="nav-icon" viewBox="0 0 20 20" fill="currentColor"> | |
134 | + <path fill-rule="evenodd" d="M12.316 3.051a1 1 0 01.633 1.265l-4 12a1 1 0 11-1.898-.632l4-12a1 1 0 011.265-.633zM5.707 6.293a1 1 0 010 1.414L3.414 10l2.293 2.293a1 1 0 11-1.414 1.414l-3-3a1 1 0 010-1.414l3-3a1 1 0 011.414 0zm8.586 0a1 1 0 011.414 0l3 3a1 1 0 010 1.414l-3 3a1 1 0 11-1.414-1.414L16.586 10l-2.293-2.293a1 1 0 010-1.414z" clip-rule="evenodd"/> | |
135 | + </svg> | |
136 | + API Reference | |
137 | + </a> | |
138 | + </div> | |
139 | + </nav> | |
140 | + | |
141 | + <div class="sidebar-footer"> | |
142 | + <a href="https://github.com/swadhinbiswas/opengrammar" target="_blank" class="github-link"> | |
143 | + <svg class="github-icon" viewBox="0 0 24 24" fill="currentColor"> | |
144 | + <path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clip-rule="evenodd"/> | |
145 | + </svg> | |
146 | + GitHub | |
147 | + </a> | |
148 | + </div> | |
149 | + </aside> | |
150 | + | |
151 | + <!-- Main Content --> | |
152 | + <main class="main-content"> | |
153 | + <header class="content-header"> | |
154 | + <button class="menu-toggle" id="menuToggle"> | |
155 | + <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> | |
156 | + <path d="M3 12h18M3 6h18M3 18h18"/> | |
157 | + </svg> | |
158 | + </button> | |
159 | + <div class="search-box"> | |
160 | + <svg class="search-icon" viewBox="0 0 20 20" fill="currentColor"> | |
161 | + <path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"/> | |
162 | + </svg> | |
163 | + <input type="text" placeholder="Search documentation..." id="searchInput"> | |
164 | + <kbd>βK</kbd> | |
165 | + </div> | |
166 | + <div class="header-actions"> | |
167 | + <button class="theme-toggle" id="themeToggle" title="Toggle theme"> | |
168 | + <svg class="sun-icon" viewBox="0 0 20 20" fill="currentColor"> | |
169 | + <path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clip-rule="evenodd"/> | |
170 | + </svg> | |
171 | + <svg class="moon-icon" viewBox="0 0 20 20" fill="currentColor"> | |
172 | + <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"/> | |
173 | + </svg> | |
174 | + </button> | |
175 | + <a href="https://github.com/swadhinbiswas/opengrammar" target="_blank" class="github-btn"> | |
176 | + <svg viewBox="0 0 24 24" fill="currentColor"> | |
177 | + <path fill-rule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"/> | |
178 | + </svg> | |
179 | + Star on GitHub | |
180 | + </a> | |
181 | + </div> | |
182 | + </header> | |
183 | + | |
184 | + <div class="content-wrapper"> | |
185 | + <!-- Quick Start Section --> | |
186 | + <article id="quick-start" class="content-section active"> | |
187 | + <div class="section-header"> | |
188 | + <nav class="breadcrumb"> | |
189 | + <a href="#">Docs</a> | |
190 | + <span class="breadcrumb-sep">/</span> | |
191 | + <span>Getting Started</span> | |
192 | + <span class="breadcrumb-sep">/</span> | |
193 | + <span class="current">Quick Start</span> | |
194 | + </nav> | |
195 | + <h1>π Quick Start</h1> | |
196 | + <p class="section-description">Get OpenGrammar up and running in 5 minutes!</p> | |
197 | + </div> | |
198 | + | |
199 | + <div class="content-body"> | |
200 | + <div class="callout callout-primary"> | |
201 | + <div class="callout-icon">β‘</div> | |
202 | + <div class="callout-content"> | |
203 | + <strong>5-Minute Setup</strong> | |
204 | + <p>Follow these steps to get OpenGrammar running quickly. You'll need an API key for the best experience.</p> | |
205 | + </div> | |
206 | + </div> | |
207 | + | |
208 | + <h2 id="step-1-get-api-key">Step 1: Get Your API Key (Optional but Recommended)</h2> | |
209 | + <p>For the best grammar checking experience, you'll need an API key. We recommend <strong>Groq</strong> for its free tier:</p> | |
210 | + | |
211 | + <ol class="step-list"> | |
212 | + <li>Visit <a href="https://console.groq.com" target="_blank">Groq Console</a></li> | |
213 | + <li>Sign up / Log in</li> | |
214 | + <li>Go to <strong>API Keys</strong> β <strong>Create API Key</strong></li> | |
215 | + <li>Copy your key (starts with <code>gsk_</code>)</li> | |
216 | + </ol> | |
217 | + | |
218 | + <div class="callout callout-success"> | |
219 | + <div class="callout-icon">β
</div> | |
220 | + <div class="callout-content"> | |
221 | + <strong>Free Tier:</strong> 100 requests/day - enough for most users! | |
222 | + </div> | |
223 | + </div> | |
224 | + | |
225 | + <h2 id="step-2-build-extension">Step 2: Build the Extension</h2> | |
226 | + | |
227 | + <div class="code-block"> | |
228 | + <div class="code-header"> | |
229 | + <span class="code-lang">bash</span> | |
230 | + <button class="copy-btn" onclick="copyCode(this)"> | |
231 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
232 | + <path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z"/> | |
233 | + <path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z"/> | |
234 | + </svg> | |
235 | + Copy | |
236 | + </button> | |
237 | + </div> | |
238 | + <pre><code class="language-bash"># Clone the repository | |
239 | +git clone https://github.com/swadhinbiswas/opengrammar.git | |
240 | +cd opengrammar/opengrammar/extension | |
241 | + | |
242 | +# Install dependencies | |
243 | +bun install | |
244 | + | |
245 | +# Build the extension | |
246 | +bun run build</code></pre> | |
247 | + </div> | |
248 | + | |
249 | + <p>This creates a <code>dist/</code> folder with the built extension.</p> | |
250 | + | |
251 | + <h2 id="step-3-load-browser">Step 3: Load in Your Browser</h2> | |
252 | + | |
253 | + <div class="tabs"> | |
254 | + <div class="tab-buttons"> | |
255 | + <button class="tab-btn active" data-tab="chrome">Chrome</button> | |
256 | + <button class="tab-btn" data-tab="brave">Brave</button> | |
257 | + <button class="tab-btn" data-tab="edge">Edge</button> | |
258 | + <button class="tab-btn" data-tab="firefox">Firefox</button> | |
259 | + </div> | |
260 | + <div class="tab-content"> | |
261 | + <div class="tab-pane active" id="chrome"> | |
262 | + <h4>Chrome / Brave / Edge</h4> | |
263 | + <ol> | |
264 | + <li>Open <code>chrome://extensions/</code> (or <code>brave://extensions/</code> / <code>edge://extensions/</code>)</li> | |
265 | + <li>Enable <strong>Developer mode</strong> (toggle in top-right)</li> | |
266 | + <li>Click <strong>Load unpacked</strong></li> | |
267 | + <li>Select the <code>opengrammar/extension/dist</code> folder</li> | |
268 | + <li>β
Extension loaded! You'll see the OpenGrammar icon</li> | |
269 | + </ol> | |
270 | + </div> | |
271 | + <div class="tab-pane" id="brave"> | |
272 | + <h4>Brave Browser</h4> | |
273 | + <ol> | |
274 | + <li>Open <code>brave://extensions/</code></li> | |
275 | + <li>Enable <strong>Developer mode</strong> (top-right)</li> | |
276 | + <li>Click <strong>Load unpacked</strong></li> | |
277 | + <li>Select <code>opengrammar/extension/dist</code> folder</li> | |
278 | + <li>β
Extension loaded!</li> | |
279 | + </ol> | |
280 | + </div> | |
281 | + <div class="tab-pane" id="edge"> | |
282 | + <h4>Microsoft Edge</h4> | |
283 | + <ol> | |
284 | + <li>Open <code>edge://extensions/</code></li> | |
285 | + <li>Enable <strong>Developer mode</strong> (left sidebar)</li> | |
286 | + <li>Click <strong>Load unpacked</strong></li> | |
287 | + <li>Select <code>opengrammar/extension/dist</code> folder</li> | |
288 | + <li>β
Extension loaded!</li> | |
289 | + </ol> | |
290 | + </div> | |
291 | + <div class="tab-pane" id="firefox"> | |
292 | + <h4>Mozilla Firefox</h4> | |
293 | + <div class="callout callout-warning"> | |
294 | + <div class="callout-icon">β οΈ</div> | |
295 | + <div class="callout-content"> | |
296 | + <strong>Note:</strong> Firefox support is temporary. The extension must be reloaded each time you restart Firefox. | |
297 | + </div> | |
298 | + </div> | |
299 | + <ol> | |
300 | + <li>Open <code>about:debugging#/runtime/this-firefox</code></li> | |
301 | + <li>Click <strong>Load Temporary Add-on</strong></li> | |
302 | + <li>Navigate to <code>opengrammar/extension/dist</code></li> | |
303 | + <li>Select <code>manifest.json</code></li> | |
304 | + <li>β
Extension loaded!</li> | |
305 | + </ol> | |
306 | + </div> | |
307 | + </div> | |
308 | + </div> | |
309 | + | |
310 | + <h2 id="step-4-configure">Step 4: Configure</h2> | |
311 | + <ol class="step-list"> | |
312 | + <li>Click the OpenGrammar icon in your toolbar</li> | |
313 | + <li>Click <strong>Settings</strong> (gear icon)</li> | |
314 | + <li>Enter your API key (from Step 1)</li> | |
315 | + <li>Select Provider: <strong>Groq</strong></li> | |
316 | + <li>Select Model: <strong>llama-3.1-70b-versatile</strong></li> | |
317 | + <li>Backend URL: <code>http://localhost:8787</code> (for local testing)</li> | |
318 | + </ol> | |
319 | + | |
320 | + <h2 id="step-5-start-writing">Step 5: Start Writing!</h2> | |
321 | + <ol class="step-list"> | |
322 | + <li>Open any text box (Gmail, Google Docs, Notion, etc.)</li> | |
323 | + <li>Type something with a grammar error: <code>me and him went to store</code></li> | |
324 | + <li>You'll see a <span class="highlight-red">red underline</span> under the error</li> | |
325 | + <li>Click it to see the suggestion: <code>he and I went to store</code></li> | |
326 | + <li>Click <strong>Apply</strong> to fix it!</li> | |
327 | + </ol> | |
328 | + | |
329 | + <div class="feature-grid"> | |
330 | + <div class="feature-card"> | |
331 | + <div class="feature-icon">π</div> | |
332 | + <h4>Read Next</h4> | |
333 | + <ul class="link-list"> | |
334 | + <li><a href="#backend-deployment">Backend Deployment</a></li> | |
335 | + <li><a href="#ai-providers">AI Provider Setup</a></li> | |
336 | + <li><a href="#using-opengrammar">Using OpenGrammar</a></li> | |
337 | + </ul> | |
338 | + </div> | |
339 | + <div class="feature-card"> | |
340 | + <div class="feature-icon">β¨οΈ</div> | |
341 | + <h4>Quick Commands</h4> | |
342 | + <div class="code-block small"> | |
343 | + <pre><code># Start local backend | |
344 | +cd opengrammar/opengrammar/backend | |
345 | +bun run dev | |
346 | + | |
347 | +# Test backend | |
348 | +curl http://localhost:8787/health</code></pre> | |
349 | + </div> | |
350 | + </div> | |
351 | + </div> | |
352 | + | |
353 | + <div class="section-nav"> | |
354 | + <a href="#" class="prev-link"> | |
355 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
356 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
357 | + </svg> | |
358 | + <span>Previous</span> | |
359 | + </a> | |
360 | + <a href="#browser-setup" class="next-link"> | |
361 | + <span>Next</span> | |
362 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
363 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
364 | + </svg> | |
365 | + </a> | |
366 | + </div> | |
367 | + </div> | |
368 | + </article> | |
369 | + | |
370 | + <!-- Browser Extension Setup --> | |
371 | + <article id="browser-setup" class="content-section"> | |
372 | + <div class="section-header"> | |
373 | + <nav class="breadcrumb"> | |
374 | + <a href="#">Docs</a> | |
375 | + <span class="breadcrumb-sep">/</span> | |
376 | + <span>Installation</span> | |
377 | + <span class="breadcrumb-sep">/</span> | |
378 | + <span class="current">Browser Extension</span> | |
379 | + </nav> | |
380 | + <h1>π Browser Extension Setup</h1> | |
381 | + <p class="section-description">Install and configure OpenGrammar on Chrome, Brave, Edge, and Firefox.</p> | |
382 | + </div> | |
383 | + | |
384 | + <div class="content-body"> | |
385 | + <h2>π Supported Browsers</h2> | |
386 | + | |
387 | + <div class="table-wrapper"> | |
388 | + <table class="data-table"> | |
389 | + <thead> | |
390 | + <tr> | |
391 | + <th>Browser</th> | |
392 | + <th>Version</th> | |
393 | + <th>Status</th> | |
394 | + </tr> | |
395 | + </thead> | |
396 | + <tbody> | |
397 | + <tr> | |
398 | + <td><strong>Google Chrome</strong></td> | |
399 | + <td>88+</td> | |
400 | + <td><span class="status-badge success">β
Fully Supported</span></td> | |
401 | + </tr> | |
402 | + <tr> | |
403 | + <td><strong>Brave</strong></td> | |
404 | + <td>1.20+</td> | |
405 | + <td><span class="status-badge success">β
Fully Supported</span></td> | |
406 | + </tr> | |
407 | + <tr> | |
408 | + <td><strong>Microsoft Edge</strong></td> | |
409 | + <td>88+</td> | |
410 | + <td><span class="status-badge success">β
Fully Supported</span></td> | |
411 | + </tr> | |
412 | + <tr> | |
413 | + <td><strong>Mozilla Firefox</strong></td> | |
414 | + <td>90+</td> | |
415 | + <td><span class="status-badge warning">β
Supported (Temporary)</span></td> | |
416 | + </tr> | |
417 | + <tr> | |
418 | + <td><strong>Opera</strong></td> | |
419 | + <td>74+</td> | |
420 | + <td><span class="status-badge success">β
Supported</span></td> | |
421 | + </tr> | |
422 | + <tr> | |
423 | + <td><strong>Vivaldi</strong></td> | |
424 | + <td>3.6+</td> | |
425 | + <td><span class="status-badge success">β
Supported</span></td> | |
426 | + </tr> | |
427 | + </tbody> | |
428 | + </table> | |
429 | + </div> | |
430 | + | |
431 | + <h2>π§ Installation - Chrome</h2> | |
432 | + | |
433 | + <h3>Step 1: Build the Extension</h3> | |
434 | + <div class="code-block"> | |
435 | + <div class="code-header"> | |
436 | + <span class="code-lang">bash</span> | |
437 | + <button class="copy-btn" onclick="copyCode(this)"> | |
438 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
439 | + <path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z"/> | |
440 | + <path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z"/> | |
441 | + </svg> | |
442 | + Copy | |
443 | + </button> | |
444 | + </div> | |
445 | + <pre><code class="language-bash"># Navigate to extension folder | |
446 | +cd opengrammar/opengrammar/extension | |
447 | + | |
448 | +# Install dependencies | |
449 | +bun install | |
450 | + | |
451 | +# Build for production | |
452 | +bun run build</code></pre> | |
453 | + </div> | |
454 | + | |
455 | + <h3>Step 2: Load in Chrome</h3> | |
456 | + <ol class="step-list"> | |
457 | + <li>Open Chrome</li> | |
458 | + <li>Navigate to <code>chrome://extensions/</code></li> | |
459 | + <li>Enable <strong>Developer mode</strong> (toggle in top-right corner)</li> | |
460 | + <li>Click <strong>Load unpacked</strong></li> | |
461 | + <li>Select the <code>opengrammar/extension/dist</code> folder</li> | |
462 | + <li>Click <strong>Select</strong></li> | |
463 | + </ol> | |
464 | + <div class="callout callout-success"> | |
465 | + <div class="callout-icon">β
</div> | |
466 | + <div class="callout-content"> | |
467 | + <strong>Extension loaded!</strong> You'll see the OpenGrammar icon in your toolbar. | |
468 | + </div> | |
469 | + </div> | |
470 | + | |
471 | + <h2>βοΈ Initial Configuration</h2> | |
472 | + | |
473 | + <h3>Step 1: Open Settings</h3> | |
474 | + <ol> | |
475 | + <li>Click the OpenGrammar icon in your toolbar</li> | |
476 | + <li>Click the <strong>Settings</strong> (gear) icon</li> | |
477 | + </ol> | |
478 | + | |
479 | + <h3>Step 2: Configure Backend URL</h3> | |
480 | + <p>Enter your backend URL based on your deployment:</p> | |
481 | + <ul> | |
482 | + <li>Local: <code>http://localhost:8787</code></li> | |
483 | + <li>Cloudflare: <code>https://opengrammar.yourname.workers.dev</code></li> | |
484 | + <li>Vercel: <code>https://opengrammar-backend.vercel.app</code></li> | |
485 | + <li>Railway: <code>https://your-app.railway.app</code></li> | |
486 | + <li>Render: <code>https://opengrammar-backend.onrender.com</code></li> | |
487 | + <li>Docker: <code>http://localhost:8787</code></li> | |
488 | + </ul> | |
489 | + | |
490 | + <h3>Step 3: Configure AI Provider</h3> | |
491 | + <div class="provider-cards"> | |
492 | + <div class="provider-card"> | |
493 | + <div class="provider-icon">β‘</div> | |
494 | + <h4>Groq (Free)</h4> | |
495 | + <p>100 requests/day free</p> | |
496 | + <code>llama-3.1-70b-versatile</code> | |
497 | + </div> | |
498 | + <div class="provider-card"> | |
499 | + <div class="provider-icon">π’</div> | |
500 | + <h4>OpenAI</h4> | |
501 | + <p>Best quality</p> | |
502 | + <code>gpt-4o-mini</code> | |
503 | + </div> | |
504 | + <div class="provider-card"> | |
505 | + <div class="provider-icon">π¦</div> | |
506 | + <h4>Ollama</h4> | |
507 | + <p>Local & offline</p> | |
508 | + <code>qwen2.5:1.5b</code> | |
509 | + </div> | |
510 | + </div> | |
511 | + | |
512 | + <h2>π¨ User Interface</h2> | |
513 | + | |
514 | + <h3>Color-Coded Underlines</h3> | |
515 | + <div class="color-guide"> | |
516 | + <div class="color-item"> | |
517 | + <div class="color-swatch red"></div> | |
518 | + <div class="color-info"> | |
519 | + <strong>Red</strong> | |
520 | + <span>Grammar/Spelling errors</span> | |
521 | + </div> | |
522 | + </div> | |
523 | + <div class="color-item"> | |
524 | + <div class="color-swatch amber"></div> | |
525 | + <div class="color-info"> | |
526 | + <strong>Amber</strong> | |
527 | + <span>Clarity issues</span> | |
528 | + </div> | |
529 | + </div> | |
530 | + <div class="color-item"> | |
531 | + <div class="color-swatch blue"></div> | |
532 | + <div class="color-info"> | |
533 | + <strong>Blue</strong> | |
534 | + <span>Style suggestions</span> | |
535 | + </div> | |
536 | + </div> | |
537 | + </div> | |
538 | + | |
539 | + <div class="section-nav"> | |
540 | + <a href="#quick-start" class="prev-link"> | |
541 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
542 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
543 | + </svg> | |
544 | + <span>Previous</span> | |
545 | + </a> | |
546 | + <a href="#backend-deployment" class="next-link"> | |
547 | + <span>Next</span> | |
548 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
549 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
550 | + </svg> | |
551 | + </a> | |
552 | + </div> | |
553 | + </div> | |
554 | + </article> | |
555 | + | |
556 | + <!-- More sections will be loaded dynamically --> | |
557 | + <article id="what-is-opengrammar" class="content-section"> | |
558 | + <div class="section-header"> | |
559 | + <nav class="breadcrumb"> | |
560 | + <a href="#">Docs</a> | |
561 | + <span class="breadcrumb-sep">/</span> | |
562 | + <span>Getting Started</span> | |
563 | + <span class="breadcrumb-sep">/</span> | |
564 | + <span class="current">What is OpenGrammar?</span> | |
565 | + </nav> | |
566 | + <h1>π What is OpenGrammar?</h1> | |
567 | + <p class="section-description">Your privacy-first, open-source writing assistant</p> | |
568 | + </div> | |
569 | + | |
570 | + <div class="content-body"> | |
571 | + <div class="hero-card"> | |
572 | + <div class="hero-card-content"> | |
573 | + <h2>Why OpenGrammar?</h2> | |
574 | + <p>Most popular grammar assistants require you to send every keystroke to their servers and charge a hefty monthly fee for advanced features. OpenGrammar changes that.</p> | |
575 | + </div> | |
576 | + </div> | |
577 | + | |
578 | + <h2>π Key Features</h2> | |
579 | + | |
580 | + <div class="feature-grid-2"> | |
581 | + <div class="feature-box"> | |
582 | + <div class="feature-box-icon">π</div> | |
583 | + <h3>Zero Cost Option</h3> | |
584 | + <p>The core engine runs locally in your browser, checking for passive voice, repetition, and readability without needing a server or an internet connection.</p> | |
585 | + </div> | |
586 | + <div class="feature-box"> | |
587 | + <div class="feature-box-icon">π</div> | |
588 | + <h3>Bring Your Own AI</h3> | |
589 | + <p>Just paste in your own API key (like OpenAI, Groq, or OpenRouter). You pay only fractions of a cent for what you actually use, directly to the AI provider.</p> | |
590 | + </div> | |
591 | + <div class="feature-box"> | |
592 | + <div class="feature-box-icon">π‘οΈ</div> | |
593 | + <h3>Absolute Privacy</h3> | |
594 | + <p>We don't have a database. We don't have user accounts. Your API key never leaves your browser. If you use the AI features, your text is sent securely to a stateless edge function, processed, and immediately forgotten.</p> | |
595 | + </div> | |
596 | + <div class="feature-box"> | |
597 | + <div class="feature-box-icon">π¦</div> | |
598 | + <h3>Open Source & Self-Hosted</h3> | |
599 | + <p>You can deploy the backend to Cloudflare Workers or Vercel Edge for free in one command. You own the infrastructure.</p> | |
600 | + </div> | |
601 | + </div> | |
602 | + | |
603 | + <h2>β¨ Features</h2> | |
604 | + | |
605 | + <ul class="feature-list"> | |
606 | + <li> | |
607 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
608 | + <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/> | |
609 | + </svg> | |
610 | + <strong>Works Everywhere:</strong> Seamlessly integrates into text inputs, textareas, and rich text editors (like Gmail, Google Docs, Notion, and Reddit). | |
611 | + </li> | |
612 | + <li> | |
613 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
614 | + <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/> | |
615 | + </svg> | |
616 | + <strong>Blazing Fast:</strong> Built with modern web technologies (React, Vite, Manifest V3) for minimal performance impact. | |
617 | + </li> | |
618 | + <li> | |
619 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
620 | + <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/> | |
621 | + </svg> | |
622 | + <strong>Dual-Engine Architecture:</strong> | |
623 | + <ul> | |
624 | + <li><em>Rule-Based (Free & Offline):</em> Catches passive voice, repeated words, and overly long sentences.</li> | |
625 | + <li><em>AI-Powered (Requires API Key):</em> Advanced grammar, spelling, clarity, and stylistic suggestions.</li> | |
626 | + </ul> | |
627 | + </li> | |
628 | + <li> | |
629 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
630 | + <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/> | |
631 | + </svg> | |
632 | + <strong>Tone & Style Rewriting:</strong> Right-click context menus or shortcuts to quickly rewrite text in 8 different tones. | |
633 | + </li> | |
634 | + <li> | |
635 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
636 | + <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/> | |
637 | + </svg> | |
638 | + <strong>Writing Statistics:</strong> Built-in dashboard for readability scores, reading time, and vocabulary diversity. | |
639 | + </li> | |
640 | + <li> | |
641 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
642 | + <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/> | |
643 | + </svg> | |
644 | + <strong>Intuitive UI:</strong> Familiar red, yellow, and blue underlines with click-to-apply suggestions. | |
645 | + </li> | |
646 | + </ul> | |
647 | + | |
648 | + <div class="section-nav"> | |
649 | + <a href="#quick-start" class="prev-link"> | |
650 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
651 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
652 | + </svg> | |
653 | + <span>Previous</span> | |
654 | + </a> | |
655 | + <a href="#browser-setup" class="next-link"> | |
656 | + <span>Next</span> | |
657 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
658 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
659 | + </svg> | |
660 | + </a> | |
661 | + </div> | |
662 | + </div> | |
663 | + </article> | |
664 | + | |
665 | + <!-- Placeholder sections for other docs --> | |
666 | + <article id="backend-deployment" class="content-section"> | |
667 | + <div class="section-header"> | |
668 | + <nav class="breadcrumb"> | |
669 | + <a href="#">Docs</a> | |
670 | + <span class="breadcrumb-sep">/</span> | |
671 | + <span>Installation</span> | |
672 | + <span class="breadcrumb-sep">/</span> | |
673 | + <span class="current">Backend Deployment</span> | |
674 | + </nav> | |
675 | + <h1>π Backend Deployment</h1> | |
676 | + <p class="section-description">Deploy OpenGrammar backend to production with any of these platforms.</p> | |
677 | + </div> | |
678 | + <div class="content-body"> | |
679 | + <div class="callout callout-info"> | |
680 | + <div class="callout-icon">π</div> | |
681 | + <div class="callout-content"> | |
682 | + <strong>Deployment Options Comparison</strong> | |
683 | + <p>Choose the platform that best fits your needs.</p> | |
684 | + </div> | |
685 | + </div> | |
686 | + | |
687 | + <div class="table-wrapper"> | |
688 | + <table class="data-table"> | |
689 | + <thead> | |
690 | + <tr> | |
691 | + <th>Platform</th> | |
692 | + <th>Free Tier</th> | |
693 | + <th>Setup Time</th> | |
694 | + <th>Best For</th> | |
695 | + </tr> | |
696 | + </thead> | |
697 | + <tbody> | |
698 | + <tr> | |
699 | + <td><strong>Cloudflare Workers</strong></td> | |
700 | + <td>100K req/day</td> | |
701 | + <td>5 min</td> | |
702 | + <td>Production, global CDN</td> | |
703 | + </tr> | |
704 | + <tr> | |
705 | + <td><strong>Vercel</strong></td> | |
706 | + <td>100GB-hours/mo</td> | |
707 | + <td>5 min</td> | |
708 | + <td>Easy deployment</td> | |
709 | + </tr> | |
710 | + <tr> | |
711 | + <td><strong>Railway</strong></td> | |
712 | + <td>$5 credit</td> | |
713 | + <td>10 min</td> | |
714 | + <td>Always-on, no sleep</td> | |
715 | + </tr> | |
716 | + <tr> | |
717 | + <td><strong>Render</strong></td> | |
718 | + <td>750 hours/mo</td> | |
719 | + <td>10 min</td> | |
720 | + <td>Simple web service</td> | |
721 | + </tr> | |
722 | + <tr> | |
723 | + <td><strong>Docker</strong></td> | |
724 | + <td>Free</td> | |
725 | + <td>15 min</td> | |
726 | + <td>Self-hosting, full control</td> | |
727 | + </tr> | |
728 | + </tbody> | |
729 | + </table> | |
730 | + </div> | |
731 | + | |
732 | + <h2>βοΈ Cloudflare Workers (Recommended)</h2> | |
733 | + | |
734 | + <h3>Prerequisites</h3> | |
735 | + <ul> | |
736 | + <li>Cloudflare account (free)</li> | |
737 | + <li>Node.js 18+</li> | |
738 | + </ul> | |
739 | + | |
740 | + <h3>Step 1: Install Wrangler CLI</h3> | |
741 | + <div class="code-block"> | |
742 | + <div class="code-header"> | |
743 | + <span class="code-lang">bash</span> | |
744 | + <button class="copy-btn" onclick="copyCode(this)"> | |
745 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
746 | + <path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z"/> | |
747 | + <path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z"/> | |
748 | + </svg> | |
749 | + Copy | |
750 | + </button> | |
751 | + </div> | |
752 | + <pre><code class="language-bash">npm install -g wrangler</code></pre> | |
753 | + </div> | |
754 | + | |
755 | + <h3>Step 2: Login to Cloudflare</h3> | |
756 | + <div class="code-block"> | |
757 | + <pre><code class="language-bash">wrangler login</code></pre> | |
758 | + </div> | |
759 | + | |
760 | + <h3>Step 3: Configure Environment</h3> | |
761 | + <div class="code-block"> | |
762 | + <pre><code class="language-bash">cd opengrammar/opengrammar/backend | |
763 | + | |
764 | +# Create .dev.vars for local development | |
765 | +cat > .dev.vars << EOF | |
766 | +DEBUG=true | |
767 | +GROQ_API_KEY=your_groq_key | |
768 | +OPENAI_API_KEY=your_openai_key | |
769 | +EOF</code></pre> | |
770 | + </div> | |
771 | + | |
772 | + <h3>Step 4: Deploy</h3> | |
773 | + <div class="code-block"> | |
774 | + <pre><code class="language-bash"># Deploy to production | |
775 | +wrangler deploy --env production</code></pre> | |
776 | + </div> | |
777 | + | |
778 | + <h3>Step 5: Get Your URL</h3> | |
779 | + <p>After deployment, you'll see:</p> | |
780 | + <div class="code-block"> | |
781 | + <pre><code>Deployed https://opengrammar.yourname.workers.dev</code></pre> | |
782 | + </div> | |
783 | + | |
784 | + <h2>β² Vercel</h2> | |
785 | + | |
786 | + <h3>Step 1: Install Vercel CLI</h3> | |
787 | + <div class="code-block"> | |
788 | + <pre><code class="language-bash">npm install -g vercel</code></pre> | |
789 | + </div> | |
790 | + | |
791 | + <h3>Step 2: Deploy</h3> | |
792 | + <div class="code-block"> | |
793 | + <pre><code class="language-bash">cd opengrammar/opengrammar/backend | |
794 | +vercel --prod</code></pre> | |
795 | + </div> | |
796 | + | |
797 | + <h2>π³ Docker Self-Hosting</h2> | |
798 | + | |
799 | + <h3>Option 1: Docker Compose</h3> | |
800 | + <div class="code-block"> | |
801 | + <pre><code class="language-bash">cd opengrammar/opengrammar | |
802 | + | |
803 | +# Start backend only | |
804 | +docker-compose up -d opengrammar-backend | |
805 | + | |
806 | +# Start with Ollama (local LLM) | |
807 | +docker-compose --profile local-llm up -d</code></pre> | |
808 | + </div> | |
809 | + | |
810 | + <div class="section-nav"> | |
811 | + <a href="#browser-setup" class="prev-link"> | |
812 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
813 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
814 | + </svg> | |
815 | + <span>Previous</span> | |
816 | + </a> | |
817 | + <a href="#docker-self-hosting" class="next-link"> | |
818 | + <span>Next</span> | |
819 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
820 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
821 | + </svg> | |
822 | + </a> | |
823 | + </div> | |
824 | + </div> | |
825 | + </article> | |
826 | + | |
827 | + <article id="docker-self-hosting" class="content-section"> | |
828 | + <div class="section-header"> | |
829 | + <nav class="breadcrumb"> | |
830 | + <a href="#">Docs</a> | |
831 | + <span class="breadcrumb-sep">/</span> | |
832 | + <span>Installation</span> | |
833 | + <span class="breadcrumb-sep">/</span> | |
834 | + <span class="current">Docker Self-Hosting</span> | |
835 | + </nav> | |
836 | + <h1>π³ Docker Self-Hosting</h1> | |
837 | + <p class="section-description">Run OpenGrammar locally with Docker and optional local LLM support (Ollama).</p> | |
838 | + </div> | |
839 | + <div class="content-body"> | |
840 | + <div class="callout callout-primary"> | |
841 | + <div class="callout-icon">π―</div> | |
842 | + <div class="callout-content"> | |
843 | + <strong>Why Self-Host with Docker?</strong> | |
844 | + <ul> | |
845 | + <li><strong>Complete Privacy:</strong> All data stays on your machine</li> | |
846 | + <li><strong>Free:</strong> No API costs (with local LLM)</li> | |
847 | + <li><strong>Offline:</strong> Works without internet</li> | |
848 | + <li><strong>Full Control:</strong> Customize everything</li> | |
849 | + <li><strong>No Rate Limits:</strong> Use as much as you want</li> | |
850 | + </ul> | |
851 | + </div> | |
852 | + </div> | |
853 | + | |
854 | + <h2>π Quick Start</h2> | |
855 | + | |
856 | + <h3>Option 1: Backend Only (Use Cloud APIs)</h3> | |
857 | + <div class="code-block"> | |
858 | + <pre><code class="language-bash">cd opengrammar/opengrammar | |
859 | + | |
860 | +# Create environment file | |
861 | +cat > .env << EOF | |
862 | +PORT=8787 | |
863 | +NODE_ENV=production | |
864 | +GROQ_API_KEY=your_groq_key | |
865 | +OPENAI_API_KEY=your_openai_key | |
866 | +EOF | |
867 | + | |
868 | +# Start backend | |
869 | +docker-compose up -d opengrammar-backend | |
870 | + | |
871 | +# Check status | |
872 | +docker-compose ps | |
873 | + | |
874 | +# View logs | |
875 | +docker-compose logs -f opengrammar-backend</code></pre> | |
876 | + </div> | |
877 | + | |
878 | + <h3>Option 2: Backend + Ollama (Local LLM)</h3> | |
879 | + <div class="code-block"> | |
880 | + <pre><code class="language-bash">cd opengrammar/opengrammar | |
881 | + | |
882 | +# Start everything (requires NVIDIA GPU) | |
883 | +docker-compose --profile local-llm up -d</code></pre> | |
884 | + </div> | |
885 | + | |
886 | + <h2>π€ Local LLM Setup with Ollama</h2> | |
887 | + | |
888 | + <h3>Step 1: Start Ollama Container</h3> | |
889 | + <div class="code-block"> | |
890 | + <pre><code class="language-bash">docker-compose --profile local-llm up -d ollama</code></pre> | |
891 | + </div> | |
892 | + | |
893 | + <h3>Step 2: Pull Grammar-Focused Models</h3> | |
894 | + <div class="code-block"> | |
895 | + <pre><code class="language-bash"># Enter Ollama container | |
896 | +docker exec -it opengrammar-ollama bash | |
897 | + | |
898 | +# Pull models (inside container) | |
899 | +ollama pull qwen2.5:0.5b # Ultra fast, 400MB | |
900 | +ollama pull qwen2.5:1.5b # Balanced, 1GB | |
901 | +ollama pull phi4-mini:3.8b # Great quality, 2.5GB | |
902 | +ollama pull llama3.2:3b # Good all-rounder, 2GB | |
903 | + | |
904 | +# Exit container | |
905 | +exit</code></pre> | |
906 | + </div> | |
907 | + | |
908 | + <h2>π― Model Recommendations</h2> | |
909 | + | |
910 | + <div class="table-wrapper"> | |
911 | + <table class="data-table"> | |
912 | + <thead> | |
913 | + <tr> | |
914 | + <th>Model</th> | |
915 | + <th>Size</th> | |
916 | + <th>RAM</th> | |
917 | + <th>Speed</th> | |
918 | + <th>Quality</th> | |
919 | + <th>Best For</th> | |
920 | + </tr> | |
921 | + </thead> | |
922 | + <tbody> | |
923 | + <tr> | |
924 | + <td><strong>qwen2.5:0.5b</strong></td> | |
925 | + <td>400MB</td> | |
926 | + <td>1GB</td> | |
927 | + <td>β‘β‘β‘β‘β‘</td> | |
928 | + <td>βββ</td> | |
929 | + <td>Fast basic checks</td> | |
930 | + </tr> | |
931 | + <tr> | |
932 | + <td><strong>qwen2.5:1.5b</strong></td> | |
933 | + <td>1GB</td> | |
934 | + <td>2GB</td> | |
935 | + <td>β‘β‘β‘β‘</td> | |
936 | + <td>ββββ</td> | |
937 | + <td>Balanced</td> | |
938 | + </tr> | |
939 | + <tr> | |
940 | + <td><strong>phi4-mini:3.8b</strong></td> | |
941 | + <td>2.5GB</td> | |
942 | + <td>4GB</td> | |
943 | + <td>β‘β‘β‘</td> | |
944 | + <td>βββββ</td> | |
945 | + <td>Best quality</td> | |
946 | + </tr> | |
947 | + <tr> | |
948 | + <td><strong>llama3.2:3b</strong></td> | |
949 | + <td>2GB</td> | |
950 | + <td>3GB</td> | |
951 | + <td>β‘β‘β‘β‘</td> | |
952 | + <td>ββββ</td> | |
953 | + <td>Good balance</td> | |
954 | + </tr> | |
955 | + </tbody> | |
956 | + </table> | |
957 | + </div> | |
958 | + | |
959 | + <div class="section-nav"> | |
960 | + <a href="#backend-deployment" class="prev-link"> | |
961 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
962 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
963 | + </svg> | |
964 | + <span>Previous</span> | |
965 | + </a> | |
966 | + <a href="#ai-providers" class="next-link"> | |
967 | + <span>Next</span> | |
968 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
969 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
970 | + </svg> | |
971 | + </a> | |
972 | + </div> | |
973 | + </div> | |
974 | + </article> | |
975 | + | |
976 | + <article id="ai-providers" class="content-section"> | |
977 | + <div class="section-header"> | |
978 | + <nav class="breadcrumb"> | |
979 | + <a href="#">Docs</a> | |
980 | + <span class="breadcrumb-sep">/</span> | |
981 | + <span>Configuration</span> | |
982 | + <span class="breadcrumb-sep">/</span> | |
983 | + <span class="current">AI Providers</span> | |
984 | + </nav> | |
985 | + <h1>π€ AI Provider Setup</h1> | |
986 | + <p class="section-description">Configure AI providers for advanced grammar checking and tone rewriting.</p> | |
987 | + </div> | |
988 | + <div class="content-body"> | |
989 | + <h2>π Overview</h2> | |
990 | + <p>OpenGrammar supports <strong>6 AI providers</strong>, giving you flexibility in cost, quality, and privacy.</p> | |
991 | + | |
992 | + <div class="provider-comparison"> | |
993 | + <div class="provider-card-large"> | |
994 | + <div class="provider-header"> | |
995 | + <span class="provider-icon">β‘</span> | |
996 | + <h3>Groq</h3> | |
997 | + </div> | |
998 | + <div class="provider-stats"> | |
999 | + <div class="stat"><span>Speed:</span> β‘β‘β‘</div> | |
1000 | + <div class="stat"><span>Quality:</span> ββββ</div> | |
1001 | + <div class="stat"><span>Cost:</span> Free tier</div> | |
1002 | + </div> | |
1003 | + <p class="provider-desc">Fast & free - 100 requests/day</p> | |
1004 | + </div> | |
1005 | + <div class="provider-card-large"> | |
1006 | + <div class="provider-header"> | |
1007 | + <span class="provider-icon">π’</span> | |
1008 | + <h3>OpenAI</h3> | |
1009 | + </div> | |
1010 | + <div class="provider-stats"> | |
1011 | + <div class="stat"><span>Speed:</span> β‘β‘</div> | |
1012 | + <div class="stat"><span>Quality:</span> βββββ</div> | |
1013 | + <div class="stat"><span>Cost:</span> $$</div> | |
1014 | + </div> | |
1015 | + <p class="provider-desc">Best quality - GPT-4o-mini</p> | |
1016 | + </div> | |
1017 | + <div class="provider-card-large"> | |
1018 | + <div class="provider-header"> | |
1019 | + <span class="provider-icon">π¦</span> | |
1020 | + <h3>Ollama</h3> | |
1021 | + </div> | |
1022 | + <div class="provider-stats"> | |
1023 | + <div class="stat"><span>Speed:</span> β‘β‘β‘</div> | |
1024 | + <div class="stat"><span>Quality:</span> βββ</div> | |
1025 | + <div class="stat"><span>Cost:</span> Free</div> | |
1026 | + </div> | |
1027 | + <p class="provider-desc">Privacy, offline - Local LLM</p> | |
1028 | + </div> | |
1029 | + </div> | |
1030 | + | |
1031 | + <h2>β‘ Groq (Recommended - Free)</h2> | |
1032 | + | |
1033 | + <h3>Step 1: Create Account</h3> | |
1034 | + <ol> | |
1035 | + <li>Visit <a href="https://console.groq.com" target="_blank">Groq Console</a></li> | |
1036 | + <li>Click <strong>Sign Up</strong></li> | |
1037 | + <li>Complete registration</li> | |
1038 | + </ol> | |
1039 | + | |
1040 | + <h3>Step 2: Get API Key</h3> | |
1041 | + <ol> | |
1042 | + <li>Go to <strong>API Keys</strong> in left sidebar</li> | |
1043 | + <li>Click <strong>Create API Key</strong></li> | |
1044 | + <li>Give it a name (e.g., "OpenGrammar")</li> | |
1045 | + <li>Copy the key (starts with <code>gsk_</code>)</li> | |
1046 | + </ol> | |
1047 | + | |
1048 | + <h3>Step 3: Configure in Extension</h3> | |
1049 | + <ol> | |
1050 | + <li>Click OpenGrammar icon β Settings</li> | |
1051 | + <li>Provider: <strong>Groq</strong></li> | |
1052 | + <li>API Key: <code>gsk_xxx</code> (paste your key)</li> | |
1053 | + <li>Model: <strong>llama-3.1-70b-versatile</strong></li> | |
1054 | + <li>Click <strong>Save</strong></li> | |
1055 | + </ol> | |
1056 | + | |
1057 | + <div class="section-nav"> | |
1058 | + <a href="#docker-self-hosting" class="prev-link"> | |
1059 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1060 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
1061 | + </svg> | |
1062 | + <span>Previous</span> | |
1063 | + </a> | |
1064 | + <a href="#using-opengrammar" class="next-link"> | |
1065 | + <span>Next</span> | |
1066 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1067 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
1068 | + </svg> | |
1069 | + </a> | |
1070 | + </div> | |
1071 | + </div> | |
1072 | + </article> | |
1073 | + | |
1074 | + <article id="using-opengrammar" class="content-section"> | |
1075 | + <div class="section-header"> | |
1076 | + <nav class="breadcrumb"> | |
1077 | + <a href="#">Docs</a> | |
1078 | + <span class="breadcrumb-sep">/</span> | |
1079 | + <span>User Guide</span> | |
1080 | + <span class="breadcrumb-sep">/</span> | |
1081 | + <span class="current">Using OpenGrammar</span> | |
1082 | + </nav> | |
1083 | + <h1>π Using OpenGrammar</h1> | |
1084 | + <p class="section-description">Complete user guide to all features and functionality.</p> | |
1085 | + </div> | |
1086 | + <div class="content-body"> | |
1087 | + <h2>βοΈ Grammar Checking</h2> | |
1088 | + | |
1089 | + <h3>Color-Coded Underlines</h3> | |
1090 | + <div class="color-guide"> | |
1091 | + <div class="color-item"> | |
1092 | + <div class="color-swatch red"></div> | |
1093 | + <div class="color-info"> | |
1094 | + <strong>Red</strong> | |
1095 | + <span>Spelling/Grammar errors</span> | |
1096 | + </div> | |
1097 | + </div> | |
1098 | + <div class="color-item"> | |
1099 | + <div class="color-swatch amber"></div> | |
1100 | + <div class="color-info"> | |
1101 | + <strong>Amber</strong> | |
1102 | + <span>Clarity issues</span> | |
1103 | + </div> | |
1104 | + </div> | |
1105 | + <div class="color-item"> | |
1106 | + <div class="color-swatch blue"></div> | |
1107 | + <div class="color-info"> | |
1108 | + <strong>Blue</strong> | |
1109 | + <span>Style suggestions</span> | |
1110 | + </div> | |
1111 | + </div> | |
1112 | + </div> | |
1113 | + | |
1114 | + <h3>Using Grammar Checking</h3> | |
1115 | + <ol class="step-list"> | |
1116 | + <li><strong>Start Typing</strong> - Open any text input (Gmail, Google Docs, Notion, etc.)</li> | |
1117 | + <li><strong>Watch for Underlines</strong> - As you type, OpenGrammar automatically checks</li> | |
1118 | + <li><strong>Review Suggestions</strong> - Click any underlined text to see suggestions</li> | |
1119 | + <li><strong>Apply Changes</strong> - Click Apply, Ignore, or Add to Dictionary</li> | |
1120 | + </ol> | |
1121 | + | |
1122 | + <h2>π¨ Tone Rewriting</h2> | |
1123 | + | |
1124 | + <h3>Available Tones</h3> | |
1125 | + <div class="tone-grid"> | |
1126 | + <div class="tone-card"> | |
1127 | + <span class="tone-emoji">π©</span> | |
1128 | + <h4>Formal</h4> | |
1129 | + <p>Business, academic</p> | |
1130 | + </div> | |
1131 | + <div class="tone-card"> | |
1132 | + <span class="tone-emoji">π</span> | |
1133 | + <h4>Casual</h4> | |
1134 | + <p>Friends, chat</p> | |
1135 | + </div> | |
1136 | + <div class="tone-card"> | |
1137 | + <span class="tone-emoji">πΌ</span> | |
1138 | + <h4>Professional</h4> | |
1139 | + <p>Work emails</p> | |
1140 | + </div> | |
1141 | + <div class="tone-card"> | |
1142 | + <span class="tone-emoji">π€</span> | |
1143 | + <h4>Friendly</h4> | |
1144 | + <p>Social media</p> | |
1145 | + </div> | |
1146 | + <div class="tone-card"> | |
1147 | + <span class="tone-emoji">β‘</span> | |
1148 | + <h4>Concise</h4> | |
1149 | + <p>Quick messages</p> | |
1150 | + </div> | |
1151 | + <div class="tone-card"> | |
1152 | + <span class="tone-emoji">π</span> | |
1153 | + <h4>Detailed</h4> | |
1154 | + <p>Explanations</p> | |
1155 | + </div> | |
1156 | + <div class="tone-card"> | |
1157 | + <span class="tone-emoji">πͺ</span> | |
1158 | + <h4>Persuasive</h4> | |
1159 | + <p>Sales, pitches</p> | |
1160 | + </div> | |
1161 | + <div class="tone-card"> | |
1162 | + <span class="tone-emoji">π</span> | |
1163 | + <h4>Neutral</h4> | |
1164 | + <p>General use</p> | |
1165 | + </div> | |
1166 | + </div> | |
1167 | + | |
1168 | + <div class="section-nav"> | |
1169 | + <a href="#ai-providers" class="prev-link"> | |
1170 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1171 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
1172 | + </svg> | |
1173 | + <span>Previous</span> | |
1174 | + </a> | |
1175 | + <a href="#tone-rewriting" class="next-link"> | |
1176 | + <span>Next</span> | |
1177 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1178 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
1179 | + </svg> | |
1180 | + </a> | |
1181 | + </div> | |
1182 | + </div> | |
1183 | + </article> | |
1184 | + | |
1185 | + <!-- Additional placeholder sections --> | |
1186 | + <article id="tone-rewriting" class="content-section"> | |
1187 | + <div class="section-header"> | |
1188 | + <nav class="breadcrumb"> | |
1189 | + <a href="#">Docs</a> | |
1190 | + <span class="breadcrumb-sep">/</span> | |
1191 | + <span>User Guide</span> | |
1192 | + <span class="breadcrumb-sep">/</span> | |
1193 | + <span class="current">Tone Rewriting</span> | |
1194 | + </nav> | |
1195 | + <h1>π¨ Tone Rewriting</h1> | |
1196 | + <p class="section-description">Master the art of rewriting text in different tones.</p> | |
1197 | + </div> | |
1198 | + <div class="content-body"> | |
1199 | + <h2>π Available Tones</h2> | |
1200 | + | |
1201 | + <div class="tone-detail-grid"> | |
1202 | + <div class="tone-detail-card"> | |
1203 | + <div class="tone-detail-header"> | |
1204 | + <span class="tone-detail-icon">π©</span> | |
1205 | + <h3>Formal</h3> | |
1206 | + </div> | |
1207 | + <p class="tone-detail-use">Use for: Academic writing, business proposals, official communications</p> | |
1208 | + <div class="tone-detail-example"> | |
1209 | + <div class="example-input"> | |
1210 | + <span class="label">Input:</span> | |
1211 | + <code>hey whats up</code> | |
1212 | + </div> | |
1213 | + <div class="example-output"> | |
1214 | + <span class="label">Output:</span> | |
1215 | + <code>Greetings, how are you?</code> | |
1216 | + </div> | |
1217 | + </div> | |
1218 | + </div> | |
1219 | + | |
1220 | + <div class="tone-detail-card"> | |
1221 | + <div class="tone-detail-header"> | |
1222 | + <span class="tone-detail-icon">π</span> | |
1223 | + <h3>Casual</h3> | |
1224 | + </div> | |
1225 | + <p class="tone-detail-use">Use for: Social media, text messages, informal emails</p> | |
1226 | + <div class="tone-detail-example"> | |
1227 | + <div class="example-input"> | |
1228 | + <span class="label">Input:</span> | |
1229 | + <code>Greetings, how are you?</code> | |
1230 | + </div> | |
1231 | + <div class="example-output"> | |
1232 | + <span class="label">Output:</span> | |
1233 | + <code>Hey, what's up?</code> | |
1234 | + </div> | |
1235 | + </div> | |
1236 | + </div> | |
1237 | + | |
1238 | + <div class="tone-detail-card"> | |
1239 | + <div class="tone-detail-header"> | |
1240 | + <span class="tone-detail-icon">πΌ</span> | |
1241 | + <h3>Professional</h3> | |
1242 | + </div> | |
1243 | + <p class="tone-detail-use">Use for: Work emails, business communication, reports</p> | |
1244 | + <div class="tone-detail-example"> | |
1245 | + <div class="example-input"> | |
1246 | + <span class="label">Input:</span> | |
1247 | + <code>hey can we meet tmrw</code> | |
1248 | + </div> | |
1249 | + <div class="example-output"> | |
1250 | + <span class="label">Output:</span> | |
1251 | + <code>Hello, could we schedule a meeting for tomorrow?</code> | |
1252 | + </div> | |
1253 | + </div> | |
1254 | + </div> | |
1255 | + </div> | |
1256 | + | |
1257 | + <h2>π How to Use</h2> | |
1258 | + | |
1259 | + <h3>Method 1: Right-Click Menu</h3> | |
1260 | + <ol> | |
1261 | + <li>Select text you want to rewrite</li> | |
1262 | + <li>Right-click</li> | |
1263 | + <li>Choose "Rewrite with OpenGrammar"</li> | |
1264 | + <li>Choose tone and see preview</li> | |
1265 | + <li>Apply or Copy result</li> | |
1266 | + </ol> | |
1267 | + | |
1268 | + <h3>Method 2: Keyboard Shortcut</h3> | |
1269 | + <ol> | |
1270 | + <li>Select text</li> | |
1271 | + <li>Press <kbd>Ctrl+Shift+R</kbd> (Windows/Linux) or <kbd>Cmd+Shift+R</kbd> (Mac)</li> | |
1272 | + <li>Choose tone</li> | |
1273 | + <li>Apply changes</li> | |
1274 | + </ol> | |
1275 | + | |
1276 | + <div class="section-nav"> | |
1277 | + <a href="#using-opengrammar" class="prev-link"> | |
1278 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1279 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
1280 | + </svg> | |
1281 | + <span>Previous</span> | |
1282 | + </a> | |
1283 | + <a href="#writing-statistics" class="next-link"> | |
1284 | + <span>Next</span> | |
1285 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1286 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
1287 | + </svg> | |
1288 | + </a> | |
1289 | + </div> | |
1290 | + </div> | |
1291 | + </article> | |
1292 | + | |
1293 | + <article id="writing-statistics" class="content-section"> | |
1294 | + <div class="section-header"> | |
1295 | + <nav class="breadcrumb"> | |
1296 | + <a href="#">Docs</a> | |
1297 | + <span class="breadcrumb-sep">/</span> | |
1298 | + <span>User Guide</span> | |
1299 | + <span class="breadcrumb-sep">/</span> | |
1300 | + <span class="current">Writing Statistics</span> | |
1301 | + </nav> | |
1302 | + <h1>π Writing Statistics</h1> | |
1303 | + <p class="section-description">Analyze and improve your writing with detailed statistics.</p> | |
1304 | + </div> | |
1305 | + <div class="content-body"> | |
1306 | + <h2>π Available Metrics</h2> | |
1307 | + | |
1308 | + <h3>Readability Scores</h3> | |
1309 | + | |
1310 | + <div class="metric-card"> | |
1311 | + <div class="metric-header"> | |
1312 | + <h4>Flesch Reading Ease Score</h4> | |
1313 | + <span class="metric-badge">0-100</span> | |
1314 | + </div> | |
1315 | + <div class="metric-scale"> | |
1316 | + <div class="scale-item"><span class="range">90-100</span> <span class="label">Very Easy (5th grade)</span></div> | |
1317 | + <div class="scale-item"><span class="range">80-89</span> <span class="label">Easy (6th grade)</span></div> | |
1318 | + <div class="scale-item"><span class="range">70-79</span> <span class="label">Fairly Easy (7th grade)</span></div> | |
1319 | + <div class="scale-item"><span class="range">60-69</span> <span class="label">Standard (8th-9th grade)</span></div> | |
1320 | + <div class="scale-item"><span class="range">50-59</span> <span class="label">Fairly Difficult (10th-12th)</span></div> | |
1321 | + <div class="scale-item"><span class="range">30-49</span> <span class="label">Difficult (College)</span></div> | |
1322 | + <div class="scale-item"><span class="range">0-29</span> <span class="label">Very Difficult (Graduate+)</span></div> | |
1323 | + </div> | |
1324 | + </div> | |
1325 | + | |
1326 | + <div class="metric-card"> | |
1327 | + <div class="metric-header"> | |
1328 | + <h4>Flesch-Kincaid Grade Level</h4> | |
1329 | + <span class="metric-badge">US Grades</span> | |
1330 | + </div> | |
1331 | + <div class="metric-scale"> | |
1332 | + <div class="scale-item"><span class="range">1-6</span> <span class="label">Elementary School</span></div> | |
1333 | + <div class="scale-item"><span class="range">7-9</span> <span class="label">Middle School</span></div> | |
1334 | + <div class="scale-item"><span class="range">10-12</span> <span class="label">High School</span></div> | |
1335 | + <div class="scale-item"><span class="range">13-16</span> <span class="label">College</span></div> | |
1336 | + <div class="scale-item"><span class="range">17+</span> <span class="label">Graduate School</span></div> | |
1337 | + </div> | |
1338 | + </div> | |
1339 | + | |
1340 | + <h3>Time Estimates</h3> | |
1341 | + <ul> | |
1342 | + <li><strong>Reading Time:</strong> Words Γ· 200 words per minute</li> | |
1343 | + <li><strong>Speaking Time:</strong> Words Γ· 150 words per minute</li> | |
1344 | + </ul> | |
1345 | + | |
1346 | + <div class="section-nav"> | |
1347 | + <a href="#tone-rewriting" class="prev-link"> | |
1348 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1349 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
1350 | + </svg> | |
1351 | + <span>Previous</span> | |
1352 | + </a> | |
1353 | + <a href="#keyboard-shortcuts" class="next-link"> | |
1354 | + <span>Next</span> | |
1355 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1356 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
1357 | + </svg> | |
1358 | + </a> | |
1359 | + </div> | |
1360 | + </div> | |
1361 | + </article> | |
1362 | + | |
1363 | + <article id="keyboard-shortcuts" class="content-section"> | |
1364 | + <div class="section-header"> | |
1365 | + <nav class="breadcrumb"> | |
1366 | + <a href="#">Docs</a> | |
1367 | + <span class="breadcrumb-sep">/</span> | |
1368 | + <span>User Guide</span> | |
1369 | + <span class="breadcrumb-sep">/</span> | |
1370 | + <span class="current">Keyboard Shortcuts</span> | |
1371 | + </nav> | |
1372 | + <h1>β¨οΈ Keyboard Shortcuts</h1> | |
1373 | + <p class="section-description">All keyboard shortcuts for quick access to OpenGrammar features.</p> | |
1374 | + </div> | |
1375 | + <div class="content-body"> | |
1376 | + <h2>Default Shortcuts</h2> | |
1377 | + | |
1378 | + <div class="table-wrapper"> | |
1379 | + <table class="data-table"> | |
1380 | + <thead> | |
1381 | + <tr> | |
1382 | + <th>Action</th> | |
1383 | + <th>Windows/Linux</th> | |
1384 | + <th>Mac</th> | |
1385 | + </tr> | |
1386 | + </thead> | |
1387 | + <tbody> | |
1388 | + <tr> | |
1389 | + <td><strong>Rewrite Selected Text</strong></td> | |
1390 | + <td><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>R</kbd></td> | |
1391 | + <td><kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>R</kbd></td> | |
1392 | + </tr> | |
1393 | + <tr> | |
1394 | + <td><strong>Toggle Extension</strong></td> | |
1395 | + <td><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd></td> | |
1396 | + <td><kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd></td> | |
1397 | + </tr> | |
1398 | + <tr> | |
1399 | + <td><strong>Open Statistics</strong></td> | |
1400 | + <td><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd></td> | |
1401 | + <td><kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd></td> | |
1402 | + </tr> | |
1403 | + <tr> | |
1404 | + <td><strong>Open Settings</strong></td> | |
1405 | + <td><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>,</kbd></td> | |
1406 | + <td><kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>,</kbd></td> | |
1407 | + </tr> | |
1408 | + </tbody> | |
1409 | + </table> | |
1410 | + </div> | |
1411 | + | |
1412 | + <div class="section-nav"> | |
1413 | + <a href="#writing-statistics" class="prev-link"> | |
1414 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1415 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
1416 | + </svg> | |
1417 | + <span>Previous</span> | |
1418 | + </a> | |
1419 | + <a href="#troubleshooting" class="next-link"> | |
1420 | + <span>Next</span> | |
1421 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1422 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
1423 | + </svg> | |
1424 | + </a> | |
1425 | + </div> | |
1426 | + </div> | |
1427 | + </article> | |
1428 | + | |
1429 | + <article id="troubleshooting" class="content-section"> | |
1430 | + <div class="section-header"> | |
1431 | + <nav class="breadcrumb"> | |
1432 | + <a href="#">Docs</a> | |
1433 | + <span class="breadcrumb-sep">/</span> | |
1434 | + <span>Support</span> | |
1435 | + <span class="breadcrumb-sep">/</span> | |
1436 | + <span class="current">Troubleshooting</span> | |
1437 | + </nav> | |
1438 | + <h1>π§ Troubleshooting</h1> | |
1439 | + <p class="section-description">Solve common OpenGrammar issues with this comprehensive guide.</p> | |
1440 | + </div> | |
1441 | + <div class="content-body"> | |
1442 | + <h2>π Common Issues</h2> | |
1443 | + | |
1444 | + <h3>No Grammar Highlights</h3> | |
1445 | + <div class="troubleshoot-card"> | |
1446 | + <h4>Symptoms</h4> | |
1447 | + <ul> | |
1448 | + <li>Typing text with errors</li> | |
1449 | + <li>No red/amber/blue underlines appear</li> | |
1450 | + <li>Extension icon shows no error count</li> | |
1451 | + </ul> | |
1452 | + <h4>Solutions</h4> | |
1453 | + <ol> | |
1454 | + <li>Check extension is enabled</li> | |
1455 | + <li>Verify site is not in disabled domains</li> | |
1456 | + <li>Test backend: <code>curl http://localhost:8787/health</code></li> | |
1457 | + <li>Reload the page</li> | |
1458 | + <li>Check browser console (F12) for errors</li> | |
1459 | + </ol> | |
1460 | + </div> | |
1461 | + | |
1462 | + <h3>Backend Connection Failed</h3> | |
1463 | + <div class="troubleshoot-card"> | |
1464 | + <h4>Symptoms</h4> | |
1465 | + <ul> | |
1466 | + <li>Red status indicator in extension</li> | |
1467 | + <li>"Cannot connect to backend" error</li> | |
1468 | + <li>No AI suggestions</li> | |
1469 | + </ul> | |
1470 | + <h4>Solutions</h4> | |
1471 | + <ol> | |
1472 | + <li>Verify Backend URL in settings</li> | |
1473 | + <li>Test backend: <code>curl your-backend-url/health</code></li> | |
1474 | + <li>Check CORS configuration</li> | |
1475 | + <li>Restart backend service</li> | |
1476 | + <li>Check firewall settings</li> | |
1477 | + </ol> | |
1478 | + </div> | |
1479 | + | |
1480 | + <h3>AI Not Working</h3> | |
1481 | + <div class="troubleshoot-card"> | |
1482 | + <h4>Symptoms</h4> | |
1483 | + <ul> | |
1484 | + <li>Rule-based checks work</li> | |
1485 | + <li>AI suggestions don't appear</li> | |
1486 | + <li>"API key invalid" error</li> | |
1487 | + </ul> | |
1488 | + <h4>Solutions</h4> | |
1489 | + <ol> | |
1490 | + <li>Verify API key is entered correctly</li> | |
1491 | + <li>Check for typos (no spaces)</li> | |
1492 | + <li>Ensure correct provider is selected</li> | |
1493 | + <li>Test API key with provider directly</li> | |
1494 | + <li>Check rate limits (Groq: 100/day free)</li> | |
1495 | + </ol> | |
1496 | + </div> | |
1497 | + | |
1498 | + <div class="section-nav"> | |
1499 | + <a href="#keyboard-shortcuts" class="prev-link"> | |
1500 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1501 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
1502 | + </svg> | |
1503 | + <span>Previous</span> | |
1504 | + </a> | |
1505 | + <a href="#faq" class="next-link"> | |
1506 | + <span>Next</span> | |
1507 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1508 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
1509 | + </svg> | |
1510 | + </a> | |
1511 | + </div> | |
1512 | + </div> | |
1513 | + </article> | |
1514 | + | |
1515 | + <article id="faq" class="content-section"> | |
1516 | + <div class="section-header"> | |
1517 | + <nav class="breadcrumb"> | |
1518 | + <a href="#">Docs</a> | |
1519 | + <span class="breadcrumb-sep">/</span> | |
1520 | + <span>Support</span> | |
1521 | + <span class="breadcrumb-sep">/</span> | |
1522 | + <span class="current">FAQ</span> | |
1523 | + </nav> | |
1524 | + <h1>β Frequently Asked Questions</h1> | |
1525 | + <p class="section-description">Common questions about OpenGrammar.</p> | |
1526 | + </div> | |
1527 | + <div class="content-body"> | |
1528 | + <div class="faq-list"> | |
1529 | + <div class="faq-item"> | |
1530 | + <div class="faq-question"> | |
1531 | + <h3>Is OpenGrammar really free?</h3> | |
1532 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1533 | + <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/> | |
1534 | + </svg> | |
1535 | + </div> | |
1536 | + <div class="faq-answer"> | |
1537 | + <p>Yes! The core rule-based engine is completely free and works offline. For AI-powered features, you bring your own API key and pay only for what you use directly to the provider (often fractions of a cent).</p> | |
1538 | + </div> | |
1539 | + </div> | |
1540 | + | |
1541 | + <div class="faq-item"> | |
1542 | + <div class="faq-question"> | |
1543 | + <h3>How does OpenGrammar protect my privacy?</h3> | |
1544 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1545 | + <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/> | |
1546 | + </svg> | |
1547 | + </div> | |
1548 | + <div class="faq-answer"> | |
1549 | + <p>OpenGrammar has no databases, no user accounts, and no tracking. Your API key never leaves your browser. When using AI features, text is sent to a stateless edge function, processed, and immediately forgotten.</p> | |
1550 | + </div> | |
1551 | + </div> | |
1552 | + | |
1553 | + <div class="faq-item"> | |
1554 | + <div class="faq-question"> | |
1555 | + <h3>Which AI provider should I use?</h3> | |
1556 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1557 | + <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/> | |
1558 | + </svg> | |
1559 | + </div> | |
1560 | + <div class="faq-answer"> | |
1561 | + <p>For free usage, we recommend <strong>Groq</strong> (100 requests/day free). For best quality, use <strong>OpenAI GPT-4o-mini</strong>. For complete privacy, use <strong>Ollama</strong> to run models locally offline.</p> | |
1562 | + </div> | |
1563 | + </div> | |
1564 | + | |
1565 | + <div class="faq-item"> | |
1566 | + <div class="faq-question"> | |
1567 | + <h3>Can I use OpenGrammar without internet?</h3> | |
1568 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1569 | + <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/> | |
1570 | + </svg> | |
1571 | + </div> | |
1572 | + <div class="faq-answer"> | |
1573 | + <p>Yes! The rule-based engine works completely offline. For AI features, you can use Ollama to run models locally on your machine, giving you full offline capability.</p> | |
1574 | + </div> | |
1575 | + </div> | |
1576 | + | |
1577 | + <div class="faq-item"> | |
1578 | + <div class="faq-question"> | |
1579 | + <h3>Does OpenGrammar work on Google Docs?</h3> | |
1580 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1581 | + <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"/> | |
1582 | + </svg> | |
1583 | + </div> | |
1584 | + <div class="faq-answer"> | |
1585 | + <p>Yes, OpenGrammar works on Google Docs and most rich text editors. Google Docs support is actively being improved for better compatibility.</p> | |
1586 | + </div> | |
1587 | + </div> | |
1588 | + </div> | |
1589 | + | |
1590 | + <div class="section-nav"> | |
1591 | + <a href="#troubleshooting" class="prev-link"> | |
1592 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1593 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
1594 | + </svg> | |
1595 | + <span>Previous</span> | |
1596 | + </a> | |
1597 | + <a href="#api-reference" class="next-link"> | |
1598 | + <span>Next</span> | |
1599 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1600 | + <path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/> | |
1601 | + </svg> | |
1602 | + </a> | |
1603 | + </div> | |
1604 | + </div> | |
1605 | + </article> | |
1606 | + | |
1607 | + <article id="api-reference" class="content-section"> | |
1608 | + <div class="section-header"> | |
1609 | + <nav class="breadcrumb"> | |
1610 | + <a href="#">Docs</a> | |
1611 | + <span class="breadcrumb-sep">/</span> | |
1612 | + <span>Support</span> | |
1613 | + <span class="breadcrumb-sep">/</span> | |
1614 | + <span class="current">API Reference</span> | |
1615 | + </nav> | |
1616 | + <h1>π API Reference</h1> | |
1617 | + <p class="section-description">Backend API documentation for developers.</p> | |
1618 | + </div> | |
1619 | + <div class="content-body"> | |
1620 | + <h2>Endpoints</h2> | |
1621 | + | |
1622 | + <h3>Health Check</h3> | |
1623 | + <div class="api-endpoint"> | |
1624 | + <div class="api-method get">GET</div> | |
1625 | + <code class="api-path">/health</code> | |
1626 | + </div> | |
1627 | + <p>Returns the health status of the backend service.</p> | |
1628 | + | |
1629 | + <div class="code-block"> | |
1630 | + <div class="code-header"> | |
1631 | + <span class="code-lang">bash</span> | |
1632 | + <button class="copy-btn" onclick="copyCode(this)"> | |
1633 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1634 | + <path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z"/> | |
1635 | + <path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z"/> | |
1636 | + </svg> | |
1637 | + Copy | |
1638 | + </button> | |
1639 | + </div> | |
1640 | + <pre><code class="language-bash">curl http://localhost:8787/health</code></pre> | |
1641 | + </div> | |
1642 | + | |
1643 | + <h4>Response</h4> | |
1644 | + <div class="code-block"> | |
1645 | + <pre><code class="language-json">{ | |
1646 | + "status": "healthy", | |
1647 | + "timestamp": "2026-03-20T12:00:00.000Z", | |
1648 | + "environment": "production", | |
1649 | + "version": "2.0.0" | |
1650 | +}</code></pre> | |
1651 | + </div> | |
1652 | + | |
1653 | + <h3>Analyze Text</h3> | |
1654 | + <div class="api-endpoint"> | |
1655 | + <div class="api-method post">POST</div> | |
1656 | + <code class="api-path">/analyze</code> | |
1657 | + </div> | |
1658 | + <p>Analyze text for grammar, spelling, clarity, and style issues.</p> | |
1659 | + | |
1660 | + <div class="code-block"> | |
1661 | + <div class="code-header"> | |
1662 | + <span class="code-lang">bash</span> | |
1663 | + <button class="copy-btn" onclick="copyCode(this)"> | |
1664 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1665 | + <path d="M8 3a1 1 0 011-1h2a1 1 0 110 2H9a1 1 0 01-1-1z"/> | |
1666 | + <path d="M6 3a2 2 0 00-2 2v11a2 2 0 002 2h8a2 2 0 002-2V5a2 2 0 00-2-2 3 3 0 01-3 3H9a3 3 0 01-3-3z"/> | |
1667 | + </svg> | |
1668 | + Copy | |
1669 | + </button> | |
1670 | + </div> | |
1671 | + <pre><code class="language-bash">curl -X POST http://localhost:8787/analyze \ | |
1672 | + -H "Content-Type: application/json" \ | |
1673 | + -d '{ | |
1674 | + "text": "me and him went to store", | |
1675 | + "apiKey": "your-api-key", | |
1676 | + "provider": "groq", | |
1677 | + "model": "llama-3.1-70b-versatile" | |
1678 | + }'</code></pre> | |
1679 | + </div> | |
1680 | + | |
1681 | + <h4>Request Body</h4> | |
1682 | + <div class="table-wrapper"> | |
1683 | + <table class="data-table"> | |
1684 | + <thead> | |
1685 | + <tr> | |
1686 | + <th>Field</th> | |
1687 | + <th>Type</th> | |
1688 | + <th>Required</th> | |
1689 | + <th>Description</th> | |
1690 | + </tr> | |
1691 | + </thead> | |
1692 | + <tbody> | |
1693 | + <tr> | |
1694 | + <td><code>text</code></td> | |
1695 | + <td>string</td> | |
1696 | + <td>Yes</td> | |
1697 | + <td>Text to analyze (max 50,000 chars)</td> | |
1698 | + </tr> | |
1699 | + <tr> | |
1700 | + <td><code>apiKey</code></td> | |
1701 | + <td>string</td> | |
1702 | + <td>No</td> | |
1703 | + <td>AI provider API key</td> | |
1704 | + </tr> | |
1705 | + <tr> | |
1706 | + <td><code>provider</code></td> | |
1707 | + <td>string</td> | |
1708 | + <td>No</td> | |
1709 | + <td>AI provider (groq, openai, ollama, etc.)</td> | |
1710 | + </tr> | |
1711 | + <tr> | |
1712 | + <td><code>model</code></td> | |
1713 | + <td>string</td> | |
1714 | + <td>No</td> | |
1715 | + <td>Model to use for AI analysis</td> | |
1716 | + </tr> | |
1717 | + </tbody> | |
1718 | + </table> | |
1719 | + </div> | |
1720 | + | |
1721 | + <h3>Rewrite Text</h3> | |
1722 | + <div class="api-endpoint"> | |
1723 | + <div class="api-method post">POST</div> | |
1724 | + <code class="api-path">/rewrite</code> | |
1725 | + </div> | |
1726 | + <p>Rewrite text in different tones.</p> | |
1727 | + | |
1728 | + <div class="code-block"> | |
1729 | + <pre><code class="language-bash">curl -X POST http://localhost:8787/rewrite \ | |
1730 | + -H "Content-Type: application/json" \ | |
1731 | + -d '{ | |
1732 | + "text": "hey whats up", | |
1733 | + "tone": "formal", | |
1734 | + "apiKey": "your-api-key" | |
1735 | + }'</code></pre> | |
1736 | + </div> | |
1737 | + | |
1738 | + <h4>Response</h4> | |
1739 | + <div class="code-block"> | |
1740 | + <pre><code class="language-json">{ | |
1741 | + "original": "hey whats up", | |
1742 | + "rewritten": "Greetings, how are you?", | |
1743 | + "tone": "formal" | |
1744 | +}</code></pre> | |
1745 | + </div> | |
1746 | + | |
1747 | + <div class="section-nav"> | |
1748 | + <a href="#faq" class="prev-link"> | |
1749 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
1750 | + <path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
1751 | + </svg> | |
1752 | + <span>Previous</span> | |
1753 | + </a> | |
1754 | + </div> | |
1755 | + </div> | |
1756 | + </article> | |
1757 | + </div> | |
1758 | + | |
1759 | + <footer class="content-footer"> | |
1760 | + <div class="footer-content"> | |
1761 | + <p>Built with β€οΈ by <a href="https://github.com/swadhinbiswas" target="_blank">Swadhin Biswas</a></p> | |
1762 | + <p>OpenGrammar is licensed under <a href="https://opensource.org/licenses/Apache-2.0" target="_blank">Apache 2.0</a></p> | |
1763 | + </div> | |
1764 | + </footer> | |
1765 | + </main> | |
1766 | + | |
1767 | + <script src="script.js"></script> | |
1768 | +</body> | |
1769 | +</html> | |
0 | 1770 | |
βΌdocs-site/script.js
+365-0
| @@ -0,0 +1,365 @@ | ||
1 | +// =================================== | |
2 | +// OpenGrammar Documentation Scripts | |
3 | +// =================================== | |
4 | + | |
5 | +document.addEventListener('DOMContentLoaded', () => { | |
6 | + // Initialize theme | |
7 | + initTheme(); | |
8 | + | |
9 | + // Initialize navigation | |
10 | + initNavigation(); | |
11 | + | |
12 | + // Initialize tabs | |
13 | + initTabs(); | |
14 | + | |
15 | + // Initialize FAQ | |
16 | + initFAQ(); | |
17 | + | |
18 | + // Initialize search | |
19 | + initSearch(); | |
20 | + | |
21 | + // Initialize mobile menu | |
22 | + initMobileMenu(); | |
23 | + | |
24 | + // Initialize code copy | |
25 | + initCodeCopy(); | |
26 | + | |
27 | + // Initialize smooth scroll | |
28 | + initSmoothScroll(); | |
29 | +}); | |
30 | + | |
31 | +// Theme Toggle | |
32 | +function initTheme() { | |
33 | + const themeToggle = document.getElementById('themeToggle'); | |
34 | + const mobileThemeToggle = document.getElementById('mobile-theme-toggle'); | |
35 | + | |
36 | + // Check for saved theme preference or default to light mode | |
37 | + const savedTheme = localStorage.getItem('theme'); | |
38 | + if (savedTheme === 'dark') { | |
39 | + document.body.classList.add('dark'); | |
40 | + } | |
41 | + | |
42 | + // Desktop theme toggle | |
43 | + if (themeToggle) { | |
44 | + themeToggle.addEventListener('click', () => { | |
45 | + document.body.classList.toggle('dark'); | |
46 | + const isDark = document.body.classList.contains('dark'); | |
47 | + localStorage.setItem('theme', isDark ? 'dark' : 'light'); | |
48 | + }); | |
49 | + } | |
50 | + | |
51 | + // Mobile theme toggle | |
52 | + if (mobileThemeToggle) { | |
53 | + mobileThemeToggle.addEventListener('click', () => { | |
54 | + document.body.classList.toggle('dark'); | |
55 | + const isDark = document.body.classList.contains('dark'); | |
56 | + localStorage.setItem('theme', isDark ? 'dark' : 'light'); | |
57 | + }); | |
58 | + } | |
59 | +} | |
60 | + | |
61 | +// Navigation | |
62 | +function initNavigation() { | |
63 | + const navLinks = document.querySelectorAll('.nav-link'); | |
64 | + const sections = document.querySelectorAll('.content-section'); | |
65 | + | |
66 | + // Handle nav link clicks | |
67 | + navLinks.forEach(link => { | |
68 | + link.addEventListener('click', (e) => { | |
69 | + e.preventDefault(); | |
70 | + const targetId = link.getAttribute('data-page'); | |
71 | + | |
72 | + // Update active nav link | |
73 | + navLinks.forEach(l => l.classList.remove('active')); | |
74 | + link.classList.add('active'); | |
75 | + | |
76 | + // Show target section | |
77 | + showSection(targetId); | |
78 | + | |
79 | + // Update URL hash | |
80 | + window.location.hash = targetId; | |
81 | + | |
82 | + // Close mobile menu if open | |
83 | + closeMobileMenu(); | |
84 | + | |
85 | + // Scroll to top | |
86 | + window.scrollTo({ top: 0, behavior: 'smooth' }); | |
87 | + }); | |
88 | + }); | |
89 | + | |
90 | + // Handle initial hash | |
91 | + const hash = window.location.hash.slice(1); | |
92 | + if (hash) { | |
93 | + showSection(hash); | |
94 | + navLinks.forEach(link => { | |
95 | + if (link.getAttribute('data-page') === hash) { | |
96 | + link.classList.add('active'); | |
97 | + } | |
98 | + }); | |
99 | + } else { | |
100 | + // Default to quick-start | |
101 | + showSection('quick-start'); | |
102 | + const firstLink = document.querySelector('.nav-link[data-page="quick-start"]'); | |
103 | + if (firstLink) firstLink.classList.add('active'); | |
104 | + } | |
105 | + | |
106 | + // Handle browser back/forward | |
107 | + window.addEventListener('hashchange', () => { | |
108 | + const hash = window.location.hash.slice(1); | |
109 | + if (hash) { | |
110 | + showSection(hash); | |
111 | + navLinks.forEach(link => { | |
112 | + link.classList.toggle('active', link.getAttribute('data-page') === hash); | |
113 | + }); | |
114 | + } | |
115 | + }); | |
116 | +} | |
117 | + | |
118 | +function showSection(sectionId) { | |
119 | + const sections = document.querySelectorAll('.content-section'); | |
120 | + sections.forEach(section => { | |
121 | + section.classList.toggle('active', section.id === sectionId); | |
122 | + }); | |
123 | + | |
124 | + // Update breadcrumb | |
125 | + updateBreadcrumb(sectionId); | |
126 | +} | |
127 | + | |
128 | +function updateBreadcrumb(sectionId) { | |
129 | + const section = document.getElementById(sectionId); | |
130 | + if (!section) return; | |
131 | + | |
132 | + const navLink = document.querySelector(`.nav-link[data-page="${sectionId}"]`); | |
133 | + if (!navLink) return; | |
134 | + | |
135 | + const sectionTitle = navLink.textContent.trim(); | |
136 | + const sectionGroup = navLink.closest('.nav-section'); | |
137 | + const groupName = sectionGroup?.querySelector('.nav-section-title')?.textContent.trim() || 'Docs'; | |
138 | + | |
139 | + const breadcrumbs = document.querySelectorAll('.breadcrumb'); | |
140 | + breadcrumbs.forEach(breadcrumb => { | |
141 | + const parentSection = breadcrumb.closest('.content-section'); | |
142 | + if (parentSection && parentSection.id === sectionId) { | |
143 | + breadcrumb.innerHTML = ` | |
144 | + <a href="#">Docs</a> | |
145 | + <span class="breadcrumb-sep">/</span> | |
146 | + <span>${groupName}</span> | |
147 | + <span class="breadcrumb-sep">/</span> | |
148 | + <span class="current">${sectionTitle}</span> | |
149 | + `; | |
150 | + } | |
151 | + }); | |
152 | +} | |
153 | + | |
154 | +// Tabs | |
155 | +function initTabs() { | |
156 | + const tabContainers = document.querySelectorAll('.tabs'); | |
157 | + | |
158 | + tabContainers.forEach(container => { | |
159 | + const buttons = container.querySelectorAll('.tab-btn'); | |
160 | + const panes = container.querySelectorAll('.tab-pane'); | |
161 | + | |
162 | + buttons.forEach(button => { | |
163 | + button.addEventListener('click', () => { | |
164 | + const targetTab = button.getAttribute('data-tab'); | |
165 | + | |
166 | + // Update active button | |
167 | + buttons.forEach(b => b.classList.remove('active')); | |
168 | + button.classList.add('active'); | |
169 | + | |
170 | + // Update active pane | |
171 | + panes.forEach(pane => { | |
172 | + pane.classList.toggle('active', pane.id === targetTab); | |
173 | + }); | |
174 | + }); | |
175 | + }); | |
176 | + }); | |
177 | +} | |
178 | + | |
179 | +// FAQ | |
180 | +function initFAQ() { | |
181 | + const faqItems = document.querySelectorAll('.faq-item'); | |
182 | + | |
183 | + faqItems.forEach(item => { | |
184 | + const question = item.querySelector('.faq-question'); | |
185 | + question?.addEventListener('click', () => { | |
186 | + const isActive = item.classList.contains('active'); | |
187 | + | |
188 | + // Close all other items | |
189 | + faqItems.forEach(otherItem => { | |
190 | + if (otherItem !== item) { | |
191 | + otherItem.classList.remove('active'); | |
192 | + } | |
193 | + }); | |
194 | + | |
195 | + // Toggle current item | |
196 | + item.classList.toggle('active', !isActive); | |
197 | + }); | |
198 | + }); | |
199 | +} | |
200 | + | |
201 | +// Search | |
202 | +function initSearch() { | |
203 | + const searchInput = document.getElementById('searchInput'); | |
204 | + if (!searchInput) return; | |
205 | + | |
206 | + searchInput.addEventListener('input', (e) => { | |
207 | + const query = e.target.value.toLowerCase().trim(); | |
208 | + | |
209 | + if (query.length < 2) { | |
210 | + return; | |
211 | + } | |
212 | + | |
213 | + // Search in section titles | |
214 | + const sections = document.querySelectorAll('.content-section'); | |
215 | + let foundMatch = false; | |
216 | + | |
217 | + sections.forEach(section => { | |
218 | + const title = section.querySelector('h1')?.textContent.toLowerCase() || ''; | |
219 | + const description = section.querySelector('.section-description')?.textContent.toLowerCase() || ''; | |
220 | + | |
221 | + if (title.includes(query) || description.includes(query)) { | |
222 | + if (!foundMatch) { | |
223 | + showSection(section.id); | |
224 | + foundMatch = true; | |
225 | + | |
226 | + // Update nav | |
227 | + document.querySelectorAll('.nav-link').forEach(link => { | |
228 | + link.classList.toggle('active', link.getAttribute('data-page') === section.id); | |
229 | + }); | |
230 | + } | |
231 | + } | |
232 | + }); | |
233 | + | |
234 | + if (foundMatch) { | |
235 | + window.scrollTo({ top: 0, behavior: 'smooth' }); | |
236 | + } | |
237 | + }); | |
238 | + | |
239 | + // Keyboard shortcut for search | |
240 | + document.addEventListener('keydown', (e) => { | |
241 | + if ((e.metaKey || e.ctrlKey) && e.key === 'k') { | |
242 | + e.preventDefault(); | |
243 | + searchInput?.focus(); | |
244 | + } | |
245 | + }); | |
246 | +} | |
247 | + | |
248 | +// Mobile Menu | |
249 | +function initMobileMenu() { | |
250 | + const menuToggle = document.getElementById('menuToggle'); | |
251 | + const sidebar = document.querySelector('.sidebar'); | |
252 | + | |
253 | + menuToggle?.addEventListener('click', () => { | |
254 | + sidebar?.classList.toggle('open'); | |
255 | + }); | |
256 | + | |
257 | + // Close menu on outside click | |
258 | + document.addEventListener('click', (e) => { | |
259 | + if (sidebar && !sidebar.contains(e.target) && !menuToggle?.contains(e.target)) { | |
260 | + closeMobileMenu(); | |
261 | + } | |
262 | + }); | |
263 | +} | |
264 | + | |
265 | +function closeMobileMenu() { | |
266 | + const sidebar = document.querySelector('.sidebar'); | |
267 | + sidebar?.classList.remove('open'); | |
268 | +} | |
269 | + | |
270 | +// Code Copy | |
271 | +function initCodeCopy() { | |
272 | + document.addEventListener('click', (e) => { | |
273 | + const copyBtn = e.target.closest('.copy-btn'); | |
274 | + if (!copyBtn) return; | |
275 | + | |
276 | + const codeBlock = copyBtn.closest('.code-block'); | |
277 | + const code = codeBlock?.querySelector('code')?.textContent; | |
278 | + | |
279 | + if (code) { | |
280 | + navigator.clipboard.writeText(code).then(() => { | |
281 | + // Show success feedback | |
282 | + const originalText = copyBtn.innerHTML; | |
283 | + copyBtn.innerHTML = ` | |
284 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
285 | + <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
286 | + </svg> | |
287 | + Copied! | |
288 | + `; | |
289 | + | |
290 | + setTimeout(() => { | |
291 | + copyBtn.innerHTML = originalText; | |
292 | + }, 2000); | |
293 | + }); | |
294 | + } | |
295 | + }); | |
296 | +} | |
297 | + | |
298 | +// Copy code function (global) | |
299 | +window.copyCode = function(btn) { | |
300 | + const codeBlock = btn.closest('.code-block'); | |
301 | + const code = codeBlock?.querySelector('code')?.textContent; | |
302 | + | |
303 | + if (code) { | |
304 | + navigator.clipboard.writeText(code).then(() => { | |
305 | + const originalText = btn.innerHTML; | |
306 | + btn.innerHTML = ` | |
307 | + <svg viewBox="0 0 20 20" fill="currentColor"> | |
308 | + <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/> | |
309 | + </svg> | |
310 | + Copied! | |
311 | + `; | |
312 | + | |
313 | + setTimeout(() => { | |
314 | + btn.innerHTML = originalText; | |
315 | + }, 2000); | |
316 | + }); | |
317 | + } | |
318 | +}; | |
319 | + | |
320 | +// Smooth Scroll | |
321 | +function initSmoothScroll() { | |
322 | + document.querySelectorAll('a[href^="#"]').forEach(anchor => { | |
323 | + anchor.addEventListener('click', function(e) { | |
324 | + const href = this.getAttribute('href'); | |
325 | + if (href !== '#') { | |
326 | + e.preventDefault(); | |
327 | + const target = document.querySelector(href); | |
328 | + if (target) { | |
329 | + target.scrollIntoView({ | |
330 | + behavior: 'smooth', | |
331 | + block: 'start' | |
332 | + }); | |
333 | + } | |
334 | + } | |
335 | + }); | |
336 | + }); | |
337 | +} | |
338 | + | |
339 | +// Highlight active section on scroll | |
340 | +window.addEventListener('scroll', () => { | |
341 | + const sections = document.querySelectorAll('.content-section.active'); | |
342 | + const navLinks = document.querySelectorAll('.nav-link'); | |
343 | + | |
344 | + // This could be enhanced to update nav based on scroll position | |
345 | + // for long pages with multiple subsections | |
346 | +}); | |
347 | + | |
348 | +// Add animation on section change | |
349 | +document.addEventListener('DOMContentLoaded', () => { | |
350 | + const observer = new MutationObserver((mutations) => { | |
351 | + mutations.forEach((mutation) => { | |
352 | + if (mutation.attributeName === 'class' && mutation.target.classList.contains('content-section')) { | |
353 | + if (mutation.target.classList.contains('active')) { | |
354 | + mutation.target.style.animation = 'none'; | |
355 | + mutation.target.offsetHeight; // Trigger reflow | |
356 | + mutation.target.style.animation = 'fadeIn 0.3s ease'; | |
357 | + } | |
358 | + } | |
359 | + }); | |
360 | + }); | |
361 | + | |
362 | + document.querySelectorAll('.content-section').forEach(section => { | |
363 | + observer.observe(section, { attributes: true }); | |
364 | + }); | |
365 | +}); | |
0 | 366 | |
βΌdocs-site/styles.css
+1549-0
| @@ -0,0 +1,1549 @@ | ||
1 | +/* =================================== | |
2 | + OpenGrammar Documentation Styles | |
3 | + Paper Texture & 256-bit Color Theme | |
4 | + =================================== */ | |
5 | + | |
6 | +:root { | |
7 | + /* Paper Theme Colors */ | |
8 | + --paper-bg: #FDFBF7; | |
9 | + --paper-bg-secondary: #F8F6F0; | |
10 | + --paper-border: #E8E4D9; | |
11 | + --paper-text: #2D2A26; | |
12 | + --paper-text-muted: #6B665C; | |
13 | + | |
14 | + /* 256-bit Rich Colors */ | |
15 | + --primary-50: #EEF4FF; | |
16 | + --primary-100: #DCE6FF; | |
17 | + --primary-200: #BACEFF; | |
18 | + --primary-300: #96A9FF; | |
19 | + --primary-400: #6B85FF; | |
20 | + --primary-500: #4F66F0; | |
21 | + --primary-600: #3D4FDE; | |
22 | + --primary-700: #303EC4; | |
23 | + --primary-800: #2834A3; | |
24 | + --primary-900: #242F85; | |
25 | + | |
26 | + /* Accent Colors */ | |
27 | + --amber-50: #FFFBEB; | |
28 | + --amber-100: #FEF3C7; | |
29 | + --amber-200: #FDE68A; | |
30 | + --amber-300: #FCD34D; | |
31 | + --amber-400: #FBBF24; | |
32 | + --amber-500: #F59E0B; | |
33 | + --amber-600: #D97706; | |
34 | + | |
35 | + --red-50: #FEF2F2; | |
36 | + --red-100: #FEE2E2; | |
37 | + --red-200: #FECACA; | |
38 | + --red-300: #FCA5A5; | |
39 | + --red-400: #F87171; | |
40 | + --red-500: #EF4444; | |
41 | + --red-600: #DC2626; | |
42 | + | |
43 | + --green-50: #F0FDF4; | |
44 | + --green-100: #DCFCE7; | |
45 | + --green-200: #BBF7D0; | |
46 | + --green-300: #86EFAC; | |
47 | + --green-400: #4ADE80; | |
48 | + --green-500: #22C55E; | |
49 | + --green-600: #16A34A; | |
50 | + | |
51 | + --blue-50: #EFF6FF; | |
52 | + --blue-100: #DBEAFE; | |
53 | + --blue-200: #BFDBFE; | |
54 | + --blue-300: #93C5FD; | |
55 | + --blue-400: #60A5FA; | |
56 | + --blue-500: #3B82F6; | |
57 | + --blue-600: #2563EB; | |
58 | + | |
59 | + --purple-50: #F5F3FF; | |
60 | + --purple-100: #EDE9FE; | |
61 | + --purple-200: #DDD6FE; | |
62 | + --purple-300: #C4B5FD; | |
63 | + --purple-400: #A78BFA; | |
64 | + --purple-500: #8B5CF6; | |
65 | + --purple-600: #7C3AED; | |
66 | + | |
67 | + /* Dark Mode Colors */ | |
68 | + --dark-bg: #0F1115; | |
69 | + --dark-bg-secondary: #16181D; | |
70 | + --dark-border: #2A2D35; | |
71 | + --dark-text: #E8E6E3; | |
72 | + --dark-text-muted: #9CA3AF; | |
73 | + | |
74 | + /* Typography */ | |
75 | + --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | |
76 | + --font-mono: 'JetBrains Mono', 'Fira Code', monospace; | |
77 | + | |
78 | + /* Spacing */ | |
79 | + --sidebar-width: 280px; | |
80 | + --header-height: 64px; | |
81 | + | |
82 | + /* Shadows */ | |
83 | + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); | |
84 | + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); | |
85 | + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); | |
86 | + --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); | |
87 | +} | |
88 | + | |
89 | +/* Dark Mode */ | |
90 | +.dark { | |
91 | + --paper-bg: #0F1115; | |
92 | + --paper-bg-secondary: #16181D; | |
93 | + --paper-border: #2A2D35; | |
94 | + --paper-text: #E8E6E3; | |
95 | + --paper-text-muted: #9CA3AF; | |
96 | +} | |
97 | + | |
98 | +/* Reset & Base */ | |
99 | +*, *::before, *::after { | |
100 | + box-sizing: border-box; | |
101 | + margin: 0; | |
102 | + padding: 0; | |
103 | +} | |
104 | + | |
105 | +html { | |
106 | + scroll-behavior: smooth; | |
107 | + -webkit-font-smoothing: antialiased; | |
108 | + -moz-osx-font-smoothing: grayscale; | |
109 | +} | |
110 | + | |
111 | +body { | |
112 | + font-family: var(--font-sans); | |
113 | + font-size: 16px; | |
114 | + line-height: 1.7; | |
115 | + color: var(--paper-text); | |
116 | + background-color: var(--paper-bg); | |
117 | + overflow-x: hidden; | |
118 | +} | |
119 | + | |
120 | +/* Paper Texture Overlay */ | |
121 | +.paper-texture { | |
122 | + position: fixed; | |
123 | + top: 0; | |
124 | + left: 0; | |
125 | + width: 100%; | |
126 | + height: 100%; | |
127 | + pointer-events: none; | |
128 | + z-index: -1; | |
129 | + opacity: 0.4; | |
130 | + background-image: | |
131 | + url("data:image/svg+xml,%3Csvg width='200' height='200' viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23noise)' opacity='0.08'/%3E%3C/svg%3E"); | |
132 | +} | |
133 | + | |
134 | +/* Sidebar */ | |
135 | +.sidebar { | |
136 | + position: fixed; | |
137 | + top: 0; | |
138 | + left: 0; | |
139 | + width: var(--sidebar-width); | |
140 | + height: 100vh; | |
141 | + background: linear-gradient(180deg, var(--paper-bg) 0%, var(--paper-bg-secondary) 100%); | |
142 | + border-right: 1px solid var(--paper-border); | |
143 | + display: flex; | |
144 | + flex-direction: column; | |
145 | + z-index: 100; | |
146 | + overflow: hidden; | |
147 | +} | |
148 | + | |
149 | +.sidebar-header { | |
150 | + padding: 24px 20px; | |
151 | + border-bottom: 1px solid var(--paper-border); | |
152 | + display: flex; | |
153 | + flex-direction: column; | |
154 | + gap: 12px; | |
155 | +} | |
156 | + | |
157 | +.logo { | |
158 | + display: flex; | |
159 | + align-items: center; | |
160 | + gap: 12px; | |
161 | +} | |
162 | + | |
163 | +.logo-icon { | |
164 | + width: 40px; | |
165 | + height: 40px; | |
166 | + border-radius: 10px; | |
167 | + box-shadow: var(--shadow-md); | |
168 | +} | |
169 | + | |
170 | +.logo-text { | |
171 | + font-size: 20px; | |
172 | + font-weight: 700; | |
173 | + background: linear-gradient(135deg, var(--primary-600) 0%, var(--purple-600) 100%); | |
174 | + -webkit-background-clip: text; | |
175 | + -webkit-text-fill-color: transparent; | |
176 | + background-clip: text; | |
177 | +} | |
178 | + | |
179 | +.version-badge { | |
180 | + display: inline-block; | |
181 | + padding: 4px 10px; | |
182 | + background: linear-gradient(135deg, var(--primary-100) 0%, var(--purple-100) 100%); | |
183 | + color: var(--primary-700); | |
184 | + font-size: 12px; | |
185 | + font-weight: 600; | |
186 | + border-radius: 20px; | |
187 | + text-align: center; | |
188 | +} | |
189 | + | |
190 | +/* Sidebar Navigation */ | |
191 | +.sidebar-nav { | |
192 | + flex: 1; | |
193 | + overflow-y: auto; | |
194 | + padding: 16px 12px; | |
195 | +} | |
196 | + | |
197 | +.nav-section { | |
198 | + margin-bottom: 24px; | |
199 | +} | |
200 | + | |
201 | +.nav-section-title { | |
202 | + font-size: 11px; | |
203 | + font-weight: 600; | |
204 | + text-transform: uppercase; | |
205 | + letter-spacing: 0.05em; | |
206 | + color: var(--paper-text-muted); | |
207 | + padding: 8px 12px; | |
208 | + margin-bottom: 4px; | |
209 | +} | |
210 | + | |
211 | +.nav-link { | |
212 | + display: flex; | |
213 | + align-items: center; | |
214 | + gap: 10px; | |
215 | + padding: 10px 12px; | |
216 | + color: var(--paper-text-muted); | |
217 | + text-decoration: none; | |
218 | + border-radius: 8px; | |
219 | + font-size: 14px; | |
220 | + font-weight: 500; | |
221 | + transition: all 0.2s ease; | |
222 | + margin-bottom: 2px; | |
223 | +} | |
224 | + | |
225 | +.nav-link:hover { | |
226 | + background: var(--paper-bg-secondary); | |
227 | + color: var(--paper-text); | |
228 | +} | |
229 | + | |
230 | +.nav-link.active { | |
231 | + background: linear-gradient(135deg, var(--primary-50) 0%, var(--purple-50) 100%); | |
232 | + color: var(--primary-700); | |
233 | +} | |
234 | + | |
235 | +.nav-icon { | |
236 | + width: 18px; | |
237 | + height: 18px; | |
238 | + flex-shrink: 0; | |
239 | +} | |
240 | + | |
241 | +/* Sidebar Footer */ | |
242 | +.sidebar-footer { | |
243 | + padding: 16px; | |
244 | + border-top: 1px solid var(--paper-border); | |
245 | +} | |
246 | + | |
247 | +.github-link { | |
248 | + display: flex; | |
249 | + align-items: center; | |
250 | + justify-content: center; | |
251 | + gap: 8px; | |
252 | + padding: 10px; | |
253 | + background: var(--paper-bg-secondary); | |
254 | + border: 1px solid var(--paper-border); | |
255 | + border-radius: 8px; | |
256 | + color: var(--paper-text); | |
257 | + text-decoration: none; | |
258 | + font-size: 14px; | |
259 | + font-weight: 500; | |
260 | + transition: all 0.2s ease; | |
261 | +} | |
262 | + | |
263 | +.github-link:hover { | |
264 | + background: var(--paper-bg); | |
265 | + border-color: var(--primary-300); | |
266 | +} | |
267 | + | |
268 | +.github-icon { | |
269 | + width: 20px; | |
270 | + height: 20px; | |
271 | +} | |
272 | + | |
273 | +/* Main Content */ | |
274 | +.main-content { | |
275 | + margin-left: var(--sidebar-width); | |
276 | + min-height: 100vh; | |
277 | +} | |
278 | + | |
279 | +/* Content Header */ | |
280 | +.content-header { | |
281 | + position: sticky; | |
282 | + top: 0; | |
283 | + z-index: 50; | |
284 | + height: var(--header-height); | |
285 | + background: rgba(253, 251, 247, 0.9); | |
286 | + backdrop-filter: blur(12px); | |
287 | + border-bottom: 1px solid var(--paper-border); | |
288 | + display: flex; | |
289 | + align-items: center; | |
290 | + padding: 0 32px; | |
291 | + gap: 24px; | |
292 | +} | |
293 | + | |
294 | +.dark .content-header { | |
295 | + background: rgba(15, 17, 21, 0.9); | |
296 | +} | |
297 | + | |
298 | +.menu-toggle { | |
299 | + display: none; | |
300 | + background: none; | |
301 | + border: none; | |
302 | + cursor: pointer; | |
303 | + padding: 8px; | |
304 | + border-radius: 8px; | |
305 | + color: var(--paper-text); | |
306 | +} | |
307 | + | |
308 | +.menu-toggle:hover { | |
309 | + background: var(--paper-bg-secondary); | |
310 | +} | |
311 | + | |
312 | +.menu-toggle svg { | |
313 | + width: 24px; | |
314 | + height: 24px; | |
315 | +} | |
316 | + | |
317 | +/* Search Box */ | |
318 | +.search-box { | |
319 | + flex: 1; | |
320 | + max-width: 480px; | |
321 | + position: relative; | |
322 | + display: flex; | |
323 | + align-items: center; | |
324 | +} | |
325 | + | |
326 | +.search-icon { | |
327 | + position: absolute; | |
328 | + left: 14px; | |
329 | + width: 18px; | |
330 | + height: 18px; | |
331 | + color: var(--paper-text-muted); | |
332 | + pointer-events: none; | |
333 | +} | |
334 | + | |
335 | +.search-box input { | |
336 | + width: 100%; | |
337 | + padding: 10px 16px 10px 42px; | |
338 | + background: var(--paper-bg-secondary); | |
339 | + border: 1px solid var(--paper-border); | |
340 | + border-radius: 10px; | |
341 | + font-size: 14px; | |
342 | + color: var(--paper-text); | |
343 | + outline: none; | |
344 | + transition: all 0.2s ease; | |
345 | +} | |
346 | + | |
347 | +.search-box input:focus { | |
348 | + border-color: var(--primary-400); | |
349 | + box-shadow: 0 0 0 3px var(--primary-100); | |
350 | +} | |
351 | + | |
352 | +.search-box kbd { | |
353 | + position: absolute; | |
354 | + right: 12px; | |
355 | + padding: 4px 8px; | |
356 | + background: var(--paper-bg); | |
357 | + border: 1px solid var(--paper-border); | |
358 | + border-radius: 6px; | |
359 | + font-size: 12px; | |
360 | + font-family: var(--font-mono); | |
361 | + color: var(--paper-text-muted); | |
362 | +} | |
363 | + | |
364 | +/* Header Actions */ | |
365 | +.header-actions { | |
366 | + display: flex; | |
367 | + align-items: center; | |
368 | + gap: 12px; | |
369 | + margin-left: auto; | |
370 | +} | |
371 | + | |
372 | +.theme-toggle { | |
373 | + background: var(--paper-bg-secondary); | |
374 | + border: 1px solid var(--paper-border); | |
375 | + padding: 8px; | |
376 | + border-radius: 8px; | |
377 | + cursor: pointer; | |
378 | + color: var(--paper-text); | |
379 | + transition: all 0.2s ease; | |
380 | +} | |
381 | + | |
382 | +.theme-toggle:hover { | |
383 | + background: var(--paper-bg); | |
384 | +} | |
385 | + | |
386 | +.theme-toggle svg { | |
387 | + width: 20px; | |
388 | + height: 20px; | |
389 | +} | |
390 | + | |
391 | +.theme-toggle .moon-icon { | |
392 | + display: none; | |
393 | +} | |
394 | + | |
395 | +.dark .theme-toggle .sun-icon { | |
396 | + display: none; | |
397 | +} | |
398 | + | |
399 | +.dark .theme-toggle .moon-icon { | |
400 | + display: block; | |
401 | +} | |
402 | + | |
403 | +.github-btn { | |
404 | + display: flex; | |
405 | + align-items: center; | |
406 | + gap: 8px; | |
407 | + padding: 8px 16px; | |
408 | + background: var(--paper-text); | |
409 | + color: var(--paper-bg); | |
410 | + border: none; | |
411 | + border-radius: 8px; | |
412 | + font-size: 14px; | |
413 | + font-weight: 500; | |
414 | + text-decoration: none; | |
415 | + transition: all 0.2s ease; | |
416 | +} | |
417 | + | |
418 | +.github-btn:hover { | |
419 | + opacity: 0.9; | |
420 | + transform: translateY(-1px); | |
421 | +} | |
422 | + | |
423 | +.github-btn svg { | |
424 | + width: 20px; | |
425 | + height: 20px; | |
426 | +} | |
427 | + | |
428 | +/* Content Wrapper */ | |
429 | +.content-wrapper { | |
430 | + padding: 48px 64px; | |
431 | + max-width: 1200px; | |
432 | +} | |
433 | + | |
434 | +/* Content Section */ | |
435 | +.content-section { | |
436 | + display: none; | |
437 | +} | |
438 | + | |
439 | +.content-section.active { | |
440 | + display: block; | |
441 | + animation: fadeIn 0.3s ease; | |
442 | +} | |
443 | + | |
444 | +@keyframes fadeIn { | |
445 | + from { | |
446 | + opacity: 0; | |
447 | + transform: translateY(10px); | |
448 | + } | |
449 | + to { | |
450 | + opacity: 1; | |
451 | + transform: translateY(0); | |
452 | + } | |
453 | +} | |
454 | + | |
455 | +/* Section Header */ | |
456 | +.section-header { | |
457 | + margin-bottom: 40px; | |
458 | + padding-bottom: 32px; | |
459 | + border-bottom: 1px solid var(--paper-border); | |
460 | +} | |
461 | + | |
462 | +.breadcrumb { | |
463 | + display: flex; | |
464 | + align-items: center; | |
465 | + gap: 8px; | |
466 | + font-size: 14px; | |
467 | + color: var(--paper-text-muted); | |
468 | + margin-bottom: 16px; | |
469 | +} | |
470 | + | |
471 | +.breadcrumb a { | |
472 | + color: var(--primary-600); | |
473 | + text-decoration: none; | |
474 | +} | |
475 | + | |
476 | +.breadcrumb a:hover { | |
477 | + text-decoration: underline; | |
478 | +} | |
479 | + | |
480 | +.breadcrumb-sep { | |
481 | + color: var(--paper-text-muted); | |
482 | +} | |
483 | + | |
484 | +.breadcrumb .current { | |
485 | + color: var(--paper-text); | |
486 | +} | |
487 | + | |
488 | +.section-header h1 { | |
489 | + font-size: 42px; | |
490 | + font-weight: 800; | |
491 | + line-height: 1.2; | |
492 | + margin-bottom: 12px; | |
493 | + background: linear-gradient(135deg, var(--paper-text) 0%, var(--paper-text-muted) 100%); | |
494 | + -webkit-background-clip: text; | |
495 | + -webkit-text-fill-color: transparent; | |
496 | + background-clip: text; | |
497 | +} | |
498 | + | |
499 | +.section-description { | |
500 | + font-size: 18px; | |
501 | + color: var(--paper-text-muted); | |
502 | + max-width: 700px; | |
503 | +} | |
504 | + | |
505 | +/* Content Body */ | |
506 | +.content-body { | |
507 | + font-size: 17px; | |
508 | + line-height: 1.8; | |
509 | +} | |
510 | + | |
511 | +.content-body h2 { | |
512 | + font-size: 28px; | |
513 | + font-weight: 700; | |
514 | + margin: 48px 0 20px; | |
515 | + color: var(--paper-text); | |
516 | +} | |
517 | + | |
518 | +.content-body h3 { | |
519 | + font-size: 22px; | |
520 | + font-weight: 600; | |
521 | + margin: 36px 0 16px; | |
522 | + color: var(--paper-text); | |
523 | +} | |
524 | + | |
525 | +.content-body h4 { | |
526 | + font-size: 18px; | |
527 | + font-weight: 600; | |
528 | + margin: 28px 0 12px; | |
529 | + color: var(--paper-text); | |
530 | +} | |
531 | + | |
532 | +.content-body p { | |
533 | + margin-bottom: 20px; | |
534 | + color: var(--paper-text); | |
535 | +} | |
536 | + | |
537 | +.content-body ul, | |
538 | +.content-body ol { | |
539 | + margin: 20px 0 20px 28px; | |
540 | +} | |
541 | + | |
542 | +.content-body li { | |
543 | + margin-bottom: 10px; | |
544 | +} | |
545 | + | |
546 | +.content-body a { | |
547 | + color: var(--primary-600); | |
548 | + text-decoration: none; | |
549 | + border-bottom: 1px solid transparent; | |
550 | + transition: border-color 0.2s ease; | |
551 | +} | |
552 | + | |
553 | +.content-body a:hover { | |
554 | + border-bottom-color: var(--primary-600); | |
555 | +} | |
556 | + | |
557 | +.content-body code { | |
558 | + font-family: var(--font-mono); | |
559 | + font-size: 14px; | |
560 | + padding: 3px 8px; | |
561 | + background: var(--paper-bg-secondary); | |
562 | + border: 1px solid var(--paper-border); | |
563 | + border-radius: 6px; | |
564 | + color: var(--paper-text); | |
565 | +} | |
566 | + | |
567 | +.content-body pre { | |
568 | + margin: 20px 0; | |
569 | + overflow-x: auto; | |
570 | +} | |
571 | + | |
572 | +/* Callouts */ | |
573 | +.callout { | |
574 | + display: flex; | |
575 | + gap: 16px; | |
576 | + padding: 20px; | |
577 | + border-radius: 12px; | |
578 | + margin: 24px 0; | |
579 | + border-left: 4px solid; | |
580 | +} | |
581 | + | |
582 | +.callout-icon { | |
583 | + font-size: 24px; | |
584 | + flex-shrink: 0; | |
585 | +} | |
586 | + | |
587 | +.callout-content strong { | |
588 | + display: block; | |
589 | + margin-bottom: 4px; | |
590 | +} | |
591 | + | |
592 | +.callout-primary { | |
593 | + background: var(--primary-50); | |
594 | + border-color: var(--primary-500); | |
595 | +} | |
596 | + | |
597 | +.callout-success { | |
598 | + background: var(--green-50); | |
599 | + border-color: var(--green-500); | |
600 | +} | |
601 | + | |
602 | +.callout-warning { | |
603 | + background: var(--amber-50); | |
604 | + border-color: var(--amber-500); | |
605 | +} | |
606 | + | |
607 | +.callout-info { | |
608 | + background: var(--blue-50); | |
609 | + border-color: var(--blue-500); | |
610 | +} | |
611 | + | |
612 | +/* Code Block */ | |
613 | +.code-block { | |
614 | + margin: 24px 0; | |
615 | + border-radius: 12px; | |
616 | + overflow: hidden; | |
617 | + border: 1px solid var(--paper-border); | |
618 | +} | |
619 | + | |
620 | +.code-header { | |
621 | + display: flex; | |
622 | + justify-content: space-between; | |
623 | + align-items: center; | |
624 | + padding: 12px 16px; | |
625 | + background: var(--paper-bg-secondary); | |
626 | + border-bottom: 1px solid var(--paper-border); | |
627 | +} | |
628 | + | |
629 | +.code-lang { | |
630 | + font-size: 12px; | |
631 | + font-weight: 600; | |
632 | + color: var(--paper-text-muted); | |
633 | + text-transform: uppercase; | |
634 | +} | |
635 | + | |
636 | +.copy-btn { | |
637 | + display: flex; | |
638 | + align-items: center; | |
639 | + gap: 6px; | |
640 | + padding: 6px 12px; | |
641 | + background: transparent; | |
642 | + border: 1px solid var(--paper-border); | |
643 | + border-radius: 6px; | |
644 | + font-size: 13px; | |
645 | + color: var(--paper-text-muted); | |
646 | + cursor: pointer; | |
647 | + transition: all 0.2s ease; | |
648 | +} | |
649 | + | |
650 | +.copy-btn:hover { | |
651 | + background: var(--paper-bg); | |
652 | + color: var(--paper-text); | |
653 | +} | |
654 | + | |
655 | +.copy-btn svg { | |
656 | + width: 16px; | |
657 | + height: 16px; | |
658 | +} | |
659 | + | |
660 | +.code-block pre { | |
661 | + margin: 0; | |
662 | + padding: 20px; | |
663 | + background: var(--paper-bg-secondary); | |
664 | + overflow-x: auto; | |
665 | +} | |
666 | + | |
667 | +.code-block small pre { | |
668 | + padding: 12px; | |
669 | +} | |
670 | + | |
671 | +.code-block code { | |
672 | + font-family: var(--font-mono); | |
673 | + font-size: 14px; | |
674 | + line-height: 1.6; | |
675 | + color: var(--paper-text); | |
676 | +} | |
677 | + | |
678 | +/* Step List */ | |
679 | +.step-list { | |
680 | + counter-reset: step; | |
681 | + list-style: none; | |
682 | + margin: 24px 0; | |
683 | + padding: 0; | |
684 | +} | |
685 | + | |
686 | +.step-list li { | |
687 | + position: relative; | |
688 | + padding-left: 48px; | |
689 | + margin-bottom: 16px; | |
690 | +} | |
691 | + | |
692 | +.step-list li::before { | |
693 | + counter-increment: step; | |
694 | + content: counter(step); | |
695 | + position: absolute; | |
696 | + left: 0; | |
697 | + top: 0; | |
698 | + width: 32px; | |
699 | + height: 32px; | |
700 | + background: linear-gradient(135deg, var(--primary-500) 0%, var(--purple-500) 100%); | |
701 | + color: white; | |
702 | + border-radius: 50%; | |
703 | + display: flex; | |
704 | + align-items: center; | |
705 | + justify-content: center; | |
706 | + font-weight: 600; | |
707 | + font-size: 14px; | |
708 | +} | |
709 | + | |
710 | +/* Tabs */ | |
711 | +.tabs { | |
712 | + margin: 24px 0; | |
713 | +} | |
714 | + | |
715 | +.tab-buttons { | |
716 | + display: flex; | |
717 | + gap: 4px; | |
718 | + padding: 4px; | |
719 | + background: var(--paper-bg-secondary); | |
720 | + border: 1px solid var(--paper-border); | |
721 | + border-radius: 10px; | |
722 | + margin-bottom: 16px; | |
723 | +} | |
724 | + | |
725 | +.tab-btn { | |
726 | + flex: 1; | |
727 | + padding: 10px 16px; | |
728 | + background: transparent; | |
729 | + border: none; | |
730 | + border-radius: 8px; | |
731 | + font-size: 14px; | |
732 | + font-weight: 500; | |
733 | + color: var(--paper-text-muted); | |
734 | + cursor: pointer; | |
735 | + transition: all 0.2s ease; | |
736 | +} | |
737 | + | |
738 | +.tab-btn:hover { | |
739 | + color: var(--paper-text); | |
740 | +} | |
741 | + | |
742 | +.tab-btn.active { | |
743 | + background: var(--paper-bg); | |
744 | + color: var(--primary-600); | |
745 | + box-shadow: var(--shadow-sm); | |
746 | +} | |
747 | + | |
748 | +.tab-content { | |
749 | + background: var(--paper-bg); | |
750 | + border: 1px solid var(--paper-border); | |
751 | + border-radius: 10px; | |
752 | + padding: 24px; | |
753 | +} | |
754 | + | |
755 | +.tab-pane { | |
756 | + display: none; | |
757 | +} | |
758 | + | |
759 | +.tab-pane.active { | |
760 | + display: block; | |
761 | +} | |
762 | + | |
763 | +/* Tables */ | |
764 | +.table-wrapper { | |
765 | + overflow-x: auto; | |
766 | + margin: 24px 0; | |
767 | + border-radius: 12px; | |
768 | + border: 1px solid var(--paper-border); | |
769 | +} | |
770 | + | |
771 | +.data-table { | |
772 | + width: 100%; | |
773 | + border-collapse: collapse; | |
774 | + font-size: 15px; | |
775 | +} | |
776 | + | |
777 | +.data-table th, | |
778 | +.data-table td { | |
779 | + padding: 14px 16px; | |
780 | + text-align: left; | |
781 | + border-bottom: 1px solid var(--paper-border); | |
782 | +} | |
783 | + | |
784 | +.data-table th { | |
785 | + background: var(--paper-bg-secondary); | |
786 | + font-weight: 600; | |
787 | + font-size: 13px; | |
788 | + text-transform: uppercase; | |
789 | + letter-spacing: 0.05em; | |
790 | + color: var(--paper-text-muted); | |
791 | +} | |
792 | + | |
793 | +.data-table tr:last-child td { | |
794 | + border-bottom: none; | |
795 | +} | |
796 | + | |
797 | +.data-table tr:hover { | |
798 | + background: var(--paper-bg-secondary); | |
799 | +} | |
800 | + | |
801 | +/* Status Badge */ | |
802 | +.status-badge { | |
803 | + display: inline-block; | |
804 | + padding: 4px 10px; | |
805 | + border-radius: 20px; | |
806 | + font-size: 12px; | |
807 | + font-weight: 600; | |
808 | +} | |
809 | + | |
810 | +.status-badge.success { | |
811 | + background: var(--green-100); | |
812 | + color: var(--green-700); | |
813 | +} | |
814 | + | |
815 | +.status-badge.warning { | |
816 | + background: var(--amber-100); | |
817 | + color: var(--amber-700); | |
818 | +} | |
819 | + | |
820 | +/* Feature Grid */ | |
821 | +.feature-grid { | |
822 | + display: grid; | |
823 | + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); | |
824 | + gap: 20px; | |
825 | + margin: 32px 0; | |
826 | +} | |
827 | + | |
828 | +.feature-card { | |
829 | + padding: 24px; | |
830 | + background: var(--paper-bg-secondary); | |
831 | + border: 1px solid var(--paper-border); | |
832 | + border-radius: 12px; | |
833 | +} | |
834 | + | |
835 | +.feature-card .feature-icon { | |
836 | + font-size: 32px; | |
837 | + margin-bottom: 12px; | |
838 | +} | |
839 | + | |
840 | +.feature-card h4 { | |
841 | + font-size: 18px; | |
842 | + font-weight: 600; | |
843 | + margin-bottom: 12px; | |
844 | +} | |
845 | + | |
846 | +.link-list { | |
847 | + list-style: none; | |
848 | + margin: 0; | |
849 | + padding: 0; | |
850 | +} | |
851 | + | |
852 | +.link-list li { | |
853 | + margin-bottom: 8px; | |
854 | +} | |
855 | + | |
856 | +.link-list a { | |
857 | + color: var(--primary-600); | |
858 | + text-decoration: none; | |
859 | +} | |
860 | + | |
861 | +.link-list a:hover { | |
862 | + text-decoration: underline; | |
863 | +} | |
864 | + | |
865 | +/* Provider Cards */ | |
866 | +.provider-cards { | |
867 | + display: grid; | |
868 | + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |
869 | + gap: 16px; | |
870 | + margin: 24px 0; | |
871 | +} | |
872 | + | |
873 | +.provider-card { | |
874 | + padding: 20px; | |
875 | + background: var(--paper-bg-secondary); | |
876 | + border: 1px solid var(--paper-border); | |
877 | + border-radius: 12px; | |
878 | + text-align: center; | |
879 | +} | |
880 | + | |
881 | +.provider-card .provider-icon { | |
882 | + font-size: 32px; | |
883 | + margin-bottom: 12px; | |
884 | +} | |
885 | + | |
886 | +.provider-card h4 { | |
887 | + font-size: 16px; | |
888 | + font-weight: 600; | |
889 | + margin-bottom: 8px; | |
890 | +} | |
891 | + | |
892 | +.provider-card p { | |
893 | + font-size: 14px; | |
894 | + color: var(--paper-text-muted); | |
895 | + margin-bottom: 8px; | |
896 | +} | |
897 | + | |
898 | +.provider-card code { | |
899 | + font-size: 12px; | |
900 | +} | |
901 | + | |
902 | +/* Color Guide */ | |
903 | +.color-guide { | |
904 | + display: flex; | |
905 | + flex-direction: column; | |
906 | + gap: 12px; | |
907 | + margin: 24px 0; | |
908 | +} | |
909 | + | |
910 | +.color-item { | |
911 | + display: flex; | |
912 | + align-items: center; | |
913 | + gap: 16px; | |
914 | +} | |
915 | + | |
916 | +.color-swatch { | |
917 | + width: 40px; | |
918 | + height: 40px; | |
919 | + border-radius: 8px; | |
920 | + border: 2px solid var(--paper-border); | |
921 | + box-shadow: var(--shadow-sm); | |
922 | +} | |
923 | + | |
924 | +.color-swatch.red { | |
925 | + background: linear-gradient(135deg, var(--red-400) 0%, var(--red-500) 100%); | |
926 | +} | |
927 | + | |
928 | +.color-swatch.amber { | |
929 | + background: linear-gradient(135deg, var(--amber-400) 0%, var(--amber-500) 100%); | |
930 | +} | |
931 | + | |
932 | +.color-swatch.blue { | |
933 | + background: linear-gradient(135deg, var(--blue-400) 0%, var(--blue-500) 100%); | |
934 | +} | |
935 | + | |
936 | +.color-info { | |
937 | + display: flex; | |
938 | + flex-direction: column; | |
939 | +} | |
940 | + | |
941 | +.color-info strong { | |
942 | + font-size: 16px; | |
943 | + margin-bottom: 2px; | |
944 | +} | |
945 | + | |
946 | +.color-info span { | |
947 | + font-size: 14px; | |
948 | + color: var(--paper-text-muted); | |
949 | +} | |
950 | + | |
951 | +/* Tone Grid */ | |
952 | +.tone-grid { | |
953 | + display: grid; | |
954 | + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); | |
955 | + gap: 16px; | |
956 | + margin: 24px 0; | |
957 | +} | |
958 | + | |
959 | +.tone-card { | |
960 | + padding: 20px; | |
961 | + background: var(--paper-bg-secondary); | |
962 | + border: 1px solid var(--paper-border); | |
963 | + border-radius: 12px; | |
964 | + text-align: center; | |
965 | + transition: all 0.2s ease; | |
966 | +} | |
967 | + | |
968 | +.tone-card:hover { | |
969 | + transform: translateY(-2px); | |
970 | + box-shadow: var(--shadow-md); | |
971 | +} | |
972 | + | |
973 | +.tone-emoji { | |
974 | + font-size: 32px; | |
975 | + display: block; | |
976 | + margin-bottom: 8px; | |
977 | +} | |
978 | + | |
979 | +.tone-card h4 { | |
980 | + font-size: 15px; | |
981 | + font-weight: 600; | |
982 | + margin-bottom: 4px; | |
983 | +} | |
984 | + | |
985 | +.tone-card p { | |
986 | + font-size: 13px; | |
987 | + color: var(--paper-text-muted); | |
988 | + margin: 0; | |
989 | +} | |
990 | + | |
991 | +/* Tone Detail Grid */ | |
992 | +.tone-detail-grid { | |
993 | + display: grid; | |
994 | + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
995 | + gap: 20px; | |
996 | + margin: 24px 0; | |
997 | +} | |
998 | + | |
999 | +.tone-detail-card { | |
1000 | + padding: 24px; | |
1001 | + background: var(--paper-bg-secondary); | |
1002 | + border: 1px solid var(--paper-border); | |
1003 | + border-radius: 12px; | |
1004 | +} | |
1005 | + | |
1006 | +.tone-detail-header { | |
1007 | + display: flex; | |
1008 | + align-items: center; | |
1009 | + gap: 12px; | |
1010 | + margin-bottom: 12px; | |
1011 | +} | |
1012 | + | |
1013 | +.tone-detail-icon { | |
1014 | + font-size: 28px; | |
1015 | +} | |
1016 | + | |
1017 | +.tone-detail-header h3 { | |
1018 | + font-size: 18px; | |
1019 | + font-weight: 600; | |
1020 | + margin: 0; | |
1021 | +} | |
1022 | + | |
1023 | +.tone-detail-use { | |
1024 | + font-size: 14px; | |
1025 | + color: var(--paper-text-muted); | |
1026 | + margin-bottom: 16px; | |
1027 | +} | |
1028 | + | |
1029 | +.tone-detail-example { | |
1030 | + background: var(--paper-bg); | |
1031 | + border-radius: 8px; | |
1032 | + padding: 16px; | |
1033 | +} | |
1034 | + | |
1035 | +.example-input, | |
1036 | +.example-output { | |
1037 | + margin-bottom: 12px; | |
1038 | +} | |
1039 | + | |
1040 | +.example-input:last-child, | |
1041 | +.example-output:last-child { | |
1042 | + margin-bottom: 0; | |
1043 | +} | |
1044 | + | |
1045 | +.example-input .label, | |
1046 | +.example-output .label { | |
1047 | + font-size: 12px; | |
1048 | + font-weight: 600; | |
1049 | + color: var(--paper-text-muted); | |
1050 | + text-transform: uppercase; | |
1051 | + margin-bottom: 4px; | |
1052 | + display: block; | |
1053 | +} | |
1054 | + | |
1055 | +.example-output code { | |
1056 | + background: var(--green-50); | |
1057 | + border-color: var(--green-200); | |
1058 | + color: var(--green-700); | |
1059 | +} | |
1060 | + | |
1061 | +/* Metric Card */ | |
1062 | +.metric-card { | |
1063 | + background: var(--paper-bg-secondary); | |
1064 | + border: 1px solid var(--paper-border); | |
1065 | + border-radius: 12px; | |
1066 | + padding: 24px; | |
1067 | + margin: 24px 0; | |
1068 | +} | |
1069 | + | |
1070 | +.metric-header { | |
1071 | + display: flex; | |
1072 | + justify-content: space-between; | |
1073 | + align-items: center; | |
1074 | + margin-bottom: 16px; | |
1075 | +} | |
1076 | + | |
1077 | +.metric-header h4 { | |
1078 | + font-size: 18px; | |
1079 | + font-weight: 600; | |
1080 | + margin: 0; | |
1081 | +} | |
1082 | + | |
1083 | +.metric-badge { | |
1084 | + padding: 4px 10px; | |
1085 | + background: var(--primary-100); | |
1086 | + color: var(--primary-700); | |
1087 | + border-radius: 20px; | |
1088 | + font-size: 12px; | |
1089 | + font-weight: 600; | |
1090 | +} | |
1091 | + | |
1092 | +.metric-scale { | |
1093 | + display: flex; | |
1094 | + flex-direction: column; | |
1095 | + gap: 8px; | |
1096 | +} | |
1097 | + | |
1098 | +.scale-item { | |
1099 | + display: flex; | |
1100 | + gap: 12px; | |
1101 | + font-size: 14px; | |
1102 | +} | |
1103 | + | |
1104 | +.scale-item .range { | |
1105 | + font-family: var(--font-mono); | |
1106 | + font-weight: 600; | |
1107 | + color: var(--primary-600); | |
1108 | + min-width: 80px; | |
1109 | +} | |
1110 | + | |
1111 | +.scale-item .label { | |
1112 | + color: var(--paper-text-muted); | |
1113 | +} | |
1114 | + | |
1115 | +/* FAQ List */ | |
1116 | +.faq-list { | |
1117 | + display: flex; | |
1118 | + flex-direction: column; | |
1119 | + gap: 16px; | |
1120 | +} | |
1121 | + | |
1122 | +.faq-item { | |
1123 | + background: var(--paper-bg-secondary); | |
1124 | + border: 1px solid var(--paper-border); | |
1125 | + border-radius: 12px; | |
1126 | + overflow: hidden; | |
1127 | +} | |
1128 | + | |
1129 | +.faq-question { | |
1130 | + display: flex; | |
1131 | + justify-content: space-between; | |
1132 | + align-items: center; | |
1133 | + padding: 20px 24px; | |
1134 | + cursor: pointer; | |
1135 | + transition: all 0.2s ease; | |
1136 | +} | |
1137 | + | |
1138 | +.faq-question:hover { | |
1139 | + background: var(--paper-bg); | |
1140 | +} | |
1141 | + | |
1142 | +.faq-question h3 { | |
1143 | + font-size: 17px; | |
1144 | + font-weight: 600; | |
1145 | + margin: 0; | |
1146 | +} | |
1147 | + | |
1148 | +.faq-question svg { | |
1149 | + width: 20px; | |
1150 | + height: 20px; | |
1151 | + color: var(--paper-text-muted); | |
1152 | + transition: transform 0.2s ease; | |
1153 | +} | |
1154 | + | |
1155 | +.faq-item.active .faq-question svg { | |
1156 | + transform: rotate(180deg); | |
1157 | +} | |
1158 | + | |
1159 | +.faq-answer { | |
1160 | + padding: 0 24px; | |
1161 | + max-height: 0; | |
1162 | + overflow: hidden; | |
1163 | + transition: all 0.3s ease; | |
1164 | +} | |
1165 | + | |
1166 | +.faq-item.active .faq-answer { | |
1167 | + padding: 0 24px 20px; | |
1168 | + max-height: 500px; | |
1169 | +} | |
1170 | + | |
1171 | +/* Troubleshoot Card */ | |
1172 | +.troubleshoot-card { | |
1173 | + background: var(--paper-bg-secondary); | |
1174 | + border: 1px solid var(--paper-border); | |
1175 | + border-radius: 12px; | |
1176 | + padding: 24px; | |
1177 | + margin: 24px 0; | |
1178 | +} | |
1179 | + | |
1180 | +.troubleshoot-card h4 { | |
1181 | + font-size: 16px; | |
1182 | + font-weight: 600; | |
1183 | + margin: 20px 0 12px; | |
1184 | +} | |
1185 | + | |
1186 | +.troubleshoot-card h4:first-child { | |
1187 | + margin-top: 0; | |
1188 | +} | |
1189 | + | |
1190 | +.troubleshoot-card ul, | |
1191 | +.troubleshoot-card ol { | |
1192 | + margin: 12px 0 12px 24px; | |
1193 | +} | |
1194 | + | |
1195 | +/* Provider Comparison */ | |
1196 | +.provider-comparison { | |
1197 | + display: grid; | |
1198 | + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); | |
1199 | + gap: 20px; | |
1200 | + margin: 24px 0; | |
1201 | +} | |
1202 | + | |
1203 | +.provider-card-large { | |
1204 | + background: var(--paper-bg-secondary); | |
1205 | + border: 1px solid var(--paper-border); | |
1206 | + border-radius: 12px; | |
1207 | + padding: 24px; | |
1208 | + transition: all 0.2s ease; | |
1209 | +} | |
1210 | + | |
1211 | +.provider-card-large:hover { | |
1212 | + transform: translateY(-2px); | |
1213 | + box-shadow: var(--shadow-lg); | |
1214 | +} | |
1215 | + | |
1216 | +.provider-header { | |
1217 | + display: flex; | |
1218 | + align-items: center; | |
1219 | + gap: 12px; | |
1220 | + margin-bottom: 16px; | |
1221 | +} | |
1222 | + | |
1223 | +.provider-icon { | |
1224 | + font-size: 32px; | |
1225 | +} | |
1226 | + | |
1227 | +.provider-header h3 { | |
1228 | + font-size: 20px; | |
1229 | + font-weight: 700; | |
1230 | + margin: 0; | |
1231 | +} | |
1232 | + | |
1233 | +.provider-stats { | |
1234 | + display: flex; | |
1235 | + flex-direction: column; | |
1236 | + gap: 8px; | |
1237 | + margin-bottom: 16px; | |
1238 | +} | |
1239 | + | |
1240 | +.provider-stats .stat { | |
1241 | + font-size: 14px; | |
1242 | + color: var(--paper-text-muted); | |
1243 | +} | |
1244 | + | |
1245 | +.provider-desc { | |
1246 | + font-size: 14px; | |
1247 | + color: var(--paper-text); | |
1248 | + margin: 0; | |
1249 | +} | |
1250 | + | |
1251 | +/* Feature Grid 2 */ | |
1252 | +.feature-grid-2 { | |
1253 | + display: grid; | |
1254 | + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); | |
1255 | + gap: 20px; | |
1256 | + margin: 24px 0; | |
1257 | +} | |
1258 | + | |
1259 | +.feature-box { | |
1260 | + padding: 24px; | |
1261 | + background: var(--paper-bg-secondary); | |
1262 | + border: 1px solid var(--paper-border); | |
1263 | + border-radius: 12px; | |
1264 | +} | |
1265 | + | |
1266 | +.feature-box-icon { | |
1267 | + font-size: 32px; | |
1268 | + margin-bottom: 12px; | |
1269 | +} | |
1270 | + | |
1271 | +.feature-box h3 { | |
1272 | + font-size: 18px; | |
1273 | + font-weight: 600; | |
1274 | + margin-bottom: 8px; | |
1275 | +} | |
1276 | + | |
1277 | +.feature-box p { | |
1278 | + font-size: 15px; | |
1279 | + color: var(--paper-text-muted); | |
1280 | + margin: 0; | |
1281 | +} | |
1282 | + | |
1283 | +/* Feature List */ | |
1284 | +.feature-list { | |
1285 | + list-style: none; | |
1286 | + margin: 24px 0; | |
1287 | + padding: 0; | |
1288 | +} | |
1289 | + | |
1290 | +.feature-list li { | |
1291 | + display: flex; | |
1292 | + gap: 12px; | |
1293 | + margin-bottom: 16px; | |
1294 | + padding-left: 0; | |
1295 | +} | |
1296 | + | |
1297 | +.feature-list li::before { | |
1298 | + content: none; | |
1299 | +} | |
1300 | + | |
1301 | +.feature-list li svg { | |
1302 | + width: 20px; | |
1303 | + height: 20px; | |
1304 | + color: var(--green-500); | |
1305 | + flex-shrink: 0; | |
1306 | + margin-top: 2px; | |
1307 | +} | |
1308 | + | |
1309 | +.feature-list li ul { | |
1310 | + margin: 8px 0 0 32px; | |
1311 | +} | |
1312 | + | |
1313 | +/* Hero Card */ | |
1314 | +.hero-card { | |
1315 | + background: linear-gradient(135deg, var(--primary-50) 0%, var(--purple-50) 100%); | |
1316 | + border: 1px solid var(--primary-200); | |
1317 | + border-radius: 16px; | |
1318 | + padding: 32px; | |
1319 | + margin: 24px 0; | |
1320 | +} | |
1321 | + | |
1322 | +.hero-card-content h2 { | |
1323 | + font-size: 24px; | |
1324 | + font-weight: 700; | |
1325 | + margin: 0 0 12px; | |
1326 | +} | |
1327 | + | |
1328 | +.hero-card-content p { | |
1329 | + font-size: 16px; | |
1330 | + color: var(--paper-text-muted); | |
1331 | + margin: 0; | |
1332 | +} | |
1333 | + | |
1334 | +/* Section Nav */ | |
1335 | +.section-nav { | |
1336 | + display: flex; | |
1337 | + justify-content: space-between; | |
1338 | + margin-top: 64px; | |
1339 | + padding-top: 32px; | |
1340 | + border-top: 1px solid var(--paper-border); | |
1341 | +} | |
1342 | + | |
1343 | +.prev-link, | |
1344 | +.next-link { | |
1345 | + display: flex; | |
1346 | + align-items: center; | |
1347 | + gap: 8px; | |
1348 | + padding: 12px 20px; | |
1349 | + background: var(--paper-bg-secondary); | |
1350 | + border: 1px solid var(--paper-border); | |
1351 | + border-radius: 10px; | |
1352 | + color: var(--paper-text); | |
1353 | + text-decoration: none; | |
1354 | + font-size: 14px; | |
1355 | + font-weight: 500; | |
1356 | + transition: all 0.2s ease; | |
1357 | +} | |
1358 | + | |
1359 | +.prev-link:hover, | |
1360 | +.next-link:hover { | |
1361 | + background: var(--paper-bg); | |
1362 | + border-color: var(--primary-300); | |
1363 | +} | |
1364 | + | |
1365 | +.prev-link svg, | |
1366 | +.next-link svg { | |
1367 | + width: 18px; | |
1368 | + height: 18px; | |
1369 | +} | |
1370 | + | |
1371 | +/* API Endpoint */ | |
1372 | +.api-endpoint { | |
1373 | + display: flex; | |
1374 | + align-items: center; | |
1375 | + gap: 12px; | |
1376 | + margin: 16px 0; | |
1377 | +} | |
1378 | + | |
1379 | +.api-method { | |
1380 | + padding: 6px 12px; | |
1381 | + border-radius: 6px; | |
1382 | + font-size: 13px; | |
1383 | + font-weight: 700; | |
1384 | + font-family: var(--font-mono); | |
1385 | +} | |
1386 | + | |
1387 | +.api-method.get { | |
1388 | + background: var(--blue-100); | |
1389 | + color: var(--blue-700); | |
1390 | +} | |
1391 | + | |
1392 | +.api-method.post { | |
1393 | + background: var(--green-100); | |
1394 | + color: var(--green-700); | |
1395 | +} | |
1396 | + | |
1397 | +.api-path { | |
1398 | + font-family: var(--font-mono); | |
1399 | + font-size: 15px; | |
1400 | + font-weight: 600; | |
1401 | +} | |
1402 | + | |
1403 | +/* Highlight */ | |
1404 | +.highlight-red { | |
1405 | + color: var(--red-600); | |
1406 | + font-weight: 600; | |
1407 | +} | |
1408 | + | |
1409 | +/* Kbd */ | |
1410 | +kbd { | |
1411 | + display: inline-block; | |
1412 | + padding: 4px 8px; | |
1413 | + background: var(--paper-bg-secondary); | |
1414 | + border: 1px solid var(--paper-border); | |
1415 | + border-radius: 6px; | |
1416 | + font-family: var(--font-mono); | |
1417 | + font-size: 13px; | |
1418 | + color: var(--paper-text); | |
1419 | +} | |
1420 | + | |
1421 | +/* Footer */ | |
1422 | +.content-footer { | |
1423 | + padding: 48px 64px; | |
1424 | + border-top: 1px solid var(--paper-border); | |
1425 | + margin-top: 64px; | |
1426 | +} | |
1427 | + | |
1428 | +.footer-content { | |
1429 | + max-width: 1200px; | |
1430 | + text-align: center; | |
1431 | + color: var(--paper-text-muted); | |
1432 | + font-size: 14px; | |
1433 | +} | |
1434 | + | |
1435 | +.footer-content p { | |
1436 | + margin-bottom: 8px; | |
1437 | +} | |
1438 | + | |
1439 | +.footer-content a { | |
1440 | + color: var(--primary-600); | |
1441 | + text-decoration: none; | |
1442 | +} | |
1443 | + | |
1444 | +.footer-content a:hover { | |
1445 | + text-decoration: underline; | |
1446 | +} | |
1447 | + | |
1448 | +/* Responsive */ | |
1449 | +@media (max-width: 1024px) { | |
1450 | + .main-content { | |
1451 | + margin-left: 0; | |
1452 | + } | |
1453 | + | |
1454 | + .sidebar { | |
1455 | + transform: translateX(-100%); | |
1456 | + transition: transform 0.3s ease; | |
1457 | + } | |
1458 | + | |
1459 | + .sidebar.open { | |
1460 | + transform: translateX(0); | |
1461 | + } | |
1462 | + | |
1463 | + .menu-toggle { | |
1464 | + display: block; | |
1465 | + } | |
1466 | + | |
1467 | + .content-wrapper { | |
1468 | + padding: 32px 24px; | |
1469 | + } | |
1470 | + | |
1471 | + .content-header { | |
1472 | + padding: 0 24px; | |
1473 | + } | |
1474 | + | |
1475 | + .search-box { | |
1476 | + max-width: 100%; | |
1477 | + } | |
1478 | + | |
1479 | + .section-header h1 { | |
1480 | + font-size: 32px; | |
1481 | + } | |
1482 | +} | |
1483 | + | |
1484 | +@media (max-width: 768px) { | |
1485 | + .header-actions { | |
1486 | + gap: 8px; | |
1487 | + } | |
1488 | + | |
1489 | + .github-btn span { | |
1490 | + display: none; | |
1491 | + } | |
1492 | + | |
1493 | + .content-wrapper { | |
1494 | + padding: 24px 16px; | |
1495 | + } | |
1496 | + | |
1497 | + .content-footer { | |
1498 | + padding: 32px 16px; | |
1499 | + } | |
1500 | + | |
1501 | + .provider-cards, | |
1502 | + .provider-comparison, | |
1503 | + .feature-grid, | |
1504 | + .feature-grid-2, | |
1505 | + .tone-grid, | |
1506 | + .tone-detail-grid { | |
1507 | + grid-template-columns: 1fr; | |
1508 | + } | |
1509 | + | |
1510 | + .tab-buttons { | |
1511 | + flex-wrap: wrap; | |
1512 | + } | |
1513 | + | |
1514 | + .section-nav { | |
1515 | + flex-direction: column; | |
1516 | + gap: 12px; | |
1517 | + } | |
1518 | + | |
1519 | + .prev-link, | |
1520 | + .next-link { | |
1521 | + width: 100%; | |
1522 | + justify-content: center; | |
1523 | + } | |
1524 | +} | |
1525 | + | |
1526 | +/* Scrollbar */ | |
1527 | +::-webkit-scrollbar { | |
1528 | + width: 10px; | |
1529 | + height: 10px; | |
1530 | +} | |
1531 | + | |
1532 | +::-webkit-scrollbar-track { | |
1533 | + background: var(--paper-bg-secondary); | |
1534 | +} | |
1535 | + | |
1536 | +::-webkit-scrollbar-thumb { | |
1537 | + background: var(--paper-border); | |
1538 | + border-radius: 5px; | |
1539 | +} | |
1540 | + | |
1541 | +::-webkit-scrollbar-thumb:hover { | |
1542 | + background: var(--paper-text-muted); | |
1543 | +} | |
1544 | + | |
1545 | +/* Selection */ | |
1546 | +::selection { | |
1547 | + background: var(--primary-200); | |
1548 | + color: var(--primary-900); | |
1549 | +} | |
0 | 1550 | |