diff --git a/README.md b/README.md index 59dcb81..a68f3fa 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,6 @@ The server cron runs this once per minute. - Uploads: `/volume2/AKA Drive/사진 받기` - Upload page template: `src/public/upload.html` - Upload page style: `src/public/upload.css` -- Upload page image: `src/public/wedding-poster.png` +- Upload page images: `src/public/wedding-gate-bg.png`, `src/public/wedding-couple.png` Each request creates its own folder under the upload directory. diff --git a/src/public/upload.css b/src/public/upload.css index d81e58b..244067d 100644 --- a/src/public/upload.css +++ b/src/public/upload.css @@ -25,7 +25,8 @@ body { margin: 0 auto; padding: 0; background: - radial-gradient(circle at 50% 18%, rgba(220, 220, 214, 0.28), transparent 42%), + radial-gradient(ellipse at 50% 22%, rgba(214, 214, 208, 0.28), transparent 56%), + radial-gradient(ellipse at 50% 54%, rgba(235, 235, 230, 0.34), transparent 62%), linear-gradient(180deg, #ffffff 0%, #fbfbfa 74%, #ffffff 100%); } @@ -35,7 +36,8 @@ body { margin: 0 auto; padding: 0 clamp(12px, 3.6vw, 34px) 38px; background: - radial-gradient(circle at 50% 35%, rgba(255, 255, 255, 0.7), transparent 44%), + radial-gradient(ellipse at 50% 30%, rgba(218, 218, 212, 0.28), transparent 58%), + radial-gradient(circle at 50% 35%, rgba(255, 255, 255, 0.7), transparent 48%), linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #fbfbfa 82%, #ffffff 100%); text-align: center; } @@ -44,7 +46,9 @@ body { position: relative; width: min(100%, 620px); margin: 0 auto; - padding: 0 clamp(4px, 1.4vw, 10px); + aspect-ratio: 4 / 5.22; + overflow: hidden; + padding: 0; } .poster::before { @@ -59,31 +63,54 @@ body { pointer-events: none; } -.poster__image { +.poster__bg, +.poster__couple { position: relative; - z-index: 1; display: block; - width: 100%; - height: auto; - filter: drop-shadow(0 18px 30px rgba(88, 88, 80, 0.08)); +} + +.poster__bg { + position: absolute; + inset: 0 50% 0 auto; + z-index: 1; + width: 118%; + height: 100%; + max-width: none; + object-fit: cover; + object-position: center top; + transform: translateX(50%); + opacity: 0.66; + filter: saturate(0.78) contrast(0.82) brightness(1.1) drop-shadow(0 18px 30px rgba(88, 88, 80, 0.05)); -webkit-mask-image: - linear-gradient(90deg, transparent 0%, #000 5%, #000 95%, transparent 100%), - linear-gradient(180deg, #000 0%, #000 88%, transparent 100%); + linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.48) 4%, #000 13%, #000 87%, rgba(0, 0, 0, 0.48) 96%, transparent 100%), + linear-gradient(180deg, #000 0%, #000 84%, transparent 99%); -webkit-mask-composite: source-in; mask-image: - linear-gradient(90deg, transparent 0%, #000 5%, #000 95%, transparent 100%), - linear-gradient(180deg, #000 0%, #000 88%, transparent 100%); + linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.48) 4%, #000 13%, #000 87%, rgba(0, 0, 0, 0.48) 96%, transparent 100%), + linear-gradient(180deg, #000 0%, #000 84%, transparent 99%); mask-composite: intersect; } +.poster__couple { + position: absolute; + left: 50%; + bottom: 22.5%; + z-index: 2; + width: 62%; + height: auto; + max-width: none; + transform: translateX(-50%); + filter: drop-shadow(0 12px 18px rgba(65, 65, 58, 0.08)); +} + .poster__plate { position: absolute; - z-index: 2; - left: 10.5%; - right: 10.5%; - bottom: 11.8%; - padding: clamp(18px, 4vw, 28px) 12px clamp(14px, 3vw, 22px); - background: rgba(255, 255, 255, 0.72); + z-index: 3; + left: 8.5%; + right: 8.5%; + bottom: 13%; + padding: clamp(16px, 3.5vw, 25px) 12px clamp(13px, 2.6vw, 20px); + background: rgba(255, 255, 255, 0.78); border-top: 1px solid rgba(55, 55, 55, 0.12); border-bottom: 1px solid rgba(55, 55, 55, 0.12); backdrop-filter: blur(2px); @@ -121,7 +148,7 @@ h1 { .upload-panel { width: min(100%, 430px); - margin: clamp(10px, 2.8vw, 20px) auto 0; + margin: clamp(-24px, -3vw, -12px) auto 0; } .upload-panel__today { @@ -129,7 +156,14 @@ h1 { align-items: center; justify-content: center; gap: clamp(10px, 2.4vw, 16px); - margin: 0 0 clamp(18px, 3.6vw, 26px); + margin: 0 auto clamp(14px, 2.8vw, 20px); + padding: 11px clamp(12px, 3vw, 22px) 9px; + width: fit-content; + max-width: 100%; + border-radius: 999px; + background: rgba(255, 255, 255, 0.78); + box-shadow: 0 8px 22px rgba(120, 120, 112, 0.08); + backdrop-filter: blur(3px); color: #4f4f4f; font-size: clamp(24px, 4.8vw, 35px); line-height: 1.15; @@ -361,20 +395,23 @@ h1 { @media (max-width: 430px) { .upload-page { background: - radial-gradient(circle at 50% 14%, rgba(218, 218, 212, 0.24), transparent 44%), + radial-gradient(ellipse at 50% 18%, rgba(214, 214, 208, 0.26), transparent 58%), + radial-gradient(ellipse at 50% 52%, rgba(235, 235, 230, 0.32), transparent 64%), linear-gradient(180deg, #ffffff 0%, #fbfbfa 78%, #ffffff 100%); } .wedding-card { padding: 0 0 30px; background: - radial-gradient(circle at 50% 33%, rgba(255, 255, 255, 0.66), transparent 45%), + radial-gradient(ellipse at 50% 30%, rgba(218, 218, 212, 0.24), transparent 58%), + radial-gradient(circle at 50% 33%, rgba(255, 255, 255, 0.66), transparent 48%), linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #fbfbfa 82%, #ffffff 100%); } .poster { width: 100%; padding: 0; + aspect-ratio: 390 / 545; } .poster::before { @@ -382,19 +419,26 @@ h1 { filter: blur(18px); } - .poster__image { + .poster__bg { + width: 132%; + opacity: 0.66; -webkit-mask-image: - linear-gradient(90deg, transparent 0%, #000 3%, #000 97%, transparent 100%), - linear-gradient(180deg, #000 0%, #000 89%, transparent 100%); + linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.5) 2%, #000 8%, #000 92%, rgba(0, 0, 0, 0.5) 98%, transparent 100%), + linear-gradient(180deg, #000 0%, #000 84%, transparent 99%); mask-image: - linear-gradient(90deg, transparent 0%, #000 3%, #000 97%, transparent 100%), - linear-gradient(180deg, #000 0%, #000 89%, transparent 100%); + linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.5) 2%, #000 8%, #000 92%, rgba(0, 0, 0, 0.5) 98%, transparent 100%), + linear-gradient(180deg, #000 0%, #000 84%, transparent 99%); + } + + .poster__couple { + bottom: 22.8%; + width: 62%; } .poster__plate { - left: 9%; - right: 9%; - bottom: 11.2%; + left: 8%; + right: 8%; + bottom: 13.5%; } .upload-panel { diff --git a/src/public/upload.html b/src/public/upload.html index 339dabd..984e107 100644 --- a/src/public/upload.html +++ b/src/public/upload.html @@ -10,7 +10,8 @@
- + +

{{title}}

@@ -42,7 +43,7 @@
@@ -116,8 +117,8 @@ form.hidden = true; thanks.hidden = false; - thanks.querySelector("p:last-of-type").textContent = - `${result.count || input.files.length}개 파일을 잘 받았어요. 소중한 오늘을 함께 남겨주셔서 고마워요.`; + thanks.querySelector("p:last-of-type").innerHTML = + `${result.count || input.files.length}개의 파일 잘 받았습니다.
소중한 오늘을 함께 남겨주셔서 감사드립니다.`; } catch (error) { submit.disabled = false; form.dataset.uploading = "false"; diff --git a/src/public/wedding-couple.png b/src/public/wedding-couple.png new file mode 100644 index 0000000..ac5f991 Binary files /dev/null and b/src/public/wedding-couple.png differ diff --git a/src/public/wedding-gate-bg.png b/src/public/wedding-gate-bg.png new file mode 100644 index 0000000..4cc30d1 Binary files /dev/null and b/src/public/wedding-gate-bg.png differ diff --git a/src/public/wedding-poster.png b/src/public/wedding-poster.png deleted file mode 100644 index c79dfde..0000000 Binary files a/src/public/wedding-poster.png and /dev/null differ diff --git a/src/server.js b/src/server.js index a1729f3..a3a9306 100644 --- a/src/server.js +++ b/src/server.js @@ -168,7 +168,8 @@ function uploadResultPage(request, { heading, message, isError = false }) {
- + +

${title}

2026.05.24 SUN

@@ -435,7 +436,7 @@ app.post("/r/:slug", async (req, res) => { res.json({ ok: true, count: files.length }); return; } - res.send(uploadResultPage(request, { heading: "감사합니다", message: `${files.length}개 파일을 잘 받았어요. 소중한 오늘을 함께 남겨주셔서 고마워요.` })); + res.send(uploadResultPage(request, { heading: "감사합니다", message: `${files.length}개의 파일 잘 받았습니다. 소중한 오늘을 함께 남겨주셔서 감사드립니다.` })); } catch { await removeFiles(req.files); if (wantsJson(req)) {