*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --bg: #0a0a0a;
  --text: #f0f0f0;
  --text-muted: #999;
  --accent: #fff;
  /* Scrim strengths for the landing photo. The nav and the gallery link are
     white and sit directly on the image, so without this they disappear
     against any light part of the frame. */
  --scrim-edge: rgba(0, 0, 0, 0.62);
  --scrim-mid: rgba(0, 0, 0, 0.15);
  --scrim-center: rgba(0, 0, 0, 0.55);
  --header-bg: rgba(10, 10, 10, 0.95);
  --border-light: rgba(255, 255, 255, 0.08);
  --border-muted: rgba(255, 255, 255, 0.15);
  --font-sans: Inter, 'halyard-display', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-heading: Inter, 'halyard-display', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --transition: 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

.gallery-page {
  --bg: #0a0a0a;
  --text: #f0f0f0;
  --text-muted: #999;
  --accent: #fff;
  --header-bg: rgba(10, 10, 10, 0.95);
  --border-light: rgba(255, 255, 255, 0.08);
  --border-muted: rgba(255, 255, 255, 0.15);
}

@media (prefers-color-scheme: light) {
  .gallery-page {
    --bg: #fff;
    --text: #111;
    --text-muted: #888;
    --accent: #000;
    --header-bg: rgba(255, 255, 255, 0.95);
    --border-light: rgba(0, 0, 0, 0.08);
    --border-muted: rgba(0, 0, 0, 0.15);
  }
}

html {
  font-size: 16px;
  scroll-behavior: smooth;
}

body {
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* 100dvh tracks the visible viewport. On iOS 100vh is the *large* viewport
     (as if the toolbars were hidden), which would otherwise force the body
     taller than a 100dvh hero and leave blank space to scroll into. */
  min-height: 100vh;
  min-height: 100dvh;
}

a {
  color: var(--text);
  text-decoration: none;
  transition: opacity var(--transition);
}

a:hover {
  opacity: 0.7;
}

img {
  max-width: 100%;
  height: auto;
  display: block;
}

/* Header */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  padding: 2.5vw 4vw;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background: transparent;
  transition: background var(--transition);
}

.site-header.scrolled {
  background: var(--header-bg);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}

.site-logo {
  font-family: var(--font-heading);
  font-size: 1.2rem;
  font-weight: 300;
  letter-spacing: 0.05em;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: 2rem;
}

.site-nav a {
  font-family: var(--font-heading);
  font-size: 1rem;
  letter-spacing: 0.02em;
  text-transform: lowercase;
  font-weight: 300;
}

.site-nav a.active {
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 1px;
}

.social-links {
  display: flex;
  gap: 1rem;
  margin-left: 1rem;
  padding-left: 1rem;
  border-left: 1px solid var(--border-muted);
}

.social-links a {
  font-size: 0.8rem;
  opacity: 0.6;
}

.social-links a:hover {
  opacity: 1;
}

.menu-toggle {
  display: none;
  background: none;
  border: none;
  color: var(--text);
  font-size: 1.5rem;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  position: relative;
  z-index: 220;
}

/* Portfolio Index (Homepage) */

/* The homepage is a single full-viewport hero, so it should never scroll.
   .portfolio-index already clips its own overflow; this pins the document to
   the visible viewport so there is nothing to scroll into. */
.home-page {
  height: 100dvh;
  overflow: hidden;
}

.portfolio-index {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.portfolio-index .bg-image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity 0.6s ease;
  opacity: 0;
}

.portfolio-index .bg-image.active {
  opacity: 1;
}

.portfolio-index .bg-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1;
  /* Darkest at the top and bottom edges (behind the header) and in a soft
     pool at the centre (behind the gallery link), while leaving the middle
     bands of the photo close to untouched. */
  background:
    radial-gradient(ellipse 60% 45% at 50% 50%,
      var(--scrim-center) 0%, rgba(0, 0, 0, 0) 100%),
    linear-gradient(to bottom,
      var(--scrim-edge) 0%,
      var(--scrim-mid) 30%,
      var(--scrim-mid) 70%,
      var(--scrim-edge) 100%);
}

.portfolio-index .gallery-list {
  position: relative;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100%;
  gap: 0.5rem;
}

.home-page .site-header,
.portfolio-index .gallery-list {
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
}

.gallery-item {
  cursor: pointer;
  text-align: center;
}

.gallery-item a {
  font-family: var(--font-heading);
  font-size: clamp(1.5rem, 2.5vw + 1rem, 2.5rem);
  font-weight: 300;
  letter-spacing: 0.02em;
  text-transform: lowercase;
  color: var(--text);
  transition: all var(--transition);
  display: inline-block;
}

.gallery-item a:hover {
  opacity: 1;
  transform: scale(1.05);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6), 0 0 40px rgba(255, 255, 255, 0.15);
}

.gallery-item a::after {
  content: '';
  display: block;
  width: 0;
  height: 1px;
  background: var(--text);
  transition: width 0.4s ease;
  margin: 0 auto;
}

