147 lines
3.5 KiB
Plaintext
147 lines
3.5 KiB
Plaintext
---
|
|
import ThemeToggle from "./ThemeToggle.astro";
|
|
import { site } from "../data/site";
|
|
|
|
// Plain links. Hover shows the underline; there is no scroll-spy - tracking the
|
|
// active section as you scrolled read as clunky, so the underline is hover-only.
|
|
const links = [
|
|
{ label: "About", href: "/#about" },
|
|
{ label: "Skills", href: "/#skills" },
|
|
{ label: "Projects", href: "/projects/" },
|
|
{ label: "Blog", href: "/blog/" },
|
|
{ label: "Contact", href: "/#contact" },
|
|
{ label: "Learn", href: "https://learn.bztmon.com", external: true },
|
|
];
|
|
---
|
|
|
|
<header class="nav">
|
|
<div class="container nav__inner">
|
|
<a class="nav__brand mono" href="/" aria-label={`${site.name} - home`}>
|
|
<span class="nav__prompt">~/</span><span>{site.handle}</span><span class="nav__caret" aria-hidden="true">▮</span>
|
|
</a>
|
|
|
|
<nav class="nav__links" aria-label="Primary">
|
|
{links.map((l) => (
|
|
<a
|
|
href={l.href}
|
|
target={l.external ? "_blank" : undefined}
|
|
rel={l.external ? "noopener noreferrer" : undefined}
|
|
>
|
|
{l.label}
|
|
</a>
|
|
))}
|
|
</nav>
|
|
|
|
<div class="nav__actions">
|
|
<ThemeToggle />
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<style>
|
|
.nav {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 50;
|
|
background: color-mix(in srgb, var(--bg) 82%, transparent);
|
|
backdrop-filter: blur(10px);
|
|
border-bottom: 1px solid var(--border);
|
|
}
|
|
.nav__inner {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: var(--space-4);
|
|
height: 4rem;
|
|
}
|
|
.nav__brand {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.1rem;
|
|
font-size: var(--step-0);
|
|
font-weight: 600;
|
|
color: var(--text);
|
|
}
|
|
.nav__brand:hover {
|
|
text-decoration: none;
|
|
color: var(--accent);
|
|
}
|
|
.nav__prompt {
|
|
color: var(--text-faint);
|
|
}
|
|
.nav__caret {
|
|
color: var(--accent);
|
|
animation: blink 1.1s steps(1) infinite;
|
|
margin-left: 0.1rem;
|
|
}
|
|
@keyframes blink {
|
|
50% {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.nav__caret {
|
|
animation: none;
|
|
}
|
|
}
|
|
.nav__links {
|
|
display: none;
|
|
gap: var(--space-5);
|
|
font-family: var(--font-mono);
|
|
font-size: var(--step--1);
|
|
}
|
|
.nav__links a {
|
|
position: relative;
|
|
color: var(--text-dim);
|
|
}
|
|
.nav__links a:hover {
|
|
color: var(--text);
|
|
text-decoration: none;
|
|
}
|
|
/* Hover = glow, not an underline (owner call 2026-08-18: the bar read as clunky).
|
|
Keyboard focus gets the same treatment so the affordance is not mouse-only. */
|
|
.nav__links a:hover,
|
|
.nav__links a:focus-visible {
|
|
color: var(--accent);
|
|
text-shadow: 0 0 10px var(--accent-glow), 0 0 22px var(--accent-glow);
|
|
}
|
|
.nav__actions {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: var(--space-3);
|
|
}
|
|
@media (min-width: 720px) {
|
|
.nav__links {
|
|
display: flex;
|
|
}
|
|
}
|
|
/* phones: the tabs live on a compact second row (zero-JS, no hamburger) -
|
|
the bar wraps: brand + toggle on row 1, links across row 2 */
|
|
@media (max-width: 719px) {
|
|
.nav__inner {
|
|
height: auto;
|
|
flex-wrap: wrap;
|
|
row-gap: 0;
|
|
padding-block: 0.55rem 0.6rem;
|
|
}
|
|
.nav__links {
|
|
display: flex;
|
|
order: 3;
|
|
width: 100%;
|
|
gap: var(--space-4);
|
|
overflow-x: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
scrollbar-width: none;
|
|
font-size: 0.78rem;
|
|
padding-top: 0.5rem;
|
|
}
|
|
.nav__links::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
.nav__links a {
|
|
flex-shrink: 0;
|
|
padding-bottom: 0.15rem;
|
|
}
|
|
}
|
|
</style>
|