/* ────────────────────────────────────────────────────────────────────────
   DESIGN TOKENS
   Change these to re-theme the whole site. Everything below references
   these variables — there are no hard-coded colors elsewhere in this file.
   ──────────────────────────────────────────────────────────────────────── */
:root {
  --bg:            #121210;   /* darkroom black */
  --bg-elevated:   #1c1b18;   /* card / panel surface */
  --bg-overlay:    rgba(18, 18, 16, 0.92);

  --paper:         #edeae2;   /* matte print paper — primary text */
  --paper-dim:     #cfc9bd;
  --ink-muted:     #8f897c;   /* secondary text */
  --hairline:      #38352e;   /* borders / rules */

  --accent:        #c4622d;   /* safelight amber */
  --accent-dim:    #8a4620;
  --accent-tint:   rgba(196, 98, 45, 0.14);

  --scrim-strong:  rgba(18, 18, 16, 0.92);
  --scrim-soft:    rgba(18, 18, 16, 0.55);
  --lightbox-bg:   rgba(10, 10, 9, 0.96);
  /* Booking modal sits over the page rather than replacing it, so its
     backdrop is lighter than the lightbox's. */
  --modal-scrim:   rgba(10, 10, 9, 0.66);

  /* Fixed regardless of theme — these sit directly on top of photos, not
     page chrome, so they stay readable whether the site is light or dark. */
  --overlay-ink:          #edeae2;
  --overlay-scrim-soft:   rgba(18, 18, 16, 0.55);

  --font-display: "Big Shoulders Display", "Arial Narrow", sans-serif;
  --font-body:    "Source Serif 4", Georgia, serif;
  --font-mono:    "IBM Plex Mono", "Courier New", monospace;

  --container: 1440px;
  --gutter: clamp(20px, 4vw, 64px);

  --ease: cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* ────────────────────────────────────────────────────────────────────────
   LIGHT MODE — same tokens, print-paper palette instead of darkroom.
   Toggled by setting data-theme="light" on <html> via app.js.
   ──────────────────────────────────────────────────────────────────────── */
:root[data-theme="light"] {
  --bg:            #f3efe4;   /* print paper */
  --bg-elevated:   #ffffff;
  --bg-overlay:    rgba(243, 239, 228, 0.92);

  --paper:         #18160f;
  --paper-dim:     #46423a;
  --ink-muted:     #736c5f;
  --hairline:      #ddd5c2;

  --accent:        #a4501f;   /* deeper amber for contrast on paper */
  --accent-dim:    #7a3a18;
  --accent-tint:   rgba(164, 80, 31, 0.12);

  --scrim-strong:  rgba(243, 239, 228, 0.92);
  --scrim-soft:    rgba(243, 239, 228, 0.65);
  --lightbox-bg:   rgba(238, 233, 220, 0.97);
  --modal-scrim:   rgba(28, 26, 20, 0.42);
}

* { color-scheme: light dark; }
:root[data-theme="light"] { color-scheme: light; }
:root:not([data-theme="light"]) { color-scheme: dark; }

/* ────────────────────────────────────────────────────────────────────────
   RESET & BASE
   ──────────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  transition: background 0.35s var(--ease), color 0.35s var(--ease);
}

img { max-width: 100%; display: block; }
a { color: inherit; }

.wrap {
  max-width: var(--container);
  margin: 0 auto;
  padding-left: var(--gutter);
  padding-right: var(--gutter);
}

.kicker {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* ────────────────────────────────────────────────────────────────────────
   SPROCKET STRIP — decorative filmstrip edge, used as a section divider
   ──────────────────────────────────────────────────────────────────────── */
.sprocket-strip {
  height: 14px;
  background-image: repeating-linear-gradient(
    to right,
    var(--bg-elevated) 0px, var(--bg-elevated) 6px,
    transparent 6px, transparent 16px
  );
  background-color: var(--bg);
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
}

/* ────────────────────────────────────────────────────────────────────────
   NAV
   ──────────────────────────────────────────────────────────────────────── */
.site-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px var(--gutter);
  background: var(--bg-overlay);
  backdrop-filter: blur(6px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease);
}
.site-nav.is-scrolled { border-bottom-color: var(--hairline); }

.site-nav .logo {
  font-family: var(--font-mono);
  font-size: 14px;
  letter-spacing: 0.12em;
  color: var(--paper);
  text-decoration: none;
}

.nav-right {
  display: flex;
  align-items: center;
  gap: 28px;
}

