header {
  position: sticky;
  top: 0;
  z-index: 100;
}

/* Sticky header overlaps whatever it's pinned above, so anchor targets need
   room to clear it — matches the header's rendered height plus a small gap. */
main section[id] {
  scroll-margin-top: 8.5rem;
}

header nav {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: 1280px;
  margin: 0 auto;
  padding: 2rem 1.5rem;
}

header nav .logo {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  font-weight: 700;
  font-size: 1.1rem;
  color: var(--color-body);
  text-decoration: none;
}

.logo-image {
  display: block;
  width: 36px;
  height: 36px;
}

header nav .logo:hover {
  color: var(--color-text-strong);
}

/*
  The nav is a translucent material floating over the content, not an opaque
  strip that eats a fixed band of the page — content scrolls underneath it and
  stays partly visible, which is what tells you the bar is a layer rather than
  a wall. Blur, saturation and background opacity come from the shared
  material tokens so `prefers-reduced-transparency` and `prefers-contrast` can
  turn the whole thing solid in one place (css/base/motion.css).
*/
header nav ul {
  list-style: none;
  margin: 0;
  padding: 0.6rem 0.8rem;
  display: flex;
  align-items: center;
  gap: 2rem;
  border: 0px solid var(--color-border);
  border-radius: var(--radius-pill);
  box-shadow: 0 8px 24px rgba(var(--color-black-rgb), 0.16);
  background: rgba(var(--color-surface-rgb), var(--material-alpha-strong));
  backdrop-filter: blur(var(--material-blur-strong)) saturate(var(--material-saturate));
  -webkit-backdrop-filter: blur(var(--material-blur-strong)) saturate(var(--material-saturate));
  /* A bright top edge reads as light catching the near edge of the material. */
  border-top: 1px solid rgba(var(--color-white-rgb), var(--material-edge-alpha));
  border-bottom: 1px solid rgba(var(--color-hairline-rgb), var(--material-border-alpha));
  transition: box-shadow var(--response) var(--ease-enter);
}

/*
  Scroll edge effect. Rather than a permanent hard divider, the material only
  deepens once there is actually content passing beneath it — separation
  appears exactly when it's needed and not before.
*/
header.is-scrolled nav ul {
  box-shadow: 0 12px 32px rgba(var(--color-black-rgb), 0.2);
}

header nav ul li a {
  display: inline-block;
  color: var(--color-body);
  text-decoration: none;
  font-size: 0.95rem;
  padding: 0.4rem 1rem;
  border-radius: var(--radius-pill);
  white-space: nowrap;
  transition: background-color var(--response-fast) var(--ease-enter),
    color var(--response-fast) var(--ease-enter),
    transform var(--response-instant) var(--ease-enter);
}

header nav ul li a:hover {
  background-color: var(--color-surface-hover);
  color: var(--color-text-strong);
}

/* Feedback lands on the press, not on release (see js/components/press.js). */
header nav ul li a.is-pressed {
  transform: scale(var(--press-scale));
  background-color: var(--color-surface-hover);
}

/*
  Wayfinding: "where am I" answered without the user asking. Set from the
  scroll spy in js/components/nav-scroll.js.
*/
header nav ul li a[aria-current="true"] {
  color: var(--color-brand);
  background-color: rgba(var(--color-brand-rgb), 0.1);
}

/*
  `[aria-current]` and `:hover` tie on specificity, so without this the
  current item would go completely inert under the pointer — the one item on
  the bar that gave no feedback. It keeps its identity colour and deepens
  instead.
*/
header nav ul li a[aria-current="true"]:hover,
header nav ul li a[aria-current="true"].is-pressed {
  color: var(--color-brand);
  background-color: rgba(var(--color-brand-rgb), 0.2);
}

header nav ul li a.nav-link-external {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
}

.external-link-icon {
  opacity: 0.6;
}

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 6px;
  width: 50px;
  height: 50px;
  padding: 0;
  border: none;
  border-radius: var(--radius-pill);
  background: rgba(var(--color-surface-rgb), var(--material-alpha-strong));
  backdrop-filter: blur(var(--material-blur)) saturate(var(--material-saturate));
  -webkit-backdrop-filter: blur(var(--material-blur)) saturate(var(--material-saturate));
  box-shadow: 0 8px 24px rgba(var(--color-black-rgb), 0.16);
  cursor: pointer;
  transition: transform var(--response-instant) var(--ease-enter);
}

