diff --git a/src/AdminPage.tsx b/src/AdminPage.tsx index 252fe11..ab1b0b1 100644 --- a/src/AdminPage.tsx +++ b/src/AdminPage.tsx @@ -3831,6 +3831,7 @@ export default function AdminPage({ content, onSave, onLogout }: Props) {
setForm(f => ({ ...f, finishedBooks: (f.finishedBooks ?? []).map(b => b.id === book.id ? { ...b, imageUrl: e.target.value } : b) }))} /> + {renderImageAssetSelector(book.imageUrl, value => setForm(f => ({ ...f, finishedBooks: (f.finishedBooks ?? []).map(b => b.id === book.id ? { ...b, imageUrl: value } : b) })), `finished-book-img-${book.id}`)} {renderImagePreview(book.imageUrl, `${book.title} cover`)}
diff --git a/src/App.css b/src/App.css index 8c77aed..c582cb9 100644 --- a/src/App.css +++ b/src/App.css @@ -190,7 +190,8 @@ cursor: pointer; } -.header-nav a { +.header-nav a, +.header-nav button { color: var(--brand-muted); text-decoration: none; font-family: var(--brand-font-body); @@ -8701,18 +8702,29 @@ display: flex; align-items: center; gap: 0.25rem; + color: var(--brand-muted); + font-family: inherit; + font-weight: 500; + letter-spacing: 0.06em; + text-transform: uppercase; + font-size: 0.96rem; + line-height: inherit; + transition: color 200ms; +} + +.nav-dropdown-trigger:hover, +.nav-dropdown--open .nav-dropdown-trigger { + color: var(--brand-gold); } .nav-dropdown-arrow { font-size: 0.7em; opacity: 0.7; - transition: transform 200ms; } .nav-dropdown-menu { - display: none; position: absolute; - top: calc(100% + 0.5rem); + top: calc(100% + 0.75rem); left: 50%; transform: translateX(-50%); background: rgba(15, 15, 12, 0.98); @@ -8724,11 +8736,6 @@ box-shadow: 0 8px 24px rgba(0,0,0,0.5); } -.nav-dropdown:hover .nav-dropdown-menu, -.nav-dropdown:focus-within .nav-dropdown-menu { - display: block; -} - .nav-dropdown-item { display: block; padding: 0.55rem 1.1rem; @@ -8993,3 +9000,52 @@ height: 120px; } } + +/* ── Finished Books page section ── */ +.section-finished-books { + min-height: 60vh; + padding: 4rem 0 6rem; +} + +.finished-books-header { + text-align: center; + margin-bottom: 3rem; +} + +.finished-books-intro { + color: var(--brand-muted); + font-size: 1.05rem; + max-width: 540px; + margin: -1rem auto 0; + line-height: 1.65; +} + +.finished-books-empty-state { + text-align: center; + padding: 4rem 2rem 5rem; + border: 1px solid rgba(201, 168, 76, 0.15); + border-radius: 16px; + background: rgba(26, 26, 21, 0.5); + max-width: 520px; + margin: 0 auto; +} + +.finished-books-empty-icon { + font-size: 3rem; + margin-bottom: 1.25rem; + opacity: 0.6; +} + +.finished-books-empty-heading { + font-family: var(--brand-font-heading); + font-size: 1.6rem; + color: var(--brand-warm-white); + margin: 0 0 0.75rem; +} + +.finished-books-empty-text { + color: var(--brand-muted); + font-size: 0.97rem; + line-height: 1.65; + margin: 0; +} diff --git a/src/App.tsx b/src/App.tsx index d8ea0c6..adcb17a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, useRef } from 'react' import type { ReactElement } from 'react' import { Link, NavLink, Routes, Route, useLocation, useNavigate, useParams } from 'react-router-dom' import AdminPage from './AdminPage' @@ -355,10 +355,21 @@ function SiteSearchBar({ content }: { content: SiteContent }) { function SiteHeader({ content }: { content: SiteContent }) { const [menuOpen, setMenuOpen] = useState(false) const [episodesOpen, setEpisodesOpen] = useState(false) + const dropdownRef = useRef(null) const spotifyUrl = content.platformSpotifyUrl || '/spotify' const location = useLocation() const episodesActive = location.pathname.startsWith('/episodes') || location.pathname.startsWith('/finished') + useEffect(() => { + function handleOutsideClick(e: MouseEvent) { + if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { + setEpisodesOpen(false) + } + } + if (episodesOpen) document.addEventListener('mousedown', handleOutsideClick) + return () => document.removeEventListener('mousedown', handleOutsideClick) + }, [episodesOpen]) + return (
@@ -376,19 +387,21 @@ function SiteHeader({ content }: { content: SiteContent }) {