swadhinbiswas

[email protected]
2026-07-17 20:48:21 +0600 committed NaN years ago
288fa63
commit 288fa63
5 files changed
+233 -223
▼Dockerfile
+10-3
6
6
org.opencontainers.image.source="https://github.com/swadhinbiswas/OpencodeHub" \
7
7
org.opencontainers.image.licenses="MIT"
8
8
9
-# Install dependencies
9
+# Install ALL dependencies (needed for build including CSS tooling)
10
10
FROM base AS deps
11
11
RUN apt-get update && apt-get install -y python3 make g++ gcc libc6-dev && rm -rf /var/lib/apt/lists/*
12
12
COPY package.json bun.lock ./
13
13
COPY cli/package.json ./cli/package.json
14
14
RUN for i in 1 2 3; do \
15
- bun install --frozen-lockfile --production && break || \
15
+ bun install --frozen-lockfile && break || \
16
16
(echo "bun install attempt $i failed, retrying in 10s..." && sleep 10); \
17
17
done
18
18
19
+# Install production dependencies only (for runtime image)
20
+FROM base AS prod-deps
21
+RUN apt-get update && apt-get install -y python3 make g++ gcc libc6-dev && rm -rf /var/lib/apt/lists/*
22
+COPY package.json bun.lock ./
23
+COPY cli/package.json ./cli/package.json
24
+RUN bun install --frozen-lockfile --production
25
+
19
26
# Build the application
20
27
FROM base AS builder
21
28
COPY --from=deps /app/node_modules ./node_modules
37
44
38
45
# Copy only what's needed for runtime
39
46
COPY --from=builder --chown=bun:bun /app/dist ./dist
40
-COPY --from=deps --chown=bun:bun /app/node_modules ./node_modules
47
+COPY --from=prod-deps --chown=bun:bun /app/node_modules ./node_modules
41
48
COPY --from=builder --chown=bun:bun /app/package.json ./
42
49
43
50
# Copy drizzle config and schema for migrations
44
51
▼astro.config.mjs
+0-4
1
1
import node from "@astrojs/node";
2
2
import react from "@astrojs/react";
3
-import tailwind from "@astrojs/tailwind";
4
3
import { defineConfig } from "astro/config";
5
4
import icon from "astro-icon";
6
5
8
7
integrations: [
9
8
react(),
10
9
icon(),
11
- tailwind({
12
- applyBaseStyles: false,
13
- }),
14
10
],
15
11
output: "server",
16
12
adapter: node({
17
13
▼bun.lock
+11-14
8
8
"@astrojs/check": "^0.9.6",
9
9
"@astrojs/node": "^8.3.0",
10
10
"@astrojs/react": "^3.6.0",
11
- "@astrojs/tailwind": "^5.1.0",
12
11
"@astrojs/vercel": "^7.7.0",
13
12
"@aws-sdk/client-s3": "^3.948.0",
14
13
"@aws-sdk/lib-storage": "^3.972.0",
56
55
"arctic": "^3.7.0",
57
56
"astro": "^4.11.0",
58
57
"astro-icon": "^1.1.5",
58
+ "autoprefixer": "^10.4.19",
59
59
"bcryptjs": "^2.4.3",
60
60
"better-sqlite3": "^11.1.2",
61
61
"bullmq": "^5.65.1",
93
93
"pg": "^8.16.3",
94
94
"pino": "^10.1.0",
95
95
"pino-loki": "^3.0.0",
96
+ "postcss": "~8.4.49",
96
97
"postgres": "^3.4.7",
97
98
"prom-client": "^15.1.3",
98
99
"qrcode": "^1.5.4",
111
112
"sonner": "^2.0.7",
112
113
"ssh2": "^1.15.0",
113
114
"tailwind-merge": "^2.6.0",
115
+ "tailwindcss": "^3.4.4",
114
116
"tailwindcss-animate": "^1.0.7",
115
117
"three": "^0.182.0",
116
118
"unified": "^11.0.5",
137
139
"@types/ssh2": "^1.15.0",
138
140
"@types/three": "^0.182.0",
139
141
"@vitest/coverage-v8": "^4.1.5",
140
- "autoprefixer": "^10.4.19",
141
142
"drizzle-kit": "^0.31.8",
142
143
"pino-pretty": "^13.1.3",
143
- "postcss": "~8.4.49",
144
- "tailwindcss": "^3.4.4",
145
144
"typescript": "^5.9.3",
146
145
"vitest": "^4.1.5",
147
146
},
231
230
232
231
"@astrojs/react": ["@astrojs/[email protected]", "https://registry.npmmirror.com/@astrojs/react/-/react-3.6.3.tgz", { "dependencies": { "@vitejs/plugin-react": "^4.3.3", "ultrahtml": "^1.5.3", "vite": "^5.4.10" }, "peerDependencies": { "@types/react": "^17.0.50 || ^18.0.21", "@types/react-dom": "^17.0.17 || ^18.0.6", "react": "^17.0.2 || ^18.0.0 || ^19.0.0-beta", "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0-beta" } }, "sha512-5ihLQDH5Runddug5AZYlnp/Q5T81QxhwnWJXA9rchBAdh11c6UhBbv9Kdk7b2PkXoEU70CGWBP9hSh0VCR58eA=="],
233
232
234
- "@astrojs/tailwind": ["@astrojs/[email protected]", "https://registry.npmmirror.com/@astrojs/tailwind/-/tailwind-5.1.5.tgz", { "dependencies": { "autoprefixer": "^10.4.20", "postcss": "^8.5.1", "postcss-load-config": "^4.0.2" }, "peerDependencies": { "astro": "^3.0.0 || ^4.0.0 || ^5.0.0", "tailwindcss": "^3.0.24" } }, "sha512-1diguZEau7FZ9vIjzE4BwavGdhD3+JkdS8zmibl1ene+EHgIU5hI0NMgRYG3yea+Niaf7cyMwjeWeLvzq/maxg=="],
235
-
236
233
"@astrojs/telemetry": ["@astrojs/[email protected]", "https://registry.npmmirror.com/@astrojs/telemetry/-/telemetry-3.1.0.tgz", { "dependencies": { "ci-info": "^4.0.0", "debug": "^4.3.4", "dlv": "^1.1.3", "dset": "^3.1.3", "is-docker": "^3.0.0", "is-wsl": "^3.0.0", "which-pm-runs": "^1.1.0" } }, "sha512-/ca/+D8MIKEC8/A9cSaPUqQNZm+Es/ZinRv0ZAzvu2ios7POQSsVD+VOj7/hypWNsNM3T7RpfgNq7H2TU1KEHA=="],
237
234
238
235
"@astrojs/vercel": ["@astrojs/[email protected]", "https://registry.npmmirror.com/@astrojs/vercel/-/vercel-7.8.2.tgz", { "dependencies": { "@astrojs/internal-helpers": "^0.4.1", "@vercel/analytics": "^1.3.1", "@vercel/edge": "^1.1.2", "@vercel/nft": "^0.27.4", "esbuild": "^0.21.5", "fast-glob": "^3.3.2", "web-vitals": "^3.5.2" }, "peerDependencies": { "astro": "^4.2.0" } }, "sha512-U2JsfN0LzFMX5CPrcb+5bAAyqyYURP6Dk/mUIXX87r5x4baQy+juU+ntvf926YA0tR7u6jPRXHymE2axQ/l3NQ=="],
1451
1448
1452
1449
"cheerio-select": ["[email protected]", "https://registry.npmmirror.com/cheerio-select/-/cheerio-select-2.1.0.tgz", { "dependencies": { "boolbase": "^1.0.0", "css-select": "^5.1.0", "css-what": "^6.1.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1" } }, "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g=="],
1453
1450
1454
- "chokidar": ["[email protected]", "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
1451
+ "chokidar": ["[email protected]", "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
1455
1452
1456
1453
"chownr": ["[email protected]", "https://registry.npmmirror.com/chownr/-/chownr-1.1.4.tgz", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
1457
1454
2539
2536
2540
2537
"readable-stream": ["[email protected]", "https://registry.npmmirror.com/readable-stream/-/readable-stream-4.7.0.tgz", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="],
2541
2538
2542
- "readdirp": ["[email protected]", "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
2539
+ "readdirp": ["[email protected]", "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
2543
2540
2544
2541
"real-require": ["[email protected]", "https://registry.npmmirror.com/real-require/-/real-require-0.2.0.tgz", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
2545
2542
3037
3034
3038
3035
"@asamuzakjp/dom-selector/lru-cache": ["[email protected]", "https://registry.npmmirror.com/lru-cache/-/lru-cache-11.5.1.tgz", {}, "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A=="],
3039
3036
3040
- "@astrojs/check/chokidar": ["[email protected]", "https://registry.npmmirror.com/chokidar/-/chokidar-4.0.3.tgz", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
3041
-
3042
3037
"@astrojs/react/vite": ["[email protected]", "https://registry.npmmirror.com/vite/-/vite-5.4.21.tgz", { "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", "rollup": "^4.20.0" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" }, "optionalPeers": ["@types/node", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": { "vite": "bin/vite.js" } }, "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw=="],
3043
3038
3044
3039
"@astrojs/vercel/esbuild": ["[email protected]", "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
3153
3148
3154
3149
"cheerio/whatwg-mimetype": ["[email protected]", "https://registry.npmmirror.com/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="],
3155
3150
3156
- "chokidar/glob-parent": ["[email protected]", "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
3157
-
3158
3151
"cli-progress/string-width": ["[email protected]", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
3159
3152
3160
3153
"cli-table3/string-width": ["[email protected]", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
3285
3278
3286
3279
"svgo/css-tree": ["[email protected]", "https://registry.npmmirror.com/css-tree/-/css-tree-2.3.1.tgz", { "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" } }, "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw=="],
3287
3280
3281
+ "tailwindcss/chokidar": ["[email protected]", "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="],
3282
+
3288
3283
"tailwindcss/postcss-selector-parser": ["[email protected]", "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="],
3289
3284
3290
3285
"tar/chownr": ["[email protected]", "https://registry.npmmirror.com/chownr/-/chownr-3.0.0.tgz", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
3313
3308
3314
3309
"yargs/string-width": ["[email protected]", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
3315
3310
3316
- "@astrojs/check/chokidar/readdirp": ["[email protected]", "https://registry.npmmirror.com/readdirp/-/readdirp-4.1.2.tgz", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
3317
-
3318
3311
"@astrojs/react/vite/esbuild": ["[email protected]", "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.21.5", "@esbuild/android-arm": "0.21.5", "@esbuild/android-arm64": "0.21.5", "@esbuild/android-x64": "0.21.5", "@esbuild/darwin-arm64": "0.21.5", "@esbuild/darwin-x64": "0.21.5", "@esbuild/freebsd-arm64": "0.21.5", "@esbuild/freebsd-x64": "0.21.5", "@esbuild/linux-arm": "0.21.5", "@esbuild/linux-arm64": "0.21.5", "@esbuild/linux-ia32": "0.21.5", "@esbuild/linux-loong64": "0.21.5", "@esbuild/linux-mips64el": "0.21.5", "@esbuild/linux-ppc64": "0.21.5", "@esbuild/linux-riscv64": "0.21.5", "@esbuild/linux-s390x": "0.21.5", "@esbuild/linux-x64": "0.21.5", "@esbuild/netbsd-x64": "0.21.5", "@esbuild/openbsd-x64": "0.21.5", "@esbuild/sunos-x64": "0.21.5", "@esbuild/win32-arm64": "0.21.5", "@esbuild/win32-ia32": "0.21.5", "@esbuild/win32-x64": "0.21.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw=="],
3319
3312
3320
3313
"@astrojs/vercel/esbuild/@esbuild/aix-ppc64": ["@esbuild/[email protected]", "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", { "os": "aix", "cpu": "ppc64" }, "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ=="],
3549
3542
3550
3543
"svgo/css-tree/mdn-data": ["[email protected]", "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.0.30.tgz", {}, "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="],
3551
3544
3545
+ "tailwindcss/chokidar/glob-parent": ["[email protected]", "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
3546
+
3547
+ "tailwindcss/chokidar/readdirp": ["[email protected]", "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="],
3548
+
3552
3549
"tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/[email protected]", "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", { "os": "aix", "cpu": "ppc64" }, "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA=="],
3553
3550
3554
3551
"tsx/esbuild/@esbuild/android-arm": ["@esbuild/[email protected]", "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.28.0.tgz", { "os": "android", "cpu": "arm" }, "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ=="],
3555
3552
▼package.json
+4-5
47
47
"@astrojs/check": "^0.9.6",
48
48
"@astrojs/node": "^8.3.0",
49
49
"@astrojs/react": "^3.6.0",
50
- "@astrojs/tailwind": "^5.1.0",
51
50
"@astrojs/vercel": "^7.7.0",
52
51
"@aws-sdk/client-s3": "^3.948.0",
53
52
"@aws-sdk/lib-storage": "^3.972.0",
156
155
"unist-util-visit": "^5.1.0",
157
156
"yaml": "^2.8.0",
158
157
"zod": "^3.23.8",
159
- "zustand": "^4.5.4"
158
+ "zustand": "^4.5.4",
159
+ "autoprefixer": "^10.4.19",
160
+ "postcss": "~8.4.49",
161
+ "tailwindcss": "^3.4.4"
160
162
},
161
163
"devDependencies": {
162
164
"@axe-core/playwright": "^4.10.0",
176
178
"@types/ssh2": "^1.15.0",
177
179
"@types/three": "^0.182.0",
178
180
"@vitest/coverage-v8": "^4.1.5",
179
- "autoprefixer": "^10.4.19",
180
181
"drizzle-kit": "^0.31.8",
181
182
"pino-pretty": "^13.1.3",
182
- "postcss": "~8.4.49",
183
- "tailwindcss": "^3.4.4",
184
183
"typescript": "^5.9.3",
185
184
"vitest": "^4.1.5"
186
185
},
187
186
▼src/styles/globals.css
+208-197
4
4
5
5
@layer base {
6
6
:root {
7
+ /* Premium Design System - OpenCodeHub Light Theme */
7
8
--background: 0 0% 100%;
8
- --foreground: 222.2 84% 4.9%;
9
+ --foreground: 210 11% 15%;
9
10
--card: 0 0% 100%;
10
- --card-foreground: 222.2 84% 4.9%;
11
+ --card-foreground: 210 11% 15%;
11
12
--popover: 0 0% 100%;
12
- --popover-foreground: 222.2 84% 4.9%;
13
- --primary: 222.2 47.4% 11.2%;
14
- --primary-foreground: 210 40% 98%;
15
- --secondary: 210 40% 96.1%;
16
- --secondary-foreground: 222.2 47.4% 11.2%;
17
- --muted: 210 40% 96.1%;
18
- --muted-foreground: 215.4 16.3% 46.9%;
19
- --accent: 210 40% 96.1%;
20
- --accent-foreground: 222.2 47.4% 11.2%;
21
- --destructive: 0 84.2% 60.2%;
22
- --destructive-foreground: 210 40% 98%;
23
- --border: 214.3 31.8% 91.4%;
24
- --input: 214.3 31.8% 91.4%;
25
- --ring: 222.2 84% 4.9%;
13
+ --popover-foreground: 210 11% 15%;
14
+ --primary: 212 100% 48%;
15
+ --primary-foreground: 0 0% 100%;
16
+ --secondary: 210 14% 95%;
17
+ --secondary-foreground: 210 11% 15%;
18
+ --muted: 210 20% 98%;
19
+ --muted-foreground: 210 11% 40%;
20
+ --accent: 210 20% 96%;
21
+ --accent-foreground: 210 11% 15%;
22
+ --destructive: 354 70% 54%;
23
+ --destructive-foreground: 0 0% 100%;
24
+ --border: 210 18% 87%;
25
+ --input: 210 18% 87%;
26
+ --ring: 212 100% 48%;
26
27
--radius: 0.5rem;
28
+
29
+ --success: 142 70% 45%;
30
+ --hero-gradient: radial-gradient(ellipse at top center, hsl(210 20% 98%) 0%, hsl(0 0% 100%) 60%);
31
+ --glass-blur: 20px;
32
+ --glass-bg: rgba(255, 255, 255, 0.7);
33
+
34
+ /* Sidebar Tokens */
35
+ --sidebar-background: 0 0% 98%;
36
+ --sidebar-foreground: 240 5.3% 26.1%;
37
+ --sidebar-primary: 240 5.9% 10%;
38
+ --sidebar-primary-foreground: 0 0% 98%;
39
+ --sidebar-accent: 240 4.8% 95.9%;
40
+ --sidebar-accent-foreground: 240 5.9% 10%;
41
+ --sidebar-border: 220 13% 91%;
42
+ --sidebar-ring: 217.2 91.2% 59.8%;
43
+
44
+ /* Chart Tokens */
27
45
--chart-1: 12 76% 61%;
28
46
--chart-2: 173 58% 39%;
29
47
--chart-3: 197 37% 24%;
56
74
--hero-gradient: radial-gradient(ellipse at top center, hsl(229 40% 18%) 0%, hsl(227 45% 5%) 60%);
57
75
--glass-blur: 20px;
58
76
--glass-bg: rgba(18, 23, 42, 0.6);
77
+
78
+ /* Sidebar Tokens */
79
+ --sidebar-background: 229 40% 12%;
80
+ --sidebar-foreground: 228 33% 92%;
81
+ --sidebar-primary: 233 100% 74%;
82
+ --sidebar-primary-foreground: 227 45% 5%;
83
+ --sidebar-accent: 229 40% 16%;
84
+ --sidebar-accent-foreground: 228 33% 92%;
85
+ --sidebar-border: 0 0% 100% / 0.06;
86
+ --sidebar-ring: 233 100% 74%;
59
87
}
60
88
61
89
/* GitHub Dark Theme */
81
109
--ring: 212 92% 63%;
82
110
--hero-gradient: radial-gradient(ellipse at top center, hsl(215 22% 14%) 0%, hsl(216 28% 7%) 60%);
83
111
--glass-bg: rgba(13, 17, 23, 0.6);
112
+
113
+ /* Sidebar Tokens */
114
+ --sidebar-background: 215 22% 10%;
115
+ --sidebar-foreground: 210 17% 82%;
116
+ --sidebar-primary: 212 92% 63%;
117
+ --sidebar-primary-foreground: 0 0% 100%;
118
+ --sidebar-accent: 215 22% 14%;
119
+ --sidebar-accent-foreground: 210 17% 82%;
120
+ --sidebar-border: 215 14% 34%;
121
+ --sidebar-ring: 212 92% 63%;
84
122
}
85
123
86
124
/* Dracula Theme */
106
144
--ring: 326 100% 74%;
107
145
--hero-gradient: radial-gradient(ellipse at top center, hsl(231 15% 25%) 0%, hsl(231 15% 18%) 60%);
108
146
--glass-bg: rgba(40, 42, 54, 0.6);
147
+
148
+ /* Sidebar Tokens */
149
+ --sidebar-background: 231 15% 20%;
150
+ --sidebar-foreground: 60 30% 96%;
151
+ --sidebar-primary: 326 100% 74%;
152
+ --sidebar-primary-foreground: 231 15% 18%;
153
+ --sidebar-accent: 231 15% 25%;
154
+ --sidebar-accent-foreground: 60 30% 96%;
155
+ --sidebar-border: 231 15% 25%;
156
+ --sidebar-ring: 326 100% 74%;
109
157
}
110
158
111
159
/* Rose Pine Theme */
131
179
--ring: 343 35% 65%;
132
180
--hero-gradient: radial-gradient(ellipse at top center, hsl(247 23% 15%) 0%, hsl(249 22% 12%) 60%);
133
181
--glass-bg: rgba(25, 23, 36, 0.6);
182
+
183
+ /* Sidebar Tokens */
184
+ --sidebar-background: 247 23% 15%;
185
+ --sidebar-foreground: 248 19% 89%;
186
+ --sidebar-primary: 343 35% 65%;
187
+ --sidebar-primary-foreground: 249 22% 12%;
188
+ --sidebar-accent: 248 25% 18%;
189
+ --sidebar-accent-foreground: 248 19% 89%;
190
+ --sidebar-border: 248 25% 18%;
191
+ --sidebar-ring: 343 35% 65%;
134
192
}
135
193
136
194
/* Tokyo Night Theme */
156
214
--ring: 263 70% 74%;
157
215
--hero-gradient: radial-gradient(ellipse at top center, hsl(235 18% 20%) 0%, hsl(235 18% 14%) 60%);
158
216
--glass-bg: rgba(26, 27, 38, 0.6);
217
+
218
+ /* Sidebar Tokens */
219
+ --sidebar-background: 235 18% 16%;
220
+ --sidebar-foreground: 227 70% 87%;
221
+ --sidebar-primary: 263 70% 74%;
222
+ --sidebar-primary-foreground: 235 18% 14%;
223
+ --sidebar-accent: 235 18% 20%;
224
+ --sidebar-accent-foreground: 227 70% 87%;
225
+ --sidebar-border: 235 18% 20%;
226
+ --sidebar-ring: 263 70% 74%;
159
227
}
160
228
}
161
229
165
233
}
166
234
167
235
body {
168
- @apply bg-background text-foreground;
236
+ @apply bg-background text-foreground transition-colors duration-300;
237
+ font-family: "Inter", system-ui, sans-serif;
238
+ }
239
+
240
+ code,
241
+ pre,
242
+ .font-mono {
243
+ font-family: "JetBrains Mono", monospace;
244
+ }
245
+
246
+ html {
247
+ scroll-behavior: smooth;
169
248
}
170
249
}
171
250
172
-/* Custom scrollbar */
251
+/* ==========================================================================
252
+ Base Elements & Globals
253
+ ========================================================================== */
254
+
255
+/* Modern Custom scrollbar */
256
+* {
257
+ scrollbar-width: thin;
258
+ scrollbar-color: hsl(var(--border)) transparent;
259
+}
260
+
173
261
::-webkit-scrollbar {
174
262
width: 8px;
175
263
height: 8px;
176
264
}
177
265
178
266
::-webkit-scrollbar-track {
179
- background: hsl(var(--muted));
267
+ background: transparent;
180
268
border-radius: 4px;
181
269
}
182
270
213
301
}
214
302
215
303
.diff-add-line {
216
- @apply bg-green-50 dark:bg-green-900/20 border-l-4 border-green-500;
304
+ @apply bg-green-50/50 dark:bg-green-900/20 border-l-4 border-green-500;
217
305
}
218
306
219
307
.diff-remove-line {
220
- @apply bg-red-50 dark:bg-red-900/20 border-l-4 border-red-500;
308
+ @apply bg-red-50/50 dark:bg-red-900/20 border-l-4 border-red-500;
221
309
}
222
310
223
311
.diff-context-line {
226
314
227
315
/* File tree styles */
228
316
.file-tree-item {
229
- @apply flex items-center gap-2 px-2 py-1 rounded cursor-pointer hover:bg-accent transition-colors;
317
+ @apply flex items-center gap-2 px-2 py-1 rounded cursor-pointer hover:bg-accent hover:text-accent-foreground transition-colors;
230
318
}
231
319
232
320
.file-tree-item.selected {
233
- @apply bg-accent text-accent-foreground;
321
+ @apply bg-accent text-accent-foreground font-medium;
234
322
}
235
323
236
324
/* Commit graph styles */
260
348
@apply text-blue-600 dark:text-blue-400;
261
349
}
262
350
263
-/* Animation keyframes */
264
-@keyframes pulse-slow {
265
-
266
- 0%,
267
- 100% {
268
- opacity: 1;
269
- }
351
+/* ==========================================================================
352
+ Animations
353
+ ========================================================================== */
270
354
271
- 50% {
272
- opacity: 0.5;
273
- }
355
+@keyframes pulse-slow {
356
+ 0%, 100% { opacity: 1; }
357
+ 50% { opacity: 0.5; }
274
358
}
275
359
276
360
.animate-pulse-slow {
278
362
}
279
363
280
364
@keyframes spin-slow {
281
- from {
282
- transform: rotate(0deg);
283
- }
284
-
285
- to {
286
- transform: rotate(360deg);
287
- }
365
+ from { transform: rotate(0deg); }
366
+ to { transform: rotate(360deg); }
288
367
}
289
368
290
369
.animate-spin-slow {
291
370
animation: spin-slow 3s linear infinite;
292
371
}
293
372
294
-/* Markdown preview styles */
373
+/* ==========================================================================
374
+ Markdown Elements
375
+ ========================================================================== */
376
+
295
377
.markdown-body {
296
378
@apply text-foreground;
297
379
}
321
403
}
322
404
323
405
.markdown-body code {
324
- @apply bg-muted px-1.5 py-0.5 rounded text-sm font-mono;
406
+ @apply bg-muted px-1.5 py-0.5 rounded text-sm font-mono border border-border;
325
407
}
326
408
327
409
.markdown-body pre {
328
- @apply bg-muted p-4 rounded-lg overflow-x-auto mb-4;
410
+ @apply bg-muted p-4 rounded-lg overflow-x-auto mb-4 border border-border;
329
411
}
330
412
331
413
.markdown-body pre code {
332
- @apply bg-transparent p-0;
414
+ @apply bg-transparent p-0 border-none;
333
415
}
334
416
335
417
.markdown-body blockquote {
336
- @apply border-l-4 border-muted-foreground pl-4 italic my-4;
418
+ @apply border-l-4 border-muted-foreground pl-4 italic my-4 text-muted-foreground;
337
419
}
338
420
339
421
.markdown-body table {
350
432
}
351
433
352
434
.markdown-body a {
353
- @apply text-primary hover:underline;
435
+ @apply text-primary hover:underline font-medium;
354
436
}
355
437
356
438
.markdown-body img {
357
- @apply max-w-full rounded-lg;
439
+ @apply max-w-full rounded-lg border border-border;
358
440
}
359
441
360
-/* Loading skeleton */
442
+/* ==========================================================================
443
+ Utilities
444
+ ========================================================================== */
445
+
361
446
.skeleton {
362
447
@apply animate-pulse bg-muted rounded;
363
448
}
367
452
@apply focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background;
368
453
}
369
454
370
-/* ====== Premium Landing Page Animations ====== */
455
+.text-balance {
456
+ text-wrap: balance;
457
+}
458
+
459
+/* ==========================================================================
460
+ Premium Landing Page Animations
461
+ ========================================================================== */
371
462
372
-/* Text reveal animation - staggered word appearance */
373
463
@keyframes text-reveal {
374
464
0% {
375
465
opacity: 0;
376
466
transform: translateY(20px);
377
467
filter: blur(4px);
378
468
}
379
-
380
469
100% {
381
470
opacity: 1;
382
471
transform: translateY(0);
389
478
opacity: 0;
390
479
}
391
480
392
-/* Shimmer effect for timeline */
393
481
@keyframes shimmer {
394
- 0% {
395
- transform: translateX(-100%);
396
- }
397
-
398
- 100% {
399
- transform: translateX(200%);
400
- }
482
+ 0% { transform: translateX(-100%); }
483
+ 100% { transform: translateX(200%); }
401
484
}
402
485
403
486
.animate-shimmer {
404
487
animation: shimmer 3s infinite linear;
405
488
}
406
489
407
-/* Slide up + fade */
408
490
@keyframes slide-fade-up {
409
491
0% {
410
492
opacity: 0;
411
493
transform: translateY(30px);
412
494
}
413
-
414
495
100% {
415
496
opacity: 1;
416
497
transform: translateY(0);
421
502
animation: slide-fade-up 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
422
503
}
423
504
424
-/* Soft pulse for dots */
425
505
@keyframes soft-pulse {
426
-
427
- 0%,
428
- 100% {
506
+ 0%, 100% {
429
507
opacity: 0.6;
430
508
transform: scale(1);
431
509
}
432
-
433
510
50% {
434
511
opacity: 1;
435
512
transform: scale(1.3);
440
517
animation: soft-pulse 2s ease-in-out infinite;
441
518
}
442
519
443
-/* Glass card hover effect */
520
+/* CTA Button Styles */
521
+.btn-primary-glow {
522
+ background: linear-gradient(135deg, hsl(var(--primary)) 0%, color-mix(in srgb, hsl(var(--primary)) 80%, white) 100%);
523
+ color: hsl(var(--primary-foreground));
524
+ transition: all 0.3s cubic-bezier(0.22, 1, 0.36, 1);
525
+ box-shadow: 0 4px 20px color-mix(in srgb, hsl(var(--primary)) 30%, transparent);
526
+}
527
+
528
+.btn-primary-glow:hover {
529
+ transform: translateY(-2px);
530
+ box-shadow: 0 8px 30px color-mix(in srgb, hsl(var(--primary)) 50%, transparent);
531
+}
532
+
533
+.hero-gradient {
534
+ background: var(--hero-gradient);
535
+}
536
+
537
+/* ==========================================================================
538
+ Glass & Dashboard HUD
539
+ ========================================================================== */
540
+
444
541
.glass-card {
445
542
background: var(--glass-bg);
446
543
backdrop-filter: blur(var(--glass-blur));
447
- border: 1px solid rgba(255, 255, 255, 0.06);
544
+ border: 1px solid color-mix(in srgb, currentColor 10%, transparent);
448
545
border-radius: 16px;
449
546
transition: all 0.3s cubic-bezier(0.22, 1, 0.36, 1);
450
547
}
451
548
452
549
.glass-card:hover {
453
- background: rgba(18, 23, 42, 0.8);
454
- border-color: rgba(255, 255, 255, 0.12);
550
+ background: color-mix(in srgb, var(--glass-bg) 90%, black);
551
+ border-color: color-mix(in srgb, currentColor 20%, transparent);
455
552
transform: translateY(-2px);
456
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
553
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
457
554
}
458
555
459
-/* CTA Button Styles */
460
-.btn-primary-glow {
461
- background: linear-gradient(135deg, hsl(233 100% 74%) 0%, hsl(230 100% 82%) 100%);
462
- color: hsl(227 45% 5%);
463
- transition: all 0.3s cubic-bezier(0.22, 1, 0.36, 1);
464
- box-shadow: 0 4px 20px rgba(124, 140, 255, 0.3);
556
+/* Glass panel for admin dashboard / HUD */
557
+.glass-panel {
558
+ background: color-mix(in srgb, var(--glass-bg) 80%, transparent);
559
+ backdrop-filter: blur(var(--glass-blur));
560
+ border: 1px solid color-mix(in srgb, currentColor 10%, transparent);
561
+ box-shadow: 0 4px 30px rgba(0, 0, 0, 0.05);
465
562
}
466
563
467
-.btn-primary-glow:hover {
468
- transform: translateY(-2px);
469
- box-shadow: 0 8px 30px rgba(124, 140, 255, 0.5);
564
+/* Custom thin scrollbar for panels */
565
+.custom-scrollbar::-webkit-scrollbar {
566
+ width: 4px;
470
567
}
471
-
472
-/* Hero gradient background */
473
-.hero-gradient {
474
- background: var(--hero-gradient);
568
+.custom-scrollbar::-webkit-scrollbar-track {
569
+ background: transparent;
475
570
}
476
-
477
-/* Motion preference support */
478
-@media (prefers-reduced-motion: reduce) {
479
-
480
- .animate-text-reveal,
481
- .animate-shimmer,
482
- .animate-slide-up,
483
- .animate-soft-pulse {
484
- animation: none;
485
- opacity: 1;
486
- transform: none;
487
- }
571
+.custom-scrollbar::-webkit-scrollbar-thumb {
572
+ background: color-mix(in srgb, currentColor 15%, transparent);
573
+ border-radius: 2px;
574
+}
575
+.custom-scrollbar::-webkit-scrollbar-thumb:hover {
576
+ background: color-mix(in srgb, currentColor 25%, transparent);
488
577
}
489
578
490
-/* ====== Aceternity UI Styles ====== */
579
+/* ==========================================================================
580
+ Aceternity UI Styles
581
+ ========================================================================== */
491
582
492
-/* Spotlight animation */
493
583
@keyframes spotlight {
494
584
0% {
495
585
opacity: 0;
496
586
transform: translate(-72%, -62%) scale(0.5);
497
587
}
498
-
499
588
100% {
500
589
opacity: 1;
501
590
transform: translate(-50%, -40%) scale(1);
506
595
animation: spotlight 2s ease 0.75s 1 forwards;
507
596
}
508
597
509
-/* Dot backgrounds for Hero Highlight */
510
598
.bg-dot-thick-neutral-800 {
511
599
background-image: radial-gradient(circle, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
512
600
background-size: 16px 16px;
517
605
background-size: 16px 16px;
518
606
}
519
607
520
-/* Grid background */
521
608
.bg-grid-white\/\[0\.02\] {
522
609
background-image: linear-gradient(to right, rgba(255, 255, 255, 0.02) 1px, transparent 1px),
523
610
linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
524
611
background-size: 40px 40px;
525
612
}
526
613
527
-/* Gradient text */
528
614
.bg-clip-text {
529
615
-webkit-background-clip: text;
530
616
background-clip: text;
531
617
}
532
618
533
-/* Glass panel for admin dashboard */
534
-.glass-panel {
535
- background: rgba(18, 23, 42, 0.6);
536
- backdrop-filter: blur(20px);
537
- border: 1px solid rgba(255, 255, 255, 0.06);
538
-}
539
-
540
-/* Custom scrollbar for panels */
541
-.custom-scrollbar::-webkit-scrollbar {
542
- width: 6px;
543
-}
544
-
545
-.custom-scrollbar::-webkit-scrollbar-track {
546
- background: transparent;
547
-}
548
-
549
-.custom-scrollbar::-webkit-scrollbar-thumb {
550
- background: rgba(255, 255, 255, 0.1);
551
- border-radius: 3px;
552
-}
553
-
554
-.custom-scrollbar::-webkit-scrollbar-thumb:hover {
555
- background: rgba(255, 255, 255, 0.2);
556
-}
557
-
558
-/* Smooth transitions for all interactive elements */
559
619
@layer utilities {
560
620
.transition-smooth {
561
621
transition: all 0.3s cubic-bezier(0.22, 1, 0.36, 1);
562
622
}
563
623
}
564
624
565
-/* Gradient text animation */
566
625
@keyframes gradient-x {
567
- 0% {
568
- background-position: 0% 50%;
569
- }
570
-
571
- 50% {
572
- background-position: 100% 50%;
573
- }
574
-
575
- 100% {
576
- background-position: 0% 50%;
577
- }
626
+ 0% { background-position: 0% 50%; }
627
+ 50% { background-position: 100% 50%; }
628
+ 100% { background-position: 0% 50%; }
578
629
}
579
630
580
631
.animate-gradient-x {
581
632
animation: gradient-x 3s ease infinite;
582
633
}
583
634
584
-/* ====== Responsive Utilities ====== */
635
+/* ==========================================================================
636
+ Responsive & Accessibility Utilities
637
+ ========================================================================== */
585
638
586
-/* Hide scrollbar on mobile */
587
639
.no-scrollbar::-webkit-scrollbar {
588
640
display: none;
589
641
}
592
644
scrollbar-width: none;
593
645
}
594
646
595
-/* Better mobile spacing */
596
647
@media (max-width: 640px) {
597
648
.container {
598
649
padding-left: 1rem;
599
650
padding-right: 1rem;
600
651
}
601
-
602
- /* Stack grid items on mobile */
603
652
.grid-cols-2 {
604
653
grid-template-columns: repeat(1, minmax(0, 1fr));
605
654
}
606
655
}
607
656
608
-/* Tablet adjustments */
609
657
@media (min-width: 640px) and (max-width: 1024px) {
610
658
.container {
611
659
padding-left: 1.5rem;
613
661
}
614
662
}
615
663
616
-/* Touch-friendly interactive elements */
617
664
@media (hover: none) and (pointer: coarse) {
618
665
button, a, input, textarea, select {
619
666
min-height: 44px;
620
667
min-width: 44px;
621
668
}
622
-
623
- /* Remove hover effects on touch devices */
624
669
.hover\:-translate-y-1:hover,
625
670
.hover\:scale-105:hover {
626
671
transform: none;
627
672
}
628
673
}
629
674
630
-/* Print styles */
631
675
@media print {
632
- .no-print {
633
- display: none !important;
634
- }
635
-
676
+ .no-print { display: none !important; }
636
677
body {
637
678
background: white !important;
638
679
color: black !important;
639
680
}
640
681
}
641
682
642
-/* Reduced motion */
643
683
@media (prefers-reduced-motion: reduce) {
644
684
*, *::before, *::after {
645
685
animation-duration: 0.01ms !important;
647
687
transition-duration: 0.01ms !important;
648
688
scroll-behavior: auto !important;
649
689
}
690
+
691
+ .animate-text-reveal,
692
+ .animate-shimmer,
693
+ .animate-slide-up,
694
+ .animate-soft-pulse {
695
+ animation: none;
696
+ opacity: 1;
697
+ transform: none;
698
+ }
650
699
}
651
700
652
-/* Focus visible for keyboard navigation */
653
701
:focus-visible {
654
702
outline: 2px solid hsl(var(--ring));
655
703
outline-offset: 2px;
704
+ border-radius: calc(var(--radius) - 2px);
656
705
}
657
706
658
-/* Prevent layout shift from lazy images */
659
707
img {
660
708
max-width: 100%;
661
709
height: auto;
662
710
}
663
711
664
-/* Better overflow handling */
665
712
.overflow-x-auto {
666
713
-webkit-overflow-scrolling: touch;
667
714
}
675
722
background: transparent;
676
723
}
677
724
.blob-scrollbar::-webkit-scrollbar-thumb {
678
- background: #30363d;
725
+ background: color-mix(in srgb, currentColor 15%, transparent);
679
726
border-radius: 5px;
680
- border: 2px solid #0d1117;
727
+ border: 2px solid var(--background);
681
728
}
682
729
.blob-scrollbar::-webkit-scrollbar-thumb:hover {
683
- background: #424a53;
730
+ background: color-mix(in srgb, currentColor 25%, transparent);
684
731
}
685
732
686
733
/* Shiki code highlighting overrides */
696
743
.shiki .line {
697
744
height: 1.5rem;
698
745
display: block;
699
-}
700
-
701
-/* Admin HUD styles */
702
-.glass-panel {
703
- background: rgba(13, 17, 23, 0.3);
704
- backdrop-filter: blur(10px);
705
- border: 1px solid rgba(255, 255, 255, 0.05);
706
- box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
707
-}
708
-
709
-.custom-scrollbar::-webkit-scrollbar {
710
- width: 4px;
711
-}
712
-
713
-.custom-scrollbar::-webkit-scrollbar-thumb {
714
- background: rgba(255, 255, 255, 0.1);
715
- border-radius: 2px;
716
-}
717
-
718
-/* Base layout styles */
719
-body {
720
- font-family: "Inter", system-ui, sans-serif;
721
-}
722
-
723
-code,
724
-pre,
725
-.font-mono {
726
- font-family: "JetBrains Mono", monospace;
727
-}
728
-
729
-.text-balance {
730
- text-wrap: balance;
731
-}
732
-
733
-html {
734
- scroll-behavior: smooth;
735
746
}
736
747