.gallery-item a:hover::after {
  width: 100%;
}

.gallery-empty {
  font-family: var(--font-heading);
  font-weight: 300;
  text-transform: lowercase;
  text-align: center;
  color: var(--text-muted);
  padding: 6rem 0;
}

/* Page Content */
.page-content {
  min-height: 100vh;
  padding: 120px 4vw 60px;
  max-width: 1400px;
  margin: 0 auto;
}

.page-content.narrow {
  max-width: 800px;
}

.page-title {
  font-family: var(--font-heading);
  font-size: 2.5rem;
  font-weight: 300;
  letter-spacing: 0.02em;
  text-transform: lowercase;
  margin-bottom: 2rem;
}

.page-subtitle {
  font-size: 0.9rem;
  color: var(--text-muted);
  margin-bottom: 3rem;
  letter-spacing: 0.02em;
  font-weight: 300;
}

/* About Page */
.about-page .site-header {
  color: #111;
}

.about-page .site-header a {
  color: #111;
}

.about-page .site-header .menu-toggle {
  color: #111;
}

.about-page .site-header.scrolled {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
}

.about-hero {
  position: relative;
  width: 100%;
  min-height: 100vh;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: #fff;
}

.about-hero-bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  opacity: 0.6;
}

.about-hero-content {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 3rem;
  max-width: 1100px;
  margin: 0 auto;
  padding: 120px 4vw 60px;
}

.about-portrait {
  flex-shrink: 0;
  width: 280px;
  height: 280px;
  border-radius: 50%;
  overflow: hidden;
  border: 3px solid rgba(255, 255, 255, 0.3);
}

.about-portrait img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.about-text {
  color: #111;
  text-shadow: none;
}

.about-text h1 {
  font-family: var(--font-heading);
  font-size: 1.6rem;
  font-weight: 400;
  margin-bottom: 1.2rem;
  line-height: 1.4;
}

.about-text p {
  font-size: 1rem;
  line-height: 1.7;
  margin-bottom: 1rem;
  color: #333;
}

.about-contact-btn {
  display: inline-block;
  margin-top: 0.5rem;
  padding: 0.6rem 1.6rem;
  border: 1px solid #111;
  border-radius: 4px;
  color: #111;
  text-decoration: none;
  font-size: 0.95rem;
  transition: background 0.2s, color 0.2s;
}

.about-contact-btn:hover {
  background: #111;
  color: #fff;
}

.about-redbubble {
  background: #fff;
  color: #222;
  padding: 5rem 4vw;
}

.about-redbubble-content {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  align-items: flex-start;
  gap: 3rem;
}

.about-redbubble-text {
  flex: 1;
}

.about-redbubble-text h2 {
  font-family: var(--font-heading);
  font-size: 1.7rem;
  font-weight: 300;
  letter-spacing: 0.02em;
  margin-bottom: 1.2rem;
}

.about-redbubble-text p {
  font-size: 1rem;
  line-height: 1.7;
  margin-bottom: 1rem;
  color: #555;
}

.about-redbubble-text a {
  color: #222;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

.about-redbubble-text a:hover {
  opacity: 0.7;
}

.about-redbubble-screenshot {
  flex-shrink: 0;
  width: 420px;
  border-radius: 6px;
  overflow: hidden;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

.about-redbubble-screenshot img {
  width: 100%;
  height: auto;
  display: block;
}

/* Gallery Grid */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 2rem;
}

.gallery-grid img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  cursor: pointer;
  transition: transform 0.4s ease, opacity 0.4s ease;
}

.gallery-grid img:hover {
  transform: scale(1.03);
  opacity: 0.9;
}

/* Sits outside .page-content, so it needs that element's width and side
   padding of its own to line up with the grid above it. */
.gallery-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  max-width: 1400px;
  margin: 3rem auto 0;
  padding: 2rem 4vw 2rem;
  border-top: 1px solid var(--border-light);
}

.gallery-nav a {
  font-family: var(--font-heading);
  font-size: 0.9rem;
  letter-spacing: 0.02em;
  text-transform: lowercase;
  font-weight: 300;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.gallery-nav .back-link {
  color: var(--text-muted);
}

/* Lightbox */
.lightbox {
  display: none;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.95);
  z-index: 200;
  justify-content: center;
  align-items: center;
  cursor: pointer;
}

.lightbox.active {
  display: flex;
}

.lightbox img {
  max-width: 90%;
  max-height: 90%;
  object-fit: contain;
}

.lightbox .close {
  position: absolute;
  top: 20px;
  right: 30px;
  font-size: 2rem;
  color: var(--text);
  cursor: pointer;
  background: none;
  border: none;
  opacity: 0.6;
  transition: opacity var(--transition);
}

.lightbox .close:hover {
  opacity: 1;
}

.lightbox .prev,
.lightbox .next {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  font-size: 4rem;
  color: var(--text);
  cursor: pointer;
  background: none;
  border: none;
  opacity: 0.4;
  transition: opacity var(--transition);
  z-index: 210;
  padding: 1rem;
  line-height: 1;
}

