/* ============================================================
   BRYAN A. MACKENZIE
   One stylesheet for the whole film site.
   Headshots lives in /headshots/ with its own CSS — never
   include this file from there, or the lift gets messy later.
   ============================================================ */

:root{
  --ground:      #0B0B0C;
  --ground-soft: #121214;
  --ink:         #F2F0EC;
  --ink-dim:     rgba(242,240,236,0.62);
  --ink-faint:   rgba(242,240,236,0.38);
  --rule:        rgba(242,240,236,0.14);
  --accent:      #D4A24C;

  --display: 'Bodoni Moda', Georgia, serif;
  --ui:      'Archivo', system-ui, sans-serif;

  --pad: 40px;
  --nav-h: 74px;
  --index-w: 38vw;      /* how much of the frame the floating index occupies */
  --index-max: 520px;
}

*{ box-sizing: border-box; }

html, body{
  margin: 0;
  padding: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--ui);
  font-weight: 300;
  -webkit-font-smoothing: antialiased;
}

body{ overflow-x: hidden; }

a{ color: inherit; text-decoration: none; }

:focus-visible{
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Keyboard users land here first and can jump straight past the nav. */
.skip-link{
  position: absolute;
  top: -60px;
  left: var(--pad);
  z-index: 200;
  background: var(--ink);
  color: var(--ground);
  padding: 11px 18px;
  font-size: 12px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: top .14s ease;
}
.skip-link:focus{ top: 12px; }

/* Off-screen but readable by screen readers and crawlers. */
.visually-hidden{
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Shared small-caps label treatment */
.label{
  font-family: var(--ui);
  font-size: 10.5px;
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

/* ── NAV ─────────────────────────────────────────────────── */

.nav{
  position: relative;
  z-index: 30;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--pad);
}

.nav-brand{
  display: flex;
  align-items: baseline;
  gap: 9px;
  white-space: nowrap;
}
.nav-brand strong{
  font-family: var(--ui);
  font-weight: 500;
  font-size: 13px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.nav-brand span{
  font-size: 11.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.nav-links{
  display: flex;
  gap: 30px;
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-links a{
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-dim);
  padding-bottom: 3px;
  border-bottom: 1px solid transparent;
  transition: color .18s ease, border-color .18s ease;
}
.nav-links a:hover,
.nav-links a[aria-current="page"]{
  color: var(--ink);
  border-color: var(--accent);
}

/* The headshots door. Marked so it reads as a second discipline,
   not another film page. */
.nav-links a.alt{ color: var(--accent); }
.nav-links a.alt:hover{ color: var(--accent); border-color: var(--accent); }

/* Hamburger — hidden on desktop, shown under 900px. */
.nav-toggle{
  display: none;
  position: relative;
  z-index: 80;
  margin-left: auto;   /* belt and braces: always pinned right */
  width: 44px;
  height: 44px;
  margin-right: -10px;
  background: none;
  border: 0;
  cursor: pointer;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
  gap: 7px;
  padding: 0;
}
.nav-toggle span{
  display: block;
  width: 24px;
  height: 1px;
  background: var(--ink);
  transition: transform .22s ease, opacity .18s linear, width .22s ease;
}
.nav-toggle[aria-expanded="true"] span:nth-child(1){ transform: translateY(4px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2){ transform: translateY(-4px) rotate(-45deg); }

/* ── HOME: split stage ───────────────────────────────────── */

/* Homepage stage runs to the very top — the nav floats over it,
   same as the project hero, so the still starts at the window edge. */
.home .nav{
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
}

.stage{
  position: relative;
  height: 100vh;
  height: 100dvh;
  min-height: 560px;
}

/* Push the index heading clear of the floating nav. */
.home .index-head{
  padding-top: calc(var(--nav-h) + 10px);
}

/* The preview is the whole stage now — the index floats over it. */

.preview{
  position: absolute;
  inset: 0;
  overflow: hidden;
}

.preview-layer{
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center;
  opacity: 0;
  transition: opacity .16s linear;
  will-change: opacity;
}
.preview-layer.is-on{ opacity: 1; }

/* Shown when a project has no hero image yet. */
.preview-empty{
  position: absolute;
  inset: 0;
  background:
    repeating-linear-gradient(
      38deg,
      #101012 0 2px,
      #0D0D0F 2px 54px
    );
}

.preview-scrim{
  position: absolute;
  inset: 0;
  z-index: 2;   /* above the background video, below the title */
  pointer-events: none;   /* must not swallow taps meant for the arrows */
  background: linear-gradient(
    to top,
    rgba(8,8,9,0.92) 0%,
    rgba(8,8,9,0.55) 32%,
    rgba(8,8,9,0.10) 68%,
    rgba(8,8,9,0.30) 100%
  );
}

.preview-grain{
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0.30;
  background-size: 190px;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.08'/%3E%3C/svg%3E");
}

/* Bottom-left caption block */

.caption{
  position: absolute;
  left: var(--pad);
  right: calc(var(--index-w) + var(--pad));
  bottom: 44px;
  z-index: 3;
  text-shadow: 0 1px 24px rgba(0,0,0,0.55);
}

.caption-label{
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 16px;
}
.caption-label .dot{
  width: 6px; height: 6px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
}

/* The "inflating" title. Scale + rise on change, driven by the
   .is-swapping class the JS toggles. */
.caption-title{
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(42px, 5.6vw, 92px);
  line-height: 0.96;
  letter-spacing: -0.015em;
  margin: 0 0 18px;
  transform-origin: left bottom;
  transition: transform .17s cubic-bezier(.2,.9,.3,1), opacity .09s linear;
}
.caption.is-swapping .caption-title{
  transform: scale(0.982) translateY(4px);
  opacity: 0;
}
.caption.is-swapping .caption-credits,
.caption.is-swapping .caption-label{
  opacity: 0;
}

.caption-credits{
  font-size: 11px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 24px;
  transition: opacity .09s linear;
  min-height: 14px;
}
.caption-credits .sep{ color: var(--ink-faint); margin: 0 10px; }
.caption-label{ transition: opacity .09s linear; }

.caption-cta{
  display: inline-flex;
  align-items: center;
  gap: 11px;
  border: 1px solid rgba(242,240,236,0.34);
  padding: 12px 22px;
  font-size: 10.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  transition: background .2s ease, border-color .2s ease, gap .2s ease;
}
.caption-cta:hover{
  background: rgba(242,240,236,0.08);
  border-color: var(--ink);
  gap: 16px;
}
.caption-cta svg{ flex: none; }

/* Right: the index */

/* Floats over the still. No panel — just a soft falloff behind the
   type so it stays legible on a bright frame. Kill the gradient
   below if you want the still completely untouched. */
.index{
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: 10;
  width: var(--index-w);
  max-width: var(--index-max);
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: linear-gradient(
    to right,
    rgba(8,8,9,0) 0%,
    rgba(8,8,9,0.34) 30%,
    rgba(8,8,9,0.62) 100%
  );
  text-shadow: 0 1px 18px rgba(0,0,0,0.6);
}

.index-head{
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 26px var(--pad) 14px;
  flex: none;
}

.index-scroll{
  overflow-y: auto;
  flex: 1 1 auto;
  padding: 0 var(--pad) 40px;
  scrollbar-width: thin;
  scrollbar-color: rgba(242,240,236,0.22) transparent;
}
.index-scroll::-webkit-scrollbar{ width: 3px; }
.index-scroll::-webkit-scrollbar-thumb{
  background: rgba(242,240,236,0.22);
}

/* Rows are buttons: they select a project, they don't navigate. */
.index-row{
  -webkit-appearance: none;
  appearance: none;
  background: none;
  border: 0;
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
  display: grid;
  grid-template-columns: 30px 1fr auto;
  align-items: center;
  gap: 14px;
  padding: 15px 0;
  /* Slightly stronger than --rule: these sit on photography now. */
  border-bottom: 1px solid rgba(242,240,236,0.20);
  color: rgba(242,240,236,0.78);
  transition: color .1s linear, padding-left .12s ease-out;
}
.index-row:hover,
.index-row:focus-visible,
.index-row.is-active{
  color: var(--ink);
  padding-left: 8px;
}

.index-num{
  font-size: 9.5px;
  letter-spacing: 0.12em;
  color: rgba(242,240,236,0.55);
  font-variant-numeric: tabular-nums;
}
.index-row.is-active .index-num{ color: var(--accent); }

/* The pinned row keeps a marker so you can tell what's selected
   from what you're merely hovering past. */
.index-row.is-active{
  box-shadow: inset 2px 0 0 var(--accent);
  padding-left: 10px;
}

.index-title{
  font-size: 16px;
  font-weight: 400;
  letter-spacing: 0.005em;
}

.index-meta{
  font-size: 9.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(242,240,236,0.55);
  white-space: nowrap;
}

/* ── MOBILE / NARROW: carousel ───────────────────────────── */

.carousel-ui{ display: none; }

/* Hidden by default too — without this the two arrow buttons render in
   normal flow on desktop and sit in the tab order for no reason. */
.carousel-arrows{ display: none; }

@media (max-width: 900px){
  :root{ --pad: 22px; --nav-h: 64px; }

  /* ── Mobile nav ── */
  .nav-toggle{ display: flex; }

  /* Drop the "/ Cinematographer" tail — it's what overflows first. */
  .nav-brand span{ display: none; }
  .nav-brand strong{ font-size: 12px; letter-spacing: 0.12em; }

  .nav-links{
    position: fixed;
    inset: 0;
    z-index: 70;
    /* Slightly see-through so the still or video behind stays visible.
       Blur keeps the links legible over a busy frame. */
    background: rgba(11, 11, 12, 0.82);
    backdrop-filter: blur(16px) saturate(120%);
    -webkit-backdrop-filter: blur(16px) saturate(120%);
    flex-direction: column;
    justify-content: center;
    align-items: center;      /* centred, not hugging the left edge */
    gap: 2px;
    padding: 0 var(--pad);
    margin: 0;
    text-align: center;
    transform: translateY(-100%);
    transition: transform .26s ease;
  }
  .nav-links.is-open{ transform: translateY(0); }
  .nav-links li{ width: 100%; }
  .nav-links a{
    display: block;
    font-size: 22px;
    letter-spacing: 0.1em;
    padding: 16px 0;
    border-bottom: 0;
    color: var(--ink);
    text-align: center;
  }
  .nav-links a.alt{ color: var(--accent); }

  /* The index panel is its own full-screen layer; it doesn't need to
     clear the floating nav. */
  .home .index-head{ padding-top: 22px; }

  /* The floating index becomes a full-screen panel behind a button. */
  .index{
    position: fixed;
    inset: 0;
    width: auto;
    max-width: none;
    z-index: 60;
    background: var(--ground);
    text-shadow: none;
    transform: translateY(100%);
    transition: transform .34s ease;
    padding-top: 12px;
  }
  .index.is-open{ transform: translateY(0); }

  .index-head{ padding-top: 20px; }

  .caption{ bottom: 104px; right: var(--pad); }
  .caption-title{ font-size: clamp(34px, 11vw, 60px); }

  .carousel-ui{
    display: block;
    position: absolute;
    left: 0; right: 0; bottom: 0;
    z-index: 30;
    padding: 0 var(--pad) 18px;
    pointer-events: none;
  }
  .carousel-ui > *{ pointer-events: auto; }

  .carousel-bar{
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
  }

  .carousel-count{
    font-size: 10px;
    letter-spacing: 0.16em;
    color: var(--ink-dim);
    font-variant-numeric: tabular-nums;
  }
  .carousel-count b{ color: var(--ink); font-weight: 500; }

  .carousel-dots{
    display: flex;
    gap: 5px;
    flex: 1 1 auto;
    justify-content: center;
  }
  .carousel-dots i{
    display: block;
    width: 5px; height: 5px;
    border-radius: 50%;
    background: rgba(242,240,236,0.26);
    transition: background .2s ease, width .2s ease, border-radius .2s ease;
  }
  .carousel-dots i.is-on{
    background: var(--ink);
    width: 18px;
    border-radius: 3px;
  }

  .btn-ghost{
    background: none;
    border: 1px solid rgba(242,240,236,0.3);
    color: var(--ink);
    font-family: var(--ui);
    font-size: 10px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    padding: 11px 16px;
    min-height: 44px;
    cursor: pointer;
  }

  .carousel-arrows{
    display: flex;
    position: absolute;
    inset: 0;
    z-index: 30;              /* above the scrim, or taps never land */
    display: flex;
    justify-content: space-between;
    align-items: center;
    pointer-events: none;
  }

  /* The content below the video is already visible on a phone, so the
     cue is redundant — scrolling reads as obvious without it. */
  .scroll-cue{ display: none; }
  .hero-tools{ display: none; }
  .carousel-arrows button{
    pointer-events: auto;
    width: 46px;
    height: 76px;
    background: rgba(10,10,11,0.42);
    border: none;
    color: var(--ink);
    font-size: 17px;
    cursor: pointer;
  }
}

@media (min-width: 901px){
  .index-close{ display: none; }
}

/* ── PROJECT PAGE ────────────────────────────────────────── */

/* Project hero fills the ENTIRE page — the nav floats over it. */
.project .nav{
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
}

/* One full screen of video, then the page scrolls past it normally.
   svh is the small viewport height — it does not change as mobile
   browser chrome hides and reappears, so nothing shifts mid-scroll. */
.project-hero{
  position: relative;
  z-index: 1;
  width: 100%;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
}

.hero-fixed{
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}

/* Solid ground so the content covers the fixed video as it rises. */
.project-content{
  position: relative;
  z-index: 2;
  background: var(--ground);
}
.project-hero .preview-layer{ opacity: 1; }

/* Vimeo background video. Sits over the still, under the scrim,
   so the title stays readable. Scaled to cover, never letterboxed. */
.hero-video{
  position: absolute;
  inset: 0;
  overflow: hidden;
  z-index: 1;
}
/* Self-hosted loop: the whole frame, always inside the window. */
.hero-video video{
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
  pointer-events: none;
}
.hero-video.fit-cover video{ object-fit: cover; }

.hero-video iframe{
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border: 0;
  pointer-events: none;     /* clicks fall through; no stray controls */

  /* Cover, stated directly: take the larger of "fill the width" and
     "fill the height", in both axes. On a portrait phone that means
     the video is grown far wider than the screen and cropped at the
     sides, which is what keeps it edge to edge with no bars. */
  /* CONTAIN: the largest 16:9 box that fits inside the window, at any
     window shape. min() on both axes means it can never exceed either
     dimension, so the frame is always whole and never spills past an
     edge — portrait phone, square window, or wide monitor. */
  width: min(100vw, 177.78vh);
  height: min(100vh, 56.25vw);
}
@supports (height: 100svh){
  .hero-video iframe{
    width: min(100vw, 177.78svh);
    height: min(100svh, 56.25vw);
  }
}

/* COVER: opt in with hero_fit => 'cover' in data.php. Fills the window
   edge to edge and crops whatever does not fit. */
.hero-video.fit-cover iframe{
  width: max(100vw, 177.78vh);
  height: max(100vh, 56.25vw);
}
@supports (height: 100svh){
  .hero-video.fit-cover iframe{
    width: max(100vw, 177.78svh);
    height: max(100svh, 56.25vw);
  }
}

/* TALL WINDOWS (anything narrower than ~16:10 — phones, and a narrow
   desktop window). Holding a full screen of height just to centre a
   16:9 video leaves a large dead band above and below it. Instead the
   hero collapses to the video's own height: nav, then video, then
   title directly beneath. */
@media (max-aspect-ratio: 16/10){
  .project .nav{ position: relative; }   /* no longer floats over the video */

  .project-hero{
    height: auto;
    min-height: 0;
  }

  .hero-fixed{
    position: relative;
    inset: auto;
    width: 100%;
    aspect-ratio: 16 / 9;    /* the box IS the video */
  }

  .hero-video,
  .hero-video.fit-cover{
    position: absolute;
    inset: 0;
  }
  .hero-video iframe,
  .hero-video.fit-cover iframe{
    position: absolute;
    top: 0;
    left: 0;
    transform: none;
    width: 100%;
    height: 100%;
    min-width: 0;
    min-height: 0;
  }
  .hero-video video,
  .hero-video.fit-cover video{
    object-fit: cover;       /* the box is already 16:9, so nothing crops */
  }

  /* Title sits under the video rather than over it.
     SCOPED TO .project — the homepage uses .caption too, and there it
     must stay pinned over the still. */
  .project .caption{
    position: static;
    padding: 28px var(--pad) 8px;
    left: auto; right: auto; bottom: auto;
    text-shadow: none;
  }

  /* The scrim exists to keep white text legible over a picture. With
     the title below the video it has nothing to do. */
  .project-hero .preview-scrim{ display: none; }

  /* Pinned bottom-right of a hero that is now only as tall as the
     video — it would land on top of the title. */
  .hero-tools{ display: none; }
}

/* ── MOBILE SPACING ──────────────────────────────────────── */
/* The desktop rhythm is built for a 1400px-wide page. On a phone the
   same values read as large empty gaps, so everything tightens. */
@media (max-width: 900px){
  .project .caption{ padding-top: 20px; padding-bottom: 0; }
  .caption-title{ margin-bottom: 10px; }
  .caption-credits{ margin-bottom: 0; font-size: 10px; }

  .project-body{ padding-top: 20px; padding-bottom: 20px; }
  .project-synopsis{ margin-bottom: 26px; line-height: 1.34; }

  .credit-grid{
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 18px;
    padding-top: 20px;
  }
  .credit-grid dt{ margin-bottom: 5px; }
  .credit-grid dd{ font-size: 13.5px; }

  .stills-section{ padding-top: 34px; }
  .section-title{ margin-bottom: 14px; }
  .stills{ gap: 12px; }

  .project-next{ padding-top: 44px; padding-bottom: 44px; }

  .site-footer{ padding-top: 20px; padding-bottom: 20px; }
}

/* Anyone who asked the OS for less motion gets the still instead. */
@media (prefers-reduced-motion: reduce){
  .hero-video{ display: none; }
}

/* Hero controls, paired bottom-right: back on the left, scroll on the right. */
.hero-tools{
  position: absolute;
  right: var(--pad);
  bottom: 46px;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 30px;
}

/* Quiet cue that there's more under the fold. */
.scroll-cue{
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  color: rgba(242,240,236,0.55);
  animation: cueBob 2.2s ease-in-out infinite;
}
.scroll-cue:hover{ color: var(--ink); }
@keyframes cueBob{
  0%,100%{ transform: translateY(0); }
  50%    { transform: translateY(5px); }
}

/* ONE LEFT RAIL.
   Everything below the hero starts on the same line as the title:
   left edge = var(--pad). Nothing is centred, nothing is indented. */
.rail{
  padding-left: var(--pad);
  padding-right: var(--pad);
  max-width: none;
  margin: 0;
}

.project-body{
  padding-top: 38px;
  padding-bottom: 40px;
}

.project-synopsis{
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(21px, 2.3vw, 29px);
  line-height: 1.42;
  margin: 0 0 56px;
  /* Spans the full rail, matching the stills grid and credits. */
  max-width: none;
}

.credit-grid{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 30px;
  border-top: 1px solid var(--rule);
  padding-top: 30px;
}
.credit-grid dt{
  font-size: 9.5px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.credit-grid dd{
  margin: 0;
  font-size: 14.5px;
  color: var(--ink);
}

/* Section heading, left on the rail with the title above it. */
.section-title{
  font-family: var(--ui);
  font-weight: 400;
  font-size: 12px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 22px;
}

.stills-section{ padding-top: 72px; }

.stills{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
  gap: 22px;
}

/* Each still is a button: click to enlarge. */
.still-btn{
  -webkit-appearance: none;
  appearance: none;
  padding: 0;
  border: 0;
  background: none;
  display: block;
  cursor: zoom-in;
  overflow: hidden;
  line-height: 0;
}
.still-btn img,
.still-btn .placeholder{
  transition: opacity .14s linear, transform .22s ease-out;
}
.still-btn:hover img,
.still-btn:hover .placeholder{
  opacity: 0.86;
  transform: scale(1.012);
}
/* Placeholder inside a button needs to lay itself out. */
.still-btn .placeholder{
  display: flex;
  width: 100%;
}

/* ── LIGHTBOX ────────────────────────────────────────────── */

.lightbox{
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 3vmin;
  background: rgba(6,6,7,0.96);
  cursor: zoom-out;
  opacity: 0;
  transition: opacity .14s linear;
}
.lightbox[hidden]{ display: none; }
.lightbox.is-open{ opacity: 1; }

.lightbox img{
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  display: block;
}
.lightbox img[src=""]{ display: none; }

/* Enlarged view of a placeholder, so the interaction is testable
   before any stills are uploaded. */
.lightbox-placeholder{
  width: min(86vw, 1400px);
  aspect-ratio: 16 / 9;
  display: none;
  align-items: center;
  justify-content: center;
  background: repeating-linear-gradient(38deg,#101012 0 2px,#0D0D0F 2px 54px);
  border: 1px solid var(--rule);
}
.lightbox.is-placeholder .lightbox-placeholder{ display: flex; }

.lightbox-close{
  position: absolute;
  top: 18px;
  right: 22px;
  width: 44px;
  height: 44px;
  background: none;
  border: 0;
  color: var(--ink-dim);
  font-size: 30px;
  line-height: 1;
  cursor: pointer;
}
.lightbox-close:hover{ color: var(--ink); }
.stills img{
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  aspect-ratio: 16 / 9;
}
.stills .placeholder{
  aspect-ratio: 16 / 9;
  background:
    repeating-linear-gradient(38deg, #101012 0 2px, #0D0D0F 2px 54px);
  display: flex;
  align-items: center;
  justify-content: center;
}

.project-next{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
  padding-top: 88px;
  padding-bottom: 88px;
}
.project-next .back-index{
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink-dim);
  padding: 10px 0;
  transition: color .12s linear, gap .16s ease-out;
}
.project-next .back-index:hover{ color: var(--ink); gap: 15px; }
.project-next .back-index svg{ flex: none; }

.project-next .next-link{
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  text-align: right;
}
.project-next .next-title{
  font-family: var(--display);
  font-size: clamp(30px, 4vw, 54px);
  line-height: 1;
  transition: opacity .12s linear;
}
.project-next a:hover .next-title{ opacity: 0.62; }

@media (max-width: 700px){
  .project-next{ flex-direction: column; align-items: flex-start; }
  .project-next .next-link{ align-items: flex-start; text-align: left; }
}

/* ── STANDALONE PAGES (about, contact) ───────────────────── */

.page-main{ padding-top: 40px; }

.page-head{ padding-top: 24px; padding-bottom: 8px; }
.page-title{
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(38px, 6vw, 76px);
  line-height: 1.02;
  letter-spacing: -0.015em;
  margin: 14px 0 0;
}

.page-body{ padding-top: 40px; padding-bottom: 90px; }

.page-cols{
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: 60px;
  align-items: start;
}

.page-copy p{ color: var(--ink-dim); margin: 0 0 18px; max-width: 62ch; }
.page-copy .lead{
  font-family: var(--display);
  font-size: clamp(19px, 2vw, 25px);
  line-height: 1.42;
  color: var(--ink);
  margin-bottom: 26px;
}
.page-copy a{ border-bottom: 1px solid var(--rule); }
.page-copy a:hover{ border-color: var(--accent); }
.page-copy .caption-cta{ border-bottom: 1px solid rgba(242,240,236,0.34); }

.page-figure img{ width: 100%; height: auto; display: block; }
.figure-placeholder{
  aspect-ratio: 4 / 5;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 20px;
  background: repeating-linear-gradient(38deg, #101012 0 2px, #0D0D0F 2px 54px);
  border: 1px solid var(--rule);
}

/* ── FORMS ───────────────────────────────────────────────── */

.enquiry{ margin-top: 26px; }
.field{ margin-bottom: 20px; }
.field-row{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
}
.field label,
.enquiry label{
  display: block;
  font-size: 10px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink-faint);
  margin-bottom: 8px;
}
.enquiry input,
.enquiry select,
.enquiry textarea{
  width: 100%;
  background: rgba(242,240,236,0.04);
  border: 1px solid var(--rule);
  color: var(--ink);
  font-family: var(--ui);
  font-weight: 300;
  font-size: 15px;
  padding: 12px 13px;
  border-radius: 2px;
  min-height: 44px;              /* comfortable tap target */
  -webkit-appearance: none;
  appearance: none;
}
.enquiry textarea{ resize: vertical; min-height: 130px; line-height: 1.6; }
.enquiry select{
  background-image: linear-gradient(45deg, transparent 50%, var(--ink-faint) 50%),
                    linear-gradient(135deg, var(--ink-faint) 50%, transparent 50%);
  background-position: calc(100% - 19px) 50%, calc(100% - 14px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 38px;
}
.enquiry select option{ background: var(--ground-soft); color: var(--ink); }
.enquiry input:focus,
.enquiry select:focus,
.enquiry textarea:focus{
  outline: 2px solid var(--accent);
  outline-offset: 1px;
  border-color: var(--accent);
  background: rgba(242,240,236,0.07);
}
.enquiry input::placeholder,
.enquiry textarea::placeholder{ color: rgba(242,240,236,0.3); }

.hp{ position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-actions{
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 8px;
}
button.caption-cta{
  background: none;
  cursor: pointer;
  font-family: var(--ui);
  color: var(--ink);
}
button.caption-cta:disabled{ opacity: 0.5; cursor: default; }
.form-note{ margin: 0; font-size: 13px; color: var(--ink-faint); }
.form-note a{ border-bottom: 1px solid var(--rule); }

.form-msg{
  margin: 0 0 18px;
  padding: 12px 14px;
  font-size: 14px;
  border: 1px solid var(--rule);
  border-radius: 2px;
}
.form-msg.ok{ color: #A8D5A2; border-color: rgba(168,213,162,0.35); background: rgba(168,213,162,0.07); }
.form-msg.bad{ color: #E8A58C; border-color: rgba(232,165,140,0.35); background: rgba(232,165,140,0.07); }

.form-warn{
  border: 1px dashed rgba(212,162,76,0.5);
  color: var(--accent);
  padding: 12px 14px;
  font-size: 13.5px;
  border-radius: 2px;
}
.form-warn code{ font-family: ui-monospace, Menlo, monospace; font-size: 12.5px; }

@media (max-width: 900px){
  .page-main{ padding-top: 8px; }
  .page-head{ padding-top: 14px; }
  .page-body{ padding-top: 26px; padding-bottom: 54px; }
  .page-cols{ grid-template-columns: 1fr; gap: 34px; }
  .page-copy .lead{ margin-bottom: 20px; }
  .figure-placeholder{ aspect-ratio: 3 / 2; }
}

/* ── FOOTER ──────────────────────────────────────────────── */

.site-footer{
  position: relative;
  z-index: 2;
  background: var(--ground);
  border-top: 1px solid var(--rule);
  padding: 26px var(--pad);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.site-footer a:hover{ color: var(--ink); }

/* The homepage is a fixed stage, so its footer would push the
   viewport. Hidden there, shown everywhere else. */
.home .site-footer{ display: none; }

@media (prefers-reduced-motion: reduce){
  *{ animation: none !important; transition-duration: .01ms !important; }
}
