Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 19 additions & 59 deletions frontend/404.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>404 — Not Found | CodePVG</title>
<link rel="icon" type="image/png" href="assets/logo.png" />
<link rel="icon" type="image/png" href="/assets/logo.png" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Space+Mono:wght@400;700&family=Share+Tech+Mono&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="styles/main.css" />
<link rel="stylesheet" href="/styles/main.css" />
<style>
/* 404-specific overrides */
body {
Expand All @@ -26,17 +26,6 @@
position: relative;
}

/* Matrix rain canvas */
#matrix {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
opacity: 0.18;
}

/* Main panel */
.panel {
position: relative;
Expand Down Expand Up @@ -159,37 +148,51 @@
pointer-events: none;
z-index: 2;
}

@media (max-width: 768px) {
.panel {
padding: 2rem 2rem;
max-width: 90%;
}
}

@media (max-width: 480px) {
.panel {
padding: 1.5rem 1.2rem;
width: 95%;
}

.title {
font-size: 1.6rem;
}

.subtitle {
font-size: 0.75rem;
}

.line {
font-size: 0.82rem;
line-height: 1.6;
}

.nav-links {
flex-direction: column;
align-items: center;
gap: 0.75rem;
}

.nav-links a {
text-align: center;
width: 100%;
max-width: 280px;
box-sizing: border-box;
}
}
</style>
</head>

<body>
<canvas id="matrix"></canvas>
<canvas id="matrix-canvas"></canvas>

<div class="panel">
<div class="title">404 — Not Found</div>
Expand Down Expand Up @@ -262,50 +265,7 @@
</div>
</div>

<script>
// Inject actual bad path
const p = window.location.pathname;
document.getElementById("cd-line").textContent = " cd " + p;
document.getElementById("path-display").textContent = p;

// Matrix rain
const canvas = document.getElementById("matrix");
const ctx = canvas.getContext("2d");

function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resize();
window.addEventListener("resize", resize);

const chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()アイウエオカキクケコサシスセソタチツテトナニヌネノ";
const fontSize = 14;
let cols = Math.floor(canvas.width / fontSize);
let drops = Array(cols).fill(1);

function drawMatrix() {
ctx.fillStyle = "rgba(0, 0, 0, 0.05)";
ctx.fillRect(0, 0, canvas.width, canvas.height);

ctx.fillStyle = "#00ff41";
ctx.font = fontSize + "px Share Tech Mono, monospace";

cols = Math.floor(canvas.width / fontSize);
if (drops.length < cols)
drops = drops.concat(Array(cols - drops.length).fill(1));

for (let i = 0; i < cols; i++) {
const char = chars[Math.floor(Math.random() * chars.length)];
ctx.fillText(char, i * fontSize, drops[i] * fontSize);
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975)
drops[i] = 0;
drops[i]++;
}
}