.site-nav ul {
  list-style: none;
  display: flex;
  gap: 32px;
  margin: 0;
  padding: 0;
}
.site-nav a.nav-link {
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--paper-dim);
  position: relative;
  padding-bottom: 4px;
}
.site-nav a.nav-link:hover { color: var(--paper); }
.site-nav a.nav-link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 0; height: 1px;
  background: var(--accent);
  transition: width 0.25s var(--ease);
}
.site-nav a.nav-link:hover::after { width: 100%; }

.nav-controls {
  display: flex;
  align-items: center;
  gap: 10px;
}

.theme-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--paper);
  height: 38px;
  padding: 0 12px;
  border-radius: 2px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.theme-toggle:hover { border-color: var(--accent); color: var(--accent); }

/* Standalone booking button in the nav bar. Hidden on desktop (the nav
   list already has an accent Contact link there); on mobile it takes over,
   because the nav list collapses into an overflow:hidden dropdown that a
   child can't visually escape. */
.nav-book { display: none; }

@media (max-width: 720px) {
  /* At rest the bar is present (logo + controls). As soon as the page
     scrolls, the bar and logo fade away, leaving just the Contact and
     theme buttons floating.
     No menu button or dropdown here: a hidden toggle would still occupy
     layout space and push the two controls sideways as the bar faded. */
  .site-nav {
    justify-content: space-between;
    padding: 14px var(--gutter);
    transition: background 0.3s var(--ease), backdrop-filter 0.3s var(--ease),
                border-color 0.3s var(--ease);
  }
  .site-nav.is-scrolled {
    background: none;
    backdrop-filter: none;
    border-bottom-color: transparent;
    /* The now-invisible strip must not swallow taps meant for the photos
       underneath; .nav-right re-enables them for the buttons themselves. */
    pointer-events: none;
  }
  .site-nav .logo {
    transition: opacity 0.3s var(--ease), visibility 0.3s var(--ease);
  }
  .site-nav.is-scrolled .logo {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
  }

  .site-nav ul { display: none; }

  .nav-right { gap: 8px; pointer-events: auto; }
  .theme-toggle span { display: none; }
  .theme-toggle { width: 38px; padding: 0; justify-content: center; }

  .nav-book {
    display: inline-block;
    background: var(--accent);
    color: var(--bg);
    border: none;
    border-radius: 2px;
    font-family: var(--font-mono);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    padding: 0 14px;
    height: 38px;
    cursor: pointer;
    transition: background 0.2s var(--ease), box-shadow 0.3s var(--ease);
  }
  .nav-book:hover { background: var(--paper); }

  /* Once the bar behind them is gone, the buttons sit directly on top of
     photos — a shadow keeps them readable over light and dark images. */
  .site-nav.is-scrolled .nav-book,
  .site-nav.is-scrolled .theme-toggle {
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.22);
  }
  .site-nav.is-scrolled .theme-toggle { background: var(--bg-elevated); }
}

/* ────────────────────────────────────────────────────────────────────────
   SECTION SCAFFOLDING
   ──────────────────────────────────────────────────────────────────────── */
/* ────────────────────────────────────────────────────────────────────────
   WAVE BACKDROP
   A seamless wavy line pattern behind the whole page, so large empty
   stretches (section gutters, the space around the about column) read as
   textured rather than blank. Fixed, so it stays put while the page
   scrolls, and non-interactive.

   The tile is a set of quadratic waves using T-reflection: each segment
   mirrors the previous control point, so the tile ends mid-cycle exactly
   where the next copy starts and there's no kink at the seam.
   ──────────────────────────────────────────────────────────────────────── */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22240%22%20height%3D%22120%22%20viewBox%3D%220%200%20240%20120%22%3E%3Cg%20fill%3D%22none%22%20stroke%3D%22%23ffffff%22%20stroke-width%3D%221.1%22%3E%3Cpath%20d%3D%22M0%2030%20q%2030%20-14%2060%200%20t%2060%200%20t%2060%200%20t%2060%200%22%2F%3E%3Cpath%20d%3D%22M0%2070%20q%2030%2014%2060%200%20t%2060%200%20t%2060%200%20t%2060%200%22%2F%3E%3Cpath%20d%3D%22M0%20110%20q%2030%20-14%2060%200%20t%2060%200%20t%2060%200%20t%2060%200%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
  background-size: 240px 120px;
  background-repeat: repeat;
  opacity: 0.055;
  transition: opacity 0.35s var(--ease);
}
:root[data-theme="light"] body::before {
  background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22240%22%20height%3D%22120%22%20viewBox%3D%220%200%20240%20120%22%3E%3Cg%20fill%3D%22none%22%20stroke%3D%22%23101010%22%20stroke-width%3D%221.1%22%3E%3Cpath%20d%3D%22M0%2030%20q%2030%20-14%2060%200%20t%2060%200%20t%2060%200%20t%2060%200%22%2F%3E%3Cpath%20d%3D%22M0%2070%20q%2030%2014%2060%200%20t%2060%200%20t%2060%200%20t%2060%200%22%2F%3E%3Cpath%20d%3D%22M0%20110%20q%2030%20-14%2060%200%20t%2060%200%20t%2060%200%20t%2060%200%22%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
  opacity: 0.075;
}
section { padding: 96px 0; }
/* The gallery and about sections sit back to back, so their padding
   stacked into an oversized gap. About is also the last section before
   the footer, which brings its own top padding. */
