summaryrefslogtreecommitdiffstats
path: root/public/css/style.css
diff options
context:
space:
mode:
authorKen D'Ambrosio <ken@jots.org>2026-06-08 19:00:02 +0000
committerKen D'Ambrosio <ken@jots.org>2026-06-08 19:00:02 +0000
commit01f52565f460a0107679999588b73b770f01a98c (patch)
tree806c723ad62221f176fd97d5fdcaadac5d8da2d4 /public/css/style.css
parent625b3d5176f2c274e91fcf28bda8e45cc0477722 (diff)
Add people/face clustering feature
- scripts/cluster_faces.py: greedy centroid clustering (numpy) with 3 refinement passes; preserves existing UUID/name mappings across re-runs; writes MEDIA_ROOT/people.json atomically. - app.rb: GET /face/* serves cropped+padded face thumbnails (100x100, cached under cache/faces/); GET|POST /admin/people for cluster management; POST /admin/people/recluster runs cluster_faces.py as a background job; POST /admin/people/:uuid saves names+slugs; GET /people public grid of named people; GET /people/:slug photos for one person. - views/admin/people.erb: lists all clusters (named first, then by size), face crop samples, inline name form, re-cluster button with live log. - views/people.erb: public grid of named people. - views/person.erb: photo grid for one person, linking back to album lightbox for each photo. - views/layout.erb: People link in nav (conditional on FACES_ENABLED). - public/css/style.css: styles for people admin list and public tiles. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'public/css/style.css')
-rw-r--r--public/css/style.css43
1 files changed, 43 insertions, 0 deletions
diff --git a/public/css/style.css b/public/css/style.css
index ec22f39..ba9b822 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -421,6 +421,49 @@ tr.delete-marked td { background: rgba(192,57,43,.08); }
padding: 12px 14px; border-radius: var(--radius); max-height: 340px;
overflow-y: auto; white-space: pre-wrap; word-break: break-all; margin: 0; }
+/* ── People — admin ───────────────────────────────────────────────────── */
+.admin-people h1 { font-size: 1.4rem; margin: 16px 0; }
+
+.people-admin-list { margin-top: 24px; display: flex; flex-direction: column; gap: 4px; }
+
+.people-admin-row {
+ display: flex; align-items: center; gap: 14px;
+ padding: 10px 12px;
+ background: var(--bg2); border: 1px solid var(--border); border-radius: var(--radius);
+}
+.people-admin-row:hover { background: var(--bg3); }
+.unnamed-cluster { opacity: .7; }
+.unnamed-cluster:hover { opacity: 1; }
+
+.face-samples { display: flex; gap: 4px; align-items: center; flex-shrink: 0; }
+.face-samples img { border-radius: 50%; object-fit: cover; border: 2px solid var(--bg3); }
+.face-more { font-size: .8rem; color: var(--text-dim); white-space: nowrap; min-width: 28px; }
+
+.people-admin-meta { display: flex; align-items: center; gap: 10px; flex: 1; flex-wrap: wrap; }
+.face-count { font-size: .8rem; color: var(--text-dim); white-space: nowrap; min-width: 64px; }
+
+.name-form { display: flex; align-items: center; gap: 6px; flex: 1; }
+.name-input {
+ flex: 1; max-width: 280px;
+ background: var(--bg3); border: 1px solid var(--border); border-radius: var(--radius);
+ color: var(--text); padding: 5px 10px; font-size: .9rem;
+}
+.name-input:focus { border-color: var(--accent); outline: none; }
+
+/* ── People — public ───────────────────────────────────────────────────── */
+.people-grid { margin-top: 8px; }
+
+.person-tile {
+ display: block; border-radius: var(--radius); overflow: hidden;
+ background: var(--bg2); text-decoration: none;
+ transition: transform .15s, box-shadow .15s;
+}
+.person-tile:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,0,0,.5); text-decoration: none; }
+.person-tile .thumb-wrap img { transition: transform .2s; }
+.person-tile:hover .thumb-wrap img { transform: scale(1.04); }
+.person-name { padding: 7px 10px 2px; font-size: .9rem; font-weight: 500; color: var(--text); }
+.person-count { padding: 0 10px 8px; font-size: .75rem; color: var(--text-dim); }
+
/* ── Admin upload ──────────────────────────────────────────────────────── */
.admin-upload { margin-top: 32px; }
.admin-upload h2 { font-size: 1rem; color: var(--text-dim); margin-bottom: 6px; }