.lightbox .prev:hover,
.lightbox .next:hover {
  opacity: 1;
}

.lightbox .prev {
  left: 10px;
}

.lightbox .next {
  right: 10px;
}

.lightbox .prev,
.lightbox .next {
  pointer-events: auto;
}

@media (max-width: 768px) {
  .lightbox .prev,
  .lightbox .next {
    font-size: 2.5rem;
  }
  .lightbox .prev {
    left: 5px;
  }
  .lightbox .next {
    right: 5px;
  }
}

/* 404 — full-viewport hero over a random gallery photo */
.error-page {
  height: 100dvh;
  overflow: hidden;
}

.error-hero {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

.error-bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  opacity: 0;
  transition: opacity 0.6s ease;
}

.error-bg.loaded {
  opacity: 1;
}

.error-overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.45);
  z-index: 1;
}

.error-content {
  position: relative;
  z-index: 2;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  padding: 0 6vw;
}

.error-code {
  font-family: var(--font-heading);
  font-size: clamp(4rem, 17vw, 8rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: 0.04em;
  color: #fff;
}

.error-title {
  font-family: var(--font-heading);
  font-size: clamp(1.1rem, 4vw, 1.5rem);
  font-weight: 300;
  letter-spacing: 0.02em;
  text-transform: lowercase;
  color: #fff;
  margin-top: 0.75rem;
  margin-bottom: 2rem;
}

.error-home {
  font-family: var(--font-heading);
  font-size: clamp(0.95rem, 2.5vw, 1.05rem);
  font-weight: 300;
  letter-spacing: 0.02em;
  text-transform: lowercase;
  color: #fff;
  display: inline-block;
}

.error-home:hover {
  opacity: 1;
}

.error-home::after {
  content: '';
  display: block;
  width: 0;
  height: 1px;
  background: #fff;
  transition: width 0.4s ease;
  margin: 0 auto;
}

.error-home:hover::after {
  width: 100%;
}

/* Back to top */
.back-home {
  font-family: var(--font-heading);
  display: inline-block;
  margin-top: 2rem;
  font-size: 0.9rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  font-weight: 300;
  color: var(--text-muted);
}

/* Footer */
.site-footer {
  text-align: center;
  padding: 2rem 4vw;
  font-size: 0.8rem;
  color: var(--text-muted);
  border-top: 1px solid var(--border-light);
}

/* Mobile */
@media (max-width: 768px) {
  .site-header {
    padding: 4vw 6vw;
  }

  .site-nav {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: #fff;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: 2rem;
    z-index: 200;
  }

  .site-nav.open {
    display: flex;
  }

  .site-nav.open ~ .site-logo,
  .site-header.nav-open .site-logo {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 210;
    color: #111;
    padding: 4vw 6vw;
  }

  .site-header.nav-open .menu-toggle {
    position: fixed;
    top: 0;
    right: 0;
    z-index: 210;
    color: #111;
    padding: 4vw 6vw;
  }

  /* The open nav, the logo and the toggle are all position: fixed. A
     backdrop-filter on the header makes the header their containing block
     instead of the viewport, which collapses the full-screen nav down to the
     header box. Drop the scrolled treatment while the menu is open so the
     overlay looks the same whether or not the page has been scrolled. */
  .site-header.nav-open,
  .about-page .site-header.nav-open {
    background: transparent;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }

  .site-nav a {
    font-family: var(--font-heading);
    font-size: 1.8rem;
    color: #111;
    text-transform: lowercase;
    font-weight: 300;
    letter-spacing: 0.02em;
  }

  .site-nav .social-links {
    position: absolute;
    bottom: 3rem;
    margin-left: 0;
    padding-left: 0;
    border-left: none;
    margin-top: 0;
    display: flex;
    gap: 1.5rem;
  }

  .site-nav .social-links a {
    font-size: 0.85rem;
    color: #999;
  }

  .menu-toggle {
    display: block;
    padding: 12px;
    margin: -12px;
  }

  .page-content {
    padding: 100px 6vw 40px;
  }

  .page-title {
    font-size: 1.8rem;
  }

  .gallery-item a {
    font-size: clamp(1.5rem, 8vw, 2.5rem);
  }

  .gallery-grid {
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 1.2rem;
  }

  /* .gallery-nav is the last element on a gallery page, so without the extra
     bottom padding it ends up flush against the bottom of the document and
     the iOS home indicator sits on top of the prev/next links. */
  .gallery-nav {
    padding: 2rem 6vw calc(2.5rem + env(safe-area-inset-bottom, 0px));
  }

  .portfolio-index .gallery-list {
    gap: 0.25rem;
  }

  .about-hero-content {
    flex-direction: column;
    text-align: center;
    padding: 100px 6vw 40px;
  }

  .about-portrait {
    width: 200px;
    height: 200px;
  }

  .about-text h1 {
    font-size: 1.3rem;
  }

  .about-redbubble-content {
    flex-direction: column;
  }

  .about-redbubble-screenshot {
    width: 100%;
  }
}