#work { padding-bottom: 44px; }
#about { padding-top: 44px; padding-bottom: 40px; }
@media (max-width: 720px) {
  section { padding: 64px 0; }
  /* The fixed bar is ~66px tall at rest, so the first section needs extra
     top clearance to avoid starting underneath it. */
  #work { padding-top: 90px; padding-bottom: 32px; }
  #about { padding-top: 32px; padding-bottom: 28px; }
}
.section-head {
  margin-bottom: 20px;
  max-width: 60ch;
}
.section-head h2 {
  font-family: var(--font-display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(1.8rem, 4vw, 2.8rem);
  line-height: 1.05;
  margin: 10px 0 0;
  color: var(--paper);
}

/* ────────────────────────────────────────────────────────────────────────
   ABOUT
   ──────────────────────────────────────────────────────────────────────── */
.about-grid {
  display: grid;
  grid-template-columns: 320px 1fr;
  gap: 64px;
  align-items: start;
}
@media (max-width: 820px) {
  .about-grid { grid-template-columns: 1fr; gap: 36px; }
}

.about-photo {
  position: relative;
  border: 1px solid var(--hairline);
  padding: 10px;
  background: var(--bg-elevated);
}
.about-photo img { width: 100%; aspect-ratio: 4/5; object-fit: cover; }
.about-photo .frame-label {
  display: flex;
  justify-content: space-between;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
  padding: 8px 2px 0;
}

.about-body p {
  color: var(--paper-dim);
  font-size: 1.05rem;
  max-width: 62ch;
}

.about-stats {
  display: flex;
  gap: 40px;
  margin: 36px 0 0;
  padding: 24px 0;
  border-top: 1px solid var(--hairline);
  border-bottom: 1px solid var(--hairline);
  flex-wrap: wrap;
}
.about-stats .stat .value {
  font-family: var(--font-display);
  font-size: 2.2rem;
  color: var(--accent);
  line-height: 1;
}
.about-stats .stat .label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-top: 6px;
}

/* Left column: profile photo with the social links stacked beneath it. */
.about-photo-col {
  display: flex;
  flex-direction: column;
  gap: 20px;
}
.about-social {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 10px 20px;
  list-style: none;
  padding: 0;
  margin: 0;
}
.about-social a {
  display: inline-block;
  align-self: flex-start;
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.06em;
  color: var(--paper);
  border-bottom: 1px solid var(--accent);
  padding-bottom: 2px;
}
.about-social a:hover { color: var(--accent); }

/* ────────────────────────────────────────────────────────────────────────
   GALLERY / CONTACT SHEET
   ──────────────────────────────────────────────────────────────────────── */
.gallery-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 40px;
}
.gallery-filters button {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--paper-dim);
  padding: 9px 16px;
  cursor: pointer;
  transition: all 0.2s var(--ease);
}
.gallery-filters button:hover { border-color: var(--accent); color: var(--paper); }
.gallery-filters button.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
}

/* Rows, filled left to right. This used to be CSS columns, which fill
   top to bottom and "balance" column heights — with every tile the same
   height, that left a column empty whenever a filter showed 5, 6 or 9
   photos (6 photos became 2+2+2+0). A grid always fills every column, and
   reads in the same order as the list in config.js. */
