design: polish nav ice-glass, section headers, cards, timeline, skills, footer, marquee
Changes
@@@ -3,12 +3,13 @@<section class="contact" id="contact"><div class="container"><div class="section-eyebrow"><i class="fa-solid fa-paper-plane"></i> Contact</div>-- <h2 class="section-title"><i class="fa-solid fa-paper-plane"></i> Let's build something</h2>++ <h2 class="section-title">Let's connect</h2><div class="contact__grid"><div class="card contact__card"><p class="contact__lead">-- Open to data-analyst, software-engineering, and platform-builder roles-- across the Pacific Northwest and remote. Always happy to chat shop.++ Open to data analyst, software engineer, and platform builder roles —++ Pacific Northwest, remote, or hybrid. Happy to talk tech, collaborate on++ something interesting, or just say hi.</p><div class="contact__direct">@@@ -44,14 +45,9 @@<style>.contact__grid { display: grid; }-- .section-title i {-- color: var(--accent);-- margin-right: 0.4rem;-- font-size: 0.9em;-- }--.contact__lead {font-size: 1.1rem;++ line-height: 1.7;color: var(--fg);margin-bottom: 1.8rem;}@@@ -6,13 +6,13 @@ const items = (await getCollection("experience"))<section class="exp" id="experience"><div class="container"><div class="section-eyebrow"><i class="fa-solid fa-briefcase"></i> Experience</div>-- <h2 class="section-title"><i class="fa-solid fa-timeline"></i> A decade-plus of building</h2>++ <h2 class="section-title">A decade-plus of shipping</h2><ol class="exp__list">{items.map((it) => (<li class="exp__item card" data-reveal><div class="exp__dates"><span class="exp__dot" aria-hidden="true"></span>-- <span><i class="fa-regular fa-calendar-days"></i> {it.data.start} — {it.data.end}</span>++ <span><i class="fa-regular fa-calendar-days"></i> {it.data.start} — {it.data.end ?? 'Present'}</span></div><div class="exp__body"><h3>{it.data.role}</h3>@@@ -33,33 +33,49 @@ const items = (await getCollection("experience"))</section><style>-- .exp__list { list-style: none; padding: 0; margin: 0; display: grid; gap: 18px; }++ .exp__list { list-style: none; padding: 0; margin: 0; display: grid; gap: 16px; }.exp__item {display: grid;grid-template-columns: 200px 1fr;-- gap: 20px;++ gap: 24px;++ align-items: start;}@media (max-width: 720px) {-- .exp__item { grid-template-columns: 1fr; }++ .exp__item { grid-template-columns: 1fr; gap: 10px; }}.exp__dates {-- display: flex; align-items: center; gap: 10px;++ display: flex;++ flex-direction: column;++ align-items: flex-start;++ gap: 8px;color: var(--muted);font-family: var(--font-mono);-- font-size: .9rem;++ font-size: .8rem;++ padding-top: 6px;++ line-height: 1.6;}.exp__dot {-- width: 10px; height: 10px; border-radius: 50%;-- background: var(--accent); box-shadow: 0 0 14px var(--accent);++ width: 9px; height: 9px; border-radius: 50%;++ background: var(--accent);++ box-shadow: 0 0 10px rgba(76,201,176,0.6), 0 0 24px rgba(76,201,176,0.25);++ flex-shrink: 0;++ }++ .exp__body {++ border-left: 2px solid rgba(76,201,176,0.15);++ padding-left: 20px;++ }++ @media (max-width: 720px) {++ .exp__body { border-left: none; padding-left: 0; border-top: 2px solid rgba(76,201,176,0.15); padding-top: 12px; }}.exp__body h3 {font-family: var(--font-display);-- font-size: 1.25rem; margin: 0 0 .3rem;++ font-size: 1.2rem; margin: 0 0 .3rem;}-- .exp__company { color: var(--accent); margin-bottom: .8rem; font-weight: 600; }++ .exp__company { color: var(--accent); margin-bottom: .8rem; font-size: 0.9rem; font-weight: 600; }.exp__body ul {margin: 0 0 1rem; padding-left: 1.1rem;-- color: var(--muted); line-height: 1.7;++ color: var(--muted); line-height: 1.75;}++ .exp__body ul li { margin-bottom: 0.25rem; }.exp__stack { display: flex; flex-wrap: wrap; gap: 6px; }</style>@@@ -2,26 +2,67 @@const year = new Date().getFullYear();---<footer class="foot">-- <div class="container foot__row">-- <small>© {year} Alex Frison · Built in the Pacific Northwest</small>-- <small>-- <a href="mailto:[email protected]"><i class="fa-solid fa-envelope"></i> [email protected]</a> ·-- <a href="tel:+14253673997"><i class="fa-solid fa-phone"></i> (425) 367-3997</a> ·-- <a href="https://github.com/HoboStreamer" rel="me noopener" target="_blank"><i class="fa-brands fa-github"></i></a> ·-- <a href="https://www.linkedin.com/in/fris/" rel="me noopener" target="_blank"><i class="fa-brands fa-linkedin"></i></a>-- </small>++ <div class="container foot__inner">++ <div class="foot__brand">++ <span class="foot__name">Alex Frison</span>++ <span class="foot__sub">© {year} · Built in the Pacific Northwest</span>++ </div>++ <div class="foot__links">++ <a href="mailto:[email protected]" title="Email"><i class="fa-solid fa-envelope"></i> [email protected]</a>++ <a href="tel:+14253673997" title="Phone"><i class="fa-solid fa-phone"></i> (425) 367-3997</a>++ <a href="https://github.com/HoboStreamer" rel="me noopener" target="_blank" title="GitHub"><i class="fa-brands fa-github"></i> GitHub</a>++ <a href="https://www.linkedin.com/in/fris/" rel="me noopener" target="_blank" title="LinkedIn"><i class="fa-brands fa-linkedin"></i> LinkedIn</a>++ </div></div></footer><style>.foot {border-top: 1px solid var(--border);-- padding: 28px 0;++ padding: 40px 0;color: var(--dim);++ background: linear-gradient(to top, rgba(76,201,176,0.02), transparent);}-- .foot__row {-- display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px;++ .foot__inner {++ display: flex;++ justify-content: space-between;++ align-items: center;++ flex-wrap: wrap;++ gap: 20px;++ }++ .foot__brand {++ display: flex;++ flex-direction: column;++ gap: 3px;++ }++ .foot__name {++ font-family: var(--font-display);++ font-weight: 700;++ font-size: 1rem;++ color: var(--fg);++ letter-spacing: -0.01em;++ }++ .foot__sub {++ font-size: 0.8rem;++ color: var(--muted);++ }++ .foot__links {++ display: flex;++ flex-wrap: wrap;++ gap: 10px 24px;++ align-items: center;++ }++ .foot a {++ color: var(--muted);++ font-size: 0.85rem;++ display: inline-flex;++ align-items: center;++ gap: 6px;++ transition: color .2s;++ text-decoration: none;}-- .foot a { color: var(--muted); transition: color .2s; }.foot a:hover { color: var(--accent); }-- .foot a i { font-size: 0.9rem; }++ .foot a i { font-size: 0.9em; }++ @media (max-width: 540px) {++ .foot__inner { flex-direction: column; align-items: flex-start; }++ }</style>@@@ -48,9 +48,9 @@ const metrics = [transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;}.impact__card:hover {-- transform: translateY(-3px);-- border-color: var(--accent);-- box-shadow: 0 12px 28px -16px color-mix(in srgb, var(--accent) 55%, transparent);++ transform: translateY(-4px);++ border-color: rgba(76,201,176,0.35);++ box-shadow: 0 12px 40px -12px rgba(76,201,176,0.3), 0 0 0 1px rgba(76,201,176,0.08);}.impact__icon {font-size: 1.05rem;@@@ -64,7 +64,7 @@ const metrics = [font-family: var(--font-display);font-size: clamp(1.7rem, 2.6vw, 2.1rem);font-weight: 700;-- color: var(--text);++ color: var(--fg);line-height: 1.05;}.impact__lbl {@@@ -19,15 +19,20 @@ const tech = [backdrop-filter: blur(8px);}.marquee__track {-- display: flex; gap: 56px; padding: 18px 0;++ display: flex; gap: 0; padding: 16px 0;width: max-content;animation: scroll 80s linear infinite;font-family: var(--font-mono);color: var(--muted);-- font-size: .95rem;++ font-size: .88rem;letter-spacing: 0.04em;}-- .marquee__track span { white-space: nowrap; }++ .marquee__track span {++ white-space: nowrap;++ padding: 0 28px;++ border-right: 1px solid var(--border);++ }++ .marquee__track span:last-child { border-right: none; }@media (hover: hover) {.marquee:hover .marquee__track { animation-play-state: paused; }}@@@ -54,14 +54,31 @@ const links = [border-bottom: 1px solid transparent;backdrop-filter: none;-webkit-backdrop-filter: none;-- transition: background .35s ease, border-color .35s ease;++ transition: background .4s ease, border-color .4s ease, box-shadow .4s ease;will-change: background;}++ /* Frosted ice-glass on scroll */.nav--scrolled {-- backdrop-filter: blur(14px);-- -webkit-backdrop-filter: blur(14px);-- background: color-mix(in oklab, var(--bg) 78%, transparent);-- border-bottom: 1px solid var(--border);++ backdrop-filter: blur(24px) saturate(180%);++ -webkit-backdrop-filter: blur(24px) saturate(180%);++ background: color-mix(in oklab, var(--bg) 68%, transparent);++ border-bottom: 1px solid rgba(255, 255, 255, 0.07);++ box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.04), 0 8px 40px rgba(0, 0, 0, 0.38);++ }++ /* Brighter links when floating over hero (transparent state) */++ .nav:not(.nav--scrolled) .nav__links a {++ color: rgba(230, 237, 243, 0.88);++ }++ .nav:not(.nav--scrolled) .nav__links a:hover {++ color: #fff;++ }++ .nav:not(.nav--scrolled) .nav__brand {++ color: var(--fg);++ }++ .nav:not(.nav--scrolled) .nav__toggle,++ .nav:not(.nav--scrolled) .nav__burger {++ border-color: rgba(255, 255, 255, 0.15);++ color: rgba(230, 237, 243, 0.8);}.nav__row {display: flex; align-items: center; gap: 16px;@@@ -6,7 +6,7 @@ const featured = all.sort((a, b) => a.data.order - b.data.order);<section class="featured" id="work"><div class="container"><div class="section-eyebrow"><i class="fa-solid fa-star"></i> Featured Work</div>-- <h2 class="section-title"><i class="fa-solid fa-star"></i> Things I've shipped</h2>++ <h2 class="section-title">Things I've shipped</h2><p class="featured__lead">A rotating gallery of the products, tools, and agents I've built —from Amazon ICQA analytics to the Hobo Network creator stack.@@@ -22,7 +22,7 @@ const filterIcon: Record<string, string> = {<section class="grid-sec" id="portfolio"><div class="container"><div class="section-eyebrow"><i class="fa-solid fa-layer-group"></i> Portfolio</div>-- <h2 class="section-title"><i class="fa-solid fa-layer-group"></i> All work</h2>++ <h2 class="section-title">All work</h2><div class="filters" role="tablist">{cats.map((c, i) => (<button class={`filter ${i === 0 ? "is-active" : ""}`} data-filter={c} role="tab">@@@ -5,7 +5,7 @@ const groups = (await getCollection("skills")).sort((a, b) => a.data.order - b.d<section class="skills" id="skills"><div class="container"><div class="section-eyebrow"><i class="fa-solid fa-code"></i> Stack</div>-- <h2 class="section-title"><i class="fa-solid fa-code"></i> Skills & tooling</h2>++ <h2 class="section-title">Skills & stack</h2><div class="skills__grid">{groups.map((g) => (<article class="card skills__card" data-reveal>@@@ -28,23 +28,32 @@ const groups = (await getCollection("skills")).sort((a, b) => a.data.order - b.ddisplay: grid; gap: 18px;grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));}++ .skills__card {++ border-top: 2px solid rgba(76,201,176,0.25) !important;++ }.skills__card h3 {font-family: var(--font-display);-- font-size: 1.05rem;++ font-size: 1rem;++ font-weight: 700;color: var(--accent);margin-bottom: 1rem;++ letter-spacing: 0.01em;}.skills__card ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 6px; }.skills__item {-- padding: 6px 12px;++ padding: 5px 12px;border-radius: 8px;border: 1px solid var(--border);-- font: 500 .85rem var(--font-body);++ font: 500 .83rem var(--font-body);color: var(--fg);background: rgba(255,255,255,0.02);-- transition: transform .2s var(--ease), border-color .2s var(--ease);++ transition: transform .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);++ }++ .skills__item:hover { transform: translateY(-2px); border-color: rgba(76,201,176,0.4); background: rgba(76,201,176,0.05); }++ .skills__item--core {++ border-color: rgba(76,201,176,.32);++ color: var(--accent);++ background: rgba(76,201,176,.06);}-- .skills__item:hover { transform: translateY(-2px); border-color: var(--accent); }-- .skills__item--core { border-color: rgba(76,201,176,.35); color: var(--accent); }-- .skills__item--familiar { color: var(--dim); }++ .skills__item--familiar { color: var(--dim); border-color: var(--border); }</style>@@@ -18,7 +18,7 @@ import ContactBlock from "../components/ContactBlock.astro";<div class="container profile__row"><div data-reveal><div class="section-eyebrow"><i class="fa-solid fa-user"></i> Profile</div>-- <h2 class="section-title"><i class="fa-solid fa-user"></i> A versatile builder</h2>++ <h2 class="section-title">A versatile builder</h2><p class="profile-para"><i class="fa-solid fa-microchip profile-para__icon"></i><span>Data analyst and systems architect with 10+ years of shipping — from@@@ -114,7 +114,11 @@ section { padding: clamp(60px, 10vw, 120px) 0; position: relative; }box-shadow: var(--shadow-card);transition: transform .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease);}--.card:hover { border-color: var(--border-strong); transform: translateY(-3px); }++.card:hover {++ border-color: rgba(76, 201, 176, 0.3);++ transform: translateY(-4px);++ box-shadow: var(--shadow-card), 0 0 0 1px rgba(76,201,176,0.08), 0 12px 48px -8px rgba(76,201,176,0.18);++}.btn {display: inline-flex; align-items: center; gap: 10px;@@@ -128,19 +132,22 @@ section { padding: clamp(60px, 10vw, 120px) 0; position: relative; }transition: all .25s var(--ease);text-decoration: none;}--.btn:hover { background: var(--surface-2); transform: translateY(-2px); text-decoration: none; }--.btn--primary { background: var(--accent); color: #06221c; border-color: transparent; }--.btn--primary:hover { background: #5fdcc4; box-shadow: var(--shadow-glow); }++.btn:hover { background: var(--surface-2); transform: translateY(-2px); text-decoration: none; border-color: var(--border-strong); }++.btn--primary { background: var(--accent); color: #06221c; border-color: transparent; font-weight: 700; letter-spacing: 0.01em; }++.btn--primary:hover { background: #5fdcc4; box-shadow: var(--shadow-glow), 0 6px 24px rgba(76,201,176,0.25); transform: translateY(-2px); }.chip {display: inline-flex; align-items: center; gap: 5px;-- padding: 4px 10px;++ padding: 4px 12px;border-radius: 999px;-- font: 500 0.78rem var(--font-mono);-- background: rgba(76, 201, 176, 0.08);-- border: 1px solid rgba(76, 201, 176, 0.2);++ font: 500 0.75rem var(--font-mono);++ background: rgba(76, 201, 176, 0.07);++ border: 1px solid rgba(76, 201, 176, 0.22);color: var(--accent);++ letter-spacing: 0.03em;++ transition: background .2s var(--ease), border-color .2s var(--ease);}++.chip:hover { background: rgba(76, 201, 176, 0.14); border-color: rgba(76, 201, 176, 0.38); }.chip i { font-size: 0.75em; }.skip-link {@@@ -153,6 +160,7 @@ section { padding: clamp(60px, 10vw, 120px) 0; position: relative; }/* Reveal — initial hidden state only; animation driven by JS (Web Animations API) */[data-reveal] {opacity: 0;-- transform: translateY(24px);++ transform: translateY(28px);++ transition: opacity .55s var(--ease), transform .55s var(--ease);}[data-reveal].in { opacity: 1; transform: none; }
@@ -3,12 +3,13 @@
@@ -3,12 +3,13 @@
<section class="contact" id="contact">
<section class="contact" id="contact">
<div class="container">
<div class="container">
<div class="section-eyebrow"><i class="fa-solid fa-paper-plane"></i> Contact</div>
<div class="section-eyebrow"><i class="fa-solid fa-paper-plane"></i> Contact</div>
- <h2 class="section-title"><i class="fa-solid fa-paper-plane"></i> Let's build something</h2>
+ <h2 class="section-title">Let's connect</h2>
<div class="contact__grid">
<div class="contact__grid">
<div class="card contact__card">
<div class="card contact__card">
<p class="contact__lead">
<p class="contact__lead">
- Open to data-analyst, software-engineering, and platform-builder roles
- across the Pacific Northwest and remote. Always happy to chat shop.
+ Open to data analyst, software engineer, and platform builder roles —
+ Pacific Northwest, remote, or hybrid. Happy to talk tech, collaborate on
+ something interesting, or just say hi.
</p>
</p>
<div class="contact__direct">
<div class="contact__direct">
@@ -44,14 +45,9 @@
@@ -44,14 +45,9 @@
<style>
<style>
.contact__grid { display: grid; }
.contact__grid { display: grid; }
- .section-title i {
- color: var(--accent);
- margin-right: 0.4rem;
- font-size: 0.9em;
- }
-
.contact__lead {
.contact__lead {
font-size: 1.1rem;
font-size: 1.1rem;
+ line-height: 1.7;
color: var(--fg);
color: var(--fg);
margin-bottom: 1.8rem;
margin-bottom: 1.8rem;
}
}
@@ -6,13 +6,13 @@ const items = (await getCollection("experience"))
@@ -6,13 +6,13 @@ const items = (await getCollection("experience"))
<section class="exp" id="experience">
<section class="exp" id="experience">
<div class="container">
<div class="container">
<div class="section-eyebrow"><i class="fa-solid fa-briefcase"></i> Experience</div>
<div class="section-eyebrow"><i class="fa-solid fa-briefcase"></i> Experience</div>
- <h2 class="section-title"><i class="fa-solid fa-timeline"></i> A decade-plus of building</h2>
+ <h2 class="section-title">A decade-plus of shipping</h2>
<ol class="exp__list">
<ol class="exp__list">
{items.map((it) => (
{items.map((it) => (
<li class="exp__item card" data-reveal>
<li class="exp__item card" data-reveal>
<div class="exp__dates">
<div class="exp__dates">
<span class="exp__dot" aria-hidden="true"></span>
<span class="exp__dot" aria-hidden="true"></span>
- <span><i class="fa-regular fa-calendar-days"></i> {it.data.start} — {it.data.end}</span>
+ <span><i class="fa-regular fa-calendar-days"></i> {it.data.start} — {it.data.end ?? 'Present'}</span>
</div>
</div>
<div class="exp__body">
<div class="exp__body">
<h3>{it.data.role}</h3>
<h3>{it.data.role}</h3>
@@ -33,33 +33,49 @@ const items = (await getCollection("experience"))
@@ -33,33 +33,49 @@ const items = (await getCollection("experience"))
</section>
</section>
<style>
<style>
- .exp__list { list-style: none; padding: 0; margin: 0; display: grid; gap: 18px; }
+ .exp__list { list-style: none; padding: 0; margin: 0; display: grid; gap: 16px; }
.exp__item {
.exp__item {
display: grid;
display: grid;
grid-template-columns: 200px 1fr;
grid-template-columns: 200px 1fr;
- gap: 20px;
+ gap: 24px;
+ align-items: start;
}
}
@media (max-width: 720px) {
@media (max-width: 720px) {
- .exp__item { grid-template-columns: 1fr; }
+ .exp__item { grid-template-columns: 1fr; gap: 10px; }
}
}
.exp__dates {
.exp__dates {
- display: flex; align-items: center; gap: 10px;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 8px;
color: var(--muted);
color: var(--muted);
font-family: var(--font-mono);
font-family: var(--font-mono);
- font-size: .9rem;
+ font-size: .8rem;
+ padding-top: 6px;
+ line-height: 1.6;
}
}
.exp__dot {
.exp__dot {
- width: 10px; height: 10px; border-radius: 50%;
- background: var(--accent); box-shadow: 0 0 14px var(--accent);
+ width: 9px; height: 9px; border-radius: 50%;
+ background: var(--accent);
+ box-shadow: 0 0 10px rgba(76,201,176,0.6), 0 0 24px rgba(76,201,176,0.25);
+ flex-shrink: 0;
+ }
+ .exp__body {
+ border-left: 2px solid rgba(76,201,176,0.15);
+ padding-left: 20px;
+ }
+ @media (max-width: 720px) {
+ .exp__body { border-left: none; padding-left: 0; border-top: 2px solid rgba(76,201,176,0.15); padding-top: 12px; }
}
}
.exp__body h3 {
.exp__body h3 {
font-family: var(--font-display);
font-family: var(--font-display);
- font-size: 1.25rem; margin: 0 0 .3rem;
+ font-size: 1.2rem; margin: 0 0 .3rem;
}
}
- .exp__company { color: var(--accent); margin-bottom: .8rem; font-weight: 600; }
+ .exp__company { color: var(--accent); margin-bottom: .8rem; font-size: 0.9rem; font-weight: 600; }
.exp__body ul {
.exp__body ul {
margin: 0 0 1rem; padding-left: 1.1rem;
margin: 0 0 1rem; padding-left: 1.1rem;
- color: var(--muted); line-height: 1.7;
+ color: var(--muted); line-height: 1.75;
}
}
+ .exp__body ul li { margin-bottom: 0.25rem; }
.exp__stack { display: flex; flex-wrap: wrap; gap: 6px; }
.exp__stack { display: flex; flex-wrap: wrap; gap: 6px; }
</style>
</style>
@@ -2,26 +2,67 @@
@@ -2,26 +2,67 @@
const year = new Date().getFullYear();
const year = new Date().getFullYear();
---
---
<footer class="foot">
<footer class="foot">
- <div class="container foot__row">
- <small>© {year} Alex Frison · Built in the Pacific Northwest</small>
- <small>
- <a href="mailto:[email protected]"><i class="fa-solid fa-envelope"></i> [email protected]</a> ·
- <a href="tel:+14253673997"><i class="fa-solid fa-phone"></i> (425) 367-3997</a> ·
- <a href="https://github.com/HoboStreamer" rel="me noopener" target="_blank"><i class="fa-brands fa-github"></i></a> ·
- <a href="https://www.linkedin.com/in/fris/" rel="me noopener" target="_blank"><i class="fa-brands fa-linkedin"></i></a>
- </small>
+ <div class="container foot__inner">
+ <div class="foot__brand">
+ <span class="foot__name">Alex Frison</span>
+ <span class="foot__sub">© {year} · Built in the Pacific Northwest</span>
+ </div>
+ <div class="foot__links">
+ <a href="mailto:[email protected]" title="Email"><i class="fa-solid fa-envelope"></i> [email protected]</a>
+ <a href="tel:+14253673997" title="Phone"><i class="fa-solid fa-phone"></i> (425) 367-3997</a>
+ <a href="https://github.com/HoboStreamer" rel="me noopener" target="_blank" title="GitHub"><i class="fa-brands fa-github"></i> GitHub</a>
+ <a href="https://www.linkedin.com/in/fris/" rel="me noopener" target="_blank" title="LinkedIn"><i class="fa-brands fa-linkedin"></i> LinkedIn</a>
+ </div>
</div>
</div>
</footer>
</footer>
<style>
<style>
.foot {
.foot {
border-top: 1px solid var(--border);
border-top: 1px solid var(--border);
- padding: 28px 0;
+ padding: 40px 0;
color: var(--dim);
color: var(--dim);
+ background: linear-gradient(to top, rgba(76,201,176,0.02), transparent);
}
}
- .foot__row {
- display: flex; justify-content: space-between; flex-wrap: wrap; gap: 12px;
+ .foot__inner {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 20px;
+ }
+ .foot__brand {
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+ }
+ .foot__name {
+ font-family: var(--font-display);
+ font-weight: 700;
+ font-size: 1rem;
+ color: var(--fg);
+ letter-spacing: -0.01em;
+ }
+ .foot__sub {
+ font-size: 0.8rem;
+ color: var(--muted);
+ }
+ .foot__links {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px 24px;
+ align-items: center;
+ }
+ .foot a {
+ color: var(--muted);
+ font-size: 0.85rem;
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ transition: color .2s;
+ text-decoration: none;
}
}
- .foot a { color: var(--muted); transition: color .2s; }
.foot a:hover { color: var(--accent); }
.foot a:hover { color: var(--accent); }
- .foot a i { font-size: 0.9rem; }
+ .foot a i { font-size: 0.9em; }
+ @media (max-width: 540px) {
+ .foot__inner { flex-direction: column; align-items: flex-start; }
+ }
</style>
</style>
@@ -48,9 +48,9 @@ const metrics = [
@@ -48,9 +48,9 @@ const metrics = [
transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;
transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;
}
}
.impact__card:hover {
.impact__card:hover {
- transform: translateY(-3px);
- border-color: var(--accent);
- box-shadow: 0 12px 28px -16px color-mix(in srgb, var(--accent) 55%, transparent);
+ transform: translateY(-4px);
+ border-color: rgba(76,201,176,0.35);
+ box-shadow: 0 12px 40px -12px rgba(76,201,176,0.3), 0 0 0 1px rgba(76,201,176,0.08);
}
}
.impact__icon {
.impact__icon {
font-size: 1.05rem;
font-size: 1.05rem;
@@ -64,7 +64,7 @@ const metrics = [
@@ -64,7 +64,7 @@ const metrics = [
font-family: var(--font-display);
font-family: var(--font-display);
font-size: clamp(1.7rem, 2.6vw, 2.1rem);
font-size: clamp(1.7rem, 2.6vw, 2.1rem);
font-weight: 700;
font-weight: 700;
- color: var(--text);
+ color: var(--fg);
line-height: 1.05;
line-height: 1.05;
}
}
.impact__lbl {
.impact__lbl {
@@ -19,15 +19,20 @@ const tech = [
@@ -19,15 +19,20 @@ const tech = [
backdrop-filter: blur(8px);
backdrop-filter: blur(8px);
}
}
.marquee__track {
.marquee__track {
- display: flex; gap: 56px; padding: 18px 0;
+ display: flex; gap: 0; padding: 16px 0;
width: max-content;
width: max-content;
animation: scroll 80s linear infinite;
animation: scroll 80s linear infinite;
font-family: var(--font-mono);
font-family: var(--font-mono);
color: var(--muted);
color: var(--muted);
- font-size: .95rem;
+ font-size: .88rem;
letter-spacing: 0.04em;
letter-spacing: 0.04em;
}
}
- .marquee__track span { white-space: nowrap; }
+ .marquee__track span {
+ white-space: nowrap;
+ padding: 0 28px;
+ border-right: 1px solid var(--border);
+ }
+ .marquee__track span:last-child { border-right: none; }
@media (hover: hover) {
@media (hover: hover) {
.marquee:hover .marquee__track { animation-play-state: paused; }
.marquee:hover .marquee__track { animation-play-state: paused; }
}
}
@@ -54,14 +54,31 @@ const links = [
@@ -54,14 +54,31 @@ const links = [
border-bottom: 1px solid transparent;
border-bottom: 1px solid transparent;
backdrop-filter: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
-webkit-backdrop-filter: none;
- transition: background .35s ease, border-color .35s ease;
+ transition: background .4s ease, border-color .4s ease, box-shadow .4s ease;
will-change: background;
will-change: background;
}
}
+ /* Frosted ice-glass on scroll */
.nav--scrolled {
.nav--scrolled {
- backdrop-filter: blur(14px);
- -webkit-backdrop-filter: blur(14px);
- background: color-mix(in oklab, var(--bg) 78%, transparent);
- border-bottom: 1px solid var(--border);
+ backdrop-filter: blur(24px) saturate(180%);
+ -webkit-backdrop-filter: blur(24px) saturate(180%);
+ background: color-mix(in oklab, var(--bg) 68%, transparent);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.07);
+ box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.04), 0 8px 40px rgba(0, 0, 0, 0.38);
+ }
+ /* Brighter links when floating over hero (transparent state) */
+ .nav:not(.nav--scrolled) .nav__links a {
+ color: rgba(230, 237, 243, 0.88);
+ }
+ .nav:not(.nav--scrolled) .nav__links a:hover {
+ color: #fff;
+ }
+ .nav:not(.nav--scrolled) .nav__brand {
+ color: var(--fg);
+ }
+ .nav:not(.nav--scrolled) .nav__toggle,
+ .nav:not(.nav--scrolled) .nav__burger {
+ border-color: rgba(255, 255, 255, 0.15);
+ color: rgba(230, 237, 243, 0.8);
}
}
.nav__row {
.nav__row {
display: flex; align-items: center; gap: 16px;
display: flex; align-items: center; gap: 16px;
@@ -6,7 +6,7 @@ const featured = all.sort((a, b) => a.data.order - b.data.order);
@@ -6,7 +6,7 @@ const featured = all.sort((a, b) => a.data.order - b.data.order);
<section class="featured" id="work">
<section class="featured" id="work">
<div class="container">
<div class="container">
<div class="section-eyebrow"><i class="fa-solid fa-star"></i> Featured Work</div>
<div class="section-eyebrow"><i class="fa-solid fa-star"></i> Featured Work</div>
- <h2 class="section-title"><i class="fa-solid fa-star"></i> Things I've shipped</h2>
+ <h2 class="section-title">Things I've shipped</h2>
<p class="featured__lead">
<p class="featured__lead">
A rotating gallery of the products, tools, and agents I've built —
A rotating gallery of the products, tools, and agents I've built —
from Amazon ICQA analytics to the Hobo Network creator stack.
from Amazon ICQA analytics to the Hobo Network creator stack.
@@ -22,7 +22,7 @@ const filterIcon: Record<string, string> = {
@@ -22,7 +22,7 @@ const filterIcon: Record<string, string> = {
<section class="grid-sec" id="portfolio">
<section class="grid-sec" id="portfolio">
<div class="container">
<div class="container">
<div class="section-eyebrow"><i class="fa-solid fa-layer-group"></i> Portfolio</div>
<div class="section-eyebrow"><i class="fa-solid fa-layer-group"></i> Portfolio</div>
- <h2 class="section-title"><i class="fa-solid fa-layer-group"></i> All work</h2>
+ <h2 class="section-title">All work</h2>
<div class="filters" role="tablist">
<div class="filters" role="tablist">
{cats.map((c, i) => (
{cats.map((c, i) => (
<button class={`filter ${i === 0 ? "is-active" : ""}`} data-filter={c} role="tab">
<button class={`filter ${i === 0 ? "is-active" : ""}`} data-filter={c} role="tab">
@@ -5,7 +5,7 @@ const groups = (await getCollection("skills")).sort((a, b) => a.data.order - b.d
@@ -5,7 +5,7 @@ const groups = (await getCollection("skills")).sort((a, b) => a.data.order - b.d
<section class="skills" id="skills">
<section class="skills" id="skills">
<div class="container">
<div class="container">
<div class="section-eyebrow"><i class="fa-solid fa-code"></i> Stack</div>
<div class="section-eyebrow"><i class="fa-solid fa-code"></i> Stack</div>
- <h2 class="section-title"><i class="fa-solid fa-code"></i> Skills & tooling</h2>
+ <h2 class="section-title">Skills & stack</h2>
<div class="skills__grid">
<div class="skills__grid">
{groups.map((g) => (
{groups.map((g) => (
<article class="card skills__card" data-reveal>
<article class="card skills__card" data-reveal>
@@ -28,23 +28,32 @@ const groups = (await getCollection("skills")).sort((a, b) => a.data.order - b.d
@@ -28,23 +28,32 @@ const groups = (await getCollection("skills")).sort((a, b) => a.data.order - b.d
display: grid; gap: 18px;
display: grid; gap: 18px;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
}
+ .skills__card {
+ border-top: 2px solid rgba(76,201,176,0.25) !important;
+ }
.skills__card h3 {
.skills__card h3 {
font-family: var(--font-display);
font-family: var(--font-display);
- font-size: 1.05rem;
+ font-size: 1rem;
+ font-weight: 700;
color: var(--accent);
color: var(--accent);
margin-bottom: 1rem;
margin-bottom: 1rem;
+ letter-spacing: 0.01em;
}
}
.skills__card ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.skills__card ul { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 6px; }
.skills__item {
.skills__item {
- padding: 6px 12px;
+ padding: 5px 12px;
border-radius: 8px;
border-radius: 8px;
border: 1px solid var(--border);
border: 1px solid var(--border);
- font: 500 .85rem var(--font-body);
+ font: 500 .83rem var(--font-body);
color: var(--fg);
color: var(--fg);
background: rgba(255,255,255,0.02);
background: rgba(255,255,255,0.02);
- transition: transform .2s var(--ease), border-color .2s var(--ease);
+ transition: transform .2s var(--ease), border-color .2s var(--ease), background .2s var(--ease);
+ }
+ .skills__item:hover { transform: translateY(-2px); border-color: rgba(76,201,176,0.4); background: rgba(76,201,176,0.05); }
+ .skills__item--core {
+ border-color: rgba(76,201,176,.32);
+ color: var(--accent);
+ background: rgba(76,201,176,.06);
}
}
- .skills__item:hover { transform: translateY(-2px); border-color: var(--accent); }
- .skills__item--core { border-color: rgba(76,201,176,.35); color: var(--accent); }
- .skills__item--familiar { color: var(--dim); }
+ .skills__item--familiar { color: var(--dim); border-color: var(--border); }
</style>
</style>
@@ -18,7 +18,7 @@ import ContactBlock from "../components/ContactBlock.astro";
@@ -18,7 +18,7 @@ import ContactBlock from "../components/ContactBlock.astro";
<div class="container profile__row">
<div class="container profile__row">
<div data-reveal>
<div data-reveal>
<div class="section-eyebrow"><i class="fa-solid fa-user"></i> Profile</div>
<div class="section-eyebrow"><i class="fa-solid fa-user"></i> Profile</div>
- <h2 class="section-title"><i class="fa-solid fa-user"></i> A versatile builder</h2>
+ <h2 class="section-title">A versatile builder</h2>
<p class="profile-para">
<p class="profile-para">
<i class="fa-solid fa-microchip profile-para__icon"></i>
<i class="fa-solid fa-microchip profile-para__icon"></i>
<span>Data analyst and systems architect with 10+ years of shipping — from
<span>Data analyst and systems architect with 10+ years of shipping — from
@@ -114,7 +114,11 @@ section { padding: clamp(60px, 10vw, 120px) 0; position: relative; }
@@ -114,7 +114,11 @@ section { padding: clamp(60px, 10vw, 120px) 0; position: relative; }
box-shadow: var(--shadow-card);
box-shadow: var(--shadow-card);
transition: transform .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease);
transition: transform .3s var(--ease), border-color .3s var(--ease), box-shadow .3s var(--ease);
}
}
-.card:hover { border-color: var(--border-strong); transform: translateY(-3px); }
+.card:hover {
+ border-color: rgba(76, 201, 176, 0.3);
+ transform: translateY(-4px);
+ box-shadow: var(--shadow-card), 0 0 0 1px rgba(76,201,176,0.08), 0 12px 48px -8px rgba(76,201,176,0.18);
+}
.btn {
.btn {
display: inline-flex; align-items: center; gap: 10px;
display: inline-flex; align-items: center; gap: 10px;
@@ -128,19 +132,22 @@ section { padding: clamp(60px, 10vw, 120px) 0; position: relative; }
@@ -128,19 +132,22 @@ section { padding: clamp(60px, 10vw, 120px) 0; position: relative; }
transition: all .25s var(--ease);
transition: all .25s var(--ease);
text-decoration: none;
text-decoration: none;
}
}
-.btn:hover { background: var(--surface-2); transform: translateY(-2px); text-decoration: none; }
-.btn--primary { background: var(--accent); color: #06221c; border-color: transparent; }
-.btn--primary:hover { background: #5fdcc4; box-shadow: var(--shadow-glow); }
+.btn:hover { background: var(--surface-2); transform: translateY(-2px); text-decoration: none; border-color: var(--border-strong); }
+.btn--primary { background: var(--accent); color: #06221c; border-color: transparent; font-weight: 700; letter-spacing: 0.01em; }
+.btn--primary:hover { background: #5fdcc4; box-shadow: var(--shadow-glow), 0 6px 24px rgba(76,201,176,0.25); transform: translateY(-2px); }
.chip {
.chip {
display: inline-flex; align-items: center; gap: 5px;
display: inline-flex; align-items: center; gap: 5px;
- padding: 4px 10px;
+ padding: 4px 12px;
border-radius: 999px;
border-radius: 999px;
- font: 500 0.78rem var(--font-mono);
- background: rgba(76, 201, 176, 0.08);
- border: 1px solid rgba(76, 201, 176, 0.2);
+ font: 500 0.75rem var(--font-mono);
+ background: rgba(76, 201, 176, 0.07);
+ border: 1px solid rgba(76, 201, 176, 0.22);
color: var(--accent);
color: var(--accent);
+ letter-spacing: 0.03em;
+ transition: background .2s var(--ease), border-color .2s var(--ease);
}
}
+.chip:hover { background: rgba(76, 201, 176, 0.14); border-color: rgba(76, 201, 176, 0.38); }
.chip i { font-size: 0.75em; }
.chip i { font-size: 0.75em; }
.skip-link {
.skip-link {
@@ -153,6 +160,7 @@ section { padding: clamp(60px, 10vw, 120px) 0; position: relative; }
@@ -153,6 +160,7 @@ section { padding: clamp(60px, 10vw, 120px) 0; position: relative; }
/* Reveal — initial hidden state only; animation driven by JS (Web Animations API) */
/* Reveal — initial hidden state only; animation driven by JS (Web Animations API) */
[data-reveal] {
[data-reveal] {
opacity: 0;
opacity: 0;
- transform: translateY(24px);
+ transform: translateY(28px);
+ transition: opacity .55s var(--ease), transform .55s var(--ease);
}
}
[data-reveal].in { opacity: 1; transform: none; }
[data-reveal].in { opacity: 1; transform: none; }