Known For
diff --git a/webui/static/video/video-person.js b/webui/static/video/video-person.js
index 0194324a..0b2b94c7 100644
--- a/webui/static/video/video-person.js
+++ b/webui/static/video/video-person.js
@@ -190,6 +190,53 @@
img.src = '/api/video/img?u=' + encodeURIComponent(photoUrl);
}
+ // ── photos gallery + lightbox (reuses the shared .vd-lightbox styles) ──────
+ var photoFulls = [], lbIdx = 0;
+ function renderPhotos(photos) {
+ var sec = q('[data-vp-photos-section]'), host = q('[data-vp-photos]');
+ photos = photos || [];
+ photoFulls = photos.map(function (p) { return p.full; });
+ if (!sec || !host) return;
+ if (!photos.length) { sec.hidden = true; return; }
+ sec.hidden = false;
+ host.innerHTML = photos.map(function (p, i) {
+ return '
';
+ }).join('');
+ }
+ function openLightbox(idx) {
+ if (!photoFulls.length) return;
+ lbIdx = idx;
+ var ov = document.getElementById('vp-lightbox');
+ if (!ov) {
+ ov = document.createElement('div'); ov.id = 'vp-lightbox'; ov.className = 'vd-lightbox';
+ ov.addEventListener('click', function (e) {
+ if (e.target.closest('[data-vp-lb-prev]')) lbStep(-1);
+ else if (e.target.closest('[data-vp-lb-next]')) lbStep(1);
+ else if (e.target === ov || e.target.closest('[data-vp-lb-close]')) closeLightbox();
+ });
+ document.body.appendChild(ov);
+ }
+ renderLb(); ov.classList.add('vd-lightbox--open');
+ }
+ function renderLb() {
+ var ov = document.getElementById('vp-lightbox'); if (!ov) return;
+ ov.innerHTML = '
' +
+ '
' +
+ '
 + ')
' +
+ '
' +
+ '
' + (lbIdx + 1) + ' / ' + photoFulls.length + '
';
+ }
+ function lbStep(dir) { lbIdx = (lbIdx + dir + photoFulls.length) % photoFulls.length; renderLb(); }
+ function closeLightbox() {
+ var ov = document.getElementById('vp-lightbox');
+ if (ov) { ov.classList.remove('vd-lightbox--open'); ov.innerHTML = ''; }
+ }
+ function lbOpen() {
+ var ov = document.getElementById('vp-lightbox');
+ return ov && ov.classList.contains('vd-lightbox--open');
+ }
+
function computeAge(birthday, deathday) {
if (!birthday) return null;
var b = new Date(birthday), end = deathday ? new Date(deathday) : new Date();
@@ -241,9 +288,16 @@
var m = q('[data-vp-meta]');
if (m) m.innerHTML = meta.map(function (x) { return '
' + esc(x) + ''; }).join('');
+ var aka = q('[data-vp-aka]');
+ if (aka) {
+ var names = d.also_known_as || [];
+ aka.textContent = names.length ? 'Also known as: ' + names.join(' · ') : '';
+ aka.hidden = !names.length;
+ }
var bio = q('[data-vp-bio]'), more = q('[data-vp-bio-more]');
if (bio) { bio.textContent = d.biography || ''; bio.hidden = !d.biography; bio.classList.remove('vp-bio--open'); }
if (more) { more.hidden = !((d.biography || '').length > 320); more.textContent = 'Read more'; }
+ renderPhotos(d.photos);
applyFilters();
var sub = document.querySelector('.video-subpage[data-video-subpage="video-person-detail"]');
@@ -264,6 +318,10 @@
var ce = q('[data-vp-credits-empty]'); if (ce) ce.hidden = true;
var ks = q('[data-vp-known-section]'); if (ks) ks.hidden = true;
var k = q('[data-vp-known]'); if (k) k.innerHTML = '';
+ var psec = q('[data-vp-photos-section]'); if (psec) psec.hidden = true;
+ var pho = q('[data-vp-photos]'); if (pho) pho.innerHTML = '';
+ var ak = q('[data-vp-aka]'); if (ak) ak.hidden = true;
+ photoFulls = [];
fetch(PERSON_URL + id, { headers: { 'Accept': 'application/json' } })
.then(function (r) { return r.ok ? r.json() : null; })
.then(function (d) {
@@ -294,6 +352,8 @@
if (deptBtn && r.contains(deptBtn)) {
dept = deptBtn.getAttribute('data-vp-dept'); applyFilters(); return;
}
+ var shot = e.target.closest('[data-vp-shot]');
+ if (shot && r.contains(shot)) { openLightbox(parseInt(shot.getAttribute('data-vp-shot'), 10) || 0); return; }
var moreBtn = e.target.closest('[data-vp-bio-more]');
if (moreBtn && r.contains(moreBtn)) {
var bio = q('[data-vp-bio]');
@@ -319,6 +379,12 @@
function init() {
document.addEventListener('soulsync:video-open-detail', onOpen);
document.addEventListener('click', onClick);
+ document.addEventListener('keydown', function (e) {
+ if (!lbOpen()) return;
+ if (e.key === 'Escape') closeLightbox();
+ else if (e.key === 'ArrowLeft') lbStep(-1);
+ else if (e.key === 'ArrowRight') lbStep(1);
+ });
var sortSel = document.querySelector('[data-vp-sort]');
if (sortSel) sortSel.addEventListener('change', function () {
sortBy = sortSel.value; renderCredits();
diff --git a/webui/static/video/video-side.css b/webui/static/video/video-side.css
index e4bceadc..3a6f18d5 100644
--- a/webui/static/video/video-side.css
+++ b/webui/static/video/video-side.css
@@ -1361,3 +1361,17 @@ a.vd-prov:hover img, a.vd-prov:hover .vd-prov-ph { border-color: rgba(var(--vd-a
.vd-cm-name { display: block; font-size: 13px; font-weight: 700; color: #fff; line-height: 1.3; }
.vd-cm-char { display: block; font-size: 12px; color: rgba(255, 255, 255, 0.55); line-height: 1.3; }
.vd-cm-eps { display: block; font-size: 11px; color: rgb(var(--vd-accent-rgb)); margin-top: 2px; font-weight: 600; }
+
+/* ── person: photos rail + also-known-as ─────────────────────────────────── */
+.vp-aka { font-size: 13.5px; color: rgba(255, 255, 255, 0.6); margin: 0 0 18px; font-style: italic; }
+.vp-photos-section { position: relative; z-index: 2; margin-bottom: 38px; }
+.vp-photos { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 12px; scroll-snap-type: x proximity; }
+.vp-photos::-webkit-scrollbar { height: 8px; }
+.vp-photos::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.15); border-radius: 4px; }
+.vp-photo-thumb {
+ flex: 0 0 120px; width: 120px; aspect-ratio: 2 / 3; scroll-snap-align: start; padding: 0; border: 0; cursor: pointer;
+ border-radius: 10px; overflow: hidden; background: #000; box-shadow: 0 6px 18px rgba(0, 0, 0, 0.4);
+ transition: transform 0.25s ease, box-shadow 0.25s ease;
+}
+.vp-photo-thumb img { width: 100%; height: 100%; object-fit: cover; }
+.vp-photo-thumb:hover { transform: translateY(-4px); box-shadow: 0 12px 30px rgba(0, 0, 0, 0.55); }