.contact-sheet {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  /* Transparent so the wave backdrop shows through the gaps between
     photos — that's the largest open area on the page. */
  background: transparent;
}
@media (max-width: 1100px) {
  .contact-sheet { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 700px) {
  .contact-sheet { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 420px) {
  .contact-sheet { grid-template-columns: 1fr; }
}

/* Every tile is portrait-shaped (gallery.portraitRatio in config.js).
   Each photo is shown whole: portraits of that shape fill the tile
   exactly, and landscapes run full width with black bars above and
   below. Nothing is cropped. */
.frame {
  position: relative;
  aspect-ratio: var(--portrait-ratio, 2 / 3);
  background: #000;
  overflow: hidden;
  cursor: pointer;
  border: none;
  padding: 0;
  display: block;
  width: 100%;
  transition: opacity 0.3s var(--ease), transform 0.3s var(--ease);
}
.frame.is-hidden { display: none; }

/* Category switch — the grid dips out, then the matching photos fade
   back in one after another. The stagger is set per-tile from JS so the
   delay follows position in the filtered set, not the full gallery. */
.contact-sheet.is-switching {
  opacity: 0;
  transform: translateY(8px);
}
.contact-sheet {
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease);
}
@keyframes frameIn {
  from { opacity: 0; transform: translateY(14px) scale(0.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.frame.is-entering {
  animation: frameIn 0.42s var(--ease) both;
}
@media (prefers-reduced-motion: reduce) {
  .contact-sheet, .contact-sheet.is-switching { transition: none; opacity: 1; transform: none; }
  .frame.is-entering { animation: none; }
}

.frame img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  transition: transform 0.5s var(--ease), filter 0.5s var(--ease);
  filter: saturate(0.9);
}
.frame:hover img { transform: scale(1.045); filter: saturate(1.05); }

/* ────────────────────────────────────────────────────────────────────────
   LIGHTBOX
   ──────────────────────────────────────────────────────────────────────── */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--lightbox-bg);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s var(--ease), background 0.35s var(--ease);
  padding: var(--gutter);
}
.lightbox.is-open { opacity: 1; pointer-events: auto; }

.lightbox-inner {
  position: relative;
  width: min(95vw, 1680px);
  height: min(92vh, 920px);
  display: flex;
  flex-direction: column;
  border: 1px solid var(--hairline);
  background: var(--bg-elevated);
  transform: scale(0.94);
  transition: transform 0.3s var(--ease);
}
.lightbox.is-open .lightbox-inner { transform: scale(1); }

.lightbox-main {
  display: flex;
  min-height: 0;
  flex: 1;
}

.lightbox-frame {
  position: relative;
  flex: 1 1 64%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  padding: 18px;
  min-height: 320px;
  overflow: hidden;
}
.lightbox-frame img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  margin: 0 auto;
  cursor: zoom-in;
  transform-origin: center center;
  transition: transform 0.25s var(--ease);
  touch-action: none;
  -webkit-user-drag: none;
  user-select: none;
}
.lightbox-frame img.is-zoomed { cursor: grab; }
.lightbox-frame img.is-dragging { cursor: grabbing; transition: none; }

.zoom-hint {
  position: absolute;
  right: 14px;
  bottom: 12px;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--overlay-ink);
  background: var(--overlay-scrim-soft);
  padding: 4px 9px;
  opacity: 0;
  transition: opacity 0.25s var(--ease);
  pointer-events: none;
  z-index: 2;
}
.lightbox-frame:hover .zoom-hint { opacity: 0.85; }
.lightbox-frame img.is-zoomed ~ .zoom-hint { opacity: 0 !important; }
@media (hover: none) {
  .zoom-hint { opacity: 0.65; }
  .lightbox-frame img.is-zoomed ~ .zoom-hint { opacity: 0 !important; }
}

.lightbox-bio {
  flex: 0 0 300px;
  padding: 32px 28px;
  border-left: 1px solid var(--hairline);
  display: flex;
  flex-direction: column;
  justify-content: center;
  overflow-y: auto;
}
.lightbox-bio .title {
  font-family: var(--font-body);
  font-size: 1.4rem;
  color: var(--paper);
  margin: 0 0 6px;
  line-height: 1.2;
}
.lightbox-bio .category {
  display: inline-block;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 18px;
}
.lightbox-bio .count {
  margin-top: 24px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ink-muted);
}

.lightbox-close,
.lightbox-nav {
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--paper);
  cursor: pointer;
  font-family: var(--font-mono);
}
.lightbox-close {
  position: absolute;
  top: -18px; right: -18px;
  width: 36px; height: 36px;
  background: var(--bg-elevated);
  z-index: 5;
}
.lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 44px; height: 44px;
  background: var(--bg-overlay);
  font-size: 18px;
  z-index: 3;
}
.lightbox-nav.prev { left: 12px; }
.lightbox-nav.next { right: 12px; }

