swadhinbiswas

[email protected]
2026-07-25 21:27:47 +0600 committed NaN years ago
921124f
commit 921124f
5 files changed
+550 -71
▼docs_site/astro.config.mjs
+2-1
17
17
},
18
18
social: [
19
19
{ icon: 'github', label: 'GitHub', href: 'https://github.com/swadhinbiswas/JustAPI' },
20
+ { icon: 'x.com', label: 'X (Twitter)', href: 'https://x.com/justapidev' },
20
21
],
21
22
customCss: ['./src/styles/custom.css'],
22
23
editLink: {
76
77
url: site,
77
78
downloadUrl: 'https://pypi.org/project/justapi/',
78
79
installUrl: 'https://pypi.org/project/justapi/',
79
- softwareVersion: '2.0.0',
80
+ softwareVersion: '2.0.8',
80
81
offers: {
81
82
'@type': 'Offer',
82
83
price: '0',
83
84
▼docs_site/public/_headers
+16-0
1
+/*
2
+ X-Frame-Options: DENY
3
+ X-Content-Type-Options: nosniff
4
+ Referrer-Policy: strict-origin-when-cross-origin
5
+ Permissions-Policy: camera=(), microphone=(), geolocation=()
6
+ Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data:
7
+ Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
8
+
9
+/_astro/*
10
+ Cache-Control: public, max-age=31536000, immutable
11
+
12
+/*.html
13
+ Cache-Control: public, max-age=0, must-revalidate
14
+
15
+/sitemap-index.xml
16
+ Cache-Control: public, max-age=86400
0
17
▼docs_site/public/robots.txt
+7-0
1
+User-agent: *
2
+Allow: /
3
+
4
+Sitemap: https://justapi.dev/sitemap-index.xml
5
+
6
+# Disallow admin/private paths
7
+Disallow: /_astro/
0
8
▼docs_site/src/content/docs/index.mdx
+88-18
1
1
---
2
-title: JustAPI Documentation
3
-description: JustAPI — the fastest FastAPI alternative. A Rust-powered Python web framework with 700k+ RPS, zero-GIL execution, and drop-in FastAPI compatibility. The production-grade FastAPI replacement.
2
+title: JustAPI Documentation — The Fastest FastAPI Alternative
3
+description: JustAPI — a Rust-powered Python web framework. Drop-in FastAPI replacement with 700k+ RPS, zero-GIL execution, and automatic OpenAPI docs.
4
4
template: splash
5
5
hero:
6
6
tagline: The speed of Rust. The elegance of Python. A drop-in replacement for FastAPI engineered for extreme throughput.
11
11
link: /getting-started/overview/
12
12
icon: right-arrow
13
13
variant: primary
14
+ - text: Tutorial — User Guide
15
+ link: /tutorials/python-types/
16
+ icon: open-book
17
+ variant: minimal
14
18
- text: View on GitHub
15
19
link: https://github.com/swadhinbiswas/JustAPI
16
20
icon: external
21
+ variant: minimal
17
22
---
18
23
19
24
import { Card, CardGrid } from '@astrojs/starlight/components';
20
25
21
-## Key Features
26
+## Why JustAPI?
27
+
28
+JustAPI moves the entire networking stack out of Python. Same FastAPI syntax. Same Pydantic models. 20× the throughput.
22
29
23
30
<CardGrid stack>
24
- <Card title="⚡ 700,000+ Requests / Sec" icon="rocket">
25
- 20× faster than FastAPI + Uvicorn. Networking, TLS, routing, schema validation, and JSON serialization run entirely in Rust at native speed.
31
+ <Card title="700,000+ Requests / Sec" icon="rocket">
32
+ Networking, TLS, routing, schema validation, and JSON serialization run entirely in Rust at native speed. 20× faster than FastAPI + Uvicorn.
26
33
</Card>
27
- <Card title="🐍 FastAPI Compatibility" icon="star">
28
- Same `@app.get()` decorators, same Pydantic v2 schemas, same `Depends()` dependency injection. Easily migrate existing FastAPI applications.
34
+ <Card title="FastAPI Compatibility" icon="star">
35
+ Same `@app.get()` decorators, same Pydantic v2 schemas, same `Depends()` dependency injection. Migrate existing FastAPI applications with one import change.
29
36
</Card>
30
- <Card title="🛡️ Zero-GIL Fast Path" icon="shield">
31
- Rust code releases the Python GIL via `py.allow_threads` during all I/O, routing, DB queries, and validation. Fully supports Python 3.13t/3.14t free-threading.
37
+ <Card title="Zero-GIL Fast Path" icon="shield">
38
+ Rust releases the Python GIL during all I/O, routing, and validation. Fully supports Python 3.13t/3.14t free-threading. Native fast path at 724k+ RPS.
32
39
</Card>
33
- <Card title="🗄️ Multi-Database & Multi-Protocol" icon="setting">
34
- Natively supports SQL (Postgres, MySQL, SQLite), Analytical OLAP (DuckDB, ClickHouse), NoSQL (Mongo, Redis), and REST, GraphQL, gRPC, and JSON-RPC 2.0.
40
+ <Card title="Multi-Database & Multi-Protocol" icon="setting">
41
+ SQL (Postgres, MySQL, SQLite), OLAP (DuckDB), NoSQL (Redis, MongoDB), and REST, GraphQL, gRPC, JSON-RPC 2.0 — all in one framework.
35
42
</Card>
36
43
</CardGrid>
37
44
38
-## Live Benchmark Comparison
45
+## Performance
39
46
40
47
| Framework | Requests/sec | p50 Latency | p99 Latency |
41
48
|---|--:|--:|--:|
42
-| **JustAPI 🦀** | **701,234** | **0.07 ms** | **0.19 ms** |
49
+| **JustAPI (native fast path)** | **701,234** | **0.07 ms** | **0.19 ms** |
50
+| **JustAPI (Python handler)** | **60,297** | **1.03 ms** | **5.21 ms** |
51
+| Robyn 0.88 | 39,103 | 1.78 ms | 11.47 ms |
43
52
| Granian | 69,195 | 0.72 ms | 3.87 ms |
44
53
| FastAPI + Uvicorn | 36,189 | 1.72 ms | 24.63 ms |
45
54
46
-## Quick Example
55
+All measurements on the same hardware (i5-13600K, 20 threads), 100 concurrent connections, 30s duration. See [Benchmarks](/reference/adr-index/) for methodology.
56
+
57
+## Quick Start
47
58
48
59
```python
49
60
from justapi import JustAPIApp
50
61
51
-app = JustAPIApp(title="My High-Speed API")
62
+app = JustAPIApp(title="My API")
52
63
53
64
@app.get("/")
54
-def hello(request):
55
- return {"message": "Hello from Rust-powered JustAPI!"}
65
+def hello():
66
+ return {"message": "Hello from JustAPI!"}
56
67
57
68
@app.get("/items/{item_id}")
58
-def read_item(request, item_id: int, q: str | None = None):
69
+def read_item(item_id: int, q: str | None = None):
59
70
return {"item_id": item_id, "q": q}
60
71
```
72
+
73
+```bash
74
+pip install justapi
75
+python main.py
76
+```
77
+
78
+Open [http://localhost:8000/docs](http://localhost:8000/docs) for interactive Swagger UI documentation.
79
+
80
+## Learn
81
+
82
+<CardGrid>
83
+ <Card title="Python Types" icon="pencil">
84
+ [Type hints, Pydantic models, validation →](/tutorials/python-types/)
85
+ </Card>
86
+ <Card title="Async / Await" icon="moon">
87
+ [Concurrency model, when to use async →](/tutorials/async-await/)
88
+ </Card>
89
+ <Card title="Path & Query" icon="list">
90
+ [Parameters, validation, constraints →](/tutorials/path-params/)
91
+ </Card>
92
+ <Card title="Request Body" icon="document">
93
+ [Pydantic, nested models, fields →](/tutorials/request-body/)
94
+ </Card>
95
+ <Card title="Dependencies" icon="puzzle">
96
+ [DI, sub-dependencies, yield cleanup →](/tutorials/dependencies/classes-as-dependencies/)
97
+ </Card>
98
+ <Card title="Security" icon="lock">
99
+ [OAuth2, JWT, API keys →](/tutorials/security/first-steps/)
100
+ </Card>
101
+</CardGrid>
102
+
103
+## Install
104
+
105
+```bash
106
+# pip
107
+pip install justapi
108
+
109
+# uv (recommended)
110
+uv pip install justapi
111
+
112
+# run without installing
113
+uvx justapi create my_app
114
+```
115
+
116
+## Migration
117
+
118
+Migrating from FastAPI? One import change:
119
+
120
+```python
121
+# Before (FastAPI)
122
+from fastapi import FastAPI
123
+app = FastAPI()
124
+
125
+# After (JustAPI)
126
+from justapi import JustAPIApp
127
+app = JustAPIApp()
128
+```
129
+
130
+Everything else stays the same — decorators, Pydantic models, dependency injection, OpenAPI docs.
61
131
▼docs_site/src/styles/custom.css
+437-52
1
+/* ═══════════════════════════════════════════════════════════════════
2
+ JustAPI Documentation — Design System
3
+ Premium, FastAPI-level documentation styling
4
+ ═══════════════════════════════════════════════════════════════════ */
5
+
6
+/* ─── Custom Properties ─── */
1
7
:root {
8
+ /* Accent palette */
2
9
--sl-color-accent-low: #2a1147;
3
10
--sl-color-accent: #8b5cf6;
4
11
--sl-color-accent-high: #c4b5fd;
12
+
13
+ /* Neutrals */
5
14
--sl-color-white: #ffffff;
6
- --sl-color-gray-1: #f3f4f6;
7
- --sl-color-gray-2: #e5e7eb;
8
- --sl-color-gray-3: #9ca3af;
9
- --sl-color-gray-4: #4b5563;
10
- --sl-color-gray-5: #1f2937;
11
- --sl-color-gray-6: #111827;
12
- --sl-color-black: #0b0f19;
15
+ --sl-color-gray-1: #f8fafc;
16
+ --sl-color-gray-2: #f1f5f9;
17
+ --sl-color-gray-3: #94a3b8;
18
+ --sl-color-gray-4: #64748b;
19
+ --sl-color-gray-5: #334155;
20
+ --sl-color-gray-6: #1e293b;
21
+ --sl-color-black: #020617;
22
+
23
+ /* Brand */
13
24
--sl-color-orange: #e6522c;
14
25
--sl-color-blue: #3b82f6;
26
+ --sl-color-green: #10b981;
27
+ --sl-color-red: #ef4444;
28
+ --sl-color-yellow: #f59e0b;
29
+
30
+ /* Typography */
31
+ --sl-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
32
+ --sl-font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'SF Mono', monospace;
33
+
34
+ /* Spacing */
35
+ --sl-content-width: 72rem;
36
+ --sl-sidebar-width: 18rem;
37
+ --sl-toc-width: 14rem;
15
38
}
16
39
40
+/* ─── Dark Mode ─── */
17
41
[data-theme='dark'] {
18
- --sl-color-bg: #0b0f19;
19
- --sl-color-bg-nav: #111827;
42
+ --sl-color-bg: #020617;
43
+ --sl-color-bg-nav: #0f172a;
20
44
--sl-color-bg-sidebar: #0f172a;
45
+ --sl-color-bg-hover: #1e293b;
46
+ --sl-color-text: #e2e8f0;
47
+ --sl-color-text-muted: #94a3b8;
48
+ --sl-color-border: #1e293b;
21
49
}
22
50
23
-.hero-gradient {
24
- background: linear-gradient(135deg, #e6522c 0%, #8b5cf6 50%, #3b82f6 100%);
25
- -webkit-background-clip: text;
26
- -webkit-text-fill-color: transparent;
27
- background-clip: text;
51
+/* ─── Light Mode ─── */
52
+[data-theme='light'] {
53
+ --sl-color-bg: #ffffff;
54
+ --sl-color-bg-nav: #f8fafc;
55
+ --sl-color-bg-sidebar: #f8fafc;
56
+ --sl-color-bg-hover: #f1f5f9;
57
+ --sl-color-text: #1e293b;
58
+ --sl-color-text-muted: #64748b;
59
+ --sl-color-border: #e2e8f0;
28
60
}
29
61
30
-.benchmark-card {
31
- border: 1px solid rgba(139, 92, 246, 0.3);
32
- border-radius: 12px;
33
- padding: 1.5rem;
34
- background: rgba(17, 24, 39, 0.7);
35
- backdrop-filter: blur(12px);
36
- margin-bottom: 1.5rem;
62
+/* ─── Global Typography ─── */
63
+html {
64
+ font-family: var(--sl-font);
65
+ -webkit-font-smoothing: antialiased;
66
+ -moz-osx-font-smoothing: grayscale;
67
+ text-rendering: optimizeLegibility;
68
+ scroll-behavior: smooth;
37
69
}
38
70
39
-.site-title {
40
- font-weight: 700;
71
+body {
72
+ line-height: 1.7;
73
+ letter-spacing: -0.011em;
74
+}
75
+
76
+/* ─── Headings ─── */
77
+.content h1 {
78
+ font-size: 2.25rem;
79
+ font-weight: 800;
80
+ letter-spacing: -0.025em;
81
+ line-height: 1.2;
82
+ margin-bottom: 1rem;
41
83
}
42
84
43
85
.content h2 {
44
- margin-top: 2.5rem;
45
- border-bottom: 1px solid var(--sl-color-gray-5);
46
- padding-bottom: 0.5rem;
86
+ font-size: 1.5rem;
87
+ font-weight: 700;
88
+ letter-spacing: -0.02em;
89
+ margin-top: 3rem;
90
+ margin-bottom: 1rem;
91
+ padding-bottom: 0.75rem;
92
+ border-bottom: 1px solid var(--sl-color-border, #e2e8f0);
47
93
}
48
94
49
95
.content h3 {
96
+ font-size: 1.2rem;
97
+ font-weight: 600;
50
98
margin-top: 2rem;
99
+ margin-bottom: 0.75rem;
100
+ letter-spacing: -0.01em;
101
+}
102
+
103
+.content h4 {
104
+ font-size: 1rem;
105
+ font-weight: 600;
106
+ margin-top: 1.5rem;
107
+}
108
+
109
+/* ─── Links ─── */
110
+.content a {
111
+ color: var(--sl-color-accent);
112
+ text-decoration: none;
113
+ transition: color 0.15s ease;
114
+}
115
+
116
+.content a:hover {
117
+ color: var(--sl-color-accent-high);
118
+ text-decoration: underline;
119
+ text-decoration-thickness: 2px;
120
+ text-underline-offset: 3px;
121
+}
122
+
123
+/* ─── Code Blocks ─── */
124
+code {
125
+ font-family: var(--sl-font-mono);
126
+ font-size: 0.85em;
127
+ border-radius: 6px;
128
+ padding: 0.15em 0.4em;
129
+ background: var(--sl-color-gray-2, #f1f5f9);
51
130
}
52
131
132
+[data-theme='dark'] code {
133
+ background: rgba(139, 92, 246, 0.15);
134
+ color: #c4b5fd;
135
+}
136
+
137
+pre {
138
+ font-family: var(--sl-font-mono);
139
+ font-size: 0.875rem;
140
+ line-height: 1.6;
141
+ border-radius: 12px;
142
+ border: 1px solid var(--sl-color-border, #e2e8f0);
143
+ padding: 1.25rem;
144
+ overflow-x: auto;
145
+ background: #0f172a !important;
146
+}
147
+
148
+[data-theme='dark'] pre {
149
+ background: #0b0f19 !important;
150
+ border-color: #1e293b;
151
+}
152
+
153
+pre code {
154
+ background: none;
155
+ padding: 0;
156
+ border-radius: 0;
157
+}
158
+
159
+/* ─── Tables ─── */
53
160
.content table {
161
+ width: 100%;
54
162
font-size: 0.875rem;
163
+ border-collapse: separate;
164
+ border-spacing: 0;
165
+ border-radius: 12px;
166
+ overflow: hidden;
167
+ border: 1px solid var(--sl-color-border, #e2e8f0);
168
+ margin: 1.5rem 0;
169
+}
170
+
171
+.content thead {
172
+ background: var(--sl-color-gray-6, #1e293b);
173
+}
174
+
175
+[data-theme='dark'] .content thead {
176
+ background: #1e293b;
177
+}
178
+
179
+[data-theme='light'] .content thead {
180
+ background: #f1f5f9;
55
181
}
56
182
57
183
.content th {
58
- background: var(--sl-color-gray-6);
59
184
font-weight: 600;
185
+ text-align: left;
186
+ padding: 0.75rem 1rem;
187
+ border-bottom: 2px solid var(--sl-color-border, #e2e8f0);
60
188
}
61
189
62
-.content td,
63
-.content th {
64
- border-color: var(--sl-color-gray-5);
190
+.content td {
191
+ padding: 0.75rem 1rem;
192
+ border-bottom: 1px solid var(--sl-color-border, #e2e8f0);
193
+}
194
+
195
+.content tbody tr:last-child td {
196
+ border-bottom: none;
197
+}
198
+
199
+.content tbody tr:hover {
200
+ background: var(--sl-color-bg-hover, #f8fafc);
201
+}
202
+
203
+/* ─── Callouts / Asides ─── */
204
+.starlight-aside {
205
+ border-radius: 12px;
206
+ border-left-width: 4px;
207
+ padding: 1rem 1.25rem;
208
+ margin: 1.5rem 0;
65
209
}
66
210
211
+.starlight-aside--note {
212
+ border-left-color: var(--sl-color-blue);
213
+ background: rgba(59, 130, 246, 0.05);
214
+}
215
+
216
+.starlight-aside--tip {
217
+ border-left-color: var(--sl-color-green);
218
+ background: rgba(16, 185, 129, 0.05);
219
+}
220
+
221
+.starlight-aside--caution {
222
+ border-left-color: var(--sl-color-yellow);
223
+ background: rgba(245, 158, 11, 0.05);
224
+}
225
+
226
+.starlight-aside--danger {
227
+ border-left-color: var(--sl-color-red);
228
+ background: rgba(239, 68, 68, 0.05);
229
+}
230
+
231
+/* ─── Hero Gradient ─── */
232
+.hero-gradient {
233
+ background: linear-gradient(135deg, #e6522c 0%, #8b5cf6 50%, #3b82f6 100%);
234
+ -webkit-background-clip: text;
235
+ -webkit-text-fill-color: transparent;
236
+ background-clip: text;
237
+}
238
+
239
+/* ─── Feature Grid ─── */
67
240
.feature-grid {
68
241
display: grid;
69
242
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
72
245
}
73
246
74
247
.feature-card {
75
- border: 1px solid var(--sl-color-gray-5);
76
- border-radius: 12px;
77
- padding: 1.5rem;
78
- background: var(--sl-color-gray-6);
79
- transition: border-color 0.2s, transform 0.2s;
248
+ border: 1px solid var(--sl-color-border, #e2e8f0);
249
+ border-radius: 16px;
250
+ padding: 1.75rem;
251
+ background: var(--sl-color-bg, #ffffff);
252
+ transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
253
+ position: relative;
254
+ overflow: hidden;
255
+}
256
+
257
+.feature-card::before {
258
+ content: '';
259
+ position: absolute;
260
+ top: 0;
261
+ left: 0;
262
+ right: 0;
263
+ height: 3px;
264
+ background: linear-gradient(90deg, var(--sl-color-accent), var(--sl-color-blue));
265
+ opacity: 0;
266
+ transition: opacity 0.25s ease;
80
267
}
81
268
82
269
.feature-card:hover {
83
270
border-color: var(--sl-color-accent);
84
- transform: translateY(-2px);
271
+ transform: translateY(-4px);
272
+ box-shadow: 0 20px 40px -12px rgba(139, 92, 246, 0.15);
273
+}
274
+
275
+.feature-card:hover::before {
276
+ opacity: 1;
85
277
}
86
278
87
279
.feature-card h3 {
88
280
margin-top: 0;
89
281
font-size: 1.1rem;
282
+ font-weight: 600;
283
+}
284
+
285
+/* ─── Benchmark Card ─── */
286
+.benchmark-card {
287
+ border: 1px solid rgba(139, 92, 246, 0.3);
288
+ border-radius: 16px;
289
+ padding: 1.75rem;
290
+ background: rgba(17, 24, 39, 0.7);
291
+ backdrop-filter: blur(16px);
292
+ margin-bottom: 1.5rem;
293
+ position: relative;
294
+ overflow: hidden;
90
295
}
91
296
297
+.benchmark-card::before {
298
+ content: '';
299
+ position: absolute;
300
+ top: 0;
301
+ left: 0;
302
+ right: 0;
303
+ height: 2px;
304
+ background: linear-gradient(90deg, var(--sl-color-orange), var(--sl-color-accent), var(--sl-color-blue));
305
+}
306
+
307
+/* ─── Performance Table ─── */
92
308
.performance-table {
93
309
width: 100%;
94
- border-collapse: collapse;
310
+ border-collapse: separate;
311
+ border-spacing: 0;
312
+ border-radius: 12px;
313
+ overflow: hidden;
314
+ border: 1px solid var(--sl-color-border, #e2e8f0);
95
315
}
96
316
97
317
.performance-table th {
98
318
text-align: left;
99
- padding: 0.75rem 1rem;
319
+ padding: 1rem 1.25rem;
320
+ font-weight: 600;
321
+ background: var(--sl-color-gray-6, #1e293b);
100
322
}
101
323
102
324
.performance-table td {
103
- padding: 0.75rem 1rem;
325
+ padding: 1rem 1.25rem;
104
326
text-align: right;
105
327
}
106
328
112
334
.performance-table .winner {
113
335
color: var(--sl-color-accent-high);
114
336
font-weight: 700;
337
+ font-size: 1.1em;
115
338
}
116
339
117
-code {
118
- font-size: 0.85em;
340
+.performance-table tbody tr:hover {
341
+ background: var(--sl-color-bg-hover, #f8fafc);
342
+}
343
+
344
+/* ─── Sidebar ─── */
345
+.sidebar-title {
346
+ font-weight: 700;
347
+ font-size: 0.8rem;
348
+ text-transform: uppercase;
349
+ letter-spacing: 0.05em;
350
+ color: var(--sl-color-text-muted, #64748b);
351
+}
352
+
353
+/* ─── Badge Styling ─── */
354
+.badge--success {
355
+ background: rgba(16, 185, 129, 0.15);
356
+ color: var(--sl-color-green);
357
+ border: 1px solid rgba(16, 185, 129, 0.3);
358
+ border-radius: 9999px;
359
+ padding: 0.15em 0.6em;
360
+ font-size: 0.75rem;
361
+ font-weight: 600;
362
+}
363
+
364
+/* ─── Card Grid Overrides ─── */
365
+.sl-card-grid {
366
+ gap: 1.25rem;
367
+}
368
+
369
+.sl-card {
370
+ border-radius: 12px;
371
+ border: 1px solid var(--sl-color-border, #e2e8f0);
372
+ transition: all 0.2s ease;
373
+}
374
+
375
+.sl-card:hover {
376
+ border-color: var(--sl-color-accent);
377
+ box-shadow: 0 8px 24px -8px rgba(139, 92, 246, 0.12);
378
+}
379
+
380
+/* ─── TOC (Table of Contents) ─── */
381
+.toc-panel {
382
+ font-size: 0.85rem;
383
+}
384
+
385
+.toc-panel a {
386
+ transition: color 0.15s ease;
387
+}
388
+
389
+/* ─── Breadcrumbs ─── */
390
+.breadcrumbs a {
391
+ font-size: 0.85rem;
392
+ color: var(--sl-color-text-muted, #64748b);
393
+ transition: color 0.15s ease;
394
+}
395
+
396
+.breadcrumbs a:hover {
397
+ color: var(--sl-color-accent);
398
+}
399
+
400
+/* ─── Navigation (Prev/Next) ─── */
401
+.prev-next-nav a {
402
+ border-radius: 12px;
403
+ transition: all 0.2s ease;
404
+ border: 1px solid var(--sl-color-border, #e2e8f0);
405
+}
406
+
407
+.prev-next-nav a:hover {
408
+ border-color: var(--sl-color-accent);
409
+ box-shadow: 0 4px 12px -4px rgba(139, 92, 246, 0.15);
410
+}
411
+
412
+/* ─── Search ─── */
413
+.search-input {
414
+ border-radius: 10px !important;
415
+ font-size: 0.9rem !important;
416
+}
417
+
418
+/* ─── Mobile Responsive ─── */
419
+@media (max-width: 768px) {
420
+ .content h1 {
421
+ font-size: 1.75rem;
422
+ }
423
+
424
+ .content h2 {
425
+ font-size: 1.3rem;
426
+ }
427
+
428
+ .feature-grid {
429
+ grid-template-columns: 1fr;
430
+ }
431
+
432
+ .performance-table {
433
+ font-size: 0.8rem;
434
+ }
435
+
436
+ .performance-table th,
437
+ .performance-table td {
438
+ padding: 0.5rem 0.75rem;
439
+ }
440
+}
441
+
442
+/* ─── Print Styles ─── */
443
+@media print {
444
+ .sidebar,
445
+ .toc-panel,
446
+ .edit-link,
447
+ .prev-next-nav {
448
+ display: none !important;
449
+ }
450
+
451
+ .content {
452
+ max-width: 100%;
453
+ }
454
+}
455
+
456
+/* ─── Focus Styles (Accessibility) ─── */
457
+:focus-visible {
458
+ outline: 2px solid var(--sl-color-accent);
459
+ outline-offset: 2px;
119
460
border-radius: 4px;
120
461
}
121
462
122
-pre {
123
- border-radius: 8px;
124
- border: 1px solid var(--sl-color-gray-5);
463
+/* ─── Selection ─── */
464
+::selection {
465
+ background: rgba(139, 92, 246, 0.3);
466
+ color: var(--sl-color-white);
125
467
}
126
468
127
-.starlight-aside {
128
- border-radius: 8px;
469
+[data-theme='light'] ::selection {
470
+ background: rgba(139, 92, 246, 0.2);
471
+ color: var(--sl-color-black);
129
472
}
130
473
131
-.starlight-aside--note {
132
- border-left-color: var(--sl-color-blue);
474
+/* ─── Scrollbar ─── */
475
+::-webkit-scrollbar {
476
+ width: 8px;
477
+ height: 8px;
133
478
}
134
479
135
-.starlight-aside--tip {
136
- border-left-color: var(--sl-color-accent);
480
+::-webkit-scrollbar-track {
481
+ background: transparent;
137
482
}
138
483
139
-.starlight-aside--caution {
140
- border-left-color: var(--sl-color-orange);
484
+::-webkit-scrollbar-thumb {
485
+ background: var(--sl-color-gray-4, #64748b);
486
+ border-radius: 4px;
487
+}
488
+
489
+::-webkit-scrollbar-thumb:hover {
490
+ background: var(--sl-color-gray-3, #94a3b8);
491
+}
492
+
493
+/* ─── Animations ─── */
494
+@keyframes fadeInUp {
495
+ from {
496
+ opacity: 0;
497
+ transform: translateY(12px);
498
+ }
499
+ to {
500
+ opacity: 1;
501
+ transform: translateY(0);
502
+ }
503
+}
504
+
505
+.content > * {
506
+ animation: fadeInUp 0.3s ease-out;
507
+}
508
+
509
+/* ─── Starlight Overrides ─── */
510
+.starlight-sidebar > div {
511
+ border-right: 1px solid var(--sl-color-border, #e2e8f0);
512
+}
513
+
514
+/* ─── Code Group Tabs ─── */
515
+.tab-label {
516
+ font-family: var(--sl-font-mono);
517
+ font-size: 0.8rem;
518
+}
519
+
520
+/* ─── Gradient Text Utility ─── */
521
+.gradient-text {
522
+ background: linear-gradient(135deg, #e6522c, #8b5cf6, #3b82f6);
523
+ -webkit-background-clip: text;
524
+ -webkit-text-fill-color: transparent;
525
+ background-clip: text;
141
526
}
142
527