Skip to content

Commit 3482d0f

Browse files
upd qol
1 parent b15e02e commit 3482d0f

1 file changed

Lines changed: 188 additions & 20 deletions

File tree

portfolio.html

Lines changed: 188 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
display: flex;
4343
align-items: center;
4444
gap: 0.1rem;
45-
z-index: 100;
45+
z-index: 300;
4646
}
4747

4848
.theme-btn {
@@ -72,7 +72,7 @@
7272
text-decoration: none;
7373
letter-spacing: 0.06em;
7474
transition: color 0.2s ease;
75-
z-index: 100;
75+
z-index: 300;
7676
}
7777

7878
.back-link:hover { color: var(--muted); }
@@ -84,6 +84,7 @@
8484
background: var(--bg);
8585
color: var(--text);
8686
line-height: 1.6;
87+
transition: background 0.2s ease, color 0.2s ease;
8788
}
8889

8990
/* ── Layout ── */
@@ -161,9 +162,7 @@
161162
line-height: 1.75;
162163
}
163164

164-
.about-text + .about-text {
165-
margin-top: 1rem;
166-
}
165+
.about-text + .about-text { margin-top: 1rem; }
167166

168167
/* ── Skills ── */
169168
.skills-grid {
@@ -201,7 +200,6 @@
201200
flex-direction: column;
202201
gap: 0.5rem;
203202
transition: background 0.2s ease;
204-
cursor: pointer;
205203
}
206204

207205
.project-card:hover { background: var(--bg2); }
@@ -251,27 +249,33 @@
251249
letter-spacing: 0.04em;
252250
}
253251

254-
/* Screenshot placeholder */
252+
/* ── Project image ── */
255253
.project-img {
256254
width: 100%;
257255
aspect-ratio: 16/9;
258256
background: var(--tag-bg);
259-
border: 1px dashed var(--line);
257+
border: 1px solid var(--line);
260258
display: flex;
261259
align-items: center;
262260
justify-content: center;
263-
margin-top: 0.5rem;
261+
margin-top: 0.75rem;
264262
overflow: hidden;
265263
position: relative;
264+
border-radius: 2px;
265+
cursor: zoom-in;
266266
}
267267

268268
.project-img img {
269269
width: 100%;
270270
height: 100%;
271271
object-fit: cover;
272+
object-position: top;
272273
display: block;
274+
transition: transform 0.4s ease;
273275
}
274276