/* Title line for the opened photo on phones, where the side panel is
   hidden to give the image the full screen. Desktop shows the title in
   that panel instead. */
.lightbox-caption { display: none; }
.lightbox-nav:hover, .lightbox-close:hover { border-color: var(--accent); color: var(--accent); }

.lightbox-filmstrip-frame {
  flex: 0 0 auto;
  /* Matches .lightbox-frame's rendered width — same card, minus the
     fixed-width bio panel (300px) and its 1px border. If .lightbox-bio's
     flex-basis ever changes, update this to match. */
  width: calc(100% - 301px);
  overflow: hidden;
  border-top: 1px solid var(--hairline);
  background: var(--bg-elevated);
}
.lightbox-filmstrip {
  display: flex;
  gap: 8px;
  padding: 14px calc(50% - 29px);
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -ms-overflow-style: none;
  scroll-behavior: auto;
  cursor: grab;
  -webkit-user-select: none;
  user-select: none;
  scroll-snap-type: x proximity;
  mask-image: linear-gradient(to right, transparent 0, black 56px, black calc(100% - 56px), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 56px, black calc(100% - 56px), transparent 100%);
}
.lightbox-filmstrip::-webkit-scrollbar { display: none; }
.lightbox-filmstrip.is-dragging {
  cursor: grabbing;
  scroll-snap-type: none;
}
.lb-thumb {
  flex: 0 0 auto;
  width: 58px;
  height: 58px;
  padding: 0;
  border: 2px solid transparent;
  background: none;
  cursor: pointer;
  opacity: 0.5;
  overflow: hidden;
  scroll-snap-align: center;
  transform-origin: center center;
  transition: opacity 0.2s var(--ease), border-color 0.2s var(--ease);
}
.lb-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lb-thumb:hover { opacity: 0.85; }
.lb-thumb.is-active { opacity: 1; border-color: var(--accent); }

@media (max-width: 820px) {
  /* On a phone the bio panel stole most of the height, so tapping a photo
     made it *smaller* than it was in the grid. Drop the panel and let the
     image and filmstrip use the whole screen. */
  .lightbox { padding: 0; }
  .lightbox-inner {
    width: 100vw;
    height: 100dvh;
    max-height: none;
    border: none;
    background: var(--bg);
  }
  .lightbox-main { flex-direction: column; min-height: 0; }
  .lightbox-bio { display: none; }
  .lightbox-frame {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
    padding: 8px;
  }
  .lightbox-close {
    top: 10px;
    right: 10px;
    background: var(--bg-overlay);
  }
  .lightbox-filmstrip-frame { width: 100%; }
  .lightbox-filmstrip { padding: 10px calc(50% - 29px); }
  .lightbox-caption {
    display: block;
    flex: 0 0 auto;
    margin: 0;
    padding: 10px 16px 2px;
    text-align: center;
    font-family: var(--font-body);
    font-size: 0.95rem;
    line-height: 1.35;
    color: var(--paper);
    /* One line; very long titles get an ellipsis rather than pushing the
       filmstrip down. */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
}

/* ────────────────────────────────────────────────────────────────────────
   CONTACT
   ──────────────────────────────────────────────────────────────────────── */
/* Booking teaser — now sits at the end of the about column rather than
   in its own full-width section, so it's left-aligned and set off by a
   rule instead of centered. */
/* Sits directly under the stats block, which already supplies the
   dividing rule with its bottom border — a second border-top here would
   read as a doubled line. */
.contact-teaser {
  padding-top: 28px;
}
.contact-teaser h3 {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-weight: 700;
  font-size: clamp(1.25rem, 2.4vw, 1.6rem);
  line-height: 1.15;
  margin: 0 0 12px;
  color: var(--paper);
}
.contact-teaser p { color: var(--paper-dim); max-width: 84ch; margin: 0 0 22px; }
.contact-teaser .btn-submit { display: inline-block; align-self: flex-start; }

.contact-body p { color: var(--paper-dim); max-width: 48ch; }
.contact-email {
  display: inline-block;
  margin-top: 8px;
  font-family: var(--font-mono);
  font-size: 1.1rem;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid var(--accent-dim);
}
.contact-email:hover { color: var(--paper); border-color: var(--paper); }

.contact-form {
  display: flex;
  flex-direction: column;
  gap: 18px;
}
.field { display: flex; flex-direction: column; gap: 8px; }
.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}
@media (max-width: 480px) {
  .field-row { grid-template-columns: 1fr; }
}
.field label {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.field label .optional {
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink-muted);
  opacity: 0.7;
}
.field input, .field textarea {
  background: var(--bg-elevated);
  border: 1px solid var(--hairline);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: 0.95rem;
  padding: 12px 14px;
  resize: vertical;
}
.field textarea { min-height: 120px; }
.field input:focus, .field textarea:focus { border-color: var(--accent); }

