π¨ docs: shadcn-style UI redesign β anime.js animations (counters, reveal, bars, terminal), tabs, readable typography, clean landing
swadhinbiswas committed 2 months ago
4705f15
1 parent 9eee375
commit 4705f15
8 files changed
+791 -691
Showing 8 changed files+791-691
βΌ.gitignore
+1-0
| @@ -146,3 +146,4 @@ wheels/ | ||
146 | 146 | |
147 | 147 | # Debugging artifacts |
148 | 148 | benchmarks/gdb_out.txt |
149 | +.wrangler/ | |
149 | 150 | |
βΌdocs_site/astro.config.mjs
+3-0
| @@ -26,6 +26,9 @@ export default defineConfig({ | ||
26 | 26 | { icon: 'x.com', label: 'X (Twitter)', href: 'https://x.com/justapidev' }, |
27 | 27 | ], |
28 | 28 | customCss: ['./src/styles/custom.css'], |
29 | + components: { | |
30 | + PageFrame: './src/components/PageFrame.astro', | |
31 | + }, | |
29 | 32 | editLink: { |
30 | 33 | baseUrl: 'https://github.com/swadhinbiswas/JustAPI/edit/main/docs_site', |
31 | 34 | }, |
32 | 35 | |
βΌdocs_site/package-lock.json
+26-0
| @@ -10,7 +10,11 @@ | ||
10 | 10 | "dependencies": { |
11 | 11 | "@astrojs/sitemap": "^3.7.3", |
12 | 12 | "@astrojs/starlight": "^0.41.4", |
13 | + "animejs": "^4.5.0", | |
13 | 14 | "astro": "^7.1.3" |
15 | + }, | |
16 | + "engines": { | |
17 | + "node": ">=22.12.0" | |
14 | 18 | } |
15 | 19 | }, |
16 | 20 | "node_modules/@astrojs/compiler-binding": { |
| @@ -2305,6 +2309,28 @@ | ||
2305 | 2309 | "am-i-vibing": "dist/cli.mjs" |
2306 | 2310 | } |
2307 | 2311 | }, |
2312 | + "node_modules/animejs": { | |
2313 | + "version": "4.5.0", | |
2314 | + "resolved": "https://registry.npmmirror.com/animejs/-/animejs-4.5.0.tgz", | |
2315 | + "integrity": "sha512-NQimYX+lz8WaXonGS9zVVoviCIAjONeJayxacUditaivYLqyXgGjFKjuyl0aUUhFKm5MriX9ty1TGovNzoJQWA==", | |
2316 | + "license": "MIT", | |
2317 | + "funding": { | |
2318 | + "type": "github", | |
2319 | + "url": "https://github.com/sponsors/juliangarnier" | |
2320 | + }, | |
2321 | + "peerDependencies": { | |
2322 | + "@types/three": ">=0.150.0", | |
2323 | + "three": ">=0.150.0" | |
2324 | + }, | |
2325 | + "peerDependenciesMeta": { | |
2326 | + "@types/three": { | |
2327 | + "optional": true | |
2328 | + }, | |
2329 | + "three": { | |
2330 | + "optional": true | |
2331 | + } | |
2332 | + } | |
2333 | + }, | |
2308 | 2334 | "node_modules/anymatch": { |
2309 | 2335 | "version": "3.1.3", |
2310 | 2336 | "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz", |
2311 | 2337 | |
βΌdocs_site/package.json
+1-0
| @@ -12,6 +12,7 @@ | ||
12 | 12 | "dependencies": { |
13 | 13 | "@astrojs/sitemap": "^3.7.3", |
14 | 14 | "@astrojs/starlight": "^0.41.4", |
15 | + "animejs": "^4.5.0", | |
15 | 16 | "astro": "^7.1.3" |
16 | 17 | }, |
17 | 18 | "engines": { |
18 | 19 | |
βΌdocs_site/src/components/PageFrame.astro
+9-0
| @@ -0,0 +1,9 @@ | ||
1 | +--- | |
2 | +import PageFrame from '@astrojs/starlight/components/PageFrame.astro'; | |
3 | +--- | |
4 | +<PageFrame> | |
5 | + <script> | |
6 | + import '../scripts/animations.js'; | |
7 | + </script> | |
8 | + <slot /> | |
9 | +</PageFrame> | |
0 | 10 | |
βΌdocs_site/src/content/docs/index.mdx
+154-94
| @@ -1,124 +1,187 @@ | ||
1 | 1 | --- |
2 | 2 | title: JustAPI |
3 | -description: Python web framework powered by Rust. 766k req/s. Built to handle real traffic. | |
3 | +description: Python web framework powered by Rust. 766k req/s hello-world. FastAPI-compatible API, zero-config OpenAPI. | |
4 | 4 | template: splash |
5 | -hero: | |
6 | - tagline: Python web framework. Rust engine underneath. | |
7 | - image: | |
8 | - file: ../../assets/logo.svg | |
9 | - actions: | |
10 | - - text: Get Started | |
11 | - link: /getting-started/overview/ | |
12 | - icon: right-arrow | |
13 | - variant: primary | |
14 | - - text: GitHub | |
15 | - link: https://github.com/swadhinbiswas/JustAPI | |
16 | - icon: external | |
17 | - variant: minimal | |
18 | 5 | --- |
19 | 6 | |
20 | -<div class="ja-hero"> | |
21 | - <img src="/og-image.png" alt="JustAPI β Python writes the logic. Rust does everything else." width="100%" /> | |
7 | +<div class="ja-hero" data-reveal> | |
8 | + <div class="ja-hero-badge"> | |
9 | + <span class="dot"></span> | |
10 | + v2.0.9 Β· published on PyPI Β· 8 platforms | |
11 | + </div> | |
12 | + <h1 data-hero-title> | |
13 | + Python writes the logic.<br/> | |
14 | + <span class="grad">Rust does everything else.</span> | |
15 | + </h1> | |
16 | + <p class="ja-hero-sub"> | |
17 | + JustAPI is a Python web framework with a Rust core. One import, zero config β | |
18 | + routing, TLS, validation, serialization and the server itself run in Rust. | |
19 | + </p> | |
20 | + <div class="ja-hero-actions"> | |
21 | + <a class="ja-btn ja-btn--primary" href="/getting-started/overview/">Get Started β</a> | |
22 | + <a class="ja-btn ja-btn--ghost" href="https://github.com/swadhinbiswas/JustAPI" target="_blank">GitHub β</a> | |
23 | + </div> | |
24 | +</div> | |
25 | + | |
26 | +<div class="ja-stats" data-reveal-group> | |
27 | + <div class="ja-stat" data-reveal-item> | |
28 | + <div class="ja-stat-value" data-count="766" data-suffix="k">0</div> | |
29 | + <div class="ja-stat-label">req/s hello-world</div> | |
30 | + </div> | |
31 | + <div class="ja-stat" data-reveal-item> | |
32 | + <div class="ja-stat-value" data-count="782" data-suffix="k">0</div> | |
33 | + <div class="ja-stat-label">req/s JSON echo</div> | |
34 | + </div> | |
35 | + <div class="ja-stat" data-reveal-item> | |
36 | + <div class="ja-stat-value" data-count="2.4" data-decimals="1" data-suffix="x">0</div> | |
37 | + <div class="ja-stat-label">faster than Granian</div> | |
38 | + </div> | |
39 | + <div class="ja-stat" data-reveal-item> | |
40 | + <div class="ja-stat-value" data-count="53" data-suffix="x">0</div> | |
41 | + <div class="ja-stat-label">native async DB awaits</div> | |
42 | + </div> | |
43 | + <div class="ja-stat" data-reveal-item> | |
44 | + <div class="ja-stat-value" data-count="181" data-suffix="k">0</div> | |
45 | + <div class="ja-stat-label">native CRUD SELECT</div> | |
46 | + </div> | |
47 | + <div class="ja-stat" data-reveal-item> | |
48 | + <div class="ja-stat-value" data-count="12" data-suffix=" MB">0</div> | |
49 | + <div class="ja-stat-label">resident memory</div> | |
50 | + </div> | |
22 | 51 | </div> |
23 | 52 | |
24 | -## Performance Matrix | |
53 | +<div class="ja-section" data-reveal>Install in seconds</div> | |
25 | 54 | |
26 | -<div class="benchmark-card"> | |
27 | - <div class="ja-stats"> | |
28 | - <div class="ja-stat"> | |
29 | - <div class="ja-stat-value">766k</div> | |
30 | - <div class="ja-stat-label">req/s hello-world</div> | |
31 | - </div> | |
32 | - <div class="ja-stat"> | |
33 | - <div class="ja-stat-value">782k</div> | |
34 | - <div class="ja-stat-label">req/s JSON echo</div> | |
35 | - </div> | |
36 | - <div class="ja-stat"> | |
37 | - <div class="ja-stat-value">2.4x</div> | |
38 | - <div class="ja-stat-label">vs Granian</div> | |
39 | - </div> | |
40 | - <div class="ja-stat"> | |
41 | - <div class="ja-stat-value">53x</div> | |
42 | - <div class="ja-stat-label">native async DB</div> | |
43 | - </div> | |
44 | - <div class="ja-stat"> | |
45 | - <div class="ja-stat-value">12MB</div> | |
46 | - <div class="ja-stat-label">resident memory</div> | |
47 | - </div> | |
48 | - <div class="ja-stat"> | |
49 | - <div class="ja-stat-value">12.4x</div> | |
50 | - <div class="ja-stat-label">free-threaded CPU</div> | |
51 | - </div> | |
55 | +<div class="ja-tabs" data-tabs data-reveal> | |
56 | + <div class="ja-tabs-bar"> | |
57 | + <button class="ja-tab-btn" data-tab-btn="pip" data-active="true">pip</button> | |
58 | + <button class="ja-tab-btn" data-tab-btn="uv">uv</button> | |
59 | + <button class="ja-tab-btn" data-tab-btn="scaffold">scaffold</button> | |
60 | + </div> | |
61 | + <div class="ja-tab-panel" data-tab-panel="pip"> | |
62 | +```bash | |
63 | +pip install justapi | |
64 | +python main.py | |
65 | +# β JustAPI running on http://127.0.0.1:8000 | |
66 | +``` | |
67 | + </div> | |
68 | + <div class="ja-tab-panel" data-tab-panel="uv" style="display:none"> | |
69 | +```bash | |
70 | +uv pip install justapi | |
71 | +uv run main.py | |
72 | +``` | |
73 | + </div> | |
74 | + <div class="ja-tab-panel" data-tab-panel="scaffold" style="display:none"> | |
75 | +```bash | |
76 | +uvx justapi create my_app | |
77 | +cd my_app && python app/main.py | |
78 | +``` | |
52 | 79 | </div> |
53 | 80 | </div> |
54 | 81 | |
55 | -## Runtime | |
82 | +<div class="ja-section" data-reveal>Minimal app</div> | |
56 | 83 | |
57 | -<div class="ja-terminal"> | |
84 | +<div class="ja-terminal" data-terminal data-reveal> | |
58 | 85 | <div class="ja-terminal-bar"> |
59 | 86 | <span class="ja-terminal-dot"></span> |
60 | 87 | <span class="ja-terminal-dot"></span> |
61 | 88 | <span class="ja-terminal-dot"></span> |
89 | + <span class="ja-terminal-title">main.py</span> | |
62 | 90 | </div> |
63 | 91 | <div class="ja-terminal-body"> |
64 | - <span class="cm">$</span> pip install justapi<br/> | |
65 | - <span class="ok">β installed 2.0.9 (8 platforms)</span><br/> | |
66 | - <span class="cm">$</span> cat main.py<br/> | |
67 | - <span class="cm">from</span> justapi <span class="cm">import</span> JustAPIApp<br/> | |
68 | - <br/> | |
69 | - app = JustAPIApp()<br/> | |
70 | - <br/> | |
71 | - <span class="cm">@app.get</span>(<span class="ok">"/"</span>)<br/> | |
72 | - <span class="cm">def</span> hello():<br/> | |
73 | - <span class="cm">return</span> {<span class="ok">"Hello"</span>: <span class="ok">"World"</span>}<br/> | |
74 | - <br/> | |
75 | - app.run()<br/> | |
76 | - <span class="ok">β server started on http://127.0.0.1:8000</span> | |
92 | + <div data-term-line><span class="cm">from</span> justapi <span class="cm">import</span> JustAPIApp</div> | |
93 | + <div data-term-line> </div> | |
94 | + <div data-term-line>app = JustAPIApp()</div> | |
95 | + <div data-term-line> </div> | |
96 | + <div data-term-line><span class="cm">@app.get</span>(<span class="ok">"/"</span>)</div> | |
97 | + <div data-term-line><span class="cm">def</span> hello():</div> | |
98 | + <div data-term-line> <span class="cm">return</span> {<span class="ok">"Hello"</span>: <span class="ok">"World"</span>}</div> | |
99 | + <div data-term-line> </div> | |
100 | + <div data-term-line>app.run()<span data-cursor style="display:inline-block">β</span></div> | |
101 | + <div data-term-line><span class="ok">β</span> <span class="dim">server started Β· /docs Β· /redoc Β· OpenAPI auto</span></div> | |
77 | 102 | </div> |
78 | 103 | </div> |
79 | 104 | |
80 | -## Feature Graph | |
105 | +<div class="ja-section" data-reveal>Benchmarks</div> | |
81 | 106 | |
82 | -<div class="ja-graph"> | |
83 | - <img src="/justapi-features.png" alt="JustAPI feature matrix" width="100%" /> | |
107 | +<div class="ja-bars" data-reveal> | |
108 | + <div class="ja-bar-row ja-bar-row--winner"> | |
109 | + <span class="ja-bar-label">JustAPI</span> | |
110 | + <div class="ja-bar-track"><div class="ja-bar-fill" data-bar data-w="100%" data-delay="0"></div></div> | |
111 | + <span class="ja-bar-value">766k</span> | |
112 | + </div> | |
113 | + <div class="ja-bar-row"> | |
114 | + <span class="ja-bar-label">Granian</span> | |
115 | + <div class="ja-bar-track"><div class="ja-bar-fill" data-bar data-w="41%" data-delay="150"></div></div> | |
116 | + <span class="ja-bar-value">314k</span> | |
117 | + </div> | |
118 | + <div class="ja-bar-row"> | |
119 | + <span class="ja-bar-label">Robyn</span> | |
120 | + <div class="ja-bar-track"><div class="ja-bar-fill" data-bar data-w="5%" data-delay="300"></div></div> | |
121 | + <span class="ja-bar-value">39k</span> | |
122 | + </div> | |
123 | + <div class="ja-bar-row"> | |
124 | + <span class="ja-bar-label">FastAPI</span> | |
125 | + <div class="ja-bar-track"><div class="ja-bar-fill" data-bar data-w="5%" data-delay="450"></div></div> | |
126 | + <span class="ja-bar-value">36k</span> | |
127 | + </div> | |
84 | 128 | </div> |
85 | 129 | |
86 | -## Pipeline | |
130 | +<p style="font-size: 0.8rem; color: var(--ja-muted); margin-top: -0.5rem;"> | |
131 | + hello-world, 100 concurrent connections, 30s, same hardware β full methodology in <a href="https://github.com/swadhinbiswas/JustAPI/blob/main/BENCHMARKS.md">BENCHMARKS.md</a> | |
132 | +</p> | |
87 | 133 | |
88 | -<div class="ja-graph"> | |
89 | - <img src="/justapi-pipeline.svg" alt="Request pipeline β Rust end to end" width="100%" /> | |
90 | -</div> | |
91 | - | |
92 | -## Why JustAPI | |
134 | +<div class="ja-section" data-reveal>Features</div> | |
93 | 135 | |
94 | -<div class="feature-grid"> | |
95 | - <div class="feature-card"> | |
96 | - <h3>Rust Core</h3> | |
97 | - Networking, TLS, routing, serialization β all in Rust before your code runs. | |
136 | +<div class="ja-grid" data-reveal-group> | |
137 | + <div class="ja-card" data-reveal-item> | |
138 | + <div class="ja-card-icon">β‘</div> | |
139 | + <h3>Rust core</h3> | |
140 | + <p>Networking, TLS, routing, serialization run in Rust. Python executes only your logic.</p> | |
141 | + </div> | |
142 | + <div class="ja-card" data-reveal-item> | |
143 | + <div class="ja-card-icon">ποΈ</div> | |
144 | + <h3>Native async DB</h3> | |
145 | + <p><code>await app.db.query_async()</code> runs SQL on Rust's tokio runtime β 53Γ faster on slow queries.</p> | |
98 | 146 | </div> |
99 | - <div class="feature-card"> | |
100 | - <h3>Native Async DB</h3> | |
101 | - `await app.db.query_async()` β SQL on Rust's tokio runtime, loop never blocked. | |
147 | + <div class="ja-card" data-reveal-item> | |
148 | + <div class="ja-card-icon">π‘</div> | |
149 | + <h3>Rust-native SSE</h3> | |
150 | + <p><code>app.sse_native()</code> streams events with zero Python per event.</p> | |
102 | 151 | </div> |
103 | - <div class="feature-card"> | |
104 | - <h3>Rust-Native SSE</h3> | |
105 | - `app.sse_native()` streams events with zero Python per event. | |
152 | + <div class="ja-card" data-reveal-item> | |
153 | + <div class="ja-card-icon">π</div> | |
154 | + <h3>Multi-worker</h3> | |
155 | + <p><code>justapi serve --workers N</code> β 1.88Γ throughput at 4 workers, auto-scale.</p> | |
106 | 156 | </div> |
107 | - <div class="feature-card"> | |
108 | - <h3>Multi-Worker</h3> | |
109 | - `justapi serve --workers N --scale` β 1.88x throughput at 4 workers. | |
157 | + <div class="ja-card" data-reveal-item> | |
158 | + <div class="ja-card-icon">π§ </div> | |
159 | + <h3>Free-threaded</h3> | |
160 | + <p>CPython 3.14t wheels β CPU-bound Python scales with cores, 12.4Γ measured.</p> | |
110 | 161 | </div> |
111 | - <div class="feature-card"> | |
112 | - <h3>Free-Threaded</h3> | |
113 | - CPython 3.14t wheels β CPU-bound Python scales with cores. | |
162 | + <div class="ja-card" data-reveal-item> | |
163 | + <div class="ja-card-icon">π</div> | |
164 | + <h3>Security built-in</h3> | |
165 | + <p>JWT, rate limiting, CORS, security headers β all in Rust middleware.</p> | |
114 | 166 | </div> |
115 | - <div class="feature-card"> | |
116 | - <h3>Type-Checked</h3> | |
117 | - `py.typed` + complete stubs β mypy-clean on user code. | |
167 | + <div class="ja-card" data-reveal-item> | |
168 | + <div class="ja-card-icon">π‘οΈ</div> | |
169 | + <h3>Production-ready</h3> | |
170 | + <p>Circuit breakers, OTel tracing, Prometheus metrics, health checks.</p> | |
171 | + </div> | |
172 | + <div class="ja-card" data-reveal-item> | |
173 | + <div class="ja-card-icon">π</div> | |
174 | + <h3>Type-checked</h3> | |
175 | + <p><code>py.typed</code> + complete stubs β mypy-clean on user code.</p> | |
176 | + </div> | |
177 | + <div class="ja-card" data-reveal-item> | |
178 | + <div class="ja-card-icon">π</div> | |
179 | + <h3>FastAPI-compatible</h3> | |
180 | + <p>Same decorators, Pydantic models, Depends. Migrate with one import.</p> | |
118 | 181 | </div> |
119 | 182 | </div> |
120 | 183 | |
121 | -## Framework vs FastAPI | |
184 | +<div class="ja-section" data-reveal>Framework comparison</div> | |
122 | 185 | |
123 | 186 | | | FastAPI | JustAPI | |
124 | 187 | |---|---|---| |
| @@ -127,12 +190,9 @@ hero: | ||
127 | 190 | | **JSON echo** | ~33k req/s | **~782k req/s** | |
128 | 191 | | **Native DB SELECT** | Python driver | **181k req/s (Γ125)** | |
129 | 192 | | **Memory** | 29 MB | **12 MB** | |
130 | -| **OpenAPI docs** | /docs | /docs | | |
131 | 193 | |
132 | -<div class="ja-cta"> | |
133 | - <div class="ja-cta-title">Ready to build?</div> | |
134 | - <p style={{ color: "var(--ja-muted)" }}>One import. Rust underneath. Zero config.</p> | |
135 | - <p> | |
136 | - <a href="/getting-started/overview/" class="ja-cta-btn" style={{ display: "inline-block", padding: "0.75rem 1.5rem", border: "1px solid var(--ja-accent)", borderRadius: "9999px", color: "var(--ja-accent)", fontWeight: 700 }}>Get Started β</a> | |
137 | - </p> | |
194 | +<div class="ja-cta" data-reveal> | |
195 | + <div class="ja-cta-title">Ready to build something fast?</div> | |
196 | + <p class="ja-cta-sub">One import. Rust underneath. Zero config.</p> | |
197 | + <a class="ja-btn ja-btn--primary" href="/getting-started/overview/">Get Started β</a> | |
138 | 198 | </div> |
139 | 199 | |
βΌdocs_site/src/scripts/animations.js
+182-0
| @@ -0,0 +1,182 @@ | ||
1 | +// JustAPI docs β animations (anime.js v4) | |
2 | +// Count-up stats, scroll-reveal, hero entrance, benchmark bars, terminal. | |
3 | +import { animate, createTimeline, utils } from 'animejs'; | |
4 | + | |
5 | +export function initAnimations() { | |
6 | + const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches; | |
7 | + if (prefersReduced) return; | |
8 | + | |
9 | + // βββ Animated stat counters (data-count attributes) βββ | |
10 | + document.querySelectorAll('[data-count]').forEach((el) => { | |
11 | + const target = parseFloat(el.dataset.count); | |
12 | + const suffix = el.dataset.suffix || ''; | |
13 | + const decimals = el.dataset.decimals ? parseInt(el.dataset.decimals, 10) : 0; | |
14 | + const obj = { v: 0 }; | |
15 | + const io = new IntersectionObserver( | |
16 | + (entries) => { | |
17 | + if (!entries[0].isIntersecting) return; | |
18 | + io.disconnect(); | |
19 | + animate({ | |
20 | + targets: obj, | |
21 | + v: target, | |
22 | + duration: 1400, | |
23 | + ease: 'outExpo', | |
24 | + update: () => { | |
25 | + el.textContent = obj.v.toFixed(decimals) + suffix; | |
26 | + }, | |
27 | + }); | |
28 | + }, | |
29 | + { threshold: 0.4 }, | |
30 | + ); | |
31 | + io.observe(el); | |
32 | + }); | |
33 | + | |
34 | + // βββ Scroll-reveal sections βββ | |
35 | + document.querySelectorAll('[data-reveal]').forEach((el) => { | |
36 | + el.style.opacity = '0'; | |
37 | + el.style.transform = 'translateY(24px)'; | |
38 | + const io = new IntersectionObserver( | |
39 | + (entries) => { | |
40 | + if (!entries[0].isIntersecting) return; | |
41 | + io.disconnect(); | |
42 | + animate({ | |
43 | + targets: el, | |
44 | + opacity: [0, 1], | |
45 | + translateY: [24, 0], | |
46 | + duration: 700, | |
47 | + ease: 'outCubic', | |
48 | + delay: parseInt(el.dataset.revealDelay || '0', 10), | |
49 | + }); | |
50 | + }, | |
51 | + { threshold: 0.15 }, | |
52 | + ); | |
53 | + io.observe(el); | |
54 | + }); | |
55 | + | |
56 | + // βββ Staggered children reveal βββ | |
57 | + document.querySelectorAll('[data-reveal-group]').forEach((group) => { | |
58 | + const items = Array.from(group.querySelectorAll('[data-reveal-item]')); | |
59 | + items.forEach((it) => { | |
60 | + it.style.opacity = '0'; | |
61 | + it.style.transform = 'translateY(20px)'; | |
62 | + }); | |
63 | + const io = new IntersectionObserver( | |
64 | + (entries) => { | |
65 | + if (!entries[0].isIntersecting) return; | |
66 | + io.disconnect(); | |
67 | + animate({ | |
68 | + targets: items, | |
69 | + opacity: [0, 1], | |
70 | + translateY: [20, 0], | |
71 | + duration: 650, | |
72 | + delay: (el, i) => i * 90, | |
73 | + ease: 'outCubic', | |
74 | + }); | |
75 | + }, | |
76 | + { threshold: 0.12 }, | |
77 | + ); | |
78 | + io.observe(group); | |
79 | + }); | |
80 | + | |
81 | + // βββ Hero entrance βββ | |
82 | + const heroTitle = document.querySelector('[data-hero-title]'); | |
83 | + if (heroTitle) { | |
84 | + createTimeline({ ease: 'outExpo' }) | |
85 | + .add({ | |
86 | + targets: heroTitle, | |
87 | + opacity: [0, 1], | |
88 | + translateY: [30, 0], | |
89 | + duration: 800, | |
90 | + }) | |
91 | + .add({ | |
92 | + targets: heroTitle, | |
93 | + textShadow: ['0 0 0px rgba(34,197,94,0)', '0 0 40px rgba(34,197,94,0.35)'], | |
94 | + duration: 900, | |
95 | + }, '-=400'); | |
96 | + } | |
97 | + | |
98 | + // βββ Terminal typing reveal βββ | |
99 | + const term = document.querySelector('[data-terminal]'); | |
100 | + if (term) { | |
101 | + const lines = Array.from(term.querySelectorAll('[data-term-line]')); | |
102 | + lines.forEach((l) => { l.style.opacity = '0'; }); | |
103 | + const io = new IntersectionObserver( | |
104 | + (entries) => { | |
105 | + if (!entries[0].isIntersecting) return; | |
106 | + io.disconnect(); | |
107 | + createTimeline({ ease: 'outCubic' }) | |
108 | + .add({ | |
109 | + targets: lines, | |
110 | + opacity: [0, 1], | |
111 | + translateX: [-8, 0], | |
112 | + duration: 220, | |
113 | + delay: (el, i) => i * 140, | |
114 | + }); | |
115 | + }, | |
116 | + { threshold: 0.3 }, | |
117 | + ); | |
118 | + io.observe(term); | |
119 | + } | |
120 | + | |
121 | + // βββ Cursor blink βββ | |
122 | + const cursor = document.querySelector('[data-cursor]'); | |
123 | + if (cursor) { | |
124 | + animate({ | |
125 | + targets: cursor, | |
126 | + opacity: [1, 0], | |
127 | + duration: 500, | |
128 | + loop: true, | |
129 | + ease: 'steps(1)', | |
130 | + }); | |
131 | + } | |
132 | + | |
133 | + // βββ Benchmark bars βββ | |
134 | + document.querySelectorAll('[data-bar]').forEach((bar) => { | |
135 | + const w = bar.dataset.w || '0%'; | |
136 | + bar.style.width = '0%'; | |
137 | + const io = new IntersectionObserver( | |
138 | + (entries) => { | |
139 | + if (!entries[0].isIntersecting) return; | |
140 | + io.disconnect(); | |
141 | + animate({ | |
142 | + targets: bar, | |
143 | + width: w, | |
144 | + duration: 1200, | |
145 | + ease: 'outExpo', | |
146 | + delay: parseInt(bar.dataset.delay || '0', 10), | |
147 | + }); | |
148 | + }, | |
149 | + { threshold: 0.4 }, | |
150 | + ); | |
151 | + io.observe(bar); | |
152 | + }); | |
153 | + | |
154 | + // βββ Tabs (shadcn-style) βββ | |
155 | + document.querySelectorAll('[data-tabs]').forEach((tabs) => { | |
156 | + const btns = tabs.querySelectorAll('[data-tab-btn]'); | |
157 | + const panels = tabs.querySelectorAll('[data-tab-panel]'); | |
158 | + btns.forEach((btn) => { | |
159 | + btn.addEventListener('click', () => { | |
160 | + const target = btn.dataset.tabBtn; | |
161 | + btns.forEach((b) => b.setAttribute('data-active', b === btn ? 'true' : 'false')); | |
162 | + panels.forEach((p) => { | |
163 | + const show = p.dataset.tabPanel === target; | |
164 | + p.style.display = show ? 'block' : 'none'; | |
165 | + if (show) { | |
166 | + animate({ targets: p, opacity: [0, 1], translateY: [6, 0], duration: 300, ease: 'outCubic' }); | |
167 | + } | |
168 | + }); | |
169 | + }); | |
170 | + }); | |
171 | + const first = tabs.querySelector('[data-tab-btn]'); | |
172 | + if (first) first.click(); | |
173 | + }); | |
174 | +} | |
175 | + | |
176 | +if (typeof window !== 'undefined') { | |
177 | + if (document.readyState === 'loading') { | |
178 | + document.addEventListener('DOMContentLoaded', initAnimations); | |
179 | + } else { | |
180 | + initAnimations(); | |
181 | + } | |
182 | +} | |
0 | 183 | |
βΌdocs_site/src/styles/custom.css
+415-597
| @@ -1,248 +1,156 @@ | ||
1 | 1 | /* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ |
2 | - JustAPI Documentation β Sci-Fi Design System | |
3 | - Themes: Sci-Fi Dark (default) Β· Light Β· Dracula Β· RosΓ© Pine Β· Warm | |
4 | - Palette: green #00ff9d Β· black #05080f Β· white #e6f1ff Β· red #ff2e4d | |
2 | + JustAPI Docs β Clean, readable design system | |
3 | + Inspired by shadcn/ui + Stripe docs patterns. | |
4 | + Themes: dark (default) Β· light Β· dracula Β· rose-pine Β· warm | |
5 | 5 | βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ */ |
6 | 6 | |
7 | -/* βββ Base palette (Sci-Fi Dark) βββ */ | |
8 | 7 | :root, |
9 | 8 | [data-theme='dark'] { |
10 | - --ja-bg: #05080f; | |
11 | - --ja-bg-2: #0a0f1c; | |
12 | - --ja-bg-3: #101830; | |
13 | - --ja-panel: rgba(10, 15, 28, 0.8); | |
14 | - --ja-border: #1a2440; | |
15 | - --ja-green: #00ff9d; | |
16 | - --ja-green-dim: #00c97d; | |
17 | - --ja-red: #ff2e4d; | |
18 | - --ja-white: #e6f1ff; | |
19 | - --ja-muted: #7d8db1; | |
20 | - --ja-accent: #00ff9d; | |
21 | - --ja-accent-2: #00d4ff; | |
22 | - | |
23 | - --sl-color-accent-low: #003d26; | |
24 | - --sl-color-accent: #00ff9d; | |
25 | - --sl-color-accent-high: #66ffc4; | |
26 | - --sl-color-white: #e6f1ff; | |
27 | - --sl-color-gray-1: #e6f1ff; | |
28 | - --sl-color-gray-2: #b8c6e0; | |
29 | - --sl-color-gray-3: #7d8db1; | |
30 | - --sl-color-gray-4: #55648c; | |
31 | - --sl-color-gray-5: #2a3550; | |
32 | - --sl-color-gray-6: #141c30; | |
33 | - --sl-color-black: #05080f; | |
34 | - --sl-color-bg: #05080f; | |
35 | - --sl-color-bg-nav: #070b15; | |
36 | - --sl-color-bg-sidebar: #070b15; | |
37 | - --sl-color-bg-hover: #0d1526; | |
38 | - --sl-color-text: #e6f1ff; | |
39 | - --sl-color-text-muted: #7d8db1; | |
40 | - --sl-color-border: #1a2440; | |
41 | -} | |
42 | - | |
43 | -/* βββ Light theme βββ */ | |
9 | + --ja-bg: #09090b; | |
10 | + --ja-bg-2: #101012; | |
11 | + --ja-bg-3: #18181b; | |
12 | + --ja-panel: #101012; | |
13 | + --ja-border: #27272a; | |
14 | + --ja-green: #22c55e; | |
15 | + --ja-green-dim: #16a34a; | |
16 | + --ja-red: #ef4444; | |
17 | + --ja-white: #fafafa; | |
18 | + --ja-muted: #a1a1aa; | |
19 | + --ja-accent: #22c55e; | |
20 | + --ja-accent-2: #3b82f6; | |
21 | + | |
22 | + --sl-color-accent-low: #052e16; | |
23 | + --sl-color-accent: #22c55e; | |
24 | + --sl-color-accent-high: #86efac; | |
25 | + --sl-color-white: #fafafa; | |
26 | + --sl-color-gray-1: #fafafa; | |
27 | + --sl-color-gray-2: #d4d4d8; | |
28 | + --sl-color-gray-3: #a1a1aa; | |
29 | + --sl-color-gray-4: #71717a; | |
30 | + --sl-color-gray-5: #3f3f46; | |
31 | + --sl-color-gray-6: #18181b; | |
32 | + --sl-color-black: #09090b; | |
33 | + --sl-color-bg: #09090b; | |
34 | + --sl-color-bg-nav: #0c0c0e; | |
35 | + --sl-color-bg-sidebar: #0c0c0e; | |
36 | + --sl-color-bg-hover: #18181b; | |
37 | + --sl-color-text: #fafafa; | |
38 | + --sl-color-text-muted: #a1a1aa; | |
39 | + --sl-color-border: #27272a; | |
40 | +} | |
41 | + | |
42 | +/* βββ Light βββ */ | |
44 | 43 | [data-theme='light'] { |
45 | - --ja-bg: #f4f7fb; | |
46 | - --ja-bg-2: #ffffff; | |
47 | - --ja-bg-3: #eef2f8; | |
48 | - --ja-panel: rgba(255, 255, 255, 0.92); | |
49 | - --ja-border: #d5dde8; | |
50 | - --ja-green: #00925c; | |
51 | - --ja-green-dim: #007a4c; | |
52 | - --ja-red: #d91f3c; | |
53 | - --ja-white: #0d1526; | |
54 | - --ja-muted: #5a6a8c; | |
55 | - --ja-accent: #00925c; | |
56 | - --ja-accent-2: #0077a8; | |
57 | - | |
58 | - --sl-color-accent-low: #e0f7ee; | |
59 | - --sl-color-accent: #00925c; | |
60 | - --sl-color-accent-high: #00593a; | |
61 | - --sl-color-white: #0d1526; | |
62 | - --sl-color-gray-1: #0d1526; | |
63 | - --sl-color-gray-2: #2a3550; | |
64 | - --sl-color-gray-3: #5a6a8c; | |
65 | - --sl-color-gray-4: #7d8db1; | |
66 | - --sl-color-gray-5: #d5dde8; | |
67 | - --sl-color-gray-6: #eef2f8; | |
44 | + --ja-bg: #ffffff; | |
45 | + --ja-bg-2: #fafafa; | |
46 | + --ja-bg-3: #f4f4f5; | |
47 | + --ja-panel: #ffffff; | |
48 | + --ja-border: #e4e4e7; | |
49 | + --ja-green: #16a34a; | |
50 | + --ja-green-dim: #15803d; | |
51 | + --ja-red: #dc2626; | |
52 | + --ja-white: #18181b; | |
53 | + --ja-muted: #71717a; | |
54 | + --ja-accent: #16a34a; | |
55 | + --ja-accent-2: #2563eb; | |
56 | + | |
57 | + --sl-color-accent-low: #dcfce7; | |
58 | + --sl-color-accent: #16a34a; | |
59 | + --sl-color-accent-high: #14532d; | |
60 | + --sl-color-white: #18181b; | |
61 | + --sl-color-gray-1: #18181b; | |
62 | + --sl-color-gray-2: #3f3f46; | |
63 | + --sl-color-gray-3: #71717a; | |
64 | + --sl-color-gray-4: #a1a1aa; | |
65 | + --sl-color-gray-5: #e4e4e7; | |
66 | + --sl-color-gray-6: #f4f4f5; | |
68 | 67 | --sl-color-black: #ffffff; |
69 | - --sl-color-bg: #f4f7fb; | |
68 | + --sl-color-bg: #ffffff; | |
70 | 69 | --sl-color-bg-nav: #ffffff; |
71 | 70 | --sl-color-bg-sidebar: #ffffff; |
72 | - --sl-color-bg-hover: #eef2f8; | |
73 | - --sl-color-text: #0d1526; | |
74 | - --sl-color-text-muted: #5a6a8c; | |
75 | - --sl-color-border: #d5dde8; | |
71 | + --sl-color-bg-hover: #f4f4f5; | |
72 | + --sl-color-text: #18181b; | |
73 | + --sl-color-text-muted: #71717a; | |
74 | + --sl-color-border: #e4e4e7; | |
76 | 75 | } |
77 | 76 | |
78 | -/* βββ Dracula theme βββ */ | |
77 | +/* βββ Dracula βββ */ | |
79 | 78 | [data-theme='dracula'] { |
80 | - --ja-bg: #282a36; | |
81 | - --ja-bg-2: #21222c; | |
82 | - --ja-bg-3: #343746; | |
83 | - --ja-panel: rgba(33, 34, 44, 0.9); | |
84 | - --ja-border: #44475a; | |
85 | - --ja-green: #50fa7b; | |
86 | - --ja-green-dim: #3dd962; | |
87 | - --ja-red: #ff5555; | |
88 | - --ja-white: #f8f8f2; | |
89 | - --ja-muted: #6272a4; | |
90 | - --ja-accent: #bd93f9; | |
91 | - --ja-accent-2: #8be9fd; | |
92 | - | |
93 | - --sl-color-accent-low: #3d3552; | |
94 | - --sl-color-accent: #bd93f9; | |
95 | - --sl-color-accent-high: #e3d5ff; | |
96 | - --sl-color-white: #f8f8f2; | |
97 | - --sl-color-gray-1: #f8f8f2; | |
98 | - --sl-color-gray-2: #bfc2d8; | |
99 | - --sl-color-gray-3: #6272a4; | |
100 | - --sl-color-gray-4: #4d5a80; | |
101 | - --sl-color-gray-5: #343746; | |
102 | - --sl-color-gray-6: #21222c; | |
103 | - --sl-color-black: #282a36; | |
104 | - --sl-color-bg: #282a36; | |
105 | - --sl-color-bg-nav: #21222c; | |
106 | - --sl-color-bg-sidebar: #21222c; | |
107 | - --sl-color-bg-hover: #343746; | |
108 | - --sl-color-text: #f8f8f2; | |
109 | - --sl-color-text-muted: #6272a4; | |
110 | - --sl-color-border: #44475a; | |
111 | -} | |
112 | - | |
113 | -/* βββ RosΓ© Pine theme βββ */ | |
79 | + --ja-bg: #282a36; --ja-bg-2: #21222c; --ja-bg-3: #343746; --ja-panel: #21222c; | |
80 | + --ja-border: #44475a; --ja-green: #50fa7b; --ja-green-dim: #3dd962; --ja-red: #ff5555; | |
81 | + --ja-white: #f8f8f2; --ja-muted: #6272a4; --ja-accent: #bd93f9; --ja-accent-2: #8be9fd; | |
82 | + --sl-color-accent-low: #3d3552; --sl-color-accent: #bd93f9; --sl-color-accent-high: #e3d5ff; | |
83 | + --sl-color-white: #f8f8f2; --sl-color-gray-1: #f8f8f2; --sl-color-gray-2: #bfc2d8; | |
84 | + --sl-color-gray-3: #6272a4; --sl-color-gray-4: #4d5a80; --sl-color-gray-5: #343746; | |
85 | + --sl-color-gray-6: #21222c; --sl-color-black: #282a36; --sl-color-bg: #282a36; | |
86 | + --sl-color-bg-nav: #21222c; --sl-color-bg-sidebar: #21222c; --sl-color-bg-hover: #343746; | |
87 | + --sl-color-text: #f8f8f2; --sl-color-text-muted: #6272a4; --sl-color-border: #44475a; | |
88 | +} | |
89 | + | |
90 | +/* βββ RosΓ© Pine βββ */ | |
114 | 91 | [data-theme='rose-pine'] { |
115 | - --ja-bg: #191724; | |
116 | - --ja-bg-2: #1f1d2e; | |
117 | - --ja-bg-3: #26233a; | |
118 | - --ja-panel: rgba(31, 29, 46, 0.9); | |
119 | - --ja-border: #403d52; | |
120 | - --ja-green: #9ccfd8; | |
121 | - --ja-green-dim: #7fb4bd; | |
122 | - --ja-red: #eb6f92; | |
123 | - --ja-white: #e0def4; | |
124 | - --ja-muted: #908caa; | |
125 | - --ja-accent: #c4a7e7; | |
126 | - --ja-accent-2: #ebbcba; | |
127 | - | |
128 | - --sl-color-accent-low: #3d3552; | |
129 | - --sl-color-accent: #c4a7e7; | |
130 | - --sl-color-accent-high: #e0def4; | |
131 | - --sl-color-white: #e0def4; | |
132 | - --sl-color-gray-1: #e0def4; | |
133 | - --sl-color-gray-2: #b5b1d6; | |
134 | - --sl-color-gray-3: #908caa; | |
135 | - --sl-color-gray-4: #6e6a86; | |
136 | - --sl-color-gray-5: #403d52; | |
137 | - --sl-color-gray-6: #26233a; | |
138 | - --sl-color-black: #191724; | |
139 | - --sl-color-bg: #191724; | |
140 | - --sl-color-bg-nav: #1f1d2e; | |
141 | - --sl-color-bg-sidebar: #1f1d2e; | |
142 | - --sl-color-bg-hover: #26233a; | |
143 | - --sl-color-text: #e0def4; | |
144 | - --sl-color-text-muted: #908caa; | |
145 | - --sl-color-border: #403d52; | |
146 | -} | |
147 | - | |
148 | -/* βββ Warm theme βββ */ | |
92 | + --ja-bg: #191724; --ja-bg-2: #1f1d2e; --ja-bg-3: #26233a; --ja-panel: #1f1d2e; | |
93 | + --ja-border: #403d52; --ja-green: #9ccfd8; --ja-green-dim: #7fb4bd; --ja-red: #eb6f92; | |
94 | + --ja-white: #e0def4; --ja-muted: #908caa; --ja-accent: #c4a7e7; --ja-accent-2: #ebbcba; | |
95 | + --sl-color-accent-low: #3d3552; --sl-color-accent: #c4a7e7; --sl-color-accent-high: #e0def4; | |
96 | + --sl-color-white: #e0def4; --sl-color-gray-1: #e0def4; --sl-color-gray-2: #b5b1d6; | |
97 | + --sl-color-gray-3: #908caa; --sl-color-gray-4: #6e6a86; --sl-color-gray-5: #403d52; | |
98 | + --sl-color-gray-6: #26233a; --sl-color-black: #191724; --sl-color-bg: #191724; | |
99 | + --sl-color-bg-nav: #1f1d2e; --sl-color-bg-sidebar: #1f1d2e; --sl-color-bg-hover: #26233a; | |
100 | + --sl-color-text: #e0def4; --sl-color-text-muted: #908caa; --sl-color-border: #403d52; | |
101 | +} | |
102 | + | |
103 | +/* βββ Warm βββ */ | |
149 | 104 | [data-theme='warm'] { |
150 | - --ja-bg: #1c1412; | |
151 | - --ja-bg-2: #241a17; | |
152 | - --ja-bg-3: #33241e; | |
153 | - --ja-panel: rgba(36, 26, 23, 0.9); | |
154 | - --ja-border: #4a362e; | |
155 | - --ja-green: #ffb454; | |
156 | - --ja-green-dim: #e89b3a; | |
157 | - --ja-red: #ff6b6b; | |
158 | - --ja-white: #f8ead9; | |
159 | - --ja-muted: #a88b7a; | |
160 | - --ja-accent: #ff9d5c; | |
161 | - --ja-accent-2: #ffd166; | |
162 | - | |
163 | - --sl-color-accent-low: #4a2c1a; | |
164 | - --sl-color-accent: #ff9d5c; | |
165 | - --sl-color-accent-high: #ffd0a8; | |
166 | - --sl-color-white: #f8ead9; | |
167 | - --sl-color-gray-1: #f8ead9; | |
168 | - --sl-color-gray-2: #d4bca8; | |
169 | - --sl-color-gray-3: #a88b7a; | |
170 | - --sl-color-gray-4: #7d6353; | |
171 | - --sl-color-gray-5: #4a362e; | |
172 | - --sl-color-gray-6: #33241e; | |
173 | - --sl-color-black: #1c1412; | |
174 | - --sl-color-bg: #1c1412; | |
175 | - --sl-color-bg-nav: #241a17; | |
176 | - --sl-color-bg-sidebar: #241a17; | |
177 | - --sl-color-bg-hover: #33241e; | |
178 | - --sl-color-text: #f8ead9; | |
179 | - --sl-color-text-muted: #a88b7a; | |
180 | - --sl-color-border: #4a362e; | |
181 | -} | |
182 | - | |
183 | -/* βββ Typography βββ */ | |
105 | + --ja-bg: #1c1412; --ja-bg-2: #241a17; --ja-bg-3: #33241e; --ja-panel: #241a17; | |
106 | + --ja-border: #4a362e; --ja-green: #ffb454; --ja-green-dim: #e89b3a; --ja-red: #ff6b6b; | |
107 | + --ja-white: #f8ead9; --ja-muted: #a88b7a; --ja-accent: #ff9d5c; --ja-accent-2: #ffd166; | |
108 | + --sl-color-accent-low: #4a2c1a; --sl-color-accent: #ff9d5c; --sl-color-accent-high: #ffd0a8; | |
109 | + --sl-color-white: #f8ead9; --sl-color-gray-1: #f8ead9; --sl-color-gray-2: #d4bca8; | |
110 | + --sl-color-gray-3: #a88b7a; --sl-color-gray-4: #7d6353; --sl-color-gray-5: #4a362e; | |
111 | + --sl-color-gray-6: #33241e; --sl-color-black: #1c1412; --sl-color-bg: #1c1412; | |
112 | + --sl-color-bg-nav: #241a17; --sl-color-bg-sidebar: #241a17; --sl-color-bg-hover: #33241e; | |
113 | + --sl-color-text: #f8ead9; --sl-color-text-muted: #a88b7a; --sl-color-border: #4a362e; | |
114 | +} | |
115 | + | |
116 | +/* βββ Typography (readable, not flashy) βββ */ | |
184 | 117 | html { |
185 | 118 | font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; |
186 | 119 | -webkit-font-smoothing: antialiased; |
187 | 120 | text-rendering: optimizeLegibility; |
188 | - scroll-behavior: smooth; | |
189 | 121 | } |
190 | 122 | |
191 | -body { | |
192 | - line-height: 1.7; | |
193 | - letter-spacing: -0.011em; | |
194 | -} | |
123 | +body { line-height: 1.7; } | |
195 | 124 | |
196 | 125 | .content h1 { |
197 | - font-size: 2.25rem; | |
126 | + font-size: 2rem; | |
198 | 127 | font-weight: 800; |
199 | - letter-spacing: -0.025em; | |
128 | + letter-spacing: -0.02em; | |
200 | 129 | line-height: 1.2; |
201 | 130 | margin-bottom: 1rem; |
202 | - background: linear-gradient(90deg, var(--ja-white), var(--ja-accent)); | |
203 | - -webkit-background-clip: text; | |
204 | - -webkit-text-fill-color: transparent; | |
205 | - background-clip: text; | |
206 | -} | |
207 | - | |
208 | -[data-theme='light'] .content h1 { | |
209 | - background: linear-gradient(90deg, var(--ja-white), var(--ja-green)); | |
210 | - -webkit-background-clip: text; | |
211 | - background-clip: text; | |
131 | + color: var(--ja-white); | |
212 | 132 | } |
213 | 133 | |
214 | 134 | .content h2 { |
215 | - font-size: 1.5rem; | |
135 | + font-size: 1.4rem; | |
216 | 136 | font-weight: 700; |
217 | - margin-top: 3rem; | |
218 | - margin-bottom: 1rem; | |
219 | - padding-bottom: 0.75rem; | |
137 | + margin-top: 2.5rem; | |
138 | + margin-bottom: 0.75rem; | |
139 | + padding-bottom: 0.5rem; | |
220 | 140 | border-bottom: 1px solid var(--sl-color-border); |
221 | 141 | } |
222 | 142 | |
223 | -.content h3 { | |
224 | - font-size: 1.2rem; | |
225 | - font-weight: 600; | |
226 | - margin-top: 2rem; | |
227 | - margin-bottom: 0.75rem; | |
228 | -} | |
143 | +.content h3 { font-size: 1.15rem; font-weight: 600; margin-top: 2rem; margin-bottom: 0.5rem; } | |
144 | +.content h4 { font-size: 1rem; font-weight: 600; margin-top: 1.5rem; } | |
229 | 145 | |
230 | -/* βββ Links βββ */ | |
231 | 146 | .content a { |
232 | 147 | color: var(--ja-accent); |
233 | 148 | text-decoration: none; |
234 | - transition: color 0.15s ease, text-shadow 0.15s ease; | |
235 | -} | |
236 | - | |
237 | -.content a:hover { | |
238 | - color: var(--ja-accent-high); | |
239 | - text-decoration: underline; | |
240 | - text-decoration-thickness: 2px; | |
241 | - text-underline-offset: 3px; | |
242 | - text-shadow: 0 0 12px rgba(0, 255, 157, 0.4); | |
149 | + transition: color 0.15s ease; | |
243 | 150 | } |
151 | +.content a:hover { text-decoration: underline; text-underline-offset: 3px; } | |
244 | 152 | |
245 | -/* βββ Code Blocks βββ */ | |
153 | +/* βββ Code blocks (shiki themes from astro.config) βββ */ | |
246 | 154 | code { |
247 | 155 | font-family: 'JetBrains Mono', 'Fira Code', monospace; |
248 | 156 | font-size: 0.85em; |
| @@ -252,526 +160,436 @@ code { | ||
252 | 160 | color: var(--ja-accent); |
253 | 161 | } |
254 | 162 | |
255 | -[data-theme='light'] code { | |
256 | - background: #e8f5ee; | |
257 | - color: #00925c; | |
258 | -} | |
259 | - | |
260 | 163 | pre { |
261 | 164 | font-family: 'JetBrains Mono', 'Fira Code', monospace; |
262 | 165 | font-size: 0.875rem; |
263 | - line-height: 1.6; | |
264 | - border-radius: 12px; | |
265 | - border: 1px solid var(--ja-border); | |
266 | - padding: 1.25rem; | |
166 | + line-height: 1.65; | |
167 | + border-radius: 10px; | |
168 | + border: 1px solid var(--sl-color-border); | |
169 | + padding: 1.1rem 1.25rem; | |
267 | 170 | overflow-x: auto; |
268 | 171 | background: var(--ja-bg-2); |
269 | - box-shadow: inset 0 0 30px rgba(0, 255, 157, 0.03); | |
270 | -} | |
271 | - | |
272 | -[data-theme='light'] pre { | |
273 | - background: #0d1526; | |
274 | - color: #e6f1ff; | |
275 | -} | |
276 | - | |
277 | -[data-theme='dracula'] pre { background: #21222c; } | |
278 | -[data-theme='rose-pine'] pre { background: #1f1d2e; } | |
279 | -[data-theme='warm'] pre { background: #241a17; } | |
280 | - | |
281 | -pre code { | |
282 | - background: none; | |
283 | - padding: 0; | |
284 | - border-radius: 0; | |
285 | - color: inherit; | |
286 | 172 | } |
287 | 173 | |
288 | -[data-theme='light'] pre code { color: #e6f1ff; } | |
174 | +pre code { background: none; padding: 0; color: inherit; } | |
289 | 175 | |
290 | 176 | /* βββ Tables βββ */ |
291 | 177 | .content table { |
292 | 178 | width: 100%; |
293 | 179 | font-size: 0.875rem; |
294 | - border-collapse: separate; | |
295 | - border-spacing: 0; | |
296 | - border-radius: 12px; | |
180 | + border-collapse: collapse; | |
181 | + border: 1px solid var(--sl-color-border); | |
182 | + margin: 1.25rem 0; | |
183 | + border-radius: 10px; | |
297 | 184 | overflow: hidden; |
298 | - border: 1px solid var(--ja-border); | |
299 | - margin: 1.5rem 0; | |
300 | -} | |
301 | - | |
302 | -.content thead { | |
303 | - background: var(--ja-bg-3); | |
304 | 185 | } |
305 | 186 | |
306 | 187 | .content th { |
307 | 188 | font-weight: 600; |
308 | 189 | text-align: left; |
309 | - padding: 0.75rem 1rem; | |
310 | - border-bottom: 2px solid var(--ja-border); | |
311 | - color: var(--ja-accent); | |
190 | + padding: 0.65rem 0.9rem; | |
191 | + background: var(--ja-bg-3); | |
192 | + border-bottom: 1px solid var(--sl-color-border); | |
312 | 193 | } |
313 | 194 | |
314 | 195 | .content td { |
315 | - padding: 0.75rem 1rem; | |
316 | - border-bottom: 1px solid var(--ja-border); | |
196 | + padding: 0.65rem 0.9rem; | |
197 | + border-bottom: 1px solid var(--sl-color-border); | |
317 | 198 | } |
318 | 199 | |
319 | -.content tbody tr { | |
320 | - transition: background 0.15s ease; | |
200 | +.content tbody tr:last-child td { border-bottom: none; } | |
201 | +.content tbody tr:hover { background: var(--ja-bg-3); } | |
202 | + | |
203 | +/* βββ Callouts βββ */ | |
204 | +.starlight-aside { border-radius: 10px; border-left-width: 3px; padding: 0.9rem 1.1rem; margin: 1.25rem 0; } | |
205 | +.starlight-aside--note { border-left-color: var(--ja-accent-2); background: color-mix(in srgb, var(--ja-accent-2) 6%, transparent); } | |
206 | +.starlight-aside--tip { border-left-color: var(--ja-green); background: color-mix(in srgb, var(--ja-green) 6%, transparent); } | |
207 | +.starlight-aside--caution { border-left-color: #f59e0b; background: color-mix(in srgb, #f59e0b 6%, transparent); } | |
208 | +.starlight-aside--danger { border-left-color: var(--ja-red); background: color-mix(in srgb, var(--ja-red) 6%, transparent); } | |
209 | + | |
210 | +/* βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
211 | + Landing page β shadcn-style components | |
212 | + ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ βββ */ | |
213 | + | |
214 | +/* Hero */ | |
215 | +.ja-hero { | |
216 | + position: relative; | |
217 | + text-align: center; | |
218 | + padding: 4rem 1rem 3rem; | |
219 | + margin: 0 0 2rem; | |
321 | 220 | } |
322 | 221 | |
323 | -.content tbody tr:hover { | |
324 | - background: var(--ja-bg-3); | |
222 | +.ja-hero-badge { | |
223 | + display: inline-flex; | |
224 | + align-items: center; | |
225 | + gap: 0.4rem; | |
226 | + padding: 0.25rem 0.75rem; | |
227 | + border-radius: 9999px; | |
228 | + border: 1px solid var(--sl-color-border); | |
229 | + background: var(--ja-bg-2); | |
230 | + font-size: 0.8rem; | |
231 | + color: var(--ja-muted); | |
232 | + margin-bottom: 1.25rem; | |
325 | 233 | } |
326 | 234 | |
327 | -/* βββ Callouts βββ */ | |
328 | -.starlight-aside { | |
329 | - border-radius: 12px; | |
330 | - border-left-width: 4px; | |
331 | - padding: 1rem 1.25rem; | |
332 | - margin: 1.5rem 0; | |
235 | +.ja-hero-badge .dot { | |
236 | + width: 6px; height: 6px; | |
237 | + border-radius: 9999px; | |
238 | + background: var(--ja-green); | |
239 | + animation: pulse 2s ease-in-out infinite; | |
333 | 240 | } |
334 | 241 | |
335 | -.starlight-aside--note { border-left-color: var(--ja-accent-2); background: rgba(0, 212, 255, 0.06); } | |
336 | -.starlight-aside--tip { border-left-color: var(--ja-green); background: rgba(0, 255, 157, 0.06); } | |
337 | -.starlight-aside--caution { border-left-color: #ffb454; background: rgba(255, 180, 84, 0.06); } | |
338 | -.starlight-aside--danger { border-left-color: var(--ja-red); background: rgba(255, 46, 77, 0.06); } | |
242 | +@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } } | |
339 | 243 | |
340 | -/* βββ Sci-Fi Background Grid βββ */ | |
341 | -.site-frame::before, | |
342 | -body::before { | |
343 | - content: ''; | |
344 | - position: fixed; | |
345 | - inset: 0; | |
346 | - z-index: -1; | |
347 | - pointer-events: none; | |
348 | - background-image: | |
349 | - linear-gradient(rgba(0, 255, 157, 0.03) 1px, transparent 1px), | |
350 | - linear-gradient(90deg, rgba(0, 255, 157, 0.03) 1px, transparent 1px); | |
351 | - background-size: 48px 48px; | |
352 | - animation: gridScroll 24s linear infinite; | |
244 | +.ja-hero h1 { | |
245 | + font-size: clamp(2.4rem, 6vw, 3.75rem); | |
246 | + font-weight: 800; | |
247 | + letter-spacing: -0.03em; | |
248 | + line-height: 1.1; | |
249 | + margin: 0 0 1rem; | |
250 | + background: linear-gradient(180deg, var(--ja-white), var(--ja-muted)); | |
251 | + -webkit-background-clip: text; | |
252 | + -webkit-text-fill-color: transparent; | |
253 | + background-clip: text; | |
353 | 254 | } |
354 | 255 | |
355 | -[data-theme='light'] body::before { | |
356 | - background-image: | |
357 | - linear-gradient(rgba(0, 146, 92, 0.04) 1px, transparent 1px), | |
358 | - linear-gradient(90deg, rgba(0, 146, 92, 0.04) 1px, transparent 1px); | |
256 | +.ja-hero h1 .grad { | |
257 | + background: linear-gradient(90deg, var(--ja-accent), var(--ja-accent-2)); | |
258 | + -webkit-background-clip: text; | |
259 | + -webkit-text-fill-color: transparent; | |
260 | + background-clip: text; | |
359 | 261 | } |
360 | 262 | |
361 | -@keyframes gridScroll { | |
362 | - from { background-position: 0 0; } | |
363 | - to { background-position: 0 48px; } | |
263 | +.ja-hero-sub { | |
264 | + font-size: 1.1rem; | |
265 | + color: var(--ja-muted); | |
266 | + max-width: 34rem; | |
267 | + margin: 0 auto 2rem; | |
364 | 268 | } |
365 | 269 | |
366 | -/* βββ Scanline sweep βββ */ | |
367 | -.main-frame::after, | |
368 | -body::after { | |
369 | - content: ''; | |
370 | - position: fixed; | |
371 | - left: 0; | |
372 | - right: 0; | |
373 | - height: 120px; | |
374 | - z-index: 9999; | |
375 | - pointer-events: none; | |
376 | - background: linear-gradient(180deg, transparent, rgba(0, 255, 157, 0.04), transparent); | |
377 | - animation: scanSweep 7s linear infinite; | |
270 | +.ja-hero-actions { | |
271 | + display: flex; | |
272 | + gap: 0.75rem; | |
273 | + justify-content: center; | |
274 | + flex-wrap: wrap; | |
378 | 275 | } |
379 | 276 | |
380 | -[data-theme='light'] body::after { | |
381 | - background: linear-gradient(180deg, transparent, rgba(0, 146, 92, 0.05), transparent); | |
277 | +.ja-btn { | |
278 | + display: inline-flex; | |
279 | + align-items: center; | |
280 | + gap: 0.4rem; | |
281 | + padding: 0.55rem 1.25rem; | |
282 | + border-radius: 8px; | |
283 | + font-size: 0.9rem; | |
284 | + font-weight: 600; | |
285 | + transition: all 0.15s ease; | |
286 | + border: 1px solid transparent; | |
382 | 287 | } |
383 | 288 | |
384 | -@keyframes scanSweep { | |
385 | - from { top: -120px; } | |
386 | - to { top: 100vh; } | |
289 | +.ja-btn--primary { | |
290 | + background: var(--ja-accent); | |
291 | + color: #052e16; | |
387 | 292 | } |
388 | - | |
389 | -/* βββ Glow Effects βββ */ | |
390 | -.content h2::after { | |
391 | - content: ''; | |
392 | - display: block; | |
393 | - width: 3rem; | |
394 | - height: 3px; | |
395 | - margin-top: 0.5rem; | |
396 | - background: linear-gradient(90deg, var(--ja-accent), transparent); | |
397 | - animation: glowPulse 3s ease-in-out infinite; | |
293 | +.ja-btn--primary:hover { | |
294 | + filter: brightness(1.1); | |
295 | + text-decoration: none; | |
398 | 296 | } |
297 | +[data-theme='light'] .ja-btn--primary { color: #fff; } | |
399 | 298 | |
400 | -@keyframes glowPulse { | |
401 | - 0%, 100% { opacity: 0.6; } | |
402 | - 50% { opacity: 1; box-shadow: 0 0 12px rgba(0, 255, 157, 0.6); } | |
299 | +.ja-btn--ghost { | |
300 | + border-color: var(--sl-color-border); | |
301 | + color: var(--ja-white); | |
302 | + background: transparent; | |
403 | 303 | } |
304 | +.ja-btn--ghost:hover { background: var(--ja-bg-3); text-decoration: none; } | |
404 | 305 | |
405 | -/* βββ Feature Cards βββ */ | |
406 | -.feature-grid { | |
306 | +/* Stats */ | |
307 | +.ja-stats { | |
407 | 308 | display: grid; |
408 | - grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); | |
409 | - gap: 1.5rem; | |
309 | + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); | |
310 | + gap: 0.75rem; | |
410 | 311 | margin: 2rem 0; |
411 | 312 | } |
412 | 313 | |
413 | -.feature-card { | |
414 | - border: 1px solid var(--ja-border); | |
415 | - border-radius: 16px; | |
416 | - padding: 1.75rem; | |
314 | +.ja-stat { | |
315 | + border: 1px solid var(--sl-color-border); | |
316 | + border-radius: 12px; | |
317 | + padding: 1.1rem 0.75rem; | |
318 | + text-align: center; | |
417 | 319 | background: var(--ja-panel); |
418 | - backdrop-filter: blur(12px); | |
419 | - transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); | |
420 | - position: relative; | |
421 | - overflow: hidden; | |
422 | -} | |
423 | - | |
424 | -.feature-card::before { | |
425 | - content: ''; | |
426 | - position: absolute; | |
427 | - top: 0; | |
428 | - left: 0; | |
429 | - right: 0; | |
430 | - height: 3px; | |
431 | - background: linear-gradient(90deg, var(--ja-accent), var(--ja-accent-2)); | |
432 | - opacity: 0; | |
433 | - transition: opacity 0.25s ease; | |
320 | + transition: border-color 0.2s ease, box-shadow 0.2s ease; | |
434 | 321 | } |
435 | 322 | |
436 | -.feature-card:hover { | |
323 | +.ja-stat:hover { | |
437 | 324 | border-color: var(--ja-accent); |
438 | - transform: translateY(-4px); | |
439 | - box-shadow: 0 0 30px rgba(0, 255, 157, 0.15); | |
325 | + box-shadow: 0 4px 20px -4px color-mix(in srgb, var(--ja-accent) 25%, transparent); | |
440 | 326 | } |
441 | 327 | |
442 | -.feature-card:hover::before { opacity: 1; } | |
443 | - | |
444 | -.feature-card h3 { | |
445 | - margin-top: 0; | |
446 | - font-size: 1.1rem; | |
447 | - font-weight: 600; | |
328 | +.ja-stat-value { | |
329 | + font-size: 1.6rem; | |
330 | + font-weight: 800; | |
448 | 331 | color: var(--ja-white); |
332 | + font-family: 'JetBrains Mono', monospace; | |
333 | + font-variant-numeric: tabular-nums; | |
449 | 334 | } |
450 | 335 | |
451 | -/* βββ Benchmark Card βββ */ | |
452 | -.benchmark-card { | |
453 | - border: 1px solid rgba(0, 255, 157, 0.3); | |
454 | - border-radius: 16px; | |
455 | - padding: 1.75rem; | |
456 | - background: var(--ja-panel); | |
457 | - backdrop-filter: blur(16px); | |
458 | - margin-bottom: 1.5rem; | |
459 | - position: relative; | |
460 | - overflow: hidden; | |
336 | +.ja-stat-label { | |
337 | + font-size: 0.8rem; | |
338 | + color: var(--ja-muted); | |
339 | + margin-top: 0.25rem; | |
461 | 340 | } |
462 | 341 | |
463 | -.benchmark-card::before { | |
464 | - content: ''; | |
465 | - position: absolute; | |
466 | - top: 0; | |
467 | - left: 0; | |
468 | - right: 0; | |
469 | - height: 2px; | |
470 | - background: linear-gradient(90deg, var(--ja-green), var(--ja-accent), var(--ja-accent-2)); | |
471 | - background-size: 200% 100%; | |
472 | - animation: gradientShift 4s linear infinite; | |
342 | +/* Cards (shadcn-style) */ | |
343 | +.ja-grid { | |
344 | + display: grid; | |
345 | + grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); | |
346 | + gap: 0.9rem; | |
347 | + margin: 1.5rem 0; | |
473 | 348 | } |
474 | 349 | |
475 | -@keyframes gradientShift { | |
476 | - from { background-position: 0 0; } | |
477 | - to { background-position: 200% 0; } | |
350 | +.ja-card { | |
351 | + border: 1px solid var(--sl-color-border); | |
352 | + border-radius: 12px; | |
353 | + padding: 1.25rem; | |
354 | + background: var(--ja-panel); | |
355 | + transition: border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease; | |
478 | 356 | } |
479 | 357 | |
480 | -/* βββ Performance Table βββ */ | |
481 | -.performance-table { | |
482 | - width: 100%; | |
483 | - border-collapse: separate; | |
484 | - border-spacing: 0; | |
485 | - border-radius: 12px; | |
486 | - overflow: hidden; | |
487 | - border: 1px solid var(--ja-border); | |
358 | +.ja-card:hover { | |
359 | + border-color: color-mix(in srgb, var(--ja-accent) 60%, var(--sl-color-border)); | |
360 | + box-shadow: 0 8px 30px -8px color-mix(in srgb, var(--ja-accent) 20%, transparent); | |
488 | 361 | } |
489 | 362 | |
490 | -.performance-table th { | |
491 | - text-align: left; | |
492 | - padding: 1rem 1.25rem; | |
493 | - font-weight: 600; | |
494 | - background: var(--ja-bg-3); | |
363 | +.ja-card-icon { | |
364 | + width: 2rem; | |
365 | + height: 2rem; | |
366 | + border-radius: 8px; | |
367 | + display: flex; | |
368 | + align-items: center; | |
369 | + justify-content: center; | |
370 | + font-size: 1rem; | |
371 | + margin-bottom: 0.75rem; | |
372 | + background: color-mix(in srgb, var(--ja-accent) 12%, transparent); | |
495 | 373 | color: var(--ja-accent); |
496 | 374 | } |
497 | 375 | |
498 | -.performance-table td { | |
499 | - padding: 1rem 1.25rem; | |
500 | - text-align: right; | |
376 | +.ja-card h3 { | |
377 | + font-size: 0.95rem; | |
378 | + font-weight: 600; | |
379 | + margin: 0 0 0.4rem; | |
380 | + color: var(--ja-white); | |
501 | 381 | } |
502 | 382 | |
503 | -.performance-table td:first-child { | |
504 | - text-align: left; | |
505 | - font-weight: 600; | |
383 | +.ja-card p { | |
384 | + font-size: 0.85rem; | |
385 | + color: var(--ja-muted); | |
386 | + margin: 0; | |
387 | + line-height: 1.6; | |
506 | 388 | } |
507 | 389 | |
508 | -.performance-table .winner { | |
509 | - color: var(--ja-green); | |
510 | - font-weight: 700; | |
511 | - font-size: 1.1em; | |
512 | - text-shadow: 0 0 10px rgba(0, 255, 157, 0.5); | |
390 | +/* Tabs (shadcn) */ | |
391 | +.ja-tabs { | |
392 | + border: 1px solid var(--sl-color-border); | |
393 | + border-radius: 12px; | |
394 | + overflow: hidden; | |
395 | + background: var(--ja-panel); | |
396 | + margin: 1.5rem 0; | |
513 | 397 | } |
514 | 398 | |
515 | -/* βββ Sidebar βββ */ | |
516 | -.sidebar-title { | |
517 | - font-weight: 700; | |
518 | - font-size: 0.8rem; | |
519 | - text-transform: uppercase; | |
520 | - letter-spacing: 0.05em; | |
399 | +.ja-tabs-bar { | |
400 | + display: flex; | |
401 | + gap: 0.25rem; | |
402 | + padding: 0.4rem; | |
403 | + border-bottom: 1px solid var(--sl-color-border); | |
404 | + background: var(--ja-bg-2); | |
405 | + overflow-x: auto; | |
406 | +} | |
407 | + | |
408 | +.ja-tab-btn { | |
409 | + padding: 0.4rem 0.9rem; | |
410 | + border-radius: 8px; | |
411 | + font-size: 0.82rem; | |
412 | + font-weight: 500; | |
521 | 413 | color: var(--ja-muted); |
414 | + border: none; | |
415 | + background: transparent; | |
416 | + cursor: pointer; | |
417 | + white-space: nowrap; | |
418 | + transition: all 0.15s ease; | |
419 | + font-family: inherit; | |
522 | 420 | } |
523 | 421 | |
524 | -/* βββ Badges βββ */ | |
525 | -.badge--success { | |
526 | - background: rgba(0, 255, 157, 0.15); | |
527 | - color: var(--ja-green); | |
528 | - border: 1px solid rgba(0, 255, 157, 0.3); | |
529 | - border-radius: 9999px; | |
530 | - padding: 0.15em 0.6em; | |
531 | - font-size: 0.75rem; | |
532 | - font-weight: 600; | |
422 | +.ja-tab-btn:hover { color: var(--ja-white); background: var(--ja-bg-3); } | |
423 | +.ja-tab-btn[data-active='true'] { | |
424 | + color: var(--ja-white); | |
425 | + background: var(--ja-bg-3); | |
533 | 426 | } |
534 | 427 | |
535 | -/* βββ Cards βββ */ | |
536 | -.sl-card { | |
428 | +.ja-tab-panel { padding: 1rem; } | |
429 | +.ja-tab-panel pre { margin: 0; border: none; background: transparent; } | |
430 | + | |
431 | +/* Terminal */ | |
432 | +.ja-terminal { | |
433 | + border: 1px solid var(--sl-color-border); | |
537 | 434 | border-radius: 12px; |
538 | - border: 1px solid var(--ja-border); | |
539 | - transition: all 0.2s ease; | |
540 | - background: var(--ja-panel); | |
435 | + overflow: hidden; | |
436 | + margin: 1.5rem 0; | |
437 | + background: var(--ja-bg-2); | |
541 | 438 | } |
542 | 439 | |
543 | -.sl-card:hover { | |
544 | - border-color: var(--ja-accent); | |
545 | - box-shadow: 0 0 24px rgba(0, 255, 157, 0.15); | |
440 | +.ja-terminal-bar { | |
441 | + display: flex; | |
442 | + align-items: center; | |
443 | + gap: 0.4rem; | |
444 | + padding: 0.55rem 0.9rem; | |
445 | + background: var(--ja-bg-3); | |
446 | + border-bottom: 1px solid var(--sl-color-border); | |
546 | 447 | } |
547 | 448 | |
548 | -/* βββ Search βββ */ | |
549 | -.search-input { | |
550 | - border-radius: 10px !important; | |
551 | - font-size: 0.9rem !important; | |
552 | -} | |
449 | +.ja-terminal-dot { width: 10px; height: 10px; border-radius: 9999px; } | |
450 | +.ja-terminal-dot:nth-child(1) { background: #ef4444; } | |
451 | +.ja-terminal-dot:nth-child(2) { background: #f59e0b; } | |
452 | +.ja-terminal-dot:nth-child(3) { background: var(--ja-green); } | |
553 | 453 | |
554 | -/* βββ Mobile Responsive βββ */ | |
555 | -@media (max-width: 768px) { | |
556 | - .content h1 { font-size: 1.75rem; } | |
557 | - .content h2 { font-size: 1.3rem; } | |
558 | - .feature-grid { grid-template-columns: 1fr; } | |
559 | - .performance-table { font-size: 0.8rem; } | |
454 | +.ja-terminal-title { | |
455 | + margin-left: 0.5rem; | |
456 | + font-size: 0.75rem; | |
457 | + color: var(--ja-muted); | |
458 | + font-family: 'JetBrains Mono', monospace; | |
560 | 459 | } |
561 | 460 | |
562 | -/* βββ Print βββ */ | |
563 | -@media print { | |
564 | - .sidebar, .toc-panel, .edit-link, .prev-next-nav { display: none !important; } | |
565 | - .content { max-width: 100%; } | |
461 | +.ja-terminal-body { | |
462 | + padding: 1rem 1.1rem; | |
463 | + font-family: 'JetBrains Mono', monospace; | |
464 | + font-size: 0.8rem; | |
465 | + line-height: 1.7; | |
466 | + color: var(--ja-green); | |
467 | + overflow-x: auto; | |
566 | 468 | } |
567 | 469 | |
568 | -/* βββ Accessibility βββ */ | |
569 | -:focus-visible { | |
570 | - outline: 2px solid var(--ja-accent); | |
571 | - outline-offset: 2px; | |
572 | -} | |
470 | +.ja-terminal-body .cm { color: var(--ja-muted); } | |
471 | +.ja-terminal-body .ok { color: var(--ja-green); } | |
472 | +.ja-terminal-body .err { color: var(--ja-red); } | |
473 | +.ja-terminal-body .dim { color: var(--ja-muted); } | |
573 | 474 | |
574 | -::selection { | |
575 | - background: rgba(0, 255, 157, 0.3); | |
576 | - color: var(--ja-white); | |
577 | -} | |
475 | +/* Benchmark bars */ | |
476 | +.ja-bars { margin: 1.5rem 0; display: flex; flex-direction: column; gap: 0.6rem; } | |
578 | 477 | |
579 | -[data-theme='light'] ::selection { | |
580 | - background: rgba(0, 146, 92, 0.2); | |
478 | +.ja-bar-row { | |
479 | + display: grid; | |
480 | + grid-template-columns: 7rem 1fr 4rem; | |
481 | + align-items: center; | |
482 | + gap: 0.75rem; | |
483 | + font-size: 0.85rem; | |
581 | 484 | } |
582 | 485 | |
583 | -/* βββ Scrollbar βββ */ | |
584 | -::-webkit-scrollbar { width: 8px; height: 8px; } | |
585 | -::-webkit-scrollbar-track { background: transparent; } | |
586 | -::-webkit-scrollbar-thumb { | |
587 | - background: var(--ja-border); | |
588 | - border-radius: 4px; | |
486 | +.ja-bar-label { color: var(--ja-muted); text-align: right; font-weight: 500; } | |
487 | +.ja-bar-track { | |
488 | + height: 1.6rem; | |
489 | + border-radius: 6px; | |
490 | + background: var(--ja-bg-3); | |
491 | + overflow: hidden; | |
589 | 492 | } |
590 | -::-webkit-scrollbar-thumb:hover { background: var(--ja-accent); } | |
591 | 493 | |
592 | -/* βββ Animations βββ */ | |
593 | -@keyframes fadeInUp { | |
594 | - from { opacity: 0; transform: translateY(12px); } | |
595 | - to { opacity: 1; transform: translateY(0); } | |
494 | +.ja-bar-fill { | |
495 | + height: 100%; | |
496 | + border-radius: 6px; | |
497 | + background: linear-gradient(90deg, var(--ja-accent), var(--ja-accent-2)); | |
498 | + width: 0%; | |
596 | 499 | } |
597 | 500 | |
598 | -.content > * { | |
599 | - animation: fadeInUp 0.3s ease-out; | |
501 | +.ja-bar-row--winner .ja-bar-fill { background: linear-gradient(90deg, var(--ja-green), var(--ja-accent-2)); } | |
502 | +.ja-bar-row--winner .ja-bar-label { color: var(--ja-green); font-weight: 700; } | |
503 | +.ja-bar-value { font-family: 'JetBrains Mono', monospace; font-size: 0.8rem; color: var(--ja-white); } | |
504 | + | |
505 | +/* CTA */ | |
506 | +.ja-cta { | |
507 | + border: 1px solid var(--sl-color-border); | |
508 | + border-radius: 16px; | |
509 | + padding: 2.5rem 1.5rem; | |
510 | + text-align: center; | |
511 | + margin: 2.5rem 0 1rem; | |
512 | + background: | |
513 | + radial-gradient(ellipse at top, color-mix(in srgb, var(--ja-accent) 8%, transparent), transparent 60%), | |
514 | + var(--ja-panel); | |
600 | 515 | } |
601 | 516 | |
602 | -/* βββ Code Group Tabs βββ */ | |
603 | -.tab-label { | |
604 | - font-family: 'JetBrains Mono', monospace; | |
605 | - font-size: 0.8rem; | |
517 | +.ja-cta-title { | |
518 | + font-size: 1.6rem; | |
519 | + font-weight: 800; | |
520 | + margin: 0 0 0.5rem; | |
521 | + color: var(--ja-white); | |
606 | 522 | } |
607 | 523 | |
608 | -/* βββ Theme Switcher Widget βββ */ | |
524 | +.ja-cta-sub { color: var(--ja-muted); margin: 0 0 1.5rem; font-size: 0.95rem; } | |
525 | + | |
526 | +/* Theme switcher */ | |
609 | 527 | .ja-theme-switcher { |
610 | 528 | position: fixed; |
611 | - bottom: 1.25rem; | |
612 | - right: 1.25rem; | |
529 | + bottom: 1rem; | |
530 | + right: 1rem; | |
613 | 531 | z-index: 1000; |
614 | 532 | display: flex; |
615 | - gap: 0.35rem; | |
616 | - padding: 0.35rem; | |
533 | + gap: 0.3rem; | |
534 | + padding: 0.3rem; | |
617 | 535 | border-radius: 9999px; |
618 | - border: 1px solid var(--ja-border); | |
536 | + border: 1px solid var(--sl-color-border); | |
619 | 537 | background: var(--ja-panel); |
620 | - backdrop-filter: blur(12px); | |
538 | + box-shadow: 0 4px 20px -4px rgba(0,0,0,0.4); | |
621 | 539 | } |
622 | 540 | |
623 | 541 | .ja-theme-btn { |
624 | - width: 2rem; | |
625 | - height: 2rem; | |
542 | + width: 1.75rem; | |
543 | + height: 1.75rem; | |
626 | 544 | border-radius: 9999px; |
627 | 545 | border: 1px solid transparent; |
628 | 546 | cursor: pointer; |
629 | 547 | transition: all 0.2s ease; |
630 | - position: relative; | |
631 | 548 | } |
632 | - | |
633 | 549 | .ja-theme-btn:hover { transform: scale(1.15); } |
634 | -.ja-theme-btn[data-active='true'] { | |
635 | - border-color: var(--ja-white); | |
636 | - box-shadow: 0 0 12px currentColor; | |
637 | -} | |
550 | +.ja-theme-btn[data-active='true'] { border-color: var(--ja-white); box-shadow: 0 0 8px currentColor; } | |
638 | 551 | |
639 | -.ja-theme-btn--dark { background: #05080f; color: #00ff9d; } | |
640 | -.ja-theme-btn--light { background: #f4f7fb; color: #00925c; } | |
552 | +.ja-theme-btn--dark { background: #09090b; color: #22c55e; } | |
553 | +.ja-theme-btn--light { background: #ffffff; color: #16a34a; } | |
641 | 554 | .ja-theme-btn--dracula { background: #282a36; color: #bd93f9; } |
642 | 555 | .ja-theme-btn--rosepine { background: #191724; color: #c4a7e7; } |
643 | 556 | .ja-theme-btn--warm { background: #1c1412; color: #ff9d5c; } |
644 | 557 | |
645 | -/* βββ Landing Page βββ */ | |
646 | -.ja-hero { | |
647 | - position: relative; | |
648 | - border: 1px solid var(--ja-border); | |
649 | - border-radius: 24px; | |
650 | - overflow: hidden; | |
651 | - margin: 1.5rem 0; | |
652 | - background: var(--ja-bg-2); | |
653 | -} | |
654 | - | |
655 | -.ja-hero img { | |
656 | - display: block; | |
657 | - width: 100%; | |
658 | - height: auto; | |
659 | -} | |
660 | - | |
661 | -.ja-stats { | |
662 | - display: grid; | |
663 | - grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); | |
664 | - gap: 1rem; | |
665 | - margin: 2rem 0; | |
666 | -} | |
667 | - | |
668 | -.ja-stat { | |
669 | - border: 1px solid var(--ja-border); | |
670 | - border-radius: 16px; | |
671 | - padding: 1.25rem; | |
672 | - text-align: center; | |
673 | - background: var(--ja-panel); | |
674 | - transition: all 0.25s ease; | |
675 | -} | |
676 | - | |
677 | -.ja-stat:hover { | |
678 | - border-color: var(--ja-accent); | |
679 | - transform: translateY(-3px); | |
680 | - box-shadow: 0 0 24px rgba(0, 255, 157, 0.12); | |
681 | -} | |
682 | - | |
683 | -.ja-stat-value { | |
684 | - font-size: 2rem; | |
685 | - font-weight: 800; | |
686 | - color: var(--ja-accent); | |
687 | - font-family: 'JetBrains Mono', monospace; | |
688 | - text-shadow: 0 0 16px rgba(0, 255, 157, 0.4); | |
689 | -} | |
690 | - | |
691 | -.ja-stat-label { | |
692 | - font-size: 0.85rem; | |
693 | - color: var(--ja-muted); | |
694 | - margin-top: 0.25rem; | |
695 | -} | |
696 | - | |
697 | -/* βββ Landing: Code Terminal βββ */ | |
698 | -.ja-terminal { | |
699 | - border: 1px solid var(--ja-border); | |
700 | - border-radius: 16px; | |
701 | - overflow: hidden; | |
702 | - margin: 2rem 0; | |
703 | - background: var(--ja-bg-2); | |
704 | -} | |
705 | - | |
706 | -.ja-terminal-bar { | |
558 | +/* Section headings on landing */ | |
559 | +.ja-section { | |
560 | + margin: 2.5rem 0 1.25rem; | |
561 | + font-size: 1.1rem; | |
562 | + font-weight: 700; | |
563 | + color: var(--ja-white); | |
707 | 564 | display: flex; |
708 | 565 | align-items: center; |
709 | 566 | gap: 0.5rem; |
710 | - padding: 0.6rem 1rem; | |
711 | - background: var(--ja-bg-3); | |
712 | - border-bottom: 1px solid var(--ja-border); | |
713 | 567 | } |
714 | 568 | |
715 | -.ja-terminal-dot { | |
716 | - width: 12px; | |
717 | - height: 12px; | |
718 | - border-radius: 9999px; | |
719 | -} | |
720 | - | |
721 | -.ja-terminal-dot:nth-child(1) { background: #ff2e4d; } | |
722 | -.ja-terminal-dot:nth-child(2) { background: #ffb454; } | |
723 | -.ja-terminal-dot:nth-child(3) { background: #00ff9d; } | |
724 | - | |
725 | -.ja-terminal-body { | |
726 | - padding: 1.25rem; | |
727 | - font-family: 'JetBrains Mono', monospace; | |
728 | - font-size: 0.85rem; | |
729 | - color: var(--ja-green); | |
730 | - line-height: 1.7; | |
731 | -} | |
732 | - | |
733 | -.ja-terminal-body .cm { color: var(--ja-muted); } | |
734 | -.ja-terminal-body .ok { color: var(--ja-green); } | |
735 | -.ja-terminal-body .err { color: var(--ja-red); } | |
736 | - | |
737 | -/* βββ Landing: Feature Matrix Graph βββ */ | |
738 | -.ja-graph { | |
739 | - border: 1px solid var(--ja-border); | |
740 | - border-radius: 16px; | |
741 | - padding: 1rem; | |
742 | - background: var(--ja-bg-2); | |
743 | - margin: 2rem 0; | |
569 | +.ja-section::after { | |
570 | + content: ''; | |
571 | + flex: 1; | |
572 | + height: 1px; | |
573 | + background: var(--sl-color-border); | |
744 | 574 | } |
745 | 575 | |
746 | -.ja-graph img { | |
747 | - display: block; | |
748 | - width: 100%; | |
749 | - height: auto; | |
750 | -} | |
576 | +/* Accessibility */ | |
577 | +:focus-visible { outline: 2px solid var(--ja-accent); outline-offset: 2px; } | |
578 | +::selection { background: color-mix(in srgb, var(--ja-accent) 25%, transparent); } | |
751 | 579 | |
752 | -/* βββ Landing: Call-to-Action βββ */ | |
753 | -.ja-cta { | |
754 | - border: 1px solid var(--ja-accent); | |
755 | - border-radius: 16px; | |
756 | - padding: 2rem; | |
757 | - text-align: center; | |
758 | - margin: 2rem 0; | |
759 | - background: | |
760 | - radial-gradient(ellipse at center, rgba(0, 255, 157, 0.08), transparent 70%), | |
761 | - var(--ja-panel); | |
762 | - animation: ctaGlow 4s ease-in-out infinite; | |
763 | -} | |
580 | +/* Scrollbar */ | |
581 | +::-webkit-scrollbar { width: 8px; height: 8px; } | |
582 | +::-webkit-scrollbar-track { background: transparent; } | |
583 | +::-webkit-scrollbar-thumb { background: var(--sl-color-gray-5); border-radius: 4px; } | |
584 | +::-webkit-scrollbar-thumb:hover { background: var(--sl-color-gray-4); } | |
764 | 585 | |
765 | -@keyframes ctaGlow { | |
766 | - 0%, 100% { box-shadow: 0 0 20px rgba(0, 255, 157, 0.1); } | |
767 | - 50% { box-shadow: 0 0 40px rgba(0, 255, 157, 0.25); } | |
586 | +/* Mobile */ | |
587 | +@media (max-width: 768px) { | |
588 | + .content h1 { font-size: 1.6rem; } | |
589 | + .ja-hero { padding: 2.5rem 0.5rem 2rem; } | |
590 | + .ja-bar-row { grid-template-columns: 5.5rem 1fr 3.5rem; } | |
591 | + .ja-stats { grid-template-columns: repeat(2, 1fr); } | |
768 | 592 | } |
769 | 593 | |
770 | -.ja-cta-title { | |
771 | - font-size: 1.75rem; | |
772 | - font-weight: 800; | |
773 | - background: linear-gradient(90deg, var(--ja-white), var(--ja-accent)); | |
774 | - -webkit-background-clip: text; | |
775 | - -webkit-text-fill-color: transparent; | |
776 | - background-clip: text; | |
777 | -} | |
594 | +/* Print */ | |
595 | +@media print { .sidebar, .toc-panel, .edit-link, .prev-next-nav, .ja-theme-switcher { display: none !important; } } | |
778 | 596 | |