diff options
| author | Ken <ken@jots.org> | 2026-05-09 04:41:03 +0000 |
|---|---|---|
| committer | Ken <ken@jots.org> | 2026-05-09 04:41:03 +0000 |
| commit | c75beda743dfd6af63f512e928d0889d9ead3973 (patch) | |
| tree | bed91fd4f9d36a905be0b1ef990457a1e37e567b /public/css/style.css | |
Initial commit — Albumen photo album
Ruby/Sinatra self-hosted photo album with directory hierarchy,
per-photo captions and visibility, lightbox, slideshow, admin UI,
and Let's Encrypt HTTPS via Apache reverse proxy on prouter.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'public/css/style.css')
| -rw-r--r-- | public/css/style.css | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/public/css/style.css b/public/css/style.css new file mode 100644 index 0000000..1f31e42 --- /dev/null +++ b/public/css/style.css @@ -0,0 +1,351 @@ +/* ── Reset & base ─────────────────────────────────────────────────────── */ +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + +:root { + --bg: #111; + --bg2: #1c1c1c; + --bg3: #2a2a2a; + --border: #333; + --text: #e0e0e0; + --text-dim: #888; + --accent: #4a90d9; + --accent-hv: #6aaff7; + --radius: 6px; + --thumb: 220px; + --gap: 12px; + --font: system-ui, -apple-system, sans-serif; +} + +body { + background: var(--bg); + color: var(--text); + font-family: var(--font); + font-size: 15px; + line-height: 1.5; + min-height: 100vh; +} + +a { color: var(--accent); text-decoration: none; } +a:hover { color: var(--accent-hv); text-decoration: underline; } + +/* ── Site header ───────────────────────────────────────────────────────── */ +.site-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 12px 24px; + background: var(--bg2); + border-bottom: 1px solid var(--border); + position: sticky; + top: 0; + z-index: 100; +} + +.site-logo { + font-size: 1.2rem; + font-weight: 700; + letter-spacing: .04em; + color: var(--text); +} +.site-logo:hover { color: var(--accent-hv); text-decoration: none; } + +.site-nav { display: flex; gap: 16px; align-items: center; } +.site-nav a { color: var(--text-dim); font-size: .9rem; } +.site-nav a:hover { color: var(--text); text-decoration: none; } + +/* ── Buttons ───────────────────────────────────────────────────────────── */ +.btn { + display: inline-block; + padding: 6px 16px; + background: var(--bg3); + border: 1px solid var(--border); + border-radius: var(--radius); + color: var(--text); + cursor: pointer; + font-size: .9rem; + transition: background .15s; +} +.btn:hover { background: var(--accent); border-color: var(--accent); color: #fff; text-decoration: none; } +.btn-sm { padding: 4px 10px; font-size: .8rem; } + +/* ── Main content ──────────────────────────────────────────────────────── */ +main { max-width: 1400px; margin: 0 auto; padding: 24px; } + +/* ── Album header ──────────────────────────────────────────────────────── */ +.album-header { margin-bottom: 24px; } +.album-header h1 { font-size: 1.6rem; font-weight: 600; margin-bottom: 6px; } + +.breadcrumbs { font-size: .85rem; color: var(--text-dim); margin-bottom: 8px; } +.breadcrumbs a { color: var(--text-dim); } +.breadcrumbs a:hover { color: var(--text); } +.breadcrumbs .sep { margin: 0 4px; } + +.album-desc { color: var(--text-dim); margin-bottom: 10px; } +.album-actions { margin-top: 10px; } + +/* ── Grid ──────────────────────────────────────────────────────────────── */ +.grid-section { margin-bottom: 32px; } +.section-label { font-size: .85rem; text-transform: uppercase; letter-spacing: .08em; color: var(--text-dim); margin-bottom: 12px; } + +.grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(var(--thumb), 1fr)); + gap: var(--gap); +} + +/* ── Cards ─────────────────────────────────────────────────────────────── */ +.card { + border-radius: var(--radius); + overflow: hidden; + background: var(--bg2); + cursor: pointer; + transition: transform .15s, box-shadow .15s; +} +.card:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,.5); } + +.thumb-wrap { + position: relative; + width: 100%; + aspect-ratio: 1; + overflow: hidden; + background: var(--bg3); +} +.thumb-wrap img { + width: 100%; height: 100%; + object-fit: cover; + display: block; + transition: transform .2s; +} +.card:hover .thumb-wrap img { transform: scale(1.04); } + +.thumb-placeholder { + width: 100%; height: 100%; + display: flex; align-items: center; justify-content: center; + font-size: 3rem; + background: var(--bg3); +} + +.card-overlay { + position: absolute; + bottom: 0; left: 0; right: 0; + padding: 24px 8px 8px; + background: linear-gradient(transparent, rgba(0,0,0,.7)); + opacity: 0; + transition: opacity .2s; +} +.card:hover .card-overlay { opacity: 1; } +.card-label { color: #fff; font-size: .85rem; font-weight: 500; } + +.type-badge { + position: absolute; + top: 6px; right: 6px; + background: rgba(0,0,0,.6); + border-radius: 4px; + padding: 2px 6px; + font-size: .8rem; + color: #fff; + pointer-events: none; +} + +.album-label { padding: 6px 8px; font-size: .88rem; font-weight: 500; color: var(--text); } +.card-meta { padding: 6px 8px; } +.card-caption { font-size: .8rem; color: var(--text-dim); } + +.hidden-item { opacity: .45; outline: 1px dashed var(--border); } +.empty-album { color: var(--text-dim); text-align: center; padding: 60px 0; } + +/* ── Lightbox ──────────────────────────────────────────────────────────── */ +.lightbox { + position: fixed; inset: 0; + z-index: 1000; + background: rgba(0,0,0,.92); + display: flex; flex-direction: column; + align-items: center; justify-content: center; +} +.lightbox.hidden { display: none; } + +.lb-stage { + flex: 1; + display: flex; align-items: center; justify-content: center; + width: 100%; + cursor: zoom-out; + overflow: hidden; + padding: 16px; +} +/* inline-block shrink-wraps to the rendered image size; + arrows inside are then anchored to the photo's actual edges */ +.lb-media { + position: relative; + display: inline-block; + line-height: 0; + cursor: default; +} +#lb-img { max-width: calc(100vw - 32px); max-height: calc(100vh - 130px); object-fit: contain; display: block; } +#lb-video { max-width: calc(100vw - 32px); max-height: calc(100vh - 130px); display: block; } +#lb-audio { width: 400px; max-width: 90vw; display: block; } + +.lb-caption-bar { + padding: 8px 80px; + text-align: center; + font-size: .9rem; + color: var(--text-dim); + display: flex; gap: 16px; justify-content: center; align-items: baseline; + flex-shrink: 0; + width: 100%; +} +#lb-title { color: var(--text); font-weight: 500; } +#lb-counter { margin-left: auto; font-size: .8rem; } +.lb-action { font-size: .78rem; padding: 3px 10px; opacity: .7; } +.lb-action:hover { opacity: 1; } + +.lb-btn { + position: absolute; + background: rgba(0,0,0,.45); + border: none; + color: #fff; + cursor: pointer; + border-radius: var(--radius); + transition: background .15s, opacity .15s; + z-index: 10; +} +.lb-btn:hover { background: rgba(0,0,0,.75); } + +/* Close stays fixed to the viewport corner */ +.lb-close { + position: fixed; + top: 12px; right: 16px; + font-size: 1.1rem; + padding: 6px 12px; + z-index: 1001; +} + +/* Prev/next are anchored to the photo's own edges */ +.lb-prev, .lb-next { + top: 50%; transform: translateY(-50%); + font-size: 2.8rem; + padding: 20px 12px; + opacity: 0; + transition: opacity .2s, background .15s; +} +.lb-media:hover .lb-prev, +.lb-media:hover .lb-next { opacity: .85; } +.lb-prev:hover, .lb-next:hover { opacity: 1 !important; } +.lb-prev { left: 0; border-radius: 0 var(--radius) var(--radius) 0; } +.lb-next { right: 0; border-radius: var(--radius) 0 0 var(--radius); } + +/* ── Slideshow ─────────────────────────────────────────────────────────── */ +.slideshow-page { background: #000; overflow: hidden; height: 100vh; display: flex; } + +#slideshow { + width: 100%; height: 100vh; + display: flex; flex-direction: column; + background: #000; +} +#ss-stage { + flex: 1; + display: flex; align-items: center; justify-content: center; + overflow: hidden; + position: relative; +} +#ss-img, #ss-video { + max-width: 100%; max-height: 100%; + object-fit: contain; + opacity: 1; + transition: opacity .5s ease; +} +#ss-img.fading, #ss-video.fading { opacity: 0; } + +#ss-caption-bar { + position: absolute; + bottom: 0; left: 0; right: 0; + padding: 32px 24px 8px; + background: linear-gradient(transparent, rgba(0,0,0,.7)); + color: #fff; + text-align: center; + font-size: .95rem; + pointer-events: none; +} +#ss-title { font-weight: 600; display: block; } + +#ss-controls { + display: flex; + align-items: center; + gap: 10px; + padding: 10px 20px; + background: rgba(0,0,0,.7); + flex-shrink: 0; +} +.ss-interval-label { color: var(--text-dim); font-size: .85rem; display: flex; align-items: center; gap: 4px; margin-left: auto; } +.ss-interval-label input { width: 48px; background: var(--bg3); border: 1px solid var(--border); color: var(--text); border-radius: var(--radius); padding: 2px 6px; } + +#ss-counter { position: absolute; top: 12px; right: 16px; color: rgba(255,255,255,.5); font-size: .8rem; pointer-events: none; } + +/* ── Admin ─────────────────────────────────────────────────────────────── */ +.admin-login { + max-width: 360px; margin: 80px auto; + padding: 32px; + background: var(--bg2); + border: 1px solid var(--border); + border-radius: var(--radius); +} +.admin-login h1 { margin-bottom: 20px; font-size: 1.3rem; } +.admin-login label { display: block; margin-bottom: 16px; color: var(--text-dim); font-size: .9rem; } +.admin-login input { display: block; width: 100%; margin-top: 4px; padding: 8px 12px; background: var(--bg3); border: 1px solid var(--border); border-radius: var(--radius); color: var(--text); font-size: 1rem; } +.form-error { color: #f55; margin-bottom: 12px; font-size: .9rem; } + +.admin-album { max-width: 1200px; } +.admin-album h1 { font-size: 1.4rem; margin: 16px 0; } +.admin-nav { display: flex; gap: 8px; margin-bottom: 8px; } + +fieldset.album-settings { + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 16px; + margin-bottom: 24px; +} +legend { padding: 0 8px; color: var(--text-dim); font-size: .85rem; } + +.form-row { margin-bottom: 12px; } +.form-row label { display: block; color: var(--text-dim); font-size: .85rem; margin-bottom: 4px; } +.form-row input[type=text], .form-row textarea, .form-row select { + width: 100%; + background: var(--bg3); border: 1px solid var(--border); + border-radius: var(--radius); color: var(--text); + padding: 7px 10px; font-size: .9rem; +} +.form-row textarea { resize: vertical; } +.form-row-inline { display: flex; gap: 20px; align-items: flex-end; flex-wrap: wrap; } +.form-row-inline label { flex: 1; min-width: 180px; } +.checkbox-label { display: flex !important; align-items: center; gap: 6px; flex: 0 0 auto !important; color: var(--text) !important; } +.checkbox-label input { width: auto !important; } + +.files-section h2 { font-size: 1rem; color: var(--text-dim); margin-bottom: 10px; } +.files-table { width: 100%; border-collapse: collapse; font-size: .88rem; } +.files-table th { text-align: left; padding: 6px 10px; border-bottom: 2px solid var(--border); color: var(--text-dim); font-weight: 500; } +.files-table td { padding: 6px 10px; border-bottom: 1px solid var(--border); vertical-align: middle; } +.files-table tr:hover td { background: var(--bg2); } +.filename { color: var(--text-dim); font-size: .8rem; max-width: 180px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.visible-cell { text-align: center; } +.files-table input[type=text] { + width: 100%; + background: var(--bg3); border: 1px solid transparent; + border-radius: 4px; color: var(--text); + padding: 4px 8px; font-size: .85rem; +} +.files-table input[type=text]:focus { border-color: var(--accent); outline: none; } + +.form-actions { margin-top: 20px; } +.sub-albums-section { margin-top: 32px; } +.sub-albums-section h2 { font-size: 1rem; color: var(--text-dim); margin-bottom: 10px; } +.sub-album-list { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; } +.sub-album-list a { padding: 4px 12px; background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius); font-size: .9rem; } + +/* ── Responsive ────────────────────────────────────────────────────────── */ +@media (max-width: 600px) { + :root { --thumb: 140px; --gap: 8px; } + main { padding: 12px; } + .lb-prev { left: 4px; } + .lb-next { right: 4px; } + .lb-stage { padding: 48px 40px; } + .files-table { font-size: .78rem; } +} |