.form-status {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  margin: 0;
  display: none;
}
.form-status.is-visible { display: block; }
.form-status.is-success { color: var(--accent); }
.form-status.is-error { color: #c0392b; }

.btn-submit {
  align-self: flex-start;
  background: var(--accent);
  color: var(--bg);
  border: none;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 13px 28px;
  cursor: pointer;
  transition: background 0.2s var(--ease);
}
.btn-submit:hover { background: var(--paper); }
.btn-submit:disabled { opacity: 0.6; cursor: default; }

/* ────────────────────────────────────────────────────────────────────────
   BOOKING MODAL
   ──────────────────────────────────────────────────────────────────────── */
.booking-modal {
  position: fixed;
  inset: 0;
  z-index: 250;
  background: var(--modal-scrim);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s var(--ease), background 0.35s var(--ease);
  padding: var(--gutter);
}
.booking-modal.is-open { opacity: 1; pointer-events: auto; }

.booking-inner {
  position: relative;
  width: min(94vw, 1040px);
  /* Fixed height rather than max-height: the calendar's contents change
     as dates and times are picked, and pinning the shell here means those
     changes never resize the modal — so nothing inside needs to reserve
     empty space to keep it stable. */
  height: min(88vh, 820px);
  background: var(--bg-elevated);
  border: 1px solid var(--hairline);
  transform: scale(0.96);
  transition: transform 0.3s var(--ease);
  overflow: hidden;
}
.booking-modal.is-open .booking-inner { transform: scale(1); }

.booking-scroll {
  height: 100%;
  overflow-y: auto;
  padding: 32px clamp(20px, 4vw, 56px) 36px;
}

.booking-close {
  position: absolute;
  top: 14px; right: 14px;
  z-index: 5;
  width: 34px; height: 34px;
  background: var(--bg-elevated);
  border: 1px solid var(--hairline);
  color: var(--paper);
  cursor: pointer;
  font-family: var(--font-mono);
}
.booking-close:hover { border-color: var(--accent); color: var(--accent); }

.booking-intro {
  text-align: center;
  max-width: 100%;
  margin: 0 auto 18px;
}
.booking-heading {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-weight: 700;
  font-size: clamp(1.15rem, 2.2vw, 1.5rem);
  line-height: 1.15;
  margin: 0 0 10px;
  color: var(--paper);
}
/* Nav "Contact" — an accent pill so the booking entry point reads as a
   call to action rather than another plain nav link. --bg is the page
   background in both themes, so the label stays legible either way. */
.site-nav a.nav-link.open-booking {
  background: var(--accent);
  color: var(--bg);
  padding: 7px 15px;
  border-radius: 2px;
  transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.site-nav a.nav-link.open-booking::after { display: none; }
.site-nav a.nav-link.open-booking:hover {
  background: var(--paper);
  color: var(--bg);
}
@media (max-width: 720px) {
  /* In the mobile dropdown, nav links are full-width rows — keep the
     accent highlight but restore the row's own padding. */
  .site-nav a.nav-link.open-booking {
    padding: 16px var(--gutter);
    border-radius: 0;
  }
}

/* ── Booking steps ───────────────────────────────────────────────────
   The modal moves through calendar -> details -> confirmation. Only one
   step is in the DOM flow at a time; the others carry [hidden]. */
.bk-step[hidden] { display: none; }
/* The steps sit inside .booking-scroll, which already supplies the modal's
   inner padding — any here just pushes things further in. */
#stepCalendar, #stepForm { padding: 0; }

/* Two panels: month grid on the left, the chosen day's times on the
   right, split by a rule — the arrangement from the reference design. */
.bk-panels {
  display: grid;
  grid-template-columns: 1fr 280px;
  border: 1px solid var(--hairline);
}
.bk-cal { padding: 20px 22px 18px; }
.bk-slots {
  border-left: 1px solid var(--hairline);
  display: flex;
  flex-direction: column;
  min-width: 0;
}
@media (max-width: 780px) {
  .bk-panels { grid-template-columns: 1fr; }
  .bk-slots { border-left: none; border-top: 1px solid var(--hairline); }
}

/* Timezone + format controls */
.bk-slots-head { padding: 16px 18px 12px; border-bottom: 1px solid var(--hairline); }
.bk-tz { display: flex; flex-direction: column; gap: 5px; margin-bottom: 14px; }
.bk-tz label {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.bk-tz select {
  background: var(--bg);
  border: 1px solid var(--hairline);
  color: var(--paper);
  font-family: var(--font-mono);
  font-size: 11px;
  padding: 7px 8px;
  width: 100%;
  cursor: pointer;
}
.bk-tz select:focus { outline: none; border-color: var(--accent); }

.bk-slots-title { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.bk-slots-title h3 {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--paper);
}
.bk-format { display: flex; border: 1px solid var(--hairline); flex: 0 0 auto; }
.bk-format button {
  background: transparent;
  border: none;
  color: var(--ink-muted);
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 4px 8px;
  cursor: pointer;
  transition: all 0.2s var(--ease);
}
.bk-format button.is-active { background: var(--accent); color: var(--bg); }

/* Slot list — scrolls independently so a long day doesn't stretch the
   modal, matching the reference's fixed-height slot column. */
.bk-slots-list {
  padding: 14px 18px 18px;
  overflow-y: auto;
  flex: 1 1 auto;
  min-height: 180px;
  max-height: 260px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  scrollbar-width: thin;
}
.bk-slot {
  display: block;
  width: 100%;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.04em;
  padding: 9px 10px;
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--paper);
  cursor: pointer;
  transition: all 0.18s var(--ease);
}
.bk-slot:hover { border-color: var(--accent); color: var(--accent); }
.bk-slot.is-active { background: var(--accent); border-color: var(--accent); color: var(--bg); }
.bk-slots-empty {
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--ink-muted);
  margin: 0;
}

/* Shown only if live availability is still arriving when the calendar
   opens — normally it's fetched at page load and this never appears. */
.bk-panels.is-loading .cal-days { display: block; }
.cal-loading {
  margin: 40px 0;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  animation: calPulse 1.2s ease-in-out infinite;
}
@keyframes calPulse { 50% { opacity: 0.4; } }
@media (prefers-reduced-motion: reduce) { .cal-loading { animation: none; } }

.cal-legend {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: 14px 0 0;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-muted);
}
.cal-legend-dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--accent);
  display: inline-block;
}

