diff --git a/README.md b/README.md index e9abb2a..f734478 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# imgur-clone +# Picta -Imgur-style image sharing app: dark-mode masonry gallery, drag-and-drop / click / **clipboard paste** uploads, 4K re-encoding, voting, and threaded comments. +Image sharing app: dark-mode masonry gallery, drag-and-drop / click / **clipboard paste** uploads, 4K re-encoding, voting, and threaded comments. ## Stack - **Backend**: Node 20 (Alpine), Express, multer (multipart), sharp (image pipeline), cors @@ -40,6 +40,8 @@ docker build -t imgur-clone:latest . docker run -d --name imgur-clone --restart unless-stopped -p 3001:3000 imgur-clone:latest ``` +> Note: The Docker image and container names remain `imgur-clone` for deployment compatibility. + ## Security - Runtime image strips npm/corepack (only `node server.js` runs at runtime) - `apk upgrade` on every build for base-image CVE coverage diff --git a/REPORT.md b/REPORT.md index 10076c4..1102653 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,6 +1,6 @@ # MCP Deployment & Test Summary Report -## Imgur Clone — Pipeline Validation Project +## Picta — Pipeline Validation Project --- @@ -13,7 +13,7 @@ | **Container Port** | `3001:3000` (host:container) | | **Backend Port** | `3000` (internal) | | **Caddy Reverse Proxy** | `192.168.0.123:2080/2443` → `192.168.0.123:3001` | -| **Gitea Repo** | `https://gitea.krisforbes.ca/krisf/imgur-clone` | +| **Gitea Repo** | `https://gitea.krisforbes.ca/krisf/imgur-clone` (Picta) | | **Build Engine** | Docker BuildKit (node:20-alpine) | | **Build Time** | ~2s (cached layers) | | **Container Status** | `running` (healthy) | @@ -146,7 +146,7 @@ User → Cloudflare DNS → dyn.krisforbes.ca → Caddy (2443) → imgur-clone:3 ### Files in Gitea Repository ``` -imgur-clone/ +imgur-clone/ (Picta) ├── .gitignore ├── Dockerfile ├── README.md diff --git a/public/css/style.css b/public/css/style.css index 034edcf..d398a95 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -62,6 +62,10 @@ --text-3xl: 24px; } +html, body { + overflow-x: hidden; +} + body { font-family: var(--font-family); background: var(--bg-primary); @@ -73,6 +77,19 @@ body { -moz-osx-font-smoothing: grayscale; } +body.modal-open { + overflow: hidden; +} + +/* Hide scrollbar tracks but keep scrollability */ +* { + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE/Edge */ +} +*::-webkit-scrollbar { + display: none; /* WebKit */ +} + /* ===== Focus Visible ===== */ :focus-visible { outline: 2px solid var(--accent-green); @@ -116,8 +133,11 @@ body { opacity: 0.85; } -.logo-icon { - font-size: 28px; +.logo-img { + width: 28px; + height: 28px; + border-radius: 6px; + filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.3)); } .logo-text { @@ -304,6 +324,8 @@ body { .post-card-image { width: 100%; + max-width: 100%; + height: auto; aspect-ratio: 4/3; object-fit: cover; display: block; @@ -324,6 +346,8 @@ body { -webkit-box-orient: vertical; overflow: hidden; letter-spacing: -0.01em; + overflow-wrap: break-word; + word-break: break-word; } .post-card-stats { @@ -410,9 +434,14 @@ body { max-width: 560px; max-height: 90vh; overflow-y: auto; + overflow-x: hidden; border: 1px solid var(--border-color); box-shadow: var(--shadow-lg); animation: modalIn 200ms ease; + scrollbar-width: none; +} +.modal::-webkit-scrollbar { + display: none; } @keyframes modalIn { @@ -652,6 +681,9 @@ body { .post-image-container img { width: 100%; + max-width: 100%; + height: auto; + display: block; border-radius: var(--radius); cursor: zoom-in; box-shadow: var(--shadow); @@ -815,6 +847,8 @@ body { font-size: var(--text-base); color: var(--text-secondary); line-height: 1.5; + overflow-wrap: break-word; + word-break: break-word; } .comment-time { @@ -922,6 +956,43 @@ body { } } +/* ===== Full-Page Drag Overlay ===== */ +.drag-overlay { + display: none; + position: fixed; + inset: 0; + background: rgba(20, 20, 28, 0.92); + backdrop-filter: blur(6px); + z-index: 5000; + align-items: center; + justify-content: center; + pointer-events: none; +} + +.drag-overlay.active { + display: flex; +} + +.drag-overlay-inner { + text-align: center; + padding: var(--space-10) var(--space-9); + border: 3px dashed var(--accent-green); + border-radius: var(--radius-xl); + background: rgba(27, 183, 110, 0.06); +} + +.drag-overlay-icon { + font-size: 56px; + margin-bottom: var(--space-4); +} + +.drag-overlay-text { + font-size: var(--text-2xl); + font-weight: 700; + color: var(--accent-green); + letter-spacing: -0.02em; +} + /* ===== Responsive ===== */ @media (max-width: 1024px) { .post-detail-grid { diff --git a/public/index.html b/public/index.html index 0665632..30438ec 100644 --- a/public/index.html +++ b/public/index.html @@ -3,7 +3,7 @@
-