.nav-toggle.is-pressed {
  transform: scale(var(--press-scale));
}

.nav-toggle-bar {
  width: 24px;
  height: 2.5px;
  background: var(--color-body);
  border-radius: var(--radius-pill);
  transition: transform var(--nav-icon-duration, 200ms) var(--ease-premium, cubic-bezier(0.22, 1, 0.36, 1)),
    opacity var(--nav-icon-duration, 200ms) var(--ease-premium, cubic-bezier(0.22, 1, 0.36, 1));
  transition-delay: var(--nav-icon-close-delay, 0ms);
}

.nav-toggle[aria-expanded="true"] .nav-toggle-bar {
  transition-delay: 0ms;
}

.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) {
  transform: translateY(8.5px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) {
  opacity: 0;
}

.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) {
  transform: translateY(-8.5px) rotate(-45deg);
}

@media (max-width: 960px) {
  header nav {
    padding: 1.5rem 1.25rem;
    --nav-icon-duration: 200ms;
    --nav-icon-close-delay: 200ms;
    --nav-container-open-duration: 280ms;
    --nav-container-close-duration: 220ms;
    --nav-container-close-delay: 70ms;
    --nav-item-open-duration: 180ms;
    --nav-item-close-duration: 160ms;
    --nav-item-open-stagger: 50ms;
    --nav-item-close-stagger: 40ms;
    --nav-item-open-base-delay: 90ms;
  }

  .nav-toggle {
    display: flex;
  }

  header nav ul {
    position: absolute;
    top: 100%;
    left: 1.25rem;
    right: 1.25rem;
    margin-top: 0.75rem;
    flex-direction: column;
    align-items: stretch;
    gap: 0.3rem;
    padding: 0.75rem;
    border-radius: var(--radius-xl);
    transform-origin: top center;
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transform: translateY(-14px) scale(0.98);
    transition: opacity var(--nav-container-close-duration) var(--ease-premium) var(--nav-container-close-delay),
      transform var(--nav-container-close-duration) var(--ease-premium) var(--nav-container-close-delay),
      visibility 0s linear calc(var(--nav-container-close-delay) + var(--nav-container-close-duration));
  }

  header nav ul.is-open {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translateY(0) scale(1);
    transition: opacity var(--nav-container-open-duration) var(--ease-premium),
      transform var(--nav-container-open-duration) var(--ease-premium),
      visibility 0s linear 0s;
    /* The open sheet owns vertical drags — they're the dismiss gesture, so
       the browser must not consume them as page scroll first. */
    touch-action: none;
  }

  /*
    While the panel is under a finger — or coasting on the velocity that
    finger let go of — nothing sits between the gesture and the pixels. JS
    writes the transform frame by frame; a CSS transition on top of that would
    interpolate toward each frame's value and lag the whole way.
  */
  header nav ul.is-dragging,
  header nav ul.is-animating {
    transition: none;
  }

  header nav ul li {
    width: 100%;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity var(--nav-item-close-duration) var(--ease-premium),
      transform var(--nav-item-close-duration) var(--ease-premium);
    transition-delay: calc(var(--ri, 0) * var(--nav-item-close-stagger));
  }

  header nav ul.is-open li {
    opacity: 1;
    transform: translateY(0);
    transition: opacity var(--nav-item-open-duration) var(--ease-premium),
      transform var(--nav-item-open-duration) var(--ease-premium);
    transition-delay: calc(var(--nav-item-open-base-delay) + (var(--i, 0) * var(--nav-item-open-stagger)));
  }

  header nav ul li a {
    display: block;
    text-align: center;
    border-radius: var(--radius-md);
  }

  header nav ul li a.nav-link-external {
    display: flex;
    justify-content: center;
  }

  header nav ul li:last-child {
    display: flex;
    justify-content: center;
    padding-top: 0.5rem;
  }
}

@media (max-width: 960px) and (prefers-reduced-motion: reduce) {
  header nav ul,
  header nav ul.is-open,
  header nav ul li,
  header nav ul.is-open li {
    transform: none;
    transition-property: opacity, visibility;
    transition-duration: 150ms;
    transition-delay: 0s;
  }

  .nav-toggle-bar,
  .nav-toggle[aria-expanded="true"] .nav-toggle-bar {
    transition-duration: 120ms;
    transition-delay: 0s;
  }
}

@media (max-width: 480px) {
  header nav .logo-name {
    display: none;
  }

  header nav ul {
    left: 1rem;
    right: 1rem;
  }
}