/* Step 2 / 3 shared bits */
/* Sized to sit alongside the form controls rather than read as fine
   print — it's the only way back to the calendar. */
.bk-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: none;
  border: 1px solid var(--hairline);
  color: var(--paper-dim);
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
  padding: 10px 16px;
  margin-bottom: 22px;
  transition: all 0.2s var(--ease);
}
.bk-back:hover { color: var(--accent); border-color: var(--accent); }
.bk-recap {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--accent);
  border-left: 2px solid var(--accent);
  padding-left: 12px;
  margin: 0 0 22px;
}

.bk-success { text-align: center; }
.bk-success-mark {
  width: 62px; height: 62px;
  margin: 4px auto 18px;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-tint);
  color: var(--accent);
}
.bk-success h3 {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: 1.4rem;
  margin: 0 0 8px;
  color: var(--paper);
}
.bk-success > p { color: var(--paper-dim); margin: 0 auto 24px; max-width: 46ch; font-size: 0.92rem; }
.bk-summary {
  border: 1px solid var(--hairline);
  padding: 18px 20px;
  text-align: left;
  max-width: 420px;
  margin: 0 auto 24px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.9;
  color: var(--paper-dim);
}
.bk-summary strong { color: var(--paper); font-weight: 500; }
.bk-addcal h4 {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 10px;
}
.bk-addcal-links { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; }
.bk-addcal-links a {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid var(--hairline);
  color: var(--paper);
  padding: 8px 14px;
  text-decoration: none;
  transition: all 0.2s var(--ease);
}
.bk-addcal-links a:hover { border-color: var(--accent); color: var(--accent); }
.bk-addcal-note {
  font-family: var(--font-mono);
  font-size: 10px;
  line-height: 1.7;
  color: var(--ink-muted);
  max-width: 44ch;
  margin: 14px auto 22px;
}