setInterval(drawMatrix, 40);
</script>
<script src="/js/404.js"></script>
<script src="/js/matrix.js"></script>
</body>
</html>
10 changes: 10 additions & 0 deletions frontend/js/404.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
document.addEventListener("DOMContentLoaded", () => {
// Inject actual bad path
const p = window.location.pathname;

const cdLine = document.getElementById("cd-line");
const pathDisplay = document.getElementById("path-display");

if (cdLine) cdLine.textContent = " cd " + p;
if (pathDisplay) pathDisplay.textContent = p;
});
18 changes: 18 additions & 0 deletions frontend/js/leaderboard/compare.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,24 @@ document.addEventListener("DOMContentLoaded", () => {
const toggleBtn = document.getElementById("compare-mode-toggle");
if (toggleBtn) {
toggleBtn.addEventListener("click", toggleCompareMode);
toggleBtn.addEventListener("mouseover", function () {
this.style.background = "var(--amber-muted)";
this.style.borderColor = "var(--amber-dim)";
this.style.textShadow = "0 0 5px rgba(255, 176, 0, 0.4)";
});
toggleBtn.addEventListener("mouseout", function () {
if (!window.compareModeActive) {
this.style.background = "var(--bg-raised)";
this.style.borderColor = "var(--border)";
this.style.color = "var(--amber)";
this.style.textShadow = "none";
} else {
this.style.background = "var(--green-muted)";
this.style.borderColor = "var(--green-dim)";
this.style.color = "var(--green)";
this.style.textShadow = "0 0 5px rgba(0, 255, 65, 0.3)";
}
});
}

const closeBtn = document.getElementById("close-compare-modal");
Expand Down
19 changes: 1 addition & 18 deletions frontend/leaderboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -175,24 +175,6 @@ <h1 class="page-title">Leaderboard</h1>
margin-right: 0.5rem;
white-space: nowrap;
"
onmouseover="
this.style.background = 'var(--amber-muted)';
this.style.borderColor = 'var(--amber-dim)';
this.style.textShadow = '0 0 5px rgba(255, 176, 0, 0.4)';
"
onmouseout="
if (!window.compareModeActive) {
this.style.background = 'var(--bg-raised)';
this.style.borderColor = 'var(--border)';
this.style.color = 'var(--amber)';
this.style.textShadow = 'none';
} else {
this.style.background = 'var(--green-muted)';
this.style.borderColor = 'var(--green-dim)';
this.style.color = 'var(--green)';
this.style.textShadow = '0 0 5px rgba(0, 255, 65, 0.3)';
}
"
>
[--compare-peers]
</button>
Expand Down Expand Up @@ -751,6 +733,7 @@ <h1 class="page-title">Leaderboard</h1>
style="
display: flex;
gap: 10px;
flex-wrap: wrap;
margin: 1.5rem 0 1rem 0;
justify-content: center;
"
Expand Down
110 changes: 110 additions & 0 deletions frontend/styles/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -3369,3 +3369,113 @@ input[type="checkbox"].compare-checkbox:checked::after {
display: none;
}
}

/* Hero responsive */
@media (max-width: 768px) {
.hero-title {
font-size: 2.8rem;
}
.hero-content {
padding: 2rem;
}
}

@media (max-width: 480px) {
.hero-title {
font-size: 2rem;
word-break: break-word;
}
.hero-subtitle {
font-size: 0.85rem;
}
.hero-content {
padding: 1.2rem;
}
.hero-buttons {
flex-direction: column;
width: 100%;
}
.hero-buttons .btn {
width: 100%;
max-width: 100%;
}
}

/* Compare Module Responsive */
@media (max-width: 768px) {
.floating-compare-bar {
width: calc(100% - 32px);
max-width: 100%;
gap: 1rem;
padding: 0.75rem 1rem;
}
.floating-compare-bar .selected-list {
font-size: 0.78rem;
}
.compare-card {
padding: 20px 16px;
}
.compare-table th,
.compare-table td {
padding: 0.5rem 0.4rem;
font-size: 0.72rem;
}
.compare-chart-card {
height: 280px;
min-height: 280px;
max-height: 280px;
}
.compare-chart-card canvas {
height: calc(100% - 50px) !important;
}
}

@media (max-width: 480px) {
.floating-compare-bar {
flex-direction: column;
gap: 0.75rem;
padding: 0.8rem 1rem;
text-align: center;
bottom: 12px;
}
.floating-compare-bar .actions {
width: 100%;
justify-content: center;
flex-wrap: wrap;
}
.floating-compare-bar .btn-compare,
.floating-compare-bar .btn-clear {
flex: 1;
text-align: center;
}
.compare-card {
padding: 16px 12px;
width: 100vw;
max-width: 100vw;
border-radius: 0;
}
.compare-card-header {
flex-direction: column;
gap: 12px;
align-items: center;
text-align: center;
}
.compare-card-title {
font-size: 0.82rem;
}
.compare-table th,
.compare-table td {
padding: 0.4rem 0.3rem;
font-size: 0.65rem;
white-space: nowrap;
}
.compare-chart-card {
height: 240px;
min-height: 240px;
max-height: 240px;
}
.compare-chart-title {
font-size: 0.68rem;
margin-bottom: 0.5rem;
}
}
4 changes: 3 additions & 1 deletion server.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ app.use(
"https://raw.githubusercontent.com",
"https://leetcode-api-dun.vercel.app",
"https://lc-backend-lyq2.onrender.com",
"https://cdn.jsdelivr.net",
],
// Inline scripts need a per-request nonce; external scripts from 'self'
// are allowed automatically.
Expand Down Expand Up @@ -165,7 +166,8 @@ app.get("/api/user/:username", async (req, res) => {

// 404 handler
app.use((req, res) => {
res.status(404).sendFile(path.join(__dirname, "frontend", "404.html"));
res.status(404);
serveHtml(res, path.join(__dirname, "frontend", "404.html"));
});

app.listen(PORT, () => {
Expand Down
Loading