diff --git a/src/pages/travel/AlbumCard.css b/src/pages/travel/AlbumCard.css new file mode 100644 index 0000000..7f8f0dd --- /dev/null +++ b/src/pages/travel/AlbumCard.css @@ -0,0 +1,116 @@ +/* ── AlbumCard ── */ + +.album-card { + position: relative; + height: 240px; + border-radius: 12px; + border: 1px solid rgba(245, 230, 200, 0.08); + overflow: hidden; + cursor: pointer; + outline: none; + transition: transform 0.28s ease, box-shadow 0.28s ease; +} + +.album-card:hover, +.album-card:focus-visible { + transform: scale(1.03); + box-shadow: 0 4px 24px color-mix(in srgb, var(--card-accent) 35%, transparent); +} + +/* cover image */ +.album-card__cover { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.35s ease; +} + +.album-card:hover .album-card__cover { + transform: scale(1.06); +} + +/* gradient overlay */ +.album-card__gradient { + position: absolute; + inset: 0; + background: linear-gradient(transparent 50%, rgba(15, 12, 9, 0.85)); + pointer-events: none; +} + +/* meta */ +.album-card__meta { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 16px; + z-index: 2; + display: flex; + flex-direction: column; + gap: 4px; +} + +.album-card__region-badge { + align-self: flex-start; + font: 10px var(--tv-mono); + letter-spacing: 0.08em; + text-transform: uppercase; + color: var(--card-accent); + background: rgba(15, 12, 9, 0.6); + padding: 2px 8px; + border-radius: 4px; +} + +.album-card__name { + margin: 0; + font: 600 24px/1.15 var(--tv-serif); + color: var(--tv-text); +} + +.album-card__count { + font: 11px var(--tv-mono); + letter-spacing: 0.06em; + color: var(--tv-muted); + background: rgba(15, 12, 9, 0.55); + padding: 2px 8px; + border-radius: 4px; + align-self: flex-start; +} + +/* grid layout */ +.album-card-grid { + display: grid; + gap: 16px; + grid-template-columns: repeat(3, 1fr); +} + +@media (max-width: 1024px) { + .album-card-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 768px) { + .album-card-grid { + grid-template-columns: 1fr; + } + + .album-card { + height: 200px; + } + + .album-card__name { + font-size: 18px; + } +} + +/* reduced motion */ +@media (prefers-reduced-motion: reduce) { + .album-card, + .album-card__cover { + transition: none; + transform: none !important; + } +} diff --git a/src/pages/travel/AlbumCard.jsx b/src/pages/travel/AlbumCard.jsx new file mode 100644 index 0000000..54049ec --- /dev/null +++ b/src/pages/travel/AlbumCard.jsx @@ -0,0 +1,55 @@ +import React, { useRef, useCallback } from 'react'; +import { getRegionAccent } from './MiniMap'; +import './AlbumCard.css'; + +/* ───────────────────────────────────────────── + AlbumCard — cover image + gradient + meta +───────────────────────────────────────────── */ +export default function AlbumCard({ album, onClick }) { + const cardRef = useRef(null); + const accent = getRegionAccent(album.region || ''); + + const handleClick = useCallback(() => { + if (!onClick) return; + const rect = cardRef.current?.getBoundingClientRect(); + onClick(album, rect); + }, [album, onClick]); + + const handleKeyDown = useCallback( + (e) => { + if (e.key === 'Enter') handleClick(); + }, + [handleClick], + ); + + return ( +
+ {/* cover */} + {album.name} + + {/* gradient overlay */} +
+ + {/* meta */} +
+ {album.regionName} +

{album.name}

+ {album.photoCount} frames +
+
+ ); +}