-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgalleries.html
More file actions
148 lines (146 loc) · 12.8 KB
/
Copy pathgalleries.html
File metadata and controls
148 lines (146 loc) · 12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Photo Galleries</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,400;1,300;1,400&family=Jost:wght@300;400;500&display=swap" rel="stylesheet" />
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--cream: #f7f3ee; --warm: #ede8e0; --border: #d4cdc4;
--ink: #1c1917; --muted: #8a7f76; --accent: #b5873a;
}
body { background: var(--cream); color: var(--ink); font-family: 'Jost', sans-serif; font-weight: 300; min-height: 100vh; }
nav { border-bottom: 1px solid var(--border); background: var(--cream); position: sticky; top: 0; z-index: 100; }
.nav-inner { max-width: 1100px; margin: 0 auto; padding: 0 2rem; display: flex; align-items: center; justify-content: space-between; height: 56px; }
.nav-brand { font-family: 'Cormorant Garamond', serif; font-size: 1.3rem; font-weight: 400; font-style: italic; color: var(--ink); text-decoration: none; }
.nav-links-row { display: flex; list-style: none; }
.nav-links-row a { display: block; padding: 0 1rem; font-size: 0.72rem; font-weight: 400; letter-spacing: 0.15em; text-transform: uppercase; color: var(--muted); text-decoration: none; line-height: 56px; border-bottom: 2px solid transparent; transition: color 0.2s, border-color 0.2s; }
.nav-links-row a:hover, .nav-links-row a.active { color: var(--ink); border-bottom-color: var(--accent); }
.hamburger { display: none; background: none; border: none; cursor: pointer; padding: 4px; flex-direction: column; gap: 5px; }
.hamburger span { display: block; width: 22px; height: 1.5px; background: var(--ink); }
.mobile-menu-nav { display: none; border-bottom: 1px solid var(--border); background: var(--cream); }
.mobile-menu-nav a { display: block; padding: 0.85rem 2rem; font-size: 0.78rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--border); }
.mobile-menu-nav a:last-child { border-bottom: none; }
.mobile-menu-nav a:hover, .mobile-menu-nav a.active { color: var(--ink); background: var(--warm); }
.mobile-menu-nav.open { display: block; }
@media (max-width: 640px) { .nav-links-row { display: none; } .hamburger { display: flex; } }
header { padding: 3rem 2rem 2rem; text-align: center; border-bottom: 1px solid var(--border); }
.site-label { font-size: 0.65rem; font-weight: 500; letter-spacing: 0.3em; text-transform: uppercase; color: var(--accent); margin-bottom: 0.75rem; }
h1 { font-family: 'Cormorant Garamond', serif; font-size: clamp(2.8rem, 6vw, 4.5rem); font-weight: 300; line-height: 1.05; letter-spacing: -0.01em; }
h1 em { font-style: italic; color: var(--muted); }
.header-rule { width: 40px; height: 1px; background: var(--accent); margin: 1.25rem auto 0; }
.gallery-count { text-align: center; font-size: 0.72rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); padding: 1.75rem 2rem 0; }
.search-area { display: none; padding: 1.25rem 2rem 0; max-width: 480px; margin: 0 auto; }
.search-area input { width: 100%; background: transparent; border: none; border-bottom: 1px solid var(--border); padding: 0.5rem 0; font-family: 'Jost', sans-serif; font-size: 0.85rem; font-weight: 300; color: var(--ink); outline: none; letter-spacing: 0.05em; transition: border-color 0.2s; }
.search-area input:focus { border-color: var(--accent); }
.search-area input::placeholder { color: var(--muted); }
.gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); padding: 2rem; max-width: 1200px; margin: 0 auto; gap: 0; }
.gallery-card { display: block; text-decoration: none; color: inherit; position: relative; overflow: hidden; aspect-ratio: 3/4; background: var(--warm); outline: 4px solid var(--cream); opacity: 0; transform: translateY(20px); animation: fadeUp 0.5s forwards; }
@keyframes fadeUp { to { opacity: 1; transform: translateY(0); } }
.gallery-card img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.6s cubic-bezier(0.25,0.46,0.45,0.94), filter 0.4s; filter: brightness(0.92) saturate(0.9); }
.gallery-card:hover img { transform: scale(1.06); filter: brightness(0.72) saturate(1.05); }
.gallery-placeholder { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: linear-gradient(145deg, var(--warm), var(--border)); font-size: 3rem; transition: transform 0.6s; }
.gallery-card:hover .gallery-placeholder { transform: scale(1.05); }
.card-overlay { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: flex-end; padding: 1.5rem; background: linear-gradient(to top, rgba(20,16,12,0.75) 0%, transparent 55%); opacity: 0; transition: opacity 0.35s; }
.gallery-card:hover .card-overlay { opacity: 1; }
.card-title { font-family: 'Cormorant Garamond', serif; font-size: 1.6rem; font-weight: 300; color: #fff; line-height: 1.1; margin-bottom: 0.3rem; }
.card-meta { font-size: 0.68rem; letter-spacing: 0.15em; text-transform: uppercase; color: rgba(255,255,255,0.55); }
.message { text-align: center; padding: 4rem 2rem; color: var(--muted); font-size: 0.9rem; line-height: 1.8; grid-column: 1/-1; }
footer { text-align: center; padding: 2rem; font-size: 0.65rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--border); border-top: 1px solid var(--border); margin-top: 2rem; }
@media (max-width: 500px) { .gallery-grid { grid-template-columns: repeat(2, 1fr); padding: 1rem; } .card-overlay { opacity: 1; } }
/* ── FOOTER ── */
.site-footer { background: var(--cream); color: var(--ink); text-align: center; padding: 2.5rem 2rem 2rem; margin-top: auto; border-top: 1px solid var(--border); }
.footer-social { display: flex; gap: 1.25rem; justify-content: center; margin-bottom: 1.25rem; }
.footer-social a { color: var(--muted); transition: color 0.25s; display: inline-flex; }
.footer-social a:hover { color: var(--accent); }
.footer-social a[data-platform="IMDb"]:hover { color: #f5c518; }
.footer-name { font-family: 'Cormorant Garamond', serif; font-size: 1.3rem; font-style: italic; font-weight: 300; display: block; margin-bottom: 0.5rem; color: var(--ink); }
.footer-copy { font-size: 0.68rem; letter-spacing: 0.12em; color: var(--muted); line-height: 1.9; }
.footer-version { font-size: 0.55rem; color: var(--border); margin-top: 0.5rem; }
</style>
</head>
<body>
<nav>
<div class="nav-inner">
<a class="nav-brand" href="index.html">Molly Loch</a>
<ul class="nav-links-row"><li><a href="index.html">Home</a></li><li><a href="galleries.html" class="active">Galleries</a></li><li><a href="resume.html">Resume</a></li><li><a href="reels.html">Reels</a></li><li><a href="contact.html">Contact</a></li></ul>
<button class="hamburger" id="hamburger"><span></span><span></span><span></span></button>
</div>
<div class="mobile-menu-nav" id="mobileMenu"><a href="index.html">Home</a><a href="galleries.html" class="active">Galleries</a><a href="resume.html">Resume</a><a href="reels.html">Reels</a><a href="contact.html">Contact</a></div>
</nav>
<header><p class="site-label">Portfolio</p><h1>Photo <em>Galleries</em></h1><div class="header-rule"></div></header>
<p class="gallery-count" id="count">Loading…</p>
<div class="search-area" id="searchArea"><input id="search" type="text" placeholder="Search galleries…" autocomplete="off" /></div>
<div class="gallery-grid" id="grid"></div>
<footer class="site-footer" id="siteFooter">
<div class="footer-social" id="footerSocial"></div>
<span class="footer-name" id="footerName"></span>
<div class="footer-copy" id="footerCopy"></div>
<div class="footer-version" id="footerVersion"></div>
</footer>
<script>
document.getElementById('hamburger').addEventListener('click', function() {
document.getElementById('mobileMenu').classList.toggle('open');
});
var grid=document.getElementById("grid"),countEl=document.getElementById("count"),searchEl=document.getElementById("search"),searchArea=document.getElementById("searchArea");
function esc(s){return String(s).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");}
fetch("galleries.json").then(function(r){if(!r.ok)throw new Error("HTTP "+r.status);return r.json();})
.then(function(galleries){
countEl.textContent=galleries.length+" Collection"+(galleries.length!==1?"s":"");
if(galleries.length===0){grid.innerHTML='<p class="message">No galleries found yet.</p>';return;}
if(galleries.length>4)searchArea.style.display="block";
galleries.forEach(function(g,i){
var a=document.createElement("a");
a.className="gallery-card";
a.href="gallery.html?folder="+encodeURIComponent(g.slug)+"&title="+encodeURIComponent(g.title);
a.style.animationDelay=(i*0.08)+"s";
a.innerHTML=(g.cover?'<img src="'+esc(g.cover)+'" alt="'+esc(g.title)+'" loading="lazy" />':'<div class="gallery-placeholder">📷</div>')
+'<div class="card-overlay"><div class="card-title">'+esc(g.title)+'</div><div class="card-meta">'+g.count+' image'+(g.count!==1?"s":"")+'</div></div>';
grid.appendChild(a);
});
searchEl.addEventListener("input",function(){
var q=searchEl.value.toLowerCase();
document.querySelectorAll(".gallery-card").forEach(function(c){c.style.display=c.textContent.toLowerCase().includes(q)?"":"none";});
});
})
.catch(function(err){grid.innerHTML='<p class="message">Could not load galleries.json ('+err.message+')<br>Run generate-galleries.js first.</p>';countEl.textContent="";});
</script>
<script>
// Footer loader
(function() {
var icons = {
"youtube": '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M23.5 6.2a3 3 0 0 0-2.1-2.1C19.5 3.5 12 3.5 12 3.5s-7.5 0-9.4.6A3 3 0 0 0 .5 6.2C0 8.1 0 12 0 12s0 3.9.5 5.8a3 3 0 0 0 2.1 2.1c1.9.6 9.4.6 9.4.6s7.5 0 9.4-.6a3 3 0 0 0 2.1-2.1C24 15.9 24 12 24 12s0-3.9-.5-5.8zM9.7 15.5V8.5l6.3 3.5-6.3 3.5z"/></svg>',
"instagram": '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.2c3.2 0 3.6 0 4.9.1 3.3.2 4.8 1.7 5 5 .1 1.3.1 1.6.1 4.9s0 3.6-.1 4.9c-.2 3.3-1.7 4.8-5 5-1.3.1-1.6.1-4.9.1s-3.6 0-4.9-.1c-3.3-.2-4.8-1.7-5-5C2 16.6 2 16.3 2 13s0-3.6.1-4.9c.2-3.3 1.7-4.8 5-5C8.4 2.2 8.8 2.2 12 2.2zm0-2.2C8.7 0 8.3 0 7.1.1 2.7.3.3 2.7.1 7.1 0 8.3 0 8.7 0 12s0 3.7.1 4.9C.3 21.3 2.7 23.7 7.1 23.9 8.3 24 8.7 24 12 24s3.7 0 4.9-.1c4.4-.2 6.8-2.6 7-7 .1-1.2.1-1.6.1-4.9s0-3.7-.1-4.9C23.7 2.7 21.3.3 16.9.1 15.7 0 15.3 0 12 0zm0 5.8a6.2 6.2 0 1 0 0 12.4A6.2 6.2 0 0 0 12 5.8zm0 10.2a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm6.4-11.8a1.4 1.4 0 1 0 0 2.8 1.4 1.4 0 0 0 0-2.8z"/></svg>',
"facebook": '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M24 12.1C24 5.4 18.6 0 12 0S0 5.4 0 12.1C0 18.1 4.4 23.1 10.1 24v-8.4H7.1v-3.5h3V9.4c0-3 1.8-4.7 4.5-4.7 1.3 0 2.7.2 2.7.2v3h-1.5c-1.5 0-2 .9-2 1.9v2.3h3.4l-.5 3.5h-2.8V24C19.6 23.1 24 18.1 24 12.1z"/></svg>',
"imdb": '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M14.3 8H13V16h1.3c2.1 0 3.3-1.2 3.3-4S16.4 8 14.3 8zM21.6 0H2.4C1.1 0 0 1.1 0 2.4v19.2C0 22.9 1.1 24 2.4 24h19.2c1.3 0 2.4-1.1 2.4-2.4V2.4C24 1.1 22.9 0 21.6 0zM7 16H5V8h2v8zm4.5 0H9.7V8h1.8v8zm7.2-3.8c-.5 2.5-2.1 3.8-4.8 3.8H11.8V8h3.9c2.7 0 4.1 1.5 4.1 4.2-.1.7-.1 0-.1 0z"/></svg>'
};
fetch('talent.json')
.then(function(r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })
.then(function(t) {
var social = document.getElementById('footerSocial');
if (social && t.social) {
t.social.forEach(function(s) {
var a = document.createElement('a');
a.href = s.url;
a.target = '_blank';
a.title = s.platform;
a.setAttribute('data-platform', s.platform);
a.innerHTML = icons[s.icon] || s.platform;
social.appendChild(a);
});
}
var fn = document.getElementById('footerName');
if (fn) fn.textContent = t.name;
var fc = document.getElementById('footerCopy');
if (fc) fc.innerHTML = '© ' + t.copyright_year + ' ' + t.name + ' · All Rights Reserved<br>' + t.role + ' · ' + t.location;
var fv = document.getElementById('footerVersion');
if (fv) fv.textContent = 'Version 1.0';
})
.catch(function(err) { console.warn('Footer: could not load talent.json -', err.message); });
})();
</script>
</body>
</html>