html {
  scroll-behavior: smooth;
}
.site-nav {
  /* fixed, not sticky: some browsers paint a sticky element's translucent
     background as solid on the very first frame and only correct it
     after a scroll-triggered repaint (independent of backdrop-filter —
     it happened with and without it). fixed is promoted to its own
     compositing layer from the start, avoiding that class of bug. It
     no longer reserves space in normal flow, so the content right
     after it (.hero, and <main> on the demo page) carries matching
     top padding to clear it. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  padding: 1rem 1.5rem;
  /* Plain alpha background, no backdrop-filter. backdrop-filter's blur
     depends on GPU compositing that isn't reliable across every
     browser/driver combo — when it fails, some renderers fall back to
     a blank/black backdrop source, so even this rgba's own transparency
     ends up blending against black instead of the photo (looks fully
     opaque, not just unblurred). Plain background-color transparency is
     ordinary alpha compositing with no such failure mode. */
  background: rgba(20, 21, 26, 0.45);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  transition: background-color 0.25s ease;
}
.site-nav.scrolled {
  background: rgba(20, 21, 26, 0.28);
}
.nav-inner {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.nav-brand {
  color: var(--text);
  text-decoration: none;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.nav-links {
  display: flex;
  gap: 1.5rem;
}
.nav-links a {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.nav-links a:hover {
  color: var(--accent);
}
.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 22px;
  height: 22px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
}
.nav-toggle span {
  display: block;
  width: 100%;
  height: 2px;
  background: var(--muted);
  border-radius: 1px;
  transition: transform 0.2s ease, opacity 0.2s ease, background-color 0.2s ease;
}
/* (hover: hover) excludes touchscreens — without it, tapping the
   button (which has no mouse to later move away and clear :hover)
   leaves it stuck gold until the visitor taps elsewhere. */
@media (hover: hover) {
  .nav-toggle:hover span {
    background: var(--accent);
  }
}
.nav-toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.nav-toggle[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
}
.nav-toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}
/* Below this, brand + 4 links + growing letter-spacing crowd into each
   other (confirmed by testing an emulated phone viewport) — collapse
   the links into a toggled dropdown instead. .nav-links goes absolute
   (relative to .site-nav, the nearest positioned ancestor) so it drops
   out of the flex row entirely, leaving .nav-toggle as the row's last
   flex item and space-between free to push it to the right edge. */
@media (max-width: 700px) {
  .nav-toggle {
    display: flex;
  }
  .nav-links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    gap: 0;
    background: rgba(20, 21, 26, 0.97);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.25s ease;
  }
  .nav-links.open {
    max-height: 300px;
  }
  .nav-links a {
    padding: 1rem 1.5rem;
    border-top: 1px solid rgba(255, 255, 255, 0.06);
  }
}
.site-footer {
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
  color: var(--muted);
  font-size: 0.95rem;
  line-height: 1.6;
  padding: 3rem 1.25rem 2.5rem;
}
.site-footer .build-time {
  display: block;
  font-size: 0.85em;
  margin-top: 0.35rem;
}
:root {
  color-scheme: dark;
  --bg: #14151a;
  --text: #e8e8ec;
  --muted: #a4a9b3;
  --accent: #d8b36a;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  text-align: center;
}
.hero {
  min-height: 70vh;
  scroll-margin-top: 4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Top padding clears the fixed .site-nav, which no longer reserves
     space in normal flow. */
  padding: calc(2rem + 4rem) 1.5rem 2rem;
  /* Dark gradient over the photo so text stays legible over any part of
     it (the bright window, lighter wood tones), darkest toward the
     bottom where the text sits. background-position is biased toward
     the top so the subject's face stays in frame even when this section
     gets cropped taller/narrower than the source photo on mobile. */
  background-image: linear-gradient(to bottom, rgba(20, 21, 26, 0.35), rgba(20, 21, 26, 0.88)), url('../img/john_west_live_site_head.webp');
  background-size: cover;
  background-position: center 20%;
}
main {
  max-width: 640px;
}
h1 {
  font-size: clamp(4rem, 13.8vw, 7.5rem);
  font-weight: 700;
  letter-spacing: 0.01em;
  margin: 0 0 0.5rem;
}
.tagline {
  color: var(--accent);
  font-size: clamp(1.3rem, 2.5vw, 1.6rem);
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 0 0 3rem;
}
.status {
  color: var(--muted);
  font-size: 1.2rem;
  margin: 0 0 1.5rem;
}
.link {
  color: var(--accent);
  text-decoration: none;
  font-weight: 500;
  font-size: 1.2rem;
  border: 1px solid var(--accent);
  border-radius: 8px;
  padding: 0.75rem 1.5rem;
  display: inline-block;
}
button.link {
  /* Buttons default to the UA font-family and their own background —
     <a> doesn't need either reset. font-family only (not the `font`
     shorthand): that shorthand also resets size/weight, which would
     wipe out the ones .link sets above. */
  font-family: inherit;
  background: none;
  cursor: pointer;
}
.link:hover {
  background: var(--accent);
  color: var(--bg);
}
.about {
  scroll-margin-top: 4rem;
  padding: 7rem 1.5rem;
}
.about-inner {
  max-width: 640px;
  margin: 0 auto;
  text-align: left;
}
.about h2 {
  color: var(--accent);
  font-size: clamp(1.8rem, 4vw, 2.3rem);
  font-weight: 600;
  text-align: center;
  margin: 0 0 2rem;
}
.about p {
  line-height: 1.75;
  font-size: 1.05rem;
  margin: 0 0 1.25rem;
}
.about strong {
  color: var(--text);
  font-weight: 700;
}
.about p.about-closing {
  color: var(--accent);
  font-weight: 600;
  font-size: 1.2rem;
  text-align: center;
  letter-spacing: 0.01em;
  margin-top: 2.5rem;
}
.gigs {
  scroll-margin-top: 4rem;
  padding: 7rem 1.5rem;
  background: #17181e;
}
.gigs-inner {
  max-width: 640px;
  margin: 0 auto;
}
.gigs h2 {
  color: var(--accent);
  font-size: clamp(1.8rem, 4vw, 2.3rem);
  font-weight: 600;
  margin: 0 0 2rem;
}
.gigs-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}
.gig {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  text-align: left;
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 10px;
  padding: 1rem 1.25rem;
}
.gig-date {
  flex: 0 0 auto;
  width: 5rem;
  text-align: center;
  color: var(--accent);
}
.gig-month {
  display: block;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.gig-day {
  display: block;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.1;
}
.gig-time {
  display: block;
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 600;
  margin-top: 0.2rem;
}
.gig-name {
  font-size: 1.1rem;
  font-weight: 600;
}
.gig-subtitle {
  color: var(--accent);
  font-size: 0.9rem;
  font-weight: 500;
  margin-top: 0.1rem;
}
.gig-venue {
  color: var(--muted);
  font-size: 0.95rem;
  margin-top: 0.15rem;
}
.gig-address {
  font-size: 0.85rem;
  margin-top: 0.15rem;
}
.gig-address a {
  color: var(--muted);
  text-decoration: underline;
  text-decoration-color: rgba(164, 169, 179, 0.4);
}
.gig-address a:hover {
  color: var(--accent);
  text-decoration-color: var(--accent);
}
.gig-note {
  color: var(--muted);
  font-size: 0.85rem;
  font-style: italic;
  margin-top: 0.15rem;
}
.contact {
  scroll-margin-top: 4rem;
  padding: 7rem 1.5rem;
}
.contact-inner {
  max-width: 480px;
  margin: 0 auto;
}
.contact h2 {
  color: var(--accent);
  font-size: clamp(1.8rem, 4vw, 2.3rem);
  font-weight: 600;
  margin: 0 0 1rem;
}
.contact > .contact-inner > p {
  color: var(--muted);
  line-height: 1.6;
  margin: 0 0 2rem;
}
.contact-form {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  text-align: left;
}
.contact-form label {
  color: var(--muted);
  font-size: 0.9rem;
  font-weight: 500;
  margin-top: 0.75rem;
}
.contact-form label:first-of-type {
  margin-top: 0;
}
.contact-form input,
.contact-form textarea {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 8px;
  color: var(--text);
  font: inherit;
  padding: 0.65rem 0.85rem;
  resize: vertical;
}
.contact-form input:focus,
.contact-form textarea:focus {
  outline: none;
  border-color: var(--accent);
}
.contact-form button {
  align-self: center;
  margin-top: 1.5rem;
}
.contact-form button:disabled {
  opacity: 0.6;
  cursor: default;
}
.contact-status {
  min-height: 1.3em;
  margin: 0.75rem 0 0;
  font-size: 0.95rem;
}
.contact-status.success {
  color: var(--accent);
}
.contact-status.error {
  color: #e08585;
}