277+
.project-card:hover .project-img img { transform: scale(1.02); }
278+
275279
.project-img-label {
276280
font-family: 'DM Mono', monospace;
277281
font-size: 0.65rem;
@@ -283,6 +287,101 @@
283287

284288
.project-img img ~ .project-img-label { display: none; }
285289

290+
/* ── Lightbox ── */
291+
.lightbox {
292+
position: fixed;
293+
inset: 0;
294+
z-index: 500;
295+
background: rgba(0,0,0,0.88);
296+
display: none;
297+
flex-direction: column;
298+
align-items: center;
299+
justify-content: center;
300+
padding: 2rem;
301+
}
302+
303+
.lightbox.open { display: flex; }
304+
305+
.lightbox-inner {
306+
position: relative;
307+
max-width: min(900px, 92vw);
308+
width: 100%;
309+
display: flex;
310+
flex-direction: column;
311+
align-items: center;
312+
gap: 1.25rem;
313+
}
314+
315+
.lightbox-img-wrap {
316+
width: 100%;
317+
position: relative;
318+
}
319+
320+
.lightbox-img-wrap img {
321+
width: 100%;
322+
max-height: 70vh;
323+
object-fit: contain;
324+
display: block;
325+
border-radius: 2px;
326+
}
327+
328+
/* nav arrows */
329+
.lightbox-nav {
330+
display: flex;
331+
align-items: center;
332+
justify-content: space-between;
333+
width: 100%;
334+
}
335+
336+
.lb-arrow {
337+
font-family: 'DM Mono', monospace;
338+
font-size: 0.75rem;
339+
color: rgba(255,255,255,0.35);
340+
background: none;
341+
border: none;
342+
cursor: pointer;
343+
letter-spacing: 0.08em;
344+
padding: 0.5rem 0;
345+
transition: color 0.2s ease;
346+
user-select: none;
347+
}
348+
349+
.lb-arrow:hover { color: rgba(255,255,255,0.85); }
350+
.lb-arrow:disabled { opacity: 0; pointer-events: none; }
351+
352+
.lb-counter {
353+
font-family: 'DM Mono', monospace;
354+
font-size: 0.65rem;
355+
color: rgba(255,255,255,0.3);
356+
letter-spacing: 0.1em;
357+
}
358+
359+
.lb-caption {
360+
font-family: 'DM Mono', monospace;
361+
font-size: 0.65rem;
362+
color: rgba(255,255,255,0.4);
363+
letter-spacing: 0.08em;
364+
text-transform: uppercase;
365+
text-align: center;
366+
}
367+
368+
.lb-close {
369+
position: absolute;
370+
top: -0.25rem;
371+
right: 0;
372+
font-family: 'DM Mono', monospace;
373+
font-size: 0.7rem;
374+
color: rgba(255,255,255,0.3);
375+
background: none;
376+
border: none;
377+
cursor: pointer;
378+
letter-spacing: 0.08em;
379+
transition: color 0.2s ease;
380+
padding: 0.25rem 0;
381+
}
382+
383+
.lb-close:hover { color: rgba(255,255,255,0.8); }
384+
286385
/* ── Contact ── */
287386
.contact-list {
288387
display: flex;
@@ -358,13 +457,29 @@
358457
<!-- Back link -->
359458
<a class="back-link" href="/index.html">← index</a>
360459

460+
<!-- Lightbox -->
461+
<div class="lightbox" id="lightbox" onclick="handleLbClick(event)">
462+
<div class="lightbox-inner">
463+
<button class="lb-close" onclick="closeLightbox()">close ×</button>
464+
<div class="lightbox-img-wrap">
465+
<img id="lb-img" src="" alt="">
466+
</div>
467+
<div class="lightbox-nav">
468+
<button class="lb-arrow" id="lb-prev" onclick="lbNav(-1)">← prev</button>
469+
<span class="lb-counter" id="lb-counter"></span>
470+
<button class="lb-arrow" id="lb-next" onclick="lbNav(1)">next →</button>
471+
</div>
472+
<p class="lb-caption" id="lb-caption"></p>
473+
</div>
474+
</div>
475+
361476
<div class="page">
362477

363478
<!-- Header -->
364479
<header>
365480
<p class="header-label">Portfolio</p>
366481
<h1>Yoshiro</h1>
367-
<p class="tagline">Homelab dev &amp; computer designer. High schooler building things that actually run.</p>
482+
<p class="tagline">Homelab dev &amp; computer designer. High schooler building things that i actually use.</p>
368483
</header>
369484

370485
<!-- About -->
@@ -411,7 +526,7 @@ <h1>Yoshiro</h1>
411526
<span class="spec">1.21.1</span>
412527
<span class="spec">modded</span>
413528
</div>
414-
<div class="project-img">
529+
<div class="project-img" onclick="openLightbox('images/mc-screenshot.png', 'Modded Minecraft Server')">
415530
<img src="images/mc-screenshot.png" alt="Minecraft server">
416531
<span class="project-img-label">add screenshot</span>
417532
</div>
@@ -429,7 +544,7 @@ <h1>Yoshiro</h1>
429544
<span class="spec">2&times;16TB HDD</span>
430545
<span class="spec">1TB SSD</span>
431546
</div>
432-
<div class="project-img">
547+
<div class="project-img" onclick="openLightbox('images/homelab.png', 'DIY Homelab')">
433548
<img src="images/homelab.png" alt="Homelab build">
434549
<span class="project-img-label">add photo</span>
435550
</div>
@@ -446,7 +561,7 @@ <h1>Yoshiro</h1>
446561
<span class="spec">DietPi</span>
447562
<span class="spec">cluster</span>
448563
</div>
449-
<div class="project-img">
564+
<div class="project-img" onclick="openLightbox('images/pi-cluster.jpg', 'Raspberry Pi Cluster')">
450565
<img src="images/pi-cluster.jpg" alt="Pi cluster">
451566
<span class="project-img-label">add photo</span>
452567
</div>
@@ -459,14 +574,14 @@ <h1>Yoshiro</h1>
459574
<section id="contact">
460575
<p class="section-label">Get in touch</p>
461576
<div class="contact-list">
462-
<a class="contact-item" href="https://github.com/yoshiro" target="_blank" rel="noopener">
577+
<a class="contact-item" href="https://github.com/YoshiroMaximus" target="_blank" rel="noopener">
463578
<span class="contact-platform">GitHub</span>
464-
<span class="contact-value">github.com/yoshiro</span>
579+
<span class="contact-value">github.com/YoshiroMaximus</span>
465580
<span class="contact-arrow"></span>
466581
</a>
467-
<a class="contact-item" href="/cdn-cgi/l/email-protection#dda4b2a89db8b0bcb4b1f3beb2b0">
582+
<a class="contact-item" href="mailto:nico@sendan.com">
468583
<span class="contact-platform">Email</span>
469-
<span class="contact-value"><span class="__cf_email__" data-cfemail="9fe6f0eadffaf2fef6f3b1fcf0f2">[email&#160;protected]</span></span>
584+
<span class="contact-value">nico@sendan.com</span>
470585
<span class="contact-arrow"></span>
471586
</a>
472587
</div>
@@ -480,17 +595,17 @@ <h1>Yoshiro</h1>
480595
</div>
481596

482597
<script>
598+
// ── Theme ──
483599
function setTheme(theme) {
484600
document.body.classList.toggle('dark', theme === 'dark');
485601
document.getElementById('btn-light').classList.toggle('active', theme === 'light');
486602
document.getElementById('btn-dark').classList.toggle('active', theme === 'dark');
487603
localStorage.setItem('theme', theme);
488604
}
489-
490-
// Load saved theme or default to light
491605
const saved = localStorage.getItem('theme') || 'light';
492606
setTheme(saved);
493607

608+
// ── Scroll observer ──
494609
const observer = new IntersectionObserver((entries) => {
495610
entries.forEach(entry => {
496611
if (entry.isIntersecting) {
@@ -499,8 +614,61 @@ <h1>Yoshiro</h1>
499614
}
500615
});
501616
}, { threshold: 0.1 });
502-
503617
document.querySelectorAll('section').forEach(el => observer.observe(el));
618+
619+
// ── Lightbox ──
620+
// Collect all images from project cards
621+
const gallery = [
622+
{ src: 'images/mc-screenshot.png', caption: 'Modded Minecraft Server' },
623+
{ src: 'images/homelab.png', caption: 'DIY Homelab' },
624+
{ src: 'images/pi-cluster.jpg', caption: 'Raspberry Pi Cluster' },
625+
];
626+
627+
let lbIndex = 0;
628+
629+
function openLightbox(src, caption) {
630+
lbIndex = gallery.findIndex(g => g.src === src);
631+
if (lbIndex === -1) lbIndex = 0;
632+
renderLb();
633+
const lb = document.getElementById('lightbox');
634+
lb.style.display = 'flex';
635+
requestAnimationFrame(() => lb.classList.add('open'));
636+
document.body.style.overflow = 'hidden';
637+
}
638+
639+
function closeLightbox() {
640+
const lb = document.getElementById('lightbox');
641+
lb.classList.remove('open');
642+
lb.style.display = 'none';
643+
document.body.style.overflow = '';
644+
}
645+
646+
function lbNav(dir) {
647+
lbIndex = Math.max(0, Math.min(gallery.length - 1, lbIndex + dir));
648+
renderLb();
649+
}
650+
651+
function renderLb() {
652+
const item = gallery[lbIndex];
653+
document.getElementById('lb-img').src = item.src;
654+
document.getElementById('lb-img').alt = item.caption;
655+
document.getElementById('lb-caption').textContent = item.caption;
656+
document.getElementById('lb-counter').textContent = (lbIndex + 1) + ' / ' + gallery.length;
657+
document.getElementById('lb-prev').disabled = lbIndex === 0;
658+
document.getElementById('lb-next').disabled = lbIndex === gallery.length - 1;
659+
}
660+
661+
function handleLbClick(e) {
662+
if (e.target === document.getElementById('lightbox')) closeLightbox();
663+
}
664+
665+
document.addEventListener('keydown', e => {
666+
const lb = document.getElementById('lightbox');
667+
if (!lb.classList.contains('open')) return;
668+
if (e.key === 'Escape') closeLightbox();
669+
if (e.key === 'ArrowLeft') lbNav(-1);
670+
if (e.key === 'ArrowRight') lbNav(1);
671+
});
504672
</script>
505673
</body>
506674
</html>

0 commit comments

Comments
 (0)