/* Calendar */
.cal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 16px;
}
.cal-month {
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--paper);
}
.cal-nav {
  width: 32px; height: 32px;
  background: transparent;
  border: 1px solid var(--hairline);
  color: var(--paper);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 16px;
}
.cal-nav:hover { border-color: var(--accent); color: var(--accent); }
.cal-nav:disabled {
  opacity: 0.25;
  cursor: default;
  border-color: var(--hairline);
  color: var(--paper);
}

.cal-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  text-align: center;
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  margin-bottom: 8px;
}

.cal-days {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 4px;
}
.cal-day {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid transparent;
  color: var(--ink-muted);
  font-family: var(--font-mono);
  font-size: 13px;
  padding: 0;
}
.cal-day.is-empty { visibility: hidden; }
.cal-day.is-disabled { opacity: 0.35; cursor: default; }
.cal-day.is-available {
  color: var(--paper);
  border-color: var(--hairline);
  cursor: pointer;
  position: relative;
}
.cal-day.is-available::after {
  content: "";
  position: absolute;
  bottom: 5px;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--accent);
}
.cal-day.is-available:hover { border-color: var(--accent); color: var(--accent); }
.cal-day.is-selected {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
}
.cal-day.is-selected::after { background: var(--bg); }
/* Today gets a ring so the month has an anchor point, as in the
   reference design. Selection still wins visually. */
.cal-day.is-today:not(.is-selected) {
  border-color: var(--ink-muted);
  color: var(--paper);
}

.cal-hint {
  margin: 14px 0 0;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--ink-muted);
}

/* Selection footer, pinned under the slot list inside the times panel. */
.bk-slots-foot {
  border-top: 1px solid var(--hairline);
  padding: 14px 18px 16px;
  flex: 0 0 auto;
}
.bk-chosen {
  margin: 0 0 12px;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.6;
  color: var(--ink-muted);
  min-height: 35px;   /* two lines, so the panel doesn't jump */
}
.bk-chosen strong { color: var(--accent); font-weight: 500; }
.bk-slots-actions { display: flex; align-items: center; gap: 8px; }
.bk-slots-actions .btn-submit {
  flex: 1;
  padding: 10px 16px;
  text-align: center;
}
.bk-slots-actions .btn-submit:hover:not(:disabled) { background: var(--paper); }
.bk-slots-actions .btn-submit:disabled { opacity: 0.4; cursor: default; }
.bk-slots-actions #calClearSelection {
  background: none;
  border: 1px solid var(--hairline);
  color: var(--ink-muted);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 10px 12px;
  transition: all 0.2s var(--ease);
}
.bk-slots-actions #calClearSelection:hover { border-color: var(--accent); color: var(--accent); }

@media (max-width: 780px) {
  /* The intro used to be a long paragraph that pushed the calendar off
     the first screen, so it was reordered below the booking UI. It's just
     a heading now, so it sits at the top in normal document order. */
  .booking-heading {
    font-size: clamp(1.05rem, 4.6vw, 1.3rem);
    margin-bottom: 10px;
  }
}

@media (max-width: 480px) {
  .booking-scroll { padding: 40px 18px 32px; }
}

/* ────────────────────────────────────────────────────────────────────────
   FOOTER
   ──────────────────────────────────────────────────────────────────────── */
.site-footer {
  padding: 32px var(--gutter) 48px;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ink-muted);
}
.site-footer a { color: var(--paper-dim); text-decoration: none; }
.site-footer a:hover { color: var(--accent); }

/* Reveal-on-scroll utility, applied via JS */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
}
.reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ────────────────────────────────────────────────────────────────────────
   BACK TO TOP — floating button, tracks scroll position
   ──────────────────────────────────────────────────────────────────────── */
.back-to-top {
  position: fixed;
  right: 22px;
  bottom: 26px;
  z-index: 150;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: var(--accent);
  color: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.28);
  opacity: 0;
  transform: translateY(14px);
  pointer-events: none;
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease), background 0.35s var(--ease);
}
.back-to-top.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.back-to-top:hover { background: var(--paper); }

/* ────────────────────────────────────────────────────────────────────────
   IMAGE PROTECTION — every photo on the site (grid, about, lightbox,
   filmstrip). Blocks the native drag-to-desktop save and iOS's long-press
   "Save to Photos" menu. Right-click and dragstart are also blocked in
   JS (see wireImageProtection in app.js) since CSS alone can't stop those.
   ──────────────────────────────────────────────────────────────────────── */
img {
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  user-select: